diff options
author | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2015-02-20 15:27:53 +0100 |
---|---|---|
committer | Gwenole Beauchesne <gwenole.beauchesne@intel.com> | 2015-02-24 15:20:03 +0100 |
commit | 1e7c4db5a740df7b68547c091148dc27f80388d7 (patch) | |
tree | 1e7519e291f43e607349308d209039a3e8686dbe /gst-libs | |
parent | 91c5d948be120c256245724fbd7e54fd38e2e49e (diff) | |
download | gst-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.am | 61 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/egl_compat.h | 39 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/egl_vtable.h | 785 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapidisplay.c | 7 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapidisplay.h | 2 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapidisplay_egl.c | 582 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapidisplay_egl.h | 55 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapidisplay_egl_priv.h | 101 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapiutils_egl.c | 1342 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/gstvaapiutils_egl.h | 238 | ||||
-rw-r--r-- | gst-libs/gst/vaapi/ogl_compat.h | 104 |
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, ¶ms); +} + +/** + * 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, ¶ms); +} + +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 */ |