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