[Piglit] [RFC] Trying to fix dmabuf/yuv tests

Kristian Høgsberg hoegsberg at gmail.com
Tue Sep 6 20:04:27 UTC 2016


On Sun, Sep 4, 2016 at 9:34 AM, Rob Clark <robdclark at gmail.com> wrote:
> Ok, so the basic problem with the YUV tests is that they currently
> completely ignore driver/hw pitch requirements, since the code that
> allocates the buffer doesn't know the pixel format, only the 'cpp'.
>
> The yuv test creates a small 4x4 yuv eglimage.  If, say, the hardware
> requires the pitch to be aligned to, say, 32pixels, everything is fine
> for the Y plane, but the subsampled U/V or U+V plane has half as many
> pixels.  (This did help me catch a bug in driver, not rejecting the
> dmabuf import with invalid pitch, but that doesn't help to get the
> piglit tests running.)
>
> My original idea was that, since cpp values are never valid fourcc
> values, and visa versa, to avoid changing too much the other existing
> RGB tests by allowing to pass down either cpp or fourcc.  Especially
> since in the case of RGB we really don't care about, for example,
> ARGB vs BRGA.  Whereas for YUV formats, we really do want to know the
> exact format to copy the src data into the allocated buffer correctly.
> But this patch turned out to be big/intrusive enough that maybe just
> fixing up the other RGB tests to use fourcc everywhere might be ok.
>
> The other issue is that egl_image_for_dma_buf_fd() made assumptions
> about the offset/pitch of each plane, which were not valid.  (And,
> I believe, incorrect even for i965..  I'm not entirely sure why it
> worked at all.)  So I ended up needing to expose piglit_dma_buf and
> adding an array of per-plane offsets/pitches.
>
> Maybe this could be split up better or made a bit more clean.. not
> sure.
>
> Fwiw, this applies on top of anholt's gbm dmabuf backend.  And also
> needs the mesa patch I sent yesterday to add gbm R8/GR88 formats.
> ---
>  tests/spec/ext_image_dma_buf_import/refcount.c     |   6 +-
>  .../spec/ext_image_dma_buf_import/sample_common.c  |  70 ++++----
>  .../spec/ext_image_dma_buf_import/sample_common.h  |   5 +-
>  tests/spec/ext_image_dma_buf_import/sample_rgb.c   |   2 +-
>  tests/spec/ext_image_dma_buf_import/sample_yuv.c   |   2 +-
>  tests/util/piglit-framework-gl.c                   |   8 +-
>  tests/util/piglit-framework-gl.h                   |   2 +-
>  .../util/piglit-framework-gl/piglit_drm_dma_buf.c  | 176 ++++++++++++++++-----
>  .../util/piglit-framework-gl/piglit_drm_dma_buf.h  |  16 +-
>  .../util/piglit-framework-gl/piglit_gl_framework.h |   7 +-
>  10 files changed, 193 insertions(+), 101 deletions(-)
>
> diff --git a/tests/spec/ext_image_dma_buf_import/refcount.c b/tests/spec/ext_image_dma_buf_import/refcount.c
> index 5b14cdd..ddb0fc8 100644
> --- a/tests/spec/ext_image_dma_buf_import/refcount.c
> +++ b/tests/spec/ext_image_dma_buf_import/refcount.c
> @@ -72,13 +72,11 @@ piglit_display(void)
>         if (res != PIGLIT_PASS)
>                 return res;
>
> -       res = egl_image_for_dma_buf_fd(dup(fd), fourcc, w, h, stride, offset,
> -                                      &img1);
> +       res = egl_image_for_dma_buf_fd(buf, dup(fd), fourcc, &img1);
>         if (res != PIGLIT_PASS)
>                 return res;
>
> -       res = egl_image_for_dma_buf_fd(dup(fd), fourcc, w, h, stride, offset,
> -                                      &img2);
> +       res = egl_image_for_dma_buf_fd(buf, dup(fd), fourcc, &img2);
>         if (res != PIGLIT_PASS)
>                 return res;
>
> diff --git a/tests/spec/ext_image_dma_buf_import/sample_common.c b/tests/spec/ext_image_dma_buf_import/sample_common.c
> index c5aa1e1..538f3c4 100644
> --- a/tests/spec/ext_image_dma_buf_import/sample_common.c
> +++ b/tests/spec/ext_image_dma_buf_import/sample_common.c
> @@ -23,6 +23,8 @@
>
>  #include <unistd.h>
>
> +#include "piglit-framework-gl/piglit_drm_dma_buf.h"
> +
>  #include "image_common.h"
>  #include "sample_common.h"
>
> @@ -105,47 +107,46 @@ sample_tex(GLuint tex, unsigned x, unsigned y, unsigned w, unsigned h)
>  }
>
>  enum piglit_result
> -egl_image_for_dma_buf_fd(int fd, int fourcc, int w, int h,
> -                        unsigned stride, unsigned offset, EGLImageKHR *out_img)
> +egl_image_for_dma_buf_fd(struct piglit_dma_buf *buf, int fd, int fourcc, EGLImageKHR *out_img)
>  {
>         EGLint error;
>         EGLImageKHR img;
>         EGLint attr_packed[] = {
> -               EGL_WIDTH, w,
> -               EGL_HEIGHT, h,
> +               EGL_WIDTH, buf->w,
> +               EGL_HEIGHT, buf->h,
>                 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
>                 EGL_DMA_BUF_PLANE0_FD_EXT, fd,
> -               EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset,
> -               EGL_DMA_BUF_PLANE0_PITCH_EXT, stride,
> +               EGL_DMA_BUF_PLANE0_OFFSET_EXT, buf->offset[0],
> +               EGL_DMA_BUF_PLANE0_PITCH_EXT, buf->stride[0],
>                 EGL_NONE
>         };
>
>         EGLint attr_nv12[] = {
> -               EGL_WIDTH, w,
> -               EGL_HEIGHT, h,
> +               EGL_WIDTH, buf->w,
> +               EGL_HEIGHT, buf->h,
>                 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
>                 EGL_DMA_BUF_PLANE0_FD_EXT, fd,
> -               EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset,
> -               EGL_DMA_BUF_PLANE0_PITCH_EXT, stride,
> +               EGL_DMA_BUF_PLANE0_OFFSET_EXT, buf->offset[0],
> +               EGL_DMA_BUF_PLANE0_PITCH_EXT, buf->stride[0],
>                 EGL_DMA_BUF_PLANE1_FD_EXT, fd,
> -               EGL_DMA_BUF_PLANE1_OFFSET_EXT, offset + h * stride,
> -               EGL_DMA_BUF_PLANE1_PITCH_EXT, stride,
> +               EGL_DMA_BUF_PLANE1_OFFSET_EXT, buf->offset[1],
> +               EGL_DMA_BUF_PLANE1_PITCH_EXT, buf->stride[1],
>                 EGL_NONE
>         };
>
>         EGLint attr_yuv420[] = {
> -               EGL_WIDTH, w,
> -               EGL_HEIGHT, h,
> +               EGL_WIDTH, buf->w,
> +               EGL_HEIGHT, buf->h,
>                 EGL_LINUX_DRM_FOURCC_EXT, fourcc,
>                 EGL_DMA_BUF_PLANE0_FD_EXT, fd,
> -               EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset,
> -               EGL_DMA_BUF_PLANE0_PITCH_EXT, stride,
> +               EGL_DMA_BUF_PLANE0_OFFSET_EXT, buf->offset[0],
> +               EGL_DMA_BUF_PLANE0_PITCH_EXT, buf->stride[0],
>                 EGL_DMA_BUF_PLANE1_FD_EXT, fd,
> -               EGL_DMA_BUF_PLANE1_OFFSET_EXT, offset + h * stride,
> -               EGL_DMA_BUF_PLANE1_PITCH_EXT, stride,
> +               EGL_DMA_BUF_PLANE1_OFFSET_EXT, buf->offset[1],
> +               EGL_DMA_BUF_PLANE1_PITCH_EXT, buf->stride[1],
>                 EGL_DMA_BUF_PLANE2_FD_EXT, fd,
> -               EGL_DMA_BUF_PLANE2_OFFSET_EXT, offset + h * stride + w / 2,
> -               EGL_DMA_BUF_PLANE2_PITCH_EXT, stride,
> +               EGL_DMA_BUF_PLANE2_OFFSET_EXT, buf->offset[2],
> +               EGL_DMA_BUF_PLANE2_PITCH_EXT, buf->stride[2],
>                 EGL_NONE
>         };
>
> @@ -191,21 +192,22 @@ egl_image_for_dma_buf_fd(int fd, int fourcc, int w, int h,
>  }
>
>  static enum piglit_result
> -sample_buffer(void *buf, int fd, int fourcc, unsigned w, unsigned h,
> -             unsigned stride, unsigned offset)
> +sample_buffer(struct piglit_dma_buf *buf, int fourcc)
>  {
>         enum piglit_result res;
>         EGLImageKHR img;
>         GLuint tex;
> +       int w = buf->w;
> +       int h = buf->h;
>
> -       res = egl_image_for_dma_buf_fd(fd, fourcc, w, h, stride, offset, &img);
> +       res = egl_image_for_dma_buf_fd(buf, buf->fd, fourcc, &img);
>
>         /* Release the creator side of the buffer. */
>         piglit_destroy_dma_buf(buf);
>
>         if (!img) {
>                 /* Close the descriptor also, EGL does not have ownership */
> -               close(fd);
> +               close(buf->fd);
>         }
>
>         if (res != PIGLIT_PASS)
> @@ -225,7 +227,7 @@ destroy:
>  }
>
>  enum piglit_result
> -dma_buf_create_and_sample_32bpp(unsigned w, unsigned h, unsigned cpp,
> +dma_buf_create_and_sample_32bpp(unsigned w, unsigned h,
>                                 int fourcc, const unsigned char *src)
>  {
>         struct piglit_dma_buf *buf;
> @@ -233,24 +235,10 @@ dma_buf_create_and_sample_32bpp(unsigned w, unsigned h, unsigned cpp,
>         int fd;
>         enum piglit_result res;
>
> -       unsigned buffer_height;
> -
> -       switch (fourcc) {
> -       case DRM_FORMAT_NV12:
> -       case DRM_FORMAT_YUV420:
> -       case DRM_FORMAT_YVU420:
> -               buffer_height = h * 3 / 2;
> -               break;
> -       default:
> -               buffer_height = h;
> -               break;
> -       }
> -
> -       res = piglit_create_dma_buf(w, buffer_height,
> -                                   cpp, src, w * cpp, &buf, &fd, &stride,
> +       res = piglit_create_dma_buf(w, h, fourcc, src, w, &buf, &fd, &stride,
>                                     &offset);
>         if (res != PIGLIT_PASS)
>                 return res;
>
> -       return sample_buffer(buf, fd, fourcc, w, h, stride, offset);
> +       return sample_buffer(buf, fourcc);
>  }
> diff --git a/tests/spec/ext_image_dma_buf_import/sample_common.h b/tests/spec/ext_image_dma_buf_import/sample_common.h
> index db2ff82..36a5bb5 100644
> --- a/tests/spec/ext_image_dma_buf_import/sample_common.h
> +++ b/tests/spec/ext_image_dma_buf_import/sample_common.h
> @@ -32,12 +32,11 @@
>   * sample it using a shader program.
>   */
>  enum piglit_result
> -dma_buf_create_and_sample_32bpp(unsigned w, unsigned h, unsigned cpp,
> +dma_buf_create_and_sample_32bpp(unsigned w, unsigned h,
>                                 int fourcc, const unsigned char *src);
>
>  enum piglit_result
> -egl_image_for_dma_buf_fd(int fd, int fourcc, int w, int h,
> -                        unsigned stride, unsigned offset, EGLImageKHR *out_img);
> +egl_image_for_dma_buf_fd(struct piglit_dma_buf *buf, int fd, int fourcc, EGLImageKHR *out_img);
>
>  enum piglit_result
>  texture_for_egl_image(EGLImageKHR img, GLuint *out_tex);
> diff --git a/tests/spec/ext_image_dma_buf_import/sample_rgb.c b/tests/spec/ext_image_dma_buf_import/sample_rgb.c
> index af9b39f..ae69e98 100644
> --- a/tests/spec/ext_image_dma_buf_import/sample_rgb.c
> +++ b/tests/spec/ext_image_dma_buf_import/sample_rgb.c
> @@ -59,7 +59,7 @@ piglit_display(void)
>
>         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
>
> -       res = dma_buf_create_and_sample_32bpp(2, 2, 4, fourcc, src);
> +       res = dma_buf_create_and_sample_32bpp(2, 2, 4, src);
>         if (res != PIGLIT_PASS)
>                 return res;
>
> diff --git a/tests/spec/ext_image_dma_buf_import/sample_yuv.c b/tests/spec/ext_image_dma_buf_import/sample_yuv.c
> index 74826c1..6119b08 100644
> --- a/tests/spec/ext_image_dma_buf_import/sample_yuv.c
> +++ b/tests/spec/ext_image_dma_buf_import/sample_yuv.c
> @@ -108,7 +108,7 @@ piglit_display(void)
>
>         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
>
> -       res = dma_buf_create_and_sample_32bpp(4, 4, 1, fourcc, t);
> +       res = dma_buf_create_and_sample_32bpp(4, 4, fourcc, t);
>         if (res != PIGLIT_PASS)
>                 return res;
>
> diff --git a/tests/util/piglit-framework-gl.c b/tests/util/piglit-framework-gl.c
> index 9748ddf..09a6932 100644
> --- a/tests/util/piglit-framework-gl.c
> +++ b/tests/util/piglit-framework-gl.c
> @@ -265,9 +265,9 @@ piglit_set_reshape_func(void (*func)(int w, int h))
>                 gl_fw->set_reshape_func(gl_fw, func);
>  }
>
> -
> +/* TODO drop fd/stride/offset args */
>  enum piglit_result
> -piglit_create_dma_buf(unsigned w, unsigned h, unsigned cpp,
> +piglit_create_dma_buf(unsigned w, unsigned h, unsigned cpp_or_fourcc,
>                       const void *src_data, unsigned src_stride,
>                       struct piglit_dma_buf **buf, int *fd,
>                       unsigned *stride, unsigned *offset)
> @@ -279,8 +279,8 @@ piglit_create_dma_buf(unsigned w, unsigned h, unsigned cpp,
>         if (!gl_fw->create_dma_buf)
>                 return PIGLIT_SKIP;
>
> -       return gl_fw->create_dma_buf(w, h, cpp, src_data, src_stride, buf, fd,
> -                               stride, offset);
> +       return gl_fw->create_dma_buf(w, h, cpp_or_fourcc, src_data,
> +                               buf, fd, stride, offset);
>  }
>
>  void
> diff --git a/tests/util/piglit-framework-gl.h b/tests/util/piglit-framework-gl.h
> index 81c1a5e..ee0b9f2 100644
> --- a/tests/util/piglit-framework-gl.h
> +++ b/tests/util/piglit-framework-gl.h
> @@ -316,7 +316,7 @@ struct piglit_dma_buf;
>   * buffers, the return value is PIGLIT_SKIP instead of PIGLIT_FAIL.
>   */
>  enum piglit_result
> -piglit_create_dma_buf(unsigned w, unsigned h, unsigned cpp,
> +piglit_create_dma_buf(unsigned w, unsigned h, unsigned cpp_or_fourcc,
>                       const void *src_data, unsigned src_stride,
>                       struct piglit_dma_buf **buf, int *fd,
>                       unsigned *stride, unsigned *offset);
> diff --git a/tests/util/piglit-framework-gl/piglit_drm_dma_buf.c b/tests/util/piglit-framework-gl/piglit_drm_dma_buf.c
> index cd308bc..6b813d3 100644
> --- a/tests/util/piglit-framework-gl/piglit_drm_dma_buf.c
> +++ b/tests/util/piglit-framework-gl/piglit_drm_dma_buf.c
> @@ -23,6 +23,7 @@
>
>  #include "piglit-util-gl.h"
>  #include "piglit_drm_dma_buf.h"
> +#include "drm_fourcc.h"
>  #ifdef HAVE_LIBDRM_INTEL
>  #include <libdrm/intel_bufmgr.h>
>  #endif
> @@ -41,21 +42,13 @@
>
>  #define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
>
> -struct piglit_dma_buf {
> -       unsigned w;
> -       unsigned h;
> -       unsigned stride;
> -       int fd;
> -       void *priv;
> -};
> -
>  struct piglit_drm_driver {
>         int fd;
>         char *name;
>
>         bool
>         (*create)(unsigned w, unsigned h, unsigned cpp,
> -                 const unsigned char *src_data, unsigned src_stride,
> +                 const unsigned char *src_data,
>                   struct piglit_dma_buf *buf);
>
>         bool
> @@ -133,23 +126,43 @@ piglit_intel_bufmgr_get(void)
>  }
>
>  static bool
> -piglit_intel_buf_create(unsigned w, unsigned h, unsigned cpp,
> -                       const unsigned char *src_data, unsigned src_stride,
> -                       struct piglit_dma_buf *buf)
> +piglit_intel_buf_create(unsigned w, unsigned h, unsigned cpp_or_fourcc,
> +                       const unsigned char *src_data, struct piglit_dma_buf *buf)
>  {
>         unsigned i;
>         drm_intel_bo *bo;
> -       unsigned stride = ALIGN(w * cpp, 4);
>         drm_intel_bufmgr *mgr = piglit_intel_bufmgr_get();
> +       unsigned stride, src_stride, cpp;
> +       unsigned buf_h = h;
>
>         if (!mgr || h % 2)
>                 return false;
>
> -       bo = drm_intel_bo_alloc(mgr, "piglit_dma_buf", h * stride, 4096);
> +       switch (cpp_or_fourcc) {
> +       case 1:
> +       case 2:
> +       case 4:
> +               cpp = cpp_or_fourcc;
> +               break;
> +       case DRM_FORMAT_NV12:
> +       case DRM_FORMAT_YUV420:
> +       case DRM_FORMAT_YVU420:
> +               cpp = 1;
> +               buf_h = h * 3 / 2;
> +               break;
> +       default:
> +               assert(0);
> +               return false;
> +       }
> +
> +       src_stride = cpp * w;
> +       stride = ALIGN(w * cpp, 4);
> +
> +       bo = drm_intel_bo_alloc(mgr, "piglit_dma_buf", buf_h * stride, 4096);
>         if (!bo)
>                 return false;
>
> -       for (i = 0; i < h; ++i) {
> +       for (i = 0; i < buf_h; ++i) {
>                 if (drm_intel_bo_subdata(bo, i * stride, w * cpp,
>                         src_data + i * src_stride)) {
>                         drm_intel_bo_unreference(bo);
> @@ -159,10 +172,33 @@ piglit_intel_buf_create(unsigned w, unsigned h, unsigned cpp,
>
>         buf->w = w;
>         buf->h = h;
> -       buf->stride = stride;
> +       buf->offset[0] = 0;
> +       buf->stride[0] = stride;
>         buf->fd = 0;
>         buf->priv = bo;
>
> +       switch (cpp_or_fourcc) {
> +       case DRM_FORMAT_NV12:
> +               buf->offset[1] = stride * h;
> +               buf->stride[1] = stride;
> +               break;
> +       case DRM_FORMAT_YUV420:
> +       case DRM_FORMAT_YVU420:
> +               // XXX previously egl_image_for_dma_buf_fd() was using
> +               // stride rather than stride/2 for U and V planes, which
> +               // is probably not right.. maybe i965 ignores it??
> +               // Now things fail for YV12 (but not YU12??).. seems like
> +               // there is a bug in i965, since at least what the test
> +               // was doing before seems pretty bogus

The test was using U and V planes with the same stride as the Y plane,
laid out side by side below the Y plane:

+-------+
|       |
|       |
+---+---+
|   |   |
+---+---+

Plane 1 is at offset (sizeof plane 0) with the same stride, plane 2 is
at offset (sizeof plane 0 + stride / 2) with the same stride.

If we have the gbm eglimage path, why do we keep the intel specific code around?

> +               buf->offset[1] = stride * h;
> +               buf->stride[1] = stride / 2;
> +               buf->offset[2] = buf->offset[1] + (stride * h / 2 / 2);
> +               buf->stride[2] = stride / 2;
> +               break;
> +       default:
> +               break;
> +       }
> +
>         return true;
>  }
>
> @@ -201,9 +237,8 @@ piglit_gbm_get(void)
>  }
>
>  static bool
> -piglit_gbm_buf_create(unsigned w, unsigned h, unsigned cpp,
> -                       const unsigned char *src_data, unsigned src_stride,
> -                       struct piglit_dma_buf *buf)
> +piglit_gbm_buf_create(unsigned w, unsigned h, unsigned cpp_or_fourcc,
> +                       const unsigned char *src_data, struct piglit_dma_buf *buf)
>  {
>         unsigned i;
>         struct gbm_bo *bo;
> @@ -212,28 +247,65 @@ piglit_gbm_buf_create(unsigned w, unsigned h, unsigned cpp,
>         void *dst_data;
>         void *map_data = NULL;
>         enum gbm_bo_format format;
> +       unsigned cpp = 0, src_stride;
> +       unsigned buf_w = w;
> +       unsigned buf_h = h;
>
> -       if (!gbm || h % 2)
> +       if (!gbm || h % 2 || w % 2)
>                 return false;
>
> -       /* It would be nice if we took in a fourcc instead of a cpp */
> -       switch (cpp) {

Can we just switch over to always taking a fourcc? This cpp_or_fourcc is messy.

> +       switch (cpp_or_fourcc) {
>         case 1:
> -               format = GBM_FORMAT_C8;
> +               format = GBM_FORMAT_R8;
> +               cpp = 1;
> +               src_stride = cpp * w;
> +               break;
> +       case 2:
> +               format = GBM_FORMAT_GR88;
> +               cpp = 2;
> +               src_stride = cpp * w;
>                 break;
>         case 4:
>                 format = GBM_BO_FORMAT_ARGB8888;
> +               cpp = 4;
> +               src_stride = cpp * w;
> +               break;
> +       /* For YUV formats, the U/V planes might have a greater relative
> +        * pitch.  For example, if the driver needs pitch aligned to 32
> +        * pixels, for a 4x4 YUV image, the stride of both the Y and U/V
> +        * planes will be 32 bytes.  Not 32 for Y and 16 for U/V.  To
> +        * account for this, use a 2cpp format with half the width.  For
> +        * hardware that only has stride requirements in bytes (rather
> +        * than pixels) this will work out the same.  For hardware that
> +        * has pitch alignment requirements in pixels, this will give an
> +        * overly conservative alignment for Y but a sufficient alignment
> +        * for U/V.
> +        */
> +       case DRM_FORMAT_NV12:
> +               format = GBM_FORMAT_GR88;
> +               buf_w = w / 2;
> +               buf_h = h * 3 / 2;
> +               src_stride = w;
> +               cpp = 1;
> +               break;
> +       case DRM_FORMAT_YUV420:
> +       case DRM_FORMAT_YVU420:
> +               format = GBM_FORMAT_GR88;
> +               buf_w = w / 2;
> +               buf_h = h * 2;    /* U/V not interleaved */
> +               src_stride = w;
> +               cpp = 1;
>                 break;
>         default:
> -               fprintf(stderr, "Unknown cpp %d\n", cpp);
> +               fprintf(stderr, "Unknown cpp/fourcc %x\n", cpp_or_fourcc);
>                 return false;
>         }
>
> -       bo = gbm_bo_create(gbm, w, h, format, GBM_BO_USE_RENDERING);
> +       bo = gbm_bo_create(gbm, buf_w, buf_h, format, GBM_BO_USE_RENDERING);
>         if (!bo)
>                 return false;
>
> -       dst_data = gbm_bo_map(bo, 0, 0, w, h, GBM_BO_TRANSFER_WRITE,
> +       dst_data = gbm_bo_map(bo, 0, 0, buf_w, buf_h, GBM_BO_TRANSFER_WRITE,
>                               &dst_stride, &map_data);
>         if (!dst_data) {
>                 fprintf(stderr, "Failed to map GBM bo\n");
> @@ -241,18 +313,49 @@ piglit_gbm_buf_create(unsigned w, unsigned h, unsigned cpp,
>                 return NULL;
>         }
>
> +       buf->w = w;
> +       buf->h = h;
> +       buf->offset[0] = 0;
> +       buf->stride[0] = dst_stride;
> +       buf->fd = -1;
> +       buf->priv = bo;
> +
>         for (i = 0; i < h; ++i) {
>                 memcpy((char *)dst_data + i * dst_stride,
>                        src_data + i * src_stride,
>                        w * cpp);
>         }
> +
> +       switch (cpp_or_fourcc) {
> +       case DRM_FORMAT_NV12:
> +               buf->offset[1] = dst_stride * h;
> +               buf->stride[1] = dst_stride;
> +               for (i = 0; i < h/2; ++i) {
> +                       memcpy(((char *)dst_data + buf->offset[1]) + i * buf->stride[1],
> +                               (src_data + (w*h)) + i * src_stride, w);
> +               }
> +               break;
> +       case DRM_FORMAT_YUV420:
> +       case DRM_FORMAT_YVU420:
> +               buf->offset[1] = dst_stride * h;
> +               buf->stride[1] = dst_stride / 2;
> +               for (i = 0; i < h/2; ++i) {
> +                       memcpy(((char *)dst_data + buf->offset[1]) + i * buf->stride[1],
> +                               (src_data + (w*h)) + i * src_stride / 2, w / 2);
> +               }
> +               buf->offset[2] = buf->offset[1] + (dst_stride * h / 2 / 2);
> +               buf->stride[2] = dst_stride / 2;
> +               for (i = 0; i < h/2; ++i) {
> +                       memcpy(((char *)dst_data + buf->offset[2]) + i * buf->stride[2],
> +                               (src_data + (w*h) + (w*h/4)) + i * src_stride / 2, w / 2);
> +               }
> +               break;
> +       default:
> +               break;
> +       }
> +
>         gbm_bo_unmap(bo, map_data);
>
> -       buf->w = w;
> -       buf->h = h;
> -       buf->stride = dst_stride;
> -       buf->fd = 0;
> -       buf->priv = bo;
>
>         return true;
>  }
> @@ -352,10 +455,9 @@ piglit_drm_get_driver(void)
>  }
>
>  enum piglit_result
> -piglit_drm_create_dma_buf(unsigned w, unsigned h, unsigned cpp,
> -                       const void *src_data, unsigned src_stride,
> -                       struct piglit_dma_buf **buf, int *fd,
> -                       unsigned *stride, unsigned *offset)
> +piglit_drm_create_dma_buf(unsigned w, unsigned h, unsigned cpp_or_fourcc,
> +                       const void *src_data,  struct piglit_dma_buf **buf,
> +                       int *fd, unsigned *stride, unsigned *offset)
>  {
>         struct piglit_dma_buf *drm_buf;
>         const struct piglit_drm_driver *drv = piglit_drm_get_driver();
> @@ -367,7 +469,7 @@ piglit_drm_create_dma_buf(unsigned w, unsigned h, unsigned cpp,
>         if (!drm_buf)
>                 return PIGLIT_FAIL;
>
> -       if (!drv->create(w, h, cpp, src_data, src_stride, drm_buf)) {
> +       if (!drv->create(w, h, cpp_or_fourcc, src_data, drm_buf)) {
>                 free(drm_buf);
>                 return PIGLIT_FAIL;
>         }
> @@ -379,7 +481,7 @@ piglit_drm_create_dma_buf(unsigned w, unsigned h, unsigned cpp,
>
>         *buf = drm_buf;
>         *fd = drm_buf->fd;
> -       *stride = drm_buf->stride;
> +       *stride = drm_buf->stride[0];
>         *offset = 0;
>
>         return PIGLIT_PASS;
> diff --git a/tests/util/piglit-framework-gl/piglit_drm_dma_buf.h b/tests/util/piglit-framework-gl/piglit_drm_dma_buf.h
> index 2c72eca..7a2b5c5 100644
> --- a/tests/util/piglit-framework-gl/piglit_drm_dma_buf.h
> +++ b/tests/util/piglit-framework-gl/piglit_drm_dma_buf.h
> @@ -23,13 +23,19 @@
>  #ifndef PIGLIT_DRM_DMA_BUF_H
>  #define PIGLIT_DRM_DMA_BUF_H
>
> -struct piglit_dma_buf;
> +struct piglit_dma_buf {
> +       unsigned w;
> +       unsigned h;
> +       unsigned offset[3];
> +       unsigned stride[3];
> +       int fd;
> +       void *priv;
> +};
>
>  enum piglit_result
> -piglit_drm_create_dma_buf(unsigned w, unsigned h, unsigned cpp,
> -                         const void *src_data, unsigned src_stride,
> -                         struct piglit_dma_buf **buf, int *fd,
> -                         unsigned *stride, unsigned *offset);
> +piglit_drm_create_dma_buf(unsigned w, unsigned h, unsigned cpp_or_fourcc,
> +                       const void *src_data,  struct piglit_dma_buf **buf,
> +                       int *fd, unsigned *stride, unsigned *offset);
>
>  void
>  piglit_drm_destroy_dma_buf(struct piglit_dma_buf *buf);
> diff --git a/tests/util/piglit-framework-gl/piglit_gl_framework.h b/tests/util/piglit-framework-gl/piglit_gl_framework.h
> index 97fecca..1966cf9 100644
> --- a/tests/util/piglit-framework-gl/piglit_gl_framework.h
> +++ b/tests/util/piglit-framework-gl/piglit_gl_framework.h
> @@ -73,10 +73,9 @@ struct piglit_gl_framework {
>         (*destroy)(struct piglit_gl_framework *gl_fw);
>
>         enum piglit_result
> -       (*create_dma_buf)(unsigned w, unsigned h, unsigned cpp,
> -                         const void *src_data, unsigned src_stride,
> -                         struct piglit_dma_buf **buf, int *fd,
> -                         unsigned *stride, unsigned *offset);
> +       (*create_dma_buf)(unsigned w, unsigned h, unsigned cpp_or_fourcc,
> +                         const void *src_data, struct piglit_dma_buf **buf,
> +                         int *fd, unsigned *stride, unsigned *offset);
>
>         void
>         (*destroy_dma_buf)(struct piglit_dma_buf *buf);
> --
> 2.7.4
>


More information about the Piglit mailing list