[727/906] egl: Refactor EGL logic into a helper object

This commit is contained in:
Sebastian Dröge 2013-07-03 09:12:39 +02:00 committed by Tim-Philipp Müller
parent ac1a2297f5
commit 92c66f55bc
7 changed files with 403 additions and 402 deletions

View file

@ -3,6 +3,8 @@ lib_LTLIBRARIES = libgstgl-@GST_API_VERSION@.la
SUBDIRS = SUBDIRS =
noinst_HEADERS =
libgstgl_@GST_API_VERSION@_la_SOURCES = \ libgstgl_@GST_API_VERSION@_la_SOURCES = \
gstgldisplay.c \ gstgldisplay.c \
gstglmemory.c \ gstglmemory.c \
@ -46,6 +48,22 @@ SUBDIRS += wayland
libgstgl_@GST_API_VERSION@_la_LIBADD += wayland/libgstgl-wayland.la libgstgl_@GST_API_VERSION@_la_LIBADD += wayland/libgstgl-wayland.la
endif endif
if USE_EGL
if HAVE_WINDOW_WAYLAND
libgstgl_@GST_API_VERSION@_la_SOURCES += gstglegl.c
noinst_HEADERS += gstglegl.h
endif
if !HAVE_WINDOW_WAYLAND
if HAVE_WINDOW_X11
libgstgl_@GST_API_VERSION@_la_SOURCES += gstglegl.c
noinst_HEADERS += gstglegl.h
endif
endif
endif
libgstgl_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl libgstgl_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/gl
libgstgl_@GST_API_VERSION@include_HEADERS = \ libgstgl_@GST_API_VERSION@include_HEADERS = \
gstglwindow.h \ gstglwindow.h \

279
gst-libs/gst/gl/gstglegl.c Normal file
View file

@ -0,0 +1,279 @@
/*
* GStreamer
* Copyright (C) 2013 Sebastian Dröge <slomo@circular-chaos.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "gstglegl.h"
static const gchar *
gst_gl_egl_get_error_string (void)
{
EGLint nErr = eglGetError ();
switch (nErr) {
case EGL_SUCCESS:
return "EGL_SUCCESS";
case EGL_BAD_DISPLAY:
return "EGL_BAD_DISPLAY";
case EGL_NOT_INITIALIZED:
return "EGL_NOT_INITIALIZED";
case EGL_BAD_ACCESS:
return "EGL_BAD_ACCESS";
case EGL_BAD_ALLOC:
return "EGL_BAD_ALLOC";
case EGL_BAD_ATTRIBUTE:
return "EGL_BAD_ATTRIBUTE";
case EGL_BAD_CONFIG:
return "EGL_BAD_CONFIG";
case EGL_BAD_CONTEXT:
return "EGL_BAD_CONTEXT";
case EGL_BAD_CURRENT_SURFACE:
return "EGL_BAD_CURRENT_SURFACE";
case EGL_BAD_MATCH:
return "EGL_BAD_MATCH";
case EGL_BAD_NATIVE_PIXMAP:
return "EGL_BAD_NATIVE_PIXMAP";
case EGL_BAD_NATIVE_WINDOW:
return "EGL_BAD_NATIVE_WINDOW";
case EGL_BAD_PARAMETER:
return "EGL_BAD_PARAMETER";
case EGL_BAD_SURFACE:
return "EGL_BAD_SURFACE";
default:
return "unknown";
}
}
static gboolean
gst_gl_egl_choose_config (GstGLEGL * egl, GError ** error)
{
EGLint numConfigs;
gint i = 0;
EGLint config_attrib[20];
config_attrib[i++] = EGL_SURFACE_TYPE;
config_attrib[i++] = EGL_WINDOW_BIT;
config_attrib[i++] = EGL_RENDERABLE_TYPE;
if (egl->gl_api & GST_GL_API_GLES2)
config_attrib[i++] = EGL_OPENGL_ES2_BIT;
else
config_attrib[i++] = EGL_OPENGL_BIT;
config_attrib[i++] = EGL_DEPTH_SIZE;
config_attrib[i++] = 16;
config_attrib[i++] = EGL_NONE;
if (eglChooseConfig (egl->egl_display, config_attrib,
&egl->egl_config, 1, &numConfigs)) {
GST_INFO ("config set: %ld, %ld", (gulong) egl->egl_config,
(gulong) numConfigs);
} else {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG,
"Failed to set window configuration: %s",
gst_gl_egl_get_error_string ());
goto failure;
}
return TRUE;
failure:
return FALSE;
}
GstGLEGL *
gst_gl_egl_create_context (EGLDisplay display, EGLNativeWindowType window,
GstGLAPI gl_api, guintptr external_gl_context, GError ** error)
{
GstGLEGL *egl;
gint i = 0;
EGLint context_attrib[3];
EGLint majorVersion;
EGLint minorVersion;
egl = g_slice_new0 (GstGLEGL);
if ((gl_api & GST_GL_API_OPENGL) == GST_GL_API_NONE &&
(gl_api & GST_GL_API_GLES2) == GST_GL_API_NONE) {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_API,
"xEGL supports opengl or gles2");
goto failure;
}
egl->egl_display = display;
if (eglInitialize (egl->egl_display, &majorVersion, &minorVersion)) {
GST_INFO ("egl initialized, version: %d.%d", majorVersion, minorVersion);
} else {
g_set_error (error, GST_GL_WINDOW_ERROR,
GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE,
"Failed to initialize egl: %s", gst_gl_egl_get_error_string ());
goto failure;
}
if (gl_api & GST_GL_API_OPENGL) {
/* egl + opengl only available with EGL 1.4+ */
if (majorVersion == 1 && minorVersion <= 3) {
if ((gl_api & ~GST_GL_API_OPENGL) == GST_GL_API_NONE) {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_OLD_LIBS,
"EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
majorVersion, minorVersion);
goto failure;
} else {
GST_WARNING
("EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
majorVersion, minorVersion);
if (gl_api & GST_GL_API_GLES2) {
goto try_gles2;
} else {
g_set_error (error, GST_GL_WINDOW_ERROR,
GST_GL_WINDOW_ERROR_WRONG_CONFIG,
"Failed to choose a suitable OpenGL API");
goto failure;
}
}
}
if (!eglBindAPI (EGL_OPENGL_API)) {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED,
"Failed to bind OpenGL|ES API: %s", gst_gl_egl_get_error_string ());
goto failure;
}
egl->gl_api = GST_GL_API_OPENGL;
} else if (gl_api & GST_GL_API_GLES2) {
try_gles2:
if (!eglBindAPI (EGL_OPENGL_ES_API)) {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED,
"Failed to bind OpenGL|ES API: %s", gst_gl_egl_get_error_string ());
goto failure;
}
egl->gl_api = GST_GL_API_GLES2;
}
if (!gst_gl_egl_choose_config (egl, error)) {
g_assert (error == NULL || *error != NULL);
goto failure;
}
GST_DEBUG ("about to create gl context\n");
if (egl->gl_api & GST_GL_API_GLES2) {
context_attrib[i++] = EGL_CONTEXT_CLIENT_VERSION;
context_attrib[i++] = 2;
}
context_attrib[i++] = EGL_NONE;
egl->egl_context =
eglCreateContext (egl->egl_display, egl->egl_config,
(EGLContext) external_gl_context, context_attrib);
if (egl->egl_context != EGL_NO_CONTEXT) {
GST_INFO ("gl context created: %ld", (gulong) egl->egl_context);
} else {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT,
"Failed to create a OpenGL context: %s",
gst_gl_egl_get_error_string ());
goto failure;
}
egl->egl_surface =
eglCreateWindowSurface (egl->egl_display, egl->egl_config, window, NULL);
if (egl->egl_surface != EGL_NO_SURFACE) {
GST_INFO ("surface created");
} else {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED,
"Failed to create window surface: %s", gst_gl_egl_get_error_string ());
goto failure;
}
gst_gl_egl_activate (egl, TRUE);
return egl;
failure:
gst_gl_egl_destroy_context (egl);
return NULL;
}
void
gst_gl_egl_destroy_context (GstGLEGL * egl)
{
gst_gl_egl_activate (egl, FALSE);
if (egl->egl_surface)
eglDestroySurface (egl->egl_surface, egl->egl_display);
if (egl->egl_context)
eglDestroyContext (egl->egl_display, egl->egl_context);
if (egl->egl_display) {
eglTerminate (egl->egl_display);
eglReleaseThread ();
}
g_slice_free (GstGLEGL, egl);
}
gboolean
gst_gl_egl_activate (GstGLEGL * egl, gboolean activate)
{
gboolean result;
if (activate)
result = eglMakeCurrent (egl->egl_display, egl->egl_surface,
egl->egl_surface, egl->egl_context);
else
result = eglMakeCurrent (egl->egl_display, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
return result;
}
guintptr
gst_gl_egl_get_gl_context (GstGLEGL * egl)
{
return (guintptr) egl->egl_context;
}
void
gst_gl_egl_swap_buffers (GstGLEGL * egl)
{
eglSwapBuffers (egl->egl_display, egl->egl_surface);
}
GstGLAPI
gst_gl_egl_get_gl_api (GstGLEGL * egl)
{
return egl->gl_api;
}
gpointer
gst_gl_egl_get_proc_address (GstGLEGL * egl, const gchar * name)
{
gpointer result;
result = eglGetProcAddress (name);
return result;
}

View file

@ -0,0 +1,55 @@
/*
* GStreamer
* Copyright (C) 2013 Sebastian Dröge <slomo@circular-chaos.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef __GST_GL_EGL_H__
#define __GST_GL_EGL_H__
#include <gst/gst.h>
#include <EGL/egl.h>
#include "gstglwindow.h"
G_BEGIN_DECLS
typedef struct _GstGLEGL GstGLEGL;
struct _GstGLEGL {
EGLContext egl_context;
EGLDisplay egl_display;
EGLSurface egl_surface;
EGLConfig egl_config;
GstGLAPI gl_api;
};
GstGLEGL * gst_gl_egl_create_context (EGLDisplay display, EGLNativeWindowType window, GstGLAPI gl_api, guintptr external_gl_context, GError ** error);
void gst_gl_egl_destroy_context (GstGLEGL *egl);
gboolean gst_gl_egl_activate (GstGLEGL *egl, gboolean activate);
void gst_gl_egl_swap_buffers (GstGLEGL *egl);
guintptr gst_gl_egl_get_gl_context (GstGLEGL *egl);
GstGLAPI gst_gl_egl_get_gl_api (GstGLEGL *egl);
gpointer gst_gl_egl_get_proc_address (GstGLEGL *egl, const gchar * name);
G_END_DECLS
#endif /* __GST_GL_EGL_H__ */

View file

@ -172,8 +172,6 @@ static const struct wl_shell_surface_listener shell_surface_listener = {
static gboolean static gboolean
create_surface (GstGLWindowWaylandEGL * window_egl) create_surface (GstGLWindowWaylandEGL * window_egl)
{ {
EGLBoolean ret;
window_egl->window.surface = window_egl->window.surface =
wl_compositor_create_surface (window_egl->display.compositor); wl_compositor_create_surface (window_egl->display.compositor);
window_egl->window.shell_surface = window_egl->window.shell_surface =
@ -191,23 +189,16 @@ create_surface (GstGLWindowWaylandEGL * window_egl)
window_egl->window.native = window_egl->window.native =
wl_egl_window_create (window_egl->window.surface, wl_egl_window_create (window_egl->window.surface,
window_egl->window.window_width, window_egl->window.window_height); window_egl->window.window_width, window_egl->window.window_height);
window_egl->egl_surface =
eglCreateWindowSurface (window_egl->egl_display, window_egl->egl_config,
window_egl->window.native, NULL);
wl_shell_surface_set_title (window_egl->window.shell_surface, wl_shell_surface_set_title (window_egl->window.shell_surface,
"OpenGL Renderer"); "OpenGL Renderer");
ret =
eglMakeCurrent (window_egl->egl_display, window_egl->egl_surface,
window_egl->egl_surface, window_egl->egl_context);
wl_shell_surface_set_toplevel (window_egl->window.shell_surface); wl_shell_surface_set_toplevel (window_egl->window.shell_surface);
wl_shell_surface_set_fullscreen (window_egl->window.shell_surface, wl_shell_surface_set_fullscreen (window_egl->window.shell_surface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE, 0, NULL); WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE, 0, NULL);
return ret == EGL_TRUE; return TRUE;
} }
static void static void
@ -282,7 +273,6 @@ gst_gl_window_wayland_egl_class_init (GstGLWindowWaylandEGLClass * klass)
static void static void
gst_gl_window_wayland_egl_init (GstGLWindowWaylandEGL * window) gst_gl_window_wayland_egl_init (GstGLWindowWaylandEGL * window)
{ {
window->gl_api = GST_GL_API_NONE;
} }
/* Must be called in the gl thread */ /* Must be called in the gl thread */
@ -363,148 +353,20 @@ error:
return FALSE; return FALSE;
} }
static gboolean
_gst_gl_window_wayland_egl_choose_config (GstGLWindowWaylandEGL * window_egl,
GError ** error)
{
EGLint numConfigs;
gint i = 0;
EGLint config_attrib[20];
config_attrib[i++] = EGL_SURFACE_TYPE;
config_attrib[i++] = EGL_WINDOW_BIT;
config_attrib[i++] = EGL_RENDERABLE_TYPE;
if (window_egl->gl_api & GST_GL_API_GLES2)
config_attrib[i++] = EGL_OPENGL_ES2_BIT;
else
config_attrib[i++] = EGL_OPENGL_BIT;
config_attrib[i++] = EGL_DEPTH_SIZE;
config_attrib[i++] = 16;
config_attrib[i++] = EGL_NONE;
if (eglChooseConfig (window_egl->egl_display, config_attrib,
&window_egl->egl_config, 1, &numConfigs))
GST_INFO ("config set: %ld, %ld", (gulong) window_egl->egl_config,
(gulong) numConfigs);
else {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG,
"Failed to set window configuration: %s", WlEGLErrorString ());
goto failure;
}
return TRUE;
failure:
return FALSE;
}
gboolean gboolean
gst_gl_window_wayland_egl_create_context (GstGLWindow * window, gst_gl_window_wayland_egl_create_context (GstGLWindow * window,
GstGLAPI gl_api, guintptr external_gl_context, GError ** error) GstGLAPI gl_api, guintptr external_gl_context, GError ** error)
{ {
GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
EGLint context_attrib[3];
gint i = 0;
EGLint majorVersion;
EGLint minorVersion;
if (!_setup_wayland (window_egl, error)) if (!_setup_wayland (window_egl, error))
return FALSE; return FALSE;
window_egl->egl_display = window_egl->egl =
eglGetDisplay ((EGLNativeDisplayType) window_egl->display.display); gst_gl_egl_create_context (eglGetDisplay ((EGLNativeDisplayType)
window_egl->display.display), window_egl->window.native, gl_api,
if (eglInitialize (window_egl->egl_display, &majorVersion, &minorVersion)) external_gl_context, error);
GST_DEBUG ("egl initialized: %d.%d", majorVersion, minorVersion); if (!window_egl->egl)
else {
g_set_error (error, GST_GL_WINDOW_ERROR,
GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE,
"Failed to initialize egl: %s", WlEGLErrorString ());
goto failure; goto failure;
}
if (gl_api & GST_GL_API_OPENGL) {
/* egl + opengl only available with EGL 1.4+ */
if (majorVersion == 1 && minorVersion <= 3) {
if ((gl_api & ~GST_GL_API_OPENGL) == GST_GL_API_NONE) {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_OLD_LIBS,
"EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
majorVersion, minorVersion);
goto failure;
} else {
GST_WARNING
("EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
majorVersion, minorVersion);
if (gl_api & GST_GL_API_GLES2) {
goto try_gles2;
} else {
g_set_error (error, GST_GL_WINDOW_ERROR,
GST_GL_WINDOW_ERROR_WRONG_CONFIG,
"Failed to choose a suitable OpenGL API");
goto failure;
}
}
}
if (!eglBindAPI (EGL_OPENGL_API)) {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED,
"Failed to bind OpenGL|ES API: %s", WlEGLErrorString ());
goto failure;
}
window_egl->gl_api = GST_GL_API_OPENGL;
} else if (gl_api & GST_GL_API_GLES2) {
try_gles2:
if (!eglBindAPI (EGL_OPENGL_ES_API)) {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED,
"Failed to bind OpenGL|ES API: %s", WlEGLErrorString ());
goto failure;
}
window_egl->gl_api = GST_GL_API_GLES2;
}
if (!_gst_gl_window_wayland_egl_choose_config (window_egl, error)) {
g_assert (error == NULL || *error != NULL);
goto failure;
}
GST_DEBUG ("about to create gl context");
if (window_egl->gl_api & GST_GL_API_GLES2) {
context_attrib[i++] = EGL_CONTEXT_CLIENT_VERSION;
context_attrib[i++] = 2;
}
context_attrib[i++] = EGL_NONE;
window_egl->egl_context =
eglCreateContext (window_egl->egl_display, window_egl->egl_config,
(EGLContext) external_gl_context, context_attrib);
if (window_egl->egl_context != EGL_NO_CONTEXT)
GST_DEBUG ("gl context created: %ld", (gulong) window_egl->egl_context);
else {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT,
"Failed to create a OpenGL context: %s", WlEGLErrorString ());
goto failure;
}
create_surface (window_egl);
/* window_egl->egl_surface =
eglCreateWindowSurface (window_egl->egl_display, window_egl->config,
(EGLNativeWindowType) window_wayland_egl->internal_win_id, NULL);
if (window_egl->egl_surface != EGL_NO_SURFACE)
GST_DEBUG ("surface created: %ld", (gulong) window_egl->egl_surface);
else {
GST_DEBUG ("failed to create surface %ld, %ld, %ld, %s",
(gulong) window_egl->egl_display, (gulong) window_egl->egl_surface,
(gulong) window_egl->egl_display, WlEGLErrorString ());
goto failure;
}
*/
return TRUE; return TRUE;
@ -515,49 +377,44 @@ failure:
static void static void
gst_gl_window_wayland_egl_destroy_context (GstGLWindowWaylandEGL * window_egl) gst_gl_window_wayland_egl_destroy_context (GstGLWindowWaylandEGL * window_egl)
{ {
gst_gl_window_wayland_egl_activate (GST_GL_WINDOW (window_egl), FALSE); gst_gl_egl_activate (window_egl->egl, FALSE);
destroy_surface (window_egl); destroy_surface (window_egl);
/*
if (window_egl->egl_context) gst_gl_egl_destroy_surface (window_egl->egl);
eglDestroyContext (window_egl->egl_display, window_egl->egl_context); */
gst_gl_egl_destroy_context (window_egl->egl);
if (window_egl->egl_display) { window_egl->egl = NULL;
eglTerminate (window_egl->egl_display);
eglReleaseThread ();
}
} }
static gboolean static gboolean
gst_gl_window_wayland_egl_activate (GstGLWindow * window, gboolean activate) gst_gl_window_wayland_egl_activate (GstGLWindow * window, gboolean activate)
{ {
gboolean result;
GstGLWindowWaylandEGL *window_egl; GstGLWindowWaylandEGL *window_egl;
window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
GST_DEBUG ("activate:%s", activate ? "TRUE" : "FALSE"); return gst_gl_egl_activate (window_egl->egl, activate);
if (activate)
result = eglMakeCurrent (window_egl->egl_display, window_egl->egl_surface,
window_egl->egl_surface, window_egl->egl_context);
else
result = eglMakeCurrent (window_egl->egl_display, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
return result;
} }
static guintptr static guintptr
gst_gl_window_wayland_egl_get_gl_context (GstGLWindow * window) gst_gl_window_wayland_egl_get_gl_context (GstGLWindow * window)
{ {
return (guintptr) GST_GL_WINDOW_WAYLAND_EGL (window)->egl_context; GstGLWindowWaylandEGL *window_egl;
window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
return gst_gl_egl_get_gl_context (window_egl->egl);
} }
static GstGLAPI static GstGLAPI
gst_gl_window_wayland_egl_get_gl_api (GstGLWindow * window) gst_gl_window_wayland_egl_get_gl_api (GstGLWindow * window)
{ {
return GST_GL_WINDOW_WAYLAND_EGL (window)->gl_api; GstGLWindowWaylandEGL *window_egl;
window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
return gst_gl_egl_get_gl_api (window_egl->egl);
} }
static void static void
@ -565,7 +422,7 @@ gst_gl_window_wayland_egl_swap_buffers (GstGLWindow * window)
{ {
GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window); GstGLWindowWaylandEGL *window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
eglSwapBuffers (window_egl->egl_display, window_egl->egl_surface); gst_gl_egl_swap_buffers (window_egl->egl);
} }
static void static void
@ -716,49 +573,14 @@ static gpointer
gst_gl_window_wayland_egl_get_proc_address (GstGLWindow * window, gst_gl_window_wayland_egl_get_proc_address (GstGLWindow * window,
const gchar * name) const gchar * name)
{ {
GstGLWindowWaylandEGL *window_egl;
gpointer result; gpointer result;
if (!(result = eglGetProcAddress (name))) { window_egl = GST_GL_WINDOW_WAYLAND_EGL (window);
if (!(result = gst_gl_egl_get_proc_address (window_egl->egl, name))) {
result = gst_gl_window_default_get_proc_address (window, name); result = gst_gl_window_default_get_proc_address (window, name);
} }
return result; return result;
} }
const gchar *
WlEGLErrorString ()
{
EGLint nErr = eglGetError ();
switch (nErr) {
case EGL_SUCCESS:
return "EGL_SUCCESS";
case EGL_BAD_DISPLAY:
return "EGL_BAD_DISPLAY";
case EGL_NOT_INITIALIZED:
return "EGL_NOT_INITIALIZED";
case EGL_BAD_ACCESS:
return "EGL_BAD_ACCESS";
case EGL_BAD_ALLOC:
return "EGL_BAD_ALLOC";
case EGL_BAD_ATTRIBUTE:
return "EGL_BAD_ATTRIBUTE";
case EGL_BAD_CONFIG:
return "EGL_BAD_CONFIG";
case EGL_BAD_CONTEXT:
return "EGL_BAD_CONTEXT";
case EGL_BAD_CURRENT_SURFACE:
return "EGL_BAD_CURRENT_SURFACE";
case EGL_BAD_MATCH:
return "EGL_BAD_MATCH";
case EGL_BAD_NATIVE_PIXMAP:
return "EGL_BAD_NATIVE_PIXMAP";
case EGL_BAD_NATIVE_WINDOW:
return "EGL_BAD_NATIVE_WINDOW";
case EGL_BAD_PARAMETER:
return "EGL_BAD_PARAMETER";
case EGL_BAD_SURFACE:
return "EGL_BAD_SURFACE";
default:
return "unknown";
}
}

View file

@ -28,6 +28,7 @@
#include <EGL/egl.h> #include <EGL/egl.h>
#include "gstglwindow.h" #include "gstglwindow.h"
#include "gstglegl.h"
G_BEGIN_DECLS G_BEGIN_DECLS
@ -74,10 +75,7 @@ struct _GstGLWindowWaylandEGL {
/*< private >*/ /*< private >*/
GstGLWindow parent; GstGLWindow parent;
EGLContext egl_context; GstGLEGL *egl;
EGLDisplay egl_display;
EGLSurface egl_surface;
EGLConfig egl_config;
struct display display; struct display display;
struct window window; struct window window;
@ -86,8 +84,6 @@ struct _GstGLWindowWaylandEGL {
GMainContext *main_context; GMainContext *main_context;
GMainLoop *loop; GMainLoop *loop;
GstGLAPI gl_api;
gpointer _reserved[GST_PADDING]; gpointer _reserved[GST_PADDING];
}; };

View file

@ -107,52 +107,12 @@ gst_gl_window_x11_egl_choose_format (GstGLWindowX11 * window_x11,
return TRUE; return TRUE;
} }
static gboolean
_gst_gl_window_x11_egl_choose_config (GstGLWindowX11EGL * window_egl,
GError ** error)
{
EGLint numConfigs;
gint i = 0;
EGLint config_attrib[20];
config_attrib[i++] = EGL_SURFACE_TYPE;
config_attrib[i++] = EGL_WINDOW_BIT;
config_attrib[i++] = EGL_RENDERABLE_TYPE;
if (window_egl->gl_api & GST_GL_API_GLES2)
config_attrib[i++] = EGL_OPENGL_ES2_BIT;
else
config_attrib[i++] = EGL_OPENGL_BIT;
config_attrib[i++] = EGL_DEPTH_SIZE;
config_attrib[i++] = 16;
config_attrib[i++] = EGL_NONE;
if (eglChooseConfig (window_egl->egl_display, config_attrib,
&window_egl->egl_config, 1, &numConfigs))
GST_INFO ("config set: %ld, %ld", (gulong) window_egl->egl_config,
(gulong) numConfigs);
else {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_CONFIG,
"Failed to set window configuration: %s", X11EGLErrorString ());
goto failure;
}
return TRUE;
failure:
return FALSE;
}
static gboolean static gboolean
gst_gl_window_x11_egl_create_context (GstGLWindowX11 * window_x11, gst_gl_window_x11_egl_create_context (GstGLWindowX11 * window_x11,
GstGLAPI gl_api, guintptr external_gl_context, GError ** error) GstGLAPI gl_api, guintptr external_gl_context, GError ** error)
{ {
GstGLWindowX11EGL *window_egl; GstGLWindowX11EGL *window_egl;
gint i = 0;
EGLint context_attrib[3];
EGLint majorVersion;
EGLint minorVersion;
if ((gl_api & GST_GL_API_OPENGL) == GST_GL_API_NONE && if ((gl_api & GST_GL_API_OPENGL) == GST_GL_API_NONE &&
(gl_api & GST_GL_API_GLES2) == GST_GL_API_NONE) { (gl_api & GST_GL_API_GLES2) == GST_GL_API_NONE) {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_API, g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_WRONG_API,
@ -162,94 +122,13 @@ gst_gl_window_x11_egl_create_context (GstGLWindowX11 * window_x11,
window_egl = GST_GL_WINDOW_X11_EGL (window_x11); window_egl = GST_GL_WINDOW_X11_EGL (window_x11);
window_egl->egl_display = window_egl->egl =
eglGetDisplay ((EGLNativeDisplayType) window_x11->device); gst_gl_egl_create_context (eglGetDisplay ((EGLNativeDisplayType)
window_x11->device),
if (eglInitialize (window_egl->egl_display, &majorVersion, &minorVersion)) (EGLNativeWindowType) window_x11->internal_win_id, gl_api,
GST_INFO ("egl initialized, version: %d.%d", majorVersion, minorVersion); external_gl_context, error);
else { if (!window_egl->egl)
g_set_error (error, GST_GL_WINDOW_ERROR,
GST_GL_WINDOW_ERROR_RESOURCE_UNAVAILABLE,
"Failed to initialize egl: %s", X11EGLErrorString ());
goto failure; goto failure;
}
if (gl_api & GST_GL_API_OPENGL) {
/* egl + opengl only available with EGL 1.4+ */
if (majorVersion == 1 && minorVersion <= 3) {
if ((gl_api & ~GST_GL_API_OPENGL) == GST_GL_API_NONE) {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_OLD_LIBS,
"EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
majorVersion, minorVersion);
goto failure;
} else {
GST_WARNING
("EGL version (%i.%i) too old for OpenGL support, (needed at least 1.4)",
majorVersion, minorVersion);
if (gl_api & GST_GL_API_GLES2) {
goto try_gles2;
} else {
g_set_error (error, GST_GL_WINDOW_ERROR,
GST_GL_WINDOW_ERROR_WRONG_CONFIG,
"Failed to choose a suitable OpenGL API");
goto failure;
}
}
}
if (!eglBindAPI (EGL_OPENGL_API)) {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED,
"Failed to bind OpenGL|ES API: %s", X11EGLErrorString ());
goto failure;
}
window_egl->gl_api = GST_GL_API_OPENGL;
} else if (gl_api & GST_GL_API_GLES2) {
try_gles2:
if (!eglBindAPI (EGL_OPENGL_ES_API)) {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED,
"Failed to bind OpenGL|ES API: %s", X11EGLErrorString ());
goto failure;
}
window_egl->gl_api = GST_GL_API_GLES2;
}
if (!_gst_gl_window_x11_egl_choose_config (window_egl, error)) {
g_assert (error == NULL || *error != NULL);
goto failure;
}
window_egl->egl_surface =
eglCreateWindowSurface (window_egl->egl_display, window_egl->egl_config,
(EGLNativeWindowType) window_x11->internal_win_id, NULL);
if (window_egl->egl_surface != EGL_NO_SURFACE)
GST_INFO ("surface created");
else {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_FAILED,
"Failed to create window surface: %s", X11EGLErrorString ());
goto failure;
}
GST_DEBUG ("about to create gl context\n");
if (window_egl->gl_api & GST_GL_API_GLES2) {
context_attrib[i++] = EGL_CONTEXT_CLIENT_VERSION;
context_attrib[i++] = 2;
}
context_attrib[i++] = EGL_NONE;
window_egl->egl_context =
eglCreateContext (window_egl->egl_display, window_egl->egl_config,
(EGLContext) external_gl_context, context_attrib);
if (window_egl->egl_context != EGL_NO_CONTEXT)
GST_INFO ("gl context created: %ld", (gulong) window_egl->egl_context);
else {
g_set_error (error, GST_GL_WINDOW_ERROR, GST_GL_WINDOW_ERROR_CREATE_CONTEXT,
"Failed to create a OpenGL context: %s", X11EGLErrorString ());
goto failure;
}
return TRUE; return TRUE;
@ -264,35 +143,28 @@ gst_gl_window_x11_egl_destroy_context (GstGLWindowX11 * window_x11)
window_egl = GST_GL_WINDOW_X11_EGL (window_x11); window_egl = GST_GL_WINDOW_X11_EGL (window_x11);
if (window_egl->egl_context) gst_gl_egl_destroy_context (window_egl->egl);
eglDestroyContext (window_x11->device, window_egl->egl_context); window_egl->egl = NULL;
if (window_x11->device)
eglTerminate (window_x11->device);
} }
static gboolean static gboolean
gst_gl_window_x11_egl_activate (GstGLWindowX11 * window_x11, gboolean activate) gst_gl_window_x11_egl_activate (GstGLWindowX11 * window_x11, gboolean activate)
{ {
gboolean result;
GstGLWindowX11EGL *window_egl; GstGLWindowX11EGL *window_egl;
window_egl = GST_GL_WINDOW_X11_EGL (window_x11); window_egl = GST_GL_WINDOW_X11_EGL (window_x11);
if (activate) return gst_gl_egl_activate (window_egl->egl, activate);
result = eglMakeCurrent (window_egl->egl_display, window_egl->egl_surface,
window_egl->egl_surface, window_egl->egl_context);
else
result = eglMakeCurrent (window_egl->egl_display, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
return result;
} }
static guintptr static guintptr
gst_gl_window_x11_egl_get_gl_context (GstGLWindowX11 * window_x11) gst_gl_window_x11_egl_get_gl_context (GstGLWindowX11 * window_x11)
{ {
return (guintptr) GST_GL_WINDOW_X11_EGL (window_x11)->egl_context; GstGLWindowX11EGL *window_egl;
window_egl = GST_GL_WINDOW_X11_EGL (window_x11);
return gst_gl_egl_get_gl_context (window_egl->egl);
} }
static void static void
@ -300,7 +172,7 @@ gst_gl_window_x11_egl_swap_buffers (GstGLWindowX11 * window_x11)
{ {
GstGLWindowX11EGL *window_egl = GST_GL_WINDOW_X11_EGL (window_x11); GstGLWindowX11EGL *window_egl = GST_GL_WINDOW_X11_EGL (window_x11);
eglSwapBuffers (window_egl->egl_display, window_egl->egl_surface); gst_gl_egl_swap_buffers (window_egl->egl);
} }
GstGLAPI GstGLAPI
@ -308,57 +180,20 @@ gst_gl_window_x11_egl_get_gl_api (GstGLWindow * window)
{ {
GstGLWindowX11EGL *window_egl = GST_GL_WINDOW_X11_EGL (window); GstGLWindowX11EGL *window_egl = GST_GL_WINDOW_X11_EGL (window);
return window_egl->gl_api ? window_egl-> return window_egl->egl ? gst_gl_egl_get_gl_api (window_egl->
gl_api : GST_GL_API_GLES2 | GST_GL_API_OPENGL; egl) : GST_GL_API_GLES2 | GST_GL_API_OPENGL;
} }
static gpointer static gpointer
gst_gl_window_x11_egl_get_proc_address (GstGLWindow * window, gst_gl_window_x11_egl_get_proc_address (GstGLWindow * window,
const gchar * name) const gchar * name)
{ {
GstGLWindowX11EGL *window_egl = GST_GL_WINDOW_X11_EGL (window);
gpointer result; gpointer result;
if (!(result = eglGetProcAddress (name))) { if (!(result = gst_gl_egl_get_proc_address (window_egl->egl, name))) {
result = gst_gl_window_default_get_proc_address (window, name); result = gst_gl_window_default_get_proc_address (window, name);
} }
return result; return result;
} }
const gchar *
X11EGLErrorString ()
{
EGLint nErr = eglGetError ();
switch (nErr) {
case EGL_SUCCESS:
return "EGL_SUCCESS";
case EGL_BAD_DISPLAY:
return "EGL_BAD_DISPLAY";
case EGL_NOT_INITIALIZED:
return "EGL_NOT_INITIALIZED";
case EGL_BAD_ACCESS:
return "EGL_BAD_ACCESS";
case EGL_BAD_ALLOC:
return "EGL_BAD_ALLOC";
case EGL_BAD_ATTRIBUTE:
return "EGL_BAD_ATTRIBUTE";
case EGL_BAD_CONFIG:
return "EGL_BAD_CONFIG";
case EGL_BAD_CONTEXT:
return "EGL_BAD_CONTEXT";
case EGL_BAD_CURRENT_SURFACE:
return "EGL_BAD_CURRENT_SURFACE";
case EGL_BAD_MATCH:
return "EGL_BAD_MATCH";
case EGL_BAD_NATIVE_PIXMAP:
return "EGL_BAD_NATIVE_PIXMAP";
case EGL_BAD_NATIVE_WINDOW:
return "EGL_BAD_NATIVE_WINDOW";
case EGL_BAD_PARAMETER:
return "EGL_BAD_PARAMETER";
case EGL_BAD_SURFACE:
return "EGL_BAD_SURFACE";
default:
return "unknown";
}
}

View file

@ -22,6 +22,7 @@
#define __GST_GL_WINDOW_X11_EGL_H__ #define __GST_GL_WINDOW_X11_EGL_H__
#include "gstglwindow_x11.h" #include "gstglwindow_x11.h"
#include "gstglegl.h"
#include <EGL/egl.h> #include <EGL/egl.h>
@ -41,12 +42,7 @@ struct _GstGLWindowX11EGL {
/*< private >*/ /*< private >*/
GstGLWindowX11 parent; GstGLWindowX11 parent;
EGLContext egl_context; GstGLEGL *egl;
EGLDisplay egl_display;
EGLSurface egl_surface;
EGLConfig egl_config;
GstGLAPI gl_api;
gpointer _reserved[GST_PADDING]; gpointer _reserved[GST_PADDING];
}; };