summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXiang, Haihao <haihao.xiang@intel.com>2011-11-10 10:47:03 +0800
committerXiang, Haihao <haihao.xiang@intel.com>2011-12-14 08:27:03 +0800
commit1cda44018e922a4557f041735a2c903c6d40bfb2 (patch)
tree5fb6ec672c4e0f96464db10376a483d78d9f4eda
parent731d575b238238e90d576692af82f74d47c1ae77 (diff)
VA/EGL interfaces
Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com>
-rw-r--r--va/Makefile.am2
-rw-r--r--va/egl/Makefile.am14
-rw-r--r--va/egl/va_backend_egl.h32
-rw-r--r--va/egl/va_egl.c178
-rw-r--r--va/egl/va_egl.h96
-rw-r--r--va/egl/va_egl_impl.c521
-rw-r--r--va/egl/va_egl_impl.h12
-rw-r--r--va/egl/va_egl_private.h74
-rw-r--r--va/va_backend.h4
9 files changed, 921 insertions, 12 deletions
diff --git a/va/Makefile.am b/va/Makefile.am
index 16a1e8f..bc70435 100644
--- a/va/Makefile.am
+++ b/va/Makefile.am
@@ -92,7 +92,7 @@ libva_egl_la_SOURCES =
libva_egl_la_LDFLAGS = $(LDADD)
libva_egl_la_DEPENDENCIES = $(libvacorelib) egl/libva_egl.la libva-x11.la
libva_egl_la_LIBADD = $(libvacorelib) egl/libva_egl.la libva-x11.la \
- $(GL_DEPS_LIBS) -ldl
+ $(EGL_DEPS_LIBS) -ldl
endif
if BUILD_DUMMY_BACKEND
diff --git a/va/egl/Makefile.am b/va/egl/Makefile.am
index c02daa7..74f3c70 100644
--- a/va/egl/Makefile.am
+++ b/va/egl/Makefile.am
@@ -20,16 +20,22 @@
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-INCLUDES = -DLINUX -I$(top_srcdir) -I$(top_srcdir)/va -I$(top_srcdir)/va/x11
+INCLUDES = -DLINUX -I$(top_srcdir) -I$(top_srcdir)/va
source_c = \
- va_egl.c
+ va_egl.c \
+ va_egl_impl.c \
+ $(NULL)
source_h = \
va_egl.h \
- va_backend_egl.h
+ va_backend_egl.h \
+ $(NULL)
-source_h_priv =
+source_h_priv = \
+ va_egl_impl.h \
+ va_egl_private.h \
+ $(NULL)
noinst_LTLIBRARIES = libva_egl.la
libva_eglincludedir = ${includedir}/va
diff --git a/va/egl/va_backend_egl.h b/va/egl/va_backend_egl.h
index 925d933..9dae84f 100644
--- a/va/egl/va_backend_egl.h
+++ b/va/egl/va_backend_egl.h
@@ -36,6 +36,38 @@ struct VADriverVTableEGL {
void **buffer
);
/* TBD: more APIs for EGL */
+ /* Optional: create a surface used for display to OpenGL */
+ VAStatus (*vaCreateSurfaceEGL)(
+ VADriverContextP ctx,
+ GLenum target,
+ GLuint texture,
+ unsigned int width,
+ unsigned int height,
+ VASurfaceEGL *egl_surface
+ );
+
+ /* Optional: destroy a VA/EGL surface */
+ VAStatus (*vaDestroySurfaceEGL)(
+ VADriverContextP ctx,
+ VASurfaceEGL egl_surface
+ );
+
+ VAStatus (*vaAssociateSurfaceEGL)(
+ VADriverContextP ctx,
+ VASurfaceEGL egl_surface,
+ VASurfaceID surface,
+ unsigned int flags
+ );
+
+ VAStatus (*vaUpdateAssociatedSurfaceEGL)(
+ VADriverContextP ctx,
+ VASurfaceEGL egl_surface
+ );
+
+ VAStatus (*vaDeassociateSurfaceEGL)(
+ VADriverContextP ctx,
+ VASurfaceEGL egl_surface
+ );
};
#endif /* VA_BACKEND_EGL_H */
diff --git a/va/egl/va_egl.c b/va/egl/va_egl.c
index 36e5504..6caf4f8 100644
--- a/va/egl/va_egl.c
+++ b/va/egl/va_egl.c
@@ -53,14 +53,34 @@
*
* Bellow API vaGetEGLClientBufferFromSurface is for this purpose
*/
-
-#include "va.h"
-#include "va_backend_egl.h"
-#include "va_egl.h"
+#include "va_egl_private.h"
+#include "va_egl_impl.h"
#define CTX(dpy) (((VADisplayContextP)dpy)->pDriverContext)
#define CHECK_DISPLAY(dpy) if( !vaDisplayIsValid(dpy) ) { return VA_STATUS_ERROR_INVALID_DISPLAY; }
+#define INIT_CONTEXT(ctx, dpy) do { \
+ if (!vaDisplayIsValid(dpy)) \
+ return VA_STATUS_ERROR_INVALID_DISPLAY; \
+ \
+ ctx = ((VADisplayContextP)(dpy))->pDriverContext; \
+ if (!(ctx)) \
+ return VA_STATUS_ERROR_INVALID_DISPLAY; \
+ \
+ status = va_egl_init_context(dpy); \
+ if (status != VA_STATUS_SUCCESS) \
+ return status; \
+ } while (0)
+
+#define INVOKE(ctx, func, args) do { \
+ VADriverVTablePrivEGLP vtable; \
+ vtable = &VA_DRIVER_CONTEXT_EGL(ctx)->vtable; \
+ if (!vtable->va##func##EGL) \
+ return VA_STATUS_ERROR_UNIMPLEMENTED; \
+ status = vtable->va##func##EGL args; \
+ } while (0)
+
+
VAStatus vaGetEGLClientBufferFromSurface (
VADisplay dpy,
VASurfaceID surface,
@@ -79,4 +99,154 @@ VAStatus vaGetEGLClientBufferFromSurface (
return VA_STATUS_ERROR_UNIMPLEMENTED;
}
+// Destroy VA/EGL display context
+static void va_DisplayContextDestroy(VADisplayContextP pDisplayContext)
+{
+ VADisplayContextEGLP pDisplayContextEGL;
+ VADriverContextP pDriverContext;
+ VADriverContextEGLP pDriverContextEGL;
+
+ if (!pDisplayContext)
+ return;
+
+ pDriverContext = pDisplayContext->pDriverContext;
+ pDriverContextEGL = pDriverContext->egl;
+ if (pDriverContextEGL) {
+ free(pDriverContextEGL);
+ pDriverContext->egl = NULL;
+ }
+
+ pDisplayContextEGL = pDisplayContext->opaque;
+ if (pDisplayContextEGL) {
+ vaDestroyFunc vaDestroy = pDisplayContextEGL->vaDestroy;
+ free(pDisplayContextEGL);
+ pDisplayContext->opaque = NULL;
+ if (vaDestroy)
+ vaDestroy(pDisplayContext);
+ }
+}
+
+// Return a suitable VADisplay for VA API
+VADisplay vaGetDisplayEGL(VANativeDisplay native_dpy,
+ EGLDisplay egl_dpy)
+{
+ VADisplay dpy = NULL;
+ VADisplayContextP pDisplayContext = NULL;
+ VADisplayContextEGLP pDisplayContextEGL = NULL;
+ VADriverContextP pDriverContext;
+ VADriverContextEGLP pDriverContextEGL = NULL;
+
+ dpy = vaGetDisplay(native_dpy);
+
+ if (!dpy)
+ return NULL;
+
+ if (egl_dpy == EGL_NO_DISPLAY)
+ goto error;
+
+ pDisplayContext = (VADisplayContextP)dpy;
+ pDriverContext = pDisplayContext->pDriverContext;
+
+ pDisplayContextEGL = calloc(1, sizeof(*pDisplayContextEGL));
+ if (!pDisplayContextEGL)
+ goto error;
+
+ pDriverContextEGL = calloc(1, sizeof(*pDriverContextEGL));
+ if (!pDriverContextEGL)
+ goto error;
+
+ pDisplayContextEGL->vaDestroy = pDisplayContext->vaDestroy;
+ pDisplayContext->vaDestroy = va_DisplayContextDestroy;
+ pDisplayContext->opaque = pDisplayContextEGL;
+ pDriverContextEGL->egl_display = egl_dpy;
+ pDriverContext->egl = pDriverContextEGL;
+ return dpy;
+
+error:
+ free(pDriverContextEGL);
+ free(pDisplayContextEGL);
+ pDisplayContext->vaDestroy(pDisplayContext);
+ return NULL;
+}
+
+// Create a surface used for display to OpenGL
+VAStatus vaCreateSurfaceEGL(
+ VADisplay dpy,
+ GLenum target,
+ GLuint texture,
+ unsigned int width,
+ unsigned int height,
+ VASurfaceEGL *gl_surface
+)
+{
+ VADriverContextP ctx;
+ VAStatus status;
+
+ if (target != GL_TEXTURE_2D)
+ return VA_STATUS_ERROR_INVALID_PARAMETER;
+
+ INIT_CONTEXT(ctx, dpy);
+
+ INVOKE(ctx, CreateSurface, (dpy, target, texture, width, height, gl_surface));
+ return status;
+}
+
+// Destroy a VA/EGL surface
+VAStatus vaDestroySurfaceEGL(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface
+)
+{
+ VADriverContextP ctx;
+ VAStatus status;
+
+ INIT_CONTEXT(ctx, dpy);
+
+ INVOKE(ctx, DestroySurface, (dpy, egl_surface));
+ return status;
+}
+
+VAStatus vaAssociateSurfaceEGL(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface,
+ VASurfaceID surface,
+ unsigned int flags
+)
+{
+ VADriverContextP ctx;
+ VAStatus status;
+
+ INIT_CONTEXT(ctx, dpy);
+
+ INVOKE(ctx, AssociateSurface, (dpy, egl_surface, surface, flags));
+ return status;
+}
+
+VAStatus vaUpdateAssociatedSurfaceEGL(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface
+)
+{
+ VADriverContextP ctx;
+ VAStatus status;
+
+ INIT_CONTEXT(ctx, dpy);
+
+ INVOKE(ctx, UpdateAssociatedSurface, (dpy, egl_surface));
+ return status;
+}
+
+VAStatus vaDeassociateSurfaceEGL(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface
+)
+{
+ VADriverContextP ctx;
+ VAStatus status;
+
+ INIT_CONTEXT(ctx, dpy);
+
+ INVOKE(ctx, DeassociateSurface, (dpy, egl_surface));
+ return status;
+}
diff --git a/va/egl/va_egl.h b/va/egl/va_egl.h
index 4243d0b..8f9c840 100644
--- a/va/egl/va_egl.h
+++ b/va/egl/va_egl.h
@@ -2,12 +2,16 @@
#define _VA_EGL_H_
#include <va/va.h>
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
#ifdef __cplusplus
extern "C" {
#endif
-typedef void* EGLClientBuffer;
+typedef void *VASurfaceEGL;
/*This function is used to get EGLClientBuffer
* (lower 16bits is buffer index, upper 16bits
@@ -20,6 +24,96 @@ VAStatus vaGetEGLClientBufferFromSurface (
EGLClientBuffer *buffer /* out*/
);
+/**
+ * Return a suitable VADisplay for VA API
+ *
+ * @param[in] native_dpy the native display
+ * @param[in] egl_dpy the EGL display
+ * @return a VADisplay
+ */
+VADisplay vaGetDisplayEGL(
+ VANativeDisplay native_dpy,
+ EGLDisplay egl_dpy
+);
+
+/**
+ * Create a surface used for display to OpenGL ES
+ *
+ * The application shall maintain the live EGL context itself.
+ *
+ * @param[in] dpy the VA display
+ * @param[in] target the GL target to which the texture needs to be bound, must be GL_TEXTURE_2D
+ * @param[in] texture the GL texture
+ * @param[in] width the surface width
+ * @param[in] height the surface height
+ * @param[out] gl_surface the VA/EGL surface
+ * @return VA_STATUS_SUCCESS if successful
+ */
+VAStatus vaCreateSurfaceEGL(
+ VADisplay dpy,
+ GLenum target,
+ GLuint texture,
+ unsigned int width,
+ unsigned int height,
+ VASurfaceEGL *gl_surface
+);
+
+/**
+ * Destroy a VA/EGL surface
+ *
+ * The application shall maintain the live EGL context itself.
+ *
+ * @param[in] dpy the VA display
+ * @param[in] gl_surface the VA surface
+ * @return VA_STATUS_SUCCESS if successful
+ */
+VAStatus vaDestroySurfaceEGL(
+ VADisplay dpy,
+ VASurfaceEGL gl_surface
+);
+
+/**
+ * Associate a EGLClientBuffer with a VA surface
+ *
+ * @param[in] dpy the VA display
+ * @param[in] egl_surface the VA/EGL destination surface
+ * @param[in] surface the VA surface
+ * @param[in] flags the flags to PutSurface
+ * @return VA_STATUS_SUCCESS if successful
+ */
+VAStatus vaAssociateSurfaceEGL(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface,
+ VASurfaceID surface,
+ unsigned int flags
+);
+
+/**
+ * Update the content of a VA/EGL surface
+ *
+ * Changes to VA surface are committed to VA/EGL surface at this point.
+ *
+ * @param[in] dpy the VA display
+ * @param[in] egl_surface the VA/EGL destination surface
+ * @return VA_STATUS_SUCCESS if successful
+ */
+VAStatus vaUpdateAssociatedSurfaceEGL(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface
+);
+
+/**
+ * Deassociate a EGLClientBuffer
+ *
+ * @param[in] dpy the VA display
+ * @param[in] egl_surface the VA/EGL destination surface
+ * @return VA_STATUS_SUCCESS if successful
+ */
+VAStatus vaDeassociateSurfaceEGL(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface
+);
+
#ifdef __cplusplus
}
#endif
diff --git a/va/egl/va_egl_impl.c b/va/egl/va_egl_impl.c
new file mode 100644
index 0000000..b47d266
--- /dev/null
+++ b/va/egl/va_egl_impl.c
@@ -0,0 +1,521 @@
+#define _GNU_SOURCE 1
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+#include <dlfcn.h>
+
+#include "va_egl_private.h"
+#include "va_egl_impl.h"
+
+// Returns the OpenGL ES VTable
+static inline VAOpenGLESVTableP
+gles_get_vtable(VADriverContextP ctx)
+{
+ return &VA_DRIVER_CONTEXT_EGL(ctx)->gles_vtable;
+}
+
+// Lookup for a EGL function
+typedef void (*EGLFuncPtr)(void);
+typedef EGLFuncPtr (*EGLGetProcAddressProc)(const char *);
+
+static EGLFuncPtr
+get_proc_address_default(const char *name)
+{
+ return NULL;
+}
+
+static EGLGetProcAddressProc
+get_proc_address_func(void)
+{
+ EGLGetProcAddressProc get_proc_func;
+
+ dlerror();
+ get_proc_func = (EGLGetProcAddressProc)
+ dlsym(RTLD_DEFAULT, "eglGetProcAddress");
+
+ if (!dlerror())
+ return get_proc_func;
+
+ return get_proc_address_default;
+}
+
+static inline EGLFuncPtr
+get_proc_address(const char *name)
+{
+ static EGLGetProcAddressProc get_proc_func = NULL;
+
+ get_proc_func = get_proc_address_func();
+
+ return get_proc_func(name);
+}
+
+// Check for GLES extensions (TFP, FBO)
+static int
+check_extension(const char *name, const char *exts)
+{
+ const char *end;
+ int name_len, n;
+
+ if (!name || !exts)
+ return 0;
+
+ end = exts + strlen(exts);
+ name_len = strlen(name);
+
+ while (exts < end) {
+ n = strcspn(exts, " ");
+
+ if (n == name_len && strncmp(name, exts, n) == 0)
+ return 1;
+
+ exts += (n + 1);
+ }
+
+ return 0;
+}
+
+static int
+check_extensions(VADriverContextP ctx, EGLDisplay egl_display)
+{
+ const char *exts;
+
+ exts = (const char *)eglQueryString(egl_display, EGL_EXTENSIONS);
+
+ if (!check_extension("EGL_KHR_image_pixmap", exts))
+ return 0;
+
+ exts = (const char *)glGetString(GL_EXTENSIONS);
+
+ if (!check_extension("GL_OES_EGL_image", exts))
+ return 0;
+
+#if 0
+ if (!check_extension("GL_OES_texture_npot", exts))
+ return 0;
+#endif
+
+ return 1;
+}
+
+static int
+init_extensions(VADriverContextP ctx)
+{
+ VAOpenGLESVTableP pOpenGLESVTable = gles_get_vtable(ctx);
+
+ /* EGL_KHR_image_pixmap */
+ pOpenGLESVTable->egl_create_image_khr =
+ (PFNEGLCREATEIMAGEKHRPROC)get_proc_address("eglCreateImageKHR");
+ pOpenGLESVTable->egl_destroy_image_khr =
+ (PFNEGLDESTROYIMAGEKHRPROC)get_proc_address("eglDestroyImageKHR");
+
+ /* GL_OES_EGL_image */
+ pOpenGLESVTable->gles_egl_image_target_texture_2d =
+ (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)get_proc_address("glEGLImageTargetTexture2DOES");
+
+ return 1;
+}
+
+/* ========================================================================= */
+/* === VA/EGL implementation from the driver (fordward calls) === */
+/* ========================================================================= */
+#ifdef INVOKE
+#undef INVOKE
+#endif
+
+#define INVOKE(ctx, func, args) do { \
+ VADriverVTableEGLP vtable = (ctx)->vtable_egl; \
+ if (!vtable->va##func##EGL) \
+ return VA_STATUS_ERROR_UNIMPLEMENTED; \
+ \
+ VAStatus status = vtable->va##func##EGL args; \
+ if (status != VA_STATUS_SUCCESS) \
+ return status; \
+ } while (0)
+
+static VAStatus
+vaCreateSurfaceEGL_impl_driver(VADisplay dpy,
+ GLenum target,
+ GLuint texture,
+ unsigned int width,
+ unsigned int height,
+ VASurfaceEGL *egl_surface)
+{
+ VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
+ INVOKE(ctx, CreateSurface, (ctx, target, texture, width, height, egl_surface));
+ return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+vaDestroySurfaceEGL_impl_driver(VADisplay dpy, VASurfaceEGL egl_surface)
+{
+ VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
+ INVOKE(ctx, DestroySurface, (ctx, egl_surface));
+ return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+vaAssociateSurfaceEGL_impl_driver(VADisplay dpy,
+ VASurfaceEGL egl_surface,
+ VASurfaceID surface,
+ unsigned int flags)
+{
+ VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
+ INVOKE(ctx, AssociateSurface, (ctx, egl_surface, surface, flags));
+
+ return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+vaUpdateAssociatedSurfaceEGL_impl_driver(VADisplay dpy,
+ VASurfaceEGL egl_surface)
+{
+ VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
+ INVOKE(ctx, UpdateAssociatedSurface, (ctx, egl_surface));
+
+ return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+vaDeassociateSurfaceEGL_impl_driver(VADisplay dpy,
+ VASurfaceEGL egl_surface)
+{
+ VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
+ INVOKE(ctx, DeassociateSurface, (ctx, egl_surface));
+
+ return VA_STATUS_SUCCESS;
+}
+
+#undef INVOKE
+
+/* ========================================================================= */
+/* === VA/EGL helpers === */
+/* ========================================================================= */
+/** Unique VASurfaceImplEGL identifier */
+#define VA_SURFACE_IMPL_EGL_MAGIC VA_FOURCC('V','I','E','L')
+
+struct VASurfaceImplEGL {
+ uint32_t magic; ///< Magic number identifying a VASurfaceImplEGL
+ VASurfaceID surface; ///< Associated VA surface
+ GLenum target; ///< GL target to which the texture is bound
+ GLuint texture; ///< GL texture
+ unsigned int width;
+ unsigned int height;
+ void *pixmap;
+ EGLImageKHR img_khr;
+ unsigned int flags;
+};
+
+static void *
+create_native_pixmap(VADisplay dpy, unsigned int width, unsigned int height)
+{
+ VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
+ VAStatus status;
+ void *native_pixmap = NULL;
+
+ status = pDisplayContext->vaCreateNativePixmap(pDisplayContext, width, height, &native_pixmap);
+
+ if (status != VA_STATUS_SUCCESS)
+ native_pixmap = NULL;
+
+ return native_pixmap;
+}
+
+static void
+destroy_native_pixmap(VADisplay dpy, void *native_pixmap)
+{
+ VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
+
+ pDisplayContext->vaFreeNativePixmap(pDisplayContext, native_pixmap);
+}
+
+// Destroy VA/EGL surface
+static void
+destroy_surface(VADisplay dpy, VASurfaceImplEGLP pSurfaceImplEGL)
+{
+ VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
+ VADriverContextEGLP egl_ctx = VA_DRIVER_CONTEXT_EGL(ctx);
+ VAOpenGLESVTableP const pOpenGLESVTable = gles_get_vtable(ctx);
+
+ if (pSurfaceImplEGL->img_khr) {
+ pOpenGLESVTable->egl_destroy_image_khr(egl_ctx->egl_display,
+ pSurfaceImplEGL->img_khr);
+ pSurfaceImplEGL->img_khr = EGL_NO_IMAGE_KHR;
+ }
+
+ if (pSurfaceImplEGL->pixmap) {
+ destroy_native_pixmap(dpy, pSurfaceImplEGL->pixmap);
+ pSurfaceImplEGL->pixmap = 0;
+ }
+
+ free(pSurfaceImplEGL);
+}
+
+// Create VA/EGL surface
+static VASurfaceImplEGLP
+create_surface(VADisplay dpy,
+ GLenum target,
+ GLuint texture,
+ unsigned int width,
+ unsigned int height)
+{
+ VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
+ VADriverContextEGLP egl_ctx = VA_DRIVER_CONTEXT_EGL(ctx);
+ VAOpenGLESVTableP const pOpenGLESVTable = gles_get_vtable(ctx);
+ VASurfaceImplEGLP pSurfaceImplEGL = NULL;
+ int is_error = 1;
+ const EGLint img_attribs[] = {
+ EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
+ EGL_NONE
+ };
+
+ pSurfaceImplEGL = calloc(1, sizeof(*pSurfaceImplEGL));
+
+ if (!pSurfaceImplEGL)
+ goto end;
+
+ pSurfaceImplEGL->magic = VA_SURFACE_IMPL_EGL_MAGIC;
+ pSurfaceImplEGL->surface = VA_INVALID_SURFACE;
+ pSurfaceImplEGL->target = target;
+ pSurfaceImplEGL->texture = texture;
+ pSurfaceImplEGL->width = width;
+ pSurfaceImplEGL->height = height;
+ pSurfaceImplEGL->pixmap = create_native_pixmap(dpy, width, height);
+
+ if (!pSurfaceImplEGL->pixmap)
+ goto end;
+
+ pSurfaceImplEGL->img_khr = pOpenGLESVTable->egl_create_image_khr(egl_ctx->egl_display,
+ EGL_NO_CONTEXT,
+ EGL_NATIVE_PIXMAP_KHR,
+ (EGLClientBuffer)pSurfaceImplEGL->pixmap,
+ img_attribs);
+
+ if (!pSurfaceImplEGL->img_khr)
+ goto end;
+
+ is_error = 0;
+
+end:
+ if (is_error && pSurfaceImplEGL) {
+ destroy_surface(dpy, pSurfaceImplEGL);
+ pSurfaceImplEGL = NULL;
+ }
+
+ return pSurfaceImplEGL;
+}
+
+// Check VASurfaceImplEGL is valid
+static inline int check_surface(VASurfaceImplEGLP pSurfaceImplEGL)
+{
+ return pSurfaceImplEGL && pSurfaceImplEGL->magic == VA_SURFACE_IMPL_EGL_MAGIC;
+}
+
+static inline VAStatus
+deassociate_surface(VADriverContextP ctx, VASurfaceImplEGLP pSurfaceImplEGL)
+{
+ pSurfaceImplEGL->surface = VA_INVALID_SURFACE;
+
+ return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+associate_surface(VADriverContextP ctx,
+ VASurfaceImplEGLP pSurfaceImplEGL,
+ VASurfaceID surface,
+ unsigned int flags)
+{
+ VAStatus status;
+
+ status = deassociate_surface(ctx, pSurfaceImplEGL);
+
+ if (status != VA_STATUS_SUCCESS)
+ return status;
+
+ pSurfaceImplEGL->surface = surface;
+ pSurfaceImplEGL->flags = flags;
+
+ return VA_STATUS_SUCCESS;
+}
+
+static inline VAStatus
+sync_surface(VADriverContextP ctx, VASurfaceImplEGLP pSurfaceImplEGL)
+{
+ if (pSurfaceImplEGL->surface == VA_INVALID_SURFACE)
+ return VA_STATUS_ERROR_INVALID_SURFACE;
+
+ return ctx->vtable->vaSyncSurface(ctx, pSurfaceImplEGL->surface);
+}
+
+static VAStatus
+update_accociated_surface(VADriverContextP ctx, VASurfaceImplEGLP pSurfaceImplEGL)
+{
+ VAOpenGLESVTableP pOpenGLESVTable = gles_get_vtable(ctx);
+ VAStatus status;
+
+ status = sync_surface(ctx, pSurfaceImplEGL);
+
+ if (status != VA_STATUS_SUCCESS)
+ return status;
+
+ status = ctx->vtable->vaPutSurface(
+ ctx,
+ pSurfaceImplEGL->surface,
+ (void *)pSurfaceImplEGL->pixmap,
+ 0, 0, pSurfaceImplEGL->width, pSurfaceImplEGL->height,
+ 0, 0, pSurfaceImplEGL->width, pSurfaceImplEGL->height,
+ NULL, 0,
+ pSurfaceImplEGL->flags
+ );
+
+ if (status == VA_STATUS_SUCCESS) {
+ eglWaitNative(EGL_CORE_NATIVE_ENGINE);
+ pOpenGLESVTable->gles_egl_image_target_texture_2d(pSurfaceImplEGL->target,
+ (GLeglImageOES)pSurfaceImplEGL->img_khr);
+ }
+
+ return status;
+}
+
+/* ========================================================================= */
+/* === VA/EGL implementation from libVA (generic and suboptimal path) === */
+/* ========================================================================= */
+#ifdef INIT_SURFACE
+#undef INIT_SURFACE
+#endif
+
+#define INIT_SURFACE(surface, egl_surface) do { \
+ surface = (VASurfaceImplEGLP)(egl_surface); \
+ if (!check_surface(surface)) \
+ return VA_STATUS_ERROR_INVALID_SURFACE; \
+ } while (0)
+
+static VAStatus
+vaCreateSurfaceEGL_impl_libva(VADisplay dpy,
+ GLenum target,
+ GLuint texture,
+ unsigned int width,
+ unsigned int height,
+ VASurfaceEGL *egl_surface)
+{
+ VASurfaceEGL pSurfaceEGL;
+
+ pSurfaceEGL = create_surface(dpy, target, texture, width, height);
+
+ if (!pSurfaceEGL)
+ return VA_STATUS_ERROR_ALLOCATION_FAILED;
+
+ *egl_surface = pSurfaceEGL;
+
+ return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+vaDestroySurfaceEGL_impl_libva(VADisplay dpy, VASurfaceEGL egl_surface)
+{
+ VASurfaceImplEGLP pSurfaceImplEGL;
+
+ INIT_SURFACE(pSurfaceImplEGL, egl_surface);
+
+ destroy_surface(dpy, pSurfaceImplEGL);
+
+ return VA_STATUS_SUCCESS;
+}
+
+static VAStatus
+vaAssociateSurfaceEGL_impl_libva(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface,
+ VASurfaceID surface,
+ unsigned int flags
+)
+{
+ VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
+ VASurfaceImplEGLP pSurfaceImplEGL;
+ VAStatus status;
+
+ INIT_SURFACE(pSurfaceImplEGL, egl_surface);
+
+ status = associate_surface(ctx, egl_surface, surface, flags);
+
+ return status;
+}
+
+static VAStatus
+vaUpdateAssociatedSurfaceEGL_impl_libva(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface
+)
+{
+ VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
+ VASurfaceImplEGLP pSurfaceImplEGL;
+ VAStatus status;
+
+ INIT_SURFACE(pSurfaceImplEGL, egl_surface);
+
+ status = update_accociated_surface(ctx, egl_surface);
+
+ return status;
+}
+
+static VAStatus
+vaDeassociateSurfaceEGL_impl_libva(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface
+)
+{
+ VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
+ VASurfaceImplEGLP pSurfaceImplEGL;
+ VAStatus status;
+
+ INIT_SURFACE(pSurfaceImplEGL, egl_surface);
+
+ status = deassociate_surface(ctx, egl_surface);
+
+ return status;
+}
+
+#undef INIT_SURFACE
+
+/* ========================================================================= */
+/* === Private VA/EGL vtable initialization === */
+/* ========================================================================= */
+
+// Initialize EGL driver context
+VAStatus va_egl_init_context(VADisplay dpy)
+{
+ VADisplayContextP pDisplayContext = (VADisplayContextP)dpy;
+ VADriverContextP ctx = pDisplayContext->pDriverContext;
+ VADriverContextEGLP egl_ctx = VA_DRIVER_CONTEXT_EGL(ctx);
+ VADriverVTablePrivEGLP vtable = &egl_ctx->vtable;
+
+ if (egl_ctx->is_initialized)
+ return VA_STATUS_SUCCESS;
+
+ if (ctx->vtable_egl && ctx->vtable_egl->vaCreateSurfaceEGL) {
+ vtable->vaCreateSurfaceEGL = vaCreateSurfaceEGL_impl_driver;
+ vtable->vaDestroySurfaceEGL = vaDestroySurfaceEGL_impl_driver;
+ vtable->vaAssociateSurfaceEGL = vaAssociateSurfaceEGL_impl_driver;
+ vtable->vaUpdateAssociatedSurfaceEGL = vaUpdateAssociatedSurfaceEGL_impl_driver;
+ vtable->vaDeassociateSurfaceEGL = vaDeassociateSurfaceEGL_impl_driver;
+ }
+ else {
+ if (pDisplayContext->vaCreateNativePixmap == NULL ||
+ pDisplayContext->vaFreeNativePixmap == NULL)
+ return VA_STATUS_ERROR_UNIMPLEMENTED;
+
+ vtable->vaCreateSurfaceEGL = vaCreateSurfaceEGL_impl_libva;
+ vtable->vaDestroySurfaceEGL = vaDestroySurfaceEGL_impl_libva;
+ vtable->vaAssociateSurfaceEGL = vaAssociateSurfaceEGL_impl_libva;
+ vtable->vaUpdateAssociatedSurfaceEGL = vaUpdateAssociatedSurfaceEGL_impl_libva;
+ vtable->vaDeassociateSurfaceEGL = vaDeassociateSurfaceEGL_impl_libva;
+
+ if (!check_extensions(ctx, egl_ctx->egl_display) || !init_extensions(ctx))
+ return VA_STATUS_ERROR_UNIMPLEMENTED;
+ }
+
+ egl_ctx->is_initialized = 1;
+
+ return VA_STATUS_SUCCESS;
+}
diff --git a/va/egl/va_egl_impl.h b/va/egl/va_egl_impl.h
new file mode 100644
index 0000000..96bc9a8
--- /dev/null
+++ b/va/egl/va_egl_impl.h
@@ -0,0 +1,12 @@
+#ifndef _VA_EGL_IMPL_H_
+#define _VA_EGL_IMPL_H_
+
+/**
+ * Initialize EGL driver context
+ *
+ * @param[in] dpy the VA Display
+ * @return VA_STATUS_SUCCESS if successful
+ */
+VAStatus va_egl_init_context(VADisplay dpy);
+
+#endif /* _VA_GLX_IMPL_H_ */
diff --git a/va/egl/va_egl_private.h b/va/egl/va_egl_private.h
new file mode 100644
index 0000000..d0d92fd
--- /dev/null
+++ b/va/egl/va_egl_private.h
@@ -0,0 +1,74 @@
+#ifndef _VA_EGL_PRIVATE_H_
+#define _VA_EGL_PRIVATE_H_
+
+#include "sysdeps.h"
+#include "va.h"
+#include "va_backend.h"
+#include "va_egl.h"
+#include "va_backend_egl.h"
+
+typedef struct VAOpenGLESVTable *VAOpenGLESVTableP;
+
+struct VAOpenGLESVTable {
+ /* EGL_KHR_image_pixmap */
+ PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr;
+ PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr;
+
+ /* GL_OES_EGL_image */
+ PFNGLEGLIMAGETARGETTEXTURE2DOESPROC gles_egl_image_target_texture_2d;
+};
+
+typedef struct VADisplayContextEGL *VADisplayContextEGLP;
+typedef struct VADriverContextEGL *VADriverContextEGLP;
+typedef struct VASurfaceImplEGL *VASurfaceImplEGLP;
+typedef struct VADriverVTableEGL *VADriverVTableEGLP;
+typedef struct VADriverVTablePrivEGL *VADriverVTablePrivEGLP;
+typedef void (*vaDestroyFunc)(VADisplayContextP);
+
+struct VADisplayContextEGL {
+ vaDestroyFunc vaDestroy;
+};
+
+#define VA_DRIVER_CONTEXT_EGL(ctx) ((VADriverContextEGLP)((ctx)->egl))
+
+struct VADriverVTablePrivEGL {
+ VAStatus (*vaCreateSurfaceEGL)(
+ VADisplay dpy,
+ GLenum target,
+ GLuint texture,
+ unsigned int width,
+ unsigned int height,
+ VASurfaceEGL *egl_surface
+ );
+
+ VAStatus (*vaDestroySurfaceEGL)(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface
+ );
+
+ VAStatus (*vaAssociateSurfaceEGL)(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface,
+ VASurfaceID surface,
+ unsigned int flags
+ );
+
+ VAStatus (*vaUpdateAssociatedSurfaceEGL)(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface
+ );
+
+ VAStatus (*vaDeassociateSurfaceEGL)(
+ VADisplay dpy,
+ VASurfaceEGL egl_surface
+ );
+};
+
+struct VADriverContextEGL {
+ struct VADriverVTablePrivEGL vtable;
+ struct VAOpenGLESVTable gles_vtable;
+ unsigned int is_initialized : 1;
+ EGLDisplay egl_display;
+};
+
+#endif /* _VA_EGL_PRIVATE_H_ */
diff --git a/va/va_backend.h b/va/va_backend.h
index 22f1765..cddf759 100644
--- a/va/va_backend.h
+++ b/va/va_backend.h
@@ -433,8 +433,8 @@ struct VADriverContext
void *dri_state;
void *glx; /* opaque for GLX code */
-
- unsigned long reserved[45]; /* reserve for future add-ins, decrease the subscript accordingly */
+ void *egl;
+ unsigned long reserved[44]; /* reserve for future add-ins, decrease the subscript accordingly */
};
#define VA_DISPLAY_MAGIC 0x56414430 /* VAD0 */