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

Rob Clark robdclark at gmail.com
Tue Sep 6 20:23:11 UTC 2016


On Tue, Sep 6, 2016 at 4:04 PM, Kristian Høgsberg <hoegsberg at gmail.com> wrote:
> 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.

ahh, cunning.. that actually should avoid the invalid pitch for chroma
plane(s) issue, so maybe what I thought was happening wasn't actually
the problem..

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

only plausible reason I could come up with is that gbm path depends on
a fairly recent version of gbm to have the gbm_bo_map/unmap() bits..
if that isn't an issue, we should drop the intel path.  Otherwise we
should plan on eventually dropping intel path.

>> +               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.

I think it made a bit more sense when I started (and thought that this
would be a smaller patch) to avoid extra churn..

Maybe in the end since you have the U/V interleaved by row, we might
not end up needing my patch.  But otherwise, at this point it wouldn't
make the patch that much larger to fix up the handful of rgb tests

BR,
-R

>> +       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