summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Olšák <[email protected]>2011-02-10 10:16:21 +0100
committerMarek Olšák <[email protected]>2011-02-10 11:27:35 +0100
commit7c24a4c6a86402be1f68d23f4d52d4d071957801 (patch)
treef376fc6a6b24bdf10eec03366be4bd8dc88bde3f
parent56ba7e913fef0ea2b1bead582108f9ab3ab8263d (diff)
r300g: add a way to change texture properties arbitrarily
So that we can implement resource_copy on arbitrary data.
-rw-r--r--src/gallium/drivers/r300/r300_blit.c51
-rw-r--r--src/gallium/drivers/r300/r300_context.h4
-rw-r--r--src/gallium/drivers/r300/r300_screen_buffer.c2
-rw-r--r--src/gallium/drivers/r300/r300_state_derived.c13
-rw-r--r--src/gallium/drivers/r300/r300_texture.c57
-rw-r--r--src/gallium/drivers/r300/r300_texture.h5
-rw-r--r--src/gallium/drivers/r300/r300_texture_desc.c37
-rw-r--r--src/gallium/drivers/r300/r300_texture_desc.h6
-rw-r--r--src/gallium/drivers/r300/r300_transfer.c5
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 cadd090d029..3fa1504ecd9 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 e55f138d638..480233bae5b 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 cf4a2e9dae5..bc4762c108a 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 41a02f37ce0..41b57b502fc 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 5b4d7b72af1..8ed03745134 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 a4838bea81e..158a387478f 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 eb946ba7c28..221e5a314ac 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 24db5f5fc98..ce6e9643ec6 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 7265fa733e9..f2b6b45ef1b 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;