r600g: fix miptree calculations
authorDave Airlie <airlied@redhat.com>
Tue, 15 Feb 2011 03:21:50 +0000 (13:21 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 15 Feb 2011 04:44:08 +0000 (14:44 +1000)
the miptree setup and pitch storing didn't work so well for block
based things like compressed textures. The CB takes blocks, where
the texture sampler takes pixels, and transfers need bytes,

So now we store blocks/bytes and translate to pixels in the sampler.

This is necessary for s3tc to work properly.

src/gallium/drivers/r600/evergreen_state.c
src/gallium/drivers/r600/r600_resource.h
src/gallium/drivers/r600/r600_state.c
src/gallium/drivers/r600/r600_texture.c

index 45469db6c958d9b77c0d0e5f379170d869de4169..261dd8d6ab82030505f064cfb75dc2027907140a 100644 (file)
@@ -389,7 +389,7 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte
        bo[0] = rbuffer->bo;
        bo[1] = rbuffer->bo;
 
-       pitch = align(tmp->pitch_in_pixels[0], 8);
+       pitch = align(tmp->pitch_in_blocks[0] * util_format_get_blockwidth(state->format), 8);
        array_mode = tmp->array_mode[0];
        tile_type = tmp->tile_type;
 
@@ -664,8 +664,8 @@ static void evergreen_cb(struct r600_pipe_context *rctx, struct r600_pipe_state
        /* XXX quite sure for dx10+ hw don't need any offset hacks */
        offset = r600_texture_get_offset((struct r600_resource_texture *)state->cbufs[cb]->texture,
                                         level, state->cbufs[cb]->u.tex.first_layer);
-       pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-       slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+       pitch = rtex->pitch_in_blocks[level] / 8 - 1;
+       slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
        ntype = 0;
        desc = util_format_description(surf->base.format);
        if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
@@ -747,8 +747,8 @@ static void evergreen_db(struct r600_pipe_context *rctx, struct r600_pipe_state
        /* XXX quite sure for dx10+ hw don't need any offset hacks */
        offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture,
                                         level, state->zsbuf->u.tex.first_layer);
-       pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-       slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+       pitch = rtex->pitch_in_blocks[level] / 8 - 1;
+       slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
        format = r600_translate_dbformat(state->zsbuf->texture->format);
        stencil_format = r600_translate_stencilformat(state->zsbuf->texture->format);
 
index a6d2141e5f2805987b54a37d1471dfdf410c3741..fdcfcd50a10c1982e486359210f09e063b940d50 100644 (file)
@@ -53,8 +53,8 @@ struct r600_resource {
 struct r600_resource_texture {
        struct r600_resource            resource;
        unsigned                        offset[PIPE_MAX_TEXTURE_LEVELS];
-       unsigned                        pitch_in_bytes[PIPE_MAX_TEXTURE_LEVELS];
-       unsigned                        pitch_in_pixels[PIPE_MAX_TEXTURE_LEVELS];
+       unsigned                        pitch_in_bytes[PIPE_MAX_TEXTURE_LEVELS];  /* transfer */
+       unsigned                        pitch_in_blocks[PIPE_MAX_TEXTURE_LEVELS]; /* texture resource */
        unsigned                        layer_size[PIPE_MAX_TEXTURE_LEVELS];
        unsigned                        array_mode[PIPE_MAX_TEXTURE_LEVELS];
        unsigned                        pitch_override;
index bf74511b63fe2d2d48a94648020e71623405a10d..bd591bdd8cc0c51fed447b726b0a65088c87bd1d 100644 (file)
@@ -437,7 +437,7 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
        rbuffer = &tmp->resource;
        bo[0] = rbuffer->bo;
        bo[1] = rbuffer->bo;
-       pitch = align(tmp->pitch_in_pixels[0], 8);
+       pitch = align(tmp->pitch_in_blocks[0] * util_format_get_blockwidth(state->format), 8);
        array_mode = tmp->array_mode[0];
        tile_type = tmp->tile_type;
 
@@ -709,8 +709,8 @@ static void r600_cb(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta
        /* XXX quite sure for dx10+ hw don't need any offset hacks */
        offset = r600_texture_get_offset(rtex,
                                         level, state->cbufs[cb]->u.tex.first_layer);
-       pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-       slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+       pitch = rtex->pitch_in_blocks[0] / 8 - 1;
+       slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
        ntype = 0;
        desc = util_format_description(surf->base.format);
        if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB)
@@ -784,8 +784,8 @@ static void r600_db(struct r600_pipe_context *rctx, struct r600_pipe_state *rsta
        /* XXX quite sure for dx10+ hw don't need any offset hacks */
        offset = r600_texture_get_offset((struct r600_resource_texture *)state->zsbuf->texture,
                                         level, state->zsbuf->u.tex.first_layer);
-       pitch = rtex->pitch_in_pixels[level] / 8 - 1;
-       slice = rtex->pitch_in_pixels[level] * surf->aligned_height / 64 - 1;
+       pitch = rtex->pitch_in_blocks[level] / 8 - 1;
+       slice = rtex->pitch_in_blocks[level] * surf->aligned_height / 64 - 1;
        format = r600_translate_dbformat(state->zsbuf->texture->format);
 
        r600_pipe_state_add_reg(rstate, R_02800C_DB_DEPTH_BASE,
index 30e31e58d3115cf9114ddafeecf58a0729b3006b..db39383e30699b6886849789988cbae553f295e6 100644 (file)
@@ -85,7 +85,7 @@ unsigned r600_texture_get_offset(struct r600_resource_texture *rtex,
        }
 }
 
-static unsigned r600_get_pixel_alignment(struct pipe_screen *screen,
+static unsigned r600_get_block_alignment(struct pipe_screen *screen,
                                         enum pipe_format format,
                                         unsigned array_mode)
 {
@@ -128,6 +128,7 @@ static unsigned r600_get_height_alignment(struct pipe_screen *screen,
        case V_038000_ARRAY_LINEAR_ALIGNED:
                h_align = 8;
                break;
+       case V_038000_ARRAY_LINEAR_GENERAL:
        default:
                h_align = 1;
                break;
@@ -141,7 +142,7 @@ static unsigned r600_get_base_alignment(struct pipe_screen *screen,
 {
        struct r600_screen* rscreen = (struct r600_screen *)screen;
        unsigned pixsize = util_format_get_blocksize(format);
-       int p_align = r600_get_pixel_alignment(screen, format, array_mode);
+       int p_align = r600_get_block_alignment(screen, format, array_mode);
        int h_align = r600_get_height_alignment(screen, array_mode);
        int b_align;
 
@@ -169,25 +170,24 @@ static unsigned mip_minify(unsigned size, unsigned level)
        return val;
 }
 
-static unsigned r600_texture_get_stride(struct pipe_screen *screen,
-                                       struct r600_resource_texture *rtex,
-                                       unsigned level)
+static unsigned r600_texture_get_nblocksx(struct pipe_screen *screen,
+                                         struct r600_resource_texture *rtex,
+                                         unsigned level)
 {
        struct pipe_resource *ptex = &rtex->resource.b.b.b;
-       unsigned width, stride, tile_width;
+       unsigned nblocksx, block_align, width;
+       unsigned blocksize = util_format_get_blocksize(ptex->format);
 
        if (rtex->pitch_override)
-               return rtex->pitch_override;
+               return rtex->pitch_override / blocksize;
 
        width = mip_minify(ptex->width0, level);
-       if (util_format_is_plain(ptex->format)) {
-               tile_width = r600_get_pixel_alignment(screen, ptex->format,
-                                                     rtex->array_mode[level]);
-               width = align(width, tile_width);
-       }
-       stride = util_format_get_stride(ptex->format, width);
+       nblocksx = util_format_get_nblocksx(ptex->format, width);
 
-       return stride;
+       block_align = r600_get_block_alignment(screen, ptex->format,
+                                             rtex->array_mode[level]);
+       nblocksx = align(nblocksx, block_align);
+       return nblocksx;
 }
 
 static unsigned r600_texture_get_nblocksy(struct pipe_screen *screen,
@@ -198,19 +198,11 @@ static unsigned r600_texture_get_nblocksy(struct pipe_screen *screen,
        unsigned height, tile_height;
 
        height = mip_minify(ptex->height0, level);
-       if (util_format_is_plain(ptex->format)) {
-               tile_height = r600_get_height_alignment(screen,
-                                                       rtex->array_mode[level]);
-               height = align(height, tile_height);
-       }
-       return util_format_get_nblocksy(ptex->format, height);
-}
-
-/* Get a width in pixels from a stride in bytes. */
-static unsigned pitch_to_width(enum pipe_format format, unsigned pitch_in_bytes)
-{
-       return (pitch_in_bytes / util_format_get_blocksize(format)) *
-               util_format_get_blockwidth(format);
+       height = util_format_get_nblocksy(ptex->format, height);
+       tile_height = r600_get_height_alignment(screen,
+                                               rtex->array_mode[level]);
+       height = align(height, tile_height);
+       return height;
 }
 
 static void r600_texture_set_array_mode(struct pipe_screen *screen,
@@ -231,7 +223,7 @@ static void r600_texture_set_array_mode(struct pipe_screen *screen,
                unsigned w, h, tile_height, tile_width;
 
                tile_height = r600_get_height_alignment(screen, array_mode);
-               tile_width = r600_get_pixel_alignment(screen, ptex->format, array_mode);
+               tile_width = r600_get_block_alignment(screen, ptex->format, array_mode);
 
                w = mip_minify(ptex->width0, level);
                h = mip_minify(ptex->height0, level);
@@ -251,17 +243,18 @@ static void r600_setup_miptree(struct pipe_screen *screen,
        struct pipe_resource *ptex = &rtex->resource.b.b.b;
        struct radeon *radeon = (struct radeon *)screen->winsys;
        enum chip_class chipc = r600_get_family_class(radeon);
-       unsigned pitch, size, layer_size, i, offset;
-       unsigned nblocksy;
+       unsigned size, layer_size, i, offset;
+       unsigned nblocksx, nblocksy;
 
        for (i = 0, offset = 0; i <= ptex->last_level; i++) {
+               unsigned blocksize = util_format_get_blocksize(ptex->format);
+
                r600_texture_set_array_mode(screen, rtex, i, array_mode);
 
-               pitch = r600_texture_get_stride(screen, rtex, i);
+               nblocksx = r600_texture_get_nblocksx(screen, rtex, i);
                nblocksy = r600_texture_get_nblocksy(screen, rtex, i);
 
-               layer_size = pitch * nblocksy;
-
+               layer_size = nblocksx * nblocksy * blocksize;
                if (ptex->target == PIPE_TEXTURE_CUBE) {
                        if (chipc >= R700)
                                size = layer_size * 8;
@@ -275,8 +268,9 @@ static void r600_setup_miptree(struct pipe_screen *screen,
                        offset = align(offset, r600_get_base_alignment(screen, ptex->format, array_mode));
                rtex->offset[i] = offset;
                rtex->layer_size[i] = layer_size;
-               rtex->pitch_in_bytes[i] = pitch;
-               rtex->pitch_in_pixels[i] = pitch_to_width(ptex->format, pitch);
+               rtex->pitch_in_blocks[i] = nblocksx; /* CB talks in elements */
+               rtex->pitch_in_bytes[i] = nblocksx * blocksize;
+
                offset += size;
        }
        rtex->size = offset;