| Index: third_party/libva/va/egl/va_egl_impl.c
|
| diff --git a/third_party/libva/va/egl/va_egl_impl.c b/third_party/libva/va/egl/va_egl_impl.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..367f43fff5875fbd1b2f247c67dc98441637810a
|
| --- /dev/null
|
| +++ b/third_party/libva/va/egl/va_egl_impl.c
|
| @@ -0,0 +1,499 @@
|
| +#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"
|
| +
|
| +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_pixmap_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;
|
| +
|
| + 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
|
| +vaQuerySurfaceTargetsEGL_impl_driver(VADisplay dpy,
|
| + EGLenum *target_list,
|
| + int *num_targets)
|
| +{
|
| + VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
|
| +
|
| + INVOKE(ctx, QuerySurfaceTargets, (ctx, target_list, num_targets));
|
| +
|
| + return VA_STATUS_SUCCESS;
|
| +}
|
| +
|
| +static VAStatus
|
| +vaCreateSurfaceEGL_impl_driver(VADisplay dpy,
|
| + EGLenum target,
|
| + unsigned int width,
|
| + unsigned int height,
|
| + VASurfaceEGL *gl_surface)
|
| +{
|
| + VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
|
| +
|
| + INVOKE(ctx, CreateSurface, (ctx, target, width, height, gl_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
|
| +vaSyncSurfaceEGL_impl_driver(VADisplay dpy,
|
| + VASurfaceEGL egl_surface)
|
| +{
|
| + VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
|
| +
|
| + INVOKE(ctx, SyncSurface, (ctx, egl_surface));
|
| +
|
| + return VA_STATUS_SUCCESS;
|
| +}
|
| +
|
| +static VAStatus
|
| +vaGetSurfaceInfoEGL_impl_driver(VADisplay dpy,
|
| + VASurfaceEGL egl_surface,
|
| + EGLenum *target,
|
| + EGLClientBuffer *buffer,
|
| + EGLint *attrib_list,
|
| + int *num_attribs)
|
| +{
|
| + VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
|
| +
|
| + INVOKE(ctx, GetSurfaceInfo, (ctx, egl_surface, target, buffer, attrib_list, num_attribs));
|
| +
|
| + 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','E','G','L')
|
| +
|
| +struct VASurfaceImplEGL {
|
| + uint32_t magic; ///< Magic number identifying a VASurfaceImplEGL
|
| + VASurfaceID surface; ///< Associated VA surface
|
| + EGLenum target; ///< EGL target
|
| + EGLClientBuffer buffer;
|
| + unsigned int width;
|
| + unsigned int height;
|
| + 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);
|
| +}
|
| +
|
| +// 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
|
| +sync_associated_surface(VADriverContextP ctx, VASurfaceImplEGLP pSurfaceImplEGL)
|
| +{
|
| + VAStatus status;
|
| +
|
| + status = sync_surface(ctx, pSurfaceImplEGL);
|
| +
|
| + if (status != VA_STATUS_SUCCESS)
|
| + return status;
|
| +
|
| + if (pSurfaceImplEGL->target != EGL_NATIVE_PIXMAP_KHR)
|
| + return VA_STATUS_ERROR_UNIMPLEMENTED;
|
| +
|
| + status = ctx->vtable->vaPutSurface(
|
| + ctx,
|
| + pSurfaceImplEGL->surface,
|
| + (void *)pSurfaceImplEGL->buffer,
|
| + 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);
|
| + }
|
| +
|
| + 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
|
| +vaQuerySurfaceTargetsEGL_impl_libva(VADisplay dpy,
|
| + EGLenum *target_list,
|
| + int *num_targets)
|
| +{
|
| + int i = 0;
|
| +
|
| + /* FIXME: support other targets ??? */
|
| + target_list[i++] = EGL_NATIVE_PIXMAP_KHR;
|
| + *num_targets = i;
|
| + assert(i <= IMPL_MAX_EGL_SURFACE_TARGETS);
|
| +
|
| + return VA_STATUS_SUCCESS;
|
| +}
|
| +
|
| +static VAStatus
|
| +vaCreateSurfaceEGL_impl_libva(VADisplay dpy,
|
| + EGLenum target,
|
| + unsigned int width,
|
| + unsigned int height,
|
| + VASurfaceEGL *egl_surface)
|
| +{
|
| + VASurfaceImplEGLP pSurfaceImplEGL = NULL;
|
| +
|
| + /* So far only support for EGL_NATIVE_PIXMAP_KHR */
|
| + if (target != 0 && target != EGL_NATIVE_PIXMAP_KHR)
|
| + return VA_STATUS_ERROR_INVALID_PARAMETER;
|
| +
|
| + pSurfaceImplEGL = calloc(1, sizeof(*pSurfaceImplEGL));
|
| +
|
| + if (!pSurfaceImplEGL) {
|
| + *egl_surface = 0;
|
| + return VA_STATUS_ERROR_ALLOCATION_FAILED;
|
| + }
|
| +
|
| + pSurfaceImplEGL->magic = VA_SURFACE_IMPL_EGL_MAGIC;
|
| + pSurfaceImplEGL->surface = VA_INVALID_SURFACE;
|
| + pSurfaceImplEGL->target = target == 0 ? EGL_NATIVE_PIXMAP_KHR : target;
|
| + pSurfaceImplEGL->buffer = 0;
|
| + pSurfaceImplEGL->width = width;
|
| + pSurfaceImplEGL->height = height;
|
| + *egl_surface = (VASurfaceEGL)pSurfaceImplEGL;
|
| +
|
| + return VA_STATUS_SUCCESS;
|
| +}
|
| +
|
| +static VAStatus
|
| +vaDestroySurfaceEGL_impl_libva(VADisplay dpy, VASurfaceEGL egl_surface)
|
| +{
|
| + VASurfaceImplEGLP pSurfaceImplEGL;
|
| +
|
| + INIT_SURFACE(pSurfaceImplEGL, egl_surface);
|
| +
|
| + if (pSurfaceImplEGL->target == EGL_NATIVE_PIXMAP_KHR) {
|
| + if (pSurfaceImplEGL->buffer) {
|
| + destroy_native_pixmap(dpy, pSurfaceImplEGL->buffer);
|
| + pSurfaceImplEGL->buffer = 0;
|
| + }
|
| + }
|
| +
|
| + free(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);
|
| +
|
| + if (surface == VA_INVALID_SURFACE)
|
| + return VA_STATUS_ERROR_INVALID_SURFACE;
|
| +
|
| + if (pSurfaceImplEGL->target == EGL_NATIVE_PIXMAP_KHR) {
|
| + if (pSurfaceImplEGL->buffer)
|
| + destroy_native_pixmap(dpy, pSurfaceImplEGL->buffer);
|
| +
|
| + pSurfaceImplEGL->buffer = create_native_pixmap(dpy, pSurfaceImplEGL->width, pSurfaceImplEGL->height);
|
| + }
|
| +
|
| + pSurfaceImplEGL->surface = surface;
|
| + pSurfaceImplEGL->flags = flags;
|
| +
|
| + if (pSurfaceImplEGL->buffer)
|
| + return VA_STATUS_SUCCESS;
|
| +
|
| + return VA_STATUS_ERROR_UNKNOWN;
|
| +}
|
| +
|
| +static VAStatus
|
| +vaSyncSurfaceEGL_impl_libva(VADisplay dpy,
|
| + VASurfaceEGL egl_surface)
|
| +{
|
| + VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
|
| + VASurfaceImplEGLP pSurfaceImplEGL;
|
| + VAStatus status;
|
| +
|
| + INIT_SURFACE(pSurfaceImplEGL, egl_surface);
|
| +
|
| + status = sync_associated_surface(ctx, pSurfaceImplEGL);
|
| +
|
| + return status;
|
| +}
|
| +
|
| +static VAStatus
|
| +vaGetSurfaceInfoEGL_impl_libva(VADisplay dpy,
|
| + VASurfaceEGL egl_surface,
|
| + EGLenum *target,
|
| + EGLClientBuffer *buffer,
|
| + EGLint *attrib_list,
|
| + int *num_attribs)
|
| +{
|
| + VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
|
| + VASurfaceImplEGLP pSurfaceImplEGL;
|
| + VAStatus status;
|
| + int i = 0;
|
| +
|
| + INIT_SURFACE(pSurfaceImplEGL, egl_surface);
|
| +
|
| + if (pSurfaceImplEGL->surface == VA_INVALID_SURFACE)
|
| + return VA_STATUS_ERROR_INVALID_SURFACE;
|
| +
|
| + if (*num_attribs < IMPL_MAX_EGL_SURFACE_ATTRIBUTES)
|
| + return VA_STATUS_ERROR_INVALID_PARAMETER;
|
| +
|
| + *target = pSurfaceImplEGL->target;
|
| + *buffer = pSurfaceImplEGL->buffer;
|
| +
|
| + if (pSurfaceImplEGL->target == EGL_NATIVE_PIXMAP_KHR) {
|
| + attrib_list[i++] = EGL_IMAGE_PRESERVED_KHR;
|
| + attrib_list[i + 1] = EGL_TRUE;
|
| + attrib_list[i++] = EGL_NONE;
|
| + } else {
|
| + /* FIXME later */
|
| + attrib_list[i++] = EGL_NONE;
|
| + }
|
| +
|
| + *num_attribs = i;
|
| +
|
| + return VA_STATUS_SUCCESS;
|
| +}
|
| +
|
| +static VAStatus
|
| +vaDeassociateSurfaceEGL_impl_libva(
|
| + VADisplay dpy,
|
| + VASurfaceEGL egl_surface
|
| + )
|
| +{
|
| + VADriverContextP ctx = ((VADisplayContextP)(dpy))->pDriverContext;
|
| + VASurfaceImplEGLP pSurfaceImplEGL;
|
| + VAStatus status;
|
| +
|
| + INIT_SURFACE(pSurfaceImplEGL, egl_surface);
|
| +
|
| + if (pSurfaceImplEGL->target == EGL_NATIVE_PIXMAP_KHR) {
|
| + if (pSurfaceImplEGL->buffer)
|
| + destroy_native_pixmap(dpy, pSurfaceImplEGL->buffer);
|
| +
|
| + pSurfaceImplEGL->buffer = 0;
|
| + }
|
| +
|
| + pSurfaceImplEGL->surface = VA_INVALID_SURFACE;
|
| +
|
| + return VA_STATUS_SUCCESS;
|
| +}
|
| +
|
| +#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->vaQuerySurfaceTargetsEGL = vaQuerySurfaceTargetsEGL_impl_driver;
|
| + vtable->vaCreateSurfaceEGL = vaCreateSurfaceEGL_impl_driver;
|
| + vtable->vaDestroySurfaceEGL = vaDestroySurfaceEGL_impl_driver;
|
| + vtable->vaAssociateSurfaceEGL = vaAssociateSurfaceEGL_impl_driver;
|
| + vtable->vaSyncSurfaceEGL = vaSyncSurfaceEGL_impl_driver;
|
| + vtable->vaGetSurfaceInfoEGL = vaGetSurfaceInfoEGL_impl_driver;
|
| + vtable->vaDeassociateSurfaceEGL = vaDeassociateSurfaceEGL_impl_driver;
|
| + }
|
| + else {
|
| + if (pDisplayContext->vaCreateNativePixmap == NULL ||
|
| + pDisplayContext->vaFreeNativePixmap == NULL)
|
| + return VA_STATUS_ERROR_UNIMPLEMENTED;
|
| +
|
| + if (!check_pixmap_extensions(ctx, egl_ctx->egl_display))
|
| + return VA_STATUS_ERROR_UNIMPLEMENTED;
|
| +
|
| + vtable->vaQuerySurfaceTargetsEGL = vaQuerySurfaceTargetsEGL_impl_libva;
|
| + vtable->vaCreateSurfaceEGL = vaCreateSurfaceEGL_impl_libva;
|
| + vtable->vaDestroySurfaceEGL = vaDestroySurfaceEGL_impl_libva;
|
| + vtable->vaAssociateSurfaceEGL = vaAssociateSurfaceEGL_impl_libva;
|
| + vtable->vaSyncSurfaceEGL = vaSyncSurfaceEGL_impl_libva;
|
| + vtable->vaGetSurfaceInfoEGL = vaGetSurfaceInfoEGL_impl_libva;
|
| + vtable->vaDeassociateSurfaceEGL = vaDeassociateSurfaceEGL_impl_libva;
|
| + }
|
| +
|
| + egl_ctx->is_initialized = 1;
|
| +
|
| + return VA_STATUS_SUCCESS;
|
| +}
|
|
|