[Mesa-dev] [PATCH 2/2] egl: add initial implementation for VA/EGL interop.

Gwenole Beauchesne gwenole.beauchesne at intel.com
Fri Aug 17 04:56:34 PDT 2012


Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne at intel.com>
---
 configure.ac                     |   27 +++++++
 include/EGL/eglmesaext.h         |    9 +++
 src/egl/drivers/dri2/Makefile.am |    1 +
 src/egl/drivers/dri2/egl_dri2.c  |  155 ++++++++++++++++++++++++++++++++++++++
 src/egl/drivers/dri2/egl_dri2.h  |    5 ++
 src/egl/main/eglimage.c          |    8 ++
 src/egl/main/eglimage.h          |    4 +
 7 files changed, 209 insertions(+)

diff --git a/configure.ac b/configure.ac
index 89686b4..a177abe 100644
--- a/configure.ac
+++ b/configure.ac
@@ -604,6 +604,11 @@ AC_ARG_ENABLE([va],
          [enable va library @<:@default=auto@:>@])],
    [enable_va="$enableval"],
    [enable_va=auto])
+AC_ARG_ENABLE([vaapi],
+   [AS_HELP_STRING([--enable-vaapi-egl],
+         [enable VA/EGL interop @<:@default=auto@:>@])],
+   [enable_vaapi_egl="$enableval"],
+   [enable_vaapi_egl=yes])
 AC_ARG_ENABLE([opencl],
    [AS_HELP_STRING([--enable-opencl],
          [enable OpenCL library @<:@default=no@:>@])],
@@ -1558,6 +1563,27 @@ if test "x$enable_va" = xyes; then
 fi
 
 dnl
+dnl VA-API / EGL interop
+dnl
+
+if test "x$enable_egl" != xyes; then
+    enable_vaapi_egl="no"
+fi
+if test "x$enable_vaapi_egl" = xyes; then
+    PKG_CHECK_MODULES([LIBVA_EGL], [libva-egl], [:], [enable_vaapi_egl="no"])
+fi
+if test "x$enable_vaapi_egl" = xyes; then
+    saved_CPPFLAGS="$CPPFLAGS"
+    CPPFLAGS="$CPPFLAGS $LIBVA_EGL_CFLAGS"
+    AC_CHECK_HEADERS([va/va_egl.h], [:], [enable_vaapi_egl="no"])
+    AC_CHECK_HEADERS([va/va_backend_egl.h], [:], [enable_vaapi_egl="no"])
+    CPPFLAGS="$saved_CPPFLAGS"
+fi
+if test "x$enable_vaapi_egl" = xyes; then
+    DEFINES="$DEFINES -DHAVE_VA_EGL_INTEROP"
+fi
+
+dnl
 dnl OpenCL configuration
 dnl
 
@@ -2252,6 +2278,7 @@ if test "$enable_egl" = yes; then
     else
         echo "        EGL drivers:    $egl_drivers"
     fi
+    echo "        VA/EGL interop:  $enable_vaapi_egl"
 fi
 
 echo ""
diff --git a/include/EGL/eglmesaext.h b/include/EGL/eglmesaext.h
index d476d18..82b5652 100644
--- a/include/EGL/eglmesaext.h
+++ b/include/EGL/eglmesaext.h
@@ -153,6 +153,15 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOK) (EGLDisplay dpy, EG
 #define EGL_NATIVE_BUFFER_ANDROID       0x3140  /* eglCreateImageKHR target */
 #endif
 
+#ifndef EGL_INTEL_VA_pixel_buffer
+#define EGL_INTEL_VA_pixel_buffer 1
+
+#define EGL_VA_PIXEL_BUFFER_INTEL       0x31DB /* eglCreateImageKHR target */
+#define EGL_VA_BUFFER_PLANE_INTEL       0x31D6 /* eglCreateImageKHR attribute */
+#define EGL_VA_BUFFER_STRUCTURE_INTEL   0x3080 /* eglCreateImageKHR attribute */
+#define EGL_VA_PICTURE_STRUCTURE_INTEL  0x31DA /* eglCreateImageKHR attribute */
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/egl/drivers/dri2/Makefile.am b/src/egl/drivers/dri2/Makefile.am
index 49ec06b..c11ee3c 100644
--- a/src/egl/drivers/dri2/Makefile.am
+++ b/src/egl/drivers/dri2/Makefile.am
@@ -30,6 +30,7 @@ AM_CFLAGS = \
 	$(DEFINES) \
 	$(LIBDRM_CFLAGS) \
 	$(LIBUDEV_CFLAGS) \
+        $(LIBVA_EGL_CFLAGS) \
 	-DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\"
 
 noinst_LTLIBRARIES = libegl_dri2.la
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index 464f768..fb9f91e 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -1175,6 +1175,157 @@ dri2_create_image_wayland_wl_buffer(_EGLDisplay *disp, _EGLContext *ctx,
 }
 #endif
 
+#ifdef HAVE_VA_EGL_INTEROP
+/* Ensure the DRIimage is attached to the VA/EGL client buffer */
+static __DRIimage *
+dri2_va_reference_buffer(_EGLDisplay *disp, struct va_egl_client_buffer *buffer)
+{
+   struct dri2_egl_display * const dri2_dpy = dri2_egl_display(disp);
+   int format, stride;
+
+   switch (buffer->format) {
+   case VA_EGL_PIXEL_FORMAT_ARGB8888:
+      format = __DRI_IMAGE_FORMAT_ARGB8888;
+      stride = buffer->pitches[0] / 4;
+      break;
+   case VA_EGL_PIXEL_FORMAT_XRGB8888:
+      format = __DRI_IMAGE_FORMAT_XRGB8888;
+      stride = buffer->pitches[0] / 4;
+      break;
+   case VA_EGL_PIXEL_FORMAT_ABGR8888:
+      format = __DRI_IMAGE_FORMAT_ABGR8888;
+      stride = buffer->pitches[0] / 4;
+      break;
+   case VA_EGL_PIXEL_FORMAT_NV12:
+   case VA_EGL_PIXEL_FORMAT_YUV410P:
+   case VA_EGL_PIXEL_FORMAT_YUV411P:
+   case VA_EGL_PIXEL_FORMAT_YUV420P:
+   case VA_EGL_PIXEL_FORMAT_YUV422P:
+   case VA_EGL_PIXEL_FORMAT_YUV444P:
+      format = __DRI_IMAGE_FORMAT_NONE;
+      stride = buffer->pitches[0];
+      break;
+   default:
+      _eglLog(_EGL_DEBUG, "DRI2-VA: failed to validate pixel format %d",
+              buffer->format);
+      return NULL;
+   }
+   return dri2_dpy->image->createImageFromName(dri2_dpy->dri_screen,
+                                               buffer->width,
+                                               buffer->height,
+                                               format,
+                                               buffer->handle,
+                                               stride,
+                                               NULL);
+}
+
+static _EGLImage *
+dri2_create_image_va_pixel_buffer(_EGLDisplay *disp, _EGLContext *ctx,
+                                  EGLClientBuffer _buffer,
+                                  const EGLint *attr_list)
+{
+   struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp);
+   struct va_egl_client_buffer *buffer = _buffer;
+   const struct dri_image_descriptor *desc;
+   __DRIimage *dri_image;
+   _EGLImageAttribs attrs;
+   EGLint plane, width, height, stride, cpp, offset, err;
+   uint32_t structure, format;
+
+   if (!buffer || buffer->version != VA_EGL_CLIENT_BUFFER_VERSION) {
+      _eglError(EGL_BAD_PARAMETER, "DRI2-VA: unsupported EGLClientBuffer");
+      return NULL;
+   }
+
+   err = _eglParseImageAttribList(&attrs, disp, attr_list);
+   if (err != EGL_SUCCESS) {
+      _eglError(EGL_BAD_PARAMETER,
+                "DRI2-VA: failed to parse eglCreateImageKHR() attributes");
+      return NULL;
+   }
+
+   plane = attrs.PlaneWL;
+   if (plane < 0) {
+      _eglError(EGL_BAD_PARAMETER, "DRI2-VA: got negative plane value");
+      return NULL;
+   }
+
+   structure = attrs.VABufferStructureINTEL;
+   if (structure && structure != buffer->structure) {
+      _eglError(EGL_BAD_PARAMETER,
+                "DRI2-VA: buffer structure coercition is not supported yet");
+      return NULL;
+   }
+
+   structure = attrs.VAPictureStructureINTEL;
+   if (structure != VA_EGL_PICTURE_STRUCTURE_FRAME) {
+      _eglError(EGL_BAD_PARAMETER,
+                "DRI2-VA: interlaced picture structure is not supported yet");
+      return NULL;
+   }
+
+   dri_image = buffer->private_data;
+   if (!dri_image) {
+      dri_image = dri2_va_reference_buffer(disp, buffer);
+      if (!dri_image) {
+         _eglError(EGL_BAD_ALLOC, "DRI2-VA: could not reference VA buffer");
+         return NULL;
+      }
+      buffer->private_data = dri_image;
+      buffer->destroy_private_data =
+         (void (*)(void *))dri2_dpy->image->destroyImage;
+   }
+
+   switch (buffer->format) {
+   case VA_EGL_PIXEL_FORMAT_ARGB8888:
+      desc = &dri_image_desc_ARGB8888;
+      break;
+   case VA_EGL_PIXEL_FORMAT_XRGB8888:
+      desc = &dri_image_desc_XRGB8888;
+      break;
+   case VA_EGL_PIXEL_FORMAT_NV12:
+      desc = &dri_image_desc_NV12;
+      break;
+   case VA_EGL_PIXEL_FORMAT_YUV420P:
+      desc = &dri_image_desc_YUV420;
+      break;
+   case VA_EGL_PIXEL_FORMAT_YUV422P:
+      desc = &dri_image_desc_YUV422;
+      break;
+   case VA_EGL_PIXEL_FORMAT_YUV444P:
+      desc = &dri_image_desc_YUV444;
+      break;
+   default:
+      desc = NULL;
+      break;
+   }
+   if (!desc) {
+      _eglError(EGL_BAD_PARAMETER, "DRI2-VA: unsupported pixel format");
+      return NULL;
+   }
+
+   if (plane >= desc->nplanes) {
+      _eglError(EGL_BAD_PARAMETER, "DRI2-VA: invalid plane index");
+      return NULL;
+   }
+
+   format = desc->planes[plane].dri_format;
+   width  = buffer->width >> desc->planes[plane].width_shift;
+   height = buffer->height >> desc->planes[plane].height_shift;
+   stride = buffer->pitches[plane];
+   cpp    = desc->planes[plane].cpp;
+   offset = buffer->offsets[plane];
+
+   dri_image = dri2_dpy->image->createSubImage(dri_image, width, height,format,
+                                               offset, stride / cpp, NULL);
+   if (!dri_image) {
+      _eglError(EGL_BAD_ALLOC, "DRI2-VA: could not create sub-buffer");
+      return NULL;
+   }
+   return dri2_create_image(disp, dri_image);
+}
+#endif
+
 _EGLImage *
 dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
 		      _EGLContext *ctx, EGLenum target,
@@ -1191,6 +1342,10 @@ dri2_create_image_khr(_EGLDriver *drv, _EGLDisplay *disp,
    case EGL_WAYLAND_BUFFER_WL:
       return dri2_create_image_wayland_wl_buffer(disp, ctx, buffer, attr_list);
 #endif
+#ifdef HAVE_VA_EGL_INTEROP
+   case EGL_VA_PIXEL_BUFFER_INTEL:
+      return dri2_create_image_va_pixel_buffer(disp, ctx, buffer, attr_list);
+#endif
    default:
       _eglError(EGL_BAD_PARAMETER, "dri2_create_image_khr");
       return EGL_NO_IMAGE_KHR;
diff --git a/src/egl/drivers/dri2/egl_dri2.h b/src/egl/drivers/dri2/egl_dri2.h
index c30e230..48d958e 100644
--- a/src/egl/drivers/dri2/egl_dri2.h
+++ b/src/egl/drivers/dri2/egl_dri2.h
@@ -44,6 +44,11 @@
 #include <GL/gl.h>
 #include <GL/internal/dri_interface.h>
 
+#ifdef HAVE_VA_EGL_INTEROP
+#  include <va/va_egl.h>
+#  include <va/va_backend_egl.h>
+#endif
+
 #ifdef HAVE_DRM_PLATFORM
 #include <gbm_driint.h>
 #endif
diff --git a/src/egl/main/eglimage.c b/src/egl/main/eglimage.c
index bfae709..0ffe673 100644
--- a/src/egl/main/eglimage.c
+++ b/src/egl/main/eglimage.c
@@ -93,6 +93,14 @@ _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *dpy,
          attrs->PlaneWL = val;
          break;
 
+      /* EGL_INTEL_VA_pixel_buffer */
+      case EGL_VA_BUFFER_STRUCTURE_INTEL:
+         attrs->VABufferStructureINTEL = val;
+         break;
+      case EGL_VA_PICTURE_STRUCTURE_INTEL:
+         attrs->VAPictureStructureINTEL = val;
+         break;
+
       default:
          /* unknown attrs are ignored */
          break;
diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h
index 9cc86d5..d1d163b 100644
--- a/src/egl/main/eglimage.h
+++ b/src/egl/main/eglimage.h
@@ -53,6 +53,10 @@ struct _egl_image_attribs
 
    /* EGL_WL_bind_wayland_display */
    EGLint PlaneWL;
+
+   /* EGL_INTEL_VA_pixel_buffer */
+   EGLint VABufferStructureINTEL;
+   EGLint VAPictureStructureINTEL;
 };
 
 /**
-- 
1.7.9.5



More information about the mesa-dev mailing list