From 7c24a4c6a86402be1f68d23f4d52d4d071957801 Mon Sep 17 00:00:00 2001 From: Marek Olšák Date: Thu, 10 Feb 2011 10:16:21 +0100 Subject: 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(-) (limited to 'src/gallium') diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index cadd090d02..3fa1504ecd 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 e55f138d63..480233bae5 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 cf4a2e9dae..bc4762c108 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 41a02f37ce..41b57b502f 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 5b4d7b72af..8ed0374513 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 a4838bea81..158a387478 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 eb946ba7c2..221e5a314a 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 24db5f5fc9..ce6e9643ec 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 7265fa733e..f2b6b45ef1 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; -- cgit v1.2.3