From 66175aac7609ad314f25fbdff0d3958af310dc24 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Wed, 18 Mar 2009 12:07:09 -0700 Subject: [PATCH] Fix DRI2 accelerated EXT_texture_from_pixmap with GL_RGB format. 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 --- include/GL/internal/dri_interface.h | 16 +++++++++++-- include/GL/internal/glcore.h | 4 ++++ src/glx/x11/glx_pbuffer.c | 19 +++++++++++++++ src/glx/x11/glxclient.h | 1 + src/glx/x11/glxcmds.c | 18 ++++++++++---- src/mesa/drivers/dri/i915/i830_texstate.c | 10 +++++--- src/mesa/drivers/dri/i915/i915_texstate.c | 11 ++++++--- .../drivers/dri/i965/brw_wm_surface_state.c | 24 +++++++++++++------ src/mesa/drivers/dri/intel/intel_screen.c | 1 + src/mesa/drivers/dri/intel/intel_tex.h | 2 ++ src/mesa/drivers/dri/intel/intel_tex_image.c | 18 ++++++++++++-- 11 files changed, 102 insertions(+), 22 deletions(-) diff --git a/include/GL/internal/dri_interface.h b/include/GL/internal/dri_interface.h index a726b932340..a83602bfd87 100644 --- a/include/GL/internal/dri_interface.h +++ b/include/GL/internal/dri_interface.h @@ -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); }; /** diff --git a/include/GL/internal/glcore.h b/include/GL/internal/glcore.h index 547b1113707..18f657662af 100644 --- a/include/GL/internal/glcore.h +++ b/include/GL/internal/glcore.h @@ -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_ */ diff --git a/src/glx/x11/glx_pbuffer.c b/src/glx/x11/glx_pbuffer.c index a602cd28817..6bcf965056a 100644 --- a/src/glx/x11/glx_pbuffer.c +++ b/src/glx/x11/glx_pbuffer.c @@ -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 diff --git a/src/glx/x11/glxclient.h b/src/glx/x11/glxclient.h index caf58bbd44a..c42e80a0e86 100644 --- a/src/glx/x11/glxclient.h +++ b/src/glx/x11/glxclient.h @@ -161,6 +161,7 @@ struct __GLXDRIdrawableRec { __GLXscreenConfigs *psc; GLenum textureTarget; __DRIdrawable *driDrawable; + GLenum textureFormat; /* EXT_texture_from_pixmap support */ }; /* diff --git a/src/glx/x11/glxcmds.c b/src/glx/x11/glxcmds.c index fc0e593cb35..e5c0db4c968 100644 --- a/src/glx/x11/glxcmds.c +++ b/src/glx/x11/glxcmds.c @@ -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 diff --git a/src/mesa/drivers/dri/i915/i830_texstate.c b/src/mesa/drivers/dri/i915/i830_texstate.c index c718bb0055d..df43b779a79 100644 --- a/src/mesa/drivers/dri/i915/i830_texstate.c +++ b/src/mesa/drivers/dri/i915/i830_texstate.c @@ -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; } diff --git a/src/mesa/drivers/dri/i915/i915_texstate.c b/src/mesa/drivers/dri/i915/i915_texstate.c index adbb52a3a3b..6d25f8dd8ef 100644 --- a/src/mesa/drivers/dri/i915/i915_texstate.c +++ b/src/mesa/drivers/dri/i915/i915_texstate.c @@ -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; } diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c index 9b320480b6d..e6113eff87e 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -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; diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index e8c074712cd..d20ea151877 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -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[] = { diff --git a/src/mesa/drivers/dri/intel/intel_tex.h b/src/mesa/drivers/dri/intel/intel_tex.h index 742ccc043aa..f5372d82fb2 100644 --- a/src/mesa/drivers/dri/intel/intel_tex.h +++ b/src/mesa/drivers/dri/intel/intel_tex.h @@ -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); diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index 943636c37b2..e902187637d 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -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); +} -- 2.30.2