r600g: don't modify pipe_resource in resource_copy_region, fixing race condition
pipe_resource can be shared between contexts, we shouldn't modify its description. Instead, let's use the resource "views" (sampler views and surfaces), where we can freely change almost any property of a resource.
This commit is contained in:
@@ -979,9 +979,11 @@ static void *evergreen_create_sampler_state(struct pipe_context *ctx,
|
||||
return ss;
|
||||
}
|
||||
|
||||
static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_context *ctx,
|
||||
struct pipe_resource *texture,
|
||||
const struct pipe_sampler_view *state)
|
||||
struct pipe_sampler_view *
|
||||
evergreen_create_sampler_view_custom(struct pipe_context *ctx,
|
||||
struct pipe_resource *texture,
|
||||
const struct pipe_sampler_view *state,
|
||||
unsigned width0, unsigned height0)
|
||||
{
|
||||
struct r600_screen *rscreen = (struct r600_screen*)ctx->screen;
|
||||
struct r600_pipe_sampler_view *view = CALLOC_STRUCT(r600_pipe_sampler_view);
|
||||
@@ -1027,8 +1029,8 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte
|
||||
|
||||
endian = r600_colorformat_endian_swap(format);
|
||||
|
||||
width = tmp->surface.level[0].npix_x;
|
||||
height = tmp->surface.level[0].npix_y;
|
||||
width = width0;
|
||||
height = height0;
|
||||
depth = tmp->surface.level[0].npix_z;
|
||||
pitch = tmp->surface.level[0].nblk_x * util_format_get_blockwidth(state->format);
|
||||
tile_type = tmp->tile_type;
|
||||
@@ -1116,6 +1118,15 @@ static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_conte
|
||||
return &view->base;
|
||||
}
|
||||
|
||||
static struct pipe_sampler_view *
|
||||
evergreen_create_sampler_view(struct pipe_context *ctx,
|
||||
struct pipe_resource *tex,
|
||||
const struct pipe_sampler_view *state)
|
||||
{
|
||||
return evergreen_create_sampler_view_custom(ctx, tex, state,
|
||||
tex->width0, tex->height0);
|
||||
}
|
||||
|
||||
static void evergreen_emit_clip_state(struct r600_context *rctx, struct r600_atom *atom)
|
||||
{
|
||||
struct radeon_winsys_cs *cs = rctx->cs;
|
||||
|
||||
@@ -434,103 +434,6 @@ void r600_copy_buffer(struct pipe_context *ctx, struct
|
||||
}
|
||||
}
|
||||
|
||||
struct texture_orig_info {
|
||||
unsigned format;
|
||||
unsigned width0;
|
||||
unsigned height0;
|
||||
unsigned npix_x;
|
||||
unsigned npix_y;
|
||||
unsigned npix0_x;
|
||||
unsigned npix0_y;
|
||||
};
|
||||
|
||||
static void r600_compressed_to_blittable(struct pipe_resource *tex,
|
||||
unsigned level,
|
||||
struct texture_orig_info *orig)
|
||||
{
|
||||
struct r600_texture *rtex = (struct r600_texture*)tex;
|
||||
unsigned pixsize = util_format_get_blocksize(rtex->resource.b.b.format);
|
||||
int new_format;
|
||||
int new_height, new_width;
|
||||
|
||||
orig->format = tex->format;
|
||||
orig->width0 = tex->width0;
|
||||
orig->height0 = tex->height0;
|
||||
orig->npix0_x = rtex->surface.level[0].npix_x;
|
||||
orig->npix0_y = rtex->surface.level[0].npix_y;
|
||||
orig->npix_x = rtex->surface.level[level].npix_x;
|
||||
orig->npix_y = rtex->surface.level[level].npix_y;
|
||||
|
||||
if (pixsize == 8)
|
||||
new_format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */
|
||||
else
|
||||
new_format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */
|
||||
|
||||
new_width = util_format_get_nblocksx(tex->format, orig->width0);
|
||||
new_height = util_format_get_nblocksy(tex->format, orig->height0);
|
||||
|
||||
tex->width0 = new_width;
|
||||
tex->height0 = new_height;
|
||||
tex->format = new_format;
|
||||
rtex->surface.level[0].npix_x = util_format_get_nblocksx(orig->format, orig->npix0_x);
|
||||
rtex->surface.level[0].npix_y = util_format_get_nblocksy(orig->format, orig->npix0_y);
|
||||
rtex->surface.level[level].npix_x = util_format_get_nblocksx(orig->format, orig->npix_x);
|
||||
rtex->surface.level[level].npix_y = util_format_get_nblocksy(orig->format, orig->npix_y);
|
||||
}
|
||||
|
||||
static void r600_subsampled_2x1_32bpp_to_blittable(struct pipe_resource *tex,
|
||||
unsigned level,
|
||||
struct texture_orig_info *orig)
|
||||
{
|
||||
struct r600_texture *rtex = (struct r600_texture*)tex;
|
||||
|
||||
orig->format = tex->format;
|
||||
orig->width0 = tex->width0;
|
||||
orig->height0 = tex->height0;
|
||||
orig->npix0_x = rtex->surface.level[0].npix_x;
|
||||
orig->npix0_y = rtex->surface.level[0].npix_y;
|
||||
orig->npix_x = rtex->surface.level[level].npix_x;
|
||||
orig->npix_y = rtex->surface.level[level].npix_y;
|
||||
|
||||
tex->width0 = util_format_get_nblocksx(orig->format, orig->width0);
|
||||
tex->format = PIPE_FORMAT_R8G8B8A8_UINT;
|
||||
rtex->surface.level[0].npix_x = util_format_get_nblocksx(orig->format, orig->npix0_x);
|
||||
rtex->surface.level[level].npix_x = util_format_get_nblocksx(orig->format, orig->npix_x);
|
||||
}
|
||||
|
||||
static void r600_change_format(struct pipe_resource *tex,
|
||||
unsigned level,
|
||||
struct texture_orig_info *orig,
|
||||
enum pipe_format format)
|
||||
{
|
||||
struct r600_texture *rtex = (struct r600_texture*)tex;
|
||||
|
||||
orig->format = tex->format;
|
||||
orig->width0 = tex->width0;
|
||||
orig->height0 = tex->height0;
|
||||
orig->npix0_x = rtex->surface.level[0].npix_x;
|
||||
orig->npix0_y = rtex->surface.level[0].npix_y;
|
||||
orig->npix_x = rtex->surface.level[level].npix_x;
|
||||
orig->npix_y = rtex->surface.level[level].npix_y;
|
||||
|
||||
tex->format = format;
|
||||
}
|
||||
|
||||
static void r600_reset_blittable_to_orig(struct pipe_resource *tex,
|
||||
unsigned level,
|
||||
struct texture_orig_info *orig)
|
||||
{
|
||||
struct r600_texture *rtex = (struct r600_texture*)tex;
|
||||
|
||||
tex->format = orig->format;
|
||||
tex->width0 = orig->width0;
|
||||
tex->height0 = orig->height0;
|
||||
rtex->surface.level[0].npix_x = orig->npix0_x;
|
||||
rtex->surface.level[0].npix_y = orig->npix0_y;
|
||||
rtex->surface.level[level].npix_x = orig->npix_x;
|
||||
rtex->surface.level[level].npix_y = orig->npix_y;
|
||||
}
|
||||
|
||||
static bool util_format_is_subsampled_2x1_32bpp(enum pipe_format format)
|
||||
{
|
||||
const struct util_format_description *desc = util_format_description(format);
|
||||
@@ -550,12 +453,12 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
|
||||
const struct pipe_box *src_box)
|
||||
{
|
||||
struct r600_context *rctx = (struct r600_context *)ctx;
|
||||
struct texture_orig_info orig_info[2];
|
||||
struct r600_texture *rsrc = (struct r600_texture*)src;
|
||||
struct r600_texture *rdst = (struct r600_texture*)dst;
|
||||
struct pipe_surface *dst_view, dst_templ;
|
||||
struct pipe_sampler_view src_templ, *src_view;
|
||||
unsigned dst_width, dst_height, src_width0, src_height0, src_widthFL, src_heightFL;
|
||||
struct pipe_box sbox;
|
||||
const struct pipe_box *psbox = src_box;
|
||||
boolean restore_orig[2];
|
||||
|
||||
memset(orig_info, 0, sizeof(orig_info));
|
||||
|
||||
/* Handle buffers first. */
|
||||
if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
|
||||
@@ -572,53 +475,70 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
|
||||
return; /* error */
|
||||
}
|
||||
|
||||
restore_orig[0] = restore_orig[1] = FALSE;
|
||||
dst_width = rdst->surface.level[dst_level].npix_x;
|
||||
dst_height = rdst->surface.level[dst_level].npix_y;
|
||||
src_width0 = src->width0;
|
||||
src_height0 = src->height0;
|
||||
src_widthFL = rsrc->surface.level[src_level].npix_x;
|
||||
src_heightFL = rsrc->surface.level[src_level].npix_y;
|
||||
|
||||
if (util_format_is_compressed(src->format) &&
|
||||
util_format_is_compressed(dst->format)) {
|
||||
r600_compressed_to_blittable(src, src_level, &orig_info[0]);
|
||||
restore_orig[0] = TRUE;
|
||||
sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x);
|
||||
sbox.y = util_format_get_nblocksy(orig_info[0].format, src_box->y);
|
||||
util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz, src_box);
|
||||
util_blitter_default_src_texture(&src_templ, src, src_level);
|
||||
|
||||
if (util_format_is_compressed(src->format)) {
|
||||
unsigned blocksize = util_format_get_blocksize(src->format);
|
||||
|
||||
if (blocksize == 8)
|
||||
src_templ.format = PIPE_FORMAT_R16G16B16A16_UINT; /* 64-bit block */
|
||||
else
|
||||
src_templ.format = PIPE_FORMAT_R32G32B32A32_UINT; /* 128-bit block */
|
||||
dst_templ.format = src_templ.format;
|
||||
|
||||
dst_width = util_format_get_nblocksx(dst->format, rdst->surface.level[dst_level].npix_x);
|
||||
dst_height = util_format_get_nblocksy(dst->format, rdst->surface.level[dst_level].npix_y);
|
||||
src_width0 = util_format_get_nblocksx(src->format, src->width0);
|
||||
src_height0 = util_format_get_nblocksy(src->format, src->height0);
|
||||
src_widthFL = util_format_get_nblocksx(src->format, rsrc->surface.level[src_level].npix_x);
|
||||
src_heightFL = util_format_get_nblocksy(src->format, rsrc->surface.level[src_level].npix_y);
|
||||
|
||||
dstx = util_format_get_nblocksx(dst->format, dstx);
|
||||
dsty = util_format_get_nblocksy(dst->format, dsty);
|
||||
|
||||
sbox.x = util_format_get_nblocksx(src->format, src_box->x);
|
||||
sbox.y = util_format_get_nblocksy(src->format, src_box->y);
|
||||
sbox.z = src_box->z;
|
||||
sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width);
|
||||
sbox.height = util_format_get_nblocksy(orig_info[0].format, src_box->height);
|
||||
sbox.width = util_format_get_nblocksx(src->format, src_box->width);
|
||||
sbox.height = util_format_get_nblocksy(src->format, src_box->height);
|
||||
sbox.depth = src_box->depth;
|
||||
psbox = &sbox;
|
||||
|
||||
r600_compressed_to_blittable(dst, dst_level, &orig_info[1]);
|
||||
restore_orig[1] = TRUE;
|
||||
/* translate the dst box as well */
|
||||
dstx = util_format_get_nblocksx(orig_info[1].format, dstx);
|
||||
dsty = util_format_get_nblocksy(orig_info[1].format, dsty);
|
||||
src_box = &sbox;
|
||||
} else if (!util_blitter_is_copy_supported(rctx->blitter, dst, src,
|
||||
PIPE_MASK_RGBAZS)) {
|
||||
if (util_format_is_subsampled_2x1_32bpp(src->format) &&
|
||||
util_format_is_subsampled_2x1_32bpp(dst->format)) {
|
||||
r600_subsampled_2x1_32bpp_to_blittable(src, src_level, &orig_info[0]);
|
||||
r600_subsampled_2x1_32bpp_to_blittable(dst, dst_level, &orig_info[1]);
|
||||
if (util_format_is_subsampled_2x1_32bpp(src->format)) {
|
||||
|
||||
src_templ.format = PIPE_FORMAT_R8G8B8A8_UINT;
|
||||
dst_templ.format = PIPE_FORMAT_R8G8B8A8_UINT;
|
||||
|
||||
dst_width = util_format_get_nblocksx(dst->format, rdst->surface.level[dst_level].npix_x);
|
||||
src_width0 = util_format_get_nblocksx(src->format, src->width0);
|
||||
src_widthFL = util_format_get_nblocksx(src->format, rsrc->surface.level[src_level].npix_x);
|
||||
|
||||
dstx = util_format_get_nblocksx(dst->format, dstx);
|
||||
|
||||
sbox = *src_box;
|
||||
sbox.x = util_format_get_nblocksx(orig_info[0].format, src_box->x);
|
||||
sbox.width = util_format_get_nblocksx(orig_info[0].format, src_box->width);
|
||||
psbox = &sbox;
|
||||
|
||||
dstx = util_format_get_nblocksx(orig_info[1].format, dstx);
|
||||
sbox.x = util_format_get_nblocksx(src->format, src_box->x);
|
||||
sbox.width = util_format_get_nblocksx(src->format, src_box->width);
|
||||
src_box = &sbox;
|
||||
} else {
|
||||
unsigned blocksize = util_format_get_blocksize(src->format);
|
||||
|
||||
switch (blocksize) {
|
||||
case 1:
|
||||
r600_change_format(src, src_level, &orig_info[0],
|
||||
PIPE_FORMAT_R8_UNORM);
|
||||
r600_change_format(dst, dst_level, &orig_info[1],
|
||||
PIPE_FORMAT_R8_UNORM);
|
||||
dst_templ.format = PIPE_FORMAT_R8_UNORM;
|
||||
src_templ.format = PIPE_FORMAT_R8_UNORM;
|
||||
break;
|
||||
case 4:
|
||||
r600_change_format(src, src_level, &orig_info[0],
|
||||
PIPE_FORMAT_R8G8B8A8_UNORM);
|
||||
r600_change_format(dst, dst_level, &orig_info[1],
|
||||
PIPE_FORMAT_R8G8B8A8_UNORM);
|
||||
dst_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM;
|
||||
src_templ.format = PIPE_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Unhandled format %s with blocksize %u\n",
|
||||
@@ -626,24 +546,32 @@ static void r600_resource_copy_region(struct pipe_context *ctx,
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
restore_orig[0] = TRUE;
|
||||
restore_orig[1] = TRUE;
|
||||
}
|
||||
|
||||
dst_view = r600_create_surface_custom(ctx, dst, &dst_templ, dst_width, dst_height);
|
||||
|
||||
if (rctx->chip_class >= EVERGREEN) {
|
||||
src_view = evergreen_create_sampler_view_custom(ctx, src, &src_templ,
|
||||
src_width0, src_height0);
|
||||
} else {
|
||||
src_view = r600_create_sampler_view_custom(ctx, src, &src_templ,
|
||||
src_widthFL, src_heightFL);
|
||||
}
|
||||
|
||||
/* Copy. */
|
||||
/* XXX Multisample texturing is unimplemented on Cayman. In the meantime,
|
||||
* copy only the first sample (which is the only one that is uncompressed
|
||||
* and therefore doesn't return garbage). */
|
||||
r600_blitter_begin(ctx, R600_COPY_TEXTURE);
|
||||
util_blitter_copy_texture(rctx->blitter, dst, dst_level, dstx, dsty, dstz,
|
||||
src, src_level, psbox, PIPE_MASK_RGBAZS,
|
||||
util_blitter_blit_generic(rctx->blitter, dst_view, dstx, dsty,
|
||||
abs(src_box->width), abs(src_box->height),
|
||||
src_view, src_box, src_width0, src_height0,
|
||||
PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL,
|
||||
rctx->chip_class != CAYMAN);
|
||||
r600_blitter_end(ctx);
|
||||
|
||||
if (restore_orig[0])
|
||||
r600_reset_blittable_to_orig(src, src_level, &orig_info[0]);
|
||||
|
||||
if (restore_orig[1])
|
||||
r600_reset_blittable_to_orig(dst, dst_level, &orig_info[1]);
|
||||
pipe_surface_reference(&dst_view, NULL);
|
||||
pipe_sampler_view_reference(&src_view, NULL);
|
||||
}
|
||||
|
||||
static void r600_msaa_color_resolve(struct pipe_context *ctx,
|
||||
|
||||
@@ -516,6 +516,11 @@ static INLINE void r600_atom_dirty(struct r600_context *rctx, struct r600_atom *
|
||||
}
|
||||
|
||||
/* evergreen_state.c */
|
||||
struct pipe_sampler_view *
|
||||
evergreen_create_sampler_view_custom(struct pipe_context *ctx,
|
||||
struct pipe_resource *texture,
|
||||
const struct pipe_sampler_view *state,
|
||||
unsigned width0, unsigned height0);
|
||||
void evergreen_init_common_regs(struct r600_command_buffer *cb,
|
||||
enum chip_class ctx_chip_class,
|
||||
enum radeon_family ctx_family,
|
||||
@@ -591,6 +596,11 @@ int r600_compute_shader_create(struct pipe_context * ctx,
|
||||
void r600_pipe_shader_destroy(struct pipe_context *ctx, struct r600_pipe_shader *shader);
|
||||
|
||||
/* r600_state.c */
|
||||
struct pipe_sampler_view *
|
||||
r600_create_sampler_view_custom(struct pipe_context *ctx,
|
||||
struct pipe_resource *texture,
|
||||
const struct pipe_sampler_view *state,
|
||||
unsigned width_first_level, unsigned height_first_level);
|
||||
void r600_set_scissor_state(struct r600_context *rctx,
|
||||
const struct pipe_scissor_state *state);
|
||||
void r600_init_state_functions(struct r600_context *rctx);
|
||||
@@ -619,6 +629,10 @@ uint32_t r600_translate_texformat(struct pipe_screen *screen, enum pipe_format f
|
||||
uint32_t *word4_p, uint32_t *yuv_format_p);
|
||||
unsigned r600_texture_get_offset(struct r600_texture *rtex,
|
||||
unsigned level, unsigned layer);
|
||||
struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
|
||||
struct pipe_resource *texture,
|
||||
const struct pipe_surface *templ,
|
||||
unsigned width, unsigned height);
|
||||
|
||||
/* r600_translate.c */
|
||||
void r600_translate_index_buffer(struct r600_context *r600,
|
||||
|
||||
@@ -1007,9 +1007,11 @@ static void *r600_create_sampler_state(struct pipe_context *ctx,
|
||||
return ss;
|
||||
}
|
||||
|
||||
static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *ctx,
|
||||
struct pipe_resource *texture,
|
||||
const struct pipe_sampler_view *state)
|
||||
struct pipe_sampler_view *
|
||||
r600_create_sampler_view_custom(struct pipe_context *ctx,
|
||||
struct pipe_resource *texture,
|
||||
const struct pipe_sampler_view *state,
|
||||
unsigned width_first_level, unsigned height_first_level)
|
||||
{
|
||||
struct r600_pipe_sampler_view *view = CALLOC_STRUCT(r600_pipe_sampler_view);
|
||||
struct r600_texture *tmp = (struct r600_texture*)texture;
|
||||
@@ -1055,8 +1057,8 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
|
||||
|
||||
offset_level = state->u.tex.first_level;
|
||||
last_level = state->u.tex.last_level - offset_level;
|
||||
width = tmp->surface.level[offset_level].npix_x;
|
||||
height = tmp->surface.level[offset_level].npix_y;
|
||||
width = width_first_level;
|
||||
height = height_first_level;
|
||||
depth = tmp->surface.level[offset_level].npix_z;
|
||||
pitch = tmp->surface.level[offset_level].nblk_x * util_format_get_blockwidth(state->format);
|
||||
tile_type = tmp->tile_type;
|
||||
@@ -1116,6 +1118,18 @@ static struct pipe_sampler_view *r600_create_sampler_view(struct pipe_context *c
|
||||
return &view->base;
|
||||
}
|
||||
|
||||
static struct pipe_sampler_view *
|
||||
r600_create_sampler_view(struct pipe_context *ctx,
|
||||
struct pipe_resource *tex,
|
||||
const struct pipe_sampler_view *state)
|
||||
{
|
||||
struct r600_texture *rtex = (struct r600_texture*)tex;
|
||||
|
||||
return r600_create_sampler_view_custom(ctx, tex, state,
|
||||
rtex->surface.level[state->u.tex.first_level].npix_x,
|
||||
rtex->surface.level[state->u.tex.first_level].npix_y);
|
||||
}
|
||||
|
||||
static void r600_emit_clip_state(struct r600_context *rctx, struct r600_atom *atom)
|
||||
{
|
||||
struct radeon_winsys_cs *cs = rctx->cs;
|
||||
|
||||
@@ -481,13 +481,12 @@ struct pipe_resource *r600_texture_create(struct pipe_screen *screen,
|
||||
0, NULL, TRUE, &surface);
|
||||
}
|
||||
|
||||
static struct pipe_surface *r600_create_surface(struct pipe_context *pipe,
|
||||
struct pipe_surface *r600_create_surface_custom(struct pipe_context *pipe,
|
||||
struct pipe_resource *texture,
|
||||
const struct pipe_surface *templ)
|
||||
const struct pipe_surface *templ,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
struct r600_texture *rtex = (struct r600_texture*)texture;
|
||||
struct r600_surface *surface = CALLOC_STRUCT(r600_surface);
|
||||
unsigned level = templ->u.tex.level;
|
||||
|
||||
assert(templ->u.tex.first_layer == templ->u.tex.last_layer);
|
||||
if (surface == NULL)
|
||||
@@ -496,13 +495,25 @@ static struct pipe_surface *r600_create_surface(struct pipe_context *pipe,
|
||||
pipe_resource_reference(&surface->base.texture, texture);
|
||||
surface->base.context = pipe;
|
||||
surface->base.format = templ->format;
|
||||
surface->base.width = rtex->surface.level[level].npix_x;
|
||||
surface->base.height = rtex->surface.level[level].npix_y;
|
||||
surface->base.width = width;
|
||||
surface->base.height = height;
|
||||
surface->base.usage = templ->usage;
|
||||
surface->base.u = templ->u;
|
||||
return &surface->base;
|
||||
}
|
||||
|
||||
static struct pipe_surface *r600_create_surface(struct pipe_context *pipe,
|
||||
struct pipe_resource *texture,
|
||||
const struct pipe_surface *templ)
|
||||
{
|
||||
struct r600_texture *rtex = (struct r600_texture*)texture;
|
||||
unsigned level = templ->u.tex.level;
|
||||
|
||||
return r600_create_surface_custom(pipe, texture, templ,
|
||||
rtex->surface.level[level].npix_x,
|
||||
rtex->surface.level[level].npix_y);
|
||||
}
|
||||
|
||||
static void r600_surface_destroy(struct pipe_context *pipe,
|
||||
struct pipe_surface *surface)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user