summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/svga/svga_format.c70
-rw-r--r--src/gallium/drivers/svga/svga_format.h6
-rw-r--r--src/gallium/drivers/svga/svga_resource_texture.c58
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;
}