Mesa (master): r300g: add a way to change texture properties arbitrarily

Marek Olšák mareko at kemper.freedesktop.org
Thu Feb 10 10:51:33 UTC 2011


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

Author: Marek Olšák <maraeo at gmail.com>
Date:   Thu Feb 10 10:16:21 2011 +0100

r300g: add a way to change texture properties arbitrarily

So that we can implement resource_copy on arbitrary data.

---

 src/gallium/drivers/r300/r300_blit.c          |   51 ++++++++++++----------
 src/gallium/drivers/r300/r300_context.h       |    4 ++
 src/gallium/drivers/r300/r300_screen_buffer.c |    2 +
 src/gallium/drivers/r300/r300_state_derived.c |   13 ++++--
 src/gallium/drivers/r300/r300_texture.c       |   57 +++++++++++++++----------
 src/gallium/drivers/r300/r300_texture.h       |    5 +-
 src/gallium/drivers/r300/r300_texture_desc.c  |   37 ++++++++--------
 src/gallium/drivers/r300/r300_texture_desc.h  |    6 +--
 src/gallium/drivers/r300/r300_transfer.c      |    5 ++
 9 files changed, 104 insertions(+), 76 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c
index cadd090..3fa1504 100644
--- a/src/gallium/drivers/r300/r300_blit.c
+++ b/src/gallium/drivers/r300/r300_blit.c
@@ -412,9 +412,12 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
     struct r300_context *r300 = r300_context(pipe);
     struct pipe_framebuffer_state *fb =
         (struct pipe_framebuffer_state*)r300->fb_state.state;
-    enum pipe_format old_format = dst->format;
-    enum pipe_format new_format = old_format;
-    const struct util_format_description *desc = util_format_description(old_format);
+    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);
 
     if (r300->zmask_in_use && !r300->zmask_locked) {
         if (fb->zsbuf->texture == src ||
@@ -429,46 +432,46 @@ static void r300_resource_copy_region(struct pipe_context *pipe,
     if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN &&
         (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB ||
          !pipe->screen->is_format_supported(pipe->screen,
-                                            old_format, src->target,
+                                            src->format, src->target,
                                             src->nr_samples,
-                                            PIPE_BIND_RENDER_TARGET |
-                                            PIPE_BIND_SAMPLER_VIEW, 0))) {
-        switch (util_format_get_blocksize(old_format)) {
+                                            PIPE_BIND_SAMPLER_VIEW, 0) ||
+         !pipe->screen->is_format_supported(pipe->screen,
+                                            dst->format, dst->target,
+                                            dst->nr_samples,
+                                            PIPE_BIND_RENDER_TARGET, 0))) {
+        switch (util_format_get_blocksize(old_dst.format)) {
             case 1:
-                new_format = PIPE_FORMAT_I8_UNORM;
+                new_dst.format = PIPE_FORMAT_I8_UNORM;
                 break;
             case 2:
-                new_format = PIPE_FORMAT_B4G4R4A4_UNORM;
+                new_dst.format = PIPE_FORMAT_B4G4R4A4_UNORM;
                 break;
             case 4:
-                new_format = PIPE_FORMAT_B8G8R8A8_UNORM;
+                new_dst.format = PIPE_FORMAT_B8G8R8A8_UNORM;
                 break;
             case 8:
-                new_format = PIPE_FORMAT_R16G16B16A16_UNORM;
+                new_dst.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(old_format));
+                             util_format_short_name(dst->format));
         }
+        new_src.format = new_dst.format;
     }
 
-    if (old_format != new_format) {
-        r300_texture_reinterpret_format(pipe->screen,
-                                        dst, new_format);
-        r300_texture_reinterpret_format(pipe->screen,
-                                        src, new_format);
-    }
+    if (old_src.format != new_src.format)
+        r300_resource_set_properties(pipe->screen, src, 0, &new_src);
+    if (old_dst.format != new_dst.format)
+        r300_resource_set_properties(pipe->screen, dst, 0, &new_dst);
 
     r300_hw_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
                         src, src_level, src_box);
 
-    if (old_format != new_format) {
-        r300_texture_reinterpret_format(pipe->screen,
-                                        dst, old_format);
-        r300_texture_reinterpret_format(pipe->screen,
-                                        src, old_format);
-    }
+    if (old_src.format != new_src.format)
+        r300_resource_set_properties(pipe->screen, src, 0, &old_src);
+    if (old_dst.format != new_dst.format)
+        r300_resource_set_properties(pipe->screen, dst, 0, &old_dst);
 
     if (r300->zmask_locked) {
         r300->zmask_locked = FALSE;
diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index e55f138..480233b 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -392,6 +392,7 @@ struct r300_resource
     struct r300_winsys_buffer *buf;
     struct r300_winsys_cs_buffer *cs_buf;
     enum r300_buffer_domain domain;
+    unsigned buf_size;
 
     /* Constant buffers are in user memory. */
     uint8_t *constant_buffer;
@@ -403,6 +404,9 @@ struct r300_resource
     /* Only format-independent bits should be filled in. */
     struct r300_texture_format_state tx_format;
 
+    /* Where the texture starts in the buffer. */
+    unsigned tex_offset;
+
     /* HiZ memory allocations. */
     struct mem_block *hiz_mem[R300_MAX_TEXTURE_LEVELS];
     boolean hiz_in_use[R300_MAX_TEXTURE_LEVELS];
diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c
index cf4a2e9..bc4762c 100644
--- a/src/gallium/drivers/r300/r300_screen_buffer.c
+++ b/src/gallium/drivers/r300/r300_screen_buffer.c
@@ -214,6 +214,7 @@ struct pipe_resource *r300_buffer_create(struct pipe_screen *screen,
     rbuf->b.user_ptr = NULL;
     rbuf->domain = R300_DOMAIN_GTT;
     rbuf->buf = NULL;
+    rbuf->buf_size = templ->width0;
     rbuf->constant_buffer = NULL;
 
     /* Alloc constant buffers in RAM. */
@@ -262,6 +263,7 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen,
     rbuf->b.user_ptr = ptr;
     rbuf->domain = R300_DOMAIN_GTT;
     rbuf->buf = NULL;
+    rbuf->buf_size = size;
     rbuf->constant_buffer = NULL;
     return &rbuf->b.b.b;
 }
diff --git a/src/gallium/drivers/r300/r300_state_derived.c b/src/gallium/drivers/r300/r300_state_derived.c
index 41a02f3..41b57b5 100644
--- a/src/gallium/drivers/r300/r300_state_derived.c
+++ b/src/gallium/drivers/r300/r300_state_derived.c
@@ -733,13 +733,18 @@ static void r300_merge_textures_and_samplers(struct r300_context* r300)
                 /* Even though we do not implement mipmapping for NPOT
                  * textures, we should at least honor the minimum level
                  * which is allowed to be displayed. We do this by setting up
-                 * an i-th mipmap level as the zero level. */
+                 * the i-th mipmap level as the zero level. */
+                unsigned offset = tex->tex_offset +
+                                  tex->tex.offset_in_bytes[min_level];
+
                 r300_texture_setup_format_state(r300->screen, tex,
                                                 min_level,
                                                 &texstate->format);
-                texstate->format.tile_config |=
-                        tex->tex.offset_in_bytes[min_level] & 0xffffffe0;
-                assert((tex->tex.offset_in_bytes[min_level] & 0x1f) == 0);
+                texstate->format.tile_config |= offset & 0xffffffe0;
+                assert((offset & 0x1f) == 0);
+            } else {
+                texstate->format.tile_config |= tex->tex_offset & 0xffffffe0;
+                assert((tex->tex_offset & 0x1f) == 0);
             }
 
             /* Assign a texture cache region. */
diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c
index 5b4d7b7..8ed0374 100644
--- a/src/gallium/drivers/r300/r300_texture.c
+++ b/src/gallium/drivers/r300/r300_texture.c
@@ -679,18 +679,27 @@ static void r300_texture_setup_fb_state(struct r300_surface *surf)
     }
 }
 
-void r300_texture_reinterpret_format(struct pipe_screen *screen,
+boolean r300_resource_set_properties(struct pipe_screen *screen,
                                      struct pipe_resource *tex,
-                                     enum pipe_format new_format)
+                                     unsigned offset,
+                                     const struct pipe_resource *new_properties)
 {
-    struct r300_screen *r300screen = r300_screen(screen);
+    struct r300_screen *rscreen = r300_screen(screen);
+    struct r300_resource *res = r300_resource(tex);
 
-    SCREEN_DBG(r300screen, DBG_TEX,
-        "r300: texture_reinterpret_format: %s -> %s\n",
+    SCREEN_DBG(rscreen, DBG_TEX,
+        "r300: texture_set_properties: %s -> %s\n",
         util_format_short_name(tex->format),
-        util_format_short_name(new_format));
+        util_format_short_name(new_properties->format));
 
-    tex->format = new_format;
+    if (!r300_texture_desc_init(rscreen, res, new_properties)) {
+        fprintf(stderr, "r300: ERROR: Cannot set texture properties.\n");
+        return FALSE;
+    }
+    res->tex_offset = offset;
+    r300_texture_setup_format_state(rscreen, res, 0, &res->tx_format);
+
+    return TRUE;
 }
 
 static void r300_texture_destroy(struct pipe_screen *screen,
@@ -755,28 +764,30 @@ r300_texture_create_object(struct r300_screen *rscreen,
         return NULL;
     }
 
-    /* Initialize the descriptor. */
-    if (!r300_texture_desc_init(rscreen, tex, base,
-                                microtile, macrotile,
-                                stride_in_bytes_override,
-                                max_buffer_size)) {
+    pipe_reference_init(&tex->b.b.b.reference, 1);
+    tex->b.b.b.screen = &rscreen->screen;
+    tex->b.b.b.usage = base->usage;
+    tex->b.b.b.bind = base->bind;
+    tex->b.b.b.flags = base->flags;
+    tex->b.b.vtbl = &r300_texture_vtbl;
+    tex->tex.microtile = microtile;
+    tex->tex.macrotile[0] = macrotile;
+    tex->tex.stride_in_bytes_override = stride_in_bytes_override;
+    tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ?
+                  R300_DOMAIN_GTT :
+                  R300_DOMAIN_VRAM | R300_DOMAIN_GTT;
+    tex->buf_size = max_buffer_size;
+
+    if (!r300_resource_set_properties(&rscreen->screen, &tex->b.b.b, 0, base)) {
         if (buffer)
             rws->buffer_reference(rws, &buffer, NULL);
         FREE(tex);
         return NULL;
     }
-    /* Initialize the hardware state. */
-    r300_texture_setup_format_state(rscreen, tex, 0, &tex->tx_format);
-
-    tex->b.b.vtbl = &r300_texture_vtbl;
-    pipe_reference_init(&tex->b.b.b.reference, 1);
-    tex->domain = base->flags & R300_RESOURCE_FLAG_TRANSFER ?
-                  R300_DOMAIN_GTT :
-                  R300_DOMAIN_VRAM | R300_DOMAIN_GTT;
-    tex->buf = buffer;
 
     /* Create the backing buffer if needed. */
-    if (!tex->buf) {
+    if (!buffer) {
+        tex->buf_size = tex->tex.size_in_bytes;
         tex->buf = rws->buffer_create(rws, tex->tex.size_in_bytes, 2048,
                                          base->bind, base->usage, tex->domain);
 
@@ -784,6 +795,8 @@ r300_texture_create_object(struct r300_screen *rscreen,
             FREE(tex);
             return NULL;
         }
+    } else {
+        tex->buf = buffer;
     }
 
     tex->cs_buf = rws->buffer_get_cs_handle(rws, tex->buf);
diff --git a/src/gallium/drivers/r300/r300_texture.h b/src/gallium/drivers/r300/r300_texture.h
index a4838be..158a387 100644
--- a/src/gallium/drivers/r300/r300_texture.h
+++ b/src/gallium/drivers/r300/r300_texture.h
@@ -46,9 +46,10 @@ uint32_t r300_translate_texformat(enum pipe_format format,
 
 uint32_t r500_tx_format_msb_bit(enum pipe_format format);
 
-void r300_texture_reinterpret_format(struct pipe_screen *screen,
+boolean r300_resource_set_properties(struct pipe_screen *screen,
                                      struct pipe_resource *tex,
-                                     enum pipe_format new_format);
+                                     unsigned offset,
+                                     const struct pipe_resource *new_properties);
 
 boolean r300_is_colorbuffer_format_supported(enum pipe_format format);
 
diff --git a/src/gallium/drivers/r300/r300_texture_desc.c b/src/gallium/drivers/r300/r300_texture_desc.c
index eb946ba..221e5a3 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.c
+++ b/src/gallium/drivers/r300/r300_texture_desc.c
@@ -401,6 +401,9 @@ static void r300_setup_tiling(struct r300_screen *screen,
     boolean is_zb = util_format_is_depth_or_stencil(format);
     boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING);
 
+    tex->tex.microtile = R300_BUFFER_LINEAR;
+    tex->tex.macrotile[0] = R300_BUFFER_LINEAR;
+
     if (!util_format_is_plain(format)) {
         return;
     }
@@ -453,15 +456,16 @@ static void r300_tex_print_info(struct r300_resource *tex,
 
 boolean r300_texture_desc_init(struct r300_screen *rscreen,
                                struct r300_resource *tex,
-                               const struct pipe_resource *base,
-                               enum r300_buffer_tiling microtile,
-                               enum r300_buffer_tiling macrotile,
-                               unsigned stride_in_bytes_override,
-                               unsigned max_buffer_size)
+                               const struct pipe_resource *base)
 {
-    tex->b.b.b = *base;
-    tex->b.b.b.screen = &rscreen->screen;
-    tex->tex.stride_in_bytes_override = stride_in_bytes_override;
+    tex->b.b.b.target = base->target;
+    tex->b.b.b.format = base->format;
+    tex->b.b.b.width0 = base->width0;
+    tex->b.b.b.height0 = base->height0;
+    tex->b.b.b.depth0 = base->depth0;
+    tex->b.b.b.array_size = base->array_size;
+    tex->b.b.b.last_level = base->last_level;
+    tex->b.b.b.nr_samples = base->nr_samples;
     tex->tex.width0 = base->width0;
     tex->tex.height0 = base->height0;
     tex->tex.depth0 = base->depth0;
@@ -476,13 +480,8 @@ boolean r300_texture_desc_init(struct r300_screen *rscreen,
     }
 
     /* Setup tiling. */
-    if (microtile == R300_BUFFER_SELECT_LAYOUT ||
-        macrotile == R300_BUFFER_SELECT_LAYOUT) {
+    if (tex->tex.microtile == R300_BUFFER_SELECT_LAYOUT) {
         r300_setup_tiling(rscreen, tex);
-    } else {
-        tex->tex.microtile = microtile;
-        tex->tex.macrotile[0] = macrotile;
-        assert(tex->b.b.b.last_level == 0);
     }
 
     r300_setup_cbzb_flags(rscreen, tex);
@@ -491,24 +490,24 @@ boolean r300_texture_desc_init(struct r300_screen *rscreen,
     r300_setup_miptree(rscreen, tex, TRUE);
     /* If the required buffer size is larger the given max size,
      * try again without the alignment for the CBZB clear. */
-    if (max_buffer_size && tex->tex.size_in_bytes > max_buffer_size) {
+    if (tex->buf_size && tex->tex.size_in_bytes > tex->buf_size) {
         r300_setup_miptree(rscreen, tex, FALSE);
     }
 
     r300_texture_3d_fix_mipmapping(rscreen, tex);
     r300_setup_zmask_flags(rscreen, tex);
 
-    if (max_buffer_size) {
+    if (tex->buf_size) {
         /* Make sure the buffer we got is large enough. */
-        if (tex->tex.size_in_bytes > max_buffer_size) {
+        if (tex->tex.size_in_bytes > tex->buf_size) {
             fprintf(stderr, "r300: texture_desc_init: The buffer is not "
                             "large enough. Got: %i, Need: %i, Info:\n",
-                            max_buffer_size, tex->tex.size_in_bytes);
+                            tex->buf_size, tex->tex.size_in_bytes);
             r300_tex_print_info(tex, "texture_desc_init");
             return FALSE;
         }
 
-        tex->tex.buffer_size_in_bytes = max_buffer_size;
+        tex->tex.buffer_size_in_bytes = tex->buf_size;
     } else {
         tex->tex.buffer_size_in_bytes = tex->tex.size_in_bytes;
     }
diff --git a/src/gallium/drivers/r300/r300_texture_desc.h b/src/gallium/drivers/r300/r300_texture_desc.h
index 24db5f5..ce6e964 100644
--- a/src/gallium/drivers/r300/r300_texture_desc.h
+++ b/src/gallium/drivers/r300/r300_texture_desc.h
@@ -45,11 +45,7 @@ unsigned r300_get_pixel_alignment(enum pipe_format format,
 
 boolean r300_texture_desc_init(struct r300_screen *rscreen,
                                struct r300_resource *tex,
-                               const struct pipe_resource *base,
-                               enum r300_buffer_tiling microtile,
-                               enum r300_buffer_tiling macrotile,
-                               unsigned stride_in_bytes_override,
-                               unsigned max_buffer_size);
+                               const struct pipe_resource *base);
 
 unsigned r300_texture_get_offset(struct r300_resource *tex,
                                  unsigned level, unsigned layer);
diff --git a/src/gallium/drivers/r300/r300_transfer.c b/src/gallium/drivers/r300/r300_transfer.c
index 7265fa7..f2b6b45 100644
--- a/src/gallium/drivers/r300/r300_transfer.c
+++ b/src/gallium/drivers/r300/r300_transfer.c
@@ -116,6 +116,11 @@ r300_texture_get_transfer(struct pipe_context *ctx,
          * Also make write transfers pipelined. */
         if (tex->tex.microtile || tex->tex.macrotile[level] ||
             ((referenced_hw & !(usage & PIPE_TRANSFER_READ)) && blittable)) {
+            if (r300->blitter->running) {
+                fprintf(stderr, "r300: ERROR: Blitter recursion in texture_get_transfer.\n");
+                os_break();
+            }
+
             base.target = PIPE_TEXTURE_2D;
             base.format = texture->format;
             base.width0 = box->width;




More information about the mesa-commit mailing list