mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-04 20:00:11 +01:00
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 <thellstrom@vmware.com> Reviewed-by: Brian Paul <brianp@vmware.com> Reviewed-by: Charmaine Lee <charmainel@vmware.com>
This commit is contained in:
parent
18d5c452d0
commit
ca59fd1706
3 changed files with 93 additions and 41 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue