r300g: add support for all missing non-FP sampler formats
authorMarek Olšák <maraeo@gmail.com>
Wed, 17 Feb 2010 23:18:23 +0000 (00:18 +0100)
committerMarek Olšák <maraeo@gmail.com>
Thu, 18 Feb 2010 05:37:43 +0000 (06:37 +0100)
The idea is to directly parse the format description in
r300_translate_texformat and return ~0 if the format is unsupported.

src/gallium/drivers/r300/r300_screen.c
src/gallium/drivers/r300/r300_state_inlines.h
src/gallium/drivers/r300/r300_texture.h

index b892c084c04e17ea2e8bb316a9f64b2767ccbe2f..5fa1ea0850ecb7cb5dc8a930ac219fcdd645b410 100644 (file)
@@ -210,6 +210,8 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
 {
     uint32_t retval = 0;
     boolean is_r500 = r300_screen(screen)->caps->is_r500;
+    boolean is_z24 = format == PIPE_FORMAT_Z24X8_UNORM ||
+                     format == PIPE_FORMAT_Z24S8_UNORM;
 
     if (target >= PIPE_MAX_TEXTURE_TYPES) {
         debug_printf("r300: Implementation error: Received bogus texture "
@@ -217,32 +219,18 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
         return FALSE;
     }
 
+    /* Check sampler format support. */
+    if ((usage & PIPE_TEXTURE_USAGE_SAMPLER) &&
+        (is_r500 || !is_z24) && /* Z24 cannot be sampled from on non-r5xx. */
+        r300_translate_texformat(format) != ~0) {
+        retval |= PIPE_TEXTURE_USAGE_SAMPLER;
+    }
+
     switch (format) {
         /* Supported formats. */
         /* Colorbuffer */
         case PIPE_FORMAT_A8_UNORM:
         case PIPE_FORMAT_L8_UNORM:
-            retval = usage &
-                (PIPE_TEXTURE_USAGE_RENDER_TARGET |
-                 PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
-                 PIPE_TEXTURE_USAGE_PRIMARY);
-            break;
-
-        /* Texture */
-        case PIPE_FORMAT_A8R8G8B8_SRGB:
-        case PIPE_FORMAT_R8G8B8A8_SRGB:
-        case PIPE_FORMAT_DXT1_RGB:
-        case PIPE_FORMAT_DXT1_RGBA:
-        case PIPE_FORMAT_DXT3_RGBA:
-        case PIPE_FORMAT_DXT5_RGBA:
-        case PIPE_FORMAT_YCBCR:
-        case PIPE_FORMAT_L8_SRGB:
-        case PIPE_FORMAT_A8L8_SRGB:
-        case PIPE_FORMAT_A8L8_UNORM:
-            retval = usage & PIPE_TEXTURE_USAGE_SAMPLER;
-            break;
-
-        /* Colorbuffer or texture */
         case PIPE_FORMAT_R5G6B5_UNORM:
         case PIPE_FORMAT_A1R5G5B5_UNORM:
         case PIPE_FORMAT_A4R4G4B4_UNORM:
@@ -251,47 +239,23 @@ static boolean r300_is_format_supported(struct pipe_screen* screen,
         case PIPE_FORMAT_R8G8B8A8_UNORM:
         case PIPE_FORMAT_R8G8B8X8_UNORM:
         case PIPE_FORMAT_I8_UNORM:
-            retval = usage &
+            retval |= usage &
                 (PIPE_TEXTURE_USAGE_RENDER_TARGET |
                  PIPE_TEXTURE_USAGE_DISPLAY_TARGET |
-                 PIPE_TEXTURE_USAGE_PRIMARY |
-                 PIPE_TEXTURE_USAGE_SAMPLER);
+                 PIPE_TEXTURE_USAGE_PRIMARY);
             break;
 
-        /* Z buffer or texture */
+        /* ZS buffer */
         case PIPE_FORMAT_Z16_UNORM:
-            retval = usage &
-                (PIPE_TEXTURE_USAGE_DEPTH_STENCIL |
-                 PIPE_TEXTURE_USAGE_SAMPLER);
-            break;
-
-        /* 24bit Z buffer can only be used as a texture on R500. */
         case PIPE_FORMAT_Z24X8_UNORM:
-        /* Z buffer with stencil or texture */
         case PIPE_FORMAT_Z24S8_UNORM:
-            retval = usage &
-                (PIPE_TEXTURE_USAGE_DEPTH_STENCIL |
-                 (is_r500 ? PIPE_TEXTURE_USAGE_SAMPLER : 0));
+            retval = usage & PIPE_TEXTURE_USAGE_DEPTH_STENCIL;
             break;
 
-        /* Definitely unsupported formats. */
-        /* Non-usable Z buffer/stencil formats. */
-        case PIPE_FORMAT_Z32_UNORM:
-        case PIPE_FORMAT_S8Z24_UNORM:
-        case PIPE_FORMAT_X8Z24_UNORM:
-            SCREEN_DBG(r300_screen(screen), DBG_TEX,
-                       "r300: Note: Got unsupported format: %s in %s\n",
-                       util_format_name(format), __FUNCTION__);
-            return FALSE;
-
         /* XXX Add all remaining gallium-supported formats,
          * see util/u_format.csv. */
 
-        default:
-            /* Unknown format... */
-            debug_printf("r300: Warning: Got unknown format: %s in %s\n",
-                util_format_name(format), __FUNCTION__);
-            break;
+        default:;
     }
 
     /* If usage was a mask that contained multiple bits, and not all of them
index 6ee6cd0e3f22a8793ec8796fa2832c7923777a45..a6083925326cf52aa76eafea1109998cd83bfe28 100644 (file)
@@ -338,7 +338,6 @@ static INLINE uint32_t r300_translate_colorformat(enum pipe_format format)
         case PIPE_FORMAT_A8_UNORM:
         case PIPE_FORMAT_I8_UNORM:
         case PIPE_FORMAT_L8_UNORM:
-        /* case PIPE_FORMAT_S8_UNORM: ??? */
             return R300_COLOR_FORMAT_I8;
         /* 16-bit buffers */
         case PIPE_FORMAT_R5G6B5_UNORM:
index b9c3ab80932d5384ef637ee17fa9eec27ce9be76..153f4eebdaf5b40ae9a5df307397c05e98820fe4 100644 (file)
@@ -52,81 +52,228 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen,
  * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */
 static INLINE uint32_t r300_translate_texformat(enum pipe_format format)
 {
-    switch (format) {
-        /* X8 */
-        case PIPE_FORMAT_A8_UNORM:
-            return R300_EASY_TX_FORMAT(ZERO, ZERO, ZERO, X, X8);
-        case PIPE_FORMAT_I8_UNORM:
-            return R300_EASY_TX_FORMAT(X, X, X, X, X8);
-        case PIPE_FORMAT_L8_UNORM:
-            return R300_EASY_TX_FORMAT(X, X, X, ONE, X8);
-        case PIPE_FORMAT_L8_SRGB:
-            return R300_EASY_TX_FORMAT(X, X, X, ONE, X8) |
-                R300_TX_FORMAT_GAMMA;
-        /* X16 */
-        case PIPE_FORMAT_A4R4G4B4_UNORM:
-            return R300_EASY_TX_FORMAT(X, Y, Z, W, W4Z4Y4X4);
-        case PIPE_FORMAT_R16_UNORM:
-        case PIPE_FORMAT_Z16_UNORM:
-            return R300_EASY_TX_FORMAT(X, X, X, X, X16);
-        case PIPE_FORMAT_R16_SNORM:
-            return R300_EASY_TX_FORMAT(X, X, X, X, X16) |
-                R300_TX_FORMAT_SIGNED;
-        /* Z5Y6X5 */
-        case PIPE_FORMAT_R5G6B5_UNORM:
-            return R300_EASY_TX_FORMAT(X, Y, Z, ONE, Z5Y6X5);
-        /* W1Z5Y5X5*/
-        case PIPE_FORMAT_A1R5G5B5_UNORM:
-            return R300_EASY_TX_FORMAT(X, Y, Z, W, W1Z5Y5X5);
-        /* Y8X8 */
-        case PIPE_FORMAT_A8L8_UNORM:
-            return R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8);
-        case PIPE_FORMAT_A8L8_SRGB:
-            return R300_EASY_TX_FORMAT(X, X, X, Y, Y8X8) |
-                R300_TX_FORMAT_GAMMA;
-        /* W8Z8Y8X8 */
-        case PIPE_FORMAT_A8R8G8B8_UNORM:
-            return R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8);
-        case PIPE_FORMAT_R8G8B8A8_UNORM:
-            return R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8);
-        case PIPE_FORMAT_X8R8G8B8_UNORM:
-            return R300_EASY_TX_FORMAT(X, Y, Z, ONE, W8Z8Y8X8);
-        case PIPE_FORMAT_R8G8B8X8_UNORM:
-            return R300_EASY_TX_FORMAT(Y, Z, ONE, X, W8Z8Y8X8);
-        case PIPE_FORMAT_A8R8G8B8_SRGB:
-            return R300_EASY_TX_FORMAT(X, Y, Z, W, W8Z8Y8X8) |
-                R300_TX_FORMAT_GAMMA;
-        case PIPE_FORMAT_R8G8B8A8_SRGB:
-            return R300_EASY_TX_FORMAT(Y, Z, W, X, W8Z8Y8X8) |
-                R300_TX_FORMAT_GAMMA;
-        /* DXT1 */
-        case PIPE_FORMAT_DXT1_RGB:
-            return R300_EASY_TX_FORMAT(X, Y, Z, ONE, DXT1);
-        case PIPE_FORMAT_DXT1_RGBA:
-            return R300_EASY_TX_FORMAT(X, Y, Z, W, DXT1);
-        /* DXT3 */
-        case PIPE_FORMAT_DXT3_RGBA:
-            return R300_EASY_TX_FORMAT(X, Y, Z, W, DXT3);
-        /* DXT5 */
-        case PIPE_FORMAT_DXT5_RGBA:
-            return R300_EASY_TX_FORMAT(Y, Z, W, X, DXT5);
-        /* YVYU422 */
-        case PIPE_FORMAT_YCBCR:
-            return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) |
-                R300_TX_FORMAT_YUV_TO_RGB;
-        /* W24_FP */
-        case PIPE_FORMAT_Z24S8_UNORM:
-        case PIPE_FORMAT_Z24X8_UNORM:
-            return R300_EASY_TX_FORMAT(X, X, X, X, W24_FP);
-
-        default:
-            debug_printf("r300: Implementation error: "
-                "Got unsupported texture format %s in %s\n",
-                util_format_name(format), __FUNCTION__);
-            assert(0);
+    uint32_t result = 0;
+    const struct util_format_description *desc;
+    unsigned components = 0, i;
+    boolean uniform = TRUE;
+    const uint32_t swizzle_shift[4] = {
+        R300_TX_FORMAT_R_SHIFT,
+        R300_TX_FORMAT_G_SHIFT,
+        R300_TX_FORMAT_B_SHIFT,
+        R300_TX_FORMAT_A_SHIFT
+    };
+    const uint32_t sign_bit[4] = {
+        R300_TX_FORMAT_SIGNED_X,
+        R300_TX_FORMAT_SIGNED_Y,
+        R300_TX_FORMAT_SIGNED_Z,
+        R300_TX_FORMAT_SIGNED_W,
+    };
+
+    desc = util_format_description(format);
+
+    /* Colorspace (return non-RGB formats directly). */
+    switch (desc->colorspace) {
+        /* Depth stencil formats. */
+        case UTIL_FORMAT_COLORSPACE_ZS:
+            switch (format) {
+                case PIPE_FORMAT_Z16_UNORM:
+                    return R300_EASY_TX_FORMAT(X, X, X, X, X16);
+                case PIPE_FORMAT_Z24X8_UNORM:
+                case PIPE_FORMAT_Z24S8_UNORM:
+                    return R300_EASY_TX_FORMAT(X, X, X, X, W24_FP);
+                default:
+                    return ~0; /* Unsupported. */
+            }
+
+        /* YUV formats. */
+        case UTIL_FORMAT_COLORSPACE_YUV:
+            result |= R300_TX_FORMAT_YUV_TO_RGB;
+
+            switch (format) {
+                case PIPE_FORMAT_YCBCR:
+                    return R300_EASY_TX_FORMAT(X, Y, Z, ONE, YVYU422) | result;
+                case PIPE_FORMAT_YCBCR_REV:
+                    return R300_EASY_TX_FORMAT(X, Y, Z, ONE, VYUY422) | result;
+                default:
+                    return ~0; /* Unsupported/unknown. */
+            }
+
+        /* Add gamma correction. */
+        case UTIL_FORMAT_COLORSPACE_SRGB:
+            result |= R300_TX_FORMAT_GAMMA;
             break;
+
+        default:;
+    }
+
+    /* Add swizzle. */
+    for (i = 0; i < 4; i++) {
+        switch (desc->swizzle[i]) {
+            case UTIL_FORMAT_SWIZZLE_X:
+            case UTIL_FORMAT_SWIZZLE_NONE:
+                result |= R300_TX_FORMAT_X << swizzle_shift[i];
+                break;
+            case UTIL_FORMAT_SWIZZLE_Y:
+                result |= R300_TX_FORMAT_Y << swizzle_shift[i];
+                break;
+            case UTIL_FORMAT_SWIZZLE_Z:
+                result |= R300_TX_FORMAT_Z << swizzle_shift[i];
+                break;
+            case UTIL_FORMAT_SWIZZLE_W:
+                result |= R300_TX_FORMAT_W << swizzle_shift[i];
+                break;
+            case UTIL_FORMAT_SWIZZLE_0:
+                result |= R300_TX_FORMAT_ZERO << swizzle_shift[i];
+                break;
+            case UTIL_FORMAT_SWIZZLE_1:
+                result |= R300_TX_FORMAT_ONE << swizzle_shift[i];
+                break;
+            default:
+                return ~0; /* Unsupported. */
+        }
+    }
+
+    /* Compressed formats. */
+    if (desc->layout == UTIL_FORMAT_LAYOUT_DXT) {
+        switch (format) {
+            case PIPE_FORMAT_DXT1_RGB:
+            case PIPE_FORMAT_DXT1_RGBA:
+            case PIPE_FORMAT_DXT1_SRGB:
+            case PIPE_FORMAT_DXT1_SRGBA:
+                return R300_TX_FORMAT_DXT1 | result;
+            case PIPE_FORMAT_DXT3_RGBA:
+            case PIPE_FORMAT_DXT3_SRGBA:
+                return R300_TX_FORMAT_DXT3 | result;
+            case PIPE_FORMAT_DXT5_RGBA:
+            case PIPE_FORMAT_DXT5_SRGBA:
+                return R300_TX_FORMAT_DXT5 | result;
+            default:
+                return ~0; /* Unsupported/unknown. */
+        }
+    }
+
+    /* Get the number of components. */
+    for (i = 0; i < 4; i++) {
+        if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID) {
+            ++components;
+        }
+    }
+
+    /* Add sign. */
+    for (i = 0; i < components; i++) {
+        if (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED) {
+            result |= sign_bit[i];
+        }
     }
-    return 0;
+
+    /* See whether the components are of the same size. */
+    for (i = 1; i < components; i++) {
+        uniform = uniform && desc->channel[0].size == desc->channel[i].size;
+    }
+
+    /* Non-uniform formats. */
+    if (!uniform) {
+        switch (components) {
+            case 3:
+                if (desc->channel[0].size == 5 &&
+                    desc->channel[1].size == 6 &&
+                    desc->channel[2].size == 5) {
+                    return R300_TX_FORMAT_Z5Y6X5 | result;
+                }
+                if (desc->channel[0].size == 5 &&
+                    desc->channel[1].size == 5 &&
+                    desc->channel[2].size == 6) {
+                    return R300_TX_FORMAT_Z6Y5X5 | result;
+                }
+                return ~0; /* Unsupported/unknown. */
+
+            case 4:
+                if (desc->channel[0].size == 5 &&
+                    desc->channel[1].size == 5 &&
+                    desc->channel[2].size == 5 &&
+                    desc->channel[3].size == 1) {
+                    return R300_TX_FORMAT_W1Z5Y5X5 | result;
+                }
+                if (desc->channel[0].size == 10 &&
+                    desc->channel[1].size == 10 &&
+                    desc->channel[2].size == 10 &&
+                    desc->channel[3].size == 2) {
+                    return R300_TX_FORMAT_W2Z10Y10X10 | result;
+                }
+        }
+        return ~0; /* Unsupported/unknown. */
+    }
+
+    /* And finally, uniform formats. */
+    switch (desc->channel[0].type) {
+        case UTIL_FORMAT_TYPE_UNSIGNED:
+        case UTIL_FORMAT_TYPE_SIGNED:
+            if (!desc->channel[0].normalized) {
+                return ~0;
+            }
+
+            switch (desc->channel[0].size) {
+                case 4:
+                    switch (components) {
+                        case 2:
+                            return R300_TX_FORMAT_Y4X4 | result;
+                        case 4:
+                            return R300_TX_FORMAT_W4Z4Y4X4 | result;
+                    }
+                    return ~0;
+
+                case 8:
+                    switch (components) {
+                        case 1:
+                            return R300_TX_FORMAT_X8 | result;
+                        case 2:
+                            return R300_TX_FORMAT_Y8X8 | result;
+                        case 4:
+                            return R300_TX_FORMAT_W8Z8Y8X8 | result;
+                    }
+                    return ~0;
+
+                case 16:
+                    switch (components) {
+                        case 1:
+                            return R300_TX_FORMAT_X16 | result;
+                        case 2:
+                            return R300_TX_FORMAT_Y16X16 | result;
+                        case 4:
+                            return R300_TX_FORMAT_W16Z16Y16X16 | result;
+                    }
+            }
+            return ~0;
+
+/* XXX Enable float textures here. */
+#if 0
+        case UTIL_FORMAT_TYPE_FLOAT:
+            switch (desc->channel[0].size) {
+                case 16:
+                    switch (components) {
+                        case 1:
+                            return R300_TX_FORMAT_16F | result;
+                        case 2:
+                            return R300_TX_FORMAT_16F_16F | result;
+                        case 4:
+                            return R300_TX_FORMAT_16F_16F_16F_16F | result;
+                    }
+                    return ~0;
+
+                case 32:
+                    switch (components) {
+                        case 1:
+                            return R300_TX_FORMAT_32F | result;
+                        case 2:
+                            return R300_TX_FORMAT_32F_32F | result;
+                        case 4:
+                            return R300_TX_FORMAT_32F_32F_32F_32F | result;
+                    }
+            }
+#endif
+    }
+
+    return ~0; /* Unsupported/unknown. */
 }
 
 struct r300_video_surface