mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-06 13:10:10 +01:00
svga: allow quad blit for more formats
Currently blitter will fail if the blit format is different and view-incompatible to the resource format. Instead of punting to software blit which will stall the pipeline, we will create temporary resource to allow blitter to work. Fixes piglit test arb_copy_image-formats. Also tested with MTT piglit, glretrace. Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
parent
4bd5ce853b
commit
f2eec4e829
1 changed files with 136 additions and 1 deletions
|
|
@ -286,12 +286,43 @@ can_blit_via_copy_region_vgpu10(struct svga_context *svga,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* A helper function to determine if the specified view format
|
||||
* is compatible with the surface format.
|
||||
* It is compatible if the view format is the same as the surface format,
|
||||
* or the associated svga format for the surface is a typeless format, or
|
||||
* the view format is an adjusted format for BGRX/BGRA resource.
|
||||
*/
|
||||
static bool
|
||||
is_view_format_compatible(enum pipe_format surf_fmt,
|
||||
SVGA3dSurfaceFormat surf_svga_fmt,
|
||||
enum pipe_format view_fmt)
|
||||
{
|
||||
if (surf_fmt == view_fmt || svga_format_is_typeless(surf_svga_fmt))
|
||||
return true;
|
||||
|
||||
if ((surf_fmt == PIPE_FORMAT_B8G8R8X8_UNORM &&
|
||||
view_fmt == PIPE_FORMAT_B8G8R8A8_UNORM) ||
|
||||
(surf_fmt == PIPE_FORMAT_B8G8R8A8_UNORM &&
|
||||
view_fmt == PIPE_FORMAT_B8G8R8X8_UNORM))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
svga_blit(struct pipe_context *pipe,
|
||||
const struct pipe_blit_info *blit_info)
|
||||
{
|
||||
struct svga_context *svga = svga_context(pipe);
|
||||
struct pipe_blit_info blit = *blit_info;
|
||||
struct pipe_resource *src = blit.src.resource;
|
||||
struct pipe_resource *dst = blit.dst.resource;
|
||||
struct pipe_resource *newSrc = NULL;
|
||||
struct pipe_resource *newDst = NULL;
|
||||
bool can_create_src_view;
|
||||
bool can_create_dst_view;
|
||||
|
||||
if (!svga_have_vgpu10(svga) &&
|
||||
blit.src.resource->nr_samples > 1 &&
|
||||
|
|
@ -333,8 +364,21 @@ svga_blit(struct pipe_context *pipe,
|
|||
return; /* done */
|
||||
}
|
||||
|
||||
/* Check if we can create shader resource view and
|
||||
* render target view for the quad blitter to work
|
||||
*/
|
||||
can_create_src_view =
|
||||
is_view_format_compatible(src->format, svga_texture(src)->key.format,
|
||||
blit.src.format);
|
||||
|
||||
can_create_dst_view =
|
||||
is_view_format_compatible(dst->format, svga_texture(dst)->key.format,
|
||||
blit.dst.format);
|
||||
|
||||
if ((blit.mask & PIPE_MASK_S) ||
|
||||
!util_blitter_is_blit_supported(svga->blitter, blit_info)) {
|
||||
((!can_create_dst_view || !can_create_src_view)
|
||||
&& !svga_have_vgpu10(svga)) ||
|
||||
!util_blitter_is_blit_supported(svga->blitter, &blit)) {
|
||||
debug_printf("svga: blit unsupported %s -> %s\n",
|
||||
util_format_short_name(blit.src.resource->format),
|
||||
util_format_short_name(blit.dst.resource->format));
|
||||
|
|
@ -367,7 +411,98 @@ svga_blit(struct pipe_context *pipe,
|
|||
svga->curr.sampler_views[PIPE_SHADER_FRAGMENT]);
|
||||
/*util_blitter_save_render_condition(svga->blitter, svga->render_cond_query,
|
||||
svga->render_cond_cond, svga->render_cond_mode);*/
|
||||
|
||||
if (!can_create_src_view) {
|
||||
struct pipe_resource template;
|
||||
unsigned src_face, src_z;
|
||||
|
||||
/**
|
||||
* If the source blit format is not compatible with the source resource
|
||||
* format, we will not be able to create a shader resource view.
|
||||
* In order to avoid falling back to software blit, we'll create
|
||||
* a new resource in the blit format, and use DXCopyResource to
|
||||
* copy from the original format to the new format. The new
|
||||
* resource will be used for the blit in util_blitter_blit().
|
||||
*/
|
||||
template = *src;
|
||||
template.format = blit.src.format;
|
||||
newSrc = svga_texture_create(svga->pipe.screen, &template);
|
||||
if (newSrc == NULL) {
|
||||
debug_printf("svga_blit: fails to create temporary src\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Copy from original resource to the temporary resource */
|
||||
adjust_z_layer(blit.src.resource->target, blit.src.box.z,
|
||||
&src_face, &src_z);
|
||||
|
||||
copy_region_vgpu10(svga,
|
||||
blit.src.resource,
|
||||
blit.src.box.x, blit.src.box.y, src_z,
|
||||
blit.src.level, src_face,
|
||||
newSrc,
|
||||
blit.src.box.x, blit.src.box.y, src_z,
|
||||
blit.src.level, src_face,
|
||||
blit.src.box.width, blit.src.box.height,
|
||||
blit.src.box.depth);
|
||||
|
||||
blit.src.resource = newSrc;
|
||||
}
|
||||
|
||||
if (!can_create_dst_view) {
|
||||
struct pipe_resource template;
|
||||
|
||||
/**
|
||||
* If the destination blit format is not compatible with the destination
|
||||
* resource format, we will not be able to create a render target view.
|
||||
* In order to avoid falling back to software blit, we'll create
|
||||
* a new resource in the blit format, and use DXPredCopyRegion
|
||||
* after the blit to copy from the blit format back to the resource
|
||||
* format.
|
||||
*/
|
||||
template = *dst;
|
||||
template.format = blit.dst.format;
|
||||
newDst = svga_texture_create(svga->pipe.screen, &template);
|
||||
if (newDst == NULL) {
|
||||
debug_printf("svga_blit: fails to create temporary dst\n");
|
||||
return;
|
||||
}
|
||||
|
||||
blit.dst.resource = newDst;
|
||||
}
|
||||
|
||||
util_blitter_blit(svga->blitter, &blit);
|
||||
|
||||
if (blit.dst.resource != dst) {
|
||||
unsigned dst_face, dst_z;
|
||||
|
||||
adjust_z_layer(blit.dst.resource->target, blit.dst.box.z,
|
||||
&dst_face, &dst_z);
|
||||
|
||||
/**
|
||||
* A temporary resource was created for the blit, we need to
|
||||
* copy from the temporary resource back to the original destination.
|
||||
*/
|
||||
copy_region_vgpu10(svga,
|
||||
blit.dst.resource,
|
||||
blit.dst.box.x, blit.dst.box.y, dst_z,
|
||||
blit.dst.level, dst_face,
|
||||
dst,
|
||||
blit.dst.box.x, blit.dst.box.y, dst_z,
|
||||
blit.dst.level, dst_face,
|
||||
blit.dst.box.width, blit.dst.box.height,
|
||||
blit.dst.box.depth);
|
||||
|
||||
/* unreference the temporary resource */
|
||||
pipe_resource_reference(&newDst, NULL);
|
||||
blit.dst.resource = dst;
|
||||
}
|
||||
|
||||
if (blit.src.resource != src) {
|
||||
/* unreference the temporary resource */
|
||||
pipe_resource_reference(&newSrc, NULL);
|
||||
blit.src.resource = src;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue