r300g: Correct viewport setup for SW TCL.
[mesa.git] / src / gallium / drivers / r300 / r300_texture.c
index e795c8df0bbd34f93e8b3827338d8860adc92dcf..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"
 
@@ -34,9 +35,6 @@
 #include "r300_screen.h"
 #include "r300_winsys.h"
 
-/* XXX Enable float textures here. */
-/*#define ENABLE_FLOAT_TEXTURES*/
-
 #define TILE_WIDTH 0
 #define TILE_HEIGHT 1
 
@@ -49,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.
@@ -74,24 +114,12 @@ static boolean r300_format_is_plain(enum pipe_format format)
  * The FORMAT specifies how the texture sampler will treat the texture, and
  * makes available X, Y, Z, W, ZERO, and ONE for swizzling. */
 uint32_t r300_translate_texformat(enum pipe_format format,
-                                  const unsigned char *swizzle)
+                                  const unsigned char *swizzle_view)
 {
     uint32_t result = 0;
     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,
@@ -103,14 +131,15 @@ uint32_t r300_translate_texformat(enum pipe_format 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. */
             }
@@ -144,53 +173,14 @@ uint32_t r300_translate_texformat(enum pipe_format format,
             }
     }
 
-    /* Add swizzle. */
-    if (!swizzle) {
-        swizzle = desc->swizzle;
-    } /*else {
-        if (swizzle[0] != desc->swizzle[0] ||
-            swizzle[1] != desc->swizzle[1] ||
-            swizzle[2] != desc->swizzle[2] ||
-            swizzle[3] != desc->swizzle[3])
-        {
-            const char n[6] = "RGBA01";
-            fprintf(stderr, "Got different swizzling! Format: %c%c%c%c, "
-                    "View: %c%c%c%c\n",
-                    n[desc->swizzle[0]], n[desc->swizzle[1]],
-                    n[desc->swizzle[2]], n[desc->swizzle[3]],
-                    n[swizzle[0]], n[swizzle[1]], n[swizzle[2]],
-                    n[swizzle[3]]);
-        }
-    }*/
-
-    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:
@@ -316,7 +306,6 @@ uint32_t r300_translate_texformat(enum pipe_format format,
             }
             return ~0;
 
-#if defined(ENABLE_FLOAT_TEXTURES)
         case UTIL_FORMAT_TYPE_FLOAT:
             switch (desc->channel[0].size) {
                 case 16:
@@ -340,7 +329,6 @@ uint32_t r300_translate_texformat(enum pipe_format format,
                             return R300_TX_FORMAT_32F_32F_32F_32F | result;
                     }
             }
-#endif
     }
 
     return ~0; /* Unsupported/unknown. */
@@ -405,16 +393,12 @@ static uint32_t r300_translate_colorformat(enum pipe_format format)
         /* 64-bit buffers. */
         case PIPE_FORMAT_R16G16B16A16_UNORM:
         case PIPE_FORMAT_R16G16B16A16_SNORM:
-#if defined(ENABLE_FLOAT_TEXTURES)
         case PIPE_FORMAT_R16G16B16A16_FLOAT:
-#endif
             return R300_COLOR_FORMAT_ARGB16161616;
 
         /* 128-bit buffers. */
-#if defined(ENABLE_FLOAT_TEXTURES)
         case PIPE_FORMAT_R32G32B32A32_FLOAT:
             return R300_COLOR_FORMAT_ARGB32323232;
-#endif
 
         /* YUV buffers. */
         case PIPE_FORMAT_UYVY:
@@ -532,7 +516,7 @@ static uint32_t r300_translate_out_fmt(enum pipe_format format)
         case PIPE_FORMAT_R10SG10SB10SA2U_NORM:
         case PIPE_FORMAT_R16G16B16A16_UNORM:
         case PIPE_FORMAT_R16G16B16A16_SNORM:
-        //case PIPE_FORMAT_R16G16B16A16_FLOAT: /* not in pipe_format */
+        case PIPE_FORMAT_R16G16B16A16_FLOAT:
         case PIPE_FORMAT_R32G32B32A32_FLOAT:
             return modifier |
                 R300_C0_SEL_R | R300_C1_SEL_G |
@@ -573,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);
@@ -600,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,
@@ -614,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);
         }
@@ -622,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);
@@ -637,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;
 
@@ -729,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);
@@ -747,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);
@@ -762,12 +743,12 @@ static unsigned r300_texture_get_nblocksy(struct r300_texture* tex,
 static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen,
                                            struct r300_texture *tex)
 {
-    /* The kernels <= 2.6.34-rc3 compute the size of mipmapped 3D textures
+    /* The kernels <= 2.6.34-rc4 compute the size of mipmapped 3D textures
      * incorrectly. This is a workaround to prevent CS from being rejected. */
 
     unsigned i, size;
 
-    if (screen->rws->get_value(screen->rws, R300_VID_TEX3D_MIP_BUG) &&
+    if (!screen->rws->get_value(screen->rws, R300_VID_DRM_2_3_0) &&
         tex->b.b.target == PIPE_TEXTURE_3D &&
         tex->b.b.last_level > 0) {
         size = 0;
@@ -787,10 +768,10 @@ static void r300_setup_miptree(struct r300_screen* screen,
 {
     struct pipe_resource* base = &tex->b.b;
     unsigned stride, size, layer_size, nblocksy, i;
-    boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_RV350;
+    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. */
@@ -813,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,
@@ -834,11 +817,11 @@ static void r300_setup_tiling(struct pipe_screen *screen,
 {
     struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys;
     enum pipe_format format = tex->b.b.format;
-    boolean rv350_mode = r300_screen(screen)->caps.family >= CHIP_FAMILY_RV350;
+    boolean rv350_mode = r300_screen(screen)->caps.is_rv350;
     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;
     }
 
@@ -940,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);
@@ -955,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);
@@ -1052,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) &&