summaryrefslogtreecommitdiff
path: root/gst-libs
diff options
context:
space:
mode:
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>2015-02-20 15:27:53 +0100
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>2015-02-24 15:20:03 +0100
commit1e7c4db5a740df7b68547c091148dc27f80388d7 (patch)
tree1e7519e291f43e607349308d209039a3e8686dbe /gst-libs
parent91c5d948be120c256245724fbd7e54fd38e2e49e (diff)
downloadgst-vaapi-1e7c4db5a740df7b68547c091148dc27f80388d7.tar.gz
Add initial support for EGL.
Add initial support for EGL to libgstvaapi core library. The target display server and the desired OpenGL API can be programmatically selected at run-time. A comprehensive set of EGL utilities are provided to support those dynamic selection needs, but also most importantly to ensure that the GL command stream is executed from within a single thread. https://bugzilla.gnome.org/show_bug.cgi?id=743846
Diffstat (limited to 'gst-libs')
-rw-r--r--gst-libs/gst/vaapi/Makefile.am61
-rw-r--r--gst-libs/gst/vaapi/egl_compat.h39
-rw-r--r--gst-libs/gst/vaapi/egl_vtable.h785
-rw-r--r--gst-libs/gst/vaapi/gstvaapidisplay.c7
-rw-r--r--gst-libs/gst/vaapi/gstvaapidisplay.h2
-rw-r--r--gst-libs/gst/vaapi/gstvaapidisplay_egl.c582
-rw-r--r--gst-libs/gst/vaapi/gstvaapidisplay_egl.h55
-rw-r--r--gst-libs/gst/vaapi/gstvaapidisplay_egl_priv.h101
-rw-r--r--gst-libs/gst/vaapi/gstvaapiutils_egl.c1342
-rw-r--r--gst-libs/gst/vaapi/gstvaapiutils_egl.h238
-rw-r--r--gst-libs/gst/vaapi/ogl_compat.h104
11 files changed, 3315 insertions, 1 deletions
diff --git a/gst-libs/gst/vaapi/Makefile.am b/gst-libs/gst/vaapi/Makefile.am
index 57b83135..a329e8fe 100644
--- a/gst-libs/gst/vaapi/Makefile.am
+++ b/gst-libs/gst/vaapi/Makefile.am
@@ -12,6 +12,10 @@ if USE_GLX
lib_LTLIBRARIES += libgstvaapi-glx-@GST_API_VERSION@.la
endif
+if USE_EGL
+lib_LTLIBRARIES += libgstvaapi-egl-@GST_API_VERSION@.la
+endif
+
if USE_WAYLAND
lib_LTLIBRARIES += libgstvaapi-wayland-@GST_API_VERSION@.la
endif
@@ -271,6 +275,23 @@ libgstvaapi_glx_source_priv_h = \
gstvaapiutils_x11.h \
$(NULL)
+libgstvaapi_egl_source_c = \
+ gstvaapidisplay_egl.c \
+ gstvaapiutils_egl.c \
+ $(NULL)
+
+libgstvaapi_egl_source_h = \
+ gstvaapidisplay_egl.h \
+ $(NULL)
+
+libgstvaapi_egl_source_priv_h = \
+ egl_compat.h \
+ egl_vtable.h \
+ gstvaapidisplay_egl_priv.h \
+ gstvaapiutils_egl.h \
+ ogl_compat.h \
+ $(NULL)
+
libgstvaapi_wayland_source_c = \
gstvaapidisplay_wayland.c \
gstvaapiutils.c \
@@ -433,6 +454,43 @@ libgstvaapi_glx_@GST_API_VERSION@_la_LDFLAGS = \
$(GST_VAAPI_LT_LDFLAGS) \
$(NULL)
+libgstvaapi_egl_@GST_API_VERSION@_la_SOURCES = \
+ $(libgstvaapi_egl_source_c) \
+ $(libgstvaapi_egl_source_priv_h) \
+ $(NULL)
+
+libgstvaapi_egl_@GST_API_VERSION@include_HEADERS = \
+ $(libgstvaapi_egl_source_h) \
+ $(NULL)
+
+libgstvaapi_egl_@GST_API_VERSION@includedir = \
+ $(libgstvaapi_includedir)
+
+libgstvaapi_egl_@GST_API_VERSION@_la_CFLAGS = \
+ -DIN_LIBGSTVAAPI \
+ -DGST_USE_UNSTABLE_API \
+ -I$(top_srcdir)/gst-libs \
+ $(GLIB_CFLAGS) \
+ $(GST_BASE_CFLAGS) \
+ $(GST_VIDEO_CFLAGS) \
+ $(EGL_CFLAGS) \
+ $(NULL)
+
+libgstvaapi_egl_@GST_API_VERSION@_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(GST_LIBS) \
+ $(GST_BASE_LIBS) \
+ $(GST_VIDEO_LIBS) \
+ libgstvaapi-$(GST_API_VERSION).la \
+ $(EGL_LIBS) \
+ $(DLOPEN_LIBS) \
+ $(NULL)
+
+libgstvaapi_egl_@GST_API_VERSION@_la_LDFLAGS = \
+ $(GST_ALL_LDFLAGS) \
+ $(GST_VAAPI_LT_LDFLAGS) \
+ $(NULL)
+
libgstvaapi_wayland_@GST_API_VERSION@_la_SOURCES = \
$(libgstvaapi_wayland_source_c) \
$(libgstvaapi_wayland_source_priv_h) \
@@ -513,6 +571,9 @@ EXTRA_DIST += \
$(libgstvaapi_jpegenc_source_c) \
$(libgstvaapi_vp8enc_source_h) \
$(libgstvaapi_vp8enc_source_c) \
+ $(libgstvaapi_egl_source_c) \
+ $(libgstvaapi_egl_source_h) \
+ $(libgstvaapi_egl_source_priv_h) \
$(NULL)
CLEANFILES = \
diff --git a/gst-libs/gst/vaapi/egl_compat.h b/gst-libs/gst/vaapi/egl_compat.h
new file mode 100644
index 00000000..c4172116
--- /dev/null
+++ b/gst-libs/gst/vaapi/egl_compat.h
@@ -0,0 +1,39 @@
+/*
+ * egl_compat.h - EGL compatiliby layer
+ *
+ * Copyright (C) 2014 Intel Corporation
+ * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301
+ */
+
+#ifndef EGL_COMPAT_H
+#define EGL_COMPAT_H
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include "ogl_compat.h"
+
+#ifndef GL_OES_EGL_image
+#define GL_OES_EGL_image 1
+typedef void *GLeglImageOES;
+typedef void (*PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)(GLenum target,
+ GLeglImageOES image);
+typedef void (*PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)(GLenum target,
+ GLeglImageOES image);
+#endif /* GL_OES_EGL_image */
+
+#endif /* EGL_COMPAT_H */
diff --git a/gst-libs/gst/vaapi/egl_vtable.h b/gst-libs/gst/vaapi/egl_vtable.h
new file mode 100644
index 00000000..89c5d029
--- /dev/null
+++ b/gst-libs/gst/vaapi/egl_vtable.h
@@ -0,0 +1,785 @@
+/*
+ * egl_vtable.h - EGL function definitions
+ *
+ * Copyright (C) 2014 Intel Corporation
+ * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301
+ */
+
+/* ------------------------------------------------------------------------- */
+// Generate strings
+
+#define GL_PROTO_GEN_STRING(x) \
+ GL_PROTO_GEN_STRING_I(x)
+#define GL_PROTO_GEN_STRING_I(x) \
+ #x
+
+/* ------------------------------------------------------------------------- */
+// Concatenate arguments
+
+#define GL_PROTO_GEN_CONCAT(a1, a2) \
+ GL_PROTO_GEN_CONCAT2_I(a1, a2)
+#define GL_PROTO_GEN_CONCAT2(a1, a2) \
+ GL_PROTO_GEN_CONCAT2_I(a1, a2)
+#define GL_PROTO_GEN_CONCAT2_I(a1, a2) \
+ a1 ## a2
+
+#define GL_PROTO_GEN_CONCAT3(a1, a2, a3) \
+ GL_PROTO_GEN_CONCAT3_I(a1, a2, a3)
+#define GL_PROTO_GEN_CONCAT3_I(a1, a2, a3) \
+ a1 ## a2 ## a3
+
+#define GL_PROTO_GEN_CONCAT4(a1, a2, a3, a4) \
+ GL_PROTO_GEN_CONCAT4_I(a1, a2, a3, a4)
+#define GL_PROTO_GEN_CONCAT4_I(a1, a2, a3, a4) \
+ a1 ## a2 ## a3 ## a4
+
+#define GL_PROTO_GEN_CONCAT5(a1, a2, a3, a4, a5) \
+ GL_PROTO_GEN_CONCAT5_I(a1, a2, a3, a4, a5)
+#define GL_PROTO_GEN_CONCAT5_I(a1, a2, a3, a4, a5) \
+ a1 ## a2 ## a3 ## a4 ## a5
+
+/* ------------------------------------------------------------------------- */
+// Default macros
+
+#ifndef EGL_PROTO_BEGIN
+#define EGL_PROTO_BEGIN(NAME, TYPE, EXTENSION)
+#endif
+#ifndef EGL_PROTO_ARG_LIST
+#define EGL_PROTO_ARG_LIST(...) GL_PROTO_ARG_LIST(__VA_ARGS__)
+#endif
+#ifndef EGL_PROTO_ARG
+#define EGL_PROTO_ARG(NAME, TYPE) GL_PROTO_ARG(NAME, TYPE)
+#endif
+#ifndef EGL_PROTO_INVOKE
+#define EGL_PROTO_INVOKE(NAME, TYPE, ARGS)
+#endif
+#ifndef EGL_PROTO_END
+#define EGL_PROTO_END()
+#endif
+#ifndef EGL_DEFINE_EXTENSION
+#define EGL_DEFINE_EXTENSION(EXTENSION)
+#endif
+
+#ifndef GL_PROTO_BEGIN
+#define GL_PROTO_BEGIN(NAME, TYPE, EXTENSION)
+#endif
+#ifndef GL_PROTO_ARG_LIST
+#define GL_PROTO_ARG_LIST(...)
+#endif
+#ifndef GL_PROTO_ARG
+#define GL_PROTO_ARG(NAME, TYPE)
+#endif
+#ifndef GL_PROTO_INVOKE
+#define GL_PROTO_INVOKE(NAME, TYPE, ARGS)
+#endif
+#ifndef GL_PROTO_END
+#define GL_PROTO_END()
+#endif
+#ifndef GL_DEFINE_EXTENSION
+#define GL_DEFINE_EXTENSION(EXTENSION)
+#endif
+
+/* NOTE: this is auto-generated code -- do not edit! */
+
+EGL_PROTO_BEGIN(CreateImageKHR, EGLImageKHR, KHR_image_base)
+EGL_PROTO_ARG_LIST(
+EGL_PROTO_ARG(dpy, EGLDisplay),
+EGL_PROTO_ARG(ctx, EGLContext),
+EGL_PROTO_ARG(target, EGLenum),
+EGL_PROTO_ARG(buffer, EGLClientBuffer),
+EGL_PROTO_ARG(attrib_list, const EGLint *))
+EGL_PROTO_INVOKE(CreateImageKHR, EGLImageKHR, (dpy, ctx, target, buffer, attrib_list))
+EGL_PROTO_END()
+
+EGL_PROTO_BEGIN(DestroyImageKHR, EGLImageKHR, KHR_image_base)
+EGL_PROTO_ARG_LIST(
+EGL_PROTO_ARG(dpy, EGLDisplay),
+EGL_PROTO_ARG(image, EGLImageKHR))
+EGL_PROTO_INVOKE(DestroyImageKHR, EGLImageKHR, (dpy, image))
+EGL_PROTO_END()
+
+EGL_PROTO_BEGIN(CreateDRMImageMESA, EGLImageKHR, MESA_drm_image)
+EGL_PROTO_ARG_LIST(
+EGL_PROTO_ARG(dpy, EGLDisplay),
+EGL_PROTO_ARG(attrib_list, const EGLint *))
+EGL_PROTO_INVOKE(CreateDRMImageMESA, EGLImageKHR, (dpy, attrib_list))
+EGL_PROTO_END()
+
+EGL_PROTO_BEGIN(ExportDRMImageMESA, EGLImageKHR, MESA_drm_image)
+EGL_PROTO_ARG_LIST(
+EGL_PROTO_ARG(dpy, EGLDisplay),
+EGL_PROTO_ARG(image, EGLImageKHR),
+EGL_PROTO_ARG(name, EGLint *),
+EGL_PROTO_ARG(handle, EGLint *),
+EGL_PROTO_ARG(stride, EGLint *))
+EGL_PROTO_INVOKE(ExportDRMImageMESA, EGLImageKHR, (dpy, image, name, handle, stride))
+EGL_PROTO_END()
+
+EGL_DEFINE_EXTENSION(EXT_image_dma_buf_import)
+EGL_DEFINE_EXTENSION(KHR_create_context)
+EGL_DEFINE_EXTENSION(KHR_gl_texture_2D_image)
+EGL_DEFINE_EXTENSION(KHR_image_base)
+EGL_DEFINE_EXTENSION(KHR_surfaceless_context)
+EGL_DEFINE_EXTENSION(MESA_configless_context)
+EGL_DEFINE_EXTENSION(MESA_drm_image)
+
+GL_PROTO_BEGIN(GetError, GLenum, CORE_1_0)
+GL_PROTO_ARG_LIST()
+GL_PROTO_INVOKE(GetError, GLenum, ())
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(GetString, const GLubyte *, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(name, GLenum))
+GL_PROTO_INVOKE(GetString, const GLubyte *, (name))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(GetIntegerv, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(pname, GLenum),
+GL_PROTO_ARG(params, GLint *))
+GL_PROTO_INVOKE(GetIntegerv, void, (pname, params))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Enable, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(cap, GLenum))
+GL_PROTO_INVOKE(Enable, void, (cap))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Disable, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(cap, GLenum))
+GL_PROTO_INVOKE(Disable, void, (cap))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(IsEnabled, GLboolean, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(cap, GLenum))
+GL_PROTO_INVOKE(IsEnabled, GLboolean, (cap))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Finish, void, CORE_1_0)
+GL_PROTO_ARG_LIST()
+GL_PROTO_INVOKE(Finish, void, ())
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Flush, void, CORE_1_0)
+GL_PROTO_ARG_LIST()
+GL_PROTO_INVOKE(Flush, void, ())
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Begin, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(mode, GLenum))
+GL_PROTO_INVOKE(Begin, void, (mode))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(End, void, CORE_1_0)
+GL_PROTO_ARG_LIST()
+GL_PROTO_INVOKE(End, void, ())
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Color4f, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(red, GLfloat),
+GL_PROTO_ARG(green, GLfloat),
+GL_PROTO_ARG(blue, GLfloat),
+GL_PROTO_ARG(alpha, GLfloat))
+GL_PROTO_INVOKE(Color4f, void, (red, green, blue, alpha))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Clear, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(mask, GLbitfield))
+GL_PROTO_INVOKE(Clear, void, (mask))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(ClearColor, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(red, GLclampf),
+GL_PROTO_ARG(green, GLclampf),
+GL_PROTO_ARG(blue, GLclampf),
+GL_PROTO_ARG(alpha, GLclampf))
+GL_PROTO_INVOKE(ClearColor, void, (red, green, blue, alpha))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(PushMatrix, void, CORE_1_0)
+GL_PROTO_ARG_LIST()
+GL_PROTO_INVOKE(PushMatrix, void, ())
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(PopMatrix, void, CORE_1_0)
+GL_PROTO_ARG_LIST()
+GL_PROTO_INVOKE(PopMatrix, void, ())
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(LoadIdentity, void, CORE_1_0)
+GL_PROTO_ARG_LIST()
+GL_PROTO_INVOKE(LoadIdentity, void, ())
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(MatrixMode, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(mode, GLenum))
+GL_PROTO_INVOKE(MatrixMode, void, (mode))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(PushAttrib, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(mask, GLbitfield))
+GL_PROTO_INVOKE(PushAttrib, void, (mask))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(PopAttrib, void, CORE_1_0)
+GL_PROTO_ARG_LIST()
+GL_PROTO_INVOKE(PopAttrib, void, ())
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Viewport, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(x, GLint),
+GL_PROTO_ARG(y, GLint),
+GL_PROTO_ARG(width, GLsizei),
+GL_PROTO_ARG(height, GLsizei))
+GL_PROTO_INVOKE(Viewport, void, (x, y, width, height))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Frustum, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(left, GLdouble),
+GL_PROTO_ARG(right, GLdouble),
+GL_PROTO_ARG(bottom, GLdouble),
+GL_PROTO_ARG(top, GLdouble),
+GL_PROTO_ARG(zNear, GLdouble),
+GL_PROTO_ARG(zFar, GLdouble))
+GL_PROTO_INVOKE(Frustum, void, (left, right, bottom, top, zNear, zFar))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Scalef, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(x, GLfloat),
+GL_PROTO_ARG(y, GLfloat),
+GL_PROTO_ARG(z, GLfloat))
+GL_PROTO_INVOKE(Scalef, void, (x, y, z))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Translatef, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(x, GLfloat),
+GL_PROTO_ARG(y, GLfloat),
+GL_PROTO_ARG(z, GLfloat))
+GL_PROTO_INVOKE(Translatef, void, (x, y, z))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(EnableClientState, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(array, GLenum))
+GL_PROTO_INVOKE(EnableClientState, void, (array))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(DisableClientState, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(array, GLenum))
+GL_PROTO_INVOKE(DisableClientState, void, (array))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(TexCoordPointer, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(size, GLint),
+GL_PROTO_ARG(type, GLenum),
+GL_PROTO_ARG(stride, GLsizei),
+GL_PROTO_ARG(pointer, const GLvoid *))
+GL_PROTO_INVOKE(TexCoordPointer, void, (size, type, stride, pointer))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(VertexPointer, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(size, GLint),
+GL_PROTO_ARG(type, GLenum),
+GL_PROTO_ARG(stride, GLsizei),
+GL_PROTO_ARG(pointer, const GLvoid *))
+GL_PROTO_INVOKE(VertexPointer, void, (size, type, stride, pointer))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(EnableVertexAttribArray, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(index, GLuint))
+GL_PROTO_INVOKE(EnableVertexAttribArray, void, (index))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(DisableVertexAttribArray, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(index, GLuint))
+GL_PROTO_INVOKE(DisableVertexAttribArray, void, (index))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(GetVertexAttribPointerv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(index, GLuint),
+GL_PROTO_ARG(pname, GLenum),
+GL_PROTO_ARG(pointer, GLvoid **))
+GL_PROTO_INVOKE(GetVertexAttribPointerv, void, (index, pname, pointer))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(VertexAttribPointer, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(index, GLuint),
+GL_PROTO_ARG(size, GLint),
+GL_PROTO_ARG(type, GLenum),
+GL_PROTO_ARG(normalized, GLboolean),
+GL_PROTO_ARG(stride, GLsizei),
+GL_PROTO_ARG(pointer, const GLvoid *))
+GL_PROTO_INVOKE(VertexAttribPointer, void, (index, size, type, normalized, stride, pointer))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(DrawArrays, void, CORE_1_1)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(mode, GLenum),
+GL_PROTO_ARG(first, GLint),
+GL_PROTO_ARG(count, GLsizei))
+GL_PROTO_INVOKE(DrawArrays, void, (mode, first, count))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(GenTextures, void, CORE_1_1)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(n, GLsizei),
+GL_PROTO_ARG(textures, GLuint *))
+GL_PROTO_INVOKE(GenTextures, void, (n, textures))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(DeleteTextures, void, CORE_1_1)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(n, GLsizei),
+GL_PROTO_ARG(textures, const GLuint *))
+GL_PROTO_INVOKE(DeleteTextures, void, (n, textures))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(BindTexture, void, CORE_1_1)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(target, GLenum),
+GL_PROTO_ARG(texture, GLuint))
+GL_PROTO_INVOKE(BindTexture, void, (target, texture))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(ActiveTexture, void, CORE_1_3)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(texture, GLenum))
+GL_PROTO_INVOKE(ActiveTexture, void, (texture))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(GetTexLevelParameteriv, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(target, GLenum),
+GL_PROTO_ARG(level, GLint),
+GL_PROTO_ARG(pname, GLenum),
+GL_PROTO_ARG(params, GLint *))
+GL_PROTO_INVOKE(GetTexLevelParameteriv, void, (target, level, pname, params))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(TexParameterf, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(target, GLenum),
+GL_PROTO_ARG(pname, GLenum),
+GL_PROTO_ARG(param, GLfloat))
+GL_PROTO_INVOKE(TexParameterf, void, (target, pname, param))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(TexParameterfv, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(target, GLenum),
+GL_PROTO_ARG(pname, GLenum),
+GL_PROTO_ARG(params, const GLfloat *))
+GL_PROTO_INVOKE(TexParameterfv, void, (target, pname, params))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(TexParameteri, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(target, GLenum),
+GL_PROTO_ARG(pname, GLenum),
+GL_PROTO_ARG(param, GLint))
+GL_PROTO_INVOKE(TexParameteri, void, (target, pname, param))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(TexParameteriv, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(target, GLenum),
+GL_PROTO_ARG(pname, GLenum),
+GL_PROTO_ARG(params, const GLint *))
+GL_PROTO_INVOKE(TexParameteriv, void, (target, pname, params))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(TexImage2D, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(target, GLenum),
+GL_PROTO_ARG(level, GLint),
+GL_PROTO_ARG(internalformat, GLint),
+GL_PROTO_ARG(width, GLsizei),
+GL_PROTO_ARG(height, GLsizei),
+GL_PROTO_ARG(border, GLint),
+GL_PROTO_ARG(format, GLenum),
+GL_PROTO_ARG(type, GLenum),
+GL_PROTO_ARG(pixels, const GLvoid *))
+GL_PROTO_INVOKE(TexImage2D, void, (target, level, internalformat, width, height, border, format, type, pixels))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(TexSubImage2D, void, CORE_1_1)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(target, GLenum),
+GL_PROTO_ARG(level, GLint),
+GL_PROTO_ARG(xoffset, GLint),
+GL_PROTO_ARG(yoffset, GLint),
+GL_PROTO_ARG(width, GLsizei),
+GL_PROTO_ARG(height, GLsizei),
+GL_PROTO_ARG(format, GLenum),
+GL_PROTO_ARG(type, GLenum),
+GL_PROTO_ARG(UNUSED, GLuint),
+GL_PROTO_ARG(pixels, const GLvoid *))
+GL_PROTO_INVOKE(TexSubImage2D, void, (target, level, xoffset, yoffset, width, height, format, type, UNUSED, pixels))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(PixelStoref, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(pname, GLenum),
+GL_PROTO_ARG(param, GLfloat))
+GL_PROTO_INVOKE(PixelStoref, void, (pname, param))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(PixelStorei, void, CORE_1_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(pname, GLenum),
+GL_PROTO_ARG(param, GLint))
+GL_PROTO_INVOKE(PixelStorei, void, (pname, param))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(CreateShader, GLuint, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(type, GLenum))
+GL_PROTO_INVOKE(CreateShader, GLuint, (type))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(DeleteShader, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(program, GLuint))
+GL_PROTO_INVOKE(DeleteShader, void, (program))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(ShaderSource, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(shader, GLuint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(string, const GLchar * const *),
+GL_PROTO_ARG(length, const GLint *))
+GL_PROTO_INVOKE(ShaderSource, void, (shader, count, string, length))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(CompileShader, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(shader, GLuint))
+GL_PROTO_INVOKE(CompileShader, void, (shader))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(GetShaderiv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(shader, GLuint),
+GL_PROTO_ARG(pname, GLenum),
+GL_PROTO_ARG(params, GLint *))
+GL_PROTO_INVOKE(GetShaderiv, void, (shader, pname, params))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(GetShaderInfoLog, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(shader, GLuint),
+GL_PROTO_ARG(bufSize, GLsizei),
+GL_PROTO_ARG(length, GLsizei *),
+GL_PROTO_ARG(infoLog, GLchar *))
+GL_PROTO_INVOKE(GetShaderInfoLog, void, (shader, bufSize, length, infoLog))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(CreateProgram, GLuint, CORE_2_0)
+GL_PROTO_ARG_LIST()
+GL_PROTO_INVOKE(CreateProgram, GLuint, ())
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(DeleteProgram, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(program, GLuint))
+GL_PROTO_INVOKE(DeleteProgram, void, (program))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(AttachShader, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(program, GLuint),
+GL_PROTO_ARG(shader, GLuint))
+GL_PROTO_INVOKE(AttachShader, void, (program, shader))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(LinkProgram, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(program, GLuint))
+GL_PROTO_INVOKE(LinkProgram, void, (program))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(UseProgram, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(program, GLuint))
+GL_PROTO_INVOKE(UseProgram, void, (program))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(GetProgramiv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(program, GLuint),
+GL_PROTO_ARG(pname, GLenum),
+GL_PROTO_ARG(params, GLint *))
+GL_PROTO_INVOKE(GetProgramiv, void, (program, pname, params))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(GetProgramInfoLog, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(program, GLuint),
+GL_PROTO_ARG(bufSize, GLsizei),
+GL_PROTO_ARG(length, GLsizei *),
+GL_PROTO_ARG(infoLog, GLchar *))
+GL_PROTO_INVOKE(GetProgramInfoLog, void, (program, bufSize, length, infoLog))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(BindAttribLocation, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(program, GLuint),
+GL_PROTO_ARG(index, GLuint),
+GL_PROTO_ARG(name, const GLchar *))
+GL_PROTO_INVOKE(BindAttribLocation, void, (program, index, name))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(GetUniformLocation, GLint, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(program, GLuint),
+GL_PROTO_ARG(name, const GLchar *))
+GL_PROTO_INVOKE(GetUniformLocation, GLint, (program, name))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform1f, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(v0, GLfloat))
+GL_PROTO_INVOKE(Uniform1f, void, (location, v0))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform1fv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(value, const GLfloat *))
+GL_PROTO_INVOKE(Uniform1fv, void, (location, count, value))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform1i, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(v0, GLint))
+GL_PROTO_INVOKE(Uniform1i, void, (location, v0))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform1iv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(value, const GLint *))
+GL_PROTO_INVOKE(Uniform1iv, void, (location, count, value))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform2f, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(v0, GLfloat),
+GL_PROTO_ARG(v1, GLfloat))
+GL_PROTO_INVOKE(Uniform2f, void, (location, v0, v1))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform2fv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(value, const GLfloat *))
+GL_PROTO_INVOKE(Uniform2fv, void, (location, count, value))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform2i, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(v0, GLint),
+GL_PROTO_ARG(v1, GLint))
+GL_PROTO_INVOKE(Uniform2i, void, (location, v0, v1))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform2iv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(value, const GLint *))
+GL_PROTO_INVOKE(Uniform2iv, void, (location, count, value))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform3f, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(v0, GLfloat),
+GL_PROTO_ARG(v1, GLfloat),
+GL_PROTO_ARG(v2, GLfloat))
+GL_PROTO_INVOKE(Uniform3f, void, (location, v0, v1, v2))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform3fv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(value, const GLfloat *))
+GL_PROTO_INVOKE(Uniform3fv, void, (location, count, value))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform3i, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(v0, GLint),
+GL_PROTO_ARG(v1, GLint),
+GL_PROTO_ARG(v2, GLint))
+GL_PROTO_INVOKE(Uniform3i, void, (location, v0, v1, v2))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform3iv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(value, const GLint *))
+GL_PROTO_INVOKE(Uniform3iv, void, (location, count, value))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform4f, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(v0, GLfloat),
+GL_PROTO_ARG(v1, GLfloat),
+GL_PROTO_ARG(v2, GLfloat),
+GL_PROTO_ARG(v3, GLfloat))
+GL_PROTO_INVOKE(Uniform4f, void, (location, v0, v1, v2, v3))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform4fv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(value, const GLfloat *))
+GL_PROTO_INVOKE(Uniform4fv, void, (location, count, value))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform4i, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(v0, GLint),
+GL_PROTO_ARG(v1, GLint),
+GL_PROTO_ARG(v2, GLint),
+GL_PROTO_ARG(v3, GLint))
+GL_PROTO_INVOKE(Uniform4i, void, (location, v0, v1, v2, v3))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(Uniform4iv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(value, const GLint *))
+GL_PROTO_INVOKE(Uniform4iv, void, (location, count, value))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(UniformMatrix2fv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(transpose, GLboolean),
+GL_PROTO_ARG(value, const GLfloat *))
+GL_PROTO_INVOKE(UniformMatrix2fv, void, (location, count, transpose, value))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(UniformMatrix3fv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(transpose, GLboolean),
+GL_PROTO_ARG(value, const GLfloat *))
+GL_PROTO_INVOKE(UniformMatrix3fv, void, (location, count, transpose, value))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(UniformMatrix4fv, void, CORE_2_0)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(location, GLint),
+GL_PROTO_ARG(count, GLsizei),
+GL_PROTO_ARG(transpose, GLboolean),
+GL_PROTO_ARG(value, const GLfloat *))
+GL_PROTO_INVOKE(UniformMatrix4fv, void, (location, count, transpose, value))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(EGLImageTargetTexture2DOES, void, OES_EGL_image)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(target, GLenum),
+GL_PROTO_ARG(image, void *))
+GL_PROTO_INVOKE(EGLImageTargetTexture2DOES, void, (target, image))
+GL_PROTO_END()
+
+GL_PROTO_BEGIN(EGLImageTargetRenderbufferStorageOES, void, OES_EGL_image)
+GL_PROTO_ARG_LIST(
+GL_PROTO_ARG(target, GLenum),
+GL_PROTO_ARG(image, void *))
+GL_PROTO_INVOKE(EGLImageTargetRenderbufferStorageOES, void, (target, image))
+GL_PROTO_END()
+
+GL_DEFINE_EXTENSION(CORE_1_0)
+GL_DEFINE_EXTENSION(CORE_1_1)
+GL_DEFINE_EXTENSION(CORE_1_3)
+GL_DEFINE_EXTENSION(CORE_2_0)
+GL_DEFINE_EXTENSION(OES_EGL_image)
+
+#undef EGL_PROTO_BEGIN
+#undef EGL_PROTO_BEGIN_I
+#undef EGL_PROTO_ARG_LIST
+#undef EGL_PROTO_ARG
+#undef EGL_PROTO_INVOKE
+#undef EGL_PROTO_INVOKE_I
+#undef EGL_PROTO_END
+#undef EGL_DEFINE_EXTENSION
+#undef EGL_DEFINE_EXTENSION_I
+
+#undef GL_PROTO_BEGIN
+#undef GL_PROTO_BEGIN_I
+#undef GL_PROTO_ARG_LIST
+#undef GL_PROTO_ARG
+#undef GL_PROTO_INVOKE
+#undef GL_PROTO_INVOKE_I
+#undef GL_PROTO_END
+#undef GL_DEFINE_EXTENSION
+#undef GL_DEFINE_EXTENSION_I
+
+#undef GL_PROTO_GEN_CONCAT5
+#undef GL_PROTO_GEN_CONCAT5_I
+#undef GL_PROTO_GEN_CONCAT4
+#undef GL_PROTO_GEN_CONCAT4_I
+#undef GL_PROTO_GEN_CONCAT3
+#undef GL_PROTO_GEN_CONCAT3_I
+#undef GL_PROTO_GEN_CONCAT2
+#undef GL_PROTO_GEN_CONCAT2_I
+#undef GL_PROTO_GEN_CONCAT
+#undef GL_PROTO_GEN_STRING
+#undef GL_PROTO_GEN_STRING_I
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay.c b/gst-libs/gst/vaapi/gstvaapidisplay.c
index fc371029..3fe523bb 100644
--- a/gst-libs/gst/vaapi/gstvaapidisplay.c
+++ b/gst-libs/gst/vaapi/gstvaapidisplay.c
@@ -163,6 +163,10 @@ gst_vaapi_display_type_get_type (void)
{GST_VAAPI_DISPLAY_TYPE_GLX,
"VA/GLX display", "glx"},
#endif
+#if USE_EGL
+ {GST_VAAPI_DISPLAY_TYPE_EGL,
+ "VA/EGL display", "egl"},
+#endif
#if USE_WAYLAND
{GST_VAAPI_DISPLAY_TYPE_WAYLAND,
"VA/Wayland display", "wayland"},
@@ -2137,5 +2141,6 @@ gst_vaapi_display_has_opengl (GstVaapiDisplay * display)
g_return_val_if_fail (display != NULL, FALSE);
klass = GST_VAAPI_DISPLAY_GET_CLASS (display);
- return (klass->display_type == GST_VAAPI_DISPLAY_TYPE_GLX);
+ return (klass->display_type == GST_VAAPI_DISPLAY_TYPE_GLX ||
+ klass->display_type == GST_VAAPI_DISPLAY_TYPE_EGL);
}
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay.h b/gst-libs/gst/vaapi/gstvaapidisplay.h
index 998e96ef..f4cc8653 100644
--- a/gst-libs/gst/vaapi/gstvaapidisplay.h
+++ b/gst-libs/gst/vaapi/gstvaapidisplay.h
@@ -91,6 +91,7 @@ typedef struct _GstVaapiDisplay GstVaapiDisplay;
* @GST_VAAPI_DISPLAY_TYPE_GLX: VA/GLX display.
* @GST_VAAPI_DISPLAY_TYPE_WAYLAND: VA/Wayland display.
* @GST_VAAPI_DISPLAY_TYPE_DRM: VA/DRM display.
+ * @GST_VAAPI_DISPLAY_TYPE_EGL: VA/EGL display.
*/
typedef enum
{
@@ -99,6 +100,7 @@ typedef enum
GST_VAAPI_DISPLAY_TYPE_GLX,
GST_VAAPI_DISPLAY_TYPE_WAYLAND,
GST_VAAPI_DISPLAY_TYPE_DRM,
+ GST_VAAPI_DISPLAY_TYPE_EGL,
} GstVaapiDisplayType;
#define GST_VAAPI_TYPE_DISPLAY_TYPE \
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_egl.c b/gst-libs/gst/vaapi/gstvaapidisplay_egl.c
new file mode 100644
index 00000000..b02f2538
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapidisplay_egl.c
@@ -0,0 +1,582 @@
+/*
+ * gstvaapidisplay_egl.c - VA/EGL display abstraction
+ *
+ * Copyright (C) 2014 Intel Corporation
+ * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#include "sysdeps.h"
+#include <gmodule.h>
+#include "gstvaapidisplay_egl.h"
+#include "gstvaapidisplay_egl_priv.h"
+#include "gstvaapiwindow.h"
+
+GST_DEBUG_CATEGORY (gst_debug_vaapidisplay_egl);
+
+/* ------------------------------------------------------------------------- */
+/* --- Display backend loader --- */
+/* ------------------------------------------------------------------------- */
+
+typedef struct _GstVaapiDisplayLoader GstVaapiDisplayLoader;
+typedef struct _GstVaapiDisplayLoaderInfo GstVaapiDisplayLoaderInfo;
+
+typedef GstVaapiDisplay *(*GstVaapiDisplayCreateFunc) (const gchar * name);
+typedef GstVaapiDisplay *(*GstVaapiDisplayCreateFromNativeFunc) (gpointer dpy);
+
+struct _GstVaapiDisplayLoader
+{
+ GstVaapiMiniObject parent_instance;
+
+ GModule *module;
+ GPtrArray *module_names;
+ GstVaapiDisplayCreateFunc create_display;
+ GstVaapiDisplayCreateFromNativeFunc create_display_from_native;
+};
+
+struct _GstVaapiDisplayLoaderInfo
+{
+ const gchar *name;
+ GstVaapiDisplayType type;
+ const gchar *create_display;
+ const gchar *create_display_from_native;
+};
+
+static GMutex g_loader_lock;
+static GstVaapiDisplayLoader *g_loader;
+
+/* *INDENT-OFF* */
+static const GstVaapiDisplayLoaderInfo g_loader_info[] = {
+#if USE_WAYLAND
+ { "wayland",
+ GST_VAAPI_DISPLAY_TYPE_WAYLAND,
+ "gst_vaapi_display_wayland_new",
+ "gst_vaapi_display_wayland_new_with_display",
+ },
+#endif
+#if USE_X11
+ { "x11",
+ GST_VAAPI_DISPLAY_TYPE_X11,
+ "gst_vaapi_display_x11_new",
+ "gst_vaapi_display_x11_new_with_display",
+ },
+#endif
+ {NULL,}
+};
+/* *INDENT-ON* */
+
+static void
+gst_vaapi_display_loader_finalize (GstVaapiDisplayLoader * loader)
+{
+ if (!loader)
+ return;
+
+ if (loader->module) {
+ g_module_close (loader->module);
+ loader->module = NULL;
+ }
+
+ if (loader->module_names) {
+ g_ptr_array_unref (loader->module_names);
+ loader->module_names = NULL;
+ }
+}
+
+static inline const GstVaapiMiniObjectClass *
+gst_vaapi_display_loader_class (void)
+{
+ static const GstVaapiMiniObjectClass g_class = {
+ .size = sizeof (GstVaapiDisplayLoader),
+ .finalize = (GDestroyNotify) gst_vaapi_display_loader_finalize,
+ };
+ return &g_class;
+}
+
+static inline GstVaapiDisplayLoader *
+gst_vaapi_display_loader_new (void)
+{
+ return (GstVaapiDisplayLoader *)
+ gst_vaapi_mini_object_new0 (gst_vaapi_display_loader_class ());
+}
+
+static gboolean
+gst_vaapi_display_loader_reset_module_names (GstVaapiDisplayLoader * loader,
+ const GstVaapiDisplayLoaderInfo * loader_info)
+{
+ gchar *module_name;
+
+ if (loader->module_names)
+ g_ptr_array_unref (loader->module_names);
+ loader->module_names = g_ptr_array_new_full (3, (GDestroyNotify) g_free);
+ if (!loader->module_names)
+ return FALSE;
+
+ module_name =
+ g_strdup_printf ("libgstvaapi-%s-%s.la", loader_info->name,
+ GST_API_VERSION_S);
+ if (module_name)
+ g_ptr_array_add (loader->module_names, module_name);
+
+ module_name =
+ g_strdup_printf ("libgstvaapi-%s-%s.so", loader_info->name,
+ GST_API_VERSION_S);
+ if (module_name)
+ g_ptr_array_add (loader->module_names, module_name);
+
+ module_name =
+ g_strdup_printf ("libgstvaapi-%s-%s.so.%s", loader_info->name,
+ GST_API_VERSION_S, GST_VAAPI_MAJOR_VERSION_S);
+ if (module_name)
+ g_ptr_array_add (loader->module_names, module_name);
+
+ return loader->module_names->len > 0;
+}
+
+static gboolean
+gst_vaapi_display_loader_try_load_module (GstVaapiDisplayLoader * loader,
+ const GstVaapiDisplayLoaderInfo * loader_info)
+{
+ guint i;
+
+ if (!gst_vaapi_display_loader_reset_module_names (loader, loader_info))
+ return FALSE;
+
+ if (loader->module) {
+ g_module_close (loader->module);
+ loader->module = NULL;
+ }
+
+ for (i = 0; i < loader->module_names->len; i++) {
+ const gchar *const module_name =
+ g_ptr_array_index (loader->module_names, i);
+
+ loader->module = g_module_open (module_name,
+ G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+ if (loader->module)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static gboolean
+gst_vaapi_display_loader_try_load (GstVaapiDisplayLoader * loader,
+ const GstVaapiDisplayLoaderInfo * loader_info)
+{
+ guint has_errors = 0;
+
+ if (!gst_vaapi_display_loader_try_load_module (loader, loader_info))
+ return FALSE;
+ GST_DEBUG ("loaded backend: %s", g_module_name (loader->module));
+
+ has_errors |= !g_module_symbol (loader->module,
+ loader_info->create_display, (gpointer *) & loader->create_display);
+ has_errors |= !g_module_symbol (loader->module,
+ loader_info->create_display_from_native,
+ (gpointer *) & loader->create_display_from_native);
+
+ return has_errors == 0;
+}
+
+static GstVaapiDisplay *
+gst_vaapi_display_loader_try_load_any (GstVaapiDisplayLoader * loader)
+{
+ GstVaapiDisplay *display;
+ const GstVaapiDisplayLoaderInfo *loader_info;
+
+ for (loader_info = g_loader_info; loader_info->name != NULL; loader_info++) {
+ if (!gst_vaapi_display_loader_try_load (loader, loader_info))
+ continue;
+
+ display = loader->create_display (NULL);
+ if (display) {
+ GST_INFO ("selected backend: %s", loader_info->name);
+ return display;
+ }
+ }
+ return NULL;
+}
+
+#define gst_vaapi_display_loader_ref(loader) \
+ ((GstVaapiDisplayLoader *) gst_vaapi_mini_object_ref (GST_VAAPI_MINI_OBJECT (loader)))
+#define gst_vaapi_display_loader_unref(loader) \
+ gst_vaapi_mini_object_unref (GST_VAAPI_MINI_OBJECT (loader))
+#define gst_vaapi_display_loader_replace(old_loader_ptr, new_loader) \
+ gst_vaapi_mini_object_replace ((GstVaapiMiniObject **)(old_loader_ptr), \
+ GST_VAAPI_MINI_OBJECT (new_loader))
+
+static GstVaapiDisplayLoader *
+gst_vaapi_display_loader_acquire_global (void)
+{
+ GstVaapiDisplayLoader *loader;
+
+ g_mutex_lock (&g_loader_lock);
+ loader = g_loader ? gst_vaapi_display_loader_ref (g_loader) :
+ gst_vaapi_display_loader_new ();
+ g_loader = loader;
+ g_mutex_unlock (&g_loader_lock);
+ return loader;
+}
+
+static void
+gst_vaapi_display_loader_release_global (void)
+{
+ g_mutex_lock (&g_loader_lock);
+ gst_vaapi_display_loader_replace (&g_loader, NULL);
+ g_mutex_unlock (&g_loader_lock);
+}
+
+static const GstVaapiDisplayLoaderInfo *
+gst_vaapi_display_loader_map_lookup_type (GstVaapiDisplayType type)
+{
+ const GstVaapiDisplayLoaderInfo *loader_info;
+
+ for (loader_info = g_loader_info; loader_info->name != NULL; loader_info++) {
+ if (loader_info->type == type)
+ return loader_info;
+ }
+ return NULL;
+}
+
+/* ------------------------------------------------------------------------- */
+/* --- EGL backend implementation --- */
+/* ------------------------------------------------------------------------- */
+
+static const guint g_display_types = 1U << GST_VAAPI_DISPLAY_TYPE_EGL;
+
+typedef struct
+{
+ gpointer display;
+ guint display_type;
+ guint gles_version;
+} InitParams;
+
+static gboolean
+reset_context (GstVaapiDisplayEGL * display, EGLContext gl_context)
+{
+ EglConfig *config;
+ EglContext *ctx;
+
+ egl_object_replace (&display->egl_context, NULL);
+
+ if (gl_context != EGL_NO_CONTEXT)
+ ctx = egl_context_new_wrapped (display->egl_display, gl_context);
+ else {
+ config = egl_config_new (display->egl_display, display->gles_version,
+ GST_VIDEO_FORMAT_RGB);
+ if (!config)
+ return FALSE;
+
+ ctx = egl_context_new (display->egl_display, config, NULL);
+ egl_object_unref (config);
+ }
+ if (!ctx)
+ return FALSE;
+
+ egl_object_replace (&display->egl_context, ctx);
+ egl_object_unref (ctx);
+ return TRUE;
+}
+
+static inline gboolean
+ensure_context (GstVaapiDisplayEGL * display)
+{
+ return display->egl_context || reset_context (display, EGL_NO_CONTEXT);
+}
+
+static inline gboolean
+ensure_context_is_wrapped (GstVaapiDisplayEGL * display, EGLContext gl_context)
+{
+ return (display->egl_context &&
+ display->egl_context->base.handle.p == gl_context) ||
+ reset_context (display, gl_context);
+}
+
+static gboolean
+gst_vaapi_display_egl_bind_display (GstVaapiDisplayEGL * display,
+ const InitParams * params)
+{
+ GstVaapiDisplay *native_display;
+ GstVaapiDisplayLoader *loader;
+ const GstVaapiDisplayLoaderInfo *loader_info;
+ EglDisplay *egl_display;
+
+ loader = gst_vaapi_display_loader_acquire_global ();
+ if (params->display) {
+ loader_info =
+ gst_vaapi_display_loader_map_lookup_type (params->display_type);
+ if (!loader_info)
+ goto error_unsupported_display_type;
+
+ loader = gst_vaapi_display_loader_new ();
+ if (!loader || !gst_vaapi_display_loader_try_load (loader, loader_info))
+ goto error_init_loader;
+
+ native_display = loader->create_display_from_native (params->display);
+ } else {
+ gst_vaapi_display_loader_ref (loader);
+ native_display = gst_vaapi_display_loader_try_load_any (loader);
+ }
+ gst_vaapi_display_loader_replace (&display->loader, loader);
+ gst_vaapi_display_loader_unref (loader);
+ if (!native_display)
+ return FALSE;
+
+ gst_vaapi_display_replace (&display->display, native_display);
+ gst_vaapi_display_unref (native_display);
+
+ egl_display = egl_display_new (GST_VAAPI_DISPLAY_NATIVE (display->display));
+ if (!egl_display)
+ return FALSE;
+
+ egl_object_replace (&display->egl_display, egl_display);
+ egl_object_unref (egl_display);
+ display->gles_version = params->gles_version;
+ return TRUE;
+
+ /* ERRORS */
+error_unsupported_display_type:
+ GST_ERROR ("unsupported display type (%d)", params->display_type);
+ return FALSE;
+error_init_loader:
+ GST_ERROR ("failed to initialize display backend loader");
+ gst_vaapi_display_loader_replace (&loader, NULL);
+ return FALSE;
+}
+
+static void
+gst_vaapi_display_egl_close_display (GstVaapiDisplayEGL * display)
+{
+ gst_vaapi_display_replace (&display->display, NULL);
+ gst_vaapi_display_loader_replace (&display->loader, NULL);
+ gst_vaapi_display_loader_release_global ();
+}
+
+static void
+gst_vaapi_display_egl_lock (GstVaapiDisplayEGL * display)
+{
+ GstVaapiDisplayClass *const klass =
+ GST_VAAPI_DISPLAY_GET_CLASS (display->display);
+
+ if (klass->lock)
+ klass->lock (display->display);
+}
+
+static void
+gst_vaapi_display_egl_unlock (GstVaapiDisplayEGL * display)
+{
+ GstVaapiDisplayClass *const klass =
+ GST_VAAPI_DISPLAY_GET_CLASS (display->display);
+
+ if (klass->unlock)
+ klass->unlock (display->display);
+}
+
+static void
+gst_vaapi_display_egl_sync (GstVaapiDisplayEGL * display)
+{
+ GstVaapiDisplayClass *const klass =
+ GST_VAAPI_DISPLAY_GET_CLASS (display->display);
+
+ if (klass->sync)
+ klass->sync (display->display);
+ else if (klass->flush)
+ klass->flush (display->display);
+}
+
+static void
+gst_vaapi_display_egl_flush (GstVaapiDisplayEGL * display)
+{
+ GstVaapiDisplayClass *const klass =
+ GST_VAAPI_DISPLAY_GET_CLASS (display->display);
+
+ if (klass->flush)
+ klass->flush (display->display);
+}
+
+static gboolean
+gst_vaapi_display_egl_get_display_info (GstVaapiDisplayEGL * display,
+ GstVaapiDisplayInfo * info)
+{
+ GstVaapiDisplayClass *const klass =
+ GST_VAAPI_DISPLAY_GET_CLASS (display->display);
+
+ if (klass->get_display && !klass->get_display (display->display, info))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+gst_vaapi_display_egl_get_size (GstVaapiDisplayEGL * display,
+ guint * width_ptr, guint * height_ptr)
+{
+ GstVaapiDisplayClass *const klass =
+ GST_VAAPI_DISPLAY_GET_CLASS (display->display);
+
+ if (klass->get_size)
+ klass->get_size (display->display, width_ptr, height_ptr);
+}
+
+static void
+gst_vaapi_display_egl_get_size_mm (GstVaapiDisplayEGL * display,
+ guint * width_ptr, guint * height_ptr)
+{
+ GstVaapiDisplayClass *const klass =
+ GST_VAAPI_DISPLAY_GET_CLASS (display->display);
+
+ if (klass->get_size_mm)
+ klass->get_size_mm (display->display, width_ptr, height_ptr);
+}
+
+static void
+gst_vaapi_display_egl_class_init (GstVaapiDisplayEGLClass * klass)
+{
+ GstVaapiMiniObjectClass *const object_class =
+ GST_VAAPI_MINI_OBJECT_CLASS (klass);
+ GstVaapiDisplayClass *const dpy_class = GST_VAAPI_DISPLAY_CLASS (klass);
+
+ GST_DEBUG_CATEGORY_INIT (gst_debug_vaapidisplay_egl, "vaapidisplay_egl", 0,
+ "VA/EGL backend");
+
+ gst_vaapi_display_class_init (dpy_class);
+
+ object_class->size = sizeof (GstVaapiDisplayEGL);
+ dpy_class->display_type = GST_VAAPI_DISPLAY_TYPE_EGL;
+ dpy_class->bind_display = (GstVaapiDisplayBindFunc)
+ gst_vaapi_display_egl_bind_display;
+ dpy_class->close_display = (GstVaapiDisplayCloseFunc)
+ gst_vaapi_display_egl_close_display;
+ dpy_class->lock = (GstVaapiDisplayLockFunc)
+ gst_vaapi_display_egl_lock;
+ dpy_class->unlock = (GstVaapiDisplayUnlockFunc)
+ gst_vaapi_display_egl_unlock;
+ dpy_class->sync = (GstVaapiDisplaySyncFunc)
+ gst_vaapi_display_egl_sync;
+ dpy_class->flush = (GstVaapiDisplayFlushFunc)
+ gst_vaapi_display_egl_flush;
+ dpy_class->get_display = (GstVaapiDisplayGetInfoFunc)
+ gst_vaapi_display_egl_get_display_info;
+ dpy_class->get_size = (GstVaapiDisplayGetSizeFunc)
+ gst_vaapi_display_egl_get_size;
+ dpy_class->get_size_mm = (GstVaapiDisplayGetSizeMFunc)
+ gst_vaapi_display_egl_get_size_mm;
+}
+
+static inline const GstVaapiDisplayClass *
+gst_vaapi_display_egl_class (void)
+{
+ static GstVaapiDisplayEGLClass g_class;
+ static gsize g_class_init = FALSE;
+
+ if (g_once_init_enter (&g_class_init)) {
+ gst_vaapi_display_egl_class_init (&g_class);
+ g_once_init_leave (&g_class_init, TRUE);
+ }
+ return GST_VAAPI_DISPLAY_CLASS (&g_class);
+}
+
+/**
+ * gst_vaapi_display_egl_new:
+ * @display: a #GstVaapiDisplay, or %NULL to pick any one
+ * @gles_version: the OpenGL ES version API to use
+ *
+ * Creates a new #GstVaapiDisplay object suitable in EGL context. If
+ * the native @display is %NULL, then any type of display is picked,
+ * i.e. one that can be successfully opened. The @gles_version will
+ * further ensure the OpenGL ES API to use, or zero to indicate
+ * "desktop" OpenGL.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_egl_new (GstVaapiDisplay * display, guint gles_version)
+{
+ InitParams params;
+
+ if (display) {
+ params.display = GST_VAAPI_DISPLAY_NATIVE (display);
+ params.display_type = GST_VAAPI_DISPLAY_VADISPLAY_TYPE (display);
+ } else {
+ params.display = NULL;
+ params.display_type = GST_VAAPI_DISPLAY_TYPE_ANY;
+ }
+ params.gles_version = gles_version;
+ return gst_vaapi_display_new (gst_vaapi_display_egl_class (),
+ GST_VAAPI_DISPLAY_INIT_FROM_NATIVE_DISPLAY, &params);
+}
+
+/**
+ * gst_vaapi_display_egl_new_with_native_display:
+ * @native_display: an EGLDisplay object
+ * @display_type: the display type of @native_display
+ * @gles_version: the OpenGL ES version API to use
+ *
+ * Creates a #GstVaapiDisplay based on the native display supplied in
+ * as @native_display. The caller still owns the display and must call
+ * native display close function when all #GstVaapiDisplay references
+ * are released. Doing so too early can yield undefined behaviour.
+ *
+ * The @gles_version will further ensure the OpenGL ES API to use, or
+ * zero to indicate "desktop" OpenGL.
+ *
+ * Return value: a newly allocated #GstVaapiDisplay object
+ */
+GstVaapiDisplay *
+gst_vaapi_display_egl_new_with_native_display (gpointer native_display,
+ GstVaapiDisplayType display_type, guint gles_version)
+{
+ InitParams params;
+
+ g_return_val_if_fail (native_display != NULL, NULL);
+
+ params.display = native_display;
+ params.display_type = display_type;
+ params.gles_version = gles_version;
+ return gst_vaapi_display_new (gst_vaapi_display_egl_class (),
+ GST_VAAPI_DISPLAY_INIT_FROM_NATIVE_DISPLAY, &params);
+}
+
+EglContext *
+gst_vaapi_display_egl_get_context (GstVaapiDisplayEGL * display)
+{
+ return ensure_context (display) ? display->egl_context : NULL;
+}
+
+EGLDisplay
+gst_vaapi_display_egl_get_gl_display (GstVaapiDisplayEGL * display)
+{
+ g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), EGL_NO_DISPLAY);
+
+ return display->egl_display->base.handle.p;
+}
+
+EGLContext
+gst_vaapi_display_egl_get_gl_context (GstVaapiDisplayEGL * display)
+{
+ g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), EGL_NO_CONTEXT);
+
+ return ensure_context (display) ? display->egl_context->base.handle.p :
+ EGL_NO_CONTEXT;
+}
+
+gboolean
+gst_vaapi_display_egl_set_gl_context (GstVaapiDisplayEGL * display,
+ EGLContext gl_context)
+{
+ g_return_val_if_fail (GST_VAAPI_IS_DISPLAY_EGL (display), FALSE);
+
+ return ensure_context_is_wrapped (display, gl_context);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_egl.h b/gst-libs/gst/vaapi/gstvaapidisplay_egl.h
new file mode 100644
index 00000000..2f79e88f
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapidisplay_egl.h
@@ -0,0 +1,55 @@
+/*
+ * gstvaapidisplay_egl.h - VA/EGL display abstraction
+ *
+ * Copyright (C) 2014 Intel Corporation
+ * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) egl later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT EGL WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_EGL_H
+#define GST_VAAPI_DISPLAY_EGL_H
+
+#include <EGL/egl.h>
+#include <gst/vaapi/gstvaapidisplay.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GstVaapiDisplayEGL GstVaapiDisplayEGL;
+
+#define GST_VAAPI_DISPLAY_EGL(obj) \
+ ((GstVaapiDisplayEGL *)(obj))
+
+GstVaapiDisplay *
+gst_vaapi_display_egl_new (GstVaapiDisplay * display, guint gles_version);
+
+GstVaapiDisplay *
+gst_vaapi_display_egl_new_with_native_display (gpointer native_display,
+ GstVaapiDisplayType display_type, guint gles_version);
+
+EGLDisplay
+gst_vaapi_display_egl_get_gl_display (GstVaapiDisplayEGL * display);
+
+EGLContext
+gst_vaapi_display_egl_get_gl_context (GstVaapiDisplayEGL * display);
+
+gboolean
+gst_vaapi_display_egl_set_gl_context (GstVaapiDisplayEGL * display,
+ EGLContext gl_context);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_EGL_H */
diff --git a/gst-libs/gst/vaapi/gstvaapidisplay_egl_priv.h b/gst-libs/gst/vaapi/gstvaapidisplay_egl_priv.h
new file mode 100644
index 00000000..3db5ad89
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapidisplay_egl_priv.h
@@ -0,0 +1,101 @@
+/*
+ * gstvaapidisplay_egl_priv.h - Internal VA/EGL interface
+ *
+ * Copyright (C) 2014 Splitted-Desktop Systems
+ * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA
+ */
+
+#ifndef GST_VAAPI_DISPLAY_EGL_PRIV_H
+#define GST_VAAPI_DISPLAY_EGL_PRIV_H
+
+#include <gst/vaapi/gstvaapiwindow.h>
+#include "gstvaapidisplay_egl.h"
+#include "gstvaapidisplay_priv.h"
+#include "gstvaapiutils_egl.h"
+
+G_BEGIN_DECLS
+
+#define GST_VAAPI_IS_DISPLAY_EGL(display) \
+ ((display) != NULL && \
+ GST_VAAPI_DISPLAY_GET_CLASS_TYPE (display) == GST_VAAPI_DISPLAY_TYPE_EGL)
+
+#define GST_VAAPI_DISPLAY_EGL_CLASS(klass) \
+ ((GstVaapiDisplayEGLClass *)(klass))
+
+#define GST_VAAPI_DISPLAY_EGL_GET_CLASS(obj) \
+ GST_VAAPI_DISPLAY_EGL_CLASS (GST_VAAPI_DISPLAY_GET_CLASS (obj))
+
+/**
+ * GST_VAAPI_DISPLAY_EGL_DISPLAY:
+ * @display: a #GstVaapiDisplay
+ *
+ * Macro that evaluates to #EglDisplay wrapper for @display.
+ * This is an internal macro that does not do any run-time type check.
+ */
+#undef GST_VAAPI_DISPLAY_EGL_DISPLAY
+#define GST_VAAPI_DISPLAY_EGL_DISPLAY(display) \
+ (GST_VAAPI_DISPLAY_EGL (display)->egl_display)
+
+/**
+ * GST_VAAPI_DISPLAY_EGL_CONTEXT:
+ * @display: a #GstVaapiDisplay
+ *
+ * Macro that evaluates to #EglContext wrapper for @display.
+ * This is an internal macro that does not do any run-time type check.
+ */
+#undef GST_VAAPI_DISPLAY_EGL_CONTEXT
+#define GST_VAAPI_DISPLAY_EGL_CONTEXT(display) \
+ gst_vaapi_display_egl_get_context (GST_VAAPI_DISPLAY_EGL (display))
+
+typedef struct _GstVaapiDisplayEGLClass GstVaapiDisplayEGLClass;
+
+/**
+ * GstVaapiDisplayEGL:
+ *
+ * VA/EGL display wrapper.
+ */
+struct _GstVaapiDisplayEGL
+{
+ /*< private >*/
+ GstVaapiDisplay parent_instance;
+
+ gpointer loader;
+ GstVaapiDisplay *display;
+ EglDisplay *egl_display;
+ EglContext *egl_context;
+ guint gles_version;
+};
+
+/**
+ * GstVaapiDisplayEGLClass:
+ *
+ * VA/EGL display wrapper clas.
+ */
+struct _GstVaapiDisplayEGLClass
+{
+ /*< private >*/
+ GstVaapiDisplayClass parent_class;
+};
+
+G_GNUC_INTERNAL
+EglContext *
+gst_vaapi_display_egl_get_context (GstVaapiDisplayEGL * display);
+
+G_END_DECLS
+
+#endif /* GST_VAAPI_DISPLAY_EGL_PRIV_H */
diff --git a/gst-libs/gst/vaapi/gstvaapiutils_egl.c b/gst-libs/gst/vaapi/gstvaapiutils_egl.c
new file mode 100644
index 00000000..62176251
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapiutils_egl.c
@@ -0,0 +1,1342 @@
+/*
+ * gstvaapiutils_egl.c - EGL utilities
+ *
+ * Copyright (C) 2014 Intel Corporation
+ * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301
+ */
+
+#include "sysdeps.h"
+#include "gstvaapiutils_egl.h"
+
+typedef struct egl_message_s EglMessage;
+struct egl_message_s
+{
+ EglObject base;
+ EglContextRunFunc func;
+ gpointer args;
+};
+
+static void
+egl_message_finalize (EglMessage * msg)
+{
+}
+
+/* ------------------------------------------------------------------------- */
+// Utility functions
+
+typedef struct gl_version_info_s GlVersionInfo;
+struct gl_version_info_s
+{
+ guint gles_version;
+ guint gl_api_bit;
+ guint gl_api;
+ const gchar *gl_api_name;
+};
+
+static const GlVersionInfo gl_version_info[] = {
+ {0, EGL_OPENGL_BIT, EGL_OPENGL_API, "OpenGL"},
+ {1, EGL_OPENGL_ES_BIT, EGL_OPENGL_ES_API, "OpenGL_ES"},
+ {2, EGL_OPENGL_ES2_BIT, EGL_OPENGL_ES_API, "OpenGL_ES2"},
+ {3, EGL_OPENGL_ES3_BIT_KHR, EGL_OPENGL_ES_API, "OpenGL_ES3"},
+ {0,}
+};
+
+static const GlVersionInfo *
+gl_version_info_lookup (guint gles_version)
+{
+ const GlVersionInfo *vinfo;
+
+ for (vinfo = gl_version_info; vinfo->gl_api_bit != 0; vinfo++) {
+ if (vinfo->gles_version == gles_version)
+ return vinfo;
+ }
+ return NULL;
+}
+
+static const GlVersionInfo *
+gl_version_info_lookup_by_api (guint api)
+{
+ const GlVersionInfo *vinfo;
+
+ for (vinfo = gl_version_info; vinfo->gl_api_bit != 0; vinfo++) {
+ if (api & vinfo->gl_api_bit)
+ return vinfo;
+ }
+ return NULL;
+}
+
+static const GlVersionInfo *
+gl_version_info_lookup_by_api_name (const gchar * name)
+{
+ const GlVersionInfo *vinfo;
+
+ for (vinfo = gl_version_info; vinfo->gl_api_bit != 0; vinfo++) {
+ if (g_strcmp0 (vinfo->gl_api_name, name) == 0)
+ return vinfo;
+ }
+ return NULL;
+}
+
+static gboolean
+g_strv_match_string (gchar ** extensions_list, const gchar * name)
+{
+ if (extensions_list) {
+ for (; *extensions_list != NULL; extensions_list++) {
+ if (g_strcmp0 (*extensions_list, name) == 0)
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean
+egl_find_attrib_value (const EGLint * attribs, EGLint type, EGLint * value_ptr)
+{
+ while (attribs[0] != EGL_NONE) {
+ if (attribs[0] == type) {
+ if (value_ptr)
+ *value_ptr = attribs[1];
+ return TRUE;
+ }
+ attribs += 2;
+ }
+ return FALSE;
+}
+
+/* ------------------------------------------------------------------------- */
+// Basic objects
+
+#define EGL_OBJECT(object) ((EglObject *)(object))
+#define EGL_OBJECT_CLASS(klass) ((EglObjectClass *)(klass))
+
+#define EGL_OBJECT_DEFINE_CLASS_WITH_CODE(TN, t_n, code) \
+static void \
+G_PASTE(t_n,_finalize) (TN * object); \
+ \
+static inline const EglObjectClass * \
+G_PASTE(t_n,_class) (void) \
+{ \
+ static G_PASTE(TN,Class) g_class; \
+ static gsize g_class_init = FALSE; \
+ \
+ if (g_once_init_enter (&g_class_init)) { \
+ GstVaapiMiniObjectClass *const object_class = \
+ GST_VAAPI_MINI_OBJECT_CLASS (&g_class); \
+ code; \
+ object_class->size = sizeof (TN); \
+ object_class->finalize = (GDestroyNotify) \
+ G_PASTE(t_n,_finalize); \
+ g_once_init_leave (&g_class_init, TRUE); \
+ } \
+ return EGL_OBJECT_CLASS (&g_class); \
+}
+
+#define EGL_OBJECT_DEFINE_CLASS(TN, t_n) \
+ EGL_OBJECT_DEFINE_CLASS_WITH_CODE (TN, t_n, /**/)
+
+static inline gpointer
+egl_object_new (const EglObjectClass * klass)
+{
+ return gst_vaapi_mini_object_new (GST_VAAPI_MINI_OBJECT_CLASS (klass));
+}
+
+static inline gpointer
+egl_object_new0 (const EglObjectClass * klass)
+{
+ return gst_vaapi_mini_object_new0 (GST_VAAPI_MINI_OBJECT_CLASS (klass));
+}
+
+typedef struct egl_object_class_s EglMessageClass;
+typedef struct egl_object_class_s EglVTableClass;
+typedef struct egl_object_class_s EglDisplayClass;
+typedef struct egl_object_class_s EglConfigClass;
+typedef struct egl_object_class_s EglContextClass;
+typedef struct egl_object_class_s EglSurfaceClass;
+typedef struct egl_object_class_s EglProgramClass;
+
+EGL_OBJECT_DEFINE_CLASS (EglMessage, egl_message);
+EGL_OBJECT_DEFINE_CLASS (EglVTable, egl_vtable);
+EGL_OBJECT_DEFINE_CLASS (EglDisplay, egl_display);
+EGL_OBJECT_DEFINE_CLASS (EglConfig, egl_config);
+EGL_OBJECT_DEFINE_CLASS (EglContext, egl_context);
+EGL_OBJECT_DEFINE_CLASS (EglSurface, egl_surface);
+EGL_OBJECT_DEFINE_CLASS (EglProgram, egl_program);
+
+/* ------------------------------------------------------------------------- */
+// Desktop OpenGL and OpenGL|ES dispatcher (vtable)
+
+static GMutex gl_vtables_lock;
+static EglVTable *gl_vtables[4];
+
+#if (USE_GLES_VERSION_MASK & (1U << 0))
+static const gchar *gl_library_names[] = {
+ "libGL.la",
+ "libGL.so.1",
+ NULL
+};
+#endif
+
+#if (USE_GLES_VERSION_MASK & (1U << 1))
+static const gchar *gles1_library_names[] = {
+ "libGLESv1_CM.la",
+ "libGLESv1_CM.so.1",
+ NULL
+};
+#endif
+
+#if (USE_GLES_VERSION_MASK & (1U << 2))
+static const gchar *gles2_library_names[] = {
+ "libGLESv2.la",
+ "libGLESv2.so.2",
+ NULL
+};
+#endif
+
+static const gchar **gl_library_names_group[] = {
+#if (USE_GLES_VERSION_MASK & (1U << 0))
+ gl_library_names,
+#endif
+ NULL
+};
+
+static const gchar **gles1_library_names_group[] = {
+#if (USE_GLES_VERSION_MASK & (1U << 1))
+ gles1_library_names,
+#endif
+ NULL
+};
+
+static const gchar **gles2_library_names_group[] = {
+#if (USE_GLES_VERSION_MASK & (1U << 2))
+ gles2_library_names,
+#endif
+ NULL
+};
+
+static const gchar **gles3_library_names_group[] = {
+#if (USE_GLES_VERSION_MASK & (1U << 3))
+ gles2_library_names,
+#endif
+ NULL
+};
+
+static const gchar ***
+egl_vtable_get_library_names_group (guint gles_version)
+{
+ const gchar ***library_names_group;
+
+ switch (gles_version) {
+ case 0:
+ library_names_group = gl_library_names_group;
+ break;
+ case 1:
+ library_names_group = gles1_library_names_group;
+ break;
+ case 2:
+ library_names_group = gles2_library_names_group;
+ break;
+ case 3:
+ library_names_group = gles3_library_names_group;
+ break;
+ default:
+ library_names_group = NULL;
+ break;
+ }
+ return library_names_group;
+}
+
+static gboolean
+egl_vtable_check_extension (EglVTable * vtable, EGLDisplay display,
+ gboolean is_egl, const gchar * group_name, guint * group_ptr)
+{
+ gchar ***extensions_list;
+ const gchar *extensions;
+
+ g_return_val_if_fail (group_name != NULL, FALSE);
+ g_return_val_if_fail (group_ptr != NULL, FALSE);
+
+ if (*group_ptr > 0)
+ return TRUE;
+
+ GST_DEBUG ("check for %s extension %s", is_egl ? "EGL" : "GL", group_name);
+
+ if (is_egl) {
+ if (!vtable->egl_extensions) {
+ extensions = eglQueryString (display, EGL_EXTENSIONS);
+ if (!extensions)
+ return FALSE;
+ GST_DEBUG ("EGL extensions: %s", extensions);
+ vtable->egl_extensions = g_strsplit (extensions, " ", 0);
+ }
+ extensions_list = &vtable->egl_extensions;
+ } else {
+ if (!vtable->gl_extensions) {
+ extensions = (const gchar *) vtable->glGetString (GL_EXTENSIONS);
+ if (!extensions)
+ return FALSE;
+ GST_DEBUG ("GL extensions: %s", extensions);
+ vtable->gl_extensions = g_strsplit (extensions, " ", 0);
+ }
+ extensions_list = &vtable->gl_extensions;
+ }
+ if (!g_strv_match_string (*extensions_list, group_name))
+ return FALSE;
+
+ GST_LOG (" found %s extension %s", is_egl ? "EGL" : "GL", group_name);
+ (*group_ptr)++;
+ return TRUE;
+}
+
+static gboolean
+egl_vtable_load_symbol (EglVTable * vtable, EGLDisplay display, gboolean is_egl,
+ const gchar * symbol_name, gpointer * symbol_ptr,
+ const gchar * group_name, guint * group_ptr)
+{
+ void (*symbol) (void);
+
+ if (group_ptr && !*group_ptr) {
+ if (!egl_vtable_check_extension (vtable, display, is_egl, group_name,
+ group_ptr))
+ return FALSE;
+ }
+
+ if (is_egl) {
+ symbol = eglGetProcAddress (symbol_name);
+ } else {
+ if (!g_module_symbol (vtable->base.handle.p, symbol_name,
+ (gpointer *) & symbol))
+ return FALSE;
+ }
+ if (!symbol)
+ return FALSE;
+
+ GST_LOG (" found symbol %s", symbol_name);
+ if (symbol_ptr)
+ *symbol_ptr = symbol;
+ if (group_ptr)
+ (*group_ptr)++;
+ return TRUE;
+}
+
+static gboolean
+egl_vtable_load_egl_symbols (EglVTable * vtable, EGLDisplay display)
+{
+ guint n = 0;
+
+#define EGL_DEFINE_EXTENSION(NAME) do { \
+ egl_vtable_check_extension (vtable, display, TRUE, \
+ "EGL_" G_STRINGIFY (NAME), \
+ &vtable->GL_PROTO_GEN_CONCAT(has_EGL_,NAME)); \
+ } while (0);
+
+#define EGL_PROTO_BEGIN(NAME, TYPE, EXTENSION) do { \
+ n += egl_vtable_load_symbol (vtable, display, TRUE, \
+ G_STRINGIFY(GL_PROTO_GEN_CONCAT(egl,NAME)), \
+ (gpointer *) &vtable->GL_PROTO_GEN_CONCAT(egl,NAME), \
+ "EGL_" G_STRINGIFY(EXTENSION), \
+ &vtable->GL_PROTO_GEN_CONCAT(has_EGL_,EXTENSION)); \
+ } while (0);
+
+#include "egl_vtable.h"
+
+ vtable->num_egl_symbols = n;
+ return TRUE;
+}
+
+static gboolean
+egl_vtable_load_gl_symbols (EglVTable * vtable, EGLDisplay display)
+{
+ guint n = 0;
+
+ vtable->has_GL_CORE_1_0 = 1;
+ vtable->has_GL_CORE_1_1 = 1;
+ vtable->has_GL_CORE_1_3 = 1;
+ vtable->has_GL_CORE_2_0 = 1;
+
+#define GL_DEFINE_EXTENSION(NAME) do { \
+ egl_vtable_check_extension (vtable, display, FALSE, \
+ "GL_" G_STRINGIFY (NAME), \
+ &vtable->GL_PROTO_GEN_CONCAT(has_GL_,NAME)); \
+ } while (0);
+
+#define GL_PROTO_BEGIN(NAME, TYPE, EXTENSION) do { \
+ n += egl_vtable_load_symbol (vtable, display, FALSE, \
+ G_STRINGIFY(GL_PROTO_GEN_CONCAT(gl,NAME)), \
+ (gpointer *) &vtable->GL_PROTO_GEN_CONCAT(gl,NAME), \
+ "GL_" G_STRINGIFY(EXTENSION), \
+ &vtable->GL_PROTO_GEN_CONCAT(has_GL_,EXTENSION)); \
+ } while (0);
+
+#include "egl_vtable.h"
+
+ --vtable->has_GL_CORE_1_0;
+ --vtable->has_GL_CORE_1_1;
+ --vtable->has_GL_CORE_1_3;
+ --vtable->has_GL_CORE_2_0;
+
+ vtable->num_gl_symbols = n;
+ return TRUE;
+}
+
+static gboolean
+egl_vtable_try_load_library (EglVTable * vtable, const gchar * name)
+{
+ if (vtable->base.handle.p)
+ g_module_close (vtable->base.handle.p);
+ vtable->base.handle.p = g_module_open (name,
+ G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);
+ if (!vtable->base.handle.p)
+ return FALSE;
+
+ GST_DEBUG ("loaded backend: %s", g_module_name (vtable->base.handle.p));
+ return TRUE;
+}
+
+static gboolean
+egl_vtable_find_library (EglVTable * vtable)
+{
+ const gchar ***library_names_ptr =
+ egl_vtable_get_library_names_group (vtable->gles_version);
+
+ if (!library_names_ptr)
+ return FALSE;
+
+ for (; *library_names_ptr != NULL; library_names_ptr++) {
+ const gchar **library_name_ptr = *library_names_ptr;
+ for (; *library_name_ptr != NULL; library_name_ptr++) {
+ if (egl_vtable_try_load_library (vtable, *library_name_ptr))
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+static gboolean
+egl_vtable_init (EglVTable * vtable, EGLDisplay display, guint gles_version)
+{
+ GST_DEBUG ("initialize for OpenGL|ES API version %d", gles_version);
+
+ vtable->gles_version = gles_version;
+ if (!egl_vtable_find_library (vtable))
+ return FALSE;
+ if (!egl_vtable_load_egl_symbols (vtable, display))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+egl_vtable_finalize (EglVTable * vtable)
+{
+ g_strfreev (vtable->egl_extensions);
+ g_strfreev (vtable->gl_extensions);
+ if (vtable->base.handle.p)
+ g_module_close (vtable->base.handle.p);
+
+ if (vtable->base.is_wrapped) {
+ g_mutex_lock (&gl_vtables_lock);
+ gl_vtables[vtable->gles_version] = NULL;
+ g_mutex_unlock (&gl_vtables_lock);
+ }
+}
+
+static EglVTable *
+egl_vtable_new (EglDisplay * display, guint gles_version)
+{
+ EglVTable *vtable;
+
+ g_return_val_if_fail (display != NULL, NULL);
+
+ vtable = egl_object_new0 (egl_vtable_class ());
+ if (!vtable
+ || !egl_vtable_init (vtable, display->base.handle.p, gles_version))
+ goto error;
+ return vtable;
+
+error:
+ egl_object_replace (&vtable, NULL);
+ return NULL;
+}
+
+static EglVTable *
+egl_vtable_new_cached (EglDisplay * display, guint gles_version)
+{
+ EglVTable *vtable, **vtable_ptr;
+
+ g_return_val_if_fail (gles_version < G_N_ELEMENTS (gl_vtables), NULL);
+
+ vtable_ptr = &gl_vtables[gles_version];
+
+ g_mutex_lock (&gl_vtables_lock);
+ vtable = *vtable_ptr;
+ if (vtable)
+ egl_object_ref (vtable);
+ else {
+ vtable = egl_vtable_new (display, gles_version);
+ if (vtable) {
+ vtable->base.is_wrapped = TRUE;
+ *vtable_ptr = vtable;
+ }
+ }
+ g_mutex_unlock (&gl_vtables_lock);
+ return vtable;
+}
+
+/* ------------------------------------------------------------------------- */
+// EGL Display
+
+static gboolean
+egl_display_run (EglDisplay * display, EglContextRunFunc func, gpointer args)
+{
+ EglMessage *msg;
+
+ if (display->gl_thread == g_thread_self ()) {
+ func (args);
+ return TRUE;
+ }
+
+ msg = egl_object_new0 (egl_message_class ());
+ if (!msg)
+ return FALSE;
+
+ msg->base.is_valid = TRUE;
+ msg->func = func;
+ msg->args = args;
+ g_async_queue_push (display->gl_queue, egl_object_ref (msg));
+
+ g_mutex_lock (&display->mutex);
+ while (msg->base.is_valid)
+ g_cond_wait (&display->gl_thread_ready, &display->mutex);
+ g_mutex_unlock (&display->mutex);
+ egl_object_unref (msg);
+ return TRUE;
+}
+
+static gpointer
+egl_display_thread (gpointer data)
+{
+ EglDisplay *const display = data;
+ EGLDisplay gl_display = display->base.handle.p;
+ EGLint major_version, minor_version;
+ gchar **gl_apis, **gl_api;
+
+ if (!display->base.is_wrapped) {
+ gl_display = display->base.handle.p = eglGetDisplay (gl_display);
+ if (!gl_display)
+ goto error;
+ if (!eglInitialize (gl_display, &major_version, &minor_version))
+ goto error;
+ }
+
+ display->gl_vendor_string =
+ g_strdup (eglQueryString (gl_display, EGL_VENDOR));
+ display->gl_version_string =
+ g_strdup (eglQueryString (gl_display, EGL_VERSION));
+ display->gl_apis_string =
+ g_strdup (eglQueryString (gl_display, EGL_CLIENT_APIS));
+
+ GST_INFO ("EGL vendor: %s", display->gl_vendor_string);
+ GST_INFO ("EGL version: %s", display->gl_version_string);
+ GST_INFO ("EGL client APIs: %s", display->gl_apis_string);
+
+ gl_apis = g_strsplit (display->gl_apis_string, " ", 0);
+ if (!gl_apis)
+ goto error;
+ for (gl_api = gl_apis; *gl_api != NULL; gl_api++) {
+ const GlVersionInfo *const vinfo =
+ gl_version_info_lookup_by_api_name (*gl_api);
+
+ if (vinfo)
+ display->gl_apis |= vinfo->gl_api_bit;
+ }
+ g_strfreev (gl_apis);
+ if (!display->gl_apis)
+ goto error;
+
+ display->base.is_valid = TRUE;
+ g_cond_broadcast (&display->gl_thread_ready);
+
+ while (!display->gl_thread_cancel) {
+ EglMessage *const msg =
+ g_async_queue_timeout_pop (display->gl_queue, 100000);
+
+ if (msg) {
+ if (msg->base.is_valid) {
+ msg->func (msg->args);
+ msg->base.is_valid = FALSE;
+ g_cond_broadcast (&display->gl_thread_ready);
+ }
+ egl_object_unref (msg);
+ }
+ }
+
+done:
+ if (gl_display != EGL_NO_DISPLAY && !display->base.is_wrapped)
+ eglTerminate (gl_display);
+ display->base.handle.p = NULL;
+ g_cond_broadcast (&display->gl_thread_ready);
+ return NULL;
+
+error:
+ display->base.is_valid = FALSE;
+ goto done;
+}
+
+static gboolean
+egl_display_init (EglDisplay * display)
+{
+ display->gl_queue =
+ g_async_queue_new_full ((GDestroyNotify) gst_vaapi_mini_object_unref);
+ if (!display->gl_queue)
+ return FALSE;
+
+ g_mutex_init (&display->mutex);
+ g_cond_init (&display->gl_thread_ready);
+ display->gl_thread = g_thread_try_new ("OpenGL Thread", egl_display_thread,
+ display, NULL);
+ if (!display->gl_thread)
+ return FALSE;
+
+ g_mutex_lock (&display->mutex);
+ g_cond_wait (&display->gl_thread_ready, &display->mutex);
+ g_mutex_unlock (&display->mutex);
+ return display->base.is_valid;
+}
+
+static void
+egl_display_finalize (EglDisplay * display)
+{
+ display->gl_thread_cancel = TRUE;
+ g_thread_join (display->gl_thread);
+ g_cond_clear (&display->gl_thread_ready);
+ g_mutex_clear (&display->mutex);
+ g_async_queue_unref (display->gl_queue);
+
+ g_free (display->gl_vendor_string);
+ g_free (display->gl_version_string);
+ g_free (display->gl_apis_string);
+}
+
+static EglDisplay *
+egl_display_new_full (gpointer handle, gboolean is_wrapped)
+{
+ EglDisplay *display;
+
+ display = egl_object_new0 (egl_display_class ());
+ if (!display)
+ return NULL;
+
+ display->base.handle.p = handle;
+ display->base.is_wrapped = is_wrapped;
+ if (!egl_display_init (display))
+ goto error;
+ return display;
+
+error:
+ egl_object_unref (display);
+ return NULL;
+}
+
+EglDisplay *
+egl_display_new (gpointer native_display)
+{
+ g_return_val_if_fail (native_display != NULL, NULL);
+
+ return egl_display_new_full (native_display, FALSE);
+}
+
+EglDisplay *
+egl_display_new_wrapped (EGLDisplay gl_display)
+{
+ g_return_val_if_fail (gl_display != EGL_NO_DISPLAY, NULL);
+
+ return egl_display_new_full (gl_display, TRUE);
+}
+
+/* ------------------------------------------------------------------------- */
+// EGL Config
+
+static gboolean
+egl_config_init (EglConfig * config, EglDisplay * display,
+ const EGLint * attribs)
+{
+ EGLDisplay const gl_display = display->base.handle.p;
+ const GlVersionInfo *vinfo;
+ EGLConfig gl_config;
+ EGLint v, gl_apis, num_configs;
+
+ egl_object_replace (&config->display, display);
+
+ if (!eglChooseConfig (gl_display, attribs, &gl_config, 1, &num_configs))
+ return FALSE;
+ if (num_configs != 1)
+ return FALSE;
+ config->base.handle.p = gl_config;
+
+ if (!eglGetConfigAttrib (gl_display, gl_config, EGL_CONFIG_ID, &v))
+ return FALSE;
+ config->config_id = v;
+
+ if (!eglGetConfigAttrib (gl_display, gl_config, EGL_NATIVE_VISUAL_ID, &v))
+ return FALSE;
+ config->visual_id = v;
+
+ if (!eglGetConfigAttrib (gl_display, gl_config, EGL_RENDERABLE_TYPE, &v))
+ return FALSE;
+ if (!egl_find_attrib_value (attribs, EGL_RENDERABLE_TYPE, &gl_apis))
+ return FALSE;
+ vinfo = gl_version_info_lookup_by_api (v & gl_apis);
+ if (!vinfo)
+ return FALSE;
+ config->gles_version = vinfo->gles_version;
+ config->gl_api = vinfo->gles_version > 0 ? EGL_OPENGL_ES_API : EGL_OPENGL_API;
+ return TRUE;
+}
+
+static void
+egl_config_finalize (EglConfig * config)
+{
+ egl_object_replace (&config->display, NULL);
+}
+
+EglConfig *
+egl_config_new (EglDisplay * display, guint gles_version, GstVideoFormat format)
+{
+ EGLint attribs[2 * 6 + 1], *attrib = attribs;
+ const GstVideoFormatInfo *finfo;
+ const GlVersionInfo *vinfo;
+
+ g_return_val_if_fail (display != NULL, NULL);
+
+ finfo = gst_video_format_get_info (format);
+ if (!finfo || !GST_VIDEO_FORMAT_INFO_IS_RGB (finfo))
+ return NULL;
+
+ vinfo = gl_version_info_lookup (gles_version);
+ if (!vinfo)
+ return NULL;
+
+ *attrib++ = EGL_COLOR_BUFFER_TYPE;
+ *attrib++ = EGL_RGB_BUFFER;
+ *attrib++ = EGL_RED_SIZE;
+ *attrib++ = GST_VIDEO_FORMAT_INFO_DEPTH (finfo, GST_VIDEO_COMP_R);
+ *attrib++ = EGL_GREEN_SIZE;
+ *attrib++ = GST_VIDEO_FORMAT_INFO_DEPTH (finfo, GST_VIDEO_COMP_G);
+ *attrib++ = EGL_BLUE_SIZE;
+ *attrib++ = GST_VIDEO_FORMAT_INFO_DEPTH (finfo, GST_VIDEO_COMP_B);
+ *attrib++ = EGL_ALPHA_SIZE;
+ *attrib++ = GST_VIDEO_FORMAT_INFO_DEPTH (finfo, GST_VIDEO_COMP_A);
+ *attrib++ = EGL_RENDERABLE_TYPE;
+ *attrib++ = vinfo->gl_api_bit;
+ *attrib++ = EGL_NONE;
+ g_assert (attrib - attribs <= G_N_ELEMENTS (attribs));
+
+ return egl_config_new_with_attribs (display, attribs);
+}
+
+EglConfig *
+egl_config_new_with_attribs (EglDisplay * display, const EGLint * attribs)
+{
+ EglConfig *config;
+
+ g_return_val_if_fail (display != NULL, NULL);
+ g_return_val_if_fail (attribs != NULL, NULL);
+
+ config = egl_object_new0 (egl_config_class ());
+ if (!config || !egl_config_init (config, display, attribs))
+ goto error;
+ return config;
+
+error:
+ egl_object_replace (&config, NULL);
+ return NULL;
+}
+
+static EglConfig *
+egl_config_new_from_gl_context (EglDisplay * display, EGLContext gl_context)
+{
+ EGLDisplay const gl_display = display->base.handle.p;
+ EGLint attribs[3 * 2 + 1], *attrib = attribs;
+ EGLint config_id, api, v;
+ guint gles_version;
+ const GlVersionInfo *vinfo;
+
+ if (!eglQueryContext (gl_display, gl_context, EGL_CONFIG_ID, &config_id))
+ return NULL;
+ if (!eglQueryContext (gl_display, gl_context, EGL_CONTEXT_CLIENT_TYPE, &api))
+ return NULL;
+ if (!eglQueryContext (gl_display, gl_context, EGL_CONTEXT_CLIENT_VERSION, &v))
+ return NULL;
+
+ if (api == EGL_OPENGL_API)
+ gles_version = 0;
+ else if (api == EGL_OPENGL_ES_API)
+ gles_version = v;
+ else {
+ GST_ERROR ("unsupported EGL client API (%d)", api);
+ return NULL;
+ }
+
+ vinfo = gl_version_info_lookup (gles_version);
+ if (!vinfo)
+ return NULL;
+
+ *attrib++ = EGL_COLOR_BUFFER_TYPE;
+ *attrib++ = EGL_RGB_BUFFER;
+ *attrib++ = EGL_CONFIG_ID;
+ *attrib++ = config_id;
+ *attrib++ = EGL_RENDERABLE_TYPE;
+ *attrib++ = vinfo->gl_api_bit;
+ *attrib++ = EGL_NONE;
+ g_assert (attrib - attribs <= G_N_ELEMENTS (attribs));
+
+ return egl_config_new_with_attribs (display, attribs);
+}
+
+/* ------------------------------------------------------------------------- */
+// EGL Surface
+
+static void
+egl_surface_finalize (EglSurface * surface)
+{
+ if (surface->base.handle.p != EGL_NO_SURFACE && !surface->base.is_wrapped)
+ eglDestroySurface (surface->display->base.handle.p, surface->base.handle.p);
+ egl_object_replace (&surface->display, NULL);
+}
+
+EglSurface *
+egl_surface_new_wrapped (EglDisplay * display, EGLSurface gl_surface)
+{
+ EglSurface *surface;
+
+ g_return_val_if_fail (display != NULL, NULL);
+
+ surface = egl_object_new (egl_surface_class ());
+ if (!surface)
+ return NULL;
+
+ surface->base.is_wrapped = TRUE;
+ surface->base.handle.p = gl_surface;
+ surface->display = egl_object_ref (display);
+ return surface;
+}
+
+/* ------------------------------------------------------------------------- */
+// EGL Context
+
+static void
+egl_context_state_get_current (EglContextState * cs);
+
+static gboolean
+egl_context_state_set_current (EglContextState * new_cs,
+ EglContextState * old_cs);
+
+static gboolean
+ensure_vtable (EglContext * ctx)
+{
+ if (!ctx->vtable) {
+ ctx->vtable = egl_vtable_new_cached (ctx->display,
+ ctx->config ? ctx->config->gles_version : 0);
+ if (!ctx->vtable)
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static gboolean
+ensure_context (EglContext * ctx, EGLContext gl_parent_context)
+{
+ EGLDisplay *const gl_display = ctx->display->base.handle.p;
+ EGLContext gl_context = ctx->base.handle.p;
+ EGLint gles_attribs[3], *attribs = NULL;
+
+ if (!gl_context) {
+ if (ctx->config->gles_version >= 2) {
+ attribs = gles_attribs;
+ attribs[0] = EGL_CONTEXT_CLIENT_VERSION;
+ attribs[1] = ctx->config->gles_version;
+ attribs[2] = EGL_NONE;
+ }
+
+ gl_context = eglCreateContext (gl_display, ctx->config->base.handle.p,
+ gl_parent_context, attribs);
+ if (!gl_context)
+ goto error_create_context;
+ ctx->base.handle.p = gl_context;
+ }
+ return TRUE;
+
+ /* ERRORS */
+error_create_context:
+ GST_ERROR ("failed to create EGL context");
+ return FALSE;
+}
+
+static inline gboolean
+ensure_gl_is_surfaceless (EglContext * ctx)
+{
+ return ctx->vtable->has_EGL_KHR_surfaceless_context ||
+ (ctx->read_surface && ctx->draw_surface);
+}
+
+static gboolean
+ensure_gl_scene (EglContext * ctx)
+{
+ EglVTable *vtable;
+
+ if (!ensure_gl_is_surfaceless (ctx))
+ return FALSE;
+
+ if (ctx->base.is_valid)
+ return TRUE;
+
+ vtable = egl_context_get_vtable (ctx, TRUE);
+ if (!vtable)
+ return FALSE;
+
+ vtable->glClearColor (0.0, 0.0, 0.0, 1.0);
+ if (ctx->config && ctx->config->gles_version == 0)
+ vtable->glEnable (GL_TEXTURE_2D);
+ vtable->glDisable (GL_BLEND);
+ vtable->glDisable (GL_DEPTH_TEST);
+
+ ctx->base.is_valid = TRUE;
+ return TRUE;
+}
+
+/**
+ * egl_context_state_get_current:
+ * @cs: return location to the current #EglContextState
+ *
+ * Retrieves the current EGL context, display and surface to pack into
+ * the #EglContextState struct.
+ */
+static void
+egl_context_state_get_current (EglContextState * cs)
+{
+ cs->display = eglGetCurrentDisplay ();
+ cs->context = eglGetCurrentContext ();
+ if (cs->context) {
+ cs->read_surface = eglGetCurrentSurface (EGL_READ);
+ cs->draw_surface = eglGetCurrentSurface (EGL_DRAW);
+ } else {
+ cs->read_surface = EGL_NO_SURFACE;
+ cs->draw_surface = EGL_NO_SURFACE;
+ }
+}
+
+/**
+ * egl_context_state_set_current:
+ * @new_cs: the requested new #EglContextState
+ * @old_cs: return location to the context that was previously current
+ *
+ * Makes the @new_cs EGL context the current EGL rendering context of
+ * the calling thread, replacing the previously current context if
+ * there was one.
+ *
+ * If @old_cs is non %NULL, the previously current EGL context and
+ * surface are recorded.
+ *
+ * Return value: %TRUE on success
+ */
+static gboolean
+egl_context_state_set_current (EglContextState * new_cs,
+ EglContextState * old_cs)
+{
+ /* If display is NULL, this could be that new_cs was retrieved from
+ egl_context_state_get_current() with none set previously. If that case,
+ the other fields are also NULL and we don't return an error */
+ if (!new_cs->display)
+ return !new_cs->context && !new_cs->read_surface && !new_cs->draw_surface;
+
+ if (old_cs) {
+ if (old_cs == new_cs)
+ return TRUE;
+ egl_context_state_get_current (old_cs);
+ if (old_cs->display == new_cs->display &&
+ old_cs->context == new_cs->context &&
+ old_cs->read_surface == new_cs->read_surface &&
+ old_cs->draw_surface == new_cs->draw_surface)
+ return TRUE;
+ }
+ return eglMakeCurrent (new_cs->display, new_cs->draw_surface,
+ new_cs->read_surface, new_cs->context);
+}
+
+static gboolean
+egl_context_init (EglContext * ctx, EglDisplay * display, EglConfig * config,
+ EGLContext gl_parent_context)
+{
+ egl_object_replace (&ctx->display, display);
+ egl_object_replace (&ctx->config, config);
+
+ if (config)
+ eglBindAPI (config->gl_api);
+
+ if (!ensure_vtable (ctx))
+ return FALSE;
+ if (!ensure_context (ctx, gl_parent_context))
+ return FALSE;
+ return TRUE;
+}
+
+static void
+egl_context_finalize (EglContext * ctx)
+{
+ if (ctx->base.handle.p && !ctx->base.is_wrapped)
+ eglDestroyContext (ctx->display->base.handle.p, ctx->base.handle.p);
+ egl_object_replace (&ctx->read_surface, NULL);
+ egl_object_replace (&ctx->draw_surface, NULL);
+ egl_object_replace (&ctx->config, NULL);
+ egl_object_replace (&ctx->display, NULL);
+ egl_object_replace (&ctx->vtable, NULL);
+}
+
+typedef struct
+{
+ EglDisplay *display;
+ EglConfig *config;
+ EGLContext gl_parent_context;
+ EglContext *context; /* result */
+} CreateContextArgs;
+
+static void
+do_egl_context_new (CreateContextArgs * args)
+{
+ EglContext *ctx;
+
+ ctx = egl_object_new0 (egl_context_class ());
+ if (!ctx || !egl_context_init (ctx, args->display, args->config,
+ args->gl_parent_context))
+ goto error;
+ args->context = ctx;
+ return;
+
+error:
+ egl_object_replace (&ctx, NULL);
+ args->context = NULL;
+}
+
+EglContext *
+egl_context_new (EglDisplay * display, EglConfig * config, EglContext * parent)
+{
+ CreateContextArgs args;
+
+ g_return_val_if_fail (display != NULL, NULL);
+ g_return_val_if_fail (config != NULL, NULL);
+
+ args.display = display;
+ args.config = config;
+ args.gl_parent_context = parent ? parent->base.handle.p : EGL_NO_CONTEXT;
+ if (!egl_display_run (display, (EglContextRunFunc) do_egl_context_new, &args))
+ return NULL;
+ return args.context;
+}
+
+EglContext *
+egl_context_new_wrapped (EglDisplay * display, EGLContext gl_context)
+{
+ CreateContextArgs args;
+ EglConfig *config;
+ gboolean success;
+
+ g_return_val_if_fail (display != NULL, NULL);
+ g_return_val_if_fail (gl_context != EGL_NO_CONTEXT, NULL);
+
+ config = egl_config_new_from_gl_context (display, gl_context);
+ if (!config)
+ return NULL;
+
+ args.display = display;
+ args.config = config;
+ args.gl_parent_context = gl_context;
+ success = egl_display_run (display, (EglContextRunFunc) do_egl_context_new,
+ &args);
+ egl_object_unref (config);
+ if (!success)
+ return NULL;
+ return args.context;
+}
+
+EglVTable *
+egl_context_get_vtable (EglContext * ctx, gboolean need_gl_symbols)
+{
+ g_return_val_if_fail (ctx != NULL, NULL);
+ g_return_val_if_fail (ctx->display->gl_thread == g_thread_self (), NULL);
+
+ if (!ensure_vtable (ctx))
+ return NULL;
+
+ if (need_gl_symbols && !(ctx->vtable->num_gl_symbols > 0 ||
+ egl_vtable_load_gl_symbols (ctx->vtable,
+ ctx->display->base.handle.p)))
+ return NULL;
+ return ctx->vtable;
+}
+
+void
+egl_context_set_surface (EglContext * ctx, EglSurface * surface)
+{
+ g_return_if_fail (ctx != NULL);
+ g_return_if_fail (surface != NULL);
+
+ egl_object_replace (&ctx->read_surface, surface);
+ egl_object_replace (&ctx->draw_surface, surface);
+}
+
+gboolean
+egl_context_set_current (EglContext * ctx, gboolean activate,
+ EglContextState * old_cs)
+{
+ EglContextState cs, *new_cs;
+
+ g_return_val_if_fail (ctx != NULL, FALSE);
+ g_return_val_if_fail (ctx->display->gl_thread == g_thread_self (), FALSE);
+
+ if (activate) {
+ new_cs = &cs;
+ new_cs->display = ctx->display->base.handle.p;
+ new_cs->context = ctx->base.handle.p;
+ new_cs->draw_surface = ctx->draw_surface ?
+ ctx->draw_surface->base.handle.p : EGL_NO_SURFACE;
+ new_cs->read_surface = ctx->read_surface ?
+ ctx->read_surface->base.handle.p : EGL_NO_SURFACE;
+ } else if (old_cs) {
+ new_cs = old_cs;
+ old_cs = NULL;
+ } else {
+ new_cs = &cs;
+ new_cs->display = ctx->display->base.handle.p;
+ new_cs->context = EGL_NO_CONTEXT;
+ new_cs->draw_surface = EGL_NO_SURFACE;
+ new_cs->read_surface = EGL_NO_SURFACE;
+ old_cs = NULL;
+ }
+
+ if (!egl_context_state_set_current (new_cs, old_cs))
+ return FALSE;
+ if (activate && !ensure_gl_scene (ctx))
+ return FALSE;
+ return TRUE;
+}
+
+gboolean
+egl_context_run (EglContext * ctx, EglContextRunFunc func, gpointer args)
+{
+ g_return_val_if_fail (ctx != NULL, FALSE);
+ g_return_val_if_fail (func != NULL, FALSE);
+
+ return egl_display_run (ctx->display, func, args);
+}
+
+/* ------------------------------------------------------------------------- */
+// EGL Program
+
+static GLuint
+egl_compile_shader (EglContext * ctx, GLenum type, const char *source)
+{
+ EglVTable *const vtable = egl_context_get_vtable (ctx, TRUE);
+ GLuint shader;
+ GLint status;
+ char log[BUFSIZ];
+ GLsizei log_length;
+
+ shader = vtable->glCreateShader (type);
+ vtable->glShaderSource (shader, 1, &source, NULL);
+ vtable->glCompileShader (shader);
+ vtable->glGetShaderiv (shader, GL_COMPILE_STATUS, &status);
+ if (!status) {
+ GST_ERROR ("failed to compile %s shader",
+ type == GL_FRAGMENT_SHADER ? "fragment" :
+ type == GL_VERTEX_SHADER ? "vertex" : "<unknown>");
+
+ vtable->glGetShaderInfoLog (shader, sizeof (log), &log_length, log);
+ GST_ERROR ("info log: %s", log);
+ return 0;
+ }
+ return shader;
+}
+
+static void
+egl_program_finalize (EglProgram * program)
+{
+ EglVTable *const vtable = program->vtable;
+
+ if (program->base.handle.u)
+ vtable->glDeleteProgram (program->base.handle.u);
+ if (program->frag_shader)
+ vtable->glDeleteShader (program->frag_shader);
+ if (program->vert_shader)
+ vtable->glDeleteShader (program->vert_shader);
+ egl_object_replace (&program->vtable, NULL);
+}
+
+static gboolean
+egl_program_init (EglProgram * program, EglContext * ctx,
+ const gchar * frag_shader_text, const gchar * vert_shader_text)
+{
+ EglVTable *const vtable = egl_context_get_vtable (ctx, TRUE);
+ GLuint prog_id;
+ char msg[BUFSIZ];
+ GLsizei msglen;
+ GLint status;
+
+ if (ctx->config->gles_version == 1)
+ goto error_unsupported_gles_version;
+
+ program->vtable = egl_object_ref (vtable);
+
+ program->frag_shader =
+ egl_compile_shader (ctx, GL_FRAGMENT_SHADER, frag_shader_text);
+ if (!program->frag_shader)
+ return FALSE;
+
+ program->vert_shader =
+ egl_compile_shader (ctx, GL_VERTEX_SHADER, vert_shader_text);
+ if (!program->vert_shader)
+ return FALSE;
+
+ prog_id = vtable->glCreateProgram ();
+ if (!prog_id)
+ return FALSE;
+ program->base.handle.u = prog_id;
+
+ vtable->glAttachShader (prog_id, program->frag_shader);
+ vtable->glAttachShader (prog_id, program->vert_shader);
+ vtable->glBindAttribLocation (prog_id, 0, "position");
+ vtable->glBindAttribLocation (prog_id, 1, "texcoord");
+ vtable->glLinkProgram (prog_id);
+
+ vtable->glGetProgramiv (prog_id, GL_LINK_STATUS, &status);
+ if (!status)
+ goto error_link_program;
+ return TRUE;
+
+ /* ERRORS */
+error_unsupported_gles_version:
+ GST_ERROR ("unsupported shader with OpenGL|ES version 1");
+ return FALSE;
+error_link_program:
+ vtable->glGetProgramInfoLog (prog_id, sizeof (msg), &msglen, msg);
+ GST_ERROR ("failed to link program: %s", msg);
+ return FALSE;
+}
+
+EglProgram *
+egl_program_new (EglContext * ctx, const gchar * frag_shader_text,
+ const gchar * vert_shader_text)
+{
+ EglProgram *program;
+
+ g_return_val_if_fail (ctx != NULL, NULL);
+ g_return_val_if_fail (frag_shader_text != NULL, NULL);
+ g_return_val_if_fail (vert_shader_text != NULL, NULL);
+
+ program = egl_object_new0 (egl_program_class ());
+ if (!program
+ || !egl_program_init (program, ctx, frag_shader_text, vert_shader_text))
+ goto error;
+ return program;
+
+error:
+ egl_object_replace (&program, NULL);
+ return NULL;
+}
+
+/* ------------------------------------------------------------------------- */
+// Misc utility functions
+
+void
+egl_matrix_set_identity (gfloat m[16])
+{
+#define MAT(m,r,c) (m)[(c) * 4 + (r)]
+ MAT(m,0,0) = 1.0; MAT(m,0,1) = 0.0; MAT(m,0,2) = 0.0; MAT(m,0,3) = 0.0;
+ MAT(m,1,0) = 0.0; MAT(m,1,1) = 1.0; MAT(m,1,2) = 0.0; MAT(m,1,3) = 0.0;
+ MAT(m,2,0) = 0.0; MAT(m,2,1) = 0.0; MAT(m,2,2) = 1.0; MAT(m,2,3) = 0.0;
+ MAT(m,3,0) = 0.0; MAT(m,3,1) = 0.0; MAT(m,3,2) = 0.0; MAT(m,3,3) = 1.0;
+#undef MAT
+}
+
+/**
+ * egl_create_texture:
+ * @ctx: the parent #EglContext object
+ * @target: the target to which the texture is bound
+ * @format: the format of the pixel data
+ * @width: the requested width, in pixels
+ * @height: the requested height, in pixels
+ *
+ * Creates a texture with the specified dimensions and @format. The
+ * internal format will be automatically derived from @format.
+ *
+ * Return value: the newly created texture name
+ */
+guint
+egl_create_texture (EglContext * ctx, guint target, guint format,
+ guint width, guint height)
+{
+ EglVTable *const vtable = egl_context_get_vtable (ctx, TRUE);
+ guint internal_format, texture, bytes_per_component;
+
+ internal_format = format;
+ switch (format) {
+ case GL_LUMINANCE:
+ bytes_per_component = 1;
+ break;
+ case GL_LUMINANCE_ALPHA:
+ bytes_per_component = 2;
+ break;
+ case GL_RGBA:
+ case GL_BGRA_EXT:
+ internal_format = GL_RGBA;
+ bytes_per_component = 4;
+ break;
+ default:
+ bytes_per_component = 0;
+ break;
+ }
+ g_assert (bytes_per_component > 0);
+
+ vtable->glGenTextures (1, &texture);
+ vtable->glBindTexture (target, texture);
+
+ if (width > 0 && height > 0)
+ vtable->glTexImage2D (target, 0, internal_format, width, height, 0,
+ format, GL_UNSIGNED_BYTE, NULL);
+
+ vtable->glTexParameteri (target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ vtable->glTexParameteri (target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ vtable->glTexParameteri (target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ vtable->glTexParameteri (target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ vtable->glPixelStorei (GL_UNPACK_ALIGNMENT, bytes_per_component);
+
+ return texture;
+}
+
+/**
+ * egl_destroy_texture:
+ * @ctx: the parent #EglContext object
+ * @texture: the texture name to delete
+ *
+ * Destroys the supplied @texture name.
+ */
+void
+egl_destroy_texture (EglContext * ctx, guint texture)
+{
+ EglVTable *const vtable = egl_context_get_vtable (ctx, TRUE);
+
+ vtable->glDeleteTextures (1, &texture);
+}
diff --git a/gst-libs/gst/vaapi/gstvaapiutils_egl.h b/gst-libs/gst/vaapi/gstvaapiutils_egl.h
new file mode 100644
index 00000000..d1fd28de
--- /dev/null
+++ b/gst-libs/gst/vaapi/gstvaapiutils_egl.h
@@ -0,0 +1,238 @@
+/*
+ * gstvaapiutils_egl.h - EGL utilities
+ *
+ * Copyright (C) 2014 Intel Corporation
+ * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301
+ */
+
+#ifndef GST_VAAPI_UTILS_EGL_H
+#define GST_VAAPI_UTILS_EGL_H
+
+#include <gmodule.h>
+#include <gst/gstinfo.h>
+#include <gst/video/video-format.h>
+#include "egl_compat.h"
+#include "gstvaapiminiobject.h"
+
+GST_DEBUG_CATEGORY_EXTERN (gst_debug_vaapidisplay_egl);
+#define GST_CAT_DEFAULT gst_debug_vaapidisplay_egl
+
+typedef union egl_handle_s EglHandle;
+typedef struct egl_object_s EglObject;
+typedef struct egl_object_class_s EglObjectClass;
+typedef struct egl_vtable_s EglVTable;
+typedef struct egl_display_s EglDisplay;
+typedef struct egl_config_s EglConfig;
+typedef struct egl_context_state_s EglContextState;
+typedef struct egl_context_s EglContext;
+typedef struct egl_surface_s EglSurface;
+typedef struct egl_program_s EglProgram;
+
+#define EGL_PROTO_BEGIN(NAME, TYPE, EXTENSION) \
+ typedef TYPE (*GL_PROTO_GEN_CONCAT3(Egl,NAME,Proc))
+#define EGL_PROTO_END() ;
+#define GL_PROTO_BEGIN(NAME, TYPE, EXTENSION) \
+ typedef TYPE (*GL_PROTO_GEN_CONCAT3(Gl,NAME,Proc))
+#define GL_PROTO_ARG_LIST(...) (__VA_ARGS__)
+#define GL_PROTO_ARG(NAME, TYPE) TYPE NAME
+#define GL_PROTO_END() ;
+#include "egl_vtable.h"
+
+union egl_handle_s
+{
+ gpointer p;
+ guintptr u;
+ gintptr i;
+};
+
+struct egl_object_s
+{
+ /*< private >*/
+ GstVaapiMiniObject parent_instance;
+
+ EglHandle handle;
+ guint is_wrapped:1;
+ guint is_valid:1;
+};
+
+struct egl_object_class_s
+{
+ /*< private >*/
+ GstVaapiMiniObjectClass parent_class;
+};
+
+struct egl_vtable_s
+{
+ EglObject base;
+
+ gchar **egl_extensions;
+ guint num_egl_symbols;
+ gchar **gl_extensions;
+ guint num_gl_symbols;
+ guint gles_version;
+
+#define EGL_PROTO_BEGIN(NAME, TYPE, EXTENSION) \
+ GL_PROTO_BEGIN_I(NAME, TYPE, EXTENSION, Egl, egl)
+#define GL_PROTO_BEGIN(NAME, TYPE, EXTENSION) \
+ GL_PROTO_BEGIN_I(NAME, TYPE, EXTENSION, Gl, gl)
+#define GL_PROTO_BEGIN_I(NAME, TYPE, EXTENSION, Prefix, prefix) \
+ GL_PROTO_GEN_CONCAT3(Prefix,NAME,Proc) GL_PROTO_GEN_CONCAT(prefix,NAME);
+#include "egl_vtable.h"
+
+#define EGL_DEFINE_EXTENSION(EXTENSION) \
+ GL_DEFINE_EXTENSION_I(EXTENSION, EGL)
+#define GL_DEFINE_EXTENSION(EXTENSION) \
+ GL_DEFINE_EXTENSION_I(EXTENSION, GL)
+#define GL_DEFINE_EXTENSION_I(EXTENSION, PREFIX) \
+ guint GL_PROTO_GEN_CONCAT4(has_,PREFIX,_,EXTENSION);
+#include "egl_vtable.h"
+};
+
+struct egl_display_s
+{
+ EglObject base;
+
+ gchar *gl_vendor_string;
+ gchar *gl_version_string;
+ gchar *gl_apis_string;
+ guint gl_apis; /* EGL_*_BIT mask */
+
+ GMutex mutex;
+ GThread *gl_thread;
+ GCond gl_thread_ready;
+ volatile gboolean gl_thread_cancel;
+ GAsyncQueue *gl_queue;
+};
+
+struct egl_config_s
+{
+ EglObject base;
+
+ EglDisplay *display;
+ guint gl_api; /* EGL_*_API value */
+ guint gles_version;
+ gint config_id;
+ gint visual_id;
+};
+
+typedef void (*EglContextRunFunc) (gpointer args);
+
+struct egl_context_state_s
+{
+ EGLDisplay display;
+ EGLContext context;
+ EGLSurface read_surface;
+ EGLSurface draw_surface;
+};
+
+struct egl_context_s
+{
+ EglObject base;
+
+ EglVTable *vtable;
+ EglDisplay *display;
+ EglConfig *config;
+ EglSurface *read_surface;
+ EglSurface *draw_surface;
+};
+
+struct egl_surface_s
+{
+ EglObject base;
+
+ EglDisplay *display;
+};
+
+/* Defined to the maximum number of uniforms for a shader program */
+#define EGL_MAX_UNIFORMS 16
+
+struct egl_program_s
+{
+ EglObject base;
+
+ EglVTable *vtable;
+ guint frag_shader;
+ guint vert_shader;
+ gint uniforms[EGL_MAX_UNIFORMS];
+};
+
+#define egl_object_ref(obj) \
+ ((gpointer)gst_vaapi_mini_object_ref ((GstVaapiMiniObject *)(obj)))
+#define egl_object_unref(obj) \
+ gst_vaapi_mini_object_unref ((GstVaapiMiniObject *)(obj))
+#define egl_object_replace(old_obj_ptr, new_obj) \
+ gst_vaapi_mini_object_replace ((GstVaapiMiniObject **)(old_obj_ptr), \
+ (GstVaapiMiniObject *)(new_obj))
+
+G_GNUC_INTERNAL
+EglDisplay *
+egl_display_new (gpointer native_display);
+
+G_GNUC_INTERNAL
+EglDisplay *
+egl_display_new_wrapped (EGLDisplay gl_display);
+
+G_GNUC_INTERNAL
+EglConfig *
+egl_config_new (EglDisplay * display, guint gles_version,
+ GstVideoFormat format);
+
+G_GNUC_INTERNAL
+EglConfig *
+egl_config_new_with_attribs (EglDisplay * display, const EGLint * attribs);
+
+G_GNUC_INTERNAL
+EglContext *
+egl_context_new (EglDisplay * display, EglConfig * config, EglContext * parent);
+
+G_GNUC_INTERNAL
+EglContext *
+egl_context_new_wrapped (EglDisplay * display, EGLContext gl_context);
+
+G_GNUC_INTERNAL
+EglVTable *
+egl_context_get_vtable (EglContext * ctx, gboolean need_gl_symbols);
+
+G_GNUC_INTERNAL
+gboolean
+egl_context_set_current (EglContext * ctx, gboolean activate,
+ EglContextState * old_cs);
+
+G_GNUC_INTERNAL
+gboolean
+egl_context_run (EglContext * ctx, EglContextRunFunc func, gpointer args);
+
+G_GNUC_INTERNAL
+EglProgram *
+egl_program_new (EglContext * ctx, const gchar * frag_shader_text,
+ const gchar * vert_shader_text);
+
+G_GNUC_INTERNAL
+guint
+egl_create_texture (EglContext * ctx, guint target, guint format,
+ guint width, guint height);
+
+G_GNUC_INTERNAL
+void
+egl_destroy_texture (EglContext * ctx, guint texture);
+
+G_GNUC_INTERNAL
+void
+egl_matrix_set_identity (gfloat m[16]);
+
+#endif /* GST_VAAPI_UTILS_EGL_H */
diff --git a/gst-libs/gst/vaapi/ogl_compat.h b/gst-libs/gst/vaapi/ogl_compat.h
new file mode 100644
index 00000000..2fa40e74
--- /dev/null
+++ b/gst-libs/gst/vaapi/ogl_compat.h
@@ -0,0 +1,104 @@
+/*
+ * ogl_compat.h - OpenGL compatiliby layer
+ *
+ * Copyright (C) 2014 Intel Corporation
+ * Author: Gwenole Beauchesne <gwenole.beauchesne@intel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301
+ */
+
+#ifndef OGL_COMPAT_H
+#define OGL_COMPAT_H
+
+typedef void GLvoid;
+typedef char GLchar;
+typedef unsigned char GLubyte;
+typedef unsigned char GLboolean;
+typedef int GLint;
+typedef unsigned int GLuint;
+typedef int GLsizei;
+typedef float GLfloat;
+typedef double GLdouble;
+typedef GLuint GLenum;
+typedef GLuint GLbitfield;
+typedef GLfloat GLclampf;
+
+#define GL_VENDOR 0x1F00
+#define GL_RENDERER 0x1F01
+#define GL_VERSION 0x1F02
+#define GL_EXTENSIONS 0x1F03
+#define GL_NEAREST 0x2600
+#define GL_LINEAR 0x2601
+
+#define GL_DEPTH_BUFFER_BIT 0x00000100
+#define GL_COLOR_BUFFER_BIT 0x00004000
+#define GL_FALSE 0
+#define GL_TRUE 1
+#define GL_NONE 0
+
+#define GL_BLEND 0x0BE2
+#define GL_DEPTH_TEST 0x0B71
+
+#define GL_TEXTURE0 0x84C0
+#define GL_TEXTURE1 0x84C1
+#define GL_TEXTURE2 0x84C2
+#define GL_TEXTURE3 0x84C3
+#define GL_TEXTURE_2D 0x0DE1
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#define GL_TEXTURE_MAG_FILTER 0x2800
+#define GL_TEXTURE_MIN_FILTER 0x2801
+#define GL_TEXTURE_WRAP_S 0x2802
+#define GL_TEXTURE_WRAP_T 0x2803
+
+#define GL_UNPACK_ALIGNMENT 0x0cf5
+
+#define GL_TRIANGLE_FAN 0x0006
+
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_INT 0x1404
+#define GL_UNSIGNED_INT 0x1405
+#define GL_FLOAT 0x1406
+
+#define GL_ALPHA 0x1906
+#define GL_RGB 0x1907
+#define GL_RGBA 0x1908
+#define GL_LUMINANCE 0x1909
+#define GL_LUMINANCE_ALPHA 0x190A
+
+#define GL_REPEAT 0x2901
+#define GL_CLAMP_TO_EDGE 0x812F
+
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_TEXTURE_COORD_ARRAY 0x8078
+
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_INFO_LOG_LENGTH 0x8B84
+
+#define GL_BGRA_EXT 0x80e1
+#ifndef GL_R8
+#define GL_R8 GL_R8_EXT
+#endif
+#ifndef GL_RG8
+#define GL_RG8 GL_RG8_EXT
+#endif
+
+#endif /* OGL_COMPAT_H */