src/video/directfb/SDL_DirectFB_video.c
author Ryan C. Gordon
Mon, 17 Jan 2005 19:38:28 +0000
changeset 1029 f87f87efd45a
parent 1018 012af0b7e8e6
child 1165 4fa705cdecb9
permissions -rw-r--r--
Date: Mon, 17 Jan 2005 20:54:50 +0200
From: Ville [snip]
Subject: [PATCH] SDL/DirectFB: remove Matrox CRTC2 flicker filter

Hi,

This patch removes the flicker filter option from the DirectFB backend's
Matrox CRTC2 code in SDL. I will be removing the option from DirectFB
(because it doesn't actually work) and that would cause the SDL code to
fail without this fix.

I was going to send this to some SDL list directly but libsdl.org is down
so I'm not sure what if any lists there are. Thomas Jarosch (the guy who
wrote the code) said you would accept SDL patches. Let me know if I should
send this somewhere else.

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