src/video/directfb/SDL_DirectFB_video.c
author Sam Lantinga <slouken@libsdl.org>
Sat, 31 Aug 2002 04:06:37 +0000
changeset 477 22581630aab7
parent 464 1c4be4a16410
child 478 f8482d7c9595
permissions -rw-r--r--
Date: Tue, 27 Aug 2002 16:14:11 +0200
From: Denis Oliver Kropp
Subject: Palette support and 8bit color keying fix

This patch adds support for 8bit palette modes dropping
the RGB332 stuff. It also fixes color keying for 8bit.
testsprite (without -bpp >8) looks correct again.
     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) && bytes > 1)
   162     return dlc.pixelformat;
   163 
   164   switch (bytes)
   165     {
   166     case 1:
   167       return DSPF_LUT8;
   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   IDirectFBPalette *palette;
   208 };
   209 
   210 void SetDirectFBerror (const char *function, DFBResult code)
   211 {
   212   const char *error = DirectFBErrorString (code);
   213 
   214   if (error)
   215     SDL_SetError("%s: %s", function, error);
   216   else
   217     SDL_SetError("Unknown error code from %s", function);
   218 }
   219 
   220 static DFBSurfacePixelFormat SDLToDFBPixelFormat (SDL_PixelFormat *format)
   221 {
   222   if (format->Rmask && format->Gmask && format->Bmask)
   223     {
   224       switch (format->BitsPerPixel)
   225         {
   226         case 8:
   227           return DSPF_LUT8;
   228           
   229         case 16:
   230           if (format->Rmask == 0xF800 &&
   231               format->Gmask == 0x07E0 &&
   232               format->Bmask == 0x001F)
   233             return DSPF_RGB16;
   234           /* fall through */
   235           
   236         case 15:
   237           if (format->Rmask == 0x7C00 &&
   238               format->Gmask == 0x03E0 &&
   239               format->Bmask == 0x001F)
   240             return DSPF_RGB15;
   241           break;
   242           
   243         case 24:
   244           if (format->Rmask == 0xFF0000 &&
   245               format->Gmask == 0x00FF00 &&
   246               format->Bmask == 0x0000FF)
   247             return DSPF_RGB24;
   248           break;
   249 
   250         case 32:
   251           if (format->Rmask == 0xFF0000 &&
   252               format->Gmask == 0x00FF00 &&
   253               format->Bmask == 0x0000FF)
   254             {
   255               if (format->Amask == 0xFF000000)
   256                 return DSPF_ARGB;
   257               else
   258                 return DSPF_RGB32;
   259             }
   260           break;
   261         }
   262     }
   263   else
   264     {
   265       switch (format->BitsPerPixel)
   266 	{
   267         case 8:
   268           return DSPF_LUT8;
   269 	case 15:
   270 	  return DSPF_RGB15;
   271 	case 16:
   272 	  return DSPF_RGB16;
   273 	case 24:
   274 	  return DSPF_RGB24;
   275 	case 32:
   276 	  return DSPF_RGB32;
   277 	}
   278     }
   279 
   280   return DSPF_UNKNOWN;
   281 }
   282 
   283 static SDL_Palette *AllocatePalette(int size)
   284 {
   285   SDL_Palette *palette;
   286   SDL_Color   *colors;
   287 
   288   palette = calloc (1, sizeof(SDL_Palette));
   289   if (!palette)
   290     {
   291       SDL_OutOfMemory();
   292       return NULL;
   293     }
   294 
   295   colors = calloc (size, sizeof(SDL_Color));
   296   if (!colors)
   297     {
   298       SDL_OutOfMemory();
   299       return NULL;
   300     }
   301 
   302   palette->ncolors = size;
   303   palette->colors  = colors;
   304 
   305   return palette;
   306 }
   307 
   308 static int DFBToSDLPixelFormat (DFBSurfacePixelFormat pixelformat, SDL_PixelFormat *format)
   309 {
   310   format->Amask = format->Rmask = format->Gmask = format->Bmask = 0;
   311   format->BitsPerPixel = format->BytesPerPixel = 0;
   312 
   313   switch (pixelformat)
   314     {
   315     case DSPF_A8:
   316       format->Amask = 0x000000FF;
   317       break;
   318 
   319     case DSPF_RGB15:
   320       format->Rmask = 0x00007C00;
   321       format->Gmask = 0x000003E0;
   322       format->Bmask = 0x0000001F;
   323       break;
   324 
   325     case DSPF_RGB16:
   326       format->Rmask = 0x0000F800;
   327       format->Gmask = 0x000007E0;
   328       format->Bmask = 0x0000001F;
   329       break;
   330 
   331     case DSPF_ARGB:
   332       format->Amask = 0; /* apps don't seem to like that:  0xFF000000; */
   333       /* fall through */
   334     case DSPF_RGB24:
   335     case DSPF_RGB32:
   336       format->Rmask = 0x00FF0000;
   337       format->Gmask = 0x0000FF00;
   338       format->Bmask = 0x000000FF;
   339       break;
   340 
   341     case DSPF_LUT8:
   342       format->Rmask = 0x000000FF;
   343       format->Gmask = 0x000000FF;
   344       format->Bmask = 0x000000FF;
   345 
   346       if (!format->palette)
   347         format->palette = AllocatePalette(256);
   348       break;
   349 
   350     default:
   351       fprintf (stderr, "SDL_DirectFB: Unsupported pixelformat (0x%08x)!\n", pixelformat);
   352       return -1;
   353     }
   354 
   355   format->BitsPerPixel  = DFB_BYTES_PER_PIXEL(pixelformat) * 8;
   356   format->BytesPerPixel = DFB_BYTES_PER_PIXEL(pixelformat);
   357 
   358   return 0;
   359 }
   360 
   361 
   362 int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat)
   363 {
   364   int                      i;
   365   DFBResult                ret;
   366   DFBCardCapabilities      caps;
   367   DFBDisplayLayerConfig    dlc;
   368   struct DirectFBEnumRect *rect;
   369   IDirectFB               *dfb    = NULL;
   370   IDirectFBDisplayLayer   *layer  = NULL;
   371   IDirectFBEventBuffer    *events = NULL;
   372 
   373 
   374   ret = DirectFBInit (NULL, NULL);
   375   if (ret)
   376     {
   377       SetDirectFBerror ("DirectFBInit", ret);
   378       goto error;
   379     }
   380 
   381   ret = DirectFBCreate (&dfb);
   382   if (ret)
   383     {
   384       SetDirectFBerror ("DirectFBCreate", ret);
   385       goto error;
   386     }
   387 
   388   ret = dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer);
   389   if (ret)
   390     {
   391       SetDirectFBerror ("dfb->GetDisplayLayer", ret);
   392       goto error;
   393     }
   394 
   395   ret = dfb->CreateEventBuffer (dfb, DICAPS_ALL, &events);
   396   if (ret)
   397     {
   398       SetDirectFBerror ("dfb->CreateEventBuffer", ret);
   399       goto error;
   400     }
   401   
   402   layer->EnableCursor (layer, 1);
   403 
   404   /* Query layer configuration to determine the current mode and pixelformat */
   405   layer->GetConfiguration (layer, &dlc);
   406 
   407   /* If current format is not supported use LUT8 as the default */
   408   if (DFBToSDLPixelFormat (dlc.pixelformat, vformat))
   409     DFBToSDLPixelFormat (DSPF_LUT8, vformat);
   410 
   411   /* Enumerate the available fullscreen modes */
   412   ret = dfb->EnumVideoModes (dfb, EnumModesCallback, this);
   413   if (ret)
   414     {
   415       SetDirectFBerror ("dfb->EnumVideoModes", ret);
   416       goto error;
   417     }
   418 
   419   HIDDEN->modelist = calloc (HIDDEN->nummodes + 1, sizeof(SDL_Rect *));
   420   if (!HIDDEN->modelist)
   421     {
   422       SDL_OutOfMemory();
   423       goto error;
   424     }
   425 
   426   for (i = 0, rect = enumlist; rect; ++i, rect = rect->next )
   427     {
   428       HIDDEN->modelist[i] = &rect->r;
   429     }
   430 
   431   HIDDEN->modelist[i] = NULL;
   432 
   433 
   434   /* Query card capabilities to get the video memory size */
   435   dfb->GetCardCapabilities (dfb, &caps);
   436 
   437   this->info.wm_available = 1;
   438   this->info.hw_available = 1;
   439   this->info.blit_hw      = 1;
   440   this->info.blit_hw_CC   = 1;
   441   this->info.blit_hw_A    = 1;
   442   this->info.blit_fill    = 1;
   443   this->info.video_mem    = caps.video_memory / 1024;
   444 
   445   HIDDEN->initialized = 1;
   446   HIDDEN->dfb         = dfb;
   447   HIDDEN->layer       = layer;
   448   HIDDEN->eventbuffer = events;
   449 
   450   return 0;
   451 
   452  error:
   453   if (events)
   454     events->Release (events);
   455   
   456   if (layer)
   457     layer->Release (layer);
   458 
   459   if (dfb)
   460     dfb->Release (dfb);
   461 
   462   return -1;
   463 }
   464 
   465 static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
   466 {
   467   if (flags & SDL_FULLSCREEN)
   468     return HIDDEN->modelist;
   469   else
   470     if (SDLToDFBPixelFormat (format) != DSPF_UNKNOWN)
   471       return (SDL_Rect**) -1;
   472 
   473   return NULL;
   474 }
   475 
   476 static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags)
   477 {
   478   DFBResult              ret;
   479   DFBSurfaceDescription  dsc;
   480   DFBSurfacePixelFormat  pixelformat;
   481   IDirectFBSurface      *surface;
   482 
   483   fprintf (stderr, "SDL DirectFB_SetVideoMode: %dx%d@%d, flags: 0x%08x\n",
   484            width, height, bpp, flags);
   485 
   486   flags |= SDL_FULLSCREEN;
   487 
   488   /* Release previous primary surface */
   489   if (current->hwdata && current->hwdata->surface)
   490     {
   491       current->hwdata->surface->Release (current->hwdata->surface);
   492       current->hwdata->surface = NULL;
   493 
   494       /* And its palette if present */
   495       if (current->hwdata->palette)
   496         {
   497           current->hwdata->palette->Release (current->hwdata->palette);
   498           current->hwdata->palette = NULL;
   499         }
   500     }
   501   else if (!current->hwdata)
   502     {
   503       /* Allocate the hardware acceleration data */
   504       current->hwdata = (struct private_hwdata *) calloc (1, sizeof(*current->hwdata));
   505       if (!current->hwdata)
   506         {
   507           SDL_OutOfMemory();
   508           return NULL;
   509 	}
   510     }
   511 
   512   /* Set cooperative level depending on flag SDL_FULLSCREEN */
   513   if (flags & SDL_FULLSCREEN)
   514     {
   515       ret = HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_FULLSCREEN);
   516       if (ret)
   517         {
   518           DirectFBError ("dfb->SetCooperativeLevel", ret);
   519           flags &= ~SDL_FULLSCREEN;
   520         }
   521     }
   522   else
   523     HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL);
   524 
   525   /* Set video mode */
   526   ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp);
   527   if (ret)
   528     {
   529       if (flags & SDL_FULLSCREEN)
   530         {
   531           flags &= ~SDL_FULLSCREEN;
   532           HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL);
   533           ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp);
   534         }
   535 
   536       if (ret)
   537         {
   538           SetDirectFBerror ("dfb->SetVideoMode", ret);
   539           return NULL;
   540         }
   541     }
   542 
   543   /* Create primary surface */
   544   dsc.flags       = DSDESC_CAPS | DSDESC_PIXELFORMAT;
   545   dsc.caps        = DSCAPS_PRIMARY | ((flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0);
   546   dsc.pixelformat = GetFormatForBpp (bpp, HIDDEN->layer);
   547 
   548   ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface);
   549   if (ret && (flags & SDL_DOUBLEBUF))
   550     {
   551       /* Try without double buffering */
   552       dsc.caps &= ~DSCAPS_FLIPPING;
   553       ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface);
   554     }
   555   if (ret)
   556     {
   557       SetDirectFBerror ("dfb->CreateSurface", ret);
   558       return NULL;
   559     }
   560 
   561   current->w     = width;
   562   current->h     = height;
   563   current->flags = SDL_HWSURFACE | SDL_PREALLOC;
   564 
   565   if (flags & SDL_FULLSCREEN)
   566     {
   567       current->flags |= SDL_FULLSCREEN;
   568       this->UpdateRects = DirectFB_DirectUpdate;
   569     }
   570   else
   571     this->UpdateRects = DirectFB_WindowedUpdate;
   572 
   573   if (dsc.caps & DSCAPS_FLIPPING)
   574     current->flags |= SDL_DOUBLEBUF;
   575 
   576   surface->GetPixelFormat (surface, &pixelformat);
   577 
   578   DFBToSDLPixelFormat (pixelformat, current->format);
   579 
   580   /* Get the surface palette (if supported) */
   581   if (DFB_PIXELFORMAT_IS_INDEXED( pixelformat ))
   582     {
   583       surface->GetPalette (surface, &current->hwdata->palette);
   584 
   585       current->flags |= SDL_HWPALETTE;
   586     }
   587 
   588   current->hwdata->surface = surface;
   589 
   590   return current;
   591 }
   592 
   593 static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface)
   594 {
   595   DFBResult             ret;
   596   DFBSurfaceDescription dsc;
   597 
   598   /*  fprintf(stderr, "SDL: DirectFB_AllocHWSurface (%dx%d@%d, flags: 0x%08x)\n",
   599       surface->w, surface->h, surface->format->BitsPerPixel, surface->flags);*/
   600 
   601   if (surface->w < 8 || surface->h < 8)
   602     return -1;
   603 
   604   /* fill surface description */
   605   dsc.flags  = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
   606   dsc.width  = surface->w;
   607   dsc.height = surface->h;
   608   dsc.caps   = (surface->flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0;
   609 
   610   /* find the right pixelformat */
   611   dsc.pixelformat = SDLToDFBPixelFormat (surface->format);
   612   if (dsc.pixelformat == DSPF_UNKNOWN)
   613     return -1;
   614 
   615   /* Allocate the hardware acceleration data */
   616   surface->hwdata = (struct private_hwdata *) calloc (1, sizeof(*surface->hwdata));
   617   if (surface->hwdata == NULL)
   618     {
   619       SDL_OutOfMemory();
   620       return -1;
   621     }
   622 
   623   /* Create the surface */
   624   ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface->hwdata->surface);
   625   if (ret)
   626     {
   627       SetDirectFBerror ("dfb->CreateSurface", ret);
   628       free (surface->hwdata);
   629       surface->hwdata = NULL;
   630       return -1;
   631     }
   632 
   633   surface->flags |= SDL_HWSURFACE | SDL_PREALLOC;
   634 
   635   return 0;
   636 }
   637 
   638 static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface)
   639 {
   640   if (surface->hwdata && HIDDEN->initialized)
   641     {
   642       surface->hwdata->surface->Release (surface->hwdata->surface);
   643       free (surface->hwdata);
   644       surface->hwdata = NULL;
   645     }
   646 }
   647 
   648 static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
   649 {
   650   /*  fprintf(stderr, "SDL: DirectFB_CheckHWBlit (src->hwdata: %p, dst->hwdata: %p)\n",
   651       src->hwdata, dst->hwdata);*/
   652 
   653   if (!src->hwdata || !dst->hwdata)
   654     return 0;
   655 
   656   src->flags |= SDL_HWACCEL;
   657   src->map->hw_blit = DirectFB_HWAccelBlit;
   658 
   659   return 1;
   660 }
   661 
   662 static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
   663                                 SDL_Surface *dst, SDL_Rect *dstrect)
   664 {
   665   DFBSurfaceBlittingFlags flags = DSBLIT_NOFX;
   666 
   667   DFBRectangle sr = { srcrect->x, srcrect->y, srcrect->w, srcrect->h };
   668   DFBRectangle dr = { dstrect->x, dstrect->y, dstrect->w, dstrect->h };
   669 
   670   IDirectFBSurface *surface = dst->hwdata->surface;
   671 
   672   if (src->flags & SDL_SRCCOLORKEY)
   673     {
   674       flags |= DSBLIT_SRC_COLORKEY;
   675       DirectFB_SetHWColorKey (NULL, src, src->format->colorkey);
   676     }
   677 
   678   if (src->flags & SDL_SRCALPHA)
   679     {
   680       flags |= DSBLIT_BLEND_COLORALPHA;
   681       surface->SetColor (surface, 0xff, 0xff, 0xff, src->format->alpha);
   682     }
   683 
   684   surface->SetBlittingFlags (surface, flags);
   685 
   686   if (sr.w == dr.w && sr.h == dr.h)
   687     surface->Blit (surface, src->hwdata->surface, &sr, dr.x, dr.y);
   688   else
   689     surface->StretchBlit (surface, src->hwdata->surface, &sr, &dr);
   690 
   691   return 0;
   692 }
   693 
   694 static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
   695 {
   696   SDL_PixelFormat  *fmt     = dst->format;
   697   IDirectFBSurface *surface = dst->hwdata->surface;
   698 
   699   /* ugly */
   700   surface->SetColor (surface,
   701                      (color & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
   702                      (color & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
   703                      (color & fmt->Bmask) << (fmt->Bloss - fmt->Bshift), 0xFF);
   704   surface->FillRectangle (surface, dstrect->x, dstrect->y, dstrect->w, dstrect->h);
   705 
   706   return 0;
   707 }
   708 
   709 static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *src, Uint32 key)
   710 {
   711   SDL_PixelFormat  *fmt     = src->format;
   712   IDirectFBSurface *surface = src->hwdata->surface;
   713 
   714   if (fmt->BitsPerPixel == 8)
   715     surface->SetSrcColorKeyIndex (surface, key);
   716   else
   717     /* ugly */
   718     surface->SetSrcColorKey (surface,
   719                              (key & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
   720                              (key & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
   721                              (key & fmt->Bmask) << (fmt->Bloss - fmt->Bshift));
   722 
   723   return 0;
   724 }
   725 
   726 static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
   727 {
   728   return 0;
   729 }
   730 
   731 static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface)
   732 {
   733   return surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, DSFLIP_WAITFORSYNC);
   734 }
   735 
   736 static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface)
   737 {
   738   DFBResult  ret;
   739   void      *data;
   740   int        pitch;
   741 
   742   ret = surface->hwdata->surface->Lock (surface->hwdata->surface,
   743                                         DSLF_WRITE, &data, &pitch);
   744   if (ret)
   745     {
   746       SetDirectFBerror ("surface->Lock", ret);
   747       return -1;
   748     }
   749 
   750   surface->pixels = data;
   751   surface->pitch  = pitch;
   752 
   753   return 0;
   754 }
   755 
   756 static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface)
   757 {
   758   surface->hwdata->surface->Unlock (surface->hwdata->surface);
   759   surface->pixels = NULL;
   760 }
   761 
   762 static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
   763 {
   764 }
   765 
   766 static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects)
   767 {
   768   DFBRegion         region;
   769   int               i;
   770   int               region_valid = 0;
   771   IDirectFBSurface *surface = this->screen->hwdata->surface;
   772 
   773   for (i=0; i<numrects; ++i)
   774     {
   775       int x2, y2;
   776 
   777       if ( ! rects[i].w ) /* Clipped? */
   778         continue;
   779 
   780       x2 = rects[i].x + rects[i].w - 1;
   781       y2 = rects[i].y + rects[i].h - 1;
   782 
   783       if (region_valid)
   784         {
   785           if (rects[i].x < region.x1)
   786             region.x1 = rects[i].x;
   787 
   788           if (rects[i].y < region.y1)
   789             region.y1 = rects[i].y;
   790 
   791           if (x2 > region.x2)
   792             region.x2 = x2;
   793 
   794           if (y2 > region.y2)
   795             region.y2 = y2;
   796         }
   797       else
   798         {
   799             region.x1 = rects[i].x;
   800             region.y1 = rects[i].y;
   801             region.x2 = x2;
   802             region.y2 = y2;
   803 
   804             region_valid = 1;
   805         }
   806     }
   807 
   808   if (region_valid)
   809     surface->Flip (surface, &region, DSFLIP_WAITFORSYNC);
   810 }
   811 
   812 int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
   813 {
   814   IDirectFBPalette *palette = this->screen->hwdata->palette;
   815 
   816   if (!palette)
   817     return 0;
   818 
   819   if (firstcolor > 255)
   820     return 0;
   821 
   822   if (firstcolor + ncolors > 256)
   823     ncolors = 256 - firstcolor;
   824 
   825   if (ncolors > 0)
   826     {
   827       int      i;
   828       DFBColor entries[ncolors];
   829 
   830       for (i=0; i<ncolors; i++)
   831         {
   832           entries[i].a = 0xff;
   833           entries[i].r = colors[i].r;
   834           entries[i].g = colors[i].g;
   835           entries[i].b = colors[i].b;
   836         }
   837 
   838       palette->SetEntries (palette, entries, ncolors, firstcolor);
   839     }
   840 
   841   return 1;
   842 }
   843 	
   844 void DirectFB_VideoQuit(_THIS)
   845 {
   846   struct DirectFBEnumRect *rect    = enumlist;
   847   IDirectFBSurface        *surface = this->screen->hwdata->surface;
   848   IDirectFBPalette        *palette = this->screen->hwdata->palette;
   849 
   850   if (palette)
   851     palette->Release (palette);
   852 
   853   if (surface)
   854     surface->Release (surface);
   855 
   856   this->screen->hwdata->surface = NULL;
   857   this->screen->hwdata->palette = NULL;
   858 
   859   if (HIDDEN->eventbuffer)
   860     {
   861       HIDDEN->eventbuffer->Release (HIDDEN->eventbuffer);
   862       HIDDEN->eventbuffer = NULL;
   863     }
   864 
   865   if (HIDDEN->layer)
   866     {
   867       HIDDEN->layer->Release (HIDDEN->layer);
   868       HIDDEN->layer = NULL;
   869     }
   870 
   871   if (HIDDEN->dfb)
   872     {
   873       HIDDEN->dfb->Release (HIDDEN->dfb);
   874       HIDDEN->dfb = NULL;
   875     }
   876 
   877   /* Free video mode list */
   878   if (HIDDEN->modelist)
   879     {
   880       free (HIDDEN->modelist);
   881       HIDDEN->modelist = NULL;
   882     }
   883 
   884   /* Free mode enumeration list */
   885   while (rect)
   886     {
   887       struct DirectFBEnumRect *next = rect->next;
   888       free (rect);
   889       rect = next;
   890     }
   891   enumlist = NULL;
   892 
   893   HIDDEN->initialized = 0;
   894 }
   895 
   896 void DirectFB_FinalQuit(void) 
   897 {
   898 }