From ca59fd17061aeffc55847755de1ed2b6600bcf84 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Fri, 7 Apr 2017 14:54:56 +0200 Subject: [PATCH] svga: Add a more elaborate format compatibility determination v2 dri3 is a bit sloppy about its format compatibility requirements, so add a possibility to import xrgb surfaces as argb textures and vice versa. At the same time, make the svga_texture_from_handle() function a bit more readable and fix the error path where we leaked a winsys surface. v2: Addressed review comments by Brian. Signed-off-by: Thomas Hellstrom Reviewed-by: Brian Paul Reviewed-by: Charmaine Lee --- src/gallium/drivers/svga/svga_format.c | 70 +++++++++++++++++++ src/gallium/drivers/svga/svga_format.h | 6 ++ .../drivers/svga/svga_resource_texture.c | 58 +++++---------- 3 files changed, 93 insertions(+), 41 deletions(-) diff --git a/src/gallium/drivers/svga/svga_format.c b/src/gallium/drivers/svga/svga_format.c index 7d970be4e5e..d8ccfbd947a 100644 --- a/src/gallium/drivers/svga/svga_format.c +++ b/src/gallium/drivers/svga/svga_format.c @@ -43,6 +43,11 @@ struct vgpu10_format_entry unsigned flags; }; +struct format_compat_entry +{ + enum pipe_format pformat; + const SVGA3dSurfaceFormat *compat_format; +}; static const struct vgpu10_format_entry format_conversion_table[] = { @@ -1847,6 +1852,23 @@ static const struct format_cap format_cap_table[] = { } }; +static const SVGA3dSurfaceFormat compat_x8r8g8b8[] = { + SVGA3D_X8R8G8B8, SVGA3D_A8R8G8B8, SVGA3D_B8G8R8X8_UNORM, + SVGA3D_B8G8R8A8_UNORM, 0 +}; +static const SVGA3dSurfaceFormat compat_r8[] = { + SVGA3D_R8_UNORM, SVGA3D_NV12, SVGA3D_YV12, 0 +}; +static const SVGA3dSurfaceFormat compat_g8r8[] = { + SVGA3D_R8G8_UNORM, SVGA3D_NV12, 0 +}; + +static const struct format_compat_entry format_compats[] = { + {PIPE_FORMAT_B8G8R8X8_UNORM, compat_x8r8g8b8}, + {PIPE_FORMAT_B8G8R8A8_UNORM, compat_x8r8g8b8}, + {PIPE_FORMAT_R8_UNORM, compat_r8}, + {PIPE_FORMAT_R8G8_UNORM, compat_g8r8} +}; /** * Debug only: @@ -2267,3 +2289,51 @@ svga_format_is_typeless(SVGA3dSurfaceFormat format) return false; } } + + +/** + * \brief Can we import a surface with a given SVGA3D format as a texture? + * + * \param ss[in] pointer to the svga screen. + * \param pformat[in] pipe format of the local texture. + * \param sformat[in] svga3d format of the imported surface. + * \param bind[in] bind flags of the imported texture. + * \param verbose[in] Print out incompatibilities in debug mode. + */ +bool +svga_format_is_shareable(const struct svga_screen *ss, + enum pipe_format pformat, + SVGA3dSurfaceFormat sformat, + unsigned bind, + bool verbose) +{ + SVGA3dSurfaceFormat default_format = + svga_translate_format(ss, pformat, bind); + int i; + + if (default_format == SVGA3D_FORMAT_INVALID) + return false; + if (default_format == sformat) + return true; + + for (i = 0; i < ARRAY_SIZE(format_compats); ++i) { + if (format_compats[i].pformat == pformat) { + const SVGA3dSurfaceFormat *compat_format = + format_compats[i].compat_format; + while (*compat_format != 0) { + if (*compat_format == sformat) + return true; + compat_format++; + } + } + } + + if (verbose) { + debug_printf("Incompatible imported surface format.\n"); + debug_printf("Texture format: \"%s\". Imported format: \"%s\".\n", + svga_format_name(default_format), + svga_format_name(sformat)); + } + + return false; +} diff --git a/src/gallium/drivers/svga/svga_format.h b/src/gallium/drivers/svga/svga_format.h index e8af40afb71..63be8f1ad79 100644 --- a/src/gallium/drivers/svga/svga_format.h +++ b/src/gallium/drivers/svga/svga_format.h @@ -111,4 +111,10 @@ svga_format_is_uncompressed_snorm(SVGA3dSurfaceFormat format); bool svga_format_is_typeless(SVGA3dSurfaceFormat format); +bool +svga_format_is_shareable(const struct svga_screen *ss, + enum pipe_format pformat, + SVGA3dSurfaceFormat sformat, + unsigned bind, + bool verbose); #endif /* SVGA_FORMAT_H_ */ diff --git a/src/gallium/drivers/svga/svga_resource_texture.c b/src/gallium/drivers/svga/svga_resource_texture.c index 1e2dfa82728..356e7c54d9d 100644 --- a/src/gallium/drivers/svga/svga_resource_texture.c +++ b/src/gallium/drivers/svga/svga_resource_texture.c @@ -1149,8 +1149,8 @@ fail_notex: struct pipe_resource * svga_texture_from_handle(struct pipe_screen *screen, - const struct pipe_resource *template, - struct winsys_handle *whandle) + const struct pipe_resource *template, + struct winsys_handle *whandle) { struct svga_winsys_screen *sws = svga_winsys_screen(screen); struct svga_screen *ss = svga_screen(screen); @@ -1172,42 +1172,18 @@ svga_texture_from_handle(struct pipe_screen *screen, if (!srf) return NULL; - if (svga_translate_format(svga_screen(screen), template->format, - template->bind) != format) { - unsigned f1 = svga_translate_format(svga_screen(screen), - template->format, template->bind); - unsigned f2 = format; - - /* It's okay for XRGB and ARGB or depth with/out stencil to get mixed up. - */ - if (f1 == SVGA3D_B8G8R8A8_UNORM) - f1 = SVGA3D_A8R8G8B8; - if (f1 == SVGA3D_B8G8R8X8_UNORM) - f1 = SVGA3D_X8R8G8B8; - - if ( !( (f1 == f2) || - (f1 == SVGA3D_X8R8G8B8 && f2 == SVGA3D_A8R8G8B8) || - (f1 == SVGA3D_X8R8G8B8 && f2 == SVGA3D_B8G8R8X8_UNORM) || - (f1 == SVGA3D_A8R8G8B8 && f2 == SVGA3D_X8R8G8B8) || - (f1 == SVGA3D_A8R8G8B8 && f2 == SVGA3D_B8G8R8A8_UNORM) || - (f1 == SVGA3D_Z_D24X8 && f2 == SVGA3D_Z_D24S8) || - (f1 == SVGA3D_Z_DF24 && f2 == SVGA3D_Z_D24S8_INT) ) ) { - debug_printf("%s wrong format %s != %s\n", __FUNCTION__, - svga_format_name(f1), svga_format_name(f2)); - return NULL; - } - } + if (!svga_format_is_shareable(ss, template->format, format, + template->bind, true)) + goto out_unref; tex = CALLOC_STRUCT(svga_texture); if (!tex) - return NULL; + goto out_unref; tex->defined = CALLOC(template->depth0 * template->array_size, sizeof(tex->defined[0])); - if (!tex->defined) { - FREE(tex); - return NULL; - } + if (!tex->defined) + goto out_no_defined; tex->b.b = *template; tex->b.vtbl = &svga_texture_vtbl; @@ -1222,11 +1198,11 @@ svga_texture_from_handle(struct pipe_screen *screen, tex->rendered_to = CALLOC(1, sizeof(tex->rendered_to[0])); if (!tex->rendered_to) - goto fail; + goto out_no_rendered_to; tex->dirty = CALLOC(1, sizeof(tex->dirty[0])); if (!tex->dirty) - goto fail; + goto out_no_dirty; tex->imported = TRUE; @@ -1234,14 +1210,14 @@ svga_texture_from_handle(struct pipe_screen *screen, return &tex->b.b; -fail: - if (tex->defined) - FREE(tex->defined); - if (tex->rendered_to) - FREE(tex->rendered_to); - if (tex->dirty) - FREE(tex->dirty); +out_no_dirty: + FREE(tex->rendered_to); +out_no_rendered_to: + FREE(tex->defined); +out_no_defined: FREE(tex); +out_unref: + sws->surface_reference(sws, &srf, NULL); return NULL; } -- 2.30.2