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