Fix DRI2 accelerated EXT_texture_from_pixmap with GL_RGB format.
authorEric Anholt <eric@anholt.net>
Wed, 18 Mar 2009 19:07:09 +0000 (12:07 -0700)
committerEric Anholt <eric@anholt.net>
Fri, 20 Mar 2009 17:41:28 +0000 (10:41 -0700)
This requires upgrading the interface so that the argument to
glXBindTexImageEXT isn't just dropped on the floor.  Note that this only
fixes the accelerated path on Intel, as Mesa's texture format support is
missing x8r8g8b8 support (right now, GL_RGB textures get uploaded as a8r8gb8,
but in this case we're not doing the upload so we can't really work around it
that way).

Fixes bugs with compositors trying to use shaders that use alpha channels, on
windows without a valid alpha channel.  Bug #19910 and likely others as well.

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>

include/GL/internal/dri_interface.h
include/GL/internal/glcore.h
src/glx/x11/glx_pbuffer.c
src/glx/x11/glxclient.h
src/glx/x11/glxcmds.c
src/mesa/drivers/dri/i915/i830_texstate.c
src/mesa/drivers/dri/i915/i915_texstate.c
src/mesa/drivers/dri/i965/brw_wm_surface_state.c
src/mesa/drivers/dri/intel/intel_screen.c
src/mesa/drivers/dri/intel/intel_tex.h
src/mesa/drivers/dri/intel/intel_tex_image.c

index a726b932340090f328d8c1e5f0623282937682a0..a83602bfd87a20d9d6dbf7aabc2592934a1633c7 100644 (file)
@@ -231,7 +231,7 @@ struct __DRItexOffsetExtensionRec {
 
 
 #define __DRI_TEX_BUFFER "DRI_TexBuffer"
-#define __DRI_TEX_BUFFER_VERSION 1
+#define __DRI_TEX_BUFFER_VERSION 2
 struct __DRItexBufferExtensionRec {
     __DRIextension base;
 
@@ -239,11 +239,23 @@ struct __DRItexBufferExtensionRec {
      * Method to override base texture image with the contents of a
      * __DRIdrawable. 
      *
-     * For GLX_EXT_texture_from_pixmap with AIGLX.
+     * For GLX_EXT_texture_from_pixmap with AIGLX.  Deprecated in favor of
+     * setTexBuffer2 in version 2 of this interface
      */
     void (*setTexBuffer)(__DRIcontext *pDRICtx,
                         GLint target,
                         __DRIdrawable *pDraw);
+
+    /**
+     * Method to override base texture image with the contents of a
+     * __DRIdrawable, including the required texture format attribute.
+     *
+     * For GLX_EXT_texture_from_pixmap with AIGLX.
+     */
+    void (*setTexBuffer2)(__DRIcontext *pDRICtx,
+                         GLint target,
+                         GLint format,
+                         __DRIdrawable *pDraw);
 };
 
 /**
index 547b1113707e231e771b82d87b42bed39fc56ccb..18f657662af973b836e905d833727b62c65e5fd4 100644 (file)
@@ -178,4 +178,8 @@ typedef struct __GLcontextModesRec {
 #define GLX_TEXTURE_2D_BIT_EXT             0x00000002
 #define GLX_TEXTURE_RECTANGLE_BIT_EXT      0x00000004
 
+#define GLX_TEXTURE_FORMAT_NONE_EXT        0x20D8
+#define GLX_TEXTURE_FORMAT_RGB_EXT         0x20D9
+#define GLX_TEXTURE_FORMAT_RGBA_EXT        0x20DA
+
 #endif /* __gl_core_h_ */
index a602cd288176cf9535f513da56924895cdc49d8d..6bcf965056a7aabfc5757ec82c61fe1237cd15d6 100644 (file)
@@ -189,6 +189,21 @@ determineTextureTarget(const int *attribs, int numAttribs)
 
    return target;
 }
+
+
+static GLenum
+determineTextureFormat(const int *attribs, int numAttribs)
+{
+   GLenum target = 0;
+   int i;
+
+   for (i = 0; i < numAttribs; i++) {
+      if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT)
+        return attribs[2 * i + 1];
+   }
+
+   return 0;
+}
 #endif
 
 /**
@@ -294,6 +309,9 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable,
             if (pdraw != NULL && !pdraw->textureTarget)
                pdraw->textureTarget =
                   determineTextureTarget((const int *) data, num_attributes);
+            if (pdraw != NULL && !pdraw->textureFormat)
+               pdraw->textureFormat =
+                  determineTextureFormat((const int *) data, num_attributes);
          }
 #endif
 
@@ -374,6 +392,7 @@ CreateDrawable(Display * dpy, const __GLcontextModes * fbconfig,
       }
 
       pdraw->textureTarget = determineTextureTarget(attrib_list, i);
+      pdraw->textureFormat = determineTextureFormat(attrib_list, i);
    } while (0);
 #endif
 
index caf58bbd44a005b2858ec9198bf789e829f30ff9..c42e80a0e868d7656397fe132caebd54018e209a 100644 (file)
@@ -161,6 +161,7 @@ struct __GLXDRIdrawableRec {
     __GLXscreenConfigs *psc;
     GLenum textureTarget;
     __DRIdrawable *driDrawable;
+    GLenum textureFormat; /* EXT_texture_from_pixmap support */
 };
 
 /*
index fc0e593cb35bfbd3e0433a0c74085764e66261d7..e5c0db4c968dec65a98713f214521472dd6c799f 100644 (file)
@@ -2631,11 +2631,19 @@ static void __glXBindTexImageEXT(Display *dpy,
     if (gc->driContext) {
        __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL);
 
-       if (pdraw != NULL)
-           (*pdraw->psc->texBuffer->setTexBuffer)(gc->__driContext,
-                                                  pdraw->textureTarget,
-                                                  pdraw->driDrawable);
-
+       if (pdraw != NULL) {
+           if (pdraw->psc->texBuffer->base.version >= 2 &&
+               pdraw->psc->texBuffer->setTexBuffer2 != NULL) {
+               (*pdraw->psc->texBuffer->setTexBuffer2)(gc->__driContext,
+                                                       pdraw->textureTarget,
+                                                       pdraw->textureFormat,
+                                                       pdraw->driDrawable);
+           } else {
+               (*pdraw->psc->texBuffer->setTexBuffer)(gc->__driContext,
+                                                      pdraw->textureTarget,
+                                                      pdraw->driDrawable);
+           }
+       }
        return;
     }
 #endif
index c718bb0055da5e3e99c10dc542c632da016b7704..df43b779a79f3e64e7eab5e010c99248ef3f0c80 100644 (file)
@@ -38,7 +38,7 @@
 
 
 static GLuint
-translate_texture_format(GLuint mesa_format)
+translate_texture_format(GLuint mesa_format, GLuint internal_format)
 {
    switch (mesa_format) {
    case MESA_FORMAT_L8:
@@ -56,7 +56,10 @@ translate_texture_format(GLuint mesa_format)
    case MESA_FORMAT_ARGB4444:
       return MAPSURF_16BIT | MT_16BIT_ARGB4444;
    case MESA_FORMAT_ARGB8888:
-      return MAPSURF_32BIT | MT_32BIT_ARGB8888;
+      if (internal_format == GL_RGB)
+        return MAPSURF_32BIT | MT_32BIT_XRGB8888;
+      else
+        return MAPSURF_32BIT | MT_32BIT_ARGB8888;
    case MESA_FORMAT_YCBCR_REV:
       return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
    case MESA_FORMAT_YCBCR:
@@ -162,7 +165,8 @@ i830_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
                                                                0, intelObj->
                                                                firstLevel);
 
-      format = translate_texture_format(firstImage->TexFormat->MesaFormat);
+      format = translate_texture_format(firstImage->TexFormat->MesaFormat,
+                                       firstImage->InternalFormat);
       pitch = intelObj->mt->pitch * intelObj->mt->cpp;
    }
 
index adbb52a3a3b2c7a5a192523277636532ac0c3501..6d25f8dd8ef75a70d45b6570c7024ce4e532dc15 100644 (file)
@@ -37,7 +37,8 @@
 
 
 static GLuint
-translate_texture_format(GLuint mesa_format, GLenum DepthMode)
+translate_texture_format(GLuint mesa_format, GLuint internal_format,
+                        GLenum DepthMode)
 {
    switch (mesa_format) {
    case MESA_FORMAT_L8:
@@ -55,7 +56,10 @@ translate_texture_format(GLuint mesa_format, GLenum DepthMode)
    case MESA_FORMAT_ARGB4444:
       return MAPSURF_16BIT | MT_16BIT_ARGB4444;
    case MESA_FORMAT_ARGB8888:
-      return MAPSURF_32BIT | MT_32BIT_ARGB8888;
+      if (internal_format == GL_RGB)
+        return MAPSURF_32BIT | MT_32BIT_XRGB8888;
+      else
+        return MAPSURF_32BIT | MT_32BIT_ARGB8888;
    case MESA_FORMAT_YCBCR_REV:
       return (MAPSURF_422 | MT_422_YCRCB_NORMAL);
    case MESA_FORMAT_YCBCR:
@@ -173,7 +177,8 @@ i915_update_tex_unit(struct intel_context *intel, GLuint unit, GLuint ss3)
                                                                 firstLevel);
 
       format = translate_texture_format(firstImage->TexFormat->MesaFormat, 
-               tObj->DepthMode);
+                                       firstImage->InternalFormat,
+                                       tObj->DepthMode);
       pitch = intelObj->mt->pitch * intelObj->mt->cpp;
    }
 
index 9b320480b6d0411862f569230c008ba8362585da..e6113eff87e0703831d6c8769f11c0cd0f310bf9 100644 (file)
@@ -69,7 +69,8 @@ static GLuint translate_tex_target( GLenum target )
 }
 
 
-static GLuint translate_tex_format( GLuint mesa_format, GLenum depth_mode )
+static GLuint translate_tex_format( GLuint mesa_format, GLenum internal_format,
+                                   GLenum depth_mode )
 {
    switch( mesa_format ) {
    case MESA_FORMAT_L8:
@@ -89,10 +90,16 @@ static GLuint translate_tex_format( GLuint mesa_format, GLenum depth_mode )
       return BRW_SURFACEFORMAT_R8G8B8_UNORM;      
 
    case MESA_FORMAT_ARGB8888:
-      return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
+      if (internal_format == GL_RGB)
+        return BRW_SURFACEFORMAT_B8G8R8X8_UNORM;
+      else
+        return BRW_SURFACEFORMAT_B8G8R8A8_UNORM;
 
    case MESA_FORMAT_RGBA8888_REV:
-      return BRW_SURFACEFORMAT_R8G8B8A8_UNORM;
+      if (internal_format == GL_RGB)
+        return BRW_SURFACEFORMAT_R8G8B8X8_UNORM;
+      else
+        return BRW_SURFACEFORMAT_R8G8B8A8_UNORM;
 
    case MESA_FORMAT_RGB565:
       return BRW_SURFACEFORMAT_B5G6R5_UNORM;
@@ -161,7 +168,7 @@ static GLuint translate_tex_format( GLuint mesa_format, GLenum depth_mode )
 struct brw_wm_surface_key {
    GLenum target, depthmode;
    dri_bo *bo;
-   GLint format;
+   GLint format, internal_format;
    GLint first_level, last_level;
    GLint width, height, depth;
    GLint pitch, cpp;
@@ -199,9 +206,11 @@ brw_create_texture_surface( struct brw_context *brw,
 
    surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
    surf.ss0.surface_type = translate_tex_target(key->target);
-
-   if (key->bo) 
-      surf.ss0.surface_format = translate_tex_format(key->format, key->depthmode);
+   if (key->bo) {
+      surf.ss0.surface_format = translate_tex_format(key->format,
+                                                    key->internal_format,
+                                                    key->depthmode);
+   }
    else {
       switch (key->depth) {
       case 32:
@@ -278,6 +287,7 @@ brw_update_texture_surface( GLcontext *ctx, GLuint unit )
       key.offset = intelObj->textureOffset;
    } else {
       key.format = firstImage->TexFormat->MesaFormat;
+      key.internal_format = firstImage->InternalFormat;
       key.pitch = intelObj->mt->pitch;
       key.depth = firstImage->Depth;
       key.bo = intelObj->mt->region->buffer;
index e8c074712cd759f7bd6b7767abc9dc91654f614d..d20ea15187790b51b39d812c4488fb4a17e26fb5 100644 (file)
@@ -211,6 +211,7 @@ static const __DRItexOffsetExtension intelTexOffsetExtension = {
 static const __DRItexBufferExtension intelTexBufferExtension = {
     { __DRI_TEX_BUFFER, __DRI_TEX_BUFFER_VERSION },
    intelSetTexBuffer,
+   intelSetTexBuffer2,
 };
 
 static const __DRIextension *intelScreenExtensions[] = {
index 742ccc043aa7990de97f9a32c8ce996c0477a067..f5372d82fb2ce0004e21aa78376d7e249691e172 100644 (file)
@@ -149,6 +149,8 @@ void intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname,
                       unsigned long long offset, GLint depth, GLuint pitch);
 void intelSetTexBuffer(__DRIcontext *pDRICtx,
                       GLint target, __DRIdrawable *pDraw);
+void intelSetTexBuffer2(__DRIcontext *pDRICtx,
+                       GLint target, GLint format, __DRIdrawable *pDraw);
 
 GLuint intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit);
 
index 943636c37b241daf682f535144c08685ce18cdc6..e902187637d9ad39290be0d98b658e5064dacce1 100644 (file)
@@ -714,7 +714,9 @@ intelSetTexOffset(__DRIcontext *pDRICtx, GLint texname,
 }
 
 void
-intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
+intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target,
+                  GLint glx_texture_format,
+                  __DRIdrawable *dPriv)
 {
    struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
    struct intel_context *intel = pDRICtx->driverPrivate;
@@ -745,7 +747,10 @@ intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
 
    type = GL_BGRA;
    format = GL_UNSIGNED_BYTE;
-   internalFormat = (rb->region->cpp == 3 ? 3 : 4);
+   if (glx_texture_format == GLX_TEXTURE_FORMAT_RGB_EXT)
+      internalFormat = GL_RGB;
+   else
+      internalFormat = GL_RGBA;
 
    mt = intel_miptree_create_for_region(intel, target,
                                        internalFormat,
@@ -785,3 +790,12 @@ intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
 
    _mesa_unlock_texture(&intel->ctx, texObj);
 }
+
+void
+intelSetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
+{
+   /* The old interface didn't have the format argument, so copy our
+    * implementation's behavior at the time.
+    */
+   intelSetTexBuffer2(pDRICtx, target, GLX_TEXTURE_FORMAT_RGBA_EXT, dPriv);
+}