MGA CRTC2 support for DirectFB target contributed by Thomas Jarosch.
authorRyan C. Gordon <icculus@icculus.org>
Fri, 03 Oct 2003 18:26:39 +0000
changeset 728 5446a009107a
parent 727 cb1208fcd946
child 729 dac996d69abb
MGA CRTC2 support for DirectFB target contributed by Thomas Jarosch.
src/video/directfb/SDL_DirectFB_video.c
src/video/directfb/SDL_DirectFB_video.h
--- a/src/video/directfb/SDL_DirectFB_video.c	Wed Oct 01 07:52:33 2003 +0000
+++ b/src/video/directfb/SDL_DirectFB_video.c	Fri Oct 03 18:26:39 2003 +0000
@@ -18,6 +18,10 @@
 
 	Sam Lantinga
 	slouken@libsdl.org
+
+	MGA CRTC2 support by Thomas Jarosch - tomj@simonv.com
+	CRTC2 support is inspired by mplayer's dfbmga driver
+	written by Ville Syrj��<syrjala@sci.fi>
 */
 
 #ifdef SAVE_RCSID
@@ -372,6 +376,9 @@
   IDirectFBDisplayLayer   *layer  = NULL;
   IDirectFBEventBuffer    *events = NULL;
 
+  HIDDEN->c2layer = NULL, HIDDEN->c2frame = NULL;
+  HIDDEN->enable_mga_crtc2 = 0;
+  HIDDEN->mga_crtc2_stretch_overscan = 1;
 
   ret = DirectFBInit (NULL, NULL);
   if (ret)
@@ -449,12 +456,93 @@
   HIDDEN->layer       = layer;
   HIDDEN->eventbuffer = events;
 
+  if (getenv("SDL_DIRECTFB_MGA_CRTC2") != NULL)
+    HIDDEN->enable_mga_crtc2 = 1;
+  
+  if (HIDDEN->enable_mga_crtc2)
+    {
+      ret = dfb->GetDisplayLayer (dfb, 2, &HIDDEN->c2layer);
+      if (ret)
+        {
+          SetDirectFBerror ("dfb->GetDisplayLayer(CRTC2)", ret);
+          goto error;
+        }
+
+      ret = HIDDEN->layer->SetCooperativeLevel(HIDDEN->layer, DLSCL_EXCLUSIVE);
+      if (ret)
+        {
+          SetDirectFBerror ("layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
+          goto error;
+        }
+ 
+      ret = HIDDEN->c2layer->SetCooperativeLevel(HIDDEN->c2layer, DLSCL_EXCLUSIVE);
+      if (ret)
+        {
+          SetDirectFBerror ("c2layer->SetCooperativeLevel(CRTC2, EXCLUSIVE)", ret);
+          goto error;
+        }
+
+      HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0x0);
+
+      /* Init the surface here as it got a fixed size */
+      DFBDisplayLayerConfig      dlc;
+      DFBDisplayLayerConfigFlags failed;
+    
+      dlc.flags      = DLCONF_PIXELFORMAT | DLCONF_BUFFERMODE | DLCONF_OPTIONS;
+      dlc.buffermode = DLBM_BACKVIDEO;
+      dlc.options    = DLOP_FLICKER_FILTERING;
+      dlc.pixelformat = DSPF_RGB32;
+      
+      ret = HIDDEN->c2layer->TestConfiguration( HIDDEN->c2layer, &dlc, &failed );
+      if (ret)
+        {
+          SetDirectFBerror ("c2layer->TestConfiguration", ret);
+          goto error;
+        }
+    
+      ret = HIDDEN->c2layer->SetConfiguration( HIDDEN->c2layer, &dlc );
+      if (ret)
+        {
+          SetDirectFBerror ("c2layer->SetConfiguration", ret);
+          goto error;
+        }
+    
+      ret = HIDDEN->c2layer->GetSurface( HIDDEN->c2layer, &HIDDEN->c2frame );
+      if (ret)
+        {
+          SetDirectFBerror ("c2layer->GetSurface", ret);
+          goto error;
+        }
+
+      HIDDEN->c2framesize.x = 0;
+      HIDDEN->c2framesize.y = 0;
+      HIDDEN->c2frame->GetSize( HIDDEN->c2frame, &HIDDEN->c2framesize.w, &HIDDEN->c2framesize.h);
+
+      HIDDEN->c2frame->SetBlittingFlags( HIDDEN->c2frame, DSBLIT_NOFX );
+      HIDDEN->c2frame->SetColor( HIDDEN->c2frame, 0, 0, 0, 0xff );
+    
+      /* Clear CRTC2 */
+      HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
+      HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 );
+      HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
+      HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, 0 );
+      HIDDEN->c2frame->Clear(HIDDEN->c2frame, 0, 0, 0, 0xff );
+
+      HIDDEN->c2layer->SetOpacity(HIDDEN->c2layer, 0xFF );
+    }
+
   return 0;
 
  error:
   if (events)
     events->Release (events);
   
+  if (HIDDEN->c2frame)
+    HIDDEN->c2frame->Release (HIDDEN->c2frame);
+
+  if (HIDDEN->c2layer)
+    HIDDEN->c2layer->Release (HIDDEN->c2layer);
+
   if (layer)
     layer->Release (layer);
 
@@ -515,7 +603,7 @@
   if (flags & SDL_FULLSCREEN)
     {
       ret = HIDDEN->dfb->SetCooperativeLevel (HIDDEN->dfb, DFSCL_FULLSCREEN);
-      if (ret)
+      if (ret && !HIDDEN->enable_mga_crtc2)
         {
           DirectFBError ("dfb->SetCooperativeLevel", ret);
           flags &= ~SDL_FULLSCREEN;
@@ -589,6 +677,73 @@
 
   current->hwdata->surface = surface;
 
+  /* MGA CRTC2 stuff */
+  if (HIDDEN->enable_mga_crtc2)
+    {
+      /* no stretching if c2ssize == c2framesize */
+      HIDDEN->c2ssize.x = 0, HIDDEN->c2ssize.y = 0;
+      HIDDEN->c2ssize.w = width;
+      HIDDEN->c2ssize.h = height;
+
+      HIDDEN->c2dsize.x = 0, HIDDEN->c2dsize.y = 0;
+      HIDDEN->c2dsize.w = width;
+      HIDDEN->c2dsize.h = height;
+
+      HIDDEN->mga_crtc2_stretch = 0;
+
+      if (getenv("SDL_DIRECTFB_MGA_STRETCH") != NULL)
+        {
+          /* don't stretch slightly smaller/larger images */
+          if (width < HIDDEN->c2framesize.w*0.95 && height < HIDDEN->c2framesize.w*0.95)
+            {
+              while (HIDDEN->c2dsize.w < HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan && HIDDEN->c2dsize.h < HIDDEN->c2framesize.h*HIDDEN->mga_crtc2_stretch_overscan)
+                {
+                   HIDDEN->c2dsize.w+=4;
+                   HIDDEN->c2dsize.h+=3;
+                }
+
+              /* one step down */
+              HIDDEN->c2dsize.w-=4;
+              HIDDEN->c2dsize.h-=3;
+
+              #ifdef DIRECTFB_CRTC2_DEBUG
+              printf("Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
+              #endif
+
+              HIDDEN->mga_crtc2_stretch = 1;
+            } 
+          else if (width > HIDDEN->c2framesize.w*0.95 && height > HIDDEN->c2framesize.w*0.95)
+            {
+              while (HIDDEN->c2dsize.w > HIDDEN->c2framesize.w*HIDDEN->mga_crtc2_stretch_overscan || HIDDEN->c2dsize.h > HIDDEN->c2framesize.h*HIDDEN->mga_crtc2_stretch_overscan)
+                {
+                  HIDDEN->c2dsize.w-=4;
+                  HIDDEN->c2dsize.h-=3;
+                }
+              
+              #ifdef DIRECTFB_CRTC2_DEBUG
+              printf("Down-Stretched resolution: X: %d, Y: %d\n", HIDDEN->c2dsize.w, HIDDEN->c2dsize.h);
+              #endif
+
+              HIDDEN->mga_crtc2_stretch = 1;
+            }
+        }
+
+      /* Panning */
+      if (HIDDEN->c2framesize.w > HIDDEN->c2dsize.w)
+        HIDDEN->c2dsize.x = (HIDDEN->c2framesize.w - HIDDEN->c2dsize.w)  / 2;
+      else
+        HIDDEN->c2dsize.x = (HIDDEN->c2dsize.w - HIDDEN->c2framesize.w)  / 2;
+
+      if (HIDDEN->c2framesize.h > HIDDEN->c2dsize.h)
+        HIDDEN->c2dsize.y = (HIDDEN->c2framesize.h - HIDDEN->c2dsize.h)  / 2;
+      else
+        HIDDEN->c2dsize.y = (HIDDEN->c2dsize.h - HIDDEN->c2framesize.h)  / 2;
+
+      #ifdef DIRECTFB_CRTC2_DEBUG
+      printf("CTRC2 position X: %d, Y: %d\n", HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
+      #endif
+   }
+
   return current;
 }
 
@@ -732,7 +887,19 @@
 
 static int DirectFB_FlipHWSurface(_THIS, SDL_Surface *surface)
 {
-  return surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, DSFLIP_WAITFORSYNC);
+  if (HIDDEN->enable_mga_crtc2)
+    {
+       int rtn = surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, 0);
+       if (HIDDEN->mga_crtc2_stretch)
+         HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize);
+       else
+         HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y);
+     
+       HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
+       return rtn;
+    } 
+  else 
+     return surface->hwdata->surface->Flip (surface->hwdata->surface, NULL, DSFLIP_WAITFORSYNC);
 }
 
 static int DirectFB_LockHWSurface(_THIS, SDL_Surface *surface)
@@ -763,6 +930,15 @@
 
 static void DirectFB_DirectUpdate(_THIS, int numrects, SDL_Rect *rects)
 {
+  if (HIDDEN->enable_mga_crtc2)
+    {
+       if (HIDDEN->mga_crtc2_stretch)
+         HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, this->screen->hwdata->surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize); 
+       else
+         HIDDEN->c2frame->Blit(HIDDEN->c2frame, this->screen->hwdata->surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 
+
+       HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
+    }
 }
 
 static void DirectFB_WindowedUpdate(_THIS, int numrects, SDL_Rect *rects)
@@ -808,7 +984,19 @@
     }
 
   if (region_valid)
-    surface->Flip (surface, &region, DSFLIP_WAITFORSYNC);
+    {
+      if (HIDDEN->enable_mga_crtc2)
+        {
+          if (HIDDEN->mga_crtc2_stretch)
+            HIDDEN->c2frame->StretchBlit(HIDDEN->c2frame, surface, &HIDDEN->c2ssize, &HIDDEN->c2dsize);
+          else
+            HIDDEN->c2frame->Blit(HIDDEN->c2frame, surface, NULL, HIDDEN->c2dsize.x, HIDDEN->c2dsize.y); 
+      
+          HIDDEN->c2frame->Flip(HIDDEN->c2frame, NULL, DSFLIP_WAITFORSYNC);
+        }
+      else 
+        surface->Flip (surface, &region, DSFLIP_WAITFORSYNC);
+    }
 }
 
 int DirectFB_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors)
@@ -855,6 +1043,12 @@
   if (surface)
     surface->Release (surface);
 
+  if (HIDDEN->c2frame)
+    {
+      HIDDEN->c2frame->Release (HIDDEN->c2frame);
+      HIDDEN->c2frame = NULL;
+    }
+
   this->screen->hwdata->surface = NULL;
   this->screen->hwdata->palette = NULL;
 
@@ -864,6 +1058,12 @@
       HIDDEN->eventbuffer = NULL;
     }
 
+  if (HIDDEN->c2layer)
+    {
+      HIDDEN->c2layer->Release (HIDDEN->c2layer);
+      HIDDEN->c2layer = NULL;
+    }
+
   if (HIDDEN->layer)
     {
       HIDDEN->layer->Release (HIDDEN->layer);
--- a/src/video/directfb/SDL_DirectFB_video.h	Wed Oct 01 07:52:33 2003 +0000
+++ b/src/video/directfb/SDL_DirectFB_video.h	Fri Oct 03 18:26:39 2003 +0000
@@ -47,6 +47,16 @@
 
   int nummodes;
   SDL_Rect **modelist;
+
+  /* MGA CRTC2 support */
+  int enable_mga_crtc2;
+  int mga_crtc2_stretch;
+  float mga_crtc2_stretch_overscan;
+  IDirectFBDisplayLayer *c2layer;
+  IDirectFBSurface *c2frame;
+  DFBRectangle c2ssize;	/* Real screen size */
+  DFBRectangle c2dsize;	/* Stretched screen size */
+  DFBRectangle c2framesize;    /* CRTC2 screen size */
 };
 
 #define HIDDEN (this->hidden)