SDL-1.2.14
[sdl_omap.git] / src / video / directfb / SDL_DirectFB_video.c
1 /*
2     SDL - Simple DirectMedia Layer
3     Copyright (C) 1997-2009 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   if (enumlist && enumlist->r.w == width && enumlist->r.h == height)
195     return DFENUM_OK;
196
197   enumrect = SDL_calloc(1, sizeof(struct DirectFBEnumRect));
198   if (!enumrect)
199     {
200       SDL_OutOfMemory();
201       return DFENUM_CANCEL;
202     }
203
204   enumrect->r.w  = (Uint16)width;
205   enumrect->r.h  = (Uint16)height;
206   enumrect->next = enumlist;
207
208   enumlist = enumrect;
209
210   return DFENUM_OK;
211 }
212
213 struct private_hwdata {
214   IDirectFBSurface *surface;
215   IDirectFBPalette *palette;
216 };
217
218 void SetDirectFBerror (const char *function, DFBResult code)
219 {
220   const char *error = DirectFBErrorString (code);
221
222   if (error)
223     SDL_SetError("%s: %s", function, error);
224   else
225     SDL_SetError("Unknown error code from %s", function);
226 }
227
228 static DFBSurfacePixelFormat SDLToDFBPixelFormat (SDL_PixelFormat *format)
229 {
230   if (format->Rmask && format->Gmask && format->Bmask)
231     {
232       switch (format->BitsPerPixel)
233         {
234         case 8:
235           return DSPF_LUT8;
236           
237         case 16:
238           if (format->Rmask == 0xF800 &&
239               format->Gmask == 0x07E0 &&
240               format->Bmask == 0x001F)
241             return DSPF_RGB16;
242           /* fall through */
243           
244         case 15:
245           if (format->Rmask == 0x7C00 &&
246               format->Gmask == 0x03E0 &&
247               format->Bmask == 0x001F)
248             return DSPF_ARGB1555;
249           break;
250           
251         case 24:
252           if (format->Rmask == 0xFF0000 &&
253               format->Gmask == 0x00FF00 &&
254               format->Bmask == 0x0000FF)
255             return DSPF_RGB24;
256           break;
257
258         case 32:
259           if (format->Rmask == 0xFF0000 &&
260               format->Gmask == 0x00FF00 &&
261               format->Bmask == 0x0000FF)
262             {
263               if (format->Amask == 0xFF000000)
264                 return DSPF_ARGB;
265               else
266                 return DSPF_RGB32;
267             }
268           break;
269         }
270     }
271   else
272     {
273       switch (format->BitsPerPixel)
274         {
275         case 8:
276           return DSPF_LUT8;
277         case 15:
278           return DSPF_ARGB1555;
279         case 16:
280           return DSPF_RGB16;
281         case 24:
282           return DSPF_RGB24;
283         case 32:
284           return DSPF_RGB32;
285         }
286     }
287
288   return DSPF_UNKNOWN;
289 }
290
291 static SDL_Palette *AllocatePalette(int size)
292 {
293   SDL_Palette *palette;
294   SDL_Color   *colors;
295
296   palette = SDL_calloc (1, sizeof(SDL_Palette));
297   if (!palette)
298     {
299       SDL_OutOfMemory();
300       return NULL;
301     }
302
303   colors = SDL_calloc (size, sizeof(SDL_Color));
304   if (!colors)
305     {
306       SDL_OutOfMemory();
307       return NULL;
308     }
309
310   palette->ncolors = size;
311   palette->colors  = colors;
312
313   return palette;
314 }
315
316 static int DFBToSDLPixelFormat (DFBSurfacePixelFormat pixelformat, SDL_PixelFormat *format)
317 {
318   format->Amask = format->Rmask = format->Gmask = format->Bmask = 0;
319   format->BitsPerPixel = format->BytesPerPixel = 0;
320
321   switch (pixelformat)
322     {
323     case DSPF_A8:
324       format->Amask = 0x000000FF;
325       break;
326
327     case DSPF_ARGB1555:
328       format->Rmask = 0x00007C00;
329       format->Gmask = 0x000003E0;
330       format->Bmask = 0x0000001F;
331       break;
332
333     case DSPF_RGB16:
334       format->Rmask = 0x0000F800;
335       format->Gmask = 0x000007E0;
336       format->Bmask = 0x0000001F;
337       break;
338
339     case DSPF_ARGB:
340       format->Amask = 0; /* apps don't seem to like that:  0xFF000000; */
341       /* fall through */
342     case DSPF_RGB24:
343     case DSPF_RGB32:
344       format->Rmask = 0x00FF0000;
345       format->Gmask = 0x0000FF00;
346       format->Bmask = 0x000000FF;
347       break;
348
349     case DSPF_LUT8:
350       format->Rmask = 0x000000FF;
351       format->Gmask = 0x000000FF;
352       format->Bmask = 0x000000FF;
353
354       if (!format->palette)
355         format->palette = AllocatePalette(256);
356       break;
357
358     default:
359       fprintf (stderr, "SDL_DirectFB: Unsupported pixelformat (0x%08x)!\n", pixelformat);
360       return -1;
361     }
362
363   format->BitsPerPixel  = DFB_BYTES_PER_PIXEL(pixelformat) * 8;
364   format->BytesPerPixel = DFB_BYTES_PER_PIXEL(pixelformat);
365
366   return 0;
367 }
368
369
370 int DirectFB_VideoInit(_THIS, SDL_PixelFormat *vformat)
371 {
372   int                      i;
373   DFBResult                ret;
374 #if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23)
375   DFBCardCapabilities      caps;
376 #else
377   DFBGraphicsDeviceDescription caps;
378 #endif
379   DFBDisplayLayerConfig    dlc;
380   struct DirectFBEnumRect *rect;
381   IDirectFB               *dfb    = NULL;
382   IDirectFBDisplayLayer   *layer  = NULL;
383   IDirectFBEventBuffer    *events = NULL;
384
385   HIDDEN->c2layer = NULL, HIDDEN->c2frame = NULL;
386   HIDDEN->enable_mga_crtc2 = 0;
387   HIDDEN->mga_crtc2_stretch_overscan = 1;
388
389   ret = DirectFBInit (NULL, NULL);
390   if (ret)
391     {
392       SetDirectFBerror ("DirectFBInit", ret);
393       goto error;
394     }
395
396   ret = DirectFBCreate (&dfb);
397   if (ret)
398     {
399       SetDirectFBerror ("DirectFBCreate", ret);
400       goto error;
401     }
402
403   ret = dfb->GetDisplayLayer (dfb, DLID_PRIMARY, &layer);
404   if (ret)
405     {
406       SetDirectFBerror ("dfb->GetDisplayLayer", ret);
407       goto error;
408     }
409
410   ret = dfb->CreateInputEventBuffer (dfb, DICAPS_ALL, DFB_FALSE, &events);
411   if (ret)
412     {
413       SetDirectFBerror ("dfb->CreateEventBuffer", ret);
414       goto error;
415     }
416   
417   layer->EnableCursor (layer, 1);
418
419   /* Query layer configuration to determine the current mode and pixelformat */
420   layer->GetConfiguration (layer, &dlc);
421
422   /* If current format is not supported use LUT8 as the default */
423   if (DFBToSDLPixelFormat (dlc.pixelformat, vformat))
424     DFBToSDLPixelFormat (DSPF_LUT8, vformat);
425
426   /* Enumerate the available fullscreen modes */
427   ret = dfb->EnumVideoModes (dfb, EnumModesCallback, this);
428   if (ret)
429     {
430       SetDirectFBerror ("dfb->EnumVideoModes", ret);
431       goto error;
432     }
433
434   HIDDEN->modelist = SDL_calloc (HIDDEN->nummodes + 1, sizeof(SDL_Rect *));
435   if (!HIDDEN->modelist)
436     {
437       SDL_OutOfMemory();
438       goto error;
439     }
440
441   for (i = 0, rect = enumlist; rect; ++i, rect = rect->next )
442     {
443       HIDDEN->modelist[i] = &rect->r;
444     }
445
446   HIDDEN->modelist[i] = NULL;
447
448
449   /* Query card capabilities to get the video memory size */
450 #if (DIRECTFB_MAJOR_VERSION == 0) && (DIRECTFB_MINOR_VERSION == 9) && (DIRECTFB_MICRO_VERSION < 23)
451   dfb->GetCardCapabilities (dfb, &caps);
452 #else
453   dfb->GetDeviceDescription (dfb, &caps);
454 #endif
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   this->info.current_w    = dlc.width;  
464   this->info.current_h    = dlc.height;
465
466   HIDDEN->initialized = 1;
467   HIDDEN->dfb         = dfb;
468   HIDDEN->layer       = layer;
469   HIDDEN->eventbuffer = events;
470
471   if (SDL_getenv("SDL_DIRECTFB_MGA_CRTC2") != NULL)
472     HIDDEN->enable_mga_crtc2 = 1;
473   
474   if (HIDDEN->enable_mga_crtc2)
475     {
476       DFBDisplayLayerConfig      dlc;
477       DFBDisplayLayerConfigFlags failed;
478
479       ret = dfb->GetDisplayLayer (dfb, 2, &HIDDEN->c2layer);
480       if (ret)
481         {
482           SetDirectFBerror ("dfb->GetDisplayLayer(CRTC2)", ret);
483           goto error;
484         }
485
486       ret = HIDDEN->layer->SetCooperativeLevel(HIDDEN->layer, DLSCL_EXCLUSIVE);
487       if (ret)
488         {
489           SetDirectFBerror ("layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
490           goto error;
491         }
492  
493       ret = HIDDEN->c2layer->SetCooperativeLevel(HIDDEN->c2layer, DLSCL_EXCLUSIVE);
494       if (ret)
495         {
496           SetDirectFBerror ("c2layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
497           goto error;
498         }
499
500       HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0x0);
501
502       /* Init the surface here as it got a fixed size */
503       dlc.flags      = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE;
504       dlc.buffermode = DLBM_BACKVIDEO;
505       dlc.pixelformat = DSPF_RGB32;
506       
507       ret = HIDDEN->c2layer->TestConfiguration( HIDDEN->c2layer, &dlc, &failed );
508       if (ret)
509         {
510           SetDirectFBerror ("c2layer->TestConfiguration", ret);
511           goto error;
512         }
513     
514       ret = HIDDEN->c2layer->SetConfiguration( HIDDEN->c2layer, &dlc );
515       if (ret)
516         {
517           SetDirectFBerror ("c2layer->SetConfiguration", ret);
518           goto error;
519         }
520     
521       ret = HIDDEN->c2layer->GetSurface( HIDDEN->c2layer, &HIDDEN->c2frame );
522       if (ret)
523         {
524           SetDirectFBerror ("c2layer->GetSurface", ret);
525           goto error;
526         }
527
528       HIDDEN->c2framesize.x = 0;
529       HIDDEN->c2framesize.y = 0;
530       HIDDEN->c2frame->GetSize( HIDDEN->c2frame, &HIDDEN->c2framesize.w, &HIDDEN->c2framesize.h);
531
532       HIDDEN->c2frame->SetBlittingFlags( HIDDEN->c2frame, DSBLIT_NOFX );
533       HIDDEN->c2frame->SetColor( HIDDEN->c2frame, 0, 0, 0, 0xff );
534     
535       /* Clear CRTC2 */
536       HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
537       HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 );
538       HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
539       HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 );
540       HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
541
542       HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0xFF );
543     
544       /* Check if overscan is possibly set */
545       if (SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN") != NULL)
546         {
547             float overscan = 0;
548             if (SDL_sscanf(SDL_getenv("SDL_DIRECTFB_MGA_OVERSCAN"), "%f", &overscan) == 1)
549                if (overscan > 0 && overscan < 2)
550                   HIDDEN->mga_crtc2_stretch_overscan = overscan;
551         }
552
553       #ifdef DIRECTFB_CRTC2_DEBUG
554       printf("CRTC2 overscan: %f\n", HIDDEN->mga_crtc2_stretch_overscan);
555       #endif
556     }
557
558   return 0;
559
560  error:
561   if (events)
562     events->Release (events);
563   
564   if (HIDDEN->c2frame)
565     HIDDEN->c2frame->Release (HIDDEN->c2frame);
566
567   if (HIDDEN->c2layer)
568     HIDDEN->c2layer->Release (HIDDEN->c2layer);
569
570   if (layer)
571     layer->Release (layer);
572
573   if (dfb)
574     dfb->Release (dfb);
575
576   return -1;
577 }
578
579 static SDL_Rect **DirectFB_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags)
580 {
581   if (flags & SDL_FULLSCREEN)
582     return HIDDEN->modelist;
583   else
584     if (SDLToDFBPixelFormat (format) != DSPF_UNKNOWN)
585       return (SDL_Rect**) -1;
586
587   return NULL;
588 }
589
590 static SDL_Surface *DirectFB_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags)
591 {
592   DFBResult              ret;
593   DFBSurfaceDescription  dsc;
594   DFBSurfacePixelFormat  pixelformat;
595   IDirectFBSurface      *surface;
596
597   fprintf (stderr, "SDL DirectFB_SetVideoMode: %dx%d@%d, flags: 0x%08x\n",
598            width, height, bpp, flags);
599
600   flags |= SDL_FULLSCREEN;
601
602   /* Release previous primary surface */
603   if (current->hwdata && current->hwdata->surface)
604     {
605       current->hwdata->surface->Release (current->hwdata->surface);
606       current->hwdata->surface = NULL;
607
608       /* And its palette if present */
609       if (current->hwdata->palette)
610         {
611           current->hwdata->palette->Release (current->hwdata->palette);
612           current->hwdata->palette = NULL;
613         }
614     }
615   else if (!current->hwdata)
616     {
617       /* Allocate the hardware acceleration data */
618       current->hwdata = (struct private_hwdata *) SDL_calloc (1, sizeof(*current->hwdata));
619       if (!current->hwdata)
620         {
621           SDL_OutOfMemory();
622           return NULL;
623         }
624     }
625
626   /* Set cooperative level depending on flag SDL_FULLSCREEN */
627   if (flags & SDL_FULLSCREEN)
628     {
629       ret = HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_FULLSCREEN);
630       if (ret && !HIDDEN->enable_mga_crtc2)
631         {
632           DirectFBError ("dfb->SetCooperativeLevel", ret);
633           flags &= ~SDL_FULLSCREEN;
634         }
635     }
636   else
637     HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL);
638
639   /* Set video mode */
640   ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp);
641   if (ret)
642     {
643       if (flags & SDL_FULLSCREEN)
644         {
645           flags &= ~SDL_FULLSCREEN;
646           HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_NORMAL);
647           ret = HIDDEN->dfb->SetVideoMode (HIDDEN->dfb, width, height, bpp);
648         }
649
650       if (ret)
651         {
652           SetDirectFBerror ("dfb->SetVideoMode", ret);
653           return NULL;
654         }
655     }
656
657   /* Create primary surface */
658   dsc.flags       = DSDESC_CAPS | DSDESC_PIXELFORMAT;
659   dsc.caps        = DSCAPS_PRIMARY | ((flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0);
660   dsc.pixelformat = GetFormatForBpp (bpp, HIDDEN->layer);
661
662   ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface);
663   if (ret && (flags & SDL_DOUBLEBUF))
664     {
665       /* Try without double buffering */
666       dsc.caps &= ~DSCAPS_FLIPPING;
667       ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface);
668     }
669   if (ret)
670     {
671       SetDirectFBerror ("dfb->CreateSurface", ret);
672       return NULL;
673     }
674
675   current->w     = width;
676   current->h     = height;
677   current->flags = SDL_HWSURFACE | SDL_PREALLOC;
678
679   if (flags & SDL_FULLSCREEN)
680     {
681       current->flags |= SDL_FULLSCREEN;
682       this->UpdateRects = DirectFB_DirectUpdate;
683     }
684   else
685     this->UpdateRects = DirectFB_WindowedUpdate;
686
687   if (dsc.caps & DSCAPS_FLIPPING)
688     current->flags |= SDL_DOUBLEBUF;
689
690   surface->GetPixelFormat (surface, &pixelformat);
691
692   DFBToSDLPixelFormat (pixelformat, current->format);
693
694   /* Get the surface palette (if supported) */
695   if (DFB_PIXELFORMAT_IS_INDEXED( pixelformat ))
696     {
697       surface->GetPalette (surface, &current->hwdata->palette);
698
699       current->flags |= SDL_HWPALETTE;
700     }
701
702   current->hwdata->surface = surface;
703
704   /* MGA CRTC2 stuff */
705   if (HIDDEN->enable_mga_crtc2)
706     {
707       /* no stretching if c2ssize == c2framesize */
708       HIDDEN->c2ssize.x = 0, HIDDEN->c2ssize.y = 0;
709       HIDDEN->c2ssize.w = width;
710       HIDDEN->c2ssize.h = height;
711
712       HIDDEN->c2dsize.x = 0, HIDDEN->c2dsize.y = 0;
713       HIDDEN->c2dsize.w = width;
714       HIDDEN->c2dsize.h = height;
715
716       HIDDEN->mga_crtc2_stretch = 0;
717
718       if (SDL_getenv("SDL_DIRECTFB_MGA_STRETCH") != NULL)
719         {
720             /* Normally assume a picture aspect ratio of 4:3 */
721             int zoom_aspect_x = 4, zoom_aspect_y = 3, i, j;
722
723             for (i = 1; i < 20; i++)
724               {
725                 for (j = 1; j < 10; j++)
726                   {
727                     if ((float)width/(float)i*(float)j == height) 
728                       {
729                         zoom_aspect_x = i;
730                         zoom_aspect_y = j;
731                         
732                         /* break the loop */
733                         i = 21;
734                         break;
735                       }
736                   }
737               }
738         
739             #ifdef DIRECTFB_CRTC2_DEBUG
740             printf("Source resolution: X: %d, Y: %d, Aspect ratio: %d:%d\n", width, height, zoom_aspect_x, zoom_aspect_y);
741             printf("CRTC2 resolution: X: %d, Y: %d\n", HIDDEN->c2framesize.w, HIDDEN->c2framesize.h);
742             #endif
743         
744           /* don't stretch only slightly smaller/larger images */
745           if ((float)width < (float)HIDDEN->c2framesize.w*0.95 || (float)height < (float)HIDDEN->c2framesize.h*0.95)
746             {
747               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)
748                 {
749                    HIDDEN->c2dsize.w+=zoom_aspect_x;
750                    HIDDEN->c2dsize.h+=zoom_aspect_y;
751                 }
752
753               /* one step down */
754                 HIDDEN->c2dsize.w-=zoom_aspect_x;
755                 HIDDEN->c2dsize.h-=zoom_aspect_y;
756
757               #ifdef DIRECTFB_CRTC2_DEBUG
758               printf("Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
759               #endif
760
761               HIDDEN->mga_crtc2_stretch = 1;
762             } 
763           else if ((float)width > (float)HIDDEN->c2framesize.w*0.95 || (float)height > (float)HIDDEN->c2framesize.h*0.95)
764             {
765                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)
766                 {
767               HIDDEN->c2dsize.w-=zoom_aspect_x;
768               HIDDEN->c2dsize.h-=zoom_aspect_y;
769                 }
770               
771               #ifdef DIRECTFB_CRTC2_DEBUG
772               printf("Down-Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
773               #endif
774
775               HIDDEN->mga_crtc2_stretch = 1;
776              } else {
777           #ifdef DIRECTFB_CRTC2_DEBUG
778           printf("Not stretching image\n");
779           #endif
780         }
781
782       /* Panning */
783       if (HIDDEN->c2framesize.w > HIDDEN->c2dsize.w)
784         HIDDEN->c2dsize.x = (HIDDEN->c2framesize.w - HIDDEN->c2dsize.w)  / 2;
785       else
786         HIDDEN->c2dsize.x = (HIDDEN->c2dsize.w - HIDDEN->c2framesize.w)  / 2;
787
788       if (HIDDEN->c2framesize.h > HIDDEN->c2dsize.h)
789         HIDDEN->c2dsize.y = (HIDDEN->c2framesize.h - HIDDEN->c2dsize.h)  / 2;
790       else
791         HIDDEN->c2dsize.y = (HIDDEN->c2dsize.h - HIDDEN->c2framesize.h)  / 2;
792
793       #ifdef DIRECTFB_CRTC2_DEBUG
794     printf("CRTC2 position X: %d, Y: %d\n", HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
795       #endif
796    }
797   }
798
799   return current;
800 }
801
802 static int DirectFB_AllocHWSurface(_THIS, SDL_Surface *surface)
803 {
804   DFBResult             ret;
805   DFBSurfaceDescription dsc;
806
807   /*  fprintf(stderr, "SDL: DirectFB_AllocHWSurface (%dx%d@%d, flags: 0x%08x)\n",
808       surface->w, surface->h, surface->format->BitsPerPixel, surface->flags);*/
809
810   if (surface->w < 8 || surface->h < 8)
811     return -1;
812
813   /* fill surface description */
814   dsc.flags  = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
815   dsc.width  = surface->w;
816   dsc.height = surface->h;
817   dsc.caps   = (surface->flags & SDL_DOUBLEBUF) ? DSCAPS_FLIPPING : 0;
818
819   /* find the right pixelformat */
820   dsc.pixelformat = SDLToDFBPixelFormat (surface->format);
821   if (dsc.pixelformat == DSPF_UNKNOWN)
822     return -1;
823
824   /* Allocate the hardware acceleration data */
825   surface->hwdata = (struct private_hwdata *) SDL_calloc (1, sizeof(*surface->hwdata));
826   if (surface->hwdata == NULL)
827     {
828       SDL_OutOfMemory();
829       return -1;
830     }
831
832   /* Create the surface */
833   ret = HIDDEN->dfb->CreateSurface (HIDDEN->dfb, &dsc, &surface->hwdata->surface);
834   if (ret)
835     {
836       SetDirectFBerror ("dfb->CreateSurface", ret);
837       free (surface->hwdata);
838       surface->hwdata = NULL;
839       return -1;
840     }
841
842   surface->flags |= SDL_HWSURFACE | SDL_PREALLOC;
843
844   return 0;
845 }
846
847 static void DirectFB_FreeHWSurface(_THIS, SDL_Surface *surface)
848 {
849   if (surface->hwdata && HIDDEN->initialized)
850     {
851       surface->hwdata->surface->Release (surface->hwdata->surface);
852       free (surface->hwdata);
853       surface->hwdata = NULL;
854     }
855 }
856
857 static int DirectFB_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst)
858 {
859   /*  fprintf(stderr, "SDL: DirectFB_CheckHWBlit (src->hwdata: %p, dst->hwdata: %p)\n",
860       src->hwdata, dst->hwdata);*/
861
862   if (!src->hwdata || !dst->hwdata)
863     return 0;
864
865   src->flags |= SDL_HWACCEL;
866   src->map->hw_blit = DirectFB_HWAccelBlit;
867
868   return 1;
869 }
870
871 static int DirectFB_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
872                                 SDL_Surface *dst, SDL_Rect *dstrect)
873 {
874   DFBSurfaceBlittingFlags flags = DSBLIT_NOFX;
875
876   DFBRectangle sr = { srcrect->x, srcrect->y, srcrect->w, srcrect->h };
877   DFBRectangle dr = { dstrect->x, dstrect->y, dstrect->w, dstrect->h };
878
879   IDirectFBSurface *surface = dst->hwdata->surface;
880
881   if (src->flags & SDL_SRCCOLORKEY)
882     {
883       flags |= DSBLIT_SRC_COLORKEY;
884       DirectFB_SetHWColorKey (NULL, src, src->format->colorkey);
885     }
886
887   if (src->flags & SDL_SRCALPHA)
888     {
889       flags |= DSBLIT_BLEND_COLORALPHA;
890       surface->SetColor (surface, 0xff, 0xff, 0xff, src->format->alpha);
891     }
892
893   surface->SetBlittingFlags (surface, flags);
894
895   if (sr.w == dr.w && sr.h == dr.h)
896     surface->Blit (surface, src->hwdata->surface, &sr, dr.x, dr.y);
897   else
898     surface->StretchBlit (surface, src->hwdata->surface, &sr, &dr);
899
900   return 0;
901 }
902
903 static int DirectFB_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color)
904 {
905   SDL_PixelFormat  *fmt     = dst->format;
906   IDirectFBSurface *surface = dst->hwdata->surface;
907
908   /* ugly */
909   surface->SetColor (surface,
910                      (color & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
911                      (color & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
912                      (color & fmt->Bmask) << (fmt->Bloss - fmt->Bshift), 0xFF);
913   surface->FillRectangle (surface, dstrect->x, dstrect->y, dstrect->w, dstrect->h);
914
915   return 0;
916 }
917
918 static int DirectFB_SetHWColorKey(_THIS, SDL_Surface *src, Uint32 key)
919 {
920   SDL_PixelFormat  *fmt     = src->format;
921   IDirectFBSurface *surface = src->hwdata->surface;
922
923   if (fmt->BitsPerPixel == 8)
924     surface->SetSrcColorKeyIndex (surface, key);
925   else
926     /* ugly */
927     surface->SetSrcColorKey (surface,
928                              (key & fmt->Rmask) >> (fmt->Rshift - fmt->Rloss),
929                              (key & fmt->Gmask) >> (fmt->Gshift - fmt->Gloss),
930                              (key & fmt->Bmask) << (fmt->Bloss - fmt->Bshift));
931
932   return 0;
933 }
934
935 static int DirectFB_SetHWAlpha(_THIS, SDL_Surface *surface, Uint8 alpha)
936 {
937   return 0;
938 }
939
940 static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface)
941 {
942   if (HIDDEN->enable_mga_crtc2)
943     {
944        int rtn = surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, 0);
945        if (HIDDEN->mga_crtc2_stretch)
946          HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize);
947        else
948          HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
949      
950        HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
951        return rtn;
952     } 
953   else 
954      return surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, DSFLIP_WAITFORSYNC);
955 }
956
957 static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface)
958 {
959   DFBResult  ret;
960   void      *data;
961   int        pitch;
962
963   ret = surface->hwdata->surface->Lock (surface->hwdata->surface,
964                                         DSLF_WRITE, &data, &pitch);
965   if (ret)
966     {
967       SetDirectFBerror ("surface->Lock", ret);
968       return -1;
969     }
970
971   surface->pixels = data;
972   surface->pitch  = pitch;
973
974   return 0;
975 }
976
977 static void DirectFB_UnlockHWSurface(_THIS, SDL_Surface *surface)
978 {
979   surface->hwdata->surface->Unlock (surface->hwdata->surface);
980   surface->pixels = NULL;
981 }
982
983 static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
984 {
985   if (HIDDEN->enable_mga_crtc2)
986     {
987        if (HIDDEN->mga_crtc2_stretch)
988          HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, this->screen->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); 
989        else
990          HIDDEN->c2frame->Blit(HIDDEN->c2frame, this->screen->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 
991
992        HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
993     }
994 }
995
996 static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects)
997 {
998   DFBRegion         region;
999   int               i;
1000   int               region_valid = 0;
1001   IDirectFBSurface *surface = this->screen->hwdata->surface;
1002
1003   for (i=0; i<numrects; ++i)
1004     {
1005       int x2, y2;
1006
1007       if ( ! rects[i].w ) /* Clipped? */
1008         continue;
1009
1010       x2 = rects[i].x + rects[i].w - 1;
1011       y2 = rects[i].y + rects[i].h - 1;
1012
1013       if (region_valid)
1014         {
1015           if (rects[i].x < region.x1)
1016             region.x1 = rects[i].x;
1017
1018           if (rects[i].y < region.y1)
1019             region.y1 = rects[i].y;
1020
1021           if (x2 > region.x2)
1022             region.x2 = x2;
1023
1024           if (y2 > region.y2)
1025             region.y2 = y2;
1026         }
1027       else
1028         {
1029             region.x1 = rects[i].x;
1030             region.y1 = rects[i].y;
1031             region.x2 = x2;
1032             region.y2 = y2;
1033
1034             region_valid = 1;
1035         }
1036     }
1037
1038   if (region_valid)
1039     {
1040       if (HIDDEN->enable_mga_crtc2)
1041         {
1042           if (HIDDEN->mga_crtc2_stretch)
1043             HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize);
1044           else
1045             HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 
1046       
1047           HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
1048         }
1049       else 
1050         surface->Flip (surface, &region, DSFLIP_WAITFORSYNC);
1051     }
1052 }
1053
1054 int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
1055 {
1056   IDirectFBPalette *palette = this->screen->hwdata->palette;
1057
1058   if (!palette)
1059     return 0;
1060
1061   if (firstcolor > 255)
1062     return 0;
1063
1064   if (firstcolor + ncolors > 256)
1065     ncolors = 256 - firstcolor;
1066
1067   if (ncolors > 0)
1068     {
1069       int      i;
1070       DFBColor entries[ncolors];
1071
1072       for (i=0; i<ncolors; i++)
1073         {
1074           entries[i].a = 0xff;
1075           entries[i].r = colors[i].r;
1076           entries[i].g = colors[i].g;
1077           entries[i].b = colors[i].b;
1078         }
1079
1080       palette->SetEntries (palette, entries, ncolors, firstcolor);
1081     }
1082
1083   return 1;
1084 }
1085         
1086 void DirectFB_VideoQuit(_THIS)
1087 {
1088   struct DirectFBEnumRect *rect    = enumlist;
1089
1090   if (this->screen && this->screen->hwdata)
1091     {
1092       IDirectFBSurface        *surface = this->screen->hwdata->surface;
1093       IDirectFBPalette        *palette = this->screen->hwdata->palette;
1094
1095       if (palette)
1096         palette->Release (palette);
1097
1098       if (surface)
1099         surface->Release (surface);
1100
1101       this->screen->hwdata->surface = NULL;
1102       this->screen->hwdata->palette = NULL;
1103     }
1104
1105   if (HIDDEN->c2frame)
1106     {
1107       HIDDEN->c2frame->Release (HIDDEN->c2frame);
1108       HIDDEN->c2frame = NULL;
1109     }
1110
1111   if (HIDDEN->eventbuffer)
1112     {
1113       HIDDEN->eventbuffer->Release (HIDDEN->eventbuffer);
1114       HIDDEN->eventbuffer = NULL;
1115     }
1116
1117   if (HIDDEN->c2layer)
1118     {
1119       HIDDEN->c2layer->Release (HIDDEN->c2layer);
1120       HIDDEN->c2layer = NULL;
1121     }
1122
1123   if (HIDDEN->layer)
1124     {
1125       HIDDEN->layer->Release (HIDDEN->layer);
1126       HIDDEN->layer = NULL;
1127     }
1128
1129   if (HIDDEN->dfb)
1130     {
1131       HIDDEN->dfb->Release (HIDDEN->dfb);
1132       HIDDEN->dfb = NULL;
1133     }
1134
1135   /* Free video mode list */
1136   if (HIDDEN->modelist)
1137     {
1138       free (HIDDEN->modelist);
1139       HIDDEN->modelist = NULL;
1140     }
1141
1142   /* Free mode enumeration list */
1143   while (rect)
1144     {
1145       struct DirectFBEnumRect *next = rect->next;
1146       free (rect);
1147       rect = next;
1148     }
1149   enumlist = NULL;
1150
1151   HIDDEN->initialized = 0;
1152 }
1153
1154
1155 int DirectFB_ShowWMCursor(_THIS, WMcursor *cursor)
1156 {
1157   /* We can only hide or show the default cursor */
1158   if ( cursor == NULL )
1159     {
1160       HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0x00);
1161     }
1162     else
1163     {
1164       HIDDEN->layer->SetCursorOpacity(HIDDEN->layer, 0xFF);
1165     }
1166   return 1;
1167 }
1168
1169 void DirectFB_FinalQuit(void) 
1170 {
1171 }