src/video/directfb/SDL_DirectFB_video.c
author Sam Lantinga
Sat, 24 Aug 2002 15:29:06 +0000
changeset 464 1c4be4a16410
parent 297 f6ffac90895c
child 477 22581630aab7
permissions -rw-r--r--
Date: Fri, 23 Aug 2002 11:48:56 +0200
From: Denis Oliver Kropp
Subject: Another patch

this is another patch fixing key code mapping
along with some other fixes and better mode handling.
     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 
    23 #ifdef SAVE_RCSID
    24 static char rcsid =
    25  "@(#) $Id$";
    26 #endif
    27 
    28 /* DirectFB video driver implementation.
    29 */
    30 
    31 #include <stdlib.h>
    32 #include <string.h>
    33 #include <stdio.h>
    34 #include <fcntl.h>
    35 #include <unistd.h>
    36 #include <sys/mman.h>
    37 
    38 #include <directfb.h>
    39 
    40 #include "SDL.h"
    41 #include "SDL_error.h"
    42 #include "SDL_video.h"
    43 #include "SDL_mouse.h"
    44 #include "SDL_sysvideo.h"
    45 #include "SDL_pixels_c.h"
    46 #include "SDL_events_c.h"
    47 #include "SDL_DirectFB_video.h"
    48 #include "SDL_DirectFB_events.h"
    49 
    50 
    51 /* Initialization/Query functions */
    52 static int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat);
    53 static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
    54 static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
    55 static int DirectFB_SetColors(_THIS, int firstcolor, int ncolors,
    56 			 SDL_Color *colors);
    57 static void DirectFB_VideoQuit(_THIS);
    58 
    59 /* Hardware surface functions */
    60 static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface);
    61 static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
    62 static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface);
    63 static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface);
    64 static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface);
    65 static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst);
    66 static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
    67                                 SDL_Surface *dst, SDL_Rect *dstrect);
    68 static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
    69 static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha);
    70 static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface);
    71 
    72 /* Various screen update functions available */
    73 static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects);
    74 static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects);
    75 
    76 /* This is the rect EnumModes2 uses */
    77 struct DirectFBEnumRect {
    78 	SDL_Rect r;
    79 	struct DirectFBEnumRect* next;
    80 };
    81 
    82 static struct DirectFBEnumRect *enumlist = NULL;
    83 
    84 
    85 /* DirectFB driver bootstrap functions */
    86 
    87 static int DirectFB_Available(void)
    88 {
    89   return 1;
    90 }
    91 
    92 static void DirectFB_DeleteDevice(SDL_VideoDevice *device)
    93 {
    94   free(device->hidden);
    95   free(device);
    96 }
    97 
    98 static SDL_VideoDevice *DirectFB_CreateDevice(int devindex)
    99 {
   100   SDL_VideoDevice *device;
   101 
   102   /* Initialize all variables that we clean on shutdown */
   103   device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
   104   if (device)
   105     {
   106       memset (device, 0, (sizeof *device));
   107       device->hidden = (struct SDL_PrivateVideoData *) malloc (sizeof (*device->hidden));
   108     }
   109   if (device == NULL  ||  device->hidden == NULL)
   110     {
   111       SDL_OutOfMemory();
   112       if (device)
   113         {
   114           free (device);
   115         }
   116       return(0);
   117     }
   118   memset (device->hidden, 0, sizeof (*device->hidden));
   119 
   120   /* Set the function pointers */
   121   device->VideoInit = DirectFB_VideoInit;
   122   device->ListModes = DirectFB_ListModes;
   123   device->SetVideoMode = DirectFB_SetVideoMode;
   124   device->SetColors = DirectFB_SetColors;
   125   device->UpdateRects = NULL;
   126   device->VideoQuit = DirectFB_VideoQuit;
   127   device->AllocHWSurface = DirectFB_AllocHWSurface;
   128   device->CheckHWBlit = DirectFB_CheckHWBlit;
   129   device->FillHWRect = DirectFB_FillHWRect;
   130   device->SetHWColorKey = DirectFB_SetHWColorKey;
   131   device->SetHWAlpha = DirectFB_SetHWAlpha;
   132   device->LockHWSurface = DirectFB_LockHWSurface;
   133   device->UnlockHWSurface = DirectFB_UnlockHWSurface;
   134   device->FlipHWSurface = DirectFB_FlipHWSurface;
   135   device->FreeHWSurface = DirectFB_FreeHWSurface;
   136   device->SetCaption = NULL;
   137   device->SetIcon = NULL;
   138   device->IconifyWindow = NULL;
   139   device->GrabInput = NULL;
   140   device->GetWMInfo = NULL;
   141   device->InitOSKeymap = DirectFB_InitOSKeymap;
   142   device->PumpEvents = DirectFB_PumpEvents;
   143 
   144   device->free = DirectFB_DeleteDevice;
   145 
   146   return device;
   147 }
   148 
   149 VideoBootStrap DirectFB_bootstrap = {
   150   "directfb", "DirectFB",
   151   DirectFB_Available, DirectFB_CreateDevice
   152 };
   153 
   154 static DFBSurfacePixelFormat GetFormatForBpp (int bpp, IDirectFBDisplayLayer *layer)
   155 {
   156   DFBDisplayLayerConfig dlc;
   157   int                   bytes = (bpp + 7) / 8;
   158 
   159   layer->GetConfiguration (layer, &dlc);
   160 
   161   if (bytes == DFB_BYTES_PER_PIXEL(dlc.pixelformat))
   162     return dlc.pixelformat;
   163 
   164   switch (bytes)
   165     {
   166     case 1:
   167       return DSPF_RGB332;
   168     case 2:
   169       return DSPF_RGB16;
   170     case 3:
   171       return DSPF_RGB24;
   172     case 4:
   173       return DSPF_RGB32;
   174     }
   175 
   176   return DSPF_UNKNOWN;
   177 }
   178 
   179 static DFBEnumerationResult EnumModesCallback (unsigned int  width,
   180                                                unsigned int  height,
   181                                                unsigned int  bpp,
   182                                                void         *data)
   183 {
   184   SDL_VideoDevice *this = (SDL_VideoDevice *)data;
   185   struct DirectFBEnumRect *enumrect;
   186 
   187   HIDDEN->nummodes++;
   188 
   189   enumrect = calloc(1, sizeof(struct DirectFBEnumRect));
   190   if (!enumrect)
   191     {
   192       SDL_OutOfMemory();
   193       return DFENUM_CANCEL;
   194     }
   195 
   196   enumrect->r.w  = width;
   197   enumrect->r.h  = height;
   198   enumrect->next = enumlist;
   199 
   200   enumlist = enumrect;
   201 
   202   return DFENUM_OK;
   203 }
   204 
   205 struct private_hwdata {
   206   IDirectFBSurface *surface;
   207 };
   208 
   209 void SetDirectFBerror (const char *function, DFBResult code)
   210 {
   211   const char *error = DirectFBErrorString (code);
   212 
   213   if (error)
   214     SDL_SetError("%s: %s", function, error);
   215   else
   216     SDL_SetError("Unknown error code from %s", function);
   217 }
   218 
   219 static DFBSurfacePixelFormat SDLToDFBPixelFormat (SDL_PixelFormat *format)
   220 {
   221   if (format->Rmask && format->Gmask && format->Bmask)
   222     {
   223       switch (format->BitsPerPixel)
   224         {
   225         case 16:
   226           if (format->Rmask == 0xF800 &&
   227               format->Gmask == 0x07E0 &&
   228               format->Bmask == 0x001F)
   229             return DSPF_RGB16;
   230           /* fall through */
   231           
   232         case 15:
   233           if (format->Rmask == 0x7C00 &&
   234               format->Gmask == 0x03E0 &&
   235               format->Bmask == 0x001F)
   236             return DSPF_RGB15;
   237           break;
   238           
   239         case 8:
   240           if (format->Rmask == 0xE0 &&
   241               format->Gmask == 0x1C &&
   242               format->Bmask == 0x03)
   243             return DSPF_RGB332;
   244           break;
   245           
   246         case 24:
   247           if (format->Rmask == 0xFF0000 &&
   248               format->Gmask == 0x00FF00 &&
   249               format->Bmask == 0x0000FF)
   250             return DSPF_RGB24;
   251           break;
   252 
   253         case 32:
   254           if (format->Rmask == 0xFF0000 &&
   255               format->Gmask == 0x00FF00 &&
   256               format->Bmask == 0x0000FF)
   257             {
   258               if (format->Amask == 0xFF000000)
   259                 return DSPF_ARGB;
   260               else
   261                 return DSPF_RGB32;
   262             }
   263           break;
   264         }
   265     }
   266   else
   267     {
   268       switch (format->BitsPerPixel)
   269 	{
   270         case 8:
   271           return DSPF_RGB332;
   272 	case 15:
   273 	  return DSPF_RGB15;
   274 	case 16:
   275 	  return DSPF_RGB16;
   276 	case 24:
   277 	  return DSPF_RGB24;
   278 	case 32:
   279 	  return DSPF_RGB32;
   280 	}
   281     }
   282 
   283   return DSPF_UNKNOWN;
   284 }
   285 
   286 static const __u8 lookup3to8[] = { 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff };
   287 static const __u8 lookup2to8[] = { 0x00, 0x55, 0xaa, 0xff };
   288 
   289 static SDL_Palette *GenerateRGB332Palette()
   290 {
   291   int          i;
   292   SDL_Palette *palette;
   293   SDL_Color   *colors;
   294 
   295   palette = calloc (1, sizeof(SDL_Palette));
   296   if (!palette)
   297     {
   298       SDL_OutOfMemory();
   299       return NULL;
   300     }
   301 
   302   colors = calloc (256, sizeof(SDL_Color));
   303   if (!colors)
   304     {
   305       SDL_OutOfMemory();
   306       return NULL;
   307     }
   308 
   309   for (i=0; i<256; i++)
   310     {
   311       colors[i].r = lookup3to8[ i >> 5 ];
   312       colors[i].g = lookup3to8[ (i >> 2) & 7 ];
   313       colors[i].g = lookup2to8[ i & 3 ];
   314     }
   315 
   316   palette->ncolors = 256;
   317   palette->colors  = colors;
   318 
   319   return palette;
   320 }
   321 
   322 static int DFBToSDLPixelFormat (DFBSurfacePixelFormat pixelformat, SDL_PixelFormat *format)
   323 {
   324   format->Amask = format->Rmask = format->Gmask = format->Bmask = 0;
   325   format->BitsPerPixel = format->BytesPerPixel = 0;
   326 
   327   switch (pixelformat)
   328     {
   329     case DSPF_A8:
   330       format->Amask = 0x000000FF;
   331       break;
   332 
   333     case DSPF_RGB15:
   334       format->Rmask = 0x00007C00;
   335       format->Gmask = 0x000003E0;
   336       format->Bmask = 0x0000001F;
   337       break;
   338 
   339     case DSPF_RGB16:
   340       format->Rmask = 0x0000F800;
   341       format->Gmask = 0x000007E0;
   342       format->Bmask = 0x0000001F;
   343       break;
   344 
   345     case DSPF_ARGB:
   346       format->Amask = 0; /* apps don't seem to like that:  0xFF000000; */
   347       /* fall through */
   348     case DSPF_RGB24:
   349     case DSPF_RGB32:
   350       format->Rmask = 0x00FF0000;
   351       format->Gmask = 0x0000FF00;
   352       format->Bmask = 0x000000FF;
   353       break;
   354 
   355     case DSPF_RGB332:
   356       format->Rmask = 0x000000E0;
   357       format->Gmask = 0x0000001C;
   358       format->Bmask = 0x00000003;
   359 
   360       format->palette = GenerateRGB332Palette();
   361       break;
   362 
   363     default:
   364       return -1;
   365     }
   366 
   367   format->BitsPerPixel  = DFB_BYTES_PER_PIXEL(pixelformat) * 8;
   368   format->BytesPerPixel = DFB_BYTES_PER_PIXEL(pixelformat);
   369 
   370   return 0;
   371 }
   372 
   373 
   374 int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat)
   375 {
   376   int                      i;
   377   DFBResult                ret;
   378   DFBCardCapabilities      caps;
   379   DFBDisplayLayerConfig    dlc;
   380   DFBSurfacePixelFormat    format;
   381   struct DirectFBEnumRect *rect;
   382   IDirectFB               *dfb    = NULL;
   383   IDirectFBDisplayLayer   *layer  = NULL;
   384   IDirectFBEventBuffer    *events = NULL;
   385 
   386 
   387   ret = DirectFBInit (NULL, NULL);
   388   if (ret)
   389     {
   390       SetDirectFBerror ("DirectFBInit", ret);
   391       goto error;
   392     }
   393 
   394   ret = DirectFBCreate (&dfb);
   395   if (ret)
   396     {
   397       SetDirectFBerror ("DirectFBCreate", ret);
   398       goto error;
   399     }
   400 
   401   ret = dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer);
   402   if (ret)
   403     {
   404       SetDirectFBerror ("dfb->GetDisplayLayer", ret);
   405       goto error;
   406     }
   407 
   408   ret = dfb->CreateEventBuffer (dfb, DICAPS_ALL, &events);
   409   if (ret)
   410     {
   411       SetDirectFBerror ("dfb->CreateEventBuffer", ret);
   412       goto error;
   413     }
   414   
   415   layer->EnableCursor (layer, 1);
   416 
   417   /* Query layer configuration to determine the current mode and pixelformat */
   418   layer->GetConfiguration (layer, &dlc);
   419 
   420   /* FIXME: Returning RGB332 as the default mode doesn't work (everything is black) */
   421   if ((format = dlc.pixelformat) == DSPF_RGB332)
   422     format = DSPF_RGB16;
   423 
   424   if (DFBToSDLPixelFormat (format, vformat))
   425     {
   426       SDL_SetError ("Unsupported pixelformat");
   427       goto error;
   428     }
   429 
   430   /* Enumerate the available fullscreen modes */
   431   ret = dfb->EnumVideoModes (dfb, EnumModesCallback, this);
   432   if (ret)
   433     {
   434       SetDirectFBerror ("dfb->EnumVideoModes", ret);
   435       goto error;
   436     }
   437 
   438   HIDDEN->modelist = calloc (HIDDEN->nummodes + 1, sizeof(SDL_Rect *));
   439   if (!HIDDEN->modelist)
   440     {
   441       SDL_OutOfMemory();
   442       goto error;
   443     }
   444 
   445   for (i = 0, rect = enumlist; rect; ++i, rect = rect->next )
   446     {
   447       HIDDEN->modelist[i] = &rect->r;
   448     }
   449 
   450   HIDDEN->modelist[i] = NULL;
   451 
   452 
   453   /* Query card capabilities to get the video memory size */
   454   dfb->GetCardCapabilities (dfb, &caps);
   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 
   464   HIDDEN->initialized = 1;
   465   HIDDEN->dfb         = dfb;
   466   HIDDEN->layer       = layer;
   467   HIDDEN->eventbuffer = events;
   468 
   469   return 0;
   470 
   471  error:
   472   if (events)
   473     events->Release (events);
   474   
   475   if (layer)
   476     layer->Release (layer);
   477 
   478   if (dfb)
   479     dfb->Release (dfb);
   480 
   481   return -1;
   482 }
   483 
   484 static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
   485 {
   486   if (flags & SDL_FULLSCREEN)
   487     return HIDDEN->modelist;
   488   else
   489     if (SDLToDFBPixelFormat (format) != DSPF_UNKNOWN)
   490       return (SDL_Rect**) -1;
   491 
   492   return NULL;
   493 }
   494 
   495 static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags)
   496 {
   497   DFBResult             ret;
   498   DFBSurfaceDescription dsc;
   499   DFBSurfacePixelFormat pixelformat;
   500 
   501   fprintf (stderr, "SDL DirectFB_SetVideoMode: %dx%d@%d, flags: 0x%08x\n",
   502            width, height, bpp, flags);
   503 
   504   flags |= SDL_FULLSCREEN;
   505 
   506   /* Release previous primary surface */
   507   if (current->hwdata && current->hwdata->surface)
   508     {
   509       current->hwdata->surface->Release (current->hwdata->surface);
   510       current->hwdata->surface = NULL;
   511     }
   512   else if (!current->hwdata)
   513     {
   514       /* Allocate the hardware acceleration data */
   515       current->hwdata = (struct private_hwdata *) calloc (1, sizeof(*current->hwdata));
   516       if (!current->hwdata)
   517         {
   518           SDL_OutOfMemory();
   519           return NULL;
   520 	}
   521     }
   522 
   523   /* Set cooperative level depending on flag SDL_FULLSCREEN */
   524   if (flags & SDL_FULLSCREEN)
   525     {
   526       ret = HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_FULLSCREEN);
   527       if (ret)
   528         {
   529           DirectFBError ("dfb->SetCooperativeLevel", ret);
   530           flags &= ~SDL_FULLSCREEN;
   531         }
   532     }
   533   else
   534     HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL);
   535 
   536   /* Set video mode */
   537   ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp);
   538   if (ret)
   539     {
   540       if (flags & SDL_FULLSCREEN)
   541         {
   542           flags &= ~SDL_FULLSCREEN;
   543           HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL);
   544           ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp);
   545         }
   546 
   547       if (ret)
   548         {
   549           SetDirectFBerror ("dfb->SetVideoMode", ret);
   550           return NULL;
   551         }
   552     }
   553 
   554   /* Create primary surface */
   555   dsc.flags       = DSDESC_CAPS | DSDESC_PIXELFORMAT;
   556   dsc.caps        = DSCAPS_PRIMARY | ((flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0);
   557   dsc.pixelformat = GetFormatForBpp (bpp, HIDDEN->layer);
   558 
   559   ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &current->hwdata->surface);
   560   if (ret && (flags & SDL_DOUBLEBUF))
   561     {
   562       /* Try without double buffering */
   563       dsc.caps &= ~DSCAPS_FLIPPING;
   564       ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &current->hwdata->surface);
   565     }
   566   if (ret)
   567     {
   568       SetDirectFBerror ("dfb->CreateSurface", ret);
   569       current->hwdata->surface = NULL;
   570       return NULL;
   571     }
   572 
   573   current->w     = width;
   574   current->h     = height;
   575   current->flags = SDL_HWSURFACE | SDL_PREALLOC;
   576 
   577   if (flags & SDL_FULLSCREEN)
   578     {
   579       current->flags |= SDL_FULLSCREEN;
   580       this->UpdateRects = DirectFB_DirectUpdate;
   581     }
   582   else
   583     this->UpdateRects = DirectFB_WindowedUpdate;
   584 
   585   if (dsc.caps & DSCAPS_FLIPPING)
   586     current->flags |= SDL_DOUBLEBUF;
   587 
   588   current->hwdata->surface->GetPixelFormat (current->hwdata->surface, &pixelformat);
   589   DFBToSDLPixelFormat (pixelformat, current->format);
   590 
   591   return current;
   592 }
   593 
   594 static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface)
   595 {
   596   DFBResult             ret;
   597   DFBSurfaceDescription dsc;
   598 
   599   /*  fprintf(stderr, "SDL: DirectFB_AllocHWSurface (%dx%d@%d, flags: 0x%08x)\n",
   600       surface->w, surface->h, surface->format->BitsPerPixel, surface->flags);*/
   601 
   602   if (surface->w < 8 || surface->h < 8)
   603     return -1;
   604 
   605   /* fill surface description */
   606   dsc.flags  = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   607   dsc.width  = surface->w;
   608   dsc.height = surface->h;
   609   dsc.caps   = (surface->flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0;
   610 
   611   /* find the right pixelformat */
   612   dsc.pixelformat = SDLToDFBPixelFormat (surface->format);
   613   if (dsc.pixelformat == DSPF_UNKNOWN)
   614     return -1;
   615 
   616   /* Allocate the hardware acceleration data */
   617   surface->hwdata = (struct private_hwdata *) calloc (1, sizeof(*surface->hwdata));
   618   if (surface->hwdata == NULL)
   619     {
   620       SDL_OutOfMemory();
   621       return -1;
   622     }
   623 
   624   /* Create the surface */
   625   ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface->hwdata->surface);
   626   if (ret)
   627     {
   628       SetDirectFBerror ("dfb->CreateSurface", ret);
   629       free (surface->hwdata);
   630       surface->hwdata = NULL;
   631       return -1;
   632     }
   633 
   634   surface->flags |= SDL_HWSURFACE | SDL_PREALLOC;
   635 
   636   return 0;
   637 }
   638 
   639 static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface)
   640 {
   641   if (surface->hwdata && HIDDEN->initialized)
   642     {
   643       surface->hwdata->surface->Release (surface->hwdata->surface);
   644       free (surface->hwdata);
   645       surface->hwdata = NULL;
   646     }
   647 }
   648 
   649 static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
   650 {
   651   /*  fprintf(stderr, "SDL: DirectFB_CheckHWBlit (src->hwdata: %p, dst->hwdata: %p)\n",
   652       src->hwdata, dst->hwdata);*/
   653 
   654   if (!src->hwdata || !dst->hwdata)
   655     return 0;
   656 
   657   src->flags |= SDL_HWACCEL;
   658   src->map->hw_blit = DirectFB_HWAccelBlit;
   659 
   660   return 1;
   661 }
   662 
   663 static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
   664                                 SDL_Surface *dst, SDL_Rect *dstrect)
   665 {
   666   DFBSurfaceBlittingFlags flags = DSBLIT_NOFX;
   667 
   668   DFBRectangle sr = { srcrect->x, srcrect->y, srcrect->w, srcrect->h };
   669   DFBRectangle dr = { dstrect->x, dstrect->y, dstrect->w, dstrect->h };
   670 
   671   IDirectFBSurface *surface = dst->hwdata->surface;
   672 
   673   if (src->flags & SDL_SRCCOLORKEY)
   674     {
   675       flags |= DSBLIT_SRC_COLORKEY;
   676       DirectFB_SetHWColorKey (NULL, src, src->format->colorkey);
   677     }
   678 
   679   if (src->flags & SDL_SRCALPHA)
   680     {
   681       flags |= DSBLIT_BLEND_COLORALPHA;
   682       surface->SetColor (surface, 0xff, 0xff, 0xff, src->format->alpha);
   683     }
   684 
   685   surface->SetBlittingFlags (surface, flags);
   686 
   687   if (sr.w == dr.w && sr.h == dr.h)
   688     surface->Blit (surface, src->hwdata->surface, &sr, dr.x, dr.y);
   689   else
   690     surface->StretchBlit (surface, src->hwdata->surface, &sr, &dr);
   691 
   692   return 0;
   693 }
   694 
   695 static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
   696 {
   697   SDL_PixelFormat  *fmt     = dst->format;
   698   IDirectFBSurface *surface = dst->hwdata->surface;
   699 
   700   /* ugly */
   701   surface->SetColor (surface,
   702                      (color & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
   703                      (color & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
   704                      (color & fmt->Bmask) << (fmt->Bloss - fmt->Bshift), 0xFF);
   705   surface->FillRectangle (surface, dstrect->x, dstrect->y, dstrect->w, dstrect->h);
   706 
   707   return 0;
   708 }
   709 
   710 static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *src, Uint32 key)
   711 {
   712   SDL_PixelFormat  *fmt     = src->format;
   713   IDirectFBSurface *surface = src->hwdata->surface;
   714 
   715   /* ugly */
   716   surface->SetSrcColorKey (surface,
   717                            (key & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
   718                            (key & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
   719                            (key & fmt->Bmask) << (fmt->Bloss - fmt->Bshift));
   720 
   721   return 0;
   722 }
   723 
   724 static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
   725 {
   726   return 0;
   727 }
   728 
   729 static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface)
   730 {
   731   return surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, DSFLIP_WAITFORSYNC);
   732 }
   733 
   734 static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface)
   735 {
   736   DFBResult  ret;
   737   void      *data;
   738   int        pitch;
   739 
   740   ret = surface->hwdata->surface->Lock (surface->hwdata->surface,
   741                                         DSLF_WRITE, &data, &pitch);
   742   if (ret)
   743     {
   744       SetDirectFBerror ("surface->Lock", ret);
   745       return -1;
   746     }
   747 
   748   surface->pixels = data;
   749   surface->pitch  = pitch;
   750 
   751   return 0;
   752 }
   753 
   754 static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface)
   755 {
   756   surface->hwdata->surface->Unlock (surface->hwdata->surface);
   757   surface->pixels = NULL;
   758 }
   759 
   760 static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
   761 {
   762 }
   763 
   764 static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects)
   765 {
   766   DFBRegion         region;
   767   int               i;
   768   int               region_valid = 0;
   769   IDirectFBSurface *surface = this->screen->hwdata->surface;
   770 
   771   for (i=0; i<numrects; ++i)
   772     {
   773       int x2, y2;
   774 
   775       if ( ! rects[i].w ) /* Clipped? */
   776         continue;
   777 
   778       x2 = rects[i].x + rects[i].w - 1;
   779       y2 = rects[i].y + rects[i].h - 1;
   780 
   781       if (region_valid)
   782         {
   783           if (rects[i].x < region.x1)
   784             region.x1 = rects[i].x;
   785 
   786           if (rects[i].y < region.y1)
   787             region.y1 = rects[i].y;
   788 
   789           if (x2 > region.x2)
   790             region.x2 = x2;
   791 
   792           if (y2 > region.y2)
   793             region.y2 = y2;
   794         }
   795       else
   796         {
   797             region.x1 = rects[i].x;
   798             region.y1 = rects[i].y;
   799             region.x2 = x2;
   800             region.y2 = y2;
   801 
   802             region_valid = 1;
   803         }
   804     }
   805 
   806   if (region_valid)
   807     surface->Flip (surface, &region, DSFLIP_WAITFORSYNC);
   808 }
   809 
   810 int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
   811 {
   812   fprintf(stderr, "SDL: Unimplemented DirectFB_SetColors!\n");
   813   return -1;
   814 }
   815 	
   816 void DirectFB_VideoQuit(_THIS)
   817 {
   818   struct DirectFBEnumRect *rect = enumlist;
   819 
   820   if (HIDDEN->eventbuffer)
   821     {
   822       HIDDEN->eventbuffer->Release (HIDDEN->eventbuffer);
   823       HIDDEN->eventbuffer = NULL;
   824     }
   825 
   826   if (HIDDEN->layer)
   827     {
   828       HIDDEN->layer->Release (HIDDEN->layer);
   829       HIDDEN->layer = NULL;
   830     }
   831 
   832   if (HIDDEN->dfb)
   833     {
   834       HIDDEN->dfb->Release (HIDDEN->dfb);
   835       HIDDEN->dfb = NULL;
   836     }
   837 
   838   /* Free video mode list */
   839   if (HIDDEN->modelist)
   840     {
   841       free (HIDDEN->modelist);
   842       HIDDEN->modelist = NULL;
   843     }
   844 
   845   /* Free mode enumeration list */
   846   while (rect)
   847     {
   848       struct DirectFBEnumRect *next = rect->next;
   849       free (rect);
   850       rect = next;
   851     }
   852   enumlist = NULL;
   853 
   854   HIDDEN->initialized = 0;
   855 }
   856 
   857 void DirectFB_FinalQuit(void) 
   858 {
   859 }