summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago Santos <thiago.sousa.santos@collabora.com>2013-03-13 13:12:50 -0300
committerThiago Santos <thiago.sousa.santos@collabora.com>2013-04-16 16:08:50 -0300
commitf0bd8598f33bd9fd5e65d0e9a8e6a6ce80f63d33 (patch)
tree77dcbf2619e213f07edb392cbaf7d30829f10200
parent554108df935ec6f83ab85d30b68b218a84501af3 (diff)
downloadgstreamer-plugins-bad-f0bd8598f33bd9fd5e65d0e9a8e6a6ce80f63d33.tar.gz
eglglessink: split egl implementation for EAGL x EGL differences
-rw-r--r--ext/eglgles/Makefile.am8
-rw-r--r--ext/eglgles/gstegladaptation.c395
-rw-r--r--ext/eglgles/gstegladaptation.h105
-rw-r--r--ext/eglgles/gstegladaptation_ios.m260
-rw-r--r--ext/eglgles/gstegladaptation_pc.c364
-rw-r--r--ext/eglgles/gsteglglessink.c260
-rw-r--r--ext/eglgles/gsteglglessink.h1
7 files changed, 898 insertions, 495 deletions
diff --git a/ext/eglgles/Makefile.am b/ext/eglgles/Makefile.am
index 229b82c2d..9d50f949a 100644
--- a/ext/eglgles/Makefile.am
+++ b/ext/eglgles/Makefile.am
@@ -1,6 +1,12 @@
plugin_LTLIBRARIES = libgsteglglessink.la
-libgsteglglessink_la_SOURCES = gsteglglessink.c video_platform_wrapper.c gstegladaptation.c
+if HAVE_IOS
+DISTRO_SRC = gstegladaptation_ios.m
+else
+DISTRO_SRC = gstegladaptation_pc.c
+endif
+
+libgsteglglessink_la_SOURCES = gsteglglessink.c video_platform_wrapper.c gstegladaptation.c $(DISTRO_SRC)
libgsteglglessink_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) \
diff --git a/ext/eglgles/gstegladaptation.c b/ext/eglgles/gstegladaptation.c
index db6357d04..e075ea9f5 100644
--- a/ext/eglgles/gstegladaptation.c
+++ b/ext/eglgles/gstegladaptation.c
@@ -45,19 +45,6 @@
#include <gst/video/video.h>
#include "gstegladaptation.h"
-/* Some EGL implementations are reporting wrong
- * values for the display's EGL_PIXEL_ASPECT_RATIO.
- * They are required by the khronos specs to report
- * this value as w/h * EGL_DISPLAY_SCALING (Which is
- * a constant with value 10000) but at least the
- * Galaxy SIII (Android) is reporting just 1 when
- * w = h. We use these two to bound returned values to
- * sanity.
- */
-#define EGL_SANE_DAR_MIN ((EGL_DISPLAY_SCALING)/10)
-#define EGL_SANE_DAR_MAX ((EGL_DISPLAY_SCALING)*10)
-
-
/* GLESv2 GLSL Shaders
*
* OpenGL ES Standard does not mandate YUV support. This is
@@ -212,35 +199,6 @@ static const char *frag_NV12_NV21_prog = {
};
/* *INDENT-ON* */
-/* will probably move elsewhere */
-static const EGLint eglglessink_RGBA8888_attribs[] = {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_NONE
-};
-
-static const EGLint eglglessink_RGB888_attribs[] = {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_NONE
-};
-
-static const EGLint eglglessink_RGB565_attribs[] = {
- EGL_RED_SIZE, 5,
- EGL_GREEN_SIZE, 6,
- EGL_BLUE_SIZE, 5,
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_NONE
-};
-
static gboolean
create_shader_program (GstEglAdaptationContext * ctx, GLuint * prog,
GLuint * vert, GLuint * frag, const gchar * vert_text,
@@ -337,62 +295,6 @@ HANDLE_ERROR:
}
-gboolean
-gst_egl_adaptation_init_display (GstEglAdaptationContext * ctx)
-{
- EGLDisplay display;
- GST_DEBUG_OBJECT (ctx->element, "Enter EGL initial configuration");
-
-#ifdef USE_EGL_RPI
- /* See https://github.com/raspberrypi/firmware/issues/99 */
- if (!eglMakeCurrent ((EGLDisplay) 1, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT)) {
- got_egl_error ("eglMakeCurrent");
- GST_ERROR_OBJECT (ctx->element, "Couldn't unbind context");
- return FALSE;
- }
-#endif
-
- display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
- if (display == EGL_NO_DISPLAY) {
- GST_ERROR_OBJECT (ctx->element, "Could not get EGL display connection");
- goto HANDLE_ERROR; /* No EGL error is set by eglGetDisplay() */
- }
- ctx->eglglesctx.display = display;
-
- if (!eglInitialize (display,
- &ctx->eglglesctx.egl_major,
- &ctx->eglglesctx.egl_minor)) {
- got_egl_error ("eglInitialize");
- GST_ERROR_OBJECT (ctx->element, "Could not init EGL display connection");
- goto HANDLE_EGL_ERROR;
- }
-
- /* Check against required EGL version
- * XXX: Need to review the version requirement in terms of the needed API
- */
- if (ctx->eglglesctx.egl_major < GST_EGLGLESSINK_EGL_MIN_VERSION) {
- GST_ERROR_OBJECT (ctx->element, "EGL v%d needed, but you only have v%d.%d",
- GST_EGLGLESSINK_EGL_MIN_VERSION, ctx->eglglesctx.egl_major,
- ctx->eglglesctx.egl_minor);
- goto HANDLE_ERROR;
- }
-
- GST_INFO_OBJECT (ctx->element, "System reports supported EGL version v%d.%d",
- ctx->eglglesctx.egl_major, ctx->eglglesctx.egl_minor);
-
- eglBindAPI (EGL_OPENGL_ES_API);
-
- return TRUE;
-
- /* Errors */
-HANDLE_EGL_ERROR:
- GST_ERROR_OBJECT (ctx->element, "EGL call returned error %x", eglGetError ());
-HANDLE_ERROR:
- GST_ERROR_OBJECT (ctx->element, "Couldn't setup window/surface from handle");
- return FALSE;
-}
-
GstEglAdaptationContext *
gst_egl_adaptation_context_new (GstElement * element)
{
@@ -427,12 +329,9 @@ got_egl_error (const char *wtf)
gboolean
gst_egl_adaptation_choose_config (GstEglAdaptationContext * ctx)
{
- EGLint con_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
- GLint egl_configs;
+ gint egl_configs;
- if ((eglChooseConfig (ctx->eglglesctx.display,
- eglglessink_RGBA8888_attribs,
- &ctx->eglglesctx.config, 1, &egl_configs)) == EGL_FALSE) {
+ if (!_gst_egl_choose_config (ctx, FALSE, &egl_configs)) {
got_egl_error ("eglChooseConfig");
GST_ERROR_OBJECT (ctx->element, "eglChooseConfig failed");
goto HANDLE_EGL_ERROR;
@@ -444,18 +343,11 @@ gst_egl_adaptation_choose_config (GstEglAdaptationContext * ctx)
goto HANDLE_ERROR;
}
- ctx->eglglesctx.eglcontext =
- eglCreateContext (ctx->eglglesctx.display,
- ctx->eglglesctx.config, EGL_NO_CONTEXT, con_attribs);
-
- if (ctx->eglglesctx.eglcontext == EGL_NO_CONTEXT) {
+ if (!gst_egl_adaptation_create_egl_context (ctx)) {
GST_ERROR_OBJECT (ctx->element, "Error getting context, eglCreateContext");
goto HANDLE_EGL_ERROR;
}
- GST_DEBUG_OBJECT (ctx->element, "EGL Context: %p",
- ctx->eglglesctx.eglcontext);
-
return TRUE;
/* Errors */
@@ -470,7 +362,6 @@ gint gst_egl_adaptation_context_fill_supported_fbuffer_configs
(GstEglAdaptationContext * ctx, GstCaps ** ret_caps)
{
gboolean ret = FALSE;
- EGLint cfg_number;
GstCaps *caps;
GST_DEBUG_OBJECT (ctx->element,
@@ -479,8 +370,7 @@ gint gst_egl_adaptation_context_fill_supported_fbuffer_configs
/* Init supported format/caps list */
caps = gst_caps_new_empty ();
- if (eglChooseConfig (ctx->eglglesctx.display,
- eglglessink_RGBA8888_attribs, NULL, 1, &cfg_number) != EGL_FALSE) {
+ if (_gst_egl_choose_config (ctx, TRUE, NULL)) {
gst_caps_append (caps,
gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGBA));
gst_caps_append (caps,
@@ -533,45 +423,6 @@ gint gst_egl_adaptation_context_fill_supported_fbuffer_configs
return ret;
}
-gboolean
-gst_egl_adaptation_context_make_current (GstEglAdaptationContext * ctx,
- gboolean bind)
-{
- g_assert (ctx->eglglesctx.display != NULL);
-
- if (bind && ctx->eglglesctx.surface &&
- ctx->eglglesctx.eglcontext) {
- EGLContext *cur_ctx = eglGetCurrentContext ();
-
- if (cur_ctx == ctx->eglglesctx.eglcontext) {
- GST_DEBUG_OBJECT (ctx->element,
- "Already attached the context to thread %p", g_thread_self ());
- return TRUE;
- }
-
- GST_DEBUG_OBJECT (ctx->element, "Attaching context to thread %p",
- g_thread_self ());
- if (!eglMakeCurrent (ctx->eglglesctx.display,
- ctx->eglglesctx.surface, ctx->eglglesctx.surface,
- ctx->eglglesctx.eglcontext)) {
- got_egl_error ("eglMakeCurrent");
- GST_ERROR_OBJECT (ctx->element, "Couldn't bind context");
- return FALSE;
- }
- } else {
- GST_DEBUG_OBJECT (ctx->element, "Detaching context from thread %p",
- g_thread_self ());
- if (!eglMakeCurrent (ctx->eglglesctx.display, EGL_NO_SURFACE,
- EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
- got_egl_error ("eglMakeCurrent");
- GST_ERROR_OBJECT (ctx->element, "Couldn't unbind context");
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
void
gst_egl_adaptation_context_cleanup (GstEglAdaptationContext * ctx)
{
@@ -580,144 +431,58 @@ gst_egl_adaptation_context_cleanup (GstEglAdaptationContext * ctx)
glUseProgram (0);
if (ctx->have_vbo) {
- glDeleteBuffers (1, &ctx->eglglesctx.position_buffer);
- glDeleteBuffers (1, &ctx->eglglesctx.index_buffer);
+ glDeleteBuffers (1, &ctx->position_buffer);
+ glDeleteBuffers (1, &ctx->index_buffer);
ctx->have_vbo = FALSE;
}
if (ctx->have_texture) {
- glDeleteTextures (ctx->eglglesctx.n_textures,
- ctx->eglglesctx.texture);
+ glDeleteTextures (ctx->n_textures, ctx->texture);
ctx->have_texture = FALSE;
- ctx->eglglesctx.n_textures = 0;
+ ctx->n_textures = 0;
}
for (i = 0; i < 2; i++) {
- if (ctx->eglglesctx.glslprogram[i]) {
- glDetachShader (ctx->eglglesctx.glslprogram[i],
- ctx->eglglesctx.fragshader[i]);
- glDetachShader (ctx->eglglesctx.glslprogram[i],
- ctx->eglglesctx.vertshader[i]);
- glDeleteProgram (ctx->eglglesctx.glslprogram[i]);
- glDeleteShader (ctx->eglglesctx.fragshader[i]);
- glDeleteShader (ctx->eglglesctx.vertshader[i]);
- ctx->eglglesctx.glslprogram[i] = 0;
- ctx->eglglesctx.fragshader[i] = 0;
- ctx->eglglesctx.vertshader[i] = 0;
+ if (ctx->glslprogram[i]) {
+ glDetachShader (ctx->glslprogram[i], ctx->fragshader[i]);
+ glDetachShader (ctx->glslprogram[i], ctx->vertshader[i]);
+ glDeleteProgram (ctx->glslprogram[i]);
+ glDeleteShader (ctx->fragshader[i]);
+ glDeleteShader (ctx->vertshader[i]);
+ ctx->glslprogram[i] = 0;
+ ctx->fragshader[i] = 0;
+ ctx->vertshader[i] = 0;
}
}
gst_egl_adaptation_context_make_current (ctx, FALSE);
- if (ctx->eglglesctx.surface) {
- eglDestroySurface (ctx->eglglesctx.display,
- ctx->eglglesctx.surface);
- ctx->eglglesctx.surface = NULL;
- ctx->have_surface = FALSE;
- }
-
- if (ctx->eglglesctx.eglcontext) {
- eglDestroyContext (ctx->eglglesctx.display,
- ctx->eglglesctx.eglcontext);
- ctx->eglglesctx.eglcontext = NULL;
- }
+ gst_egl_adaptation_destroy_surface (ctx);
+ gst_egl_adaptation_destroy_context (ctx);
}
-/* XXX: Lock eglgles context? */
-gboolean
-gst_egl_adaptation_context_update_surface_dimensions (GstEglAdaptationContext *
- ctx)
-{
- gint width, height;
-
- /* Save surface dims */
- eglQuerySurface (ctx->eglglesctx.display,
- ctx->eglglesctx.surface, EGL_WIDTH, &width);
- eglQuerySurface (ctx->eglglesctx.display,
- ctx->eglglesctx.surface, EGL_HEIGHT, &height);
-
- if (width != ctx->eglglesctx.surface_width ||
- height != ctx->eglglesctx.surface_height) {
- ctx->eglglesctx.surface_width = width;
- ctx->eglglesctx.surface_height = height;
- GST_INFO_OBJECT (ctx->element, "Got surface of %dx%d pixels", width, height);
- return TRUE;
- }
-
- return FALSE;
-}
-
-
gboolean
gst_egl_adaptation_init_egl_surface (GstEglAdaptationContext * ctx,
GstVideoFormat format)
{
GLboolean ret;
- EGLint display_par;
const gchar *texnames[3] = { NULL, };
gchar *frag_prog = NULL;
gboolean free_frag_prog = FALSE;
- EGLint swap_behavior;
gint i;
GST_DEBUG_OBJECT (ctx->element, "Enter EGL surface setup");
- ctx->eglglesctx.surface =
- eglCreateWindowSurface (ctx->eglglesctx.display,
- ctx->eglglesctx.config, ctx->eglglesctx.used_window,
- NULL);
-
- if (ctx->eglglesctx.surface == EGL_NO_SURFACE) {
- got_egl_error ("eglCreateWindowSurface");
- GST_ERROR_OBJECT (ctx->element, "Can't create surface");
+ if (!gst_egl_adaptation_create_surface (ctx)) {
goto HANDLE_EGL_ERROR_LOCKED;
}
- ctx->eglglesctx.buffer_preserved = FALSE;
- if (eglQuerySurface (ctx->eglglesctx.display,
- ctx->eglglesctx.surface, EGL_SWAP_BEHAVIOR, &swap_behavior)) {
- GST_DEBUG_OBJECT (ctx->element, "Buffer swap behavior %x", swap_behavior);
- ctx->eglglesctx.buffer_preserved =
- swap_behavior == EGL_BUFFER_PRESERVED;
- } else {
- GST_DEBUG_OBJECT (ctx->element, "Can't query buffer swap behavior");
- }
+ gst_egl_adaptation_query_buffer_preserved (ctx);
if (!gst_egl_adaptation_context_make_current (ctx, TRUE))
goto HANDLE_EGL_ERROR_LOCKED;
- /* Save display's pixel aspect ratio
- *
- * DAR is reported as w/h * EGL_DISPLAY_SCALING wich is
- * a constant with value 10000. This attribute is only
- * supported if the EGL version is >= 1.2
- * XXX: Setup this as a property.
- * or some other one time check. Right now it's being called once
- * per frame.
- */
- if (ctx->eglglesctx.egl_major == 1 &&
- ctx->eglglesctx.egl_minor < 2) {
- GST_DEBUG_OBJECT (ctx->element, "Can't query PAR. Using default: %dx%d",
- EGL_DISPLAY_SCALING, EGL_DISPLAY_SCALING);
- ctx->eglglesctx.pixel_aspect_ratio = EGL_DISPLAY_SCALING;
- } else {
- eglQuerySurface (ctx->eglglesctx.display,
- ctx->eglglesctx.surface, EGL_PIXEL_ASPECT_RATIO, &display_par);
- /* Fix for outbound DAR reporting on some implementations not
- * honoring the 'should return w/h * EGL_DISPLAY_SCALING' spec
- * requirement
- */
- if (display_par == EGL_UNKNOWN || display_par < EGL_SANE_DAR_MIN ||
- display_par > EGL_SANE_DAR_MAX) {
- GST_DEBUG_OBJECT (ctx->element, "Nonsensical PAR value returned: %d. "
- "Bad EGL implementation? "
- "Will use default: %d/%d", ctx->eglglesctx.pixel_aspect_ratio,
- EGL_DISPLAY_SCALING, EGL_DISPLAY_SCALING);
- ctx->eglglesctx.pixel_aspect_ratio = EGL_DISPLAY_SCALING;
- } else {
- ctx->eglglesctx.pixel_aspect_ratio = display_par;
- }
- }
+ gst_egl_adaptation_query_par (ctx);
/* Save surface dims */
gst_egl_adaptation_context_update_surface_dimensions (ctx);
@@ -741,7 +506,7 @@ gst_egl_adaptation_init_egl_surface (GstEglAdaptationContext * ctx,
case GST_VIDEO_FORMAT_AYUV:
frag_prog = (gchar *) frag_AYUV_prog;
free_frag_prog = FALSE;
- ctx->eglglesctx.n_textures = 1;
+ ctx->n_textures = 1;
texnames[0] = "tex";
break;
case GST_VIDEO_FORMAT_Y444:
@@ -751,7 +516,7 @@ gst_egl_adaptation_init_egl_surface (GstEglAdaptationContext * ctx,
case GST_VIDEO_FORMAT_Y41B:
frag_prog = (gchar *) frag_PLANAR_YUV_prog;
free_frag_prog = FALSE;
- ctx->eglglesctx.n_textures = 3;
+ ctx->n_textures = 3;
texnames[0] = "Ytex";
texnames[1] = "Utex";
texnames[2] = "Vtex";
@@ -759,35 +524,35 @@ gst_egl_adaptation_init_egl_surface (GstEglAdaptationContext * ctx,
case GST_VIDEO_FORMAT_YUY2:
frag_prog = g_strdup_printf (frag_YUY2_YVYU_UYVY_prog, 'r', 'g', 'a');
free_frag_prog = TRUE;
- ctx->eglglesctx.n_textures = 2;
+ ctx->n_textures = 2;
texnames[0] = "Ytex";
texnames[1] = "UVtex";
break;
case GST_VIDEO_FORMAT_YVYU:
frag_prog = g_strdup_printf (frag_YUY2_YVYU_UYVY_prog, 'r', 'a', 'g');
free_frag_prog = TRUE;
- ctx->eglglesctx.n_textures = 2;
+ ctx->n_textures = 2;
texnames[0] = "Ytex";
texnames[1] = "UVtex";
break;
case GST_VIDEO_FORMAT_UYVY:
frag_prog = g_strdup_printf (frag_YUY2_YVYU_UYVY_prog, 'a', 'r', 'b');
free_frag_prog = TRUE;
- ctx->eglglesctx.n_textures = 2;
+ ctx->n_textures = 2;
texnames[0] = "Ytex";
texnames[1] = "UVtex";
break;
case GST_VIDEO_FORMAT_NV12:
frag_prog = g_strdup_printf (frag_NV12_NV21_prog, 'r', 'a');
free_frag_prog = TRUE;
- ctx->eglglesctx.n_textures = 2;
+ ctx->n_textures = 2;
texnames[0] = "Ytex";
texnames[1] = "UVtex";
break;
case GST_VIDEO_FORMAT_NV21:
frag_prog = g_strdup_printf (frag_NV12_NV21_prog, 'a', 'r');
free_frag_prog = TRUE;
- ctx->eglglesctx.n_textures = 2;
+ ctx->n_textures = 2;
texnames[0] = "Ytex";
texnames[1] = "UVtex";
break;
@@ -796,21 +561,21 @@ gst_egl_adaptation_init_egl_surface (GstEglAdaptationContext * ctx,
case GST_VIDEO_FORMAT_BGRA:
frag_prog = g_strdup_printf (frag_REORDER_prog, 'b', 'g', 'r');
free_frag_prog = TRUE;
- ctx->eglglesctx.n_textures = 1;
+ ctx->n_textures = 1;
texnames[0] = "tex";
break;
case GST_VIDEO_FORMAT_xRGB:
case GST_VIDEO_FORMAT_ARGB:
frag_prog = g_strdup_printf (frag_REORDER_prog, 'g', 'b', 'a');
free_frag_prog = TRUE;
- ctx->eglglesctx.n_textures = 1;
+ ctx->n_textures = 1;
texnames[0] = "tex";
break;
case GST_VIDEO_FORMAT_xBGR:
case GST_VIDEO_FORMAT_ABGR:
frag_prog = g_strdup_printf (frag_REORDER_prog, 'a', 'b', 'g');
free_frag_prog = TRUE;
- ctx->eglglesctx.n_textures = 1;
+ ctx->n_textures = 1;
texnames[0] = "tex";
break;
case GST_VIDEO_FORMAT_RGB:
@@ -819,7 +584,7 @@ gst_egl_adaptation_init_egl_surface (GstEglAdaptationContext * ctx,
case GST_VIDEO_FORMAT_RGB16:
frag_prog = (gchar *) frag_COPY_prog;
free_frag_prog = FALSE;
- ctx->eglglesctx.n_textures = 1;
+ ctx->n_textures = 1;
texnames[0] = "tex";
break;
default:
@@ -828,9 +593,9 @@ gst_egl_adaptation_init_egl_surface (GstEglAdaptationContext * ctx,
}
if (!create_shader_program (ctx,
- &ctx->eglglesctx.glslprogram[0],
- &ctx->eglglesctx.vertshader[0],
- &ctx->eglglesctx.fragshader[0], vert_COPY_prog, frag_prog)) {
+ &ctx->glslprogram[0],
+ &ctx->vertshader[0],
+ &ctx->fragshader[0], vert_COPY_prog, frag_prog)) {
if (free_frag_prog)
g_free (frag_prog);
frag_prog = NULL;
@@ -840,39 +605,34 @@ gst_egl_adaptation_init_egl_surface (GstEglAdaptationContext * ctx,
g_free (frag_prog);
frag_prog = NULL;
- ctx->eglglesctx.position_loc[0] =
- glGetAttribLocation (ctx->eglglesctx.glslprogram[0], "position");
- ctx->eglglesctx.texpos_loc[0] =
- glGetAttribLocation (ctx->eglglesctx.glslprogram[0], "texpos");
+ ctx->position_loc[0] = glGetAttribLocation (ctx->glslprogram[0], "position");
+ ctx->texpos_loc[0] = glGetAttribLocation (ctx->glslprogram[0], "texpos");
- glEnableVertexAttribArray (ctx->eglglesctx.position_loc[0]);
+ glEnableVertexAttribArray (ctx->position_loc[0]);
if (got_gl_error ("glEnableVertexAttribArray"))
goto HANDLE_ERROR;
- glEnableVertexAttribArray (ctx->eglglesctx.texpos_loc[0]);
+ glEnableVertexAttribArray (ctx->texpos_loc[0]);
if (got_gl_error ("glEnableVertexAttribArray"))
goto HANDLE_ERROR;
- for (i = 0; i < ctx->eglglesctx.n_textures; i++) {
- ctx->eglglesctx.tex_loc[0][i] =
- glGetUniformLocation (ctx->eglglesctx.glslprogram[0],
- texnames[i]);
+ for (i = 0; i < ctx->n_textures; i++) {
+ ctx->tex_loc[0][i] =
+ glGetUniformLocation (ctx->glslprogram[0], texnames[i]);
}
- if (!ctx->eglglesctx.buffer_preserved) {
+ if (!ctx->buffer_preserved) {
/* Build shader program for black borders */
if (!create_shader_program (ctx,
- &ctx->eglglesctx.glslprogram[1],
- &ctx->eglglesctx.vertshader[1],
- &ctx->eglglesctx.fragshader[1], vert_COPY_prog_no_tex,
- frag_BLACK_prog))
+ &ctx->glslprogram[1],
+ &ctx->vertshader[1],
+ &ctx->fragshader[1], vert_COPY_prog_no_tex, frag_BLACK_prog))
goto HANDLE_ERROR;
- ctx->eglglesctx.position_loc[1] =
- glGetAttribLocation (ctx->eglglesctx.glslprogram[1],
- "position");
+ ctx->position_loc[1] =
+ glGetAttribLocation (ctx->glslprogram[1], "position");
- glEnableVertexAttribArray (ctx->eglglesctx.position_loc[1]);
+ glEnableVertexAttribArray (ctx->position_loc[1]);
if (got_gl_error ("glEnableVertexAttribArray"))
goto HANDLE_ERROR;
}
@@ -881,13 +641,12 @@ gst_egl_adaptation_init_egl_surface (GstEglAdaptationContext * ctx,
if (!ctx->have_texture) {
GST_INFO_OBJECT (ctx->element, "Performing initial texture setup");
- glGenTextures (ctx->eglglesctx.n_textures,
- ctx->eglglesctx.texture);
+ glGenTextures (ctx->n_textures, ctx->texture);
if (got_gl_error ("glGenTextures"))
goto HANDLE_ERROR_LOCKED;
- for (i = 0; i < ctx->eglglesctx.n_textures; i++) {
- glBindTexture (GL_TEXTURE_2D, ctx->eglglesctx.texture[i]);
+ for (i = 0; i < ctx->n_textures; i++) {
+ glBindTexture (GL_TEXTURE_2D, ctx->texture[i]);
if (got_gl_error ("glBindTexture"))
goto HANDLE_ERROR;
@@ -932,51 +691,27 @@ got_gl_error (const char *wtf)
return FALSE;
}
-
void
-gst_egl_adaptation_context_terminate_display (GstEglAdaptationContext * ctx)
+gst_egl_adaptation_context_set_window (GstEglAdaptationContext * ctx,
+ EGLNativeWindowType window)
{
- if (ctx->eglglesctx.display) {
- eglTerminate (ctx->eglglesctx.display);
- ctx->eglglesctx.display = NULL;
- }
+ ctx->window = window;
}
-void
-gst_egl_adaptation_context_bind_API (GstEglAdaptationContext * ctx)
+GLuint
+gst_egl_adaptation_context_get_texture (GstEglAdaptationContext * ctx, gint i)
{
- eglBindAPI (EGL_OPENGL_ES_API);
+ return ctx->texture[i];
}
-gboolean
-gst_egl_adaptation_context_swap_buffers (GstEglAdaptationContext * ctx)
+gint
+gst_egl_adaptation_context_get_surface_width (GstEglAdaptationContext * ctx)
{
- gboolean ret =
- eglSwapBuffers (ctx->eglglesctx.display, ctx->eglglesctx.surface);
- if (ret == EGL_FALSE) {
- got_egl_error ("eglSwapBuffers");
- }
- return ret;
+ return ctx->surface_width;
}
-/* Prints avilable EGL/GLES extensions
- * If another rendering path is implemented this is the place
- * where you want to check for the availability of its supporting
- * EGL/GLES extensions.
- */
-void
-gst_egl_adaptation_context_init_egl_exts (GstEglAdaptationContext * ctx)
+gint
+gst_egl_adaptation_context_get_surface_height (GstEglAdaptationContext * ctx)
{
- const char *eglexts;
- unsigned const char *glexts;
-
- eglexts = eglQueryString (ctx->eglglesctx.display, EGL_EXTENSIONS);
- glexts = glGetString (GL_EXTENSIONS);
-
- GST_DEBUG_OBJECT (ctx->element, "Available EGL extensions: %s\n",
- GST_STR_NULL (eglexts));
- GST_DEBUG_OBJECT (ctx->element, "Available GLES extensions: %s\n",
- GST_STR_NULL ((const char *) glexts));
-
- return;
+ return ctx->surface_height;
}
diff --git a/ext/eglgles/gstegladaptation.h b/ext/eglgles/gstegladaptation.h
index 52de204c7..4aca04d5d 100644
--- a/ext/eglgles/gstegladaptation.h
+++ b/ext/eglgles/gstegladaptation.h
@@ -55,6 +55,7 @@
#include <bcm_host.h>
#endif
+#include <gst/video/video.h>
#include "video_platform_wrapper.h"
#define GST_EGLGLESSINK_IMAGE_NOFMT 0
@@ -64,6 +65,17 @@
#define GST_EGLGLESSINK_EGL_MIN_VERSION 1
G_BEGIN_DECLS
+/* will probably move elsewhere */
+static const EGLint eglglessink_RGBA8888_attribs[] = {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_NONE
+};
+
typedef struct GstEglAdaptationContext GstEglAdaptationContext;
typedef struct _GstEglGlesRenderContext GstEglGlesRenderContext;
typedef struct _GstEglGlesImageFmt GstEglGlesImageFmt;
@@ -89,8 +101,6 @@ typedef struct _coord5
* @vertshader: Vertex shader
* @glslprogram: Compiled and linked GLSL program in use for rendering
* @texture Texture units in use
- * @surface_width: Pixel width of the surface the sink is rendering into
- * @surface_height: Pixel height of the surface the sink is rendering into
* @pixel_aspect_ratio: EGL display aspect ratio
* @egl_minor: EGL version (minor)
* @egl_major: EGL version (major)
@@ -110,27 +120,8 @@ struct _GstEglGlesRenderContext
{
EGLConfig config;
EGLContext eglcontext;
- EGLDisplay display;
- EGLNativeWindowType window, used_window;
EGLSurface surface;
- gboolean buffer_preserved;
- GLuint fragshader[3]; /* frame, border, frame-platform */
- GLuint vertshader[3]; /* frame, border, frame-platform */
- GLuint glslprogram[3]; /* frame, border, frame-platform */
- GLuint texture[3]; /* RGB/Y, U/UV, V */
- EGLint surface_width;
- EGLint surface_height;
- EGLint pixel_aspect_ratio;
EGLint egl_minor, egl_major;
- gint n_textures;
-
- /* shader vars */
- GLuint position_loc[3]; /* frame, border, frame-platform */
- GLuint texpos_loc[2]; /* frame, frame-platform */
- GLuint tex_loc[2][3]; /* [frame, frame-platform] RGB/Y, U/UV, V */
- coord5 position_array[12]; /* 4 x Frame, 4 x Border1, 4 x Border2 */
- unsigned short index_array[4];
- unsigned int position_buffer, index_buffer;
};
/*
@@ -155,37 +146,97 @@ struct _GstEglGlesImageFmt
* @have_vbo: Set if the GLES VBO setup has been performed
* @have_texture: Set if the GLES texture setup has been performed
* @have_surface: Set if the EGL surface setup has been performed
+ * @surface_width: Pixel width of the surface the sink is rendering into
+ * @surface_height: Pixel height of the surface the sink is rendering into
*
* The #GstEglAdaptationContext data structure.
*/
struct GstEglAdaptationContext
{
GstElement *element;
- GstEglGlesRenderContext eglglesctx;
+
+ EGLNativeWindowType window, used_window;
+ EGLDisplay display;
+
+ unsigned int position_buffer, index_buffer;
gboolean have_vbo;
gboolean have_texture;
gboolean have_surface;;
+
+ gboolean buffer_preserved;
+
+ gint surface_width;
+ gint surface_height;
+ gint pixel_aspect_ratio;
+
+ GLuint fragshader[3]; /* frame, border, frame-platform */
+ GLuint vertshader[3]; /* frame, border, frame-platform */
+ GLuint glslprogram[3]; /* frame, border, frame-platform */
+ GLuint texture[3]; /* RGB/Y, U/UV, V */
+ gint n_textures;
+
+ /* shader vars */
+ GLuint position_loc[3]; /* frame, border, frame-platform */
+ GLuint texpos_loc[2]; /* frame, frame-platform */
+ GLuint tex_loc[2][3]; /* [frame, frame-platform] RGB/Y, U/UV, V */
+ coord5 position_array[12]; /* 4 x Frame, 4 x Border1, 4 x Border2 */
+ unsigned short index_array[4];
+
+#if USE_IOS
+ EAGLContext *eagl_context;
+ GLUint framebuffer;
+ GLUint color_renderbuffer;
+#else
+ GstEglGlesRenderContext eglglesctx;
+#endif
};
GstEglAdaptationContext * gst_egl_adaptation_context_new (GstElement * element);
void gst_egl_adaptation_context_free (GstEglAdaptationContext * ctx);
+/* platform window */
+gboolean gst_egl_adaptation_create_native_window (GstEglAdaptationContext * ctx, gint width, gint height, gpointer * own_window_data);
+void gst_egl_adaptation_destroy_native_window (GstEglAdaptationContext * ctx, gpointer * own_window_data);
+
+/* Initialization */
gboolean gst_egl_adaptation_init_display (GstEglAdaptationContext * ctx);
-gboolean gst_egl_adaptation_choose_config (GstEglAdaptationContext * ctx);
gint gst_egl_adaptation_context_fill_supported_fbuffer_configs (GstEglAdaptationContext * ctx, GstCaps ** ret_caps);
-gboolean gst_egl_adaptation_context_make_current (GstEglAdaptationContext * ctx, gboolean bind);
-void gst_egl_adaptation_context_cleanup (GstEglAdaptationContext * ctx);
gboolean gst_egl_adaptation_init_egl_surface (GstEglAdaptationContext * ctx, GstVideoFormat format);
-gboolean gst_egl_adaptation_context_update_surface_dimensions (GstEglAdaptationContext * ctx);
+void gst_egl_adaptation_context_init_egl_exts (GstEglAdaptationContext * ctx);
+
+/* cleanup */
+void gst_egl_adaptation_context_cleanup (GstEglAdaptationContext * ctx);
void gst_egl_adaptation_context_terminate_display(GstEglAdaptationContext * ctx);
+
+/* configuration */
+gboolean gst_egl_adaptation_choose_config (GstEglAdaptationContext * ctx);
+gboolean gst_egl_adaptation_context_make_current (GstEglAdaptationContext * ctx, gboolean bind);
+gboolean gst_egl_adaptation_context_update_surface_dimensions (GstEglAdaptationContext * ctx);
+
+/* rendering */
void gst_egl_adaptation_context_bind_API (GstEglAdaptationContext * ctx);
gboolean gst_egl_adaptation_context_swap_buffers (GstEglAdaptationContext * ctx);
-void gst_egl_adaptation_context_init_egl_exts (GstEglAdaptationContext * ctx);
+/* get/set */
+void gst_egl_adaptation_context_set_window (GstEglAdaptationContext * ctx, EGLNativeWindowType window);
+GLuint gst_egl_adaptation_context_get_texture (GstEglAdaptationContext * ctx, gint i);
+gint gst_egl_adaptation_context_get_surface_width (GstEglAdaptationContext * ctx);
+gint gst_egl_adaptation_context_get_surface_height (GstEglAdaptationContext * ctx);
+
+/* error handling */
gboolean got_egl_error (const char *wtf);
gboolean got_gl_error (const char *wtf);
+/* platform specific helpers */
+gboolean _gst_egl_choose_config (GstEglAdaptationContext * ctx, gboolean try_only, gint * num_configs);
+gboolean gst_egl_adaptation_create_egl_context (GstEglAdaptationContext * ctx);
+gboolean gst_egl_adaptation_create_surface (GstEglAdaptationContext * ctx);
+void gst_egl_adaptation_query_buffer_preserved (GstEglAdaptationContext * ctx);
+void gst_egl_adaptation_query_par (GstEglAdaptationContext * ctx);
+void gst_egl_adaptation_destroy_surface (GstEglAdaptationContext * ctx);
+void gst_egl_adaptation_destroy_context (GstEglAdaptationContext * ctx);
+
G_END_DECLS
#endif /* __GST_EGL_ADAPTATION_H__ */
diff --git a/ext/eglgles/gstegladaptation_ios.m b/ext/eglgles/gstegladaptation_ios.m
new file mode 100644
index 000000000..e4eb5576a
--- /dev/null
+++ b/ext/eglgles/gstegladaptation_ios.m
@@ -0,0 +1,260 @@
+/*
+ * GStreamer EGL/GLES Sink Adaptation for IOS
+ * Copyright (C) 2013 Collabora Ltd.
+ * @author: Thiago Santos <thiago.sousa.santos@collabora.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+gboolean
+gst_egl_adaptation_init_display (GstEglAdaptationContext * ctx)
+{
+ /* NOP - the display should be initialized by the application */
+}
+
+void
+gst_egl_adaptation_context_terminate_display (GstEglAdaptationContext * ctx)
+{
+ /* NOP */
+}
+
+void
+gst_egl_adaptation_context_bind_API (GstEglAdaptationContext * ctx)
+{
+ /* NOP */
+}
+
+gboolean
+gst_egl_adaptation_create_native_window (GstEglAdaptationContext * ctx, gint width, gint height, gpointer * own_window_data)
+{
+}
+
+void
+gst_egl_adaptation_destroy_native_window (GstEglAdaptationContext * ctx, gpointer * own_window_data)
+{
+}
+
+gboolean
+gst_egl_adaptation_create_egl_context (GstEglAdaptationContext * ctx)
+{
+ EAGLContext *context;
+ context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+ if (context == nil)
+ GST_ERROR_OBJECT (ctx->element, "Failed to create EAGL GLES2 context");
+ return FALSE;
+ }
+ ctx->eagl_context = context;
+
+ return TRUE;
+}
+
+gboolean
+gst_egl_adaptation_context_make_current (GstEglAdaptationContext * ctx,
+ gboolean bind)
+{
+ if (bind && ctx->eagl_context) {
+ EAGLContext *cur_ctx = [EAGLContext currentContext];
+
+ if (cur_ctx == ctx->eagl_context) {
+ GST_DEBUG_OBJECT (ctx->element,
+ "Already attached the context to thread %p", g_thread_self ());
+ return TRUE;
+ }
+
+ GST_DEBUG_OBJECT (ctx->element, "Attaching context to thread %p",
+ g_thread_self ());
+ if ([EAGLContext setCurrentContext: ctx->eagl_context] == NO) {
+ got_egl_error ("eglMakeCurrent");
+ GST_ERROR_OBJECT (ctx->element, "Couldn't bind context");
+ return FALSE;
+ }
+ } else {
+ GST_DEBUG_OBJECT (ctx->element, "Detaching context from thread %p",
+ g_thread_self ());
+ if ([EAGLContext setCurrentContext: nil] == NO) {
+ got_egl_error ("eglMakeCurrent");
+ GST_ERROR_OBJECT (ctx->element, "Couldn't unbind context");
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+gst_egl_adaptation_create_surface (GstEglAdaptationContext * ctx)
+{
+ GLuint framebuffer;
+ GLuint colorRenderbuffer;
+ GLint width;
+ GLint height;
+ GLuint depthRenderbuffer;
+ GLenum status;
+
+ /* Allocate framebuffer */
+ glGenFramebuffers(1, &framebuffer);
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+
+ /* Allocate color render buffer */
+ glGenRenderbuffers(1, &colorRenderbuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
+ [ctx->eagl_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:myEAGLLayer];
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, colorRenderbuffer);
+
+ /* Get renderbuffer width/height */
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
+
+ /* allocate depth render buffer */
+ glGenRenderbuffers(1, &depthRenderbuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+ GL_RENDERBUFFER, depthRenderbuffer);
+
+ /* check creation status */
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+ if(status != GL_FRAMEBUFFER_COMPLETE) {
+ NSLog(@"failed to make complete framebuffer object %x", status);
+ return FALSE;
+ }
+
+ ctx->framebuffer = framebuffer;
+ ctx->color_renderbuffer = colorRenderbuffer;
+
+ return TRUE;
+}
+
+gboolean
+_gst_egl_choose_config (GstEglAdaptationContext * ctx, gboolean try_only, gint * num_configs)
+{
+ CAEAGLLayer *eaglLayer = (CAEAGLLayer *)[[UIView ctx->window] layer];
+ NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:NO], kEAGLDrawablePropertyRetainedBacking,
+ kEAGLColorFormatRGBA8888, kEAGLDrawablePropertyColorFormat,
+ nil];
+ [eaglLayer setOpaque:YES];
+ [eaglLayer setDrawableProperties:dict];
+
+ if (num_configs)
+ *num_configs = 1;
+}
+
+void
+gst_egl_adaptation_query_buffer_preserved (GstEglAdaptationContext * ctx)
+{
+ CAEAGLLayer *eaglLayer = (CAEAGLLayer *)[[UIView ctx->window] layer];
+ NSDictionary *dict = [eaglLayer drawableProperties];
+
+ ctx->buffer_preserved = FALSE;
+ if ([dict objectForKey: kEAGLDrawablePropertyRetainedBacking] != nil) {
+ NSNumber n = [dict objectForKey: kEAGLDrawablePropertyRetainedBacking];
+ ctx->buffer_preserved = n != [NSNumber numberWithBool:NO];
+ } else {
+ GST_DEBUG_OBJECT (ctx->element, "No information about buffer preserving in layer properties");
+ }
+}
+
+void
+gst_egl_adaptation_query_par (GstEglAdaptationContext * ctx)
+{
+ /* TODO how can we check this? */
+ ctx->pixel_aspect_ratio = EGL_DISPLAY_SCALING;
+}
+
+gboolean
+gst_egl_adaptation_context_update_surface_dimensions (GstEglAdaptationContext *
+ ctx)
+{
+ GLint width;
+ GLint height;
+
+ /* Get renderbuffer width/height */
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
+
+ if (width != ctx->surface_width || height != ctx->surface_height) {
+ ctx->surface_width = width;
+ ctx->surface_height = height;
+ GST_INFO_OBJECT (ctx->element, "Got surface of %dx%d pixels", width,
+ height);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+void
+gst_egl_adaptation_context_init_egl_exts (GstEglAdaptationContext * ctx)
+{
+ NSString *extensionsString = [NSString stringWithCString:glGetString(GL_EXTENSIONS) encoding: NSASCIIStringEncoding];
+
+ GST_DEBUG_OBJECT (ctx->element, "Available GL extensions: %s\n",
+ GST_STR_NULL ([extensionsString UTF8String]));
+}
+
+void
+gst_egl_adaptation_destroy_surface (GstEglAdaptationContext * ctx)
+{
+ if (ctx->framebuffer) {
+ glDeleteFrameuffers (1, &ctx->framebuffer);
+ ctx->framebuffer = 0;
+ ctx->have_surface = FALSE;
+ }
+}
+
+void
+gst_egl_adaptation_destroy_context (GstEglAdaptationContext * ctx)
+{
+ if (ctx->eglglesctx.eglcontext) {
+ [ctx->eagl_context dealloc];
+ ctx->eagl_context = NULL;
+ }
+}
+
+gboolean
+gst_egl_adaptation_context_swap_buffers (GstEglAdaptationContext * ctx)
+{
+ glBindRenderbuffer(GL_RENDERBUFFER, ctx->colorRenderbuffer);
+ [context presentRenderbuffer:GL_RENDERBUFFER];
+
+ return TRUE;
+}
+
diff --git a/ext/eglgles/gstegladaptation_pc.c b/ext/eglgles/gstegladaptation_pc.c
new file mode 100644
index 000000000..1ece48bb6
--- /dev/null
+++ b/ext/eglgles/gstegladaptation_pc.c
@@ -0,0 +1,364 @@
+/*
+ * GStreamer EGL/GLES Sink Adaptation
+ * Copyright (C) 2013 Collabora Ltd.
+ * @author: Thiago Santos <thiago.sousa.santos@collabora.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "gstegladaptation.h"
+
+#include "video_platform_wrapper.h"
+
+/* Some EGL implementations are reporting wrong
+ * values for the display's EGL_PIXEL_ASPECT_RATIO.
+ * They are required by the khronos specs to report
+ * this value as w/h * EGL_DISPLAY_SCALING (Which is
+ * a constant with value 10000) but at least the
+ * Galaxy SIII (Android) is reporting just 1 when
+ * w = h. We use these two to bound returned values to
+ * sanity.
+ */
+#define EGL_SANE_DAR_MIN ((EGL_DISPLAY_SCALING)/10)
+#define EGL_SANE_DAR_MAX ((EGL_DISPLAY_SCALING)*10)
+
+gboolean
+gst_egl_adaptation_init_display (GstEglAdaptationContext * ctx)
+{
+ EGLDisplay display;
+ GST_DEBUG_OBJECT (ctx->element, "Enter EGL initial configuration");
+
+#ifdef USE_EGL_RPI
+ /* See https://github.com/raspberrypi/firmware/issues/99 */
+ if (!eglMakeCurrent ((EGLDisplay) 1, EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT)) {
+ got_egl_error ("eglMakeCurrent");
+ GST_ERROR_OBJECT (ctx->element, "Couldn't unbind context");
+ return FALSE;
+ }
+#endif
+
+ display = eglGetDisplay (EGL_DEFAULT_DISPLAY);
+ if (display == EGL_NO_DISPLAY) {
+ GST_ERROR_OBJECT (ctx->element, "Could not get EGL display connection");
+ goto HANDLE_ERROR; /* No EGL error is set by eglGetDisplay() */
+ }
+ ctx->display = display;
+
+ if (!eglInitialize (display,
+ &ctx->eglglesctx.egl_major, &ctx->eglglesctx.egl_minor)) {
+ got_egl_error ("eglInitialize");
+ GST_ERROR_OBJECT (ctx->element, "Could not init EGL display connection");
+ goto HANDLE_EGL_ERROR;
+ }
+
+ /* Check against required EGL version
+ * XXX: Need to review the version requirement in terms of the needed API
+ */
+ if (ctx->eglglesctx.egl_major < GST_EGLGLESSINK_EGL_MIN_VERSION) {
+ GST_ERROR_OBJECT (ctx->element, "EGL v%d needed, but you only have v%d.%d",
+ GST_EGLGLESSINK_EGL_MIN_VERSION, ctx->eglglesctx.egl_major,
+ ctx->eglglesctx.egl_minor);
+ goto HANDLE_ERROR;
+ }
+
+ GST_INFO_OBJECT (ctx->element, "System reports supported EGL version v%d.%d",
+ ctx->eglglesctx.egl_major, ctx->eglglesctx.egl_minor);
+
+ eglBindAPI (EGL_OPENGL_ES_API);
+
+ return TRUE;
+
+ /* Errors */
+HANDLE_EGL_ERROR:
+ GST_ERROR_OBJECT (ctx->element, "EGL call returned error %x", eglGetError ());
+HANDLE_ERROR:
+ GST_ERROR_OBJECT (ctx->element, "Couldn't setup window/surface from handle");
+ return FALSE;
+}
+
+void
+gst_egl_adaptation_context_terminate_display (GstEglAdaptationContext * ctx)
+{
+ if (ctx->display) {
+ eglTerminate (ctx->display);
+ ctx->display = NULL;
+ }
+}
+
+
+gboolean
+_gst_egl_choose_config (GstEglAdaptationContext * ctx, gboolean try_only,
+ gint * num_configs)
+{
+ EGLint cfg_number;
+ gboolean ret;
+ EGLConfig *config = NULL;
+
+ if (!try_only)
+ config = &ctx->eglglesctx.config;
+
+ ret = eglChooseConfig (ctx->display,
+ eglglessink_RGBA8888_attribs, config, 1, &cfg_number) != EGL_FALSE;
+
+ if (num_configs)
+ *num_configs = cfg_number;
+ return ret;
+}
+
+gboolean
+gst_egl_adaptation_create_egl_context (GstEglAdaptationContext * ctx)
+{
+ EGLint con_attribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+
+ ctx->eglglesctx.eglcontext =
+ eglCreateContext (ctx->display,
+ ctx->eglglesctx.config, EGL_NO_CONTEXT, con_attribs);
+
+ if (ctx->eglglesctx.eglcontext == EGL_NO_CONTEXT) {
+ return FALSE;
+ }
+
+ GST_DEBUG_OBJECT (ctx->element, "EGL Context: %p",
+ ctx->eglglesctx.eglcontext);
+
+ return TRUE;
+}
+
+gboolean
+gst_egl_adaptation_context_make_current (GstEglAdaptationContext * ctx,
+ gboolean bind)
+{
+ g_assert (ctx->display != NULL);
+
+ if (bind && ctx->eglglesctx.surface && ctx->eglglesctx.eglcontext) {
+ EGLContext *cur_ctx = eglGetCurrentContext ();
+
+ if (cur_ctx == ctx->eglglesctx.eglcontext) {
+ GST_DEBUG_OBJECT (ctx->element,
+ "Already attached the context to thread %p", g_thread_self ());
+ return TRUE;
+ }
+
+ GST_DEBUG_OBJECT (ctx->element, "Attaching context to thread %p",
+ g_thread_self ());
+ if (!eglMakeCurrent (ctx->display,
+ ctx->eglglesctx.surface, ctx->eglglesctx.surface,
+ ctx->eglglesctx.eglcontext)) {
+ got_egl_error ("eglMakeCurrent");
+ GST_ERROR_OBJECT (ctx->element, "Couldn't bind context");
+ return FALSE;
+ }
+ } else {
+ GST_DEBUG_OBJECT (ctx->element, "Detaching context from thread %p",
+ g_thread_self ());
+ if (!eglMakeCurrent (ctx->display, EGL_NO_SURFACE,
+ EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
+ got_egl_error ("eglMakeCurrent");
+ GST_ERROR_OBJECT (ctx->element, "Couldn't unbind context");
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+gboolean
+gst_egl_adaptation_create_surface (GstEglAdaptationContext * ctx)
+{
+ ctx->eglglesctx.surface =
+ eglCreateWindowSurface (ctx->display,
+ ctx->eglglesctx.config, ctx->used_window, NULL);
+
+ if (ctx->eglglesctx.surface == EGL_NO_SURFACE) {
+ got_egl_error ("eglCreateWindowSurface");
+ GST_ERROR_OBJECT (ctx->element, "Can't create surface");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+void
+gst_egl_adaptation_query_buffer_preserved (GstEglAdaptationContext * ctx)
+{
+ EGLint swap_behavior;
+
+ ctx->buffer_preserved = FALSE;
+ if (eglQuerySurface (ctx->display,
+ ctx->eglglesctx.surface, EGL_SWAP_BEHAVIOR, &swap_behavior)) {
+ GST_DEBUG_OBJECT (ctx->element, "Buffer swap behavior %x", swap_behavior);
+ ctx->buffer_preserved = swap_behavior == EGL_BUFFER_PRESERVED;
+ } else {
+ GST_DEBUG_OBJECT (ctx->element, "Can't query buffer swap behavior");
+ }
+}
+
+void
+gst_egl_adaptation_query_par (GstEglAdaptationContext * ctx)
+{
+ EGLint display_par;
+
+ /* Save display's pixel aspect ratio
+ *
+ * DAR is reported as w/h * EGL_DISPLAY_SCALING wich is
+ * a constant with value 10000. This attribute is only
+ * supported if the EGL version is >= 1.2
+ * XXX: Setup this as a property.
+ * or some other one time check. Right now it's being called once
+ * per frame.
+ */
+ if (ctx->eglglesctx.egl_major == 1 && ctx->eglglesctx.egl_minor < 2) {
+ GST_DEBUG_OBJECT (ctx->element, "Can't query PAR. Using default: %dx%d",
+ EGL_DISPLAY_SCALING, EGL_DISPLAY_SCALING);
+ ctx->pixel_aspect_ratio = EGL_DISPLAY_SCALING;
+ } else {
+ eglQuerySurface (ctx->display,
+ ctx->eglglesctx.surface, EGL_PIXEL_ASPECT_RATIO, &display_par);
+ /* Fix for outbound DAR reporting on some implementations not
+ * honoring the 'should return w/h * EGL_DISPLAY_SCALING' spec
+ * requirement
+ */
+ if (display_par == EGL_UNKNOWN || display_par < EGL_SANE_DAR_MIN ||
+ display_par > EGL_SANE_DAR_MAX) {
+ GST_DEBUG_OBJECT (ctx->element, "Nonsensical PAR value returned: %d. "
+ "Bad EGL implementation? "
+ "Will use default: %d/%d", ctx->pixel_aspect_ratio,
+ EGL_DISPLAY_SCALING, EGL_DISPLAY_SCALING);
+ ctx->pixel_aspect_ratio = EGL_DISPLAY_SCALING;
+ } else {
+ ctx->pixel_aspect_ratio = display_par;
+ }
+ }
+}
+
+/* XXX: Lock eglgles context? */
+/* TODO refactor only to get the w/h and let common code do the updates */
+gboolean
+gst_egl_adaptation_context_update_surface_dimensions (GstEglAdaptationContext *
+ ctx)
+{
+ gint width, height;
+
+ /* Save surface dims */
+ eglQuerySurface (ctx->display, ctx->eglglesctx.surface, EGL_WIDTH, &width);
+ eglQuerySurface (ctx->display, ctx->eglglesctx.surface, EGL_HEIGHT, &height);
+
+ if (width != ctx->surface_width || height != ctx->surface_height) {
+ ctx->surface_width = width;
+ ctx->surface_height = height;
+ GST_INFO_OBJECT (ctx->element, "Got surface of %dx%d pixels", width,
+ height);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/* Prints avilable EGL/GLES extensions
+ * If another rendering path is implemented this is the place
+ * where you want to check for the availability of its supporting
+ * EGL/GLES extensions.
+ */
+void
+gst_egl_adaptation_context_init_egl_exts (GstEglAdaptationContext * ctx)
+{
+ const char *eglexts;
+ unsigned const char *glexts;
+
+ eglexts = eglQueryString (ctx->display, EGL_EXTENSIONS);
+ glexts = glGetString (GL_EXTENSIONS);
+
+ GST_DEBUG_OBJECT (ctx->element, "Available EGL extensions: %s\n",
+ GST_STR_NULL (eglexts));
+ GST_DEBUG_OBJECT (ctx->element, "Available GLES extensions: %s\n",
+ GST_STR_NULL ((const char *) glexts));
+
+ return;
+}
+
+void
+gst_egl_adaptation_destroy_surface (GstEglAdaptationContext * ctx)
+{
+ if (ctx->eglglesctx.surface) {
+ eglDestroySurface (ctx->display, ctx->eglglesctx.surface);
+ ctx->eglglesctx.surface = NULL;
+ ctx->have_surface = FALSE;
+ }
+}
+
+void
+gst_egl_adaptation_destroy_context (GstEglAdaptationContext * ctx)
+{
+ if (ctx->eglglesctx.eglcontext) {
+ eglDestroyContext (ctx->display, ctx->eglglesctx.eglcontext);
+ ctx->eglglesctx.eglcontext = NULL;
+ }
+}
+
+void
+gst_egl_adaptation_context_bind_API (GstEglAdaptationContext * ctx)
+{
+ eglBindAPI (EGL_OPENGL_ES_API);
+}
+
+gboolean
+gst_egl_adaptation_context_swap_buffers (GstEglAdaptationContext * ctx)
+{
+ gboolean ret = eglSwapBuffers (ctx->display, ctx->eglglesctx.surface);
+ if (ret == EGL_FALSE) {
+ got_egl_error ("eglSwapBuffers");
+ }
+ return ret;
+}
+
+gboolean
+gst_egl_adaptation_create_native_window (GstEglAdaptationContext * ctx,
+ gint width, gint height, gpointer * own_window_data)
+{
+ return platform_create_native_window (width, height, own_window_data);
+}
+
+void
+gst_egl_adaptation_destroy_native_window (GstEglAdaptationContext * ctx,
+ gpointer * own_window_data)
+{
+ platform_destroy_native_window (ctx->display, ctx->used_window,
+ own_window_data);
+ ctx->used_window = 0;
+}
diff --git a/ext/eglgles/gsteglglessink.c b/ext/eglgles/gsteglglessink.c
index 6cefb818e..3d34dbba1 100644
--- a/ext/eglgles/gsteglglessink.c
+++ b/ext/eglgles/gsteglglessink.c
@@ -127,24 +127,12 @@
#include <bcm_host.h>
#endif
-#include "video_platform_wrapper.h"
-
#include "gsteglglessink.h"
GST_DEBUG_CATEGORY_STATIC (gst_eglglessink_debug);
#define GST_CAT_DEFAULT gst_eglglessink_debug
-static const EGLint eglglessink_RGBA8888_attribs[] = {
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
- EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL_NONE
-};
-
/* Input capabilities. */
static GstStaticPadTemplate gst_eglglessink_sink_template_factory =
GST_STATIC_PAD_TEMPLATE ("sink",
@@ -415,12 +403,11 @@ gst_eglglessink_stop (GstEglGlesSink * eglglessink)
eglglessink->last_flow = GST_FLOW_WRONG_STATE;
if (eglglessink->using_own_window) {
- platform_destroy_native_window (eglglessink->eglglesctx->display,
- eglglessink->eglglesctx->used_window, &eglglessink->own_window_data);
- eglglessink->eglglesctx->used_window = 0;
+ gst_egl_adaptation_destroy_native_window (eglglessink->egl_context,
+ &eglglessink->own_window_data);
eglglessink->have_window = FALSE;
}
- eglglessink->eglglesctx->used_window = 0;
+ eglglessink->egl_context->used_window = 0;
if (eglglessink->current_caps) {
gst_caps_unref (eglglessink->current_caps);
eglglessink->current_caps = NULL;
@@ -464,8 +451,9 @@ gst_eglglessink_create_window (GstEglGlesSink * eglglessink, gint width,
GST_INFO_OBJECT (eglglessink, "Attempting internal window creation");
window =
- platform_create_native_window (width, height,
- &eglglessink->own_window_data);
+ gst_egl_adaptation_create_native_window (eglglessink->egl_context, width,
+ height, &eglglessink->own_window_data);
+
if (!window) {
GST_ERROR_OBJECT (eglglessink, "Could not create window");
return window;
@@ -498,8 +486,8 @@ gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink, gboolean reset)
eglglessink->egl_context->have_vbo, reset);
if (eglglessink->egl_context->have_vbo && reset) {
- glDeleteBuffers (1, &eglglessink->eglglesctx->position_buffer);
- glDeleteBuffers (1, &eglglessink->eglglesctx->index_buffer);
+ glDeleteBuffers (1, &eglglessink->egl_context->position_buffer);
+ glDeleteBuffers (1, &eglglessink->egl_context->index_buffer);
eglglessink->egl_context->have_vbo = FALSE;
}
@@ -515,127 +503,128 @@ gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink, gboolean reset)
y2 = ((eglglessink->display_region.y +
eglglessink->display_region.h) / render_height) * 2.0 - 1;
- eglglessink->eglglesctx->position_array[0].x = x2;
- eglglessink->eglglesctx->position_array[0].y = y2;
- eglglessink->eglglesctx->position_array[0].z = 0;
- eglglessink->eglglesctx->position_array[0].a = 1;
- eglglessink->eglglesctx->position_array[0].b = 0;
-
- eglglessink->eglglesctx->position_array[1].x = x2;
- eglglessink->eglglesctx->position_array[1].y = y1;
- eglglessink->eglglesctx->position_array[1].z = 0;
- eglglessink->eglglesctx->position_array[1].a = 1;
- eglglessink->eglglesctx->position_array[1].b = 1;
-
- eglglessink->eglglesctx->position_array[2].x = x1;
- eglglessink->eglglesctx->position_array[2].y = y2;
- eglglessink->eglglesctx->position_array[2].z = 0;
- eglglessink->eglglesctx->position_array[2].a = 0;
- eglglessink->eglglesctx->position_array[2].b = 0;
-
- eglglessink->eglglesctx->position_array[3].x = x1;
- eglglessink->eglglesctx->position_array[3].y = y1;
- eglglessink->eglglesctx->position_array[3].z = 0;
- eglglessink->eglglesctx->position_array[3].a = 0;
- eglglessink->eglglesctx->position_array[3].b = 1;
+ eglglessink->egl_context->position_array[0].x = x2;
+ eglglessink->egl_context->position_array[0].y = y2;
+ eglglessink->egl_context->position_array[0].z = 0;
+ eglglessink->egl_context->position_array[0].a = 1;
+ eglglessink->egl_context->position_array[0].b = 0;
+
+ eglglessink->egl_context->position_array[1].x = x2;
+ eglglessink->egl_context->position_array[1].y = y1;
+ eglglessink->egl_context->position_array[1].z = 0;
+ eglglessink->egl_context->position_array[1].a = 1;
+ eglglessink->egl_context->position_array[1].b = 1;
+
+ eglglessink->egl_context->position_array[2].x = x1;
+ eglglessink->egl_context->position_array[2].y = y2;
+ eglglessink->egl_context->position_array[2].z = 0;
+ eglglessink->egl_context->position_array[2].a = 0;
+ eglglessink->egl_context->position_array[2].b = 0;
+
+ eglglessink->egl_context->position_array[3].x = x1;
+ eglglessink->egl_context->position_array[3].y = y1;
+ eglglessink->egl_context->position_array[3].z = 0;
+ eglglessink->egl_context->position_array[3].a = 0;
+ eglglessink->egl_context->position_array[3].b = 1;
if (eglglessink->display_region.x == 0) {
/* Borders top/bottom */
- eglglessink->eglglesctx->position_array[4 + 0].x = 1;
- eglglessink->eglglesctx->position_array[4 + 0].y = 1;
- eglglessink->eglglesctx->position_array[4 + 0].z = 0;
+ eglglessink->egl_context->position_array[4 + 0].x = 1;
+ eglglessink->egl_context->position_array[4 + 0].y = 1;
+ eglglessink->egl_context->position_array[4 + 0].z = 0;
- eglglessink->eglglesctx->position_array[4 + 1].x = x2;
- eglglessink->eglglesctx->position_array[4 + 1].y = y2;
- eglglessink->eglglesctx->position_array[4 + 1].z = 0;
+ eglglessink->egl_context->position_array[4 + 1].x = x2;
+ eglglessink->egl_context->position_array[4 + 1].y = y2;
+ eglglessink->egl_context->position_array[4 + 1].z = 0;
- eglglessink->eglglesctx->position_array[4 + 2].x = -1;
- eglglessink->eglglesctx->position_array[4 + 2].y = 1;
- eglglessink->eglglesctx->position_array[4 + 2].z = 0;
+ eglglessink->egl_context->position_array[4 + 2].x = -1;
+ eglglessink->egl_context->position_array[4 + 2].y = 1;
+ eglglessink->egl_context->position_array[4 + 2].z = 0;
- eglglessink->eglglesctx->position_array[4 + 3].x = x1;
- eglglessink->eglglesctx->position_array[4 + 3].y = y2;
- eglglessink->eglglesctx->position_array[4 + 3].z = 0;
+ eglglessink->egl_context->position_array[4 + 3].x = x1;
+ eglglessink->egl_context->position_array[4 + 3].y = y2;
+ eglglessink->egl_context->position_array[4 + 3].z = 0;
- eglglessink->eglglesctx->position_array[8 + 0].x = 1;
- eglglessink->eglglesctx->position_array[8 + 0].y = y1;
- eglglessink->eglglesctx->position_array[8 + 0].z = 0;
+ eglglessink->egl_context->position_array[8 + 0].x = 1;
+ eglglessink->egl_context->position_array[8 + 0].y = y1;
+ eglglessink->egl_context->position_array[8 + 0].z = 0;
- eglglessink->eglglesctx->position_array[8 + 1].x = 1;
- eglglessink->eglglesctx->position_array[8 + 1].y = -1;
- eglglessink->eglglesctx->position_array[8 + 1].z = 0;
+ eglglessink->egl_context->position_array[8 + 1].x = 1;
+ eglglessink->egl_context->position_array[8 + 1].y = -1;
+ eglglessink->egl_context->position_array[8 + 1].z = 0;
- eglglessink->eglglesctx->position_array[8 + 2].x = x1;
- eglglessink->eglglesctx->position_array[8 + 2].y = y1;
- eglglessink->eglglesctx->position_array[8 + 2].z = 0;
+ eglglessink->egl_context->position_array[8 + 2].x = x1;
+ eglglessink->egl_context->position_array[8 + 2].y = y1;
+ eglglessink->egl_context->position_array[8 + 2].z = 0;
- eglglessink->eglglesctx->position_array[8 + 3].x = -1;
- eglglessink->eglglesctx->position_array[8 + 3].y = -1;
- eglglessink->eglglesctx->position_array[8 + 3].z = 0;
+ eglglessink->egl_context->position_array[8 + 3].x = -1;
+ eglglessink->egl_context->position_array[8 + 3].y = -1;
+ eglglessink->egl_context->position_array[8 + 3].z = 0;
} else {
/* Borders left/right */
- eglglessink->eglglesctx->position_array[4 + 0].x = x1;
- eglglessink->eglglesctx->position_array[4 + 0].y = 1;
- eglglessink->eglglesctx->position_array[4 + 0].z = 0;
+ eglglessink->egl_context->position_array[4 + 0].x = x1;
+ eglglessink->egl_context->position_array[4 + 0].y = 1;
+ eglglessink->egl_context->position_array[4 + 0].z = 0;
- eglglessink->eglglesctx->position_array[4 + 1].x = x1;
- eglglessink->eglglesctx->position_array[4 + 1].y = -1;
- eglglessink->eglglesctx->position_array[4 + 1].z = 0;
+ eglglessink->egl_context->position_array[4 + 1].x = x1;
+ eglglessink->egl_context->position_array[4 + 1].y = -1;
+ eglglessink->egl_context->position_array[4 + 1].z = 0;
- eglglessink->eglglesctx->position_array[4 + 2].x = -1;
- eglglessink->eglglesctx->position_array[4 + 2].y = 1;
- eglglessink->eglglesctx->position_array[4 + 2].z = 0;
+ eglglessink->egl_context->position_array[4 + 2].x = -1;
+ eglglessink->egl_context->position_array[4 + 2].y = 1;
+ eglglessink->egl_context->position_array[4 + 2].z = 0;
- eglglessink->eglglesctx->position_array[4 + 3].x = -1;
- eglglessink->eglglesctx->position_array[4 + 3].y = -1;
- eglglessink->eglglesctx->position_array[4 + 3].z = 0;
+ eglglessink->egl_context->position_array[4 + 3].x = -1;
+ eglglessink->egl_context->position_array[4 + 3].y = -1;
+ eglglessink->egl_context->position_array[4 + 3].z = 0;
- eglglessink->eglglesctx->position_array[8 + 0].x = 1;
- eglglessink->eglglesctx->position_array[8 + 0].y = 1;
- eglglessink->eglglesctx->position_array[8 + 0].z = 0;
+ eglglessink->egl_context->position_array[8 + 0].x = 1;
+ eglglessink->egl_context->position_array[8 + 0].y = 1;
+ eglglessink->egl_context->position_array[8 + 0].z = 0;
- eglglessink->eglglesctx->position_array[8 + 1].x = 1;
- eglglessink->eglglesctx->position_array[8 + 1].y = -1;
- eglglessink->eglglesctx->position_array[8 + 1].z = 0;
+ eglglessink->egl_context->position_array[8 + 1].x = 1;
+ eglglessink->egl_context->position_array[8 + 1].y = -1;
+ eglglessink->egl_context->position_array[8 + 1].z = 0;
- eglglessink->eglglesctx->position_array[8 + 2].x = x2;
- eglglessink->eglglesctx->position_array[8 + 2].y = y2;
- eglglessink->eglglesctx->position_array[8 + 2].z = 0;
+ eglglessink->egl_context->position_array[8 + 2].x = x2;
+ eglglessink->egl_context->position_array[8 + 2].y = y2;
+ eglglessink->egl_context->position_array[8 + 2].z = 0;
- eglglessink->eglglesctx->position_array[8 + 3].x = x2;
- eglglessink->eglglesctx->position_array[8 + 3].y = -1;
- eglglessink->eglglesctx->position_array[8 + 3].z = 0;
+ eglglessink->egl_context->position_array[8 + 3].x = x2;
+ eglglessink->egl_context->position_array[8 + 3].y = -1;
+ eglglessink->egl_context->position_array[8 + 3].z = 0;
}
- eglglessink->eglglesctx->index_array[0] = 0;
- eglglessink->eglglesctx->index_array[1] = 1;
- eglglessink->eglglesctx->index_array[2] = 2;
- eglglessink->eglglesctx->index_array[3] = 3;
+ eglglessink->egl_context->index_array[0] = 0;
+ eglglessink->egl_context->index_array[1] = 1;
+ eglglessink->egl_context->index_array[2] = 2;
+ eglglessink->egl_context->index_array[3] = 3;
- glGenBuffers (1, &eglglessink->eglglesctx->position_buffer);
- glGenBuffers (1, &eglglessink->eglglesctx->index_buffer);
+ glGenBuffers (1, &eglglessink->egl_context->position_buffer);
+ glGenBuffers (1, &eglglessink->egl_context->index_buffer);
if (got_gl_error ("glGenBuffers"))
goto HANDLE_ERROR_LOCKED;
- glBindBuffer (GL_ARRAY_BUFFER, eglglessink->eglglesctx->position_buffer);
+ glBindBuffer (GL_ARRAY_BUFFER, eglglessink->egl_context->position_buffer);
if (got_gl_error ("glBindBuffer position_buffer"))
goto HANDLE_ERROR_LOCKED;
glBufferData (GL_ARRAY_BUFFER,
- sizeof (eglglessink->eglglesctx->position_array),
- eglglessink->eglglesctx->position_array, GL_STATIC_DRAW);
+ sizeof (eglglessink->egl_context->position_array),
+ eglglessink->egl_context->position_array, GL_STATIC_DRAW);
if (got_gl_error ("glBufferData position_buffer"))
goto HANDLE_ERROR_LOCKED;
- glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, eglglessink->eglglesctx->index_buffer);
+ glBindBuffer (GL_ELEMENT_ARRAY_BUFFER,
+ eglglessink->egl_context->index_buffer);
if (got_gl_error ("glBindBuffer index_buffer"))
goto HANDLE_ERROR_LOCKED;
glBufferData (GL_ELEMENT_ARRAY_BUFFER,
- sizeof (eglglessink->eglglesctx->index_array),
- eglglessink->eglglesctx->index_array, GL_STATIC_DRAW);
+ sizeof (eglglessink->egl_context->index_array),
+ eglglessink->egl_context->index_array, GL_STATIC_DRAW);
if (got_gl_error ("glBufferData index_buffer"))
goto HANDLE_ERROR_LOCKED;
@@ -659,7 +648,7 @@ gst_eglglessink_set_window_handle (GstXOverlay * overlay, guintptr id)
/* OK, we have a new window */
GST_OBJECT_LOCK (eglglessink);
- eglglessink->eglglesctx->window = (EGLNativeWindowType) id;
+ eglglessink->egl_context->window = (EGLNativeWindowType) id;
eglglessink->have_window = ((gpointer) id != NULL);
GST_OBJECT_UNLOCK (eglglessink);
@@ -759,13 +748,13 @@ gst_eglglessink_fill_texture (GstEglGlesSink * eglglessink, GstBuffer * buf)
case GST_VIDEO_FORMAT_xRGB:
case GST_VIDEO_FORMAT_xBGR:
glActiveTexture (GL_TEXTURE0);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx->texture[0]);
+ glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[0]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
break;
case GST_VIDEO_FORMAT_AYUV:
glActiveTexture (GL_TEXTURE0);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx->texture[0]);
+ glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[0]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA,
GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
break;
@@ -781,7 +770,7 @@ gst_eglglessink_fill_texture (GstEglGlesSink * eglglessink, GstBuffer * buf)
cw = gst_video_format_get_component_width (eglglessink->format, 0, w);
ch = gst_video_format_get_component_height (eglglessink->format, 0, h);
glActiveTexture (GL_TEXTURE0);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx->texture[0]);
+ glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[0]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf) + coffset);
coffset =
@@ -789,7 +778,7 @@ gst_eglglessink_fill_texture (GstEglGlesSink * eglglessink, GstBuffer * buf)
cw = gst_video_format_get_component_width (eglglessink->format, 1, w);
ch = gst_video_format_get_component_height (eglglessink->format, 1, h);
glActiveTexture (GL_TEXTURE1);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx->texture[1]);
+ glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[1]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf) + coffset);
coffset =
@@ -797,7 +786,7 @@ gst_eglglessink_fill_texture (GstEglGlesSink * eglglessink, GstBuffer * buf)
cw = gst_video_format_get_component_width (eglglessink->format, 2, w);
ch = gst_video_format_get_component_height (eglglessink->format, 2, h);
glActiveTexture (GL_TEXTURE2);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx->texture[2]);
+ glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[2]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf) + coffset);
break;
@@ -806,11 +795,11 @@ gst_eglglessink_fill_texture (GstEglGlesSink * eglglessink, GstBuffer * buf)
case GST_VIDEO_FORMAT_YVYU:
case GST_VIDEO_FORMAT_UYVY:
glActiveTexture (GL_TEXTURE0);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx->texture[0]);
+ glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[0]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
glActiveTexture (GL_TEXTURE1);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx->texture[1]);
+ glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[1]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA, GST_ROUND_UP_2 (w) / 2,
h, 0, GL_RGBA, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf));
break;
@@ -823,7 +812,7 @@ gst_eglglessink_fill_texture (GstEglGlesSink * eglglessink, GstBuffer * buf)
cw = gst_video_format_get_component_width (eglglessink->format, 0, w);
ch = gst_video_format_get_component_height (eglglessink->format, 0, h);
glActiveTexture (GL_TEXTURE0);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx->texture[0]);
+ glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[0]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE, cw, ch, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, GST_BUFFER_DATA (buf) + coffset);
@@ -833,7 +822,7 @@ gst_eglglessink_fill_texture (GstEglGlesSink * eglglessink, GstBuffer * buf)
cw = gst_video_format_get_component_width (eglglessink->format, 1, w);
ch = gst_video_format_get_component_height (eglglessink->format, 1, h);
glActiveTexture (GL_TEXTURE1);
- glBindTexture (GL_TEXTURE_2D, eglglessink->eglglesctx->texture[1]);
+ glBindTexture (GL_TEXTURE_2D, eglglessink->egl_context->texture[1]);
glTexImage2D (GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, cw, ch, 0,
GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE,
GST_BUFFER_DATA (buf) + coffset);
@@ -890,17 +879,17 @@ gst_eglglessink_render (GstEglGlesSink * eglglessink)
* calling party explicitly ask us not to by setting
* force_aspect_ratio to FALSE.
*/
- if (gst_egl_adaptation_context_update_surface_dimensions (eglglessink->egl_context) ||
- eglglessink->render_region_changed ||
- !eglglessink->display_region.w || !eglglessink->display_region.h ||
- eglglessink->size_changed) {
+ if (gst_egl_adaptation_context_update_surface_dimensions
+ (eglglessink->egl_context) || eglglessink->render_region_changed
+ || !eglglessink->display_region.w || !eglglessink->display_region.h
+ || eglglessink->size_changed) {
GST_OBJECT_LOCK (eglglessink);
if (!eglglessink->render_region_user) {
eglglessink->render_region.x = 0;
eglglessink->render_region.y = 0;
- eglglessink->render_region.w = eglglessink->eglglesctx->surface_width;
- eglglessink->render_region.h = eglglessink->eglglesctx->surface_height;
+ eglglessink->render_region.w = eglglessink->egl_context->surface_width;
+ eglglessink->render_region.h = eglglessink->egl_context->surface_height;
}
eglglessink->render_region_changed = FALSE;
eglglessink->size_changed = FALSE;
@@ -920,7 +909,7 @@ gst_eglglessink_render (GstEglGlesSink * eglglessink)
w, h,
eglglessink->par_n,
eglglessink->par_d,
- eglglessink->eglglesctx->pixel_aspect_ratio,
+ eglglessink->egl_context->pixel_aspect_ratio,
EGL_DISPLAY_SCALING)) {
GST_WARNING_OBJECT (eglglessink, "Could not compute resulting DAR");
frame.w = w;
@@ -951,13 +940,13 @@ gst_eglglessink_render (GstEglGlesSink * eglglessink)
}
glViewport (eglglessink->render_region.x,
- eglglessink->eglglesctx->surface_height -
+ eglglessink->egl_context->surface_height -
eglglessink->render_region.y -
eglglessink->render_region.h,
eglglessink->render_region.w, eglglessink->render_region.h);
/* Clear the surface once if its content is preserved */
- if (eglglessink->eglglesctx->buffer_preserved) {
+ if (eglglessink->egl_context->buffer_preserved) {
glClearColor (0.0, 0.0, 0.0, 1.0);
glClear (GL_COLOR_BUFFER_BIT);
}
@@ -970,12 +959,12 @@ gst_eglglessink_render (GstEglGlesSink * eglglessink)
GST_OBJECT_UNLOCK (eglglessink);
}
- if (!eglglessink->eglglesctx->buffer_preserved) {
+ if (!eglglessink->egl_context->buffer_preserved) {
/* Draw black borders */
GST_DEBUG_OBJECT (eglglessink, "Drawing black border 1");
- glUseProgram (eglglessink->eglglesctx->glslprogram[1]);
+ glUseProgram (eglglessink->egl_context->glslprogram[1]);
- glVertexAttribPointer (eglglessink->eglglesctx->position_loc[1], 3,
+ glVertexAttribPointer (eglglessink->egl_context->position_loc[1], 3,
GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (4 * sizeof (coord5)));
if (got_gl_error ("glVertexAttribPointer"))
goto HANDLE_ERROR;
@@ -986,7 +975,7 @@ gst_eglglessink_render (GstEglGlesSink * eglglessink)
GST_DEBUG_OBJECT (eglglessink, "Drawing black border 2");
- glVertexAttribPointer (eglglessink->eglglesctx->position_loc[1], 3,
+ glVertexAttribPointer (eglglessink->egl_context->position_loc[1], 3,
GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (8 * sizeof (coord5)));
if (got_gl_error ("glVertexAttribPointer"))
goto HANDLE_ERROR;
@@ -998,20 +987,20 @@ gst_eglglessink_render (GstEglGlesSink * eglglessink)
/* Draw video frame */
GST_DEBUG_OBJECT (eglglessink, "Drawing video frame");
- glUseProgram (eglglessink->eglglesctx->glslprogram[0]);
+ glUseProgram (eglglessink->egl_context->glslprogram[0]);
- for (i = 0; i < eglglessink->eglglesctx->n_textures; i++) {
- glUniform1i (eglglessink->eglglesctx->tex_loc[0][i], i);
+ for (i = 0; i < eglglessink->egl_context->n_textures; i++) {
+ glUniform1i (eglglessink->egl_context->tex_loc[0][i], i);
if (got_gl_error ("glUniform1i"))
goto HANDLE_ERROR;
}
- glVertexAttribPointer (eglglessink->eglglesctx->position_loc[0], 3,
+ glVertexAttribPointer (eglglessink->egl_context->position_loc[0], 3,
GL_FLOAT, GL_FALSE, sizeof (coord5), (gpointer) (0 * sizeof (coord5)));
if (got_gl_error ("glVertexAttribPointer"))
goto HANDLE_ERROR;
- glVertexAttribPointer (eglglessink->eglglesctx->texpos_loc[0], 2, GL_FLOAT,
+ glVertexAttribPointer (eglglessink->egl_context->texpos_loc[0], 2, GL_FLOAT,
GL_FALSE, sizeof (coord5), (gpointer) (3 * sizeof (gfloat)));
if (got_gl_error ("glVertexAttribPointer"))
goto HANDLE_ERROR;
@@ -1135,15 +1124,15 @@ gst_eglglessink_configure_caps (GstEglGlesSink * eglglessink, GstCaps * caps)
goto HANDLE_ERROR;
}
eglglessink->using_own_window = TRUE;
- eglglessink->eglglesctx->window = window;
+ eglglessink->egl_context->window = window;
eglglessink->have_window = TRUE;
}
GST_DEBUG_OBJECT (eglglessink, "Using window handle %p",
- eglglessink->eglglesctx->window);
- eglglessink->eglglesctx->used_window = eglglessink->eglglesctx->window;
+ eglglessink->egl_context->window);
+ eglglessink->egl_context->used_window = eglglessink->egl_context->window;
GST_OBJECT_UNLOCK (eglglessink);
gst_x_overlay_got_window_handle (GST_X_OVERLAY (eglglessink),
- (guintptr) eglglessink->eglglesctx->used_window);
+ (guintptr) eglglessink->egl_context->used_window);
if (!eglglessink->egl_context->have_surface) {
if (!gst_egl_adaptation_init_egl_surface (eglglessink->egl_context,
@@ -1413,7 +1402,6 @@ gst_eglglessink_init (GstEglGlesSink * eglglessink,
eglglessink->egl_context =
gst_egl_adaptation_context_new (GST_ELEMENT_CAST (eglglessink));
- eglglessink->eglglesctx = &eglglessink->egl_context->eglglesctx;
}
/* Interface initializations. Used here for initializing the XOverlay
diff --git a/ext/eglgles/gsteglglessink.h b/ext/eglgles/gsteglglessink.h
index 2b7af1aa4..899d45336 100644
--- a/ext/eglgles/gsteglglessink.h
+++ b/ext/eglgles/gsteglglessink.h
@@ -112,7 +112,6 @@ struct _GstEglGlesSink
GstCaps *current_caps, *configured_caps;
GstEglAdaptationContext *egl_context;
- GstEglGlesRenderContext *eglglesctx;
/* Runtime flags */
gboolean have_window;