| Index: third_party/libva/va/egl/va_egl.c
|
| diff --git a/third_party/libva/va/egl/va_egl.c b/third_party/libva/va/egl/va_egl.c
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..48ff7a1f1792353a6c853b9d903862d0436674c2
|
| --- /dev/null
|
| +++ b/third_party/libva/va/egl/va_egl.c
|
| @@ -0,0 +1,314 @@
|
| +/*
|
| + * Copyright (c) 2007 Intel Corporation. All Rights Reserved.
|
| + *
|
| + * Permission is hereby granted, free of charge, to any person obtaining a
|
| + * copy of this software and associated documentation files (the
|
| + * "Software"), to deal in the Software without restriction, including
|
| + * without limitation the rights to use, copy, modify, merge, publish,
|
| + * distribute, sub license, and/or sell copies of the Software, and to
|
| + * permit persons to whom the Software is furnished to do so, subject to
|
| + * the following conditions:
|
| + *
|
| + * The above copyright notice and this permission notice (including the
|
| + * next paragraph) shall be included in all copies or substantial portions
|
| + * of the Software.
|
| + *
|
| + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
| + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
| + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
| + * IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
|
| + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
| + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
| + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
| + */
|
| +
|
| +/*
|
| + * Initial EGL backend, and subject to change
|
| + *
|
| + * Gstreamer gst-gltexture has a framework to support associating a buffer
|
| + * to a texture via EGL_KHR_image_base and GL_OES_EGL_image_external.
|
| + *
|
| + * EGL_KHR_image_base:
|
| + * EGLImageKHR eglCreateImageKHR(
|
| + * EGLDisplay dpy,
|
| + * EGLContext ctx,
|
| + * EGLenum target,
|
| + * EGLClientBuffer buffer,
|
| + * const EGLint *attrib_list)
|
| + *
|
| + * GL_OES_EGL_image_external:
|
| + * This extension provides a mechanism for creating EGLImage texture targets
|
| + * from EGLImages. This extension defines a new texture target TEXTURE_EXTERNAL_OES.
|
| + * This texture target can only be specified using an EGLImage.
|
| + * The first eglCreateImageKHR will create an EGLImage from an EGLClientBufferm, and with
|
| + * an EGLImage, gst-gltexture can use GL_OES_EGL_image_external extension to create textures.
|
| + *
|
| + * eglCreateImageKHR and GL_OES_EGL_image_external are all called directly from gst-gltexture,
|
| + * thus the simplest way to support gst-gltexture is defining a new API to pass EGLClientBuffer
|
| + * to gst-gltexture.
|
| + *
|
| + * EGLClientBuffer is gfx/video driver implementation specific (?). It means we need to pass up
|
| + * the low-level buffer ID (or handle) of the decoded surface to gst-gltexture, and gst-gltexture
|
| + * then pass down it to gfx driver.
|
| + *
|
| + * Bellow API vaGetEGLClientBufferFromSurface is for this purpose
|
| + */
|
| +#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,
|
| + EGLClientBuffer *buffer /* out*/
|
| +)
|
| +{
|
| + VADriverContextP ctx;
|
| + struct VADriverVTableEGL *va_egl;
|
| + CHECK_DISPLAY(dpy);
|
| + ctx = CTX(dpy);
|
| +
|
| + va_egl = (struct VADriverVTableEGL *)ctx->vtable_egl;
|
| + if (va_egl && va_egl->vaGetEGLClientBufferFromSurface) {
|
| + return va_egl->vaGetEGLClientBufferFromSurface(ctx, surface, buffer);
|
| + } else
|
| + 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;
|
| +}
|
| +
|
| +int vaMaxNumSurfaceTargetsEGL(
|
| + VADisplay dpy
|
| +)
|
| +{
|
| + VADriverContextP ctx;
|
| + struct VADriverVTableEGL *va_egl;
|
| + CHECK_DISPLAY(dpy);
|
| + ctx = CTX(dpy);
|
| +
|
| + va_egl = (struct VADriverVTableEGL *)ctx->vtable_egl;
|
| +
|
| + if (va_egl)
|
| + return va_egl->max_egl_surface_targets;
|
| + else
|
| + return IMPL_MAX_EGL_SURFACE_TARGETS;
|
| +}
|
| +
|
| +int vaMaxNumSurfaceAttributesEGL(
|
| + VADisplay dpy
|
| +)
|
| +{
|
| + VADriverContextP ctx;
|
| + struct VADriverVTableEGL *va_egl;
|
| + CHECK_DISPLAY(dpy);
|
| + ctx = CTX(dpy);
|
| +
|
| + va_egl = (struct VADriverVTableEGL *)ctx->vtable_egl;
|
| +
|
| + if (va_egl)
|
| + return va_egl->max_egl_surface_attributes;
|
| + else
|
| + return IMPL_MAX_EGL_SURFACE_ATTRIBUTES;
|
| +}
|
| +
|
| +VAStatus vaQuerySurfaceTargetsEGL(
|
| + VADisplay dpy,
|
| + EGLenum *target_list, /* out */
|
| + int *num_targets /* out */
|
| +)
|
| +{
|
| + VADriverContextP ctx;
|
| + VAStatus status;
|
| +
|
| + INIT_CONTEXT(ctx, dpy);
|
| +
|
| + INVOKE(ctx, QuerySurfaceTargets, (dpy, target_list, num_targets));
|
| + return status;
|
| +}
|
| +
|
| +VAStatus vaCreateSurfaceEGL(
|
| + VADisplay dpy,
|
| + EGLenum target,
|
| + unsigned int width,
|
| + unsigned int height,
|
| + VASurfaceEGL *gl_surface
|
| +)
|
| +{
|
| + VADriverContextP ctx;
|
| + VAStatus status;
|
| +
|
| + INIT_CONTEXT(ctx, dpy);
|
| +
|
| + INVOKE(ctx, CreateSurface, (dpy, target, 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 vaSyncSurfaceEGL(
|
| + VADisplay dpy,
|
| + VASurfaceEGL egl_surface
|
| +)
|
| +{
|
| + VADriverContextP ctx;
|
| + VAStatus status;
|
| +
|
| + INIT_CONTEXT(ctx, dpy);
|
| +
|
| + INVOKE(ctx, SyncSurface, (dpy, egl_surface));
|
| + return status;
|
| +}
|
| +
|
| +VAStatus vaGetSurfaceInfoEGL(
|
| + VADisplay dpy,
|
| + VASurfaceEGL egl_surface,
|
| + EGLenum *target, /* out, the type of <buffer> */
|
| + EGLClientBuffer *buffer, /* out */
|
| + EGLint *attrib_list, /* out, the last attribute must be EGL_NONE */
|
| + int *num_attribs /* in/out */
|
| +)
|
| +{
|
| + VADriverContextP ctx;
|
| + VAStatus status;
|
| +
|
| + INIT_CONTEXT(ctx, dpy);
|
| +
|
| + INVOKE(ctx, GetSurfaceInfo, (dpy, egl_surface, target, buffer, attrib_list, num_attribs));
|
| + 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;
|
| +}
|
| +
|
|
|