diff src/video/directfb/SDL_DirectFB_render.c @ 2721:e82a0e3e9b0e

Date: Sun, 20 Jul 2008 22:34:37 +0200 From: Couriersud Subject: Updated DirectFB driver for SDL1.3 please find attached a patch for an updated directfb driver for SDL1.3. It does now - properly supported the new input api. - send unicode text events - support directfb windows - support multiple screens - support hardware YUV scaling for the first YUV texture created. - support hardware scaling for textures. - properly interpret streaming access - support software opengl if one manages to install the mesa directfb driver (broken/not broken in mesa svn) Within bugzilla (http://bugzilla.libsdl.org/show_bug.cgi?id=603) there is another patch which fixes a crash due to GL context creation. Kind regards, couriersud
author Sam Lantinga <slouken@libsdl.org>
date Tue, 26 Aug 2008 02:32:45 +0000
parents 5234868559fa
children 91f1706b27be
line wrap: on
line diff
--- a/src/video/directfb/SDL_DirectFB_render.c	Tue Aug 26 02:26:18 2008 +0000
+++ b/src/video/directfb/SDL_DirectFB_render.c	Tue Aug 26 02:32:45 2008 +0000
@@ -87,7 +87,8 @@
      (SDL_TEXTUREMODULATE_NONE | SDL_TEXTUREMODULATE_COLOR |
       SDL_TEXTUREMODULATE_ALPHA),
      (SDL_TEXTUREBLENDMODE_NONE | SDL_TEXTUREBLENDMODE_MASK |
-      SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_MOD),
+      SDL_TEXTUREBLENDMODE_BLEND | SDL_TEXTUREBLENDMODE_ADD |
+      SDL_TEXTUREBLENDMODE_MOD),
      (SDL_TEXTURESCALEMODE_NONE | SDL_TEXTURESCALEMODE_FAST),
      14,
      {
@@ -124,16 +125,9 @@
     void *pixels;
     int pitch;
     IDirectFBPalette *palette;
+    DFB_DisplayData *display;
 } DirectFB_TextureData;
 
-static void
-UpdateYUVTextureData(SDL_Texture * texture)
-{
-    /*
-     * Not needed - directfb supports yuv surfaces
-     */
-}
-
 void
 DirectFB_AddRenderDriver(_THIS)
 {
@@ -178,7 +172,7 @@
     renderer->DestroyTexture = DirectFB_DestroyTexture;
     renderer->DestroyRenderer = DirectFB_DestroyRenderer;
     renderer->info = DirectFB_RenderDriver.info;
-    renderer->window = window->id;      // SDL window id
+    renderer->window = window->id;      /* SDL window id */
     renderer->driverdata = data;
 
     renderer->info.flags =
@@ -200,7 +194,7 @@
     else
         renderer->info.flags |= SDL_RENDERER_SINGLEBUFFER;
 
-    data->isyuvdirect = 0;
+    data->isyuvdirect = 1;      /* default is on! */
     p = getenv("SDL_DIRECTFB_YUV_DIRECT");
     if (p)
         data->isyuvdirect = atoi(p);
@@ -293,6 +287,55 @@
 }
 
 static int
+DirectFB_AcquireVidLayer(SDL_Renderer * renderer, SDL_Texture * texture)
+{
+    SDL_DFB_RENDERERDATA(renderer);
+    SDL_Window *window = SDL_GetWindowFromID(renderer->window);
+    SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
+    SDL_DFB_DEVICEDATA(display->device);
+    DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
+    DirectFB_TextureData *data = texture->driverdata;
+    DFBDisplayLayerConfig layconf;
+    int ret;
+
+    if (renddata->isyuvdirect && (dispdata->vidID >= 0)
+        && (!dispdata->vidIDinuse)
+        && SDL_ISPIXELFORMAT_FOURCC(data->format)) {
+        layconf.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT;
+        layconf.width = texture->w;
+        layconf.height = texture->h;
+        layconf.pixelformat = SDLToDFBPixelFormat(data->format);
+
+        SDL_DFB_CHECKERR(devdata->dfb->
+                         GetDisplayLayer(devdata->dfb, dispdata->vidID,
+                                         &data->vidlayer));
+        SDL_DFB_CHECKERR(data->vidlayer->
+                         SetCooperativeLevel(data->vidlayer,
+                                             DLSCL_EXCLUSIVE));
+        SDL_DFB_CHECKERR(data->vidlayer->
+                         SetConfiguration(data->vidlayer, &layconf));
+        SDL_DFB_CHECKERR(data->vidlayer->
+                         GetSurface(data->vidlayer, &data->surface));
+        //SDL_DFB_CHECKERR(data->vidlayer->GetDescription(data->vidlayer, laydsc));
+        dispdata->vidIDinuse = 1;
+        data->display = dispdata;
+        SDL_DFB_DEBUG("Created HW YUV surface\n");
+
+        return 0;
+    }
+    return 1;
+  error:
+    if (data->vidlayer) {
+        SDL_DFB_RELEASE(data->surface);
+        SDL_DFB_CHECKERR(data->vidlayer->
+                         SetCooperativeLevel(data->vidlayer,
+                                             DLSCL_ADMINISTRATIVE));
+        SDL_DFB_RELEASE(data->vidlayer);
+    }
+    return 1;
+}
+
+static int
 DirectFB_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
 {
     SDL_DFB_RENDERERDATA(renderer);
@@ -300,7 +343,6 @@
     SDL_DFB_WINDOWDATA(window);
     SDL_VideoDisplay *display = SDL_GetDisplayFromWindow(window);
     SDL_DFB_DEVICEDATA(display->device);
-    DFB_DisplayData *dispdata = (DFB_DisplayData *) display->driverdata;
     DirectFB_TextureData *data;
     DFBResult ret;
     DFBSurfaceDescription dsc;
@@ -313,37 +355,23 @@
     data->format = texture->format;
     data->pitch = (texture->w * SDL_BYTESPERPIXEL(data->format));
     data->vidlayer = NULL;
-    if (renddata->isyuvdirect && (dispdata->vidID >= 0)
-        && SDL_ISPIXELFORMAT_FOURCC(data->format)) {
-        SDL_DFB_CHECKERR(devdata->dfb->
-                         GetDisplayLayer(devdata->dfb, dispdata->vidID,
-                                         &data->vidlayer));
-        layconf.flags = DLCONF_WIDTH | DLCONF_HEIGHT | DLCONF_PIXELFORMAT;
-        layconf.width = texture->w;
-        layconf.height = texture->h;
-        layconf.pixelformat = SDLToDFBPixelFormat(data->format);
 
-        SDL_DFB_CHECKERR(data->vidlayer->
-                         SetCooperativeLevel(data->vidlayer,
-                                             DLSCL_EXCLUSIVE));
-        SDL_DFB_CHECKERR(data->vidlayer->
-                         SetConfiguration(data->vidlayer, &layconf));
-        SDL_DFB_CHECKERR(data->vidlayer->
-                         GetSurface(data->vidlayer, &data->surface));
-        SDL_DFB_CHECKERR(data->vidlayer->
-                         GetDescription(data->vidlayer, &laydsc));
-        SDL_DFB_DEBUG("Created HW YUV surface\n");
-    }
-    if (!data->vidlayer) {
+    if (DirectFB_AcquireVidLayer(renderer, texture) != 0) {
         /* fill surface description */
         dsc.flags =
             DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT | DSDESC_CAPS;
         dsc.width = texture->w;
         dsc.height = texture->h;
-        /* Never use DSCAPS_VIDEOONLY here. It kills performance
+        /* <1.2 Never use DSCAPS_VIDEOONLY here. It kills performance
          * No DSCAPS_SYSTEMONLY either - let dfb decide
+         * 1.2: DSCAPS_SYSTEMONLY boosts performance by factor ~8
          */
-        dsc.caps = 0;           //DSCAPS_PREMULTIPLIED;
+        dsc.caps = DSCAPS_PREMULTIPLIED;
+
+        if (texture->access == SDL_TEXTUREACCESS_STREAMING)
+            dsc.caps |= DSCAPS_SYSTEMONLY;
+        else
+            dsc.caps |= DSCAPS_VIDEOONLY;
 
         /* find the right pixelformat */
 
@@ -469,6 +497,7 @@
     case SDL_TEXTUREBLENDMODE_NONE:
     case SDL_TEXTUREBLENDMODE_MASK:
     case SDL_TEXTUREBLENDMODE_BLEND:
+    case SDL_TEXTUREBLENDMODE_ADD:
     case SDL_TEXTUREBLENDMODE_MOD:
         return 0;
     default:
@@ -513,8 +542,8 @@
     size_t length;
 
     SDL_DFB_CHECKERR(data->surface->Lock(data->surface,
-                                         DSLF_WRITE | DSLF_READ, &dpixels,
-                                         &dpitch));
+                                         DSLF_WRITE | DSLF_READ,
+                                         ((void **) &dpixels), &dpitch));
     src = (Uint8 *) pixels;
     dst =
         (Uint8 *) dpixels + rect->y * dpitch +
@@ -648,27 +677,52 @@
         if (texture->
             modMode & (SDL_TEXTUREMODULATE_COLOR | SDL_TEXTUREMODULATE_ALPHA))
         {
-            u8 alpha = 0xFF;
-            if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA)
+            Uint8 alpha = 0xFF;
+            if (texture->modMode & SDL_TEXTUREMODULATE_ALPHA) {
                 alpha = texture->a;
-            if (texture->modMode & SDL_TEXTUREMODULATE_COLOR)
+                flags |= DSBLIT_SRC_PREMULTCOLOR;
+                SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, 0xFF,
+                                                         0xFF, 0xFF, alpha));
+            }
+            if (texture->modMode & SDL_TEXTUREMODULATE_COLOR) {
                 SDL_DFB_CHECKERR(data->surface->
                                  SetColor(data->surface, texture->r,
                                           texture->g, texture->b, alpha));
-            else
-                SDL_DFB_CHECKERR(data->surface->SetColor(data->surface, 0xFF,
-                                                         0xFF, 0xFF, alpha));
-            // Only works together ....
-            flags |= DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR;
+                /* Only works together .... */
+                flags |= DSBLIT_COLORIZE | DSBLIT_SRC_PREMULTCOLOR;
+            }
         }
 
-        if (texture->
-            blendMode & (SDL_TEXTUREBLENDMODE_MASK |
-                         SDL_TEXTUREBLENDMODE_BLEND)) {
+        switch (texture->blendMode) {
+        case SDL_TEXTUREBLENDMODE_NONE: /**< No blending */
+            flags |= DSBLIT_NOFX;
+            data->surface->SetSrcBlendFunction(data->surface, DSBF_ONE);
+            data->surface->SetDstBlendFunction(data->surface, DSBF_ZERO);
+            break;
+        case SDL_TEXTUREBLENDMODE_MASK: /**< dst = A ? src : dst (alpha is mask) */
+            flags |= DSBLIT_BLEND_ALPHACHANNEL;
+            data->surface->SetSrcBlendFunction(data->surface, DSBF_SRCALPHA);
+            data->surface->SetDstBlendFunction(data->surface,
+                                               DSBF_INVSRCALPHA);
+            break;
+        case SDL_TEXTUREBLENDMODE_BLEND:/**< dst = (src * A) + (dst * (1-A)) */
             flags |= DSBLIT_BLEND_ALPHACHANNEL;
-        } else {
-            flags |= DSBLIT_NOFX;
+            data->surface->SetSrcBlendFunction(data->surface, DSBF_SRCALPHA);
+            data->surface->SetDstBlendFunction(data->surface,
+                                               DSBF_INVSRCALPHA);
+            break;
+        case SDL_TEXTUREBLENDMODE_ADD:  /**< dst = (src * A) + dst */
+            flags |= DSBLIT_BLEND_ALPHACHANNEL;
+            data->surface->SetSrcBlendFunction(data->surface, DSBF_SRCALPHA);
+            data->surface->SetDstBlendFunction(data->surface, DSBF_ONE);
+            break;
+        case SDL_TEXTUREBLENDMODE_MOD:  /**< dst = src * dst */
+            flags |= DSBLIT_BLEND_ALPHACHANNEL;
+            data->surface->SetSrcBlendFunction(data->surface, DSBF_DESTCOLOR);
+            data->surface->SetDstBlendFunction(data->surface, DSBF_ZERO);
+            break;
         }
+
         SDL_DFB_CHECKERR(data->surface->
                          SetBlittingFlags(data->surface, flags));
         if (srcrect->w == dstrect->w && srcrect->h == dstrect->h) {
@@ -720,6 +774,11 @@
     }
     SDL_DFB_RELEASE(data->palette);
     SDL_DFB_RELEASE(data->surface);
+    if (data->display) {
+        data->display->vidIDinuse = 0;
+        data->vidlayer->SetCooperativeLevel(data->vidlayer,
+                                            DLSCL_ADMINISTRATIVE);
+    }
     SDL_DFB_RELEASE(data->vidlayer);
     SDL_free(data);
     texture->driverdata = NULL;