st/mesa: fix format logic in compatible_src_dst_formats()
authorBrian Paul <brianp@vmware.com>
Wed, 20 Jan 2010 15:03:46 +0000 (08:03 -0700)
committerBrian Paul <brianp@vmware.com>
Wed, 20 Jan 2010 15:09:53 +0000 (08:09 -0700)
We need to consider the user-requested formats, not the actual device-
chosen formats.  See code comments for more details.

src/mesa/state_tracker/st_cb_texture.c

index e9c30cb5de5cca86f240c835aa99859c10516721..a0dc016b3340f3e417f0910e599d83de0bd72628 100644 (file)
@@ -31,6 +31,7 @@
 #include "main/convolve.h"
 #endif
 #include "main/enums.h"
+#include "main/fbobject.h"
 #include "main/formats.h"
 #include "main/image.h"
 #include "main/imports.h"
@@ -1352,33 +1353,64 @@ fallback_copy_texsubimage(GLcontext *ctx, GLenum target, GLint level,
 }
 
 
+
+/**
+ * If the format of the src renderbuffer and the format of the dest
+ * texture are compatible (in terms of blitting), return a TGSI writemask
+ * to be used during the blit.
+ * If the src/dest are incompatible, return 0.
+ */
 static unsigned
-compatible_src_dst_formats(const struct gl_renderbuffer *src,
+compatible_src_dst_formats(GLcontext *ctx,
+                           const struct gl_renderbuffer *src,
                            const struct gl_texture_image *dst)
 {
-   const GLenum srcFormat = _mesa_get_format_base_format(src->Format);
-   const GLenum dstLogicalFormat = _mesa_get_format_base_format(dst->TexFormat);
+   /* Get logical base formats for the src and dest.
+    * That is, use the user-requested formats and not the actual, device-
+    * chosen formats.
+    * For example, the user may have requested an A8 texture but the
+    * driver may actually be using an RGBA texture format.  When we
+    * copy/blit to that texture, we only want to copy the Alpha channel
+    * and not the RGB channels.
+    *
+    * Similarly, when the src FBO was created an RGB format may have been
+    * requested but the driver actually chose an RGBA format.  In that case,
+    * we don't want to copy the undefined Alpha channel to the dest texture
+    * (it should be 1.0).
+    */
+   const GLenum srcFormat = _mesa_base_fbo_format(ctx, src->InternalFormat);
+   const GLenum dstFormat = _mesa_base_tex_format(ctx, dst->InternalFormat);
 
-   if (srcFormat == dstLogicalFormat) {
+   /**
+    * XXX when we have red-only and red/green renderbuffers we'll need
+    * to add more cases here (or implement a general-purpose routine that
+    * queries the existance of the R,G,B,A channels in the src and dest).
+    */
+   if (srcFormat == dstFormat) {
       /* This is the same as matching_base_formats, which should
        * always pass, as it did previously.
        */
       return TGSI_WRITEMASK_XYZW;
    }
-   else if (srcFormat == GL_RGBA &&
-            dstLogicalFormat == GL_RGB) {
-      /* Add a single special case to cope with RGBA->RGB transfers,
-       * setting A to 1.0 to cope with situations where the RGB
-       * destination is actually stored as RGBA.
+   else if (srcFormat == GL_RGB && dstFormat == GL_RGBA) {
+      /* Make sure that A in the dest is 1.  The actual src format
+       * may be RGBA and have undefined A values.
+       */
+      return TGSI_WRITEMASK_XYZ;
+   }
+   else if (srcFormat == GL_RGBA && dstFormat == GL_RGB) {
+      /* Make sure that A in the dest is 1.  The actual dst format
+       * may be RGBA and will need A=1 to provide proper alpha values
+       * when sampled later.
        */
-      return TGSI_WRITEMASK_XYZ; /* A ==> 1.0 */
+      return TGSI_WRITEMASK_XYZ;
    }
    else {
       if (ST_DEBUG & DEBUG_FALLBACK)
          debug_printf("%s failed for src %s, dst %s\n",
                       __FUNCTION__, 
                       _mesa_lookup_enum_by_nr(srcFormat),
-                      _mesa_lookup_enum_by_nr(dstLogicalFormat));
+                      _mesa_lookup_enum_by_nr(dstFormat));
 
       /* Otherwise fail.
        */
@@ -1489,7 +1521,7 @@ st_copy_texsubimage(GLcontext *ctx,
    matching_base_formats =
       (_mesa_get_format_base_format(strb->Base.Format) ==
        _mesa_get_format_base_format(texImage->TexFormat));
-   format_writemask = compatible_src_dst_formats(&strb->Base, texImage);
+   format_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
 
    if (ctx->_ImageTransferState == 0x0) {