r300g: Correct viewport setup for SW TCL.
[mesa.git] / src / gallium / drivers / r300 / r300_texture.c
index ec4076120a8c5d1a033991fc8cce089b9bc7c4cb..c0911aef385736e20698a106e2b96fffd509d090 100644 (file)
@@ -24,6 +24,7 @@
 #include "pipe/p_screen.h"
 
 #include "util/u_format.h"
+#include "util/u_format_s3tc.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 
@@ -46,16 +47,58 @@ static const unsigned microblock_table[5][3][2] = {
     {{ 2, 1}, {0, 0}, {0, 0}}  /* 128 bits per pixel */
 };
 
-/* Return true for non-compressed and non-YUV formats. */
-static boolean r300_format_is_plain(enum pipe_format format)
+unsigned r300_get_swizzle_combined(const unsigned char *swizzle_format,
+                                   const unsigned char *swizzle_view)
 {
-    const struct util_format_description *desc = util_format_description(format);
+    unsigned i;
+    unsigned char swizzle[4];
+    unsigned result = 0;
+    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 swizzle_bit[4] = {
+        R300_TX_FORMAT_X,
+        R300_TX_FORMAT_Y,
+        R300_TX_FORMAT_Z,
+        R300_TX_FORMAT_W
+    };
 
-    if (!format) {
-        return FALSE;
+    if (swizzle_view) {
+        /* Combine two sets of swizzles. */
+        for (i = 0; i < 4; i++) {
+            swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ?
+                         swizzle_format[swizzle_view[i]] : swizzle_view[i];
+        }
+    } else {
+        memcpy(swizzle, swizzle_format, 4);
     }
 
-    return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN;
+    /* Get swizzle. */
+    for (i = 0; i < 4; i++) {
+        switch (swizzle[i]) {
+            case UTIL_FORMAT_SWIZZLE_Y:
+                result |= swizzle_bit[1] << swizzle_shift[i];
+                break;
+            case UTIL_FORMAT_SWIZZLE_Z:
+                result |= swizzle_bit[2] << swizzle_shift[i];
+                break;
+            case UTIL_FORMAT_SWIZZLE_W:
+                result |= swizzle_bit[3] << 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: /* UTIL_FORMAT_SWIZZLE_X */
+                result |= swizzle_bit[0] << swizzle_shift[i];
+        }
+    }
+    return result;
 }
 
 /* Translate a pipe_format into a useful texture format for sampling.
@@ -77,38 +120,26 @@ uint32_t r300_translate_texformat(enum pipe_format format,
     const struct util_format_description *desc;
     unsigned 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 swizzle_bit[4] = {
-        R300_TX_FORMAT_X,
-        R300_TX_FORMAT_Y,
-        R300_TX_FORMAT_Z,
-        R300_TX_FORMAT_W
-    };
     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,
     };
-    unsigned char swizzle[4];
 
     desc = util_format_description(format);
 
     /* Colorspace (return non-RGB formats directly). */
     switch (desc->colorspace) {
-        /* Depth stencil formats. */
+        /* Depth stencil formats.
+         * Swizzles are added in r300_merge_textures_and_samplers. */
         case UTIL_FORMAT_COLORSPACE_ZS:
             switch (format) {
                 case PIPE_FORMAT_Z16_UNORM:
-                    return R300_EASY_TX_FORMAT(X, X, X, X, X16);
+                    return R300_TX_FORMAT_X16;
                 case PIPE_FORMAT_X8Z24_UNORM:
                 case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
-                    return R300_EASY_TX_FORMAT(X, X, X, X, W24_FP);
+                    return R300_TX_FORMAT_W24_FP;
                 default:
                     return ~0; /* Unsupported. */
             }
@@ -142,46 +173,14 @@ uint32_t r300_translate_texformat(enum pipe_format format,
             }
     }
 
-    /* Get swizzle. */
-    if (swizzle_view) {
-        /* Compose two sets of swizzles. */
-        for (i = 0; i < 4; i++) {
-            swizzle[i] = swizzle_view[i] <= UTIL_FORMAT_SWIZZLE_W ?
-                         desc->swizzle[swizzle_view[i]] : swizzle_view[i];
-        }
-    } else {
-        memcpy(swizzle, desc->swizzle, sizeof(swizzle));
-    }
-
-    /* Add swizzle. */
-    for (i = 0; i < 4; i++) {
-        switch (swizzle[i]) {
-            case UTIL_FORMAT_SWIZZLE_X:
-            case UTIL_FORMAT_SWIZZLE_NONE:
-                result |= swizzle_bit[0] << swizzle_shift[i];
-                break;
-            case UTIL_FORMAT_SWIZZLE_Y:
-                result |= swizzle_bit[1] << swizzle_shift[i];
-                break;
-            case UTIL_FORMAT_SWIZZLE_Z:
-                result |= swizzle_bit[2] << swizzle_shift[i];
-                break;
-            case UTIL_FORMAT_SWIZZLE_W:
-                result |= swizzle_bit[3] << 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. */
-        }
-    }
+    result |= r300_get_swizzle_combined(desc->swizzle, swizzle_view);
 
     /* S3TC formats. */
     if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
+        if (!util_format_s3tc_enabled) {
+            return ~0; /* Unsupported. */
+        }
+
         switch (format) {
             case PIPE_FORMAT_DXT1_RGB:
             case PIPE_FORMAT_DXT1_RGBA:
@@ -558,7 +557,7 @@ static void r300_texture_setup_immutable_state(struct r300_screen* screen,
     if (tex->uses_pitch) {
         /* rectangles love this */
         f->format0 |= R300_TX_PITCH_EN;
-        f->format2 = (tex->pitch[0] - 1) & 0x1fff;
+        f->format2 = (tex->hwpitch[0] - 1) & 0x1fff;
     } else {
         /* power of two textures (3D, mipmaps, and no pitch) */
         f->format0 |= R300_TX_DEPTH(util_logbase2(pt->depth0) & 0xf);
@@ -585,9 +584,6 @@ static void r300_texture_setup_immutable_state(struct r300_screen* screen,
 
     f->tile_config = R300_TXO_MACRO_TILE(tex->macrotile) |
                      R300_TXO_MICRO_TILE(tex->microtile);
-
-    SCREEN_DBG(screen, DBG_TEX, "r300: Set texture state (%dx%d, %d levels)\n",
-               pt->width0, pt->height0, pt->last_level);
 }
 
 static void r300_texture_setup_fb_state(struct r300_screen* screen,
@@ -599,7 +595,7 @@ static void r300_texture_setup_fb_state(struct r300_screen* screen,
     if (util_format_is_depth_or_stencil(tex->b.b.format)) {
         for (i = 0; i <= tex->b.b.last_level; i++) {
             tex->fb_state.depthpitch[i] =
-                tex->pitch[i] |
+                tex->hwpitch[i] |
                 R300_DEPTHMACROTILE(tex->mip_macrotile[i]) |
                 R300_DEPTHMICROTILE(tex->microtile);
         }
@@ -607,7 +603,7 @@ static void r300_texture_setup_fb_state(struct r300_screen* screen,
     } else {
         for (i = 0; i <= tex->b.b.last_level; i++) {
             tex->fb_state.colorpitch[i] =
-                tex->pitch[i] |
+                tex->hwpitch[i] |
                 r300_translate_colorformat(tex->b.b.format) |
                 R300_COLOR_TILE(tex->mip_macrotile[i]) |
                 R300_COLOR_MICROTILE(tex->microtile);
@@ -622,8 +618,8 @@ void r300_texture_reinterpret_format(struct pipe_screen *screen,
 {
     struct r300_screen *r300screen = r300_screen(screen);
 
-    SCREEN_DBG(r300screen, DBG_TEX, "r300: Reinterpreting format: %s -> %s\n",
-               util_format_name(tex->format), util_format_name(new_format));
+    SCREEN_DBG(r300screen, DBG_TEX, "r300: texture_reinterpret_format: %s -> %s\n",
+               util_format_short_name(tex->format), util_format_short_name(new_format));
 
     tex->format = new_format;
 
@@ -714,7 +710,7 @@ unsigned r300_texture_get_stride(struct r300_screen* screen,
 
     width = u_minify(tex->b.b.width0, level);
 
-    if (r300_format_is_plain(tex->b.b.format)) {
+    if (util_format_is_plain(tex->b.b.format)) {
         tile_width = r300_texture_get_tile_size(tex, TILE_WIDTH,
                                                 tex->mip_macrotile[level]);
         width = align(width, tile_width);
@@ -732,7 +728,7 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture* tex,
 
     height = u_minify(tex->b.b.height0, level);
 
-    if (r300_format_is_plain(tex->b.b.format)) {
+    if (util_format_is_plain(tex->b.b.format)) {
         tile_height = r300_texture_get_tile_size(tex, TILE_HEIGHT,
                                                  tex->mip_macrotile[level]);
         height = align(height, tile_height);
@@ -774,8 +770,8 @@ static void r300_setup_miptree(struct r300_screen* screen,
     unsigned stride, size, layer_size, nblocksy, i;
     boolean rv350_mode = screen->caps.is_rv350;
 
-    SCREEN_DBG(screen, DBG_TEX, "r300: Making miptree for texture, format %s\n",
-               util_format_name(base->format));
+    SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Making miptree for texture, format %s\n",
+               util_format_short_name(base->format));
 
     for (i = 0; i <= base->last_level; i++) {
         /* Let's see if this miplevel can be macrotiled. */
@@ -798,8 +794,10 @@ static void r300_setup_miptree(struct r300_screen* screen,
         tex->size = tex->offset[i] + size;
         tex->layer_size[i] = layer_size;
         tex->pitch[i] = stride / util_format_get_blocksize(base->format);
+        tex->hwpitch[i] =
+                tex->pitch[i] * util_format_get_blockwidth(base->format);
 
-        SCREEN_DBG(screen, DBG_TEX, "r300: Texture miptree: Level %d "
+        SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d "
                 "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n",
                 i, u_minify(base->width0, i), u_minify(base->height0, i),
                 u_minify(base->depth0, i), stride, tex->size,
@@ -823,7 +821,7 @@ static void r300_setup_tiling(struct pipe_screen *screen,
     boolean is_zb = util_format_is_depth_or_stencil(format);
     boolean dbg_no_tiling = SCREEN_DBG_ON(r300_screen(screen), DBG_NO_TILING);
 
-    if (!r300_format_is_plain(format)) {
+    if (!util_format_is_plain(format)) {
         return;
     }
 
@@ -925,6 +923,18 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
         return NULL;
     }
 
+    /* Refuse to create a texture with size 0. */
+    if (!base->width0 ||
+        (!base->height0 && (base->target == PIPE_TEXTURE_2D ||
+                            base->target == PIPE_TEXTURE_CUBE)) ||
+        (!base->depth0 && base->target == PIPE_TEXTURE_3D)) {
+        fprintf(stderr, "r300: texture_create: "
+                "Got invalid texture dimensions: %ix%ix%i\n",
+                base->width0, base->height0, base->depth0);
+        FREE(tex);
+        return NULL;
+    }
+
     tex->b.b = *base;
     tex->b.vtbl = &r300_texture_vtbl;
     pipe_reference_init(&tex->b.b.reference, 1);
@@ -940,6 +950,15 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
     r300_texture_setup_immutable_state(rscreen, tex);
     r300_texture_setup_fb_state(rscreen, tex);
 
+    SCREEN_DBG(rscreen, DBG_TEX,
+               "r300: texture_create: Macro: %s, Micro: %s, Pitch: %i, "
+               "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n",
+               tex->macrotile ? "YES" : " NO",
+               tex->microtile ? "YES" : " NO",
+               tex->hwpitch[0],
+               base->width0, base->height0, base->depth0, base->last_level,
+               util_format_short_name(base->format));
+
     tex->buffer = rws->buffer_create(rws, 2048,
                                     PIPE_BIND_SAMPLER_VIEW, /* XXX */
                                     tex->size);
@@ -1037,6 +1056,14 @@ r300_texture_from_handle(struct pipe_screen* screen,
 
     rws->buffer_get_tiling(rws, buffer, &tex->microtile, &tex->macrotile);
     r300_setup_flags(tex);
+    SCREEN_DBG(rscreen, DBG_TEX,
+               "r300: texture_from_handle: Macro: %s, Micro: %s, "
+               "Pitch: % 4i, Dim: %ix%i, Format: %s\n",
+               tex->macrotile ? "YES" : " NO",
+               tex->microtile ? "YES" : " NO",
+               stride / util_format_get_blocksize(base->format),
+               base->width0, base->height0,
+               util_format_short_name(base->format));
 
     /* Enforce microtiled zbuffer. */
     override_zb_flags = util_format_is_depth_or_stencil(base->format) &&