r300g: advertise S3TC only when it's available in Gallium
[mesa.git] / src / gallium / drivers / r300 / r300_texture.c
index 4439e35d670bc00ff34553810177c2d25b7788a9..a6f65fce2161519d0ee84d717ae10e7f803d3ea1 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,18 +47,6 @@ 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)
-{
-    const struct util_format_description *desc = util_format_description(format);
-
-    if (!format) {
-        return FALSE;
-    }
-
-    return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN;
-}
-
 /* Translate a pipe_format into a useful texture format for sampling.
  *
  * Some special formats are translated directly using R300_EASY_TX_FORMAT,
@@ -74,7 +60,7 @@ 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;
@@ -98,6 +84,7 @@ uint32_t r300_translate_texformat(enum pipe_format format,
         R300_TX_FORMAT_SIGNED_Z,
         R300_TX_FORMAT_SIGNED_W,
     };
+    unsigned char swizzle[4];
 
     desc = util_format_description(format);
 
@@ -144,25 +131,18 @@ 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]]);
+    /* 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:
@@ -191,6 +171,10 @@ uint32_t r300_translate_texformat(enum pipe_format format,
 
     /* 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 +300,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 +323,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 +387,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 +510,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 +551,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 +578,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 +589,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 +597,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 +612,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 +704,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 +722,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 +737,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 +762,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 +788,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,14 +811,16 @@ 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;
     }
 
-    if (tex->b.b.width0 == 1 ||
-        tex->b.b.height0 == 1) {
+    /* If height == 1, disable microtiling except for zbuffer. */
+    if (!is_zb && (tex->b.b.height0 == 1 || dbg_no_tiling)) {
         return;
     }
 
@@ -860,6 +839,10 @@ static void r300_setup_tiling(struct pipe_screen *screen,
             break;
     }
 
+    if (dbg_no_tiling) {
+        return;
+    }
+
     /* Set macrotiling. */
     if (r300_texture_macro_switch(tex, 0, rv350_mode, TILE_WIDTH) &&
         r300_texture_macro_switch(tex, 0, rv350_mode, TILE_HEIGHT)) {
@@ -874,7 +857,7 @@ static unsigned r300_texture_is_referenced(struct pipe_context *context,
     struct r300_context *r300 = r300_context(context);
     struct r300_texture *rtex = (struct r300_texture *)texture;
 
-    if (r300->rws->is_buffer_referenced(r300->rws, rtex->buffer))
+    if (r300->rws->is_buffer_referenced(r300->rws, rtex->buffer, R300_REF_CS))
         return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE;
 
     return PIPE_UNREFERENCED;
@@ -890,13 +873,9 @@ static void r300_texture_destroy(struct pipe_screen *screen,
     FREE(tex);
 }
 
-
-
-
-static boolean
-    r300_texture_get_handle(struct pipe_screen* screen,
-                            struct pipe_resource *texture,
-                            struct winsys_handle *whandle)
+static boolean r300_texture_get_handle(struct pipe_screen* screen,
+                                       struct pipe_resource *texture,
+                                       struct winsys_handle *whandle)
 {
     struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys;
     struct r300_texture* tex = (struct r300_texture*)texture;
@@ -913,8 +892,6 @@ static boolean
     return TRUE;
 }
 
-
-
 struct u_resource_vtbl r300_texture_vtbl = 
 {
    r300_texture_get_handle,          /* get_handle */
@@ -928,8 +905,6 @@ struct u_resource_vtbl r300_texture_vtbl =
    u_default_transfer_inline_write    /* transfer_inline_write */
 };
 
-
-
 /* Create a new texture. */
 struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
                                           const struct pipe_resource* base)
@@ -942,6 +917,17 @@ 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);
+        return NULL;
+    }
+
     tex->b.b = *base;
     tex->b.vtbl = &r300_texture_vtbl;
     pipe_reference_init(&tex->b.b.reference, 1);
@@ -957,6 +943,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);
@@ -973,8 +968,6 @@ struct pipe_resource* r300_texture_create(struct pipe_screen* screen,
     return (struct pipe_resource*)tex;
 }
 
-
-
 /* Not required to implement u_resource_vtbl, consider moving to another file:
  */
 struct pipe_surface* r300_get_tex_surface(struct pipe_screen* screen,
@@ -1056,6 +1049,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) &&
@@ -1091,4 +1092,3 @@ r300_texture_from_handle(struct pipe_screen* screen,
     }
     return (struct pipe_resource*)tex;
 }
-