[Mesa-dev] [PATCH v13 09/36] st/dri: refactor multi-planar YUV import path

Daniel Stone daniels at collabora.com
Fri May 19 09:37:52 UTC 2017


From: Varad Gautam <varad.gautam at collabora.com>

we currently ignore the plane count when converting from
__DRI_IMAGE_FORMAT* tokens to __DRI_IMAGE_FOURCC* for multiplanar
images, and only return the first plane's simplified fourcc.

this adds a fourcc to __DRI_IMAGE_FORMAT_* mapping to dri, allowing
us to return the correct fourcc format from DRIimage queries, and
simplifies the multiplane import logic.

Signed-off-by: Varad Gautam <varad.gautam at collabora.com>
Signed-off-by: Daniel Stone <daniels at collabora.com>
---
 src/gallium/state_trackers/dri/dri2.c       | 288 +++++++++++++++-------------
 src/gallium/state_trackers/dri/dri_screen.h |  13 ++
 2 files changed, 168 insertions(+), 133 deletions(-)

diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c
index ed6004f836..0c5783cbd3 100644
--- a/src/gallium/state_trackers/dri/dri2.c
+++ b/src/gallium/state_trackers/dri/dri2.c
@@ -52,93 +52,133 @@
 #include "dri_query_renderer.h"
 #include "dri2_buffer.h"
 
-static int convert_fourcc(int format, int *dri_components_p)
+/* format list taken from intel_screen.c */
+static struct image_format image_formats[] = {
+   { __DRI_IMAGE_FOURCC_ARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } },
+
+   { __DRI_IMAGE_FOURCC_ABGR8888, __DRI_IMAGE_COMPONENTS_RGBA, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_ABGR8888, 4 } } },
+
+   { __DRI_IMAGE_FOURCC_SARGB8888, __DRI_IMAGE_COMPONENTS_RGBA, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_SARGB8, 4 } } },
+
+   { __DRI_IMAGE_FOURCC_XRGB8888, __DRI_IMAGE_COMPONENTS_RGB, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_XRGB8888, 4 }, } },
+
+   { __DRI_IMAGE_FOURCC_XBGR8888, __DRI_IMAGE_COMPONENTS_RGB, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_XBGR8888, 4 }, } },
+
+   { __DRI_IMAGE_FOURCC_ARGB1555, __DRI_IMAGE_COMPONENTS_RGBA, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_ARGB1555, 2 } } },
+
+   { __DRI_IMAGE_FOURCC_RGB565, __DRI_IMAGE_COMPONENTS_RGB, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_RGB565, 2 } } },
+
+   { __DRI_IMAGE_FOURCC_R8, __DRI_IMAGE_COMPONENTS_R, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 }, } },
+
+   { __DRI_IMAGE_FOURCC_R16, __DRI_IMAGE_COMPONENTS_R, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R16, 1 }, } },
+
+   { __DRI_IMAGE_FOURCC_GR88, __DRI_IMAGE_COMPONENTS_RG, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 }, } },
+
+   { __DRI_IMAGE_FOURCC_GR1616, __DRI_IMAGE_COMPONENTS_RG, 1,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR1616, 2 }, } },
+
+   { __DRI_IMAGE_FOURCC_YUV410, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YUV411, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YUV420, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YUV422, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YUV444, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YVU410, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 2, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 2, 2, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YVU411, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 2, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 2, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YVU420, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 2, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 1, 1, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YVU422, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 2, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 1, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_YVU444, __DRI_IMAGE_COMPONENTS_Y_U_V, 3,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 2, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 } } },
+
+   { __DRI_IMAGE_FOURCC_NV12, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88, 2 } } },
+
+   { __DRI_IMAGE_FOURCC_NV16, __DRI_IMAGE_COMPONENTS_Y_UV, 2,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8, 1 },
+       { 1, 1, 0, __DRI_IMAGE_FORMAT_GR88, 2 } } },
+
+   { __DRI_IMAGE_FOURCC_YUYV, __DRI_IMAGE_COMPONENTS_Y_XUXV, 2,
+     { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88, 2 },
+       { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888, 4 } } }
+};
+
+static struct image_format *
+image_format_from_fourcc(int fourcc)
 {
-   int dri_components;
-   switch(format) {
-   case __DRI_IMAGE_FOURCC_RGB565:
-      format = __DRI_IMAGE_FORMAT_RGB565;
-      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
-      break;
-   case __DRI_IMAGE_FOURCC_ARGB8888:
-      format = __DRI_IMAGE_FORMAT_ARGB8888;
-      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
-      break;
-   case __DRI_IMAGE_FOURCC_XRGB8888:
-      format = __DRI_IMAGE_FORMAT_XRGB8888;
-      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
-      break;
-   case __DRI_IMAGE_FOURCC_ABGR8888:
-      format = __DRI_IMAGE_FORMAT_ABGR8888;
-      dri_components = __DRI_IMAGE_COMPONENTS_RGBA;
-      break;
-   case __DRI_IMAGE_FOURCC_XBGR8888:
-      format = __DRI_IMAGE_FORMAT_XBGR8888;
-      dri_components = __DRI_IMAGE_COMPONENTS_RGB;
-      break;
-   case __DRI_IMAGE_FOURCC_R8:
-      format = __DRI_IMAGE_FORMAT_R8;
-      dri_components = __DRI_IMAGE_COMPONENTS_R;
-      break;
-   case __DRI_IMAGE_FOURCC_GR88:
-      format = __DRI_IMAGE_FORMAT_GR88;
-      dri_components = __DRI_IMAGE_COMPONENTS_RG;
-      break;
-   /*
-    * For multi-planar YUV formats, we return the format of the first
-    * plane only.  Since there is only one caller which supports multi-
-    * planar YUV it gets to figure out the remaining planes on it's
-    * own.
-    */
-   case __DRI_IMAGE_FOURCC_YUV420:
-   case __DRI_IMAGE_FOURCC_YVU420:
-      format = __DRI_IMAGE_FORMAT_R8;
-      dri_components = __DRI_IMAGE_COMPONENTS_Y_U_V;
-      break;
-   case __DRI_IMAGE_FOURCC_NV12:
-      format = __DRI_IMAGE_FORMAT_R8;
-      dri_components = __DRI_IMAGE_COMPONENTS_Y_UV;
-      break;
-   default:
-      return -1;
+   struct image_format *f = NULL;
+
+   for (unsigned i = 0; i < ARRAY_SIZE(image_formats); i++) {
+      if (image_formats[i].fourcc == fourcc) {
+         f = &image_formats[i];
+         break;
+      }
    }
-   *dri_components_p = dri_components;
-   return format;
+
+   return f;
 }
 
-/* NOTE this probably isn't going to do the right thing for YUV images
- * (but I think the same can be said for intel_query_image()).  I think
- * only needed for exporting dmabuf's, so I think I won't loose much
- * sleep over it.
- */
-static int convert_to_fourcc(int format)
+static struct image_format *
+image_format_from_dri2_format(int dri_format, int nplanes)
 {
-   switch(format) {
-   case __DRI_IMAGE_FORMAT_RGB565:
-      format = __DRI_IMAGE_FOURCC_RGB565;
-      break;
-   case __DRI_IMAGE_FORMAT_ARGB8888:
-      format = __DRI_IMAGE_FOURCC_ARGB8888;
-      break;
-   case __DRI_IMAGE_FORMAT_XRGB8888:
-      format = __DRI_IMAGE_FOURCC_XRGB8888;
-      break;
-   case __DRI_IMAGE_FORMAT_ABGR8888:
-      format = __DRI_IMAGE_FOURCC_ABGR8888;
-      break;
-   case __DRI_IMAGE_FORMAT_XBGR8888:
-      format = __DRI_IMAGE_FOURCC_XBGR8888;
-      break;
-   case __DRI_IMAGE_FORMAT_R8:
-      format = __DRI_IMAGE_FOURCC_R8;
-      break;
-   case __DRI_IMAGE_FORMAT_GR88:
-      format = __DRI_IMAGE_FOURCC_GR88;
-      break;
-   default:
-      return -1;
+   struct image_format *f = NULL;
+
+   for (unsigned i = 0; i < ARRAY_SIZE(image_formats); i++) {
+      if (image_formats[i].planes[0].dri_format == dri_format &&
+          image_formats[i].nplanes == nplanes) {
+         f = &image_formats[i];
+         break;
+      }
    }
-   return format;
+
+   return f;
 }
 
 static enum pipe_format dri2_format_to_pipe_format (int format)
@@ -791,13 +831,13 @@ dri2_create_image_from_winsys(__DRIscreen *_screen,
    __DRIimage *img;
    struct pipe_resource templ;
    unsigned tex_usage;
-   enum pipe_format pf;
+   struct image_format *f = NULL;
    int i;
 
    tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
 
-   pf = dri2_format_to_pipe_format (format);
-   if (pf == PIPE_FORMAT_NONE)
+   f = image_format_from_dri2_format(format, num_handles);
+   if (f == NULL)
       return NULL;
 
    img = CALLOC_STRUCT(__DRIimageRec);
@@ -811,31 +851,12 @@ dri2_create_image_from_winsys(__DRIscreen *_screen,
    templ.depth0 = 1;
    templ.array_size = 1;
 
-   for (i = num_handles - 1; i >= 0; i--) {
+   for (i = f->nplanes - 1; i >= 0; i--) {
       struct pipe_resource *tex;
 
-      /* TODO: something a lot less ugly */
-      switch (i) {
-      case 0:
-         templ.width0 = width;
-         templ.height0 = height;
-         templ.format = pf;
-         break;
-      case 1:
-         templ.width0 = width / 2;
-         templ.height0 = height / 2;
-         templ.format = (num_handles == 2) ?
-               PIPE_FORMAT_RG88_UNORM :   /* NV12, etc */
-               PIPE_FORMAT_R8_UNORM;      /* I420, etc */
-         break;
-      case 2:
-         templ.width0 = width / 2;
-         templ.height0 = height / 2;
-         templ.format = PIPE_FORMAT_R8_UNORM;
-         break;
-      default:
-         unreachable("too many planes!");
-      }
+      templ.width0 = width >> f->planes[i].width_shift;
+      templ.height0 = height >> f->planes[i].height_shift;
+      templ.format = dri2_format_to_pipe_format(f->planes[i].dri_format);
 
       tex = pscreen->resource_from_handle(pscreen,
             &templ, &whandle[i], PIPE_HANDLE_USAGE_READ_WRITE);
@@ -890,32 +911,18 @@ dri2_create_image_from_fd(__DRIscreen *_screen,
    struct winsys_handle whandles[3];
    int format;
    __DRIimage *img = NULL;
+   struct image_format *f = NULL;
    unsigned err = __DRI_IMAGE_ERROR_SUCCESS;
-   int expected_num_fds, i;
-
-   switch (fourcc) {
-   case __DRI_IMAGE_FOURCC_YUV420:
-   case __DRI_IMAGE_FOURCC_YVU420:
-      expected_num_fds = 3;
-      break;
-   case __DRI_IMAGE_FOURCC_NV12:
-      expected_num_fds = 2;
-      break;
-   default:
-      expected_num_fds = 1;
-      break;
-   }
+   int i;
 
-   if (num_fds != expected_num_fds) {
+   f = image_format_from_fourcc(fourcc);
+   if (f == NULL || num_fds != f->nplanes) {
       err = __DRI_IMAGE_ERROR_BAD_MATCH;
       goto exit;
    }
 
-   format = convert_fourcc(fourcc, dri_components);
-   if (format == -1) {
-      err = __DRI_IMAGE_ERROR_BAD_MATCH;
-      goto exit;
-   }
+   format = f->planes[0].dri_format;
+   *dri_components = f->components;
 
    memset(whandles, 0, sizeof(whandles));
 
@@ -1026,7 +1033,9 @@ static GLboolean
 dri2_query_image(__DRIimage *image, int attrib, int *value)
 {
    struct winsys_handle whandle;
+   struct image_format *f = NULL;
    unsigned usage;
+   int nplanes;
 
    if (image->use & __DRI_IMAGE_USE_BACKBUFFER)
       usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ;
@@ -1077,7 +1086,19 @@ dri2_query_image(__DRIimage *image, int attrib, int *value)
       *value = image->dri_components;
       return GL_TRUE;
    case __DRI_IMAGE_ATTRIB_FOURCC:
-      *value = convert_to_fourcc(image->dri_format);
+      switch (image->dri_components) {
+      case __DRI_IMAGE_COMPONENTS_Y_U_V:
+         nplanes = 3;
+         break;
+      case __DRI_IMAGE_COMPONENTS_Y_UV:
+      case __DRI_IMAGE_COMPONENTS_Y_XUXV:
+         nplanes = 2;
+         break;
+      default:
+         nplanes = 1;
+      }
+      f = image_format_from_dri2_format(image->dri_format, nplanes);
+      *value = f->fourcc;
       return GL_TRUE;
    case __DRI_IMAGE_ATTRIB_NUM_PLANES:
       *value = 1;
@@ -1128,14 +1149,14 @@ dri2_from_names(__DRIscreen *screen, int width, int height, int format,
                 void *loaderPrivate)
 {
    __DRIimage *img;
-   int dri_components;
    struct winsys_handle whandle;
+   struct image_format *f = NULL;
 
    if (num_names != 1)
       return NULL;
 
-   format = convert_fourcc(format, &dri_components);
-   if (format == -1)
+   f = image_format_from_fourcc(format);
+   if (f == NULL)
       return NULL;
 
    memset(&whandle, 0, sizeof(whandle));
@@ -1144,12 +1165,13 @@ dri2_from_names(__DRIscreen *screen, int width, int height, int format,
    whandle.stride = strides[0];
    whandle.offset = offsets[0];
 
-   img = dri2_create_image_from_winsys(screen, width, height, format,
+   img = dri2_create_image_from_winsys(screen, width, height,
+                                       f->planes[0].dri_format,
                                        1, &whandle, loaderPrivate);
    if (img == NULL)
       return NULL;
 
-   img->dri_components = dri_components;
+   img->dri_components = f->components;
    return img;
 }
 
diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h
index 7f5fd13630..de88cd26db 100644
--- a/src/gallium/state_trackers/dri/dri_screen.h
+++ b/src/gallium/state_trackers/dri/dri_screen.h
@@ -103,6 +103,19 @@ dri_screen(__DRIscreen * sPriv)
    return (struct dri_screen *)sPriv->driverPrivate;
 }
 
+struct image_format {
+   int fourcc;
+   int components;
+   int nplanes;
+   struct {
+      int buffer_index;
+      int width_shift;
+      int height_shift;
+      uint32_t dri_format;
+      int cpp;
+   } planes[3];
+};
+
 struct __DRIimageRec {
    struct pipe_resource *texture;
    unsigned level;
-- 
2.13.0



More information about the mesa-dev mailing list