mesa: fix format checking when doing a multisample resolve
authorMarek Olšák <maraeo@gmail.com>
Sat, 21 Jul 2012 13:16:15 +0000 (15:16 +0200)
committerMarek Olšák <maraeo@gmail.com>
Mon, 23 Jul 2012 17:23:52 +0000 (19:23 +0200)
v2: make it more bullet-proof

Reviewed-by: Brian Paul <brianp@vmware.com>
src/mesa/main/fbobject.c

index 4370c7218c88bfb27c391f1b6a3df4955c90ee9c..ca43f810553e834d9de3698fc9c2be96c20fb0e7 100644 (file)
@@ -2632,6 +2632,116 @@ compatible_color_datatypes(gl_format srcFormat, gl_format dstFormat)
 }
 
 
+/**
+ * Return the equivalent non-generic internal format.
+ * This is useful for comparing whether two internal formats are semantically
+ * equivalent.
+ */
+static GLenum
+get_nongeneric_internalformat(GLenum format)
+{
+   switch (format) {
+      /* GL 1.1 formats. */
+      case 4:
+      case GL_RGBA:
+         return GL_RGBA8;
+
+      case 3:
+      case GL_RGB:
+         return GL_RGB8;
+
+      case 2:
+      case GL_LUMINANCE_ALPHA:
+         return GL_LUMINANCE8_ALPHA8;
+
+      case 1:
+      case GL_LUMINANCE:
+         return GL_LUMINANCE8;
+
+      case GL_ALPHA:
+         return GL_ALPHA8;
+
+      case GL_INTENSITY:
+         return GL_INTENSITY8;
+
+      /* GL_ARB_texture_rg */
+      case GL_RED:
+         return GL_R8;
+
+      case GL_RG:
+         return GL_RG8;
+
+      /* GL_EXT_texture_sRGB */
+      case GL_SRGB:
+         return GL_SRGB8;
+
+      case GL_SRGB_ALPHA:
+         return GL_SRGB8_ALPHA8;
+
+      case GL_SLUMINANCE:
+         return GL_SLUMINANCE8;
+
+      case GL_SLUMINANCE_ALPHA:
+         return GL_SLUMINANCE8_ALPHA8;
+
+      /* GL_EXT_texture_snorm */
+      case GL_RGBA_SNORM:
+         return GL_RGBA8_SNORM;
+
+      case GL_RGB_SNORM:
+         return GL_RGB8_SNORM;
+
+      case GL_RG_SNORM:
+         return GL_RG8_SNORM;
+
+      case GL_RED_SNORM:
+         return GL_R8_SNORM;
+
+      case GL_LUMINANCE_ALPHA_SNORM:
+         return GL_LUMINANCE8_ALPHA8_SNORM;
+
+      case GL_LUMINANCE_SNORM:
+         return GL_LUMINANCE8_SNORM;
+
+      case GL_ALPHA_SNORM:
+         return GL_ALPHA8_SNORM;
+
+      case GL_INTENSITY_SNORM:
+         return GL_INTENSITY8_SNORM;
+
+      default:
+         return format;
+   }
+}
+
+
+static GLboolean
+compatible_resolve_formats(const struct gl_renderbuffer *colorReadRb,
+                           const struct gl_renderbuffer *colorDrawRb)
+{
+   /* The simple case where we know the backing formats are the same.
+    */
+   if (colorReadRb->Format == colorDrawRb->Format) {
+      return GL_TRUE;
+   }
+
+   /* The Mesa formats are different, so we must check whether the internal
+    * formats are compatible.
+    *
+    * Under some circumstances, the user may request e.g. two GL_RGBA8
+    * textures and get two entirely different Mesa formats like RGBA8888 and
+    * ARGB8888. Drivers behaving like that should be able to cope with
+    * non-matching formats by themselves, because it's not the user's fault.
+    */
+   if (get_nongeneric_internalformat(colorReadRb->InternalFormat) ==
+       get_nongeneric_internalformat(colorDrawRb->InternalFormat)) {
+      return GL_TRUE;
+   }
+
+   return GL_FALSE;
+}
+
+
 /**
  * Blit rectangular region, optionally from one framebuffer to another.
  *
@@ -2798,7 +2908,7 @@ _mesa_BlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
       /* color formats must match */
       if (colorReadRb &&
           colorDrawRb &&
-          colorReadRb->Format != colorDrawRb->Format) {
+          !compatible_resolve_formats(colorReadRb, colorDrawRb)) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                 "glBlitFramebufferEXT(bad src/dst multisample pixel formats)");
          return;