Mesa (master): r300g: rework resource_copy_region, not changing pipe_resource

Marek Olšák mareko at kemper.freedesktop.org
Sun Jan 1 10:47:46 UTC 2012


Module: Mesa
Branch: master
Commit: ce9d61fec64138ebf8d0bec2511e66593297b7d5
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ce9d61fec64138ebf8d0bec2511e66593297b7d5

Author: Marek Olšák <maraeo at gmail.com>
Date:   Thu Dec 29 18:18:38 2011 +0100

r300g: rework resource_copy_region, not changing pipe_resource

Changing pipe_resource was wrong, because it can be used by other contexts
at the same time. This fixes the last possible race condition in r300g
that I know of.

This also fixes blitting NPOT compressed textures. Random pixels sometimes
appeared at the right-hand edge of the texture.

Finally, this removes r300_texture_desc::stride_in_pixels. It makes little
sense with sampler views and surfaces being able to override width0, height0,
and the format entirely.

---

 src/gallium/drivers/r300/r300_blit.c          |  172 ++++++++++++++----------
 src/gallium/drivers/r300/r300_context.h       |   17 ++-
 src/gallium/drivers/r300/r300_state.c         |   33 ++++-
 src/gallium/drivers/r300/r300_state_derived.c |   11 +-
 src/gallium/drivers/r300/r300_texture.c       |   41 ++++--
 src/gallium/drivers/r300/r300_texture.h       |   12 +-
 src/gallium/drivers/r300/r300_texture_desc.c  |   13 +-
 src/gallium/drivers/r300/r300_texture_desc.h  |    3 +
 src/gallium/drivers/r300/r300_transfer.c      |   11 +-
 9 files changed, 194 insertions(+), 119 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index 3974aea..c780c8d 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -434,21 +434,14 @@ void r300_decompress_zmask_locked(struct r300_context *r300)
     pipe_surface_reference(&r300->locked_zbuffer, NULL);
 }
 
-/* Copy a block of pixels from one surface to another using HW. */
-static void r300_hw_copy_region(struct pipe_context* pipe,
-                                struct pipe_resource *dst,
-                                unsigned dst_level,
-                                unsigned dstx, unsigned dsty, unsigned dstz,
-                                struct pipe_resource *src,
-                                unsigned src_level,
-                                const struct pipe_box *src_box)
+bool r300_is_blit_supported(enum pipe_format format)
 {
-    struct r300_context* r300 = r300_context(pipe);
+    const struct util_format_description *desc =
+        util_format_description(format);
 
-    r300_blitter_begin(r300, R300_COPY);
-    util_blitter_copy_texture(r300->blitter, dst, dst_level, dstx, dsty, dstz,
-                              src, src_level, src_box, TRUE);
-    r300_blitter_end(r300);
+    return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ||
+           desc->layout == UTIL_FORMAT_LAYOUT_S3TC ||
+           desc->layout == UTIL_FORMAT_LAYOUT_RGTC;
 }
 
 /* Copy a block of pixels from one surface to another. */
@@ -460,103 +453,138 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
                                       unsigned src_level,
                                       const struct pipe_box *src_box)
 {
+    struct pipe_screen *screen = pipe->screen;
     struct r300_context *r300 = r300_context(pipe);
     struct pipe_framebuffer_state *fb =
         (struct pipe_framebuffer_state*)r300->fb_state.state;
-    struct pipe_resource old_src = *src;
-    struct pipe_resource old_dst = *dst;
-    struct pipe_resource new_src = old_src;
-    struct pipe_resource new_dst = old_dst;
-    const struct util_format_description *desc =
-            util_format_description(dst->format);
+    unsigned src_width0 = r300_resource(src)->tex.width0;
+    unsigned src_height0 = r300_resource(src)->tex.height0;
+    unsigned dst_width0 = r300_resource(dst)->tex.width0;
+    unsigned dst_height0 = r300_resource(dst)->tex.height0;
+    unsigned layout;
     struct pipe_box box;
+    struct pipe_sampler_view src_templ, *src_view;
+    struct pipe_surface dst_templ, *dst_view;
 
     /* Fallback for buffers. */
-    if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
+    if ((dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) ||
+        !r300_is_blit_supported(dst->format)) {
         util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
                                   src, src_level, src_box);
         return;
     }
 
-    if (r300->zmask_in_use && !r300->locked_zbuffer) {
-        if (fb->zsbuf->texture == src ||
-            fb->zsbuf->texture == dst) {
-            r300_decompress_zmask(r300);
-        }
-    }
+    /* The code below changes the texture format so that the copy can be done
+     * on hardware. E.g. depth-stencil surfaces are copied as RGBA
+     * colorbuffers. */
+
+    util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz, src_box);
+    util_blitter_default_src_texture(&src_templ, src, src_level);
+
+    layout = util_format_description(dst_templ.format)->layout;
 
     /* Handle non-renderable plain formats. */
-    if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
-        (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB ||
-         !pipe->screen->is_format_supported(pipe->screen,
-                                            src->format, src->target,
-                                            src->nr_samples,
-                                            PIPE_BIND_SAMPLER_VIEW) ||
-         !pipe->screen->is_format_supported(pipe->screen,
-                                            dst->format, dst->target,
-                                            dst->nr_samples,
-                                            PIPE_BIND_RENDER_TARGET))) {
-        switch (util_format_get_blocksize(old_dst.format)) {
+    if (layout == UTIL_FORMAT_LAYOUT_PLAIN &&
+        (!screen->is_format_supported(screen, src_templ.format, src->target,
+                                      src->nr_samples,
+                                      PIPE_BIND_SAMPLER_VIEW) ||
+         !screen->is_format_supported(screen, dst_templ.format, dst->target,
+                                      dst->nr_samples,
+                                      PIPE_BIND_RENDER_TARGET))) {
+        switch (util_format_get_blocksize(dst_templ.format)) {
             case 1:
-                new_dst.format = PIPE_FORMAT_I8_UNORM;
+                dst_templ.format = PIPE_FORMAT_I8_UNORM;
                 break;
             case 2:
-                new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM;
+                dst_templ.format = PIPE_FORMAT_B4G4R4A4_UNORM;
                 break;
             case 4:
-                new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+                dst_templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
                 break;
             case 8:
-                new_dst.format = PIPE_FORMAT_R16G16B16A16_UNORM;
+                dst_templ.format = PIPE_FORMAT_R16G16B16A16_UNORM;
                 break;
             default:
-                debug_printf("r300: surface_copy: Unhandled format: %s. Falling back to software.\n"
-                             "r300: surface_copy: Software fallback doesn't work for tiled textures.\n",
-                             util_format_short_name(dst->format));
+                debug_printf("r300: copy_region: Unhandled format: %s. Falling back to software.\n"
+                             "r300: copy_region: Software fallback doesn't work for tiled textures.\n",
+                             util_format_short_name(dst_templ.format));
         }
-        new_src.format = new_dst.format;
+        src_templ.format = dst_templ.format;
     }
 
     /* Handle compressed formats. */
-    if (desc->layout == UTIL_FORMAT_LAYOUT_S3TC ||
-        desc->layout == UTIL_FORMAT_LAYOUT_RGTC) {
-        switch (util_format_get_blocksize(old_dst.format)) {
+    if (layout == UTIL_FORMAT_LAYOUT_S3TC ||
+        layout == UTIL_FORMAT_LAYOUT_RGTC) {
+        assert(src_templ.format == dst_templ.format);
+
+        box = *src_box;
+        src_box = &box;
+
+        dst_width0 = align(dst_width0, 4);
+        dst_height0 = align(dst_height0, 4);
+        src_width0 = align(src_width0, 4);
+        src_height0 = align(src_height0, 4);
+        box.width = align(box.width, 4);
+        box.height = align(box.height, 4);
+
+        switch (util_format_get_blocksize(dst_templ.format)) {
         case 8:
-            /* 1 pixel = 4 bits,
-             * we set 1 pixel = 2 bytes ===> 4 times larger pixels. */
-            new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM;
+            /* one 4x4 pixel block has 8 bytes.
+             * we set 1 pixel = 4 bytes ===> 1 block corrensponds to 2 pixels. */
+            dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM;
+            dst_width0 = dst_width0 / 2;
+            src_width0 = src_width0 / 2;
+            dstx /= 2;
+            box.x /= 2;
+            box.width /= 2;
             break;
         case 16:
-            /* 1 pixel = 8 bits,
-             * we set 1 pixel = 4 bytes ===> 4 times larger pixels. */
-            new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+            /* one 4x4 pixel block has 16 bytes.
+             * we set 1 pixel = 4 bytes ===> 1 block corresponds to 4 pixels. */
+            dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM;
             break;
         }
+        src_templ.format = dst_templ.format;
 
-        /* Since the pixels are 4 times larger, we must decrease
-         * the image size and the coordinates 4 times. */
-        new_src.format = new_dst.format;
-        new_dst.height0 = (new_dst.height0 + 3) / 4;
-        new_src.height0 = (new_src.height0 + 3) / 4;
+        dst_height0 = dst_height0 / 4;
+        src_height0 = src_height0 / 4;
         dsty /= 4;
-        box = *src_box;
         box.y /= 4;
-        box.height = (box.height + 3) / 4;
-        src_box = &box;
+        box.height /= 4;
     }
 
-    if (old_src.format != new_src.format)
-        r300_resource_set_properties(pipe->screen, src, &new_src);
-    if (old_dst.format != new_dst.format)
-        r300_resource_set_properties(pipe->screen, dst, &new_dst);
+    /* Fallback for textures. */
+    if (!screen->is_format_supported(screen, dst_templ.format,
+                                     dst->target, dst->nr_samples,
+                                     PIPE_BIND_RENDER_TARGET) ||
+	!screen->is_format_supported(screen, src_templ.format,
+                                     src->target, src->nr_samples,
+                                     PIPE_BIND_SAMPLER_VIEW)) {
+        assert(0 && "this shouldn't happen, update r300_is_blit_supported");
+        util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
+                                  src, src_level, src_box);
+        return;
+    }
 
-    r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
-                        src, src_level, src_box);
+    /* Decompress ZMASK. */
+    if (r300->zmask_in_use && !r300->locked_zbuffer) {
+        if (fb->zsbuf->texture == src ||
+            fb->zsbuf->texture == dst) {
+            r300_decompress_zmask(r300);
+        }
+    }
+
+    dst_view = r300_create_surface_custom(pipe, dst, &dst_templ, dst_width0, dst_height0);
+    src_view = r300_create_sampler_view_custom(pipe, src, &src_templ, src_width0, src_height0);
+
+    r300_blitter_begin(r300, R300_COPY);
+    util_blitter_copy_texture_view(r300->blitter, dst_view, dstx, dsty,
+                                   src_view, src_box,
+                                   src_width0, src_height0);
+    r300_blitter_end(r300);
 
-    if (old_src.format != new_src.format)
-        r300_resource_set_properties(pipe->screen, src, &old_src);
-    if (old_dst.format != new_dst.format)
-        r300_resource_set_properties(pipe->screen, dst, &old_dst);
+    pipe_surface_reference(&dst_view, NULL);
+    pipe_sampler_view_reference(&src_view, NULL);
 }
 
 void r300_init_blit_functions(struct r300_context *r300)
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 5c0f53e..5588e51 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -196,6 +196,10 @@ struct r300_texture_format_state {
 struct r300_sampler_view {
     struct pipe_sampler_view base;
 
+    /* For resource_copy_region. */
+    unsigned width0_override;
+    unsigned height0_override;
+
     /* Swizzles in the UTIL_FORMAT_SWIZZLE_* representation,
      * derived from base. */
     unsigned char swizzle[4];
@@ -339,7 +343,6 @@ struct r300_texture_desc {
     unsigned offset_in_bytes[R300_MAX_TEXTURE_LEVELS];
 
     /* Strides for each mip-level. */
-    unsigned stride_in_pixels[R300_MAX_TEXTURE_LEVELS];
     unsigned stride_in_bytes[R300_MAX_TEXTURE_LEVELS];
 
     /* Size of one zslice or face or 2D image based on the texture target. */
@@ -395,10 +398,6 @@ struct r300_resource
     /* Texture description (addressing, layout, special features). */
     struct r300_texture_desc tex;
 
-    /* Registers carrying texture format data. */
-    /* Only format-independent bits should be filled in. */
-    struct r300_texture_format_state tx_format;
-
     /* This is the level tiling flags were last time set for.
      * It's used to prevent redundant tiling-flags changes from happening.*/
     unsigned surface_level;
@@ -680,6 +679,7 @@ void r300_init_resource_functions(struct r300_context* r300);
 void r300_decompress_zmask(struct r300_context *r300);
 void r300_decompress_zmask_locked_unsafe(struct r300_context *r300);
 void r300_decompress_zmask_locked(struct r300_context *r300);
+bool r300_is_blit_supported(enum pipe_format format);
 
 /* r300_flush.c */
 void r300_flush(struct pipe_context *pipe,
@@ -718,6 +718,13 @@ void r300_mark_fb_state_dirty(struct r300_context *r300,
                               enum r300_fb_state_change change);
 void r300_mark_fs_code_dirty(struct r300_context *r300);
 
+struct pipe_sampler_view *
+r300_create_sampler_view_custom(struct pipe_context *pipe,
+                         struct pipe_resource *texture,
+                         const struct pipe_sampler_view *templ,
+                         unsigned width0_override,
+                         unsigned height0_override);
+
 /* r300_state_derived.c */
 void r300_update_derived_state(struct r300_context* r300);
 
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index d704057..3606e0b 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -756,7 +756,7 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index,
             "r300:   %s[%i] Dim: %ix%i, Firstlayer: %i, "
             "Lastlayer: %i, Level: %i, Format: %s\n"
 
-            "r300:     TEX: Macro: %s, Micro: %s, Pitch: %i, "
+            "r300:     TEX: Macro: %s, Micro: %s, "
             "Dim: %ix%ix%i, LastLevel: %i, Format: %s\n",
 
             binding, index, surf->width, surf->height,
@@ -765,9 +765,8 @@ static void r300_print_fb_surf_info(struct pipe_surface *surf, unsigned index,
 
             rtex->tex.macrotile[0] ? "YES" : " NO",
             rtex->tex.microtile ? "YES" : " NO",
-            rtex->tex.stride_in_pixels[0],
             tex->width0, tex->height0, tex->depth0,
-            tex->last_level, util_format_short_name(tex->format));
+            tex->last_level, util_format_short_name(surf->format));
 }
 
 void r300_mark_fb_state_dirty(struct r300_context *r300,
@@ -888,7 +887,7 @@ r300_set_framebuffer_state(struct pipe_context* pipe,
     r300_mark_fb_state_dirty(r300, R300_CHANGED_FB_STATE);
 
     if (state->zsbuf) {
-        switch (util_format_get_blocksize(state->zsbuf->texture->format)) {
+        switch (util_format_get_blocksize(state->zsbuf->format)) {
         case 2:
             zbuffer_bpp = 16;
             break;
@@ -1458,10 +1457,12 @@ static void r300_set_fragment_sampler_views(struct pipe_context* pipe,
     }
 }
 
-static struct pipe_sampler_view *
-r300_create_sampler_view(struct pipe_context *pipe,
+struct pipe_sampler_view *
+r300_create_sampler_view_custom(struct pipe_context *pipe,
                          struct pipe_resource *texture,
-                         const struct pipe_sampler_view *templ)
+                         const struct pipe_sampler_view *templ,
+                         unsigned width0_override,
+                         unsigned height0_override)
 {
     struct r300_sampler_view *view = CALLOC_STRUCT(r300_sampler_view);
     struct r300_resource *tex = r300_resource(texture);
@@ -1477,6 +1478,8 @@ r300_create_sampler_view(struct pipe_context *pipe,
         view->base.texture = NULL;
         pipe_resource_reference(&view->base.texture, texture);
 
+	view->width0_override = width0_override;
+	view->height0_override = height0_override;
         view->swizzle[0] = templ->swizzle_r;
         view->swizzle[1] = templ->swizzle_g;
         view->swizzle[2] = templ->swizzle_b;
@@ -1493,7 +1496,10 @@ r300_create_sampler_view(struct pipe_context *pipe,
         }
         assert(hwformat != ~0);
 
-        view->format = tex->tx_format;
+	r300_texture_setup_format_state(r300_screen(pipe->screen), tex,
+					templ->format, 0,
+	                                width0_override, height0_override,
+					&view->format);
         view->format.format1 |= hwformat;
         if (is_r500) {
             view->format.format2 |= r500_tx_format_msb_bit(templ->format);
@@ -1503,6 +1509,17 @@ r300_create_sampler_view(struct pipe_context *pipe,
     return (struct pipe_sampler_view*)view;
 }
 
+static struct pipe_sampler_view *
+r300_create_sampler_view(struct pipe_context *pipe,
+                         struct pipe_resource *texture,
+                         const struct pipe_sampler_view *templ)
+{
+    return r300_create_sampler_view_custom(pipe, texture, templ,
+                                           r300_resource(texture)->tex.width0,
+                                           r300_resource(texture)->tex.height0);
+}
+
+
 static void
 r300_sampler_view_destroy(struct pipe_context *pipe,
                           struct pipe_sampler_view *view)
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index c1e25c6..2dabf18 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -785,7 +785,10 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
                 offset = tex->tex.offset_in_bytes[base_level];
 
                 r300_texture_setup_format_state(r300->screen, tex,
+                                                view->base.format,
                                                 base_level,
+                                                view->width0_override,
+		                                view->height0_override,
                                                 &texstate->format);
                 texstate->format.tile_config |= offset & 0xffffffe0;
                 assert((offset & 0x1f) == 0);
@@ -795,11 +798,11 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
             texstate->format.format1 |= view->texcache_region;
 
             /* Depth textures are kinda special. */
-            if (util_format_is_depth_or_stencil(tex->b.b.b.format)) {
+            if (util_format_is_depth_or_stencil(view->base.format)) {
                 unsigned char depth_swizzle[4];
 
                 if (!r300->screen->caps.is_r500 &&
-                    util_format_get_blocksizebits(tex->b.b.b.format) == 32) {
+                    util_format_get_blocksizebits(view->base.format) == 32) {
                     /* X24x8 is sampled as Y16X16 on r3xx-r4xx.
                      * The depth here is at the Y component. */
                     for (j = 0; j < 4; j++)
@@ -824,7 +827,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
             }
 
             if (r300->screen->caps.dxtc_swizzle &&
-                util_format_is_compressed(tex->b.b.b.format)) {
+                util_format_is_compressed(view->base.format)) {
                 texstate->filter1 |= R400_DXTC_SWIZZLE_ENABLE;
             }
 
@@ -870,7 +873,7 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
             }
 
             /* Float textures only support nearest and mip-nearest filtering. */
-            if (util_format_is_float(tex->b.b.b.format)) {
+            if (util_format_is_float(view->base.format)) {
                 /* No MAG linear filtering. */
                 if ((texstate->filter0 & R300_TX_MAG_FILTER_MASK) ==
                     R300_TX_MAG_FILTER_LINEAR) {
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 6fc60fb..b63afa1 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -722,7 +722,10 @@ boolean r300_is_sampler_format_supported(enum pipe_format format)
 
 void r300_texture_setup_format_state(struct r300_screen *screen,
                                      struct r300_resource *tex,
+                                     enum pipe_format format,
                                      unsigned level,
+                                     unsigned width0_override,
+                                     unsigned height0_override,
                                      struct r300_texture_format_state *out)
 {
     struct pipe_resource *pt = &tex->b.b.b;
@@ -731,8 +734,8 @@ void r300_texture_setup_format_state(struct r300_screen *screen,
     unsigned width, height, depth;
     unsigned txwidth, txheight, txdepth;
 
-    width = u_minify(desc->width0, level);
-    height = u_minify(desc->height0, level);
+    width = u_minify(width0_override, level);
+    height = u_minify(height0_override, level);
     depth = u_minify(desc->depth0, level);
 
     txwidth = (width - 1) & 0x7ff;
@@ -752,9 +755,11 @@ void r300_texture_setup_format_state(struct r300_screen *screen,
         R300_TX_DEPTH(txdepth);
 
     if (desc->uses_stride_addressing) {
+        unsigned stride =
+            r300_stride_to_width(format, desc->stride_in_bytes[level]);
         /* rectangles love this */
         out->format0 |= R300_TX_PITCH_EN;
-        out->format2 = (desc->stride_in_pixels[level] - 1) & 0x1fff;
+        out->format2 = (stride - 1) & 0x1fff;
     }
 
     if (pt->target == PIPE_TEXTURE_CUBE) {
@@ -803,11 +808,13 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf)
 {
     struct r300_resource *tex = r300_resource(surf->base.texture);
     unsigned level = surf->base.u.tex.level;
+    unsigned stride =
+      r300_stride_to_width(surf->base.format, tex->tex.stride_in_bytes[level]);
 
     /* Set framebuffer state. */
     if (util_format_is_depth_or_stencil(surf->base.format)) {
         surf->pitch =
-                tex->tex.stride_in_pixels[level] |
+                stride |
                 R300_DEPTHMACROTILE(tex->tex.macrotile[level]) |
                 R300_DEPTHMICROTILE(tex->tex.microtile);
         surf->format = r300_translate_zsformat(surf->base.format);
@@ -815,7 +822,7 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf)
         surf->pitch_hiz = tex->tex.hiz_stride_in_pixels[level];
     } else {
         surf->pitch =
-                tex->tex.stride_in_pixels[level] |
+                stride |
                 r300_translate_colorformat(surf->base.format) |
                 R300_COLOR_TILE(tex->tex.macrotile[level]) |
                 R300_COLOR_MICROTILE(tex->tex.microtile);
@@ -823,7 +830,7 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf)
     }
 }
 
-void r300_resource_set_properties(struct pipe_screen *screen,
+static void r300_resource_set_properties(struct pipe_screen *screen,
                                   struct pipe_resource *tex,
                                   const struct pipe_resource *new_properties)
 {
@@ -836,7 +843,6 @@ void r300_resource_set_properties(struct pipe_screen *screen,
         util_format_short_name(new_properties->format));
 
     r300_texture_desc_init(rscreen, res, new_properties);
-    r300_texture_setup_format_state(rscreen, res, 0, &res->tx_format);
 }
 
 static void r300_texture_destroy(struct pipe_screen *screen,
@@ -995,9 +1001,11 @@ struct pipe_resource *r300_texture_from_handle(struct pipe_screen *screen,
 
 /* Not required to implement u_resource_vtbl, consider moving to another file:
  */
-struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
+struct pipe_surface* r300_create_surface_custom(struct pipe_context * ctx,
                                          struct pipe_resource* texture,
-                                         const struct pipe_surface *surf_tmpl)
+                                         const struct pipe_surface *surf_tmpl,
+                                         unsigned width0_override,
+					 unsigned height0_override)
 {
     struct r300_resource* tex = r300_resource(texture);
     struct r300_surface* surface = CALLOC_STRUCT(r300_surface);
@@ -1012,8 +1020,8 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
         pipe_resource_reference(&surface->base.texture, texture);
         surface->base.context = ctx;
         surface->base.format = surf_tmpl->format;
-        surface->base.width = u_minify(texture->width0, level);
-        surface->base.height = u_minify(texture->height0, level);
+        surface->base.width = u_minify(width0_override, level);
+        surface->base.height = u_minify(height0_override, level);
         surface->base.usage = surf_tmpl->usage;
         surface->base.u.tex.level = level;
         surface->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer;
@@ -1036,7 +1044,7 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
         surface->cbzb_width = align(surface->base.width, 64);
 
         /* Height must be aligned to the size of a tile. */
-        tile_height = r300_get_pixel_alignment(tex->b.b.b.format,
+        tile_height = r300_get_pixel_alignment(surface->base.format,
                                                tex->b.b.b.nr_samples,
                                                tex->tex.microtile,
                                                tex->tex.macrotile[level],
@@ -1070,6 +1078,15 @@ struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
     return &surface->base;
 }
 
+struct pipe_surface* r300_create_surface(struct pipe_context * ctx,
+                                         struct pipe_resource* texture,
+                                         const struct pipe_surface *surf_tmpl)
+{
+    return r300_create_surface_custom(ctx, texture, surf_tmpl,
+                                      texture->width0,
+                                      texture->height0);
+}
+
 /* Not required to implement u_resource_vtbl, consider moving to another file:
  */
 void r300_surface_destroy(struct pipe_context *ctx, struct pipe_surface* s)
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index f87d284..213bdff 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -46,10 +46,6 @@ uint32_t r300_translate_texformat(enum pipe_format format,
 
 uint32_t r500_tx_format_msb_bit(enum pipe_format format);
 
-void r300_resource_set_properties(struct pipe_screen *screen,
-                                  struct pipe_resource *tex,
-                                  const struct pipe_resource *new_properties);
-
 boolean r300_is_colorbuffer_format_supported(enum pipe_format format);
 
 boolean r300_is_zs_format_supported(enum pipe_format format);
@@ -58,7 +54,10 @@ boolean r300_is_sampler_format_supported(enum pipe_format format);
 
 void r300_texture_setup_format_state(struct r300_screen *screen,
                                      struct r300_resource *tex,
+                                     enum pipe_format format,
                                      unsigned level,
+                                     unsigned width0_override,
+                                     unsigned height0_override,
                                      struct r300_texture_format_state *out);
 
 boolean r300_resource_get_handle(struct pipe_screen* screen,
@@ -74,6 +73,11 @@ struct pipe_resource*
 r300_texture_create(struct pipe_screen* screen,
 		    const struct pipe_resource* templ);
 
+struct pipe_surface* r300_create_surface_custom(struct pipe_context * ctx,
+                                         struct pipe_resource* texture,
+                                         const struct pipe_surface *surf_tmpl,
+                                         unsigned width0_override,
+					 unsigned height0_override);
 
 struct pipe_surface* r300_create_surface(struct pipe_context *ctx,
                                          struct pipe_resource* texture,
diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c
index 926bb0b..c250bf1 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.c
+++ b/src/gallium/drivers/r300/r300_texture_desc.c
@@ -206,8 +206,8 @@ static unsigned r300_texture_get_nblocksy(struct r300_resource *tex,
 }
 
 /* Get a width in pixels from a stride in bytes. */
-static unsigned stride_to_width(enum pipe_format format,
-                                unsigned stride_in_bytes)
+unsigned r300_stride_to_width(enum pipe_format format,
+                              unsigned stride_in_bytes)
 {
     return (stride_in_bytes / util_format_get_blocksize(format)) *
             util_format_get_blockwidth(format);
@@ -261,7 +261,6 @@ static void r300_setup_miptree(struct r300_screen *screen,
         tex->tex.size_in_bytes = tex->tex.offset_in_bytes[i] + size;
         tex->tex.layer_size_in_bytes[i] = layer_size;
         tex->tex.stride_in_bytes[i] = stride;
-        tex->tex.stride_in_pixels[i] = stride_to_width(tex->b.b.b.format, stride);
         tex->tex.cbzb_allowed[i] = tex->tex.cbzb_allowed[i] && aligned_for_cbzb;
 
         SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d "
@@ -277,7 +276,7 @@ static void r300_setup_flags(struct r300_resource *tex)
     tex->tex.uses_stride_addressing =
         !util_is_power_of_two(tex->b.b.b.width0) ||
         (tex->tex.stride_in_bytes_override &&
-         stride_to_width(tex->b.b.b.format,
+         r300_stride_to_width(tex->b.b.b.format,
                          tex->tex.stride_in_bytes_override) != tex->b.b.b.width0);
 
     tex->tex.is_npot =
@@ -368,7 +367,9 @@ static void r300_setup_hyperz_properties(struct r300_screen *screen,
         for (i = 0; i <= tex->b.b.b.last_level; i++) {
             unsigned zcomp_numdw, zcompsize, hiz_numdw, stride, height;
 
-            stride = align(tex->tex.stride_in_pixels[i], 16);
+            stride = r300_stride_to_width(tex->b.b.b.format,
+                                          tex->tex.stride_in_bytes[i]);
+            stride = align(stride, 16);
             height = u_minify(tex->b.b.b.height0, i);
 
             /* The 8x8 compression mode needs macrotiling. */
@@ -467,7 +468,7 @@ static void r300_tex_print_info(struct r300_resource *tex,
             func,
             tex->tex.macrotile[0] ? "YES" : " NO",
             tex->tex.microtile ? "YES" : " NO",
-            tex->tex.stride_in_pixels[0],
+            r300_stride_to_width(tex->b.b.b.format, tex->tex.stride_in_bytes[0]),
             tex->b.b.b.width0, tex->b.b.b.height0, tex->b.b.b.depth0,
             tex->b.b.b.last_level, tex->tex.size_in_bytes,
             util_format_short_name(tex->b.b.b.format));
diff --git a/src/gallium/drivers/r300/r300_texture_desc.h b/src/gallium/drivers/r300/r300_texture_desc.h
index 591592d..dd2a07e 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.h
+++ b/src/gallium/drivers/r300/r300_texture_desc.h
@@ -50,4 +50,7 @@ void r300_texture_desc_init(struct r300_screen *rscreen,
 unsigned r300_texture_get_offset(struct r300_resource *tex,
                                  unsigned level, unsigned layer);
 
+unsigned r300_stride_to_width(enum pipe_format format,
+                              unsigned stride_in_bytes);
+
 #endif
diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c
index 57d60a0..afdd530 100644
--- a/src/gallium/drivers/r300/r300_transfer.c
+++ b/src/gallium/drivers/r300/r300_transfer.c
@@ -87,9 +87,7 @@ r300_texture_get_transfer(struct pipe_context *ctx,
     struct r300_resource *tex = r300_resource(texture);
     struct r300_transfer *trans;
     struct pipe_resource base;
-    boolean referenced_cs, referenced_hw, blittable;
-    const struct util_format_description *desc =
-        util_format_description(texture->format);
+    boolean referenced_cs, referenced_hw;
 
     referenced_cs =
         r300->rws->cs_is_buffer_referenced(r300->cs, tex->cs_buf);
@@ -100,10 +98,6 @@ r300_texture_get_transfer(struct pipe_context *ctx,
             r300->rws->buffer_is_busy(tex->buf, RADEON_USAGE_READWRITE);
     }
 
-    blittable = desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ||
-                desc->layout == UTIL_FORMAT_LAYOUT_S3TC ||
-                desc->layout == UTIL_FORMAT_LAYOUT_RGTC;
-
     trans = CALLOC_STRUCT(r300_transfer);
     if (trans) {
         /* Initialize the transfer object. */
@@ -116,7 +110,8 @@ r300_texture_get_transfer(struct pipe_context *ctx,
          * for this transfer.
          * Also make write transfers pipelined. */
         if (tex->tex.microtile || tex->tex.macrotile[level] ||
-            (referenced_hw && blittable && !(usage & PIPE_TRANSFER_READ))) {
+            (referenced_hw && !(usage & PIPE_TRANSFER_READ) &&
+             r300_is_blit_supported(texture->format))) {
             if (r300->blitter->running) {
                 fprintf(stderr, "r300: ERROR: Blitter recursion in texture_get_transfer.\n");
                 os_break();




More information about the mesa-commit mailing list