Mesa (master): svga: Add a more elaborate format compatibility determination v2

Brian Paul brianp at kemper.freedesktop.org
Sat Apr 29 03:07:38 UTC 2017


Module: Mesa
Branch: master
Commit: ca59fd17061aeffc55847755de1ed2b6600bcf84
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ca59fd17061aeffc55847755de1ed2b6600bcf84

Author: Thomas Hellstrom <thellstrom at vmware.com>
Date:   Fri Apr  7 14:54:56 2017 +0200

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 at vmware.com>
Reviewed-by: Brian Paul <brianp at vmware.com>
Reviewed-by: Charmaine Lee <charmainel at vmware.com>

---

 src/gallium/drivers/svga/svga_format.c           | 70 ++++++++++++++++++++++++
 src/gallium/drivers/svga/svga_format.h           |  6 ++
 src/gallium/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 7d970be4e5..d8ccfbd947 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 e8af40afb7..63be8f1ad7 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 1e2dfa8272..356e7c54d9 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;
 }
 




More information about the mesa-commit mailing list