diff options
author | Thiago Santos <thiago.sousa.santos@collabora.com> | 2013-03-13 13:12:50 -0300 |
---|---|---|
committer | Thiago Santos <thiago.sousa.santos@collabora.com> | 2013-04-16 16:08:50 -0300 |
commit | f0bd8598f33bd9fd5e65d0e9a8e6a6ce80f63d33 (patch) | |
tree | 77dcbf2619e213f07edb392cbaf7d30829f10200 | |
parent | 554108df935ec6f83ab85d30b68b218a84501af3 (diff) | |
download | gstreamer-plugins-bad-f0bd8598f33bd9fd5e65d0e9a8e6a6ce80f63d33.tar.gz |
eglglessink: split egl implementation for EAGL x EGL differences
-rw-r--r-- | ext/eglgles/Makefile.am | 8 | ||||
-rw-r--r-- | ext/eglgles/gstegladaptation.c | 395 | ||||
-rw-r--r-- | ext/eglgles/gstegladaptation.h | 105 | ||||
-rw-r--r-- | ext/eglgles/gstegladaptation_ios.m | 260 | ||||
-rw-r--r-- | ext/eglgles/gstegladaptation_pc.c | 364 | ||||
-rw-r--r-- | ext/eglgles/gsteglglessink.c | 260 | ||||
-rw-r--r-- | ext/eglgles/gsteglglessink.h | 1 |
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; |