src/video/directfb/SDL_DirectFB_video.c
author Sam Lantinga
Sun, 04 Jan 2004 15:57:16 +0000
changeset 767 d9e79e31a7b7
parent 759 26ac9609211f
child 769 b8d311d90021
permissions -rw-r--r--
Date: Mon, 17 Nov 2003 21:59:24 -0800
From: Pete Shinners
Subject: [SDL] directfb cursor patch

here is a quick and dirty patch that allows directfb to change the
visibility of the cursor. this display backend still has no way to change
the actual cursor shape, but being able to set the cursor visibility is a
simple change that should offer some benefits.

the code was largely based on the cursor code for other sdl backends. and
this documentation.
http://directfb.org/documentation/DirectFB_Reference/IDirectFBDisplayLayer_SetCursorOpacity.html
     1 /*
     2 	SDL - Simple DirectMedia Layer
     3 	Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  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 (unsigned int  width,
   193                                                unsigned int  height,
   194                                                unsigned 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  = width;
   210   enumrect->r.h  = 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_RGB15;
   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_RGB15;
   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_RGB15:
   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       ret = dfb->GetDisplayLayer (dfb, 2, &HIDDEN->c2layer);
   472       if (ret)
   473         {
   474           SetDirectFBerror ("dfb->GetDisplayLayer(CRTC2)", ret);
   475           goto error;
   476         }
   477 
   478       ret = HIDDEN->layer->SetCooperativeLevel(HIDDEN->layer, DLSCL_EXCLUSIVE);
   479       if (ret)
   480         {
   481           SetDirectFBerror ("layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
   482           goto error;
   483         }
   484  
   485       ret = HIDDEN->c2layer->SetCooperativeLevel(HIDDEN->c2layer, DLSCL_EXCLUSIVE);
   486       if (ret)
   487         {
   488           SetDirectFBerror ("c2layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
   489           goto error;
   490         }
   491 
   492       HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0x0);
   493 
   494       /* Init the surface here as it got a fixed size */
   495       DFBDisplayLayerConfig      dlc;
   496       DFBDisplayLayerConfigFlags failed;
   497     
   498       dlc.flags      = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS;
   499       dlc.buffermode = DLBM_BACKVIDEO;
   500       dlc.options    = DLOP_FLICKER_FILTERING;
   501       dlc.pixelformat = DSPF_RGB32;
   502       
   503       ret = HIDDEN->c2layer->TestConfiguration( HIDDEN->c2layer, &dlc, &failed );
   504       if (ret)
   505         {
   506           SetDirectFBerror ("c2layer->TestConfiguration", ret);
   507           goto error;
   508         }
   509     
   510       ret = HIDDEN->c2layer->SetConfiguration( HIDDEN->c2layer, &dlc );
   511       if (ret)
   512         {
   513           SetDirectFBerror ("c2layer->SetConfiguration", ret);
   514           goto error;
   515         }
   516     
   517       ret = HIDDEN->c2layer->GetSurface( HIDDEN->c2layer, &HIDDEN->c2frame );
   518       if (ret)
   519         {
   520           SetDirectFBerror ("c2layer->GetSurface", ret);
   521           goto error;
   522         }
   523 
   524       HIDDEN->c2framesize.x = 0;
   525       HIDDEN->c2framesize.y = 0;
   526       HIDDEN->c2frame->GetSize( HIDDEN->c2frame, &HIDDEN->c2framesize.w, &HIDDEN->c2framesize.h);
   527 
   528       HIDDEN->c2frame->SetBlittingFlags( HIDDEN->c2frame, DSBLIT_NOFX );
   529       HIDDEN->c2frame->SetColor( HIDDEN->c2frame, 0, 0, 0, 0xff );
   530     
   531       /* Clear CRTC2 */
   532       HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
   533       HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 );
   534       HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
   535       HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 );
   536       HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
   537 
   538       HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0xFF );
   539     
   540       /* Check if overscan is possibly set */
   541       if (getenv("SDL_DIRECTFB_MGA_OVERSCAN") != NULL)
   542         {
   543 	    float overscan = 0;
   544 	    if (sscanf(getenv("SDL_DIRECTFB_MGA_OVERSCAN"), "%f", &overscan) == 1)
   545                if (overscan > 0 && overscan < 2)
   546 		  HIDDEN->mga_crtc2_stretch_overscan = overscan;
   547 	}
   548 
   549       #ifdef DIRECTFB_CRTC2_DEBUG
   550       printf("CRTC2 overscan: %f\n", HIDDEN->mga_crtc2_stretch_overscan);
   551       #endif
   552     }
   553 
   554   return 0;
   555 
   556  error:
   557   if (events)
   558     events->Release (events);
   559   
   560   if (HIDDEN->c2frame)
   561     HIDDEN->c2frame->Release (HIDDEN->c2frame);
   562 
   563   if (HIDDEN->c2layer)
   564     HIDDEN->c2layer->Release (HIDDEN->c2layer);
   565 
   566   if (layer)
   567     layer->Release (layer);
   568 
   569   if (dfb)
   570     dfb->Release (dfb);
   571 
   572   return -1;
   573 }
   574 
   575 static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
   576 {
   577   if (flags & SDL_FULLSCREEN)
   578     return HIDDEN->modelist;
   579   else
   580     if (SDLToDFBPixelFormat (format) != DSPF_UNKNOWN)
   581       return (SDL_Rect**) -1;
   582 
   583   return NULL;
   584 }
   585 
   586 static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags)
   587 {
   588   DFBResult              ret;
   589   DFBSurfaceDescription  dsc;
   590   DFBSurfacePixelFormat  pixelformat;
   591   IDirectFBSurface      *surface;
   592 
   593   fprintf (stderr, "SDL DirectFB_SetVideoMode: %dx%d@%d, flags: 0x%08x\n",
   594            width, height, bpp, flags);
   595 
   596   flags |= SDL_FULLSCREEN;
   597 
   598   /* Release previous primary surface */
   599   if (current->hwdata && current->hwdata->surface)
   600     {
   601       current->hwdata->surface->Release (current->hwdata->surface);
   602       current->hwdata->surface = NULL;
   603 
   604       /* And its palette if present */
   605       if (current->hwdata->palette)
   606         {
   607           current->hwdata->palette->Release (current->hwdata->palette);
   608           current->hwdata->palette = NULL;
   609         }
   610     }
   611   else if (!current->hwdata)
   612     {
   613       /* Allocate the hardware acceleration data */
   614       current->hwdata = (struct private_hwdata *) calloc (1, sizeof(*current->hwdata));
   615       if (!current->hwdata)
   616         {
   617           SDL_OutOfMemory();
   618           return NULL;
   619 	}
   620     }
   621 
   622   /* Set cooperative level depending on flag SDL_FULLSCREEN */
   623   if (flags & SDL_FULLSCREEN)
   624     {
   625       ret = HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_FULLSCREEN);
   626       if (ret && !HIDDEN->enable_mga_crtc2)
   627         {
   628           DirectFBError ("dfb->SetCooperativeLevel", ret);
   629           flags &= ~SDL_FULLSCREEN;
   630         }
   631     }
   632   else
   633     HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL);
   634 
   635   /* Set video mode */
   636   ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp);
   637   if (ret)
   638     {
   639       if (flags & SDL_FULLSCREEN)
   640         {
   641           flags &= ~SDL_FULLSCREEN;
   642           HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL);
   643           ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp);
   644         }
   645 
   646       if (ret)
   647         {
   648           SetDirectFBerror ("dfb->SetVideoMode", ret);
   649           return NULL;
   650         }
   651     }
   652 
   653   /* Create primary surface */
   654   dsc.flags       = DSDESC_CAPS | DSDESC_PIXELFORMAT;
   655   dsc.caps        = DSCAPS_PRIMARY | ((flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0);
   656   dsc.pixelformat = GetFormatForBpp (bpp, HIDDEN->layer);
   657 
   658   ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface);
   659   if (ret && (flags & SDL_DOUBLEBUF))
   660     {
   661       /* Try without double buffering */
   662       dsc.caps &= ~DSCAPS_FLIPPING;
   663       ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface);
   664     }
   665   if (ret)
   666     {
   667       SetDirectFBerror ("dfb->CreateSurface", ret);
   668       return NULL;
   669     }
   670 
   671   current->w     = width;
   672   current->h     = height;
   673   current->flags = SDL_HWSURFACE | SDL_PREALLOC;
   674 
   675   if (flags & SDL_FULLSCREEN)
   676     {
   677       current->flags |= SDL_FULLSCREEN;
   678       this->UpdateRects = DirectFB_DirectUpdate;
   679     }
   680   else
   681     this->UpdateRects = DirectFB_WindowedUpdate;
   682 
   683   if (dsc.caps & DSCAPS_FLIPPING)
   684     current->flags |= SDL_DOUBLEBUF;
   685 
   686   surface->GetPixelFormat (surface, &pixelformat);
   687 
   688   DFBToSDLPixelFormat (pixelformat, current->format);
   689 
   690   /* Get the surface palette (if supported) */
   691   if (DFB_PIXELFORMAT_IS_INDEXED( pixelformat ))
   692     {
   693       surface->GetPalette (surface, &current->hwdata->palette);
   694 
   695       current->flags |= SDL_HWPALETTE;
   696     }
   697 
   698   current->hwdata->surface = surface;
   699 
   700   /* MGA CRTC2 stuff */
   701   if (HIDDEN->enable_mga_crtc2)
   702     {
   703       /* no stretching if c2ssize == c2framesize */
   704       HIDDEN->c2ssize.x = 0, HIDDEN->c2ssize.y = 0;
   705       HIDDEN->c2ssize.w = width;
   706       HIDDEN->c2ssize.h = height;
   707 
   708       HIDDEN->c2dsize.x = 0, HIDDEN->c2dsize.y = 0;
   709       HIDDEN->c2dsize.w = width;
   710       HIDDEN->c2dsize.h = height;
   711 
   712       HIDDEN->mga_crtc2_stretch = 0;
   713 
   714       if (getenv("SDL_DIRECTFB_MGA_STRETCH") != NULL)
   715         {
   716 	    /* Normally assume a picture aspect ratio of 4:3 */
   717 	    int zoom_aspect_x = 4, zoom_aspect_y = 3, i, j;
   718 
   719 	    for (i = 1; i < 20; i++)
   720 	      {
   721 		for (j = 1; j < 10; j++)
   722 		  {
   723 		    if ((float)width/(float)i*(float)j == height) 
   724 		      {
   725 			zoom_aspect_x = i;
   726 			zoom_aspect_y = j;
   727 			
   728 			/* break the loop */
   729 			i = 21;
   730 			break;
   731 		      }
   732 		  }
   733 	      }
   734 	
   735             #ifdef DIRECTFB_CRTC2_DEBUG
   736             printf("Source resolution: X: %d, Y: %d, Aspect ratio: %d:%d\n", width, height, zoom_aspect_x, zoom_aspect_y);
   737             printf("CRTC2 resolution: X: %d, Y: %d\n", HIDDEN->c2framesize.w, HIDDEN->c2framesize.h);
   738             #endif
   739 	
   740           /* don't stretch only slightly smaller/larger images */
   741           if ((float)width < (float)HIDDEN->c2framesize.w*0.95 || (float)height < (float)HIDDEN->c2framesize.h*0.95)
   742             {
   743               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)
   744                 {
   745                    HIDDEN->c2dsize.w+=zoom_aspect_x;
   746                    HIDDEN->c2dsize.h+=zoom_aspect_y;
   747                 }
   748 
   749               /* one step down */
   750                 HIDDEN->c2dsize.w-=zoom_aspect_x;
   751                 HIDDEN->c2dsize.h-=zoom_aspect_y;
   752 
   753               #ifdef DIRECTFB_CRTC2_DEBUG
   754               printf("Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
   755               #endif
   756 
   757               HIDDEN->mga_crtc2_stretch = 1;
   758             } 
   759           else if ((float)width > (float)HIDDEN->c2framesize.w*0.95 || (float)height > (float)HIDDEN->c2framesize.h*0.95)
   760             {
   761                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)
   762                 {
   763               HIDDEN->c2dsize.w-=zoom_aspect_x;
   764               HIDDEN->c2dsize.h-=zoom_aspect_y;
   765                 }
   766               
   767               #ifdef DIRECTFB_CRTC2_DEBUG
   768               printf("Down-Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
   769               #endif
   770 
   771               HIDDEN->mga_crtc2_stretch = 1;
   772              } else {
   773           #ifdef DIRECTFB_CRTC2_DEBUG
   774           printf("Not stretching image\n");
   775           #endif
   776         }
   777 
   778       /* Panning */
   779       if (HIDDEN->c2framesize.w > HIDDEN->c2dsize.w)
   780         HIDDEN->c2dsize.x = (HIDDEN->c2framesize.w - HIDDEN->c2dsize.w)  / 2;
   781       else
   782         HIDDEN->c2dsize.x = (HIDDEN->c2dsize.w - HIDDEN->c2framesize.w)  / 2;
   783 
   784       if (HIDDEN->c2framesize.h > HIDDEN->c2dsize.h)
   785         HIDDEN->c2dsize.y = (HIDDEN->c2framesize.h - HIDDEN->c2dsize.h)  / 2;
   786       else
   787         HIDDEN->c2dsize.y = (HIDDEN->c2dsize.h - HIDDEN->c2framesize.h)  / 2;
   788 
   789       #ifdef DIRECTFB_CRTC2_DEBUG
   790     printf("CRTC2 position X: %d, Y: %d\n", HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
   791       #endif
   792    }
   793   }
   794 
   795   return current;
   796 }
   797 
   798 static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface)
   799 {
   800   DFBResult             ret;
   801   DFBSurfaceDescription dsc;
   802 
   803   /*  fprintf(stderr, "SDL: DirectFB_AllocHWSurface (%dx%d@%d, flags: 0x%08x)\n",
   804       surface->w, surface->h, surface->format->BitsPerPixel, surface->flags);*/
   805 
   806   if (surface->w < 8 || surface->h < 8)
   807     return -1;
   808 
   809   /* fill surface description */
   810   dsc.flags  = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   811   dsc.width  = surface->w;
   812   dsc.height = surface->h;
   813   dsc.caps   = (surface->flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0;
   814 
   815   /* find the right pixelformat */
   816   dsc.pixelformat = SDLToDFBPixelFormat (surface->format);
   817   if (dsc.pixelformat == DSPF_UNKNOWN)
   818     return -1;
   819 
   820   /* Allocate the hardware acceleration data */
   821   surface->hwdata = (struct private_hwdata *) calloc (1, sizeof(*surface->hwdata));
   822   if (surface->hwdata == NULL)
   823     {
   824       SDL_OutOfMemory();
   825       return -1;
   826     }
   827 
   828   /* Create the surface */
   829   ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface->hwdata->surface);
   830   if (ret)
   831     {
   832       SetDirectFBerror ("dfb->CreateSurface", ret);
   833       free (surface->hwdata);
   834       surface->hwdata = NULL;
   835       return -1;
   836     }
   837 
   838   surface->flags |= SDL_HWSURFACE | SDL_PREALLOC;
   839 
   840   return 0;
   841 }
   842 
   843 static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface)
   844 {
   845   if (surface->hwdata && HIDDEN->initialized)
   846     {
   847       surface->hwdata->surface->Release (surface->hwdata->surface);
   848       free (surface->hwdata);
   849       surface->hwdata = NULL;
   850     }
   851 }
   852 
   853 static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
   854 {
   855   /*  fprintf(stderr, "SDL: DirectFB_CheckHWBlit (src->hwdata: %p, dst->hwdata: %p)\n",
   856       src->hwdata, dst->hwdata);*/
   857 
   858   if (!src->hwdata || !dst->hwdata)
   859     return 0;
   860 
   861   src->flags |= SDL_HWACCEL;
   862   src->map->hw_blit = DirectFB_HWAccelBlit;
   863 
   864   return 1;
   865 }
   866 
   867 static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
   868                                 SDL_Surface *dst, SDL_Rect *dstrect)
   869 {
   870   DFBSurfaceBlittingFlags flags = DSBLIT_NOFX;
   871 
   872   DFBRectangle sr = { srcrect->x, srcrect->y, srcrect->w, srcrect->h };
   873   DFBRectangle dr = { dstrect->x, dstrect->y, dstrect->w, dstrect->h };
   874 
   875   IDirectFBSurface *surface = dst->hwdata->surface;
   876 
   877   if (src->flags & SDL_SRCCOLORKEY)
   878     {
   879       flags |= DSBLIT_SRC_COLORKEY;
   880       DirectFB_SetHWColorKey (NULL, src, src->format->colorkey);
   881     }
   882 
   883   if (src->flags & SDL_SRCALPHA)
   884     {
   885       flags |= DSBLIT_BLEND_COLORALPHA;
   886       surface->SetColor (surface, 0xff, 0xff, 0xff, src->format->alpha);
   887     }
   888 
   889   surface->SetBlittingFlags (surface, flags);
   890 
   891   if (sr.w == dr.w && sr.h == dr.h)
   892     surface->Blit (surface, src->hwdata->surface, &sr, dr.x, dr.y);
   893   else
   894     surface->StretchBlit (surface, src->hwdata->surface, &sr, &dr);
   895 
   896   return 0;
   897 }
   898 
   899 static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
   900 {
   901   SDL_PixelFormat  *fmt     = dst->format;
   902   IDirectFBSurface *surface = dst->hwdata->surface;
   903 
   904   /* ugly */
   905   surface->SetColor (surface,
   906                      (color & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
   907                      (color & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
   908                      (color & fmt->Bmask) << (fmt->Bloss - fmt->Bshift), 0xFF);
   909   surface->FillRectangle (surface, dstrect->x, dstrect->y, dstrect->w, dstrect->h);
   910 
   911   return 0;
   912 }
   913 
   914 static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *src, Uint32 key)
   915 {
   916   SDL_PixelFormat  *fmt     = src->format;
   917   IDirectFBSurface *surface = src->hwdata->surface;
   918 
   919   if (fmt->BitsPerPixel == 8)
   920     surface->SetSrcColorKeyIndex (surface, key);
   921   else
   922     /* ugly */
   923     surface->SetSrcColorKey (surface,
   924                              (key & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
   925                              (key & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
   926                              (key & fmt->Bmask) << (fmt->Bloss - fmt->Bshift));
   927 
   928   return 0;
   929 }
   930 
   931 static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
   932 {
   933   return 0;
   934 }
   935 
   936 static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface)
   937 {
   938   if (HIDDEN->enable_mga_crtc2)
   939     {
   940        int rtn = surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, 0);
   941        if (HIDDEN->mga_crtc2_stretch)
   942          HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize);
   943        else
   944          HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
   945      
   946        HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
   947        return rtn;
   948     } 
   949   else 
   950      return surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, DSFLIP_WAITFORSYNC);
   951 }
   952 
   953 static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface)
   954 {
   955   DFBResult  ret;
   956   void      *data;
   957   int        pitch;
   958 
   959   ret = surface->hwdata->surface->Lock (surface->hwdata->surface,
   960                                         DSLF_WRITE, &data, &pitch);
   961   if (ret)
   962     {
   963       SetDirectFBerror ("surface->Lock", ret);
   964       return -1;
   965     }
   966 
   967   surface->pixels = data;
   968   surface->pitch  = pitch;
   969 
   970   return 0;
   971 }
   972 
   973 static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface)
   974 {
   975   surface->hwdata->surface->Unlock (surface->hwdata->surface);
   976   surface->pixels = NULL;
   977 }
   978 
   979 static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
   980 {
   981   if (HIDDEN->enable_mga_crtc2)
   982     {
   983        if (HIDDEN->mga_crtc2_stretch)
   984          HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, this->screen->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); 
   985        else
   986          HIDDEN->c2frame->Blit(HIDDEN->c2frame, this->screen->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 
   987 
   988        HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
   989     }
   990 }
   991 
   992 static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects)
   993 {
   994   DFBRegion         region;
   995   int               i;
   996   int               region_valid = 0;
   997   IDirectFBSurface *surface = this->screen->hwdata->surface;
   998 
   999   for (i=0; i<numrects; ++i)
  1000     {
  1001       int x2, y2;
  1002 
  1003       if ( ! rects[i].w ) /* Clipped? */
  1004         continue;
  1005 
  1006       x2 = rects[i].x + rects[i].w - 1;
  1007       y2 = rects[i].y + rects[i].h - 1;
  1008 
  1009       if (region_valid)
  1010         {
  1011           if (rects[i].x < region.x1)
  1012             region.x1 = rects[i].x;
  1013 
  1014           if (rects[i].y < region.y1)
  1015             region.y1 = rects[i].y;
  1016 
  1017           if (x2 > region.x2)
  1018             region.x2 = x2;
  1019 
  1020           if (y2 > region.y2)
  1021             region.y2 = y2;
  1022         }
  1023       else
  1024         {
  1025             region.x1 = rects[i].x;
  1026             region.y1 = rects[i].y;
  1027             region.x2 = x2;
  1028             region.y2 = y2;
  1029 
  1030             region_valid = 1;
  1031         }
  1032     }
  1033 
  1034   if (region_valid)
  1035     {
  1036       if (HIDDEN->enable_mga_crtc2)
  1037         {
  1038           if (HIDDEN->mga_crtc2_stretch)
  1039             HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize);
  1040           else
  1041             HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 
  1042       
  1043           HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
  1044         }
  1045       else 
  1046         surface->Flip (surface, &region, DSFLIP_WAITFORSYNC);
  1047     }
  1048 }
  1049 
  1050 int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
  1051 {
  1052   IDirectFBPalette *palette = this->screen->hwdata->palette;
  1053 
  1054   if (!palette)
  1055     return 0;
  1056 
  1057   if (firstcolor > 255)
  1058     return 0;
  1059 
  1060   if (firstcolor + ncolors > 256)
  1061     ncolors = 256 - firstcolor;
  1062 
  1063   if (ncolors > 0)
  1064     {
  1065       int      i;
  1066       DFBColor entries[ncolors];
  1067 
  1068       for (i=0; i<ncolors; i++)
  1069         {
  1070           entries[i].a = 0xff;
  1071           entries[i].r = colors[i].r;
  1072           entries[i].g = colors[i].g;
  1073           entries[i].b = colors[i].b;
  1074         }
  1075 
  1076       palette->SetEntries (palette, entries, ncolors, firstcolor);
  1077     }
  1078 
  1079   return 1;
  1080 }
  1081 	
  1082 void DirectFB_VideoQuit(_THIS)
  1083 {
  1084   struct DirectFBEnumRect *rect    = enumlist;
  1085 
  1086   if (this->screen->hwdata)
  1087     {
  1088       IDirectFBSurface        *surface = this->screen->hwdata->surface;
  1089       IDirectFBPalette        *palette = this->screen->hwdata->palette;
  1090 
  1091       if (palette)
  1092         palette->Release (palette);
  1093 
  1094       if (surface)
  1095         surface->Release (surface);
  1096 
  1097       this->screen->hwdata->surface = NULL;
  1098       this->screen->hwdata->palette = NULL;
  1099     }
  1100 
  1101   if (HIDDEN->c2frame)
  1102     {
  1103       HIDDEN->c2frame->Release (HIDDEN->c2frame);
  1104       HIDDEN->c2frame = NULL;
  1105     }
  1106 
  1107   this->screen->hwdata->surface = NULL;
  1108   this->screen->hwdata->palette = NULL;
  1109 
  1110   if (HIDDEN->eventbuffer)
  1111     {
  1112       HIDDEN->eventbuffer->Release (HIDDEN->eventbuffer);
  1113       HIDDEN->eventbuffer = NULL;
  1114     }
  1115 
  1116   if (HIDDEN->c2layer)
  1117     {
  1118       HIDDEN->c2layer->Release (HIDDEN->c2layer);
  1119       HIDDEN->c2layer = NULL;
  1120     }
  1121 
  1122   if (HIDDEN->layer)
  1123     {
  1124       HIDDEN->layer->Release (HIDDEN->layer);
  1125       HIDDEN->layer = NULL;
  1126     }
  1127 
  1128   if (HIDDEN->dfb)
  1129     {
  1130       HIDDEN->dfb->Release (HIDDEN->dfb);
  1131       HIDDEN->dfb = NULL;
  1132     }
  1133 
  1134   /* Free video mode list */
  1135   if (HIDDEN->modelist)
  1136     {
  1137       free (HIDDEN->modelist);
  1138       HIDDEN->modelist = NULL;
  1139     }
  1140 
  1141   /* Free mode enumeration list */
  1142   while (rect)
  1143     {
  1144       struct DirectFBEnumRect *next = rect->next;
  1145       free (rect);
  1146       rect = next;
  1147     }
  1148   enumlist = NULL;
  1149 
  1150   HIDDEN->initialized = 0;
  1151 }
  1152 
  1153 
  1154 int DirectFB_ShowWMCursor(_THIS, WMcursor *cursor)
  1155 {
  1156   /* We can only hide or show the default cursor */
  1157   if ( cursor == NULL )
  1158     {
  1159       SetCursorOpacity(HIDDEN->layer, 0);
  1160     }
  1161     else
  1162     {
  1163       SetCursorOpacity(HIDDEN->layer, 256);
  1164     }
  1165   return 1;
  1166 }
  1167 
  1168 void DirectFB_FinalQuit(void) 
  1169 {
  1170 }