r300g: add a way to change texture properties arbitrarily

So that we can implement resource_copy on arbitrary data.
This commit is contained in:
Marek Olšák 2011-02-10 10:16:21 +01:00
parent 56ba7e913f
commit 7c24a4c6a8
9 changed files with 104 additions and 76 deletions

View file

@ -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;

View file

@ -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];

View file

@ -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;
}

View file

@ -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. */

View file

@ -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);

View file

@ -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);

View file

@ -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;
}

View file

@ -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);

View file

@ -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;