src/video/directfb/SDL_DirectFB_video.c
author Sam Lantinga
Mon, 10 Jul 2006 21:04:37 +0000
changeset 1895 c121d94672cb
parent 1777 402d5ff1cf88
child 2113 6264c973814a
permissions -rw-r--r--
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
slouken@167
     1
/*
slouken@1312
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@167
     4
slouken@1312
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@1312
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@167
     9
slouken@1312
    10
    This library is distributed in the hope that it will be useful,
slouken@1312
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@1312
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@167
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@167
    18
slouken@1312
    19
    Sam Lantinga
slouken@1312
    20
    slouken@libsdl.org
icculus@728
    21
icculus@728
    22
	MGA CRTC2 support by Thomas Jarosch - tomj@simonv.com
icculus@728
    23
	CRTC2 support is inspired by mplayer's dfbmga driver
icculus@728
    24
	written by Ville Syrj��<syrjala@sci.fi>
slouken@167
    25
*/
slouken@1402
    26
#include "SDL_config.h"
slouken@167
    27
slouken@167
    28
/* DirectFB video driver implementation.
slouken@167
    29
*/
slouken@167
    30
slouken@167
    31
#include <fcntl.h>
slouken@167
    32
#include <unistd.h>
slouken@167
    33
#include <sys/mman.h>
slouken@167
    34
slouken@167
    35
#include <directfb.h>
icculus@1165
    36
#include <directfb_version.h>
slouken@167
    37
slouken@167
    38
#include "SDL_video.h"
slouken@167
    39
#include "SDL_mouse.h"
slouken@1361
    40
#include "../SDL_sysvideo.h"
slouken@1361
    41
#include "../SDL_pixels_c.h"
slouken@1361
    42
#include "../../events/SDL_events_c.h"
slouken@167
    43
#include "SDL_DirectFB_video.h"
slouken@167
    44
#include "SDL_DirectFB_events.h"
slouken@478
    45
#include "SDL_DirectFB_yuv.h"
slouken@167
    46
slouken@767
    47
/* The implementation dependent data for the window manager cursor */
slouken@1895
    48
struct WMcursor
slouken@1895
    49
{
slouken@1895
    50
    int unused;
slouken@767
    51
};
slouken@767
    52
slouken@167
    53
slouken@167
    54
/* Initialization/Query functions */
slouken@1895
    55
static int DirectFB_VideoInit(_THIS, SDL_PixelFormat * vformat);
slouken@1895
    56
static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat * format,
slouken@1895
    57
                                     Uint32 flags);
slouken@1895
    58
static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface * current,
slouken@1895
    59
                                          int width, int height, int bpp,
slouken@1895
    60
                                          Uint32 flags);
slouken@167
    61
static int DirectFB_SetColors(_THIS, int firstcolor, int ncolors,
slouken@1895
    62
                              SDL_Color * colors);
slouken@167
    63
static void DirectFB_VideoQuit(_THIS);
slouken@167
    64
slouken@167
    65
/* Hardware surface functions */
slouken@1895
    66
static int DirectFB_AllocHWSurface(_THIS, SDL_Surface * surface);
slouken@1895
    67
static int DirectFB_FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * dstrect,
slouken@1895
    68
                               Uint32 color);
slouken@1895
    69
static int DirectFB_LockHWSurface(_THIS, SDL_Surface * surface);
slouken@1895
    70
static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface * surface);
slouken@1895
    71
static void DirectFB_FreeHWSurface(_THIS, SDL_Surface * surface);
slouken@1895
    72
static int DirectFB_CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst);
slouken@1895
    73
static int DirectFB_HWAccelBlit(SDL_Surface * src, SDL_Rect * srcrect,
slouken@1895
    74
                                SDL_Surface * dst, SDL_Rect * dstrect);
slouken@1895
    75
static int DirectFB_SetHWColorKey(_THIS, SDL_Surface * surface, Uint32 key);
slouken@1895
    76
static int DirectFB_SetHWAlpha(_THIS, SDL_Surface * surface, Uint8 alpha);
slouken@1895
    77
static int DirectFB_FlipHWSurface(_THIS, SDL_Surface * surface);
slouken@1895
    78
static int DirectFB_ShowWMCursor(_THIS, WMcursor * cursor);
slouken@167
    79
slouken@167
    80
/* Various screen update functions available */
slouken@1895
    81
static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect * rects);
slouken@1895
    82
static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect * rects);
slouken@167
    83
slouken@167
    84
/* This is the rect EnumModes2 uses */
slouken@1895
    85
struct DirectFBEnumRect
slouken@1895
    86
{
slouken@1895
    87
    SDL_Rect r;
slouken@1895
    88
    struct DirectFBEnumRect *next;
slouken@167
    89
};
slouken@167
    90
slouken@464
    91
static struct DirectFBEnumRect *enumlist = NULL;
slouken@167
    92
slouken@167
    93
slouken@167
    94
/* DirectFB driver bootstrap functions */
slouken@167
    95
slouken@1895
    96
static int
slouken@1895
    97
DirectFB_Available(void)
slouken@167
    98
{
slouken@1895
    99
    return 1;
slouken@167
   100
}
slouken@167
   101
slouken@1895
   102
static void
slouken@1895
   103
DirectFB_DeleteDevice(SDL_VideoDevice * device)
slouken@167
   104
{
slouken@1895
   105
    SDL_free(device->hidden);
slouken@1895
   106
    SDL_free(device);
slouken@167
   107
}
slouken@167
   108
slouken@1895
   109
static SDL_VideoDevice *
slouken@1895
   110
DirectFB_CreateDevice(int devindex)
slouken@167
   111
{
slouken@1895
   112
    SDL_VideoDevice *device;
slouken@167
   113
slouken@1895
   114
    /* Initialize all variables that we clean on shutdown */
slouken@1895
   115
    device = (SDL_VideoDevice *) SDL_malloc(sizeof(SDL_VideoDevice));
slouken@1895
   116
    if (device) {
slouken@1895
   117
        SDL_memset(device, 0, (sizeof *device));
slouken@1895
   118
        device->hidden = (struct SDL_PrivateVideoData *)
slouken@1895
   119
            malloc(sizeof(*device->hidden));
slouken@167
   120
    }
slouken@1895
   121
    if (device == NULL || device->hidden == NULL) {
slouken@1895
   122
        SDL_OutOfMemory();
slouken@1895
   123
        if (device) {
slouken@1895
   124
            free(device);
slouken@167
   125
        }
slouken@1895
   126
        return (0);
slouken@167
   127
    }
slouken@1895
   128
    SDL_memset(device->hidden, 0, sizeof(*device->hidden));
slouken@167
   129
slouken@1895
   130
    /* Set the function pointers */
slouken@1895
   131
    device->VideoInit = DirectFB_VideoInit;
slouken@1895
   132
    device->ListModes = DirectFB_ListModes;
slouken@1895
   133
    device->SetVideoMode = DirectFB_SetVideoMode;
slouken@1895
   134
    device->SetColors = DirectFB_SetColors;
slouken@1895
   135
    device->UpdateRects = NULL;
slouken@1895
   136
    device->CreateYUVOverlay = DirectFB_CreateYUVOverlay;
slouken@1895
   137
    device->VideoQuit = DirectFB_VideoQuit;
slouken@1895
   138
    device->AllocHWSurface = DirectFB_AllocHWSurface;
slouken@1895
   139
    device->CheckHWBlit = DirectFB_CheckHWBlit;
slouken@1895
   140
    device->FillHWRect = DirectFB_FillHWRect;
slouken@1895
   141
    device->SetHWColorKey = DirectFB_SetHWColorKey;
slouken@1895
   142
    device->SetHWAlpha = DirectFB_SetHWAlpha;
slouken@1895
   143
    device->LockHWSurface = DirectFB_LockHWSurface;
slouken@1895
   144
    device->UnlockHWSurface = DirectFB_UnlockHWSurface;
slouken@1895
   145
    device->FlipHWSurface = DirectFB_FlipHWSurface;
slouken@1895
   146
    device->FreeHWSurface = DirectFB_FreeHWSurface;
slouken@1895
   147
    device->ShowWMCursor = DirectFB_ShowWMCursor;
slouken@1895
   148
    device->SetCaption = NULL;
slouken@1895
   149
    device->SetIcon = NULL;
slouken@1895
   150
    device->IconifyWindow = NULL;
slouken@1895
   151
    device->GrabInput = NULL;
slouken@1895
   152
    device->GetWMInfo = NULL;
slouken@1895
   153
    device->InitOSKeymap = DirectFB_InitOSKeymap;
slouken@1895
   154
    device->PumpEvents = DirectFB_PumpEvents;
slouken@167
   155
slouken@1895
   156
    device->free = DirectFB_DeleteDevice;
slouken@167
   157
slouken@1895
   158
    return device;
slouken@167
   159
}
slouken@167
   160
slouken@167
   161
VideoBootStrap DirectFB_bootstrap = {
slouken@1895
   162
    "directfb", "DirectFB",
slouken@1895
   163
    DirectFB_Available, DirectFB_CreateDevice
slouken@167
   164
};
slouken@167
   165
slouken@1895
   166
static DFBSurfacePixelFormat
slouken@1895
   167
GetFormatForBpp(int bpp, IDirectFBDisplayLayer * layer)
slouken@464
   168
{
slouken@1895
   169
    DFBDisplayLayerConfig dlc;
slouken@1895
   170
    int bytes = (bpp + 7) / 8;
slouken@464
   171
slouken@1895
   172
    layer->GetConfiguration(layer, &dlc);
slouken@464
   173
slouken@1895
   174
    if (bytes == DFB_BYTES_PER_PIXEL(dlc.pixelformat) && bytes > 1)
slouken@1895
   175
        return dlc.pixelformat;
slouken@1895
   176
slouken@1895
   177
    switch (bytes) {
slouken@464
   178
    case 1:
slouken@1895
   179
        return DSPF_LUT8;
slouken@464
   180
    case 2:
slouken@1895
   181
        return DSPF_RGB16;
slouken@464
   182
    case 3:
slouken@1895
   183
        return DSPF_RGB24;
slouken@464
   184
    case 4:
slouken@1895
   185
        return DSPF_RGB32;
slouken@464
   186
    }
slouken@464
   187
slouken@1895
   188
    return DSPF_UNKNOWN;
slouken@464
   189
}
slouken@464
   190
slouken@1895
   191
static DFBEnumerationResult
slouken@1895
   192
EnumModesCallback(int width, int height, int bpp, void *data)
slouken@167
   193
{
slouken@1895
   194
    SDL_VideoDevice *this = (SDL_VideoDevice *) data;
slouken@1895
   195
    struct DirectFBEnumRect *enumrect;
slouken@1895
   196
slouken@1895
   197
    HIDDEN->nummodes++;
slouken@167
   198
slouken@1895
   199
    if (enumlist && enumlist->r.w == width && enumlist->r.h == height)
slouken@1895
   200
        return DFENUM_OK;
slouken@1777
   201
slouken@1895
   202
    enumrect = SDL_calloc(1, sizeof(struct DirectFBEnumRect));
slouken@1895
   203
    if (!enumrect) {
slouken@1895
   204
        SDL_OutOfMemory();
slouken@1895
   205
        return DFENUM_CANCEL;
slouken@167
   206
    }
slouken@167
   207
slouken@1895
   208
    enumrect->r.w = (Uint16) width;
slouken@1895
   209
    enumrect->r.h = (Uint16) height;
slouken@1895
   210
    enumrect->next = enumlist;
slouken@464
   211
slouken@1895
   212
    enumlist = enumrect;
slouken@464
   213
slouken@1895
   214
    return DFENUM_OK;
slouken@167
   215
}
slouken@167
   216
slouken@1895
   217
struct private_hwdata
slouken@1895
   218
{
slouken@1895
   219
    IDirectFBSurface *surface;
slouken@1895
   220
    IDirectFBPalette *palette;
slouken@167
   221
};
slouken@167
   222
slouken@1895
   223
void
slouken@1895
   224
SetDirectFBerror(const char *function, DFBResult code)
slouken@167
   225
{
slouken@1895
   226
    const char *error = DirectFBErrorString(code);
slouken@167
   227
slouken@1895
   228
    if (error)
slouken@1895
   229
        SDL_SetError("%s: %s", function, error);
slouken@1895
   230
    else
slouken@1895
   231
        SDL_SetError("Unknown error code from %s", function);
slouken@167
   232
}
slouken@167
   233
slouken@1895
   234
static DFBSurfacePixelFormat
slouken@1895
   235
SDLToDFBPixelFormat(SDL_PixelFormat * format)
slouken@167
   236
{
slouken@1895
   237
    if (format->Rmask && format->Gmask && format->Bmask) {
slouken@1895
   238
        switch (format->BitsPerPixel) {
slouken@477
   239
        case 8:
slouken@1895
   240
            return DSPF_LUT8;
slouken@1895
   241
slouken@167
   242
        case 16:
slouken@1895
   243
            if (format->Rmask == 0xF800 &&
slouken@1895
   244
                format->Gmask == 0x07E0 && format->Bmask == 0x001F)
slouken@1895
   245
                return DSPF_RGB16;
slouken@1895
   246
            /* fall through */
slouken@1895
   247
slouken@167
   248
        case 15:
slouken@1895
   249
            if (format->Rmask == 0x7C00 &&
slouken@1895
   250
                format->Gmask == 0x03E0 && format->Bmask == 0x001F)
slouken@1895
   251
                return DSPF_ARGB1555;
slouken@1895
   252
            break;
slouken@1895
   253
slouken@167
   254
        case 24:
slouken@1895
   255
            if (format->Rmask == 0xFF0000 &&
slouken@1895
   256
                format->Gmask == 0x00FF00 && format->Bmask == 0x0000FF)
slouken@1895
   257
                return DSPF_RGB24;
slouken@1895
   258
            break;
slouken@464
   259
slouken@167
   260
        case 32:
slouken@1895
   261
            if (format->Rmask == 0xFF0000 &&
slouken@1895
   262
                format->Gmask == 0x00FF00 && format->Bmask == 0x0000FF) {
slouken@1895
   263
                if (format->Amask == 0xFF000000)
slouken@1895
   264
                    return DSPF_ARGB;
slouken@1895
   265
                else
slouken@1895
   266
                    return DSPF_RGB32;
slouken@167
   267
            }
slouken@1895
   268
            break;
slouken@1895
   269
        }
slouken@1895
   270
    } else {
slouken@1895
   271
        switch (format->BitsPerPixel) {
slouken@1895
   272
        case 8:
slouken@1895
   273
            return DSPF_LUT8;
slouken@1895
   274
        case 15:
slouken@1895
   275
            return DSPF_ARGB1555;
slouken@1895
   276
        case 16:
slouken@1895
   277
            return DSPF_RGB16;
slouken@1895
   278
        case 24:
slouken@1895
   279
            return DSPF_RGB24;
slouken@1895
   280
        case 32:
slouken@1895
   281
            return DSPF_RGB32;
slouken@167
   282
        }
slouken@167
   283
    }
slouken@1895
   284
slouken@1895
   285
    return DSPF_UNKNOWN;
slouken@1895
   286
}
slouken@1895
   287
slouken@1895
   288
static SDL_Palette *
slouken@1895
   289
AllocatePalette(int size)
slouken@1895
   290
{
slouken@1895
   291
    SDL_Palette *palette;
slouken@1895
   292
    SDL_Color *colors;
slouken@1895
   293
slouken@1895
   294
    palette = SDL_calloc(1, sizeof(SDL_Palette));
slouken@1895
   295
    if (!palette) {
slouken@1895
   296
        SDL_OutOfMemory();
slouken@1895
   297
        return NULL;
slouken@167
   298
    }
slouken@167
   299
slouken@1895
   300
    colors = SDL_calloc(size, sizeof(SDL_Color));
slouken@1895
   301
    if (!colors) {
slouken@1895
   302
        SDL_OutOfMemory();
slouken@1895
   303
        return NULL;
slouken@464
   304
    }
slouken@464
   305
slouken@1895
   306
    palette->ncolors = size;
slouken@1895
   307
    palette->colors = colors;
slouken@464
   308
slouken@1895
   309
    return palette;
slouken@464
   310
}
slouken@464
   311
slouken@1895
   312
static int
slouken@1895
   313
DFBToSDLPixelFormat(DFBSurfacePixelFormat pixelformat,
slouken@1895
   314
                    SDL_PixelFormat * format)
slouken@167
   315
{
slouken@1895
   316
    format->Amask = format->Rmask = format->Gmask = format->Bmask = 0;
slouken@1895
   317
    format->BitsPerPixel = format->BytesPerPixel = 0;
slouken@167
   318
slouken@1895
   319
    switch (pixelformat) {
slouken@167
   320
    case DSPF_A8:
slouken@1895
   321
        format->Amask = 0x000000FF;
slouken@1895
   322
        break;
slouken@464
   323
slouken@790
   324
    case DSPF_ARGB1555:
slouken@1895
   325
        format->Rmask = 0x00007C00;
slouken@1895
   326
        format->Gmask = 0x000003E0;
slouken@1895
   327
        format->Bmask = 0x0000001F;
slouken@1895
   328
        break;
slouken@464
   329
slouken@167
   330
    case DSPF_RGB16:
slouken@1895
   331
        format->Rmask = 0x0000F800;
slouken@1895
   332
        format->Gmask = 0x000007E0;
slouken@1895
   333
        format->Bmask = 0x0000001F;
slouken@1895
   334
        break;
slouken@464
   335
slouken@167
   336
    case DSPF_ARGB:
slouken@1895
   337
        format->Amask = 0;      /* apps don't seem to like that:  0xFF000000; */
slouken@1895
   338
        /* fall through */
slouken@167
   339
    case DSPF_RGB24:
slouken@167
   340
    case DSPF_RGB32:
slouken@1895
   341
        format->Rmask = 0x00FF0000;
slouken@1895
   342
        format->Gmask = 0x0000FF00;
slouken@1895
   343
        format->Bmask = 0x000000FF;
slouken@1895
   344
        break;
slouken@464
   345
slouken@477
   346
    case DSPF_LUT8:
slouken@1895
   347
        format->Rmask = 0x000000FF;
slouken@1895
   348
        format->Gmask = 0x000000FF;
slouken@1895
   349
        format->Bmask = 0x000000FF;
slouken@464
   350
slouken@1895
   351
        if (!format->palette)
slouken@1895
   352
            format->palette = AllocatePalette(256);
slouken@1895
   353
        break;
slouken@464
   354
slouken@167
   355
    default:
slouken@1895
   356
        fprintf(stderr,
slouken@1895
   357
                "SDL_DirectFB: Unsupported pixelformat (0x%08x)!\n",
slouken@1895
   358
                pixelformat);
slouken@1895
   359
        return -1;
slouken@167
   360
    }
slouken@167
   361
slouken@1895
   362
    format->BitsPerPixel = DFB_BYTES_PER_PIXEL(pixelformat) * 8;
slouken@1895
   363
    format->BytesPerPixel = DFB_BYTES_PER_PIXEL(pixelformat);
slouken@167
   364
slouken@1895
   365
    return 0;
slouken@167
   366
}
slouken@167
   367
slouken@167
   368
slouken@1895
   369
int
slouken@1895
   370
DirectFB_VideoInit(_THIS, SDL_PixelFormat * vformat)
slouken@167
   371
{
slouken@1895
   372
    int i;
slouken@1895
   373
    DFBResult ret;
icculus@1165
   374
#if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23)
slouken@1895
   375
    DFBCardCapabilities caps;
icculus@1165
   376
#else
slouken@1895
   377
    DFBGraphicsDeviceDescription caps;
icculus@1165
   378
#endif
slouken@1895
   379
    DFBDisplayLayerConfig dlc;
slouken@1895
   380
    struct DirectFBEnumRect *rect;
slouken@1895
   381
    IDirectFB *dfb = NULL;
slouken@1895
   382
    IDirectFBDisplayLayer *layer = NULL;
slouken@1895
   383
    IDirectFBEventBuffer *events = NULL;
slouken@167
   384
slouken@1895
   385
    HIDDEN->c2layer = NULL, HIDDEN->c2frame = NULL;
slouken@1895
   386
    HIDDEN->enable_mga_crtc2 = 0;
slouken@1895
   387
    HIDDEN->mga_crtc2_stretch_overscan = 1;
slouken@167
   388
slouken@1895
   389
    ret = DirectFBInit(NULL, NULL);
slouken@1895
   390
    if (ret) {
slouken@1895
   391
        SetDirectFBerror("DirectFBInit", ret);
slouken@1895
   392
        goto error;
slouken@167
   393
    }
slouken@167
   394
slouken@1895
   395
    ret = DirectFBCreate(&dfb);
slouken@1895
   396
    if (ret) {
slouken@1895
   397
        SetDirectFBerror("DirectFBCreate", ret);
slouken@1895
   398
        goto error;
slouken@1895
   399
    }
slouken@1895
   400
slouken@1895
   401
    ret = dfb->GetDisplayLayer(dfb, DLID_PRIMARY, &layer);
slouken@1895
   402
    if (ret) {
slouken@1895
   403
        SetDirectFBerror("dfb->GetDisplayLayer", ret);
slouken@1895
   404
        goto error;
slouken@167
   405
    }
slouken@167
   406
slouken@1895
   407
    ret = dfb->CreateInputEventBuffer(dfb, DICAPS_ALL, DFB_FALSE, &events);
slouken@1895
   408
    if (ret) {
slouken@1895
   409
        SetDirectFBerror("dfb->CreateEventBuffer", ret);
slouken@1895
   410
        goto error;
slouken@1895
   411
    }
slouken@1895
   412
slouken@1895
   413
    layer->EnableCursor(layer, 1);
slouken@1895
   414
slouken@1895
   415
    /* Query layer configuration to determine the current mode and pixelformat */
slouken@1895
   416
    layer->GetConfiguration(layer, &dlc);
slouken@1895
   417
slouken@1895
   418
    /* If current format is not supported use LUT8 as the default */
slouken@1895
   419
    if (DFBToSDLPixelFormat(dlc.pixelformat, vformat))
slouken@1895
   420
        DFBToSDLPixelFormat(DSPF_LUT8, vformat);
slouken@1895
   421
slouken@1895
   422
    /* Enumerate the available fullscreen modes */
slouken@1895
   423
    ret = dfb->EnumVideoModes(dfb, EnumModesCallback, this);
slouken@1895
   424
    if (ret) {
slouken@1895
   425
        SetDirectFBerror("dfb->EnumVideoModes", ret);
slouken@1895
   426
        goto error;
slouken@167
   427
    }
slouken@167
   428
slouken@1895
   429
    HIDDEN->modelist = SDL_calloc(HIDDEN->nummodes + 1, sizeof(SDL_Rect *));
slouken@1895
   430
    if (!HIDDEN->modelist) {
slouken@1895
   431
        SDL_OutOfMemory();
slouken@1895
   432
        goto error;
slouken@167
   433
    }
slouken@464
   434
slouken@1895
   435
    for (i = 0, rect = enumlist; rect; ++i, rect = rect->next) {
slouken@1895
   436
        HIDDEN->modelist[i] = &rect->r;
slouken@167
   437
    }
slouken@167
   438
slouken@1895
   439
    HIDDEN->modelist[i] = NULL;
slouken@464
   440
slouken@464
   441
slouken@1895
   442
    /* Query card capabilities to get the video memory size */
icculus@1165
   443
#if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23)
slouken@1895
   444
    dfb->GetCardCapabilities(dfb, &caps);
icculus@1165
   445
#else
slouken@1895
   446
    dfb->GetDeviceDescription(dfb, &caps);
icculus@1165
   447
#endif
slouken@167
   448
slouken@1895
   449
    this->info.wm_available = 1;
slouken@1895
   450
    this->info.hw_available = 1;
slouken@1895
   451
    this->info.blit_hw = 1;
slouken@1895
   452
    this->info.blit_hw_CC = 1;
slouken@1895
   453
    this->info.blit_hw_A = 1;
slouken@1895
   454
    this->info.blit_fill = 1;
slouken@1895
   455
    this->info.video_mem = caps.video_memory / 1024;
slouken@167
   456
slouken@1895
   457
    HIDDEN->initialized = 1;
slouken@1895
   458
    HIDDEN->dfb = dfb;
slouken@1895
   459
    HIDDEN->layer = layer;
slouken@1895
   460
    HIDDEN->eventbuffer = events;
slouken@1895
   461
slouken@1895
   462
    if (SDL_getenv("SDL_DIRECTFB_MGA_CRTC2") != NULL)
slouken@1895
   463
        HIDDEN->enable_mga_crtc2 = 1;
slouken@1018
   464
slouken@1895
   465
    if (HIDDEN->enable_mga_crtc2) {
slouken@1895
   466
        DFBDisplayLayerConfig dlc;
slouken@1895
   467
        DFBDisplayLayerConfigFlags failed;
slouken@1895
   468
slouken@1895
   469
        ret = dfb->GetDisplayLayer(dfb, 2, &HIDDEN->c2layer);
slouken@1895
   470
        if (ret) {
slouken@1895
   471
            SetDirectFBerror("dfb->GetDisplayLayer(CRTC2)", ret);
slouken@1895
   472
            goto error;
icculus@728
   473
        }
icculus@728
   474
slouken@1895
   475
        ret =
slouken@1895
   476
            HIDDEN->layer->SetCooperativeLevel(HIDDEN->layer,
slouken@1895
   477
                                               DLSCL_EXCLUSIVE);
slouken@1895
   478
        if (ret) {
slouken@1895
   479
            SetDirectFBerror
slouken@1895
   480
                ("layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
slouken@1895
   481
            goto error;
icculus@728
   482
        }
slouken@1895
   483
slouken@1895
   484
        ret =
slouken@1895
   485
            HIDDEN->c2layer->SetCooperativeLevel(HIDDEN->c2layer,
slouken@1895
   486
                                                 DLSCL_EXCLUSIVE);
slouken@1895
   487
        if (ret) {
slouken@1895
   488
            SetDirectFBerror
slouken@1895
   489
                ("c2layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
slouken@1895
   490
            goto error;
icculus@728
   491
        }
icculus@728
   492
slouken@1895
   493
        HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0x0);
slouken@1895
   494
slouken@1895
   495
        /* Init the surface here as it got a fixed size */
slouken@1895
   496
        dlc.flags = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
slouken@1895
   497
        dlc.buffermode = DLBM_BACKVIDEO;
slouken@1895
   498
        dlc.pixelformat = DSPF_RGB32;
icculus@728
   499
slouken@1895
   500
        ret =
slouken@1895
   501
            HIDDEN->c2layer->TestConfiguration(HIDDEN->c2layer, &dlc,
slouken@1895
   502
                                               &failed);
slouken@1895
   503
        if (ret) {
slouken@1895
   504
            SetDirectFBerror("c2layer->TestConfiguration", ret);
slouken@1895
   505
            goto error;
icculus@728
   506
        }
slouken@1895
   507
slouken@1895
   508
        ret = HIDDEN->c2layer->SetConfiguration(HIDDEN->c2layer, &dlc);
slouken@1895
   509
        if (ret) {
slouken@1895
   510
            SetDirectFBerror("c2layer->SetConfiguration", ret);
slouken@1895
   511
            goto error;
icculus@728
   512
        }
slouken@1895
   513
slouken@1895
   514
        ret = HIDDEN->c2layer->GetSurface(HIDDEN->c2layer, &HIDDEN->c2frame);
slouken@1895
   515
        if (ret) {
slouken@1895
   516
            SetDirectFBerror("c2layer->GetSurface", ret);
slouken@1895
   517
            goto error;
icculus@728
   518
        }
icculus@728
   519
slouken@1895
   520
        HIDDEN->c2framesize.x = 0;
slouken@1895
   521
        HIDDEN->c2framesize.y = 0;
slouken@1895
   522
        HIDDEN->c2frame->GetSize(HIDDEN->c2frame, &HIDDEN->c2framesize.w,
slouken@1895
   523
                                 &HIDDEN->c2framesize.h);
icculus@728
   524
slouken@1895
   525
        HIDDEN->c2frame->SetBlittingFlags(HIDDEN->c2frame, DSBLIT_NOFX);
slouken@1895
   526
        HIDDEN->c2frame->SetColor(HIDDEN->c2frame, 0, 0, 0, 0xff);
slouken@1895
   527
slouken@1895
   528
        /* Clear CRTC2 */
slouken@1895
   529
        HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff);
slouken@1895
   530
        HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0);
slouken@1895
   531
        HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff);
slouken@1895
   532
        HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0);
slouken@1895
   533
        HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff);
icculus@728
   534
slouken@1895
   535
        HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0xFF);
icculus@732
   536
slouken@1895
   537
        /* Check if overscan is possibly set */
slouken@1895
   538
        if (SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN") != NULL) {
slouken@1895
   539
            float overscan = 0;
slouken@1895
   540
            if (SDL_sscanf
slouken@1895
   541
                (SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN"), "%f",
slouken@1895
   542
                 &overscan) == 1)
slouken@1895
   543
                if (overscan > 0 && overscan < 2)
slouken@1895
   544
                    HIDDEN->mga_crtc2_stretch_overscan = overscan;
slouken@1895
   545
        }
slouken@1895
   546
#ifdef DIRECTFB_CRTC2_DEBUG
slouken@1895
   547
        printf("CRTC2 overscan: %f\n", HIDDEN->mga_crtc2_stretch_overscan);
slouken@1895
   548
#endif
icculus@728
   549
    }
icculus@728
   550
slouken@1895
   551
    return 0;
slouken@464
   552
slouken@1895
   553
  error:
slouken@1895
   554
    if (events)
slouken@1895
   555
        events->Release(events);
slouken@1895
   556
slouken@1895
   557
    if (HIDDEN->c2frame)
slouken@1895
   558
        HIDDEN->c2frame->Release(HIDDEN->c2frame);
icculus@728
   559
slouken@1895
   560
    if (HIDDEN->c2layer)
slouken@1895
   561
        HIDDEN->c2layer->Release(HIDDEN->c2layer);
icculus@728
   562
slouken@1895
   563
    if (layer)
slouken@1895
   564
        layer->Release(layer);
slouken@464
   565
slouken@1895
   566
    if (dfb)
slouken@1895
   567
        dfb->Release(dfb);
slouken@464
   568
slouken@1895
   569
    return -1;
slouken@167
   570
}
slouken@167
   571
slouken@1895
   572
static SDL_Rect **
slouken@1895
   573
DirectFB_ListModes(_THIS, SDL_PixelFormat * format, Uint32 flags)
slouken@167
   574
{
slouken@1895
   575
    if (flags & SDL_FULLSCREEN)
slouken@1895
   576
        return HIDDEN->modelist;
slouken@1895
   577
    else if (SDLToDFBPixelFormat(format) != DSPF_UNKNOWN)
slouken@1895
   578
        return (SDL_Rect **) - 1;
slouken@167
   579
slouken@1895
   580
    return NULL;
slouken@167
   581
}
slouken@167
   582
slouken@1895
   583
static SDL_Surface *
slouken@1895
   584
DirectFB_SetVideoMode(_THIS, SDL_Surface * current, int width, int height,
slouken@1895
   585
                      int bpp, Uint32 flags)
slouken@167
   586
{
slouken@1895
   587
    DFBResult ret;
slouken@1895
   588
    DFBSurfaceDescription dsc;
slouken@1895
   589
    DFBSurfacePixelFormat pixelformat;
slouken@1895
   590
    IDirectFBSurface *surface;
slouken@167
   591
slouken@1895
   592
    fprintf(stderr, "SDL DirectFB_SetVideoMode: %dx%d@%d, flags: 0x%08x\n",
slouken@1895
   593
            width, height, bpp, flags);
slouken@167
   594
slouken@1895
   595
    flags |= SDL_FULLSCREEN;
slouken@167
   596
slouken@1895
   597
    /* Release previous primary surface */
slouken@1895
   598
    if (current->hwdata && current->hwdata->surface) {
slouken@1895
   599
        current->hwdata->surface->Release(current->hwdata->surface);
slouken@1895
   600
        current->hwdata->surface = NULL;
slouken@477
   601
slouken@1895
   602
        /* And its palette if present */
slouken@1895
   603
        if (current->hwdata->palette) {
slouken@1895
   604
            current->hwdata->palette->Release(current->hwdata->palette);
slouken@1895
   605
            current->hwdata->palette = NULL;
slouken@1895
   606
        }
slouken@1895
   607
    } else if (!current->hwdata) {
slouken@1895
   608
        /* Allocate the hardware acceleration data */
slouken@1895
   609
        current->hwdata =
slouken@1895
   610
            (struct private_hwdata *) SDL_calloc(1, sizeof(*current->hwdata));
slouken@1895
   611
        if (!current->hwdata) {
slouken@1895
   612
            SDL_OutOfMemory();
slouken@1895
   613
            return NULL;
slouken@477
   614
        }
slouken@167
   615
    }
slouken@167
   616
slouken@1895
   617
    /* Set cooperative level depending on flag SDL_FULLSCREEN */
slouken@1895
   618
    if (flags & SDL_FULLSCREEN) {
slouken@1895
   619
        ret = HIDDEN->dfb->SetCooperativeLevel(HIDDEN->dfb, DFSCL_FULLSCREEN);
slouken@1895
   620
        if (ret && !HIDDEN->enable_mga_crtc2) {
slouken@1895
   621
            DirectFBError("dfb->SetCooperativeLevel", ret);
slouken@1895
   622
            flags &= ~SDL_FULLSCREEN;
slouken@167
   623
        }
slouken@1895
   624
    } else
slouken@1895
   625
        HIDDEN->dfb->SetCooperativeLevel(HIDDEN->dfb, DFSCL_NORMAL);
slouken@167
   626
slouken@1895
   627
    /* Set video mode */
slouken@1895
   628
    ret = HIDDEN->dfb->SetVideoMode(HIDDEN->dfb, width, height, bpp);
slouken@1895
   629
    if (ret) {
slouken@1895
   630
        if (flags & SDL_FULLSCREEN) {
slouken@1895
   631
            flags &= ~SDL_FULLSCREEN;
slouken@1895
   632
            HIDDEN->dfb->SetCooperativeLevel(HIDDEN->dfb, DFSCL_NORMAL);
slouken@1895
   633
            ret = HIDDEN->dfb->SetVideoMode(HIDDEN->dfb, width, height, bpp);
slouken@167
   634
        }
slouken@167
   635
slouken@1895
   636
        if (ret) {
slouken@1895
   637
            SetDirectFBerror("dfb->SetVideoMode", ret);
slouken@1895
   638
            return NULL;
slouken@167
   639
        }
slouken@167
   640
    }
slouken@167
   641
slouken@1895
   642
    /* Create primary surface */
slouken@1895
   643
    dsc.flags = DSDESC_CAPS | DSDESC_PIXELFORMAT;
slouken@1895
   644
    dsc.caps =
slouken@1895
   645
        DSCAPS_PRIMARY | ((flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0);
slouken@1895
   646
    dsc.pixelformat = GetFormatForBpp(bpp, HIDDEN->layer);
slouken@167
   647
slouken@1895
   648
    ret = HIDDEN->dfb->CreateSurface(HIDDEN->dfb, &dsc, &surface);
slouken@1895
   649
    if (ret && (flags & SDL_DOUBLEBUF)) {
slouken@1895
   650
        /* Try without double buffering */
slouken@1895
   651
        dsc.caps &= ~DSCAPS_FLIPPING;
slouken@1895
   652
        ret = HIDDEN->dfb->CreateSurface(HIDDEN->dfb, &dsc, &surface);
slouken@167
   653
    }
slouken@1895
   654
    if (ret) {
slouken@1895
   655
        SetDirectFBerror("dfb->CreateSurface", ret);
slouken@1895
   656
        return NULL;
slouken@167
   657
    }
slouken@167
   658
slouken@1895
   659
    current->w = width;
slouken@1895
   660
    current->h = height;
slouken@1895
   661
    current->flags = SDL_HWSURFACE | SDL_PREALLOC;
slouken@167
   662
slouken@1895
   663
    if (flags & SDL_FULLSCREEN) {
slouken@1895
   664
        current->flags |= SDL_FULLSCREEN;
slouken@1895
   665
        this->UpdateRects = DirectFB_DirectUpdate;
slouken@1895
   666
    } else
slouken@1895
   667
        this->UpdateRects = DirectFB_WindowedUpdate;
slouken@167
   668
slouken@1895
   669
    if (dsc.caps & DSCAPS_FLIPPING)
slouken@1895
   670
        current->flags |= SDL_DOUBLEBUF;
slouken@167
   671
slouken@1895
   672
    surface->GetPixelFormat(surface, &pixelformat);
slouken@167
   673
slouken@1895
   674
    DFBToSDLPixelFormat(pixelformat, current->format);
slouken@477
   675
slouken@1895
   676
    /* Get the surface palette (if supported) */
slouken@1895
   677
    if (DFB_PIXELFORMAT_IS_INDEXED(pixelformat)) {
slouken@1895
   678
        surface->GetPalette(surface, &current->hwdata->palette);
slouken@1895
   679
slouken@1895
   680
        current->flags |= SDL_HWPALETTE;
slouken@477
   681
    }
slouken@477
   682
slouken@1895
   683
    current->hwdata->surface = surface;
slouken@477
   684
slouken@1895
   685
    /* MGA CRTC2 stuff */
slouken@1895
   686
    if (HIDDEN->enable_mga_crtc2) {
slouken@1895
   687
        /* no stretching if c2ssize == c2framesize */
slouken@1895
   688
        HIDDEN->c2ssize.x = 0, HIDDEN->c2ssize.y = 0;
slouken@1895
   689
        HIDDEN->c2ssize.w = width;
slouken@1895
   690
        HIDDEN->c2ssize.h = height;
icculus@728
   691
slouken@1895
   692
        HIDDEN->c2dsize.x = 0, HIDDEN->c2dsize.y = 0;
slouken@1895
   693
        HIDDEN->c2dsize.w = width;
slouken@1895
   694
        HIDDEN->c2dsize.h = height;
slouken@1895
   695
slouken@1895
   696
        HIDDEN->mga_crtc2_stretch = 0;
icculus@728
   697
slouken@1895
   698
        if (SDL_getenv("SDL_DIRECTFB_MGA_STRETCH") != NULL) {
slouken@1895
   699
            /* Normally assume a picture aspect ratio of 4:3 */
slouken@1895
   700
            int zoom_aspect_x = 4, zoom_aspect_y = 3, i, j;
icculus@728
   701
slouken@1895
   702
            for (i = 1; i < 20; i++) {
slouken@1895
   703
                for (j = 1; j < 10; j++) {
slouken@1895
   704
                    if ((float) width / (float) i * (float) j == height) {
slouken@1895
   705
                        zoom_aspect_x = i;
slouken@1895
   706
                        zoom_aspect_y = j;
icculus@732
   707
slouken@1895
   708
                        /* break the loop */
slouken@1895
   709
                        i = 21;
slouken@1895
   710
                        break;
slouken@1895
   711
                    }
slouken@1895
   712
                }
slouken@1895
   713
            }
slouken@1895
   714
slouken@1895
   715
#ifdef DIRECTFB_CRTC2_DEBUG
slouken@1895
   716
            printf
slouken@1895
   717
                ("Source resolution: X: %d, Y: %d, Aspect ratio: %d:%d\n",
slouken@1895
   718
                 width, height, zoom_aspect_x, zoom_aspect_y);
slouken@1895
   719
            printf("CRTC2 resolution: X: %d, Y: %d\n",
slouken@1895
   720
                   HIDDEN->c2framesize.w, HIDDEN->c2framesize.h);
slouken@1895
   721
#endif
slouken@1895
   722
slouken@1895
   723
            /* don't stretch only slightly smaller/larger images */
slouken@1895
   724
            if ((float) width < (float) HIDDEN->c2framesize.w * 0.95
slouken@1895
   725
                || (float) height < (float) HIDDEN->c2framesize.h * 0.95) {
slouken@1895
   726
                while ((float) HIDDEN->c2dsize.w <
slouken@1895
   727
                       (float) HIDDEN->c2framesize.w *
slouken@1895
   728
                       HIDDEN->mga_crtc2_stretch_overscan
slouken@1895
   729
                       && (float) HIDDEN->c2dsize.h <
slouken@1895
   730
                       (float) HIDDEN->c2framesize.h *
slouken@1895
   731
                       HIDDEN->mga_crtc2_stretch_overscan) {
slouken@1895
   732
                    HIDDEN->c2dsize.w += zoom_aspect_x;
slouken@1895
   733
                    HIDDEN->c2dsize.h += zoom_aspect_y;
icculus@728
   734
                }
icculus@728
   735
slouken@1895
   736
                /* one step down */
slouken@1895
   737
                HIDDEN->c2dsize.w -= zoom_aspect_x;
slouken@1895
   738
                HIDDEN->c2dsize.h -= zoom_aspect_y;
icculus@728
   739
slouken@1895
   740
#ifdef DIRECTFB_CRTC2_DEBUG
slouken@1895
   741
                printf("Stretched resolution: X: %d, Y: %d\n",
slouken@1895
   742
                       HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
slouken@1895
   743
#endif
icculus@728
   744
slouken@1895
   745
                HIDDEN->mga_crtc2_stretch = 1;
slouken@1895
   746
            } else if ((float) width > (float) HIDDEN->c2framesize.w * 0.95
slouken@1895
   747
                       || (float) height >
slouken@1895
   748
                       (float) HIDDEN->c2framesize.h * 0.95) {
slouken@1895
   749
                while ((float) HIDDEN->c2dsize.w >
slouken@1895
   750
                       (float) HIDDEN->c2framesize.w *
slouken@1895
   751
                       HIDDEN->mga_crtc2_stretch_overscan
slouken@1895
   752
                       || (float) HIDDEN->c2dsize.h >
slouken@1895
   753
                       (float) HIDDEN->c2framesize.h *
slouken@1895
   754
                       HIDDEN->mga_crtc2_stretch_overscan) {
slouken@1895
   755
                    HIDDEN->c2dsize.w -= zoom_aspect_x;
slouken@1895
   756
                    HIDDEN->c2dsize.h -= zoom_aspect_y;
icculus@728
   757
                }
slouken@1895
   758
slouken@1895
   759
#ifdef DIRECTFB_CRTC2_DEBUG
slouken@1895
   760
                printf("Down-Stretched resolution: X: %d, Y: %d\n",
slouken@1895
   761
                       HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
slouken@1895
   762
#endif
icculus@728
   763
slouken@1895
   764
                HIDDEN->mga_crtc2_stretch = 1;
slouken@1895
   765
            } else {
slouken@1895
   766
#ifdef DIRECTFB_CRTC2_DEBUG
slouken@1895
   767
                printf("Not stretching image\n");
slouken@1895
   768
#endif
slouken@1895
   769
            }
icculus@728
   770
slouken@1895
   771
            /* Panning */
slouken@1895
   772
            if (HIDDEN->c2framesize.w > HIDDEN->c2dsize.w)
slouken@1895
   773
                HIDDEN->c2dsize.x =
slouken@1895
   774
                    (HIDDEN->c2framesize.w - HIDDEN->c2dsize.w) / 2;
slouken@1895
   775
            else
slouken@1895
   776
                HIDDEN->c2dsize.x =
slouken@1895
   777
                    (HIDDEN->c2dsize.w - HIDDEN->c2framesize.w) / 2;
icculus@728
   778
slouken@1895
   779
            if (HIDDEN->c2framesize.h > HIDDEN->c2dsize.h)
slouken@1895
   780
                HIDDEN->c2dsize.y =
slouken@1895
   781
                    (HIDDEN->c2framesize.h - HIDDEN->c2dsize.h) / 2;
slouken@1895
   782
            else
slouken@1895
   783
                HIDDEN->c2dsize.y =
slouken@1895
   784
                    (HIDDEN->c2dsize.h - HIDDEN->c2framesize.h) / 2;
icculus@728
   785
slouken@1895
   786
#ifdef DIRECTFB_CRTC2_DEBUG
slouken@1895
   787
            printf("CRTC2 position X: %d, Y: %d\n", HIDDEN->c2dsize.x,
slouken@1895
   788
                   HIDDEN->c2dsize.y);
slouken@1895
   789
#endif
slouken@1895
   790
        }
slouken@1895
   791
    }
icculus@728
   792
slouken@1895
   793
    return current;
slouken@167
   794
}
slouken@167
   795
slouken@1895
   796
static int
slouken@1895
   797
DirectFB_AllocHWSurface(_THIS, SDL_Surface * surface)
slouken@167
   798
{
slouken@1895
   799
    DFBResult ret;
slouken@1895
   800
    DFBSurfaceDescription dsc;
slouken@167
   801
slouken@1895
   802
    /*  fprintf(stderr, "SDL: DirectFB_AllocHWSurface (%dx%d@%d, flags: 0x%08x)\n",
slouken@1895
   803
       surface->w, surface->h, surface->format->BitsPerPixel, surface->flags); */
slouken@167
   804
slouken@1895
   805
    if (surface->w < 8 || surface->h < 8)
slouken@1895
   806
        return -1;
slouken@167
   807
slouken@1895
   808
    /* fill surface description */
slouken@1895
   809
    dsc.flags =
slouken@1895
   810
        DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
slouken@1895
   811
    dsc.width = surface->w;
slouken@1895
   812
    dsc.height = surface->h;
slouken@1895
   813
    dsc.caps = (surface->flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0;
slouken@167
   814
slouken@1895
   815
    /* find the right pixelformat */
slouken@1895
   816
    dsc.pixelformat = SDLToDFBPixelFormat(surface->format);
slouken@1895
   817
    if (dsc.pixelformat == DSPF_UNKNOWN)
slouken@1895
   818
        return -1;
slouken@167
   819
slouken@1895
   820
    /* Allocate the hardware acceleration data */
slouken@1895
   821
    surface->hwdata =
slouken@1895
   822
        (struct private_hwdata *) SDL_calloc(1, sizeof(*surface->hwdata));
slouken@1895
   823
    if (surface->hwdata == NULL) {
slouken@1895
   824
        SDL_OutOfMemory();
slouken@1895
   825
        return -1;
slouken@167
   826
    }
slouken@167
   827
slouken@1895
   828
    /* Create the surface */
slouken@1895
   829
    ret =
slouken@1895
   830
        HIDDEN->dfb->CreateSurface(HIDDEN->dfb, &dsc,
slouken@1895
   831
                                   &surface->hwdata->surface);
slouken@1895
   832
    if (ret) {
slouken@1895
   833
        SetDirectFBerror("dfb->CreateSurface", ret);
slouken@1895
   834
        free(surface->hwdata);
slouken@1895
   835
        surface->hwdata = NULL;
slouken@1895
   836
        return -1;
slouken@167
   837
    }
slouken@167
   838
slouken@1895
   839
    surface->flags |= SDL_HWSURFACE | SDL_PREALLOC;
slouken@167
   840
slouken@1895
   841
    return 0;
slouken@167
   842
}
slouken@167
   843
slouken@1895
   844
static void
slouken@1895
   845
DirectFB_FreeHWSurface(_THIS, SDL_Surface * surface)
slouken@167
   846
{
slouken@1895
   847
    if (surface->hwdata && HIDDEN->initialized) {
slouken@1895
   848
        surface->hwdata->surface->Release(surface->hwdata->surface);
slouken@1895
   849
        free(surface->hwdata);
slouken@1895
   850
        surface->hwdata = NULL;
slouken@167
   851
    }
slouken@167
   852
}
slouken@167
   853
slouken@1895
   854
static int
slouken@1895
   855
DirectFB_CheckHWBlit(_THIS, SDL_Surface * src, SDL_Surface * dst)
slouken@167
   856
{
slouken@1895
   857
    /*  fprintf(stderr, "SDL: DirectFB_CheckHWBlit (src->hwdata: %p, dst->hwdata: %p)\n",
slouken@1895
   858
       src->hwdata, dst->hwdata); */
slouken@167
   859
slouken@1895
   860
    if (!src->hwdata || !dst->hwdata)
slouken@1895
   861
        return 0;
slouken@167
   862
slouken@1895
   863
    src->flags |= SDL_HWACCEL;
slouken@1895
   864
    src->map->hw_blit = DirectFB_HWAccelBlit;
slouken@167
   865
slouken@1895
   866
    return 1;
slouken@167
   867
}
slouken@167
   868
slouken@1895
   869
static int
slouken@1895
   870
DirectFB_HWAccelBlit(SDL_Surface * src, SDL_Rect * srcrect,
slouken@1895
   871
                     SDL_Surface * dst, SDL_Rect * dstrect)
slouken@167
   872
{
slouken@1895
   873
    DFBSurfaceBlittingFlags flags = DSBLIT_NOFX;
slouken@167
   874
slouken@1895
   875
    DFBRectangle sr = { srcrect->x, srcrect->y, srcrect->w, srcrect->h };
slouken@1895
   876
    DFBRectangle dr = { dstrect->x, dstrect->y, dstrect->w, dstrect->h };
slouken@167
   877
slouken@1895
   878
    IDirectFBSurface *surface = dst->hwdata->surface;
slouken@1895
   879
slouken@1895
   880
    if (src->flags & SDL_SRCCOLORKEY) {
slouken@1895
   881
        flags |= DSBLIT_SRC_COLORKEY;
slouken@1895
   882
        DirectFB_SetHWColorKey(NULL, src, src->format->colorkey);
slouken@167
   883
    }
slouken@167
   884
slouken@1895
   885
    if (src->flags & SDL_SRCALPHA) {
slouken@1895
   886
        flags |= DSBLIT_BLEND_COLORALPHA;
slouken@1895
   887
        surface->SetColor(surface, 0xff, 0xff, 0xff, src->format->alpha);
slouken@167
   888
    }
slouken@167
   889
slouken@1895
   890
    surface->SetBlittingFlags(surface, flags);
slouken@167
   891
slouken@1895
   892
    if (sr.w == dr.w && sr.h == dr.h)
slouken@1895
   893
        surface->Blit(surface, src->hwdata->surface, &sr, dr.x, dr.y);
slouken@1895
   894
    else
slouken@1895
   895
        surface->StretchBlit(surface, src->hwdata->surface, &sr, &dr);
slouken@167
   896
slouken@1895
   897
    return 0;
slouken@167
   898
}
slouken@167
   899
slouken@1895
   900
static int
slouken@1895
   901
DirectFB_FillHWRect(_THIS, SDL_Surface * dst, SDL_Rect * dstrect,
slouken@1895
   902
                    Uint32 color)
slouken@167
   903
{
slouken@1895
   904
    SDL_PixelFormat *fmt = dst->format;
slouken@1895
   905
    IDirectFBSurface *surface = dst->hwdata->surface;
slouken@167
   906
slouken@1895
   907
    /* ugly */
slouken@1895
   908
    surface->SetColor(surface,
slouken@1895
   909
                      (color & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
slouken@1895
   910
                      (color & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
slouken@1895
   911
                      (color & fmt->Bmask) << (fmt->Bloss - fmt->Bshift),
slouken@1895
   912
                      0xFF);
slouken@1895
   913
    surface->FillRectangle(surface, dstrect->x, dstrect->y, dstrect->w,
slouken@1895
   914
                           dstrect->h);
slouken@167
   915
slouken@1895
   916
    return 0;
slouken@167
   917
}
slouken@167
   918
slouken@1895
   919
static int
slouken@1895
   920
DirectFB_SetHWColorKey(_THIS, SDL_Surface * src, Uint32 key)
slouken@167
   921
{
slouken@1895
   922
    SDL_PixelFormat *fmt = src->format;
slouken@1895
   923
    IDirectFBSurface *surface = src->hwdata->surface;
slouken@219
   924
slouken@1895
   925
    if (fmt->BitsPerPixel == 8)
slouken@1895
   926
        surface->SetSrcColorKeyIndex(surface, key);
slouken@1895
   927
    else
slouken@1895
   928
        /* ugly */
slouken@1895
   929
        surface->SetSrcColorKey(surface,
slouken@1895
   930
                                (key & fmt->Rmask) >> (fmt->Rshift -
slouken@1895
   931
                                                       fmt->Rloss),
slouken@1895
   932
                                (key & fmt->Gmask) >> (fmt->Gshift -
slouken@1895
   933
                                                       fmt->Gloss),
slouken@1895
   934
                                (key & fmt->Bmask) << (fmt->Bloss -
slouken@1895
   935
                                                       fmt->Bshift));
slouken@219
   936
slouken@1895
   937
    return 0;
slouken@167
   938
}
slouken@167
   939
slouken@1895
   940
static int
slouken@1895
   941
DirectFB_SetHWAlpha(_THIS, SDL_Surface * surface, Uint8 alpha)
slouken@167
   942
{
slouken@1895
   943
    return 0;
slouken@167
   944
}
slouken@167
   945
slouken@1895
   946
static int
slouken@1895
   947
DirectFB_FlipHWSurface(_THIS, SDL_Surface * surface)
slouken@167
   948
{
slouken@1895
   949
    if (HIDDEN->enable_mga_crtc2) {
slouken@1895
   950
        int rtn =
slouken@1895
   951
            surface->hwdata->surface->Flip(surface->hwdata->surface, NULL,
slouken@1895
   952
                                           0);
slouken@1895
   953
        if (HIDDEN->mga_crtc2_stretch)
slouken@1895
   954
            HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame,
slouken@1895
   955
                                         surface->hwdata->surface,
slouken@1895
   956
                                         &HIDDEN->c2ssize, &HIDDEN->c2dsize);
slouken@1895
   957
        else
slouken@1895
   958
            HIDDEN->c2frame->Blit(HIDDEN->c2frame,
slouken@1895
   959
                                  surface->hwdata->surface, NULL,
slouken@1895
   960
                                  HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
slouken@1895
   961
slouken@1895
   962
        HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
slouken@1895
   963
        return rtn;
slouken@1895
   964
    } else
slouken@1895
   965
        return surface->hwdata->surface->Flip(surface->hwdata->surface, NULL,
slouken@1895
   966
                                              DSFLIP_WAITFORSYNC);
slouken@167
   967
}
slouken@167
   968
slouken@1895
   969
static int
slouken@1895
   970
DirectFB_LockHWSurface(_THIS, SDL_Surface * surface)
slouken@167
   971
{
slouken@1895
   972
    DFBResult ret;
slouken@1895
   973
    void *data;
slouken@1895
   974
    int pitch;
slouken@167
   975
slouken@1895
   976
    ret = surface->hwdata->surface->Lock(surface->hwdata->surface,
slouken@1895
   977
                                         DSLF_WRITE, &data, &pitch);
slouken@1895
   978
    if (ret) {
slouken@1895
   979
        SetDirectFBerror("surface->Lock", ret);
slouken@1895
   980
        return -1;
slouken@167
   981
    }
slouken@167
   982
slouken@1895
   983
    surface->pixels = data;
slouken@1895
   984
    surface->pitch = pitch;
slouken@1895
   985
slouken@1895
   986
    return 0;
slouken@1895
   987
}
slouken@167
   988
slouken@1895
   989
static void
slouken@1895
   990
DirectFB_UnlockHWSurface(_THIS, SDL_Surface * surface)
slouken@1895
   991
{
slouken@1895
   992
    surface->hwdata->surface->Unlock(surface->hwdata->surface);
slouken@1895
   993
    surface->pixels = NULL;
slouken@167
   994
}
slouken@167
   995
slouken@1895
   996
static void
slouken@1895
   997
DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect * rects)
slouken@167
   998
{
slouken@1895
   999
    if (HIDDEN->enable_mga_crtc2) {
slouken@1895
  1000
        if (HIDDEN->mga_crtc2_stretch)
slouken@1895
  1001
            HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame,
slouken@1895
  1002
                                         this->screen->hwdata->surface,
slouken@1895
  1003
                                         &HIDDEN->c2ssize, &HIDDEN->c2dsize);
slouken@1895
  1004
        else
slouken@1895
  1005
            HIDDEN->c2frame->Blit(HIDDEN->c2frame,
slouken@1895
  1006
                                  this->screen->hwdata->surface, NULL,
slouken@1895
  1007
                                  HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
icculus@728
  1008
slouken@1895
  1009
        HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
icculus@728
  1010
    }
slouken@167
  1011
}
slouken@167
  1012
slouken@1895
  1013
static void
slouken@1895
  1014
DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect * rects)
slouken@167
  1015
{
slouken@1895
  1016
    DFBRegion region;
slouken@1895
  1017
    int i;
slouken@1895
  1018
    int region_valid = 0;
slouken@1895
  1019
    IDirectFBSurface *surface = this->screen->hwdata->surface;
slouken@167
  1020
slouken@1895
  1021
    for (i = 0; i < numrects; ++i) {
slouken@1895
  1022
        int x2, y2;
slouken@167
  1023
slouken@1895
  1024
        if (!rects[i].w)        /* Clipped? */
slouken@1895
  1025
            continue;
slouken@167
  1026
slouken@1895
  1027
        x2 = rects[i].x + rects[i].w - 1;
slouken@1895
  1028
        y2 = rects[i].y + rects[i].h - 1;
slouken@167
  1029
slouken@1895
  1030
        if (region_valid) {
slouken@1895
  1031
            if (rects[i].x < region.x1)
slouken@1895
  1032
                region.x1 = rects[i].x;
slouken@167
  1033
slouken@1895
  1034
            if (rects[i].y < region.y1)
slouken@1895
  1035
                region.y1 = rects[i].y;
slouken@167
  1036
slouken@1895
  1037
            if (x2 > region.x2)
slouken@1895
  1038
                region.x2 = x2;
slouken@1895
  1039
slouken@1895
  1040
            if (y2 > region.y2)
slouken@1895
  1041
                region.y2 = y2;
slouken@1895
  1042
        } else {
slouken@286
  1043
            region.x1 = rects[i].x;
slouken@286
  1044
            region.y1 = rects[i].y;
slouken@286
  1045
            region.x2 = x2;
slouken@286
  1046
            region.y2 = y2;
slouken@167
  1047
slouken@286
  1048
            region_valid = 1;
slouken@286
  1049
        }
slouken@167
  1050
    }
slouken@167
  1051
slouken@1895
  1052
    if (region_valid) {
slouken@1895
  1053
        if (HIDDEN->enable_mga_crtc2) {
slouken@1895
  1054
            if (HIDDEN->mga_crtc2_stretch)
slouken@1895
  1055
                HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface,
slouken@1895
  1056
                                             &HIDDEN->c2ssize,
slouken@1895
  1057
                                             &HIDDEN->c2dsize);
slouken@1895
  1058
            else
slouken@1895
  1059
                HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface, NULL,
slouken@1895
  1060
                                      HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
slouken@1895
  1061
slouken@1895
  1062
            HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
slouken@1895
  1063
        } else
slouken@1895
  1064
            surface->Flip(surface, &region, DSFLIP_WAITFORSYNC);
icculus@728
  1065
    }
slouken@167
  1066
}
slouken@167
  1067
slouken@1895
  1068
int
slouken@1895
  1069
DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color * colors)
slouken@167
  1070
{
slouken@1895
  1071
    IDirectFBPalette *palette = this->screen->hwdata->palette;
slouken@477
  1072
slouken@1895
  1073
    if (!palette)
slouken@1895
  1074
        return 0;
slouken@477
  1075
slouken@1895
  1076
    if (firstcolor > 255)
slouken@1895
  1077
        return 0;
slouken@477
  1078
slouken@1895
  1079
    if (firstcolor + ncolors > 256)
slouken@1895
  1080
        ncolors = 256 - firstcolor;
slouken@477
  1081
slouken@1895
  1082
    if (ncolors > 0) {
slouken@1895
  1083
        int i;
slouken@1895
  1084
        DFBColor entries[ncolors];
slouken@477
  1085
slouken@1895
  1086
        for (i = 0; i < ncolors; i++) {
slouken@1895
  1087
            entries[i].a = 0xff;
slouken@1895
  1088
            entries[i].r = colors[i].r;
slouken@1895
  1089
            entries[i].g = colors[i].g;
slouken@1895
  1090
            entries[i].b = colors[i].b;
slouken@477
  1091
        }
slouken@477
  1092
slouken@1895
  1093
        palette->SetEntries(palette, entries, ncolors, firstcolor);
slouken@477
  1094
    }
slouken@477
  1095
slouken@1895
  1096
    return 1;
slouken@167
  1097
}
slouken@1895
  1098
slouken@1895
  1099
void
slouken@1895
  1100
DirectFB_VideoQuit(_THIS)
slouken@167
  1101
{
slouken@1895
  1102
    struct DirectFBEnumRect *rect = enumlist;
icculus@759
  1103
slouken@1895
  1104
    if (this->screen && this->screen->hwdata) {
slouken@1895
  1105
        IDirectFBSurface *surface = this->screen->hwdata->surface;
slouken@1895
  1106
        IDirectFBPalette *palette = this->screen->hwdata->palette;
slouken@477
  1107
slouken@1895
  1108
        if (palette)
slouken@1895
  1109
            palette->Release(palette);
slouken@477
  1110
slouken@1895
  1111
        if (surface)
slouken@1895
  1112
            surface->Release(surface);
icculus@759
  1113
slouken@1895
  1114
        this->screen->hwdata->surface = NULL;
slouken@1895
  1115
        this->screen->hwdata->palette = NULL;
icculus@759
  1116
    }
slouken@477
  1117
slouken@1895
  1118
    if (HIDDEN->c2frame) {
slouken@1895
  1119
        HIDDEN->c2frame->Release(HIDDEN->c2frame);
slouken@1895
  1120
        HIDDEN->c2frame = NULL;
slouken@464
  1121
    }
slouken@167
  1122
slouken@1895
  1123
    if (HIDDEN->eventbuffer) {
slouken@1895
  1124
        HIDDEN->eventbuffer->Release(HIDDEN->eventbuffer);
slouken@1895
  1125
        HIDDEN->eventbuffer = NULL;
icculus@728
  1126
    }
icculus@728
  1127
slouken@1895
  1128
    if (HIDDEN->c2layer) {
slouken@1895
  1129
        HIDDEN->c2layer->Release(HIDDEN->c2layer);
slouken@1895
  1130
        HIDDEN->c2layer = NULL;
slouken@464
  1131
    }
slouken@167
  1132
slouken@1895
  1133
    if (HIDDEN->layer) {
slouken@1895
  1134
        HIDDEN->layer->Release(HIDDEN->layer);
slouken@1895
  1135
        HIDDEN->layer = NULL;
slouken@464
  1136
    }
slouken@464
  1137
slouken@1895
  1138
    if (HIDDEN->dfb) {
slouken@1895
  1139
        HIDDEN->dfb->Release(HIDDEN->dfb);
slouken@1895
  1140
        HIDDEN->dfb = NULL;
slouken@167
  1141
    }
slouken@167
  1142
slouken@1895
  1143
    /* Free video mode list */
slouken@1895
  1144
    if (HIDDEN->modelist) {
slouken@1895
  1145
        free(HIDDEN->modelist);
slouken@1895
  1146
        HIDDEN->modelist = NULL;
slouken@464
  1147
    }
slouken@464
  1148
slouken@1895
  1149
    /* Free mode enumeration list */
slouken@1895
  1150
    while (rect) {
slouken@1895
  1151
        struct DirectFBEnumRect *next = rect->next;
slouken@1895
  1152
        free(rect);
slouken@1895
  1153
        rect = next;
slouken@1895
  1154
    }
slouken@1895
  1155
    enumlist = NULL;
slouken@1895
  1156
slouken@1895
  1157
    HIDDEN->initialized = 0;
slouken@167
  1158
}
slouken@167
  1159
slouken@767
  1160
slouken@1895
  1161
int
slouken@1895
  1162
DirectFB_ShowWMCursor(_THIS, WMcursor * cursor)
slouken@767
  1163
{
slouken@1895
  1164
    /* We can only hide or show the default cursor */
slouken@1895
  1165
    if (cursor == NULL) {
slouken@1895
  1166
        HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0x00);
slouken@1895
  1167
    } else {
slouken@1895
  1168
        HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0xFF);
slouken@767
  1169
    }
slouken@1895
  1170
    return 1;
slouken@767
  1171
}
slouken@767
  1172
slouken@1895
  1173
void
slouken@1895
  1174
DirectFB_FinalQuit(void)
slouken@167
  1175
{
slouken@167
  1176
}
slouken@1895
  1177
slouken@1895
  1178
/* vi: set ts=4 sw=4 expandtab: */