svga: Fix out-of-sync backing surface

When a backing surface is reused, it is possible that
the original surface has been changed. So before the backing surface
is bound again, we need to sync up the surface.
This patch creates a new helper function svga_texture_copy_handle_resource()
to sync up the backing surface resource.

This patch, together with the backing surface dirty bit fix, fixes
the rendering corruption in NobelClinicianViewer when rotating the model.

Also tested with MTT glretrace, piglit, Cinebench, Turbine.

Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
Charmaine Lee 2017-04-04 13:02:45 -06:00 committed by Brian Paul
parent a08e3b88ab
commit ab96d1baf4

View file

@ -103,6 +103,43 @@ svga_texture_copy_handle(struct svga_context *svga,
}
/* A helper function to sync up the two surface handles.
*/
static void
svga_texture_copy_handle_resource(struct svga_context *svga,
struct svga_texture *src_tex,
struct svga_winsys_surface *dst,
unsigned int numMipLevels,
unsigned int numLayers,
unsigned int zoffset,
unsigned int mipoffset,
unsigned int layeroffset)
{
unsigned int i, j;
for (i = 0; i < numMipLevels; i++) {
unsigned int miplevel = i + mipoffset;
for (j = 0; j < numLayers; j++) {
if (svga_is_texture_level_defined(src_tex, j+layeroffset, miplevel)) {
unsigned depth = (zoffset < 0 ?
u_minify(src_tex->b.b.depth0, miplevel) : 1);
svga_texture_copy_handle(svga,
src_tex->handle,
0, 0, zoffset,
miplevel,
j + layeroffset,
dst, 0, 0, 0, i, j,
u_minify(src_tex->b.b.width0, miplevel),
u_minify(src_tex->b.b.height0, miplevel),
depth);
}
}
}
}
struct svga_winsys_surface *
svga_texture_view_surface(struct svga_context *svga,
struct svga_texture *tex,
@ -118,7 +155,6 @@ svga_texture_view_surface(struct svga_context *svga,
{
struct svga_screen *ss = svga_screen(svga->pipe.screen);
struct svga_winsys_surface *handle;
uint32_t i, j;
unsigned z_offset = 0;
boolean validated;
@ -172,25 +208,10 @@ svga_texture_view_surface(struct svga_context *svga,
if (zslice_pick >= 0)
z_offset = zslice_pick;
for (i = 0; i < key->numMipLevels; i++) {
for (j = 0; j < key->numFaces * key->arraySize; j++) {
if (svga_is_texture_level_defined(tex, j + layer_pick, i + start_mip)) {
unsigned depth = (zslice_pick < 0 ?
u_minify(tex->b.b.depth0, i + start_mip) :
1);
svga_texture_copy_handle(svga,
tex->handle,
0, 0, z_offset,
i + start_mip,
j + layer_pick,
handle, 0, 0, 0, i, j,
u_minify(tex->b.b.width0, i + start_mip),
u_minify(tex->b.b.height0, i + start_mip),
depth);
}
}
}
svga_texture_copy_handle_resource(svga, tex, handle,
key->numMipLevels,
key->numFaces * key->arraySize,
z_offset, start_mip, layer_pick);
return handle;
}
@ -374,11 +395,12 @@ svga_create_surface(struct pipe_context *pipe,
static struct svga_surface *
create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
{
struct svga_texture *tex = svga_texture(s->base.texture);
SVGA_STATS_TIME_PUSH(svga_sws(svga),
SVGA_STATS_TIME_CREATEBACKEDSURFACEVIEW);
if (!s->backed) {
struct svga_texture *tex = svga_texture(s->base.texture);
struct pipe_surface *backed_view;
backed_view = svga_create_surface_view(&svga->pipe,
@ -390,6 +412,33 @@ create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
s->backed = svga_surface(backed_view);
}
else {
/*
* There is already an existing backing surface, but we still need to
* sync the handles.
*/
struct svga_surface *bs = s->backed;
unsigned int layer, zslice;
assert(bs->handle);
switch (tex->b.b.target) {
case PIPE_TEXTURE_CUBE:
case PIPE_TEXTURE_1D_ARRAY:
case PIPE_TEXTURE_2D_ARRAY:
layer = s->base.u.tex.first_layer;
zslice = 0;
break;
default:
layer = 0;
zslice = s->base.u.tex.first_layer;
}
svga_texture_copy_handle_resource(svga, tex, bs->handle,
bs->key.numMipLevels,
bs->key.numFaces * bs->key.arraySize,
zslice, s->base.u.tex.level, layer);
}
svga_mark_surface_dirty(&s->backed->base);