From 344253e860bcb1a1b5d62d7631825429285e595c Mon Sep 17 00:00:00 2001 From: Matthew Waters Date: Thu, 6 Dec 2012 18:40:26 +1100 Subject: [PATCH] [624/906] OPENGL_ES2 => HAVE_GLES2 and add HAVE_OPENGL use GstGLAPI to determine which code paths to execute. perform some cleanups --- gst-libs/gst/gl/Makefile.am | 3 +- gst-libs/gst/gl/gstgldisplay.c | 874 +++++++++++++++++-------- gst-libs/gst/gl/gstgldisplay.h | 29 +- gst-libs/gst/gl/gstgldownload.c | 807 ++++++++++++++--------- gst-libs/gst/gl/gstgldownload.h | 13 +- gst-libs/gst/gl/gstglfilter.c | 7 +- gst-libs/gst/gl/gstglfilter.h | 4 +- gst-libs/gst/gl/gstglmemory.c | 37 +- gst-libs/gst/gl/gstglshader.c | 172 ++--- gst-libs/gst/gl/gstglshader.h | 107 ++- gst-libs/gst/gl/gstglshadervariables.c | 27 +- gst-libs/gst/gl/gstglupload.c | 814 ++++++++++++++--------- gst-libs/gst/gl/gstglupload.h | 13 +- 13 files changed, 1810 insertions(+), 1097 deletions(-) diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am index a59b8dd4c4..946d7c110d 100644 --- a/gst-libs/gst/gl/Makefile.am +++ b/gst-libs/gst/gl/Makefile.am @@ -55,7 +55,8 @@ libgstgl_@GST_API_VERSION@include_HEADERS = \ gstglshadervariables.h \ gstglshader.h \ gstgldownload.h \ - gstglupload.h + gstglupload.h \ + gstglapi.h libgstgl_@GST_API_VERSION@_la_CFLAGS = \ $(GL_CFLAGS) \ diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index afd4a50a6c..673a3b54de 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -42,14 +42,11 @@ #define GLEW_VERSION_MINOR 0 #endif -/* - * gst-launch-0.10 --gst-debug=gldisplay:N pipeline - * N=1: errors - * N=2: errors warnings - * N=3: errors warnings infos - * N=4: errors warnings infos - * N=5: errors warnings infos logs - */ +#define USING_OPENGL(display) (display->gl_api & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (display->gl_api & GST_GL_API_OPENGL3) +#define USING_GLES(display) (display->gl_api & GST_GL_API_GLES) +#define USING_GLES2(display) (display->gl_api & GST_GL_API_GLES2) +#define USING_GLES3(display) (display->gl_api & GST_GL_API_GLES3) GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug); #define GST_CAT_DEFAULT gst_gl_display_debug @@ -59,13 +56,17 @@ GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug); G_DEFINE_TYPE_WITH_CODE (GstGLDisplay, gst_gl_display, G_TYPE_OBJECT, DEBUG_INIT); + +#define GST_GL_DISPLAY_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_DISPLAY, GstGLDisplayPrivate)) + static void gst_gl_display_finalize (GObject * object); /* Called in the gl thread, protected by lock and unlock */ gpointer gst_gl_display_thread_create_context (GstGLDisplay * display); void gst_gl_display_thread_destroy_context (GstGLDisplay * display); void gst_gl_display_thread_run_generic (GstGLDisplay * display); -#ifdef OPENGL_ES2 +#if HAVE_GLES2 void gst_gl_display_thread_init_redisplay (GstGLDisplay * display); #endif void gst_gl_display_thread_gen_fbo (GstGLDisplay * display); @@ -86,12 +87,46 @@ void gst_gl_display_del_texture_thread (GstGLDisplay * display, void gst_gl_display_gen_texture_window_cb (GstGLDisplay * display); -//------------------------------------------------------------ -//---------------------- For klass GstGLDisplay --------------- -//------------------------------------------------------------ +#if HAVE_OPENGL +void _gen_fbo_opengl (GstGLDisplay * display); +void _use_fbo_opengl (GstGLDisplay * display); +void _use_fbo_v2_opengl (GstGLDisplay * display); +void _del_fbo_opengl (GstGLDisplay * display); +void _gen_shader_opengl (GstGLDisplay * display); +void _del_shader_opengl (GstGLDisplay * display); +#endif +#if HAVE_GLES2 +void _gen_fbo_gles2 (GstGLDisplay * display); +void _use_fbo_gles2 (GstGLDisplay * display); +void _use_fbo_v2_gles2 (GstGLDisplay * display); +void _del_fbo_gles2 (GstGLDisplay * display); +void _gen_shader_gles2 (GstGLDisplay * display); +void _del_shader_gles2 (GstGLDisplay * display); +#endif + +typedef struct _GstGLVtable +{ + GstGLWindowCB gen_fbo; + GstGLWindowCB use_fbo; + GstGLWindowCB use_fbo_v2; + GstGLWindowCB del_fbo; + GstGLWindowCB gen_shader; + GstGLWindowCB del_shader; +} GstGLVtable; + +struct _GstGLDisplayPrivate +{ + GstGLVtable vtable; +}; + +/*------------------------------------------------------------ + --------------------- For klass GstGLDisplay --------------- + ----------------------------------------------------------*/ static void gst_gl_display_class_init (GstGLDisplayClass * klass) { + g_type_class_add_private (klass, sizeof (GstGLDisplayPrivate)); + G_OBJECT_CLASS (klass)->finalize = gst_gl_display_finalize; } @@ -99,52 +134,54 @@ gst_gl_display_class_init (GstGLDisplayClass * klass) static void gst_gl_display_init (GstGLDisplay * display) { - //thread safe + display->priv = GST_GL_DISPLAY_GET_PRIVATE (display); + + /* thread safe */ display->mutex = g_mutex_new (); - //gl context + /* gl context */ display->gl_thread = NULL; display->gl_window = NULL; display->isAlive = TRUE; - //conditions + /* conditions */ display->cond_create_context = g_cond_new (); display->cond_destroy_context = g_cond_new (); - //action redisplay + /* action redisplay */ display->redisplay_texture = 0; display->redisplay_texture_width = 0; display->redisplay_texture_height = 0; display->keep_aspect_ratio = FALSE; -#ifdef OPENGL_ES2 +#if HAVE_GLES2 display->redisplay_shader = NULL; display->redisplay_attr_position_loc = 0; display->redisplay_attr_texture_loc = 0; #endif - //action gen and del texture + /* action gen and del texture */ display->gen_texture = 0; display->gen_texture_width = 0; display->gen_texture_height = 0; display->gen_texture_video_format = GST_VIDEO_FORMAT_UNKNOWN; - //client callbacks + /* client callbacks */ display->clientReshapeCallback = NULL; display->clientDrawCallback = NULL; display->client_data = NULL; display->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_GLSL; - //foreign gl context + /* foreign gl context */ display->external_gl_context = 0; - //filter gen fbo + /* filter gen fbo */ display->gen_fbo_width = 0; display->gen_fbo_height = 0; display->generated_fbo = 0; display->generated_depth_buffer = 0; - //filter use fbo + /* filter use fbo */ display->use_fbo = 0; display->use_depth_buffer = 0; display->use_fbo_texture = 0; @@ -162,11 +199,11 @@ gst_gl_display_init (GstGLDisplay * display) display->input_texture_height = 0; display->input_texture = 0; - //filter del fbo + /* filter del fbo */ display->del_fbo = 0; display->del_depth_buffer = 0; - //action gen and del shader + /* action gen and del shader */ display->gen_shader_fragment_source = NULL; display->gen_shader_vertex_source = NULL; display->gen_shader = NULL; @@ -175,17 +212,19 @@ gst_gl_display_init (GstGLDisplay * display) display->uploads = NULL; display->downloads = NULL; -#ifdef OPENGL_ES2 - display->redisplay_vertex_shader_str = +#if HAVE_GLES2 +/* *INDENT-OFF* */ + display->redisplay_vertex_shader_str_gles2 = "attribute vec4 a_position; \n" "attribute vec2 a_texCoord; \n" "varying vec2 v_texCoord; \n" "void main() \n" "{ \n" " gl_Position = a_position; \n" - " v_texCoord = a_texCoord; \n" "} \n"; + " v_texCoord = a_texCoord; \n" + "} \n"; - display->redisplay_fragment_shader_str = + display->redisplay_fragment_shader_str_gles2 = "precision mediump float; \n" "varying vec2 v_texCoord; \n" "uniform sampler2D s_texture; \n" @@ -193,6 +232,7 @@ gst_gl_display_init (GstGLDisplay * display) "{ \n" " gl_FragColor = texture2D( s_texture, v_texCoord );\n" "} \n"; +/* *INDENT_ON* */ #endif display->error_message = NULL; @@ -295,14 +335,124 @@ gst_gl_display_set_error (GstGLDisplay * display, const char *format, ...) display->isAlive = FALSE; } +#if HAVE_GLES2 +static gboolean +_create_context_gles2 (GstGLDisplay * display, gint * gl_major, gint * gl_minor) +{ + GLenum gl_err = GL_NO_ERROR; + + if (glGetString (GL_VERSION)) + GST_INFO ("GL_VERSION: %s", glGetString (GL_VERSION)); + + if (glGetString (GL_SHADING_LANGUAGE_VERSION)) + GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s", + glGetString (GL_SHADING_LANGUAGE_VERSION)); + else + GST_INFO ("Your driver does not support GLSL (OpenGL Shading Language)"); + + if (glGetString (GL_VENDOR)) + GST_INFO ("GL_VENDOR: %s", glGetString (GL_VENDOR)); + + if (glGetString (GL_RENDERER)) + GST_INFO ("GL_RENDERER: %s", glGetString (GL_RENDERER)); + + gl_err = glGetError (); + if (gl_err != GL_NO_ERROR) { + gst_gl_display_set_error (display, "glGetString error: 0x%x", gl_err); + } + + if (!GL_ES_VERSION_2_0) + gst_gl_display_set_error (display, "OpenGL|ES >= 2.0 is required"); + + display->priv->vtable.gen_fbo = (GstGLWindowCB) _gen_fbo_gles2; + display->priv->vtable.use_fbo = (GstGLWindowCB) _use_fbo_gles2; + display->priv->vtable.use_fbo_v2 = (GstGLWindowCB) _use_fbo_v2_gles2; + display->priv->vtable.del_fbo = (GstGLWindowCB) _del_fbo_gles2; + display->priv->vtable.gen_shader = (GstGLWindowCB) _gen_shader_gles2; + display->priv->vtable.del_shader = (GstGLWindowCB) _del_shader_gles2; + + *gl_major = 2; + *gl_minor = 0; + + return TRUE; +} +#endif + +#if HAVE_OPENGL +gboolean +_create_context_opengl (GstGLDisplay * display, gint * gl_major, gint * gl_minor) +{ + GLenum err = GLEW_OK; + GLenum gl_err = GL_NO_ERROR; + GString *opengl_version = NULL; + + if (glewInit () != GLEW_OK) { + gst_gl_display_set_error (display, "Failed to init GLEW: %s", + glewGetErrorString (err)); + return TRUE; + } + + /* OpenGL > 1.2.0 and Glew > 1.4.0 */ + if (glGetString (GL_VERSION)) + GST_INFO ("GL_VERSION: %s", glGetString (GL_VERSION)); + + GST_INFO ("GLEW_VERSION: %s", glewGetString (GLEW_VERSION)); + + if (glGetString (GL_SHADING_LANGUAGE_VERSION)) + GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s", + glGetString (GL_SHADING_LANGUAGE_VERSION)); + else + GST_INFO ("Your driver does not support GLSL (OpenGL Shading Language)"); + + if (glGetString (GL_VENDOR)) + GST_INFO ("GL_VENDOR: %s", glGetString (GL_VENDOR)); + + if (glGetString (GL_RENDERER)) + GST_INFO ("GL_RENDERER: %s", glGetString (GL_RENDERER)); + + gl_err = glGetError (); + if (gl_err != GL_NO_ERROR) { + gst_gl_display_set_error (display, "glGetString error: 0x%x", gl_err); + } + if (glGetString (GL_VERSION)) { + opengl_version = + g_string_truncate (g_string_new ((gchar *) glGetString (GL_VERSION)), 3); + + sscanf (opengl_version->str, "%d.%d", gl_major, gl_minor); + + g_string_free (opengl_version, TRUE); + + if ((*gl_major < 1) || + (GLEW_VERSION_MAJOR < 1) || + (*gl_major < 2 && *gl_major >= 1 + && *gl_minor < 2) || (GLEW_VERSION_MAJOR < 2 + && GLEW_VERSION_MAJOR >= 1 && GLEW_VERSION_MINOR < 4)) { + /* turn off the pipeline, the old drivers are not yet supported */ + gst_gl_display_set_error (display, + "OpenGL >= 1.2.0 and Glew >= 1.4.0 is required"); + } + } + + display->priv->vtable.gen_fbo = (GstGLWindowCB) _gen_fbo_opengl; + display->priv->vtable.use_fbo = (GstGLWindowCB) _use_fbo_opengl; + display->priv->vtable.use_fbo_v2 = (GstGLWindowCB) _use_fbo_v2_opengl; + display->priv->vtable.del_fbo = (GstGLWindowCB) _del_fbo_opengl; + display->priv->vtable.gen_shader = (GstGLWindowCB) _gen_shader_opengl; + display->priv->vtable.del_shader = (GstGLWindowCB) _del_shader_opengl; + + return TRUE; +} +#endif + gpointer gst_gl_display_thread_create_context (GstGLDisplay * display) { - GLenum err = GLEW_OK; + gint gl_major = 0, gl_minor = 0; + gboolean ret = FALSE; gst_gl_display_lock (display); display->gl_window = - gst_gl_window_new (GST_GL_RENDERER_API_ANY, display->external_gl_context); + gst_gl_window_new (GST_GL_API_ANY, display->external_gl_context); if (!display->gl_window) { gst_gl_display_set_error (display, "Failed to create gl window"); @@ -313,76 +463,24 @@ gst_gl_display_thread_create_context (GstGLDisplay * display) GST_INFO ("gl window created"); -#ifndef OPENGL_ES2 - err = glewInit (); + display->gl_api = gst_gl_window_get_gl_api (display->gl_window); + + g_assert (display->gl_api != GST_GL_API_NONE && display->gl_api != GST_GL_API_ANY); + + /* gl api specific code */ +#if HAVE_OPENGL + if (!ret && USING_OPENGL(display)) + ret = _create_context_opengl (display, &gl_major, &gl_minor); #endif - if (err != GLEW_OK) { -#ifndef OPENGL_ES2 - gst_gl_display_set_error (display, "Failed to init GLEW: %s", - glewGetErrorString (err)); -#endif - } else { -#ifndef OPENGL_ES2 - //OpenGL > 1.2.0 and Glew > 1.4.0 - GString *opengl_version = NULL; - gint opengl_version_major = 0; - gint opengl_version_minor = 0; +#if HAVE_GLES2 + if (!ret && USING_GLES2(display)) + ret = _create_context_gles2 (display, &gl_major, &gl_minor); #endif - GLenum gl_err = GL_NO_ERROR; - if (glGetString (GL_VERSION)) - GST_INFO ("GL_VERSION: %s", glGetString (GL_VERSION)); + if (!ret || !gl_major) + gst_gl_display_set_error (display, "failed to create context"); -#ifndef OPENGL_ES2 - GST_INFO ("GLEW_VERSION: %s", glewGetString (GLEW_VERSION)); -#endif - if (glGetString (GL_SHADING_LANGUAGE_VERSION)) - GST_INFO ("GL_SHADING_LANGUAGE_VERSION: %s", - glGetString (GL_SHADING_LANGUAGE_VERSION)); - else - GST_INFO ("Your driver does not support GLSL (OpenGL Shading Language)"); - - if (glGetString (GL_VENDOR)) - GST_INFO ("GL_VENDOR: %s", glGetString (GL_VENDOR)); - - if (glGetString (GL_RENDERER)) - GST_INFO ("GL_RENDERER: %s", glGetString (GL_RENDERER)); - - - gl_err = glGetError (); - if (gl_err != GL_NO_ERROR) { - gst_gl_display_set_error (display, "glGetString error: 0x%x", gl_err); - } -#ifndef OPENGL_ES2 - if (glGetString (GL_VERSION) && gl_err == GL_NO_ERROR) { - - opengl_version = - g_string_truncate (g_string_new ((gchar *) glGetString (GL_VERSION)), - 3); - - sscanf (opengl_version->str, "%d.%d", &opengl_version_major, - &opengl_version_minor); - - g_string_free (opengl_version, TRUE); - - if ((opengl_version_major < 1) || - (GLEW_VERSION_MAJOR < 1) || - (opengl_version_major < 2 && opengl_version_major >= 1 - && opengl_version_minor < 2) || (GLEW_VERSION_MAJOR < 2 - && GLEW_VERSION_MAJOR >= 1 && GLEW_VERSION_MINOR < 4)) { - //turn off the pipeline, the old drivers are not yet supported - gst_gl_display_set_error (display, - "Required OpenGL >= 1.2.0 and Glew >= 1.4.0"); - } - } -#else - if (!GL_ES_VERSION_2_0) { - gst_gl_display_set_error (display, "Required OpenGL ES > 2.0"); - } -#endif - } - - //setup callbacks + /* setup callbacks */ gst_gl_window_set_resize_callback (display->gl_window, GST_GL_WINDOW_RESIZE_CB (gst_gl_display_on_resize), display); gst_gl_window_set_draw_callback (display->gl_window, @@ -418,7 +516,7 @@ gst_gl_display_thread_create_context (GstGLDisplay * display) void gst_gl_display_thread_destroy_context (GstGLDisplay * display) { -#ifdef OPENGL_ES2 +#if HAVE_GLES2 if (display->redisplay_shader) { g_object_unref (G_OBJECT (display->redisplay_shader)); display->redisplay_shader = NULL; @@ -438,18 +536,18 @@ gst_gl_display_thread_run_generic (GstGLDisplay * display) display->generic_callback (display, display->data); } -#ifdef OPENGL_ES2 +#if HAVE_GLES2 /* Called in the gl thread */ void gst_gl_display_thread_init_redisplay (GstGLDisplay * display) { GError *error = NULL; - display->redisplay_shader = gst_gl_shader_new (); + display->redisplay_shader = gst_gl_shader_new (display); gst_gl_shader_set_vertex_source (display->redisplay_shader, - display->redisplay_vertex_shader_str); + display->redisplay_vertex_shader_str_gles2); gst_gl_shader_set_fragment_source (display->redisplay_shader, - display->redisplay_fragment_shader_str); + display->redisplay_fragment_shader_str_gles2); gst_gl_shader_compile (display->redisplay_shader, &error); if (error) { @@ -468,42 +566,37 @@ gst_gl_display_thread_init_redisplay (GstGLDisplay * display) } #endif -/* Called in the gl thread */ +#if HAVE_OPENGL void -gst_gl_display_thread_gen_fbo (GstGLDisplay * display) +_gen_fbo_opengl (GstGLDisplay * display) { - //a texture must be attached to the FBO + /* a texture must be attached to the FBO */ GLuint fake_texture = 0; GST_TRACE ("creating FBO dimensions:%ux%u", display->gen_fbo_width, display->gen_fbo_height); - //-- generate frame buffer object + /* -- generate frame buffer object */ if (!GLEW_EXT_framebuffer_object) { - //turn off the pipeline because Frame buffer object is a not present - gst_gl_display_set_error (display, + gst_gl_display_set_error (display, "Context, EXT_framebuffer_object not supported"); return; } - //setup FBO + /* setup FBO */ glGenFramebuffersEXT (1, &display->generated_fbo); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->generated_fbo); - //setup the render buffer for depth + /* setup the render buffer for depth */ glGenRenderbuffersEXT (1, &display->generated_depth_buffer); glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, display->generated_depth_buffer); -#ifndef OPENGL_ES2 + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, display->gen_fbo_width, display->gen_fbo_height); glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, display->gen_fbo_width, display->gen_fbo_height); -#else - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, - display->gen_fbo_width, display->gen_fbo_height); -#endif - //setup a texture to render to + /* setup a texture to render to */ glGenTextures (1, &fake_texture); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fake_texture); glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, @@ -516,38 +609,94 @@ gst_gl_display_thread_gen_fbo (GstGLDisplay * display) glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - //attach the texture to the FBO to renderer to + /* attach the texture to the FBO to renderer to */ glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0); - //attach the depth render buffer to the FBO + /* attach the depth render buffer to the FBO */ glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, display->generated_depth_buffer); -#ifndef OPENGL_ES2 - glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, display->generated_depth_buffer); -#endif + if (USING_OPENGL(display)) + glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, display->generated_depth_buffer); if (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) != GL_FRAMEBUFFER_COMPLETE_EXT) gst_gl_display_set_error (display, "GL framebuffer status incomplete"); - //unbind the FBO + /* unbind the FBO */ glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); glDeleteTextures (1, &fake_texture); } - - -/* Called in the gl thread */ -void -gst_gl_display_thread_use_fbo (GstGLDisplay * display) -{ -#ifdef OPENGL_ES2 - GLint viewport_dim[4]; #endif +#if HAVE_GLES2 +void +_gen_fbo_gles2 (GstGLDisplay * display) +{ + /* a texture must be attached to the FBO */ + GLuint fake_texture = 0; + + GST_TRACE ("creating FBO dimensions:%ux%u", display->gen_fbo_width, + display->gen_fbo_height); + + /* -- generate frame buffer object */ + + if (!GLEW_EXT_framebuffer_object) { + gst_gl_display_set_error (display, + "Context, EXT_framebuffer_object not supported"); + return; + } + /* setup FBO */ + glGenFramebuffersEXT (1, &display->generated_fbo); + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->generated_fbo); + + /* setup the render buffer for depth */ + glGenRenderbuffersEXT (1, &display->generated_depth_buffer); + glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, display->generated_depth_buffer); + + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, + display->gen_fbo_width, display->gen_fbo_height); + + /* setup a texture to render to */ + glGenTextures (1, &fake_texture); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fake_texture); + glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, + display->gen_fbo_width, display->gen_fbo_height, 0, GL_RGBA, + GL_UNSIGNED_BYTE, NULL); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + + /* attach the texture to the FBO to renderer to */ + glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0); + + /* attach the depth render buffer to the FBO */ + glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, display->generated_depth_buffer); + + if (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) != + GL_FRAMEBUFFER_COMPLETE_EXT) + gst_gl_display_set_error (display, "GL framebuffer status incomplete"); + + /* unbind the FBO */ + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); + + glDeleteTextures (1, &fake_texture); +} +#endif + +/* Called in the gl thread */ +#if HAVE_OPENGL +void +_use_fbo_opengl (GstGLDisplay * display) +{ GST_TRACE ("Binding v1 FBO %u dimensions:%ux%u with texture:%u " "dimensions:%ux%u", display->use_fbo, display->use_fbo_width, display->use_fbo_height, display->use_fbo_texture, @@ -555,17 +704,16 @@ gst_gl_display_thread_use_fbo (GstGLDisplay * display) glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->use_fbo); - //setup a texture to render to + /* setup a texture to render to */ glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture); - //attach the texture to the FBO to renderer to + /* attach the texture to the FBO to renderer to */ glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture, 0); if (GLEW_ARB_fragment_shader) gst_gl_shader_use (NULL); -#ifndef OPENGL_ES2 glPushAttrib (GL_VIEWPORT_BIT); glMatrixMode (GL_PROJECTION); glPushMatrix (); @@ -589,44 +737,75 @@ gst_gl_display_thread_use_fbo (GstGLDisplay * display) glMatrixMode (GL_MODELVIEW); glPushMatrix (); glLoadIdentity (); -#else // OPENGL_ES2 - glGetIntegerv (GL_VIEWPORT, viewport_dim); -#endif + glViewport (0, 0, display->use_fbo_width, display->use_fbo_height); -#ifndef OPENGL_ES2 glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT); -#endif glClearColor (0.0, 0.0, 0.0, 0.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - //the opengl scene + /* the opengl scene */ display->use_fbo_scene_cb (display->input_texture_width, display->input_texture_height, display->input_texture, display->use_fbo_stuff); -#ifndef OPENGL_ES2 glDrawBuffer (GL_NONE); glMatrixMode (GL_PROJECTION); glPopMatrix (); glMatrixMode (GL_MODELVIEW); glPopMatrix (); glPopAttrib (); -#else - glViewport (viewport_dim[0], viewport_dim[1], viewport_dim[2], - viewport_dim[3]); -#endif glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); } +#endif +#if HAVE_GLES2 +void +_use_fbo_gles2 (GstGLDisplay * display) +{ + GLint viewport_dim[4]; + + GST_TRACE ("Binding v1 FBO %u dimensions:%ux%u with texture:%u " + "dimensions:%ux%u", display->use_fbo, display->use_fbo_width, + display->use_fbo_height, display->use_fbo_texture, + display->input_texture_width, display->input_texture_height); + + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->use_fbo); + + /* setup a texture to render to */ + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture); + + /* attach the texture to the FBO to renderer to */ + glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture, 0); + + glGetIntegerv (GL_VIEWPORT, viewport_dim); + + glViewport (0, 0, display->use_fbo_width, display->use_fbo_height); + + glClearColor (0.0, 0.0, 0.0, 0.0); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* the opengl scene */ + display->use_fbo_scene_cb (display->input_texture_width, + display->input_texture_height, display->input_texture, + display->use_fbo_stuff); + + glViewport (viewport_dim[0], viewport_dim[1], viewport_dim[2], + viewport_dim[3]); + + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); +} +#endif /* Called in a gl thread * Need full shader support */ +#if HAVE_OPENGL void -gst_gl_display_thread_use_fbo_v2 (GstGLDisplay * display) +_use_fbo_v2_opengl (GstGLDisplay * display) { GLint viewport_dim[4]; @@ -636,10 +815,10 @@ gst_gl_display_thread_use_fbo_v2 (GstGLDisplay * display) glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->use_fbo); - //setup a texture to render to + /* setup a texture to render to */ glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture); - //attach the texture to the FBO to renderer to + /* attach the texture to the FBO to renderer to */ glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture, 0); @@ -647,30 +826,63 @@ gst_gl_display_thread_use_fbo_v2 (GstGLDisplay * display) glViewport (0, 0, display->use_fbo_width, display->use_fbo_height); -#ifndef OPENGL_ES2 glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT); + + glClearColor (0.0, 0.0, 0.0, 0.0); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* the opengl scene */ + display->use_fbo_scene_cb_v2 (display->use_fbo_stuff); + + glDrawBuffer (GL_NONE); + + glViewport (viewport_dim[0], viewport_dim[1], + viewport_dim[2], viewport_dim[3]); + + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); +} #endif +#if HAVE_GLES2 +void +_use_fbo_v2_gles2 (GstGLDisplay * display) +{ + GLint viewport_dim[4]; + + GST_TRACE ("Binding v2 FBO %u dimensions:%ux%u with texture:%u ", + display->use_fbo, display->use_fbo_width, + display->use_fbo_height, display->use_fbo_texture); + + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->use_fbo); + + /* setup a texture to render to */ + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture); + + /* attach the texture to the FBO to renderer to */ + glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture, 0); + + glGetIntegerv (GL_VIEWPORT, viewport_dim); + + glViewport (0, 0, display->use_fbo_width, display->use_fbo_height); + glClearColor (0.0, 0.0, 0.0, 0.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); //the opengl scene display->use_fbo_scene_cb_v2 (display->use_fbo_stuff); -#ifndef OPENGL_ES2 - glDrawBuffer (GL_NONE); -#endif - glViewport (viewport_dim[0], viewport_dim[1], viewport_dim[2], viewport_dim[3]); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); } - +#endif /* Called in the gl thread */ +#if HAVE_OPENGL void -gst_gl_display_thread_del_fbo (GstGLDisplay * display) +_del_fbo_opengl (GstGLDisplay * display) { GST_TRACE ("Deleting FBO %u", display->del_fbo); @@ -683,11 +895,28 @@ gst_gl_display_thread_del_fbo (GstGLDisplay * display) display->del_depth_buffer = 0; } } +#endif +#if HAVE_GLES2 +void +_del_fbo_gles2 (GstGLDisplay * display) +{ + GST_TRACE ("Deleting FBO %u", display->del_fbo); + + if (display->del_fbo) { + glDeleteFramebuffersEXT (1, &display->del_fbo); + display->del_fbo = 0; + } + if (display->del_depth_buffer) { + glDeleteRenderbuffersEXT (1, &display->del_depth_buffer); + display->del_depth_buffer = 0; + } +} +#endif /* Called in the gl thread */ void -gst_gl_display_thread_gen_shader (GstGLDisplay * display) +_gen_shader_opengl (GstGLDisplay * display) { GST_TRACE ("Generating shader %" GST_PTR_FORMAT, display->gen_shader); @@ -696,7 +925,7 @@ gst_gl_display_thread_gen_shader (GstGLDisplay * display) display->gen_shader_fragment_source) { GError *error = NULL; - display->gen_shader = gst_gl_shader_new (); + display->gen_shader = gst_gl_shader_new (display); if (display->gen_shader_vertex_source) gst_gl_shader_set_vertex_source (display->gen_shader, @@ -723,10 +952,49 @@ gst_gl_display_thread_gen_shader (GstGLDisplay * display) } } +#if HAVE_GLES2 +void +_gen_shader_gles2 (GstGLDisplay * display) +{ + GST_TRACE ("Generating shader %" GST_PTR_FORMAT, display->gen_shader); + + if (GLEW_ARB_fragment_shader) { + if (display->gen_shader_vertex_source || + display->gen_shader_fragment_source) { + GError *error = NULL; + + display->gen_shader = gst_gl_shader_new (display); + + if (display->gen_shader_vertex_source) + gst_gl_shader_set_vertex_source (display->gen_shader, + display->gen_shader_vertex_source); + + if (display->gen_shader_fragment_source) + gst_gl_shader_set_fragment_source (display->gen_shader, + display->gen_shader_fragment_source); + + gst_gl_shader_compile (display->gen_shader, &error); + if (error) { + gst_gl_display_set_error (display, "%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_shader_use (NULL); + g_object_unref (G_OBJECT (display->gen_shader)); + display->gen_shader = NULL; + } + } + } else { + gst_gl_display_set_error (display, + "One of the filter required ARB_fragment_shader"); + display->gen_shader = NULL; + } +} +#endif /* Called in the gl thread */ +#if HAVE_OPENGL void -gst_gl_display_thread_del_shader (GstGLDisplay * display) +_del_shader_opengl (GstGLDisplay * display) { GST_TRACE ("Deleting shader %" GST_PTR_FORMAT, display->del_shader); @@ -735,7 +1003,20 @@ gst_gl_display_thread_del_shader (GstGLDisplay * display) display->del_shader = NULL; } } +#endif +#if HAVE_GLES2 +void +_del_shader_gles2 (GstGLDisplay * display) +{ + GST_TRACE ("Deleting shader %" GST_PTR_FORMAT, display->del_shader); + + if (display->del_shader) { + g_object_unref (G_OBJECT (display->del_shader)); + display->del_shader = NULL; + } +} +#endif //------------------------------------------------------------ //------------------ BEGIN GL THREAD ACTIONS ----------------- @@ -776,11 +1057,13 @@ gst_gl_display_on_resize (GstGLDisplay * display, gint width, gint height) } else { glViewport (0, 0, width, height); } -#ifndef OPENGL_ES2 - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); - gluOrtho2D (0, width, 0, height); - glMatrixMode (GL_MODELVIEW); +#if HAVE_OPENGL + if (USING_OPENGL(display)) { + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + gluOrtho2D (0, width, 0, height); + glMatrixMode (GL_MODELVIEW); + } #endif } } @@ -789,24 +1072,25 @@ gst_gl_display_on_resize (GstGLDisplay * display, gint width, gint height) void gst_gl_display_on_draw (GstGLDisplay * display) { - //check if tecture is ready for being drawn + /* check if texture is ready for being drawn */ if (!display->redisplay_texture) return; - //opengl scene + /* opengl scene */ GST_TRACE ("on draw"); - //make sure that the environnement is clean + /* make sure that the environnement is clean */ if (display->colorspace_conversion == GST_GL_DISPLAY_CONVERSION_GLSL) glUseProgramObjectARB (0); -#ifndef OPENGL_ES2 - glDisable (GL_TEXTURE_RECTANGLE_ARB); +#if HAVE_OPENGL + if (USING_OPENGL(display)) + glDisable (GL_TEXTURE_RECTANGLE_ARB); #endif glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0); - //check if a client draw callback is registered + /* check if a client draw callback is registered */ if (display->clientDrawCallback) { gboolean doRedisplay = display->clientDrawCallback (display->redisplay_texture, @@ -817,79 +1101,80 @@ gst_gl_display_on_draw (GstGLDisplay * display) gst_gl_window_draw_unlocked (display->gl_window, display->redisplay_texture_width, display->redisplay_texture_height); } - //default opengl scene + /* default opengl scene */ else { +#if HAVE_OPENGL + if (USING_OPENGL(display)) { + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -#ifndef OPENGL_ES2 - glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); - glMatrixMode (GL_PROJECTION); - glLoadIdentity (); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->redisplay_texture); + glEnable (GL_TEXTURE_RECTANGLE_ARB); - glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->redisplay_texture); - glEnable (GL_TEXTURE_RECTANGLE_ARB); + glBegin (GL_QUADS); + /* gst images are top-down while opengl plane is bottom-up */ + glTexCoord2i (display->redisplay_texture_width, 0); + glVertex2f (1.0f, 1.0f); + glTexCoord2i (0, 0); + glVertex2f (-1.0f, 1.0f); + glTexCoord2i (0, display->redisplay_texture_height); + glVertex2f (-1.0f, -1.0f); + glTexCoord2i (display->redisplay_texture_width, + display->redisplay_texture_height); + glVertex2f (1.0f, -1.0f); + /*glTexCoord2i (display->redisplay_texture_width, 0); + glVertex2i (1, -1); + glTexCoord2i (0, 0); + glVertex2f (-1.0f, -1.0f); + glTexCoord2i (0, display->redisplay_texture_height); + glVertex2f (-1.0f, 1.0f); + glTexCoord2i (display->redisplay_texture_width, + display->redisplay_texture_height); + glVertex2f (1.0f, 1.0f); */ + glEnd (); - glBegin (GL_QUADS); - /* gst images are top-down while opengl plane is bottom-up */ - glTexCoord2i (display->redisplay_texture_width, 0); - glVertex2f (1.0f, 1.0f); - glTexCoord2i (0, 0); - glVertex2f (-1.0f, 1.0f); - glTexCoord2i (0, display->redisplay_texture_height); - glVertex2f (-1.0f, -1.0f); - glTexCoord2i (display->redisplay_texture_width, - display->redisplay_texture_height); - glVertex2f (1.0f, -1.0f); - /*glTexCoord2i (display->redisplay_texture_width, 0); - glVertex2i (1, -1); - glTexCoord2i (0, 0); - glVertex2f (-1.0f, -1.0f); - glTexCoord2i (0, display->redisplay_texture_height); - glVertex2f (-1.0f, 1.0f); - glTexCoord2i (display->redisplay_texture_width, - display->redisplay_texture_height); - glVertex2f (1.0f, 1.0f); */ - glEnd (); - - glDisable (GL_TEXTURE_RECTANGLE_ARB); - -#else //OPENGL_ES2 - - const GLfloat vVertices[] = { 1.0f, 1.0f, 0.0f, - 1.0f, 0.0f, - -1.0f, 1.0f, 0.0f, - 0.0f, 0.0f, - -1.0f, -1.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, -1.0f, 0.0f, - 1.0f, 1.0f - }; - - GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; - - glClear (GL_COLOR_BUFFER_BIT); - - gst_gl_shader_use (display->redisplay_shader); - - //Load the vertex position - glVertexAttribPointer (display->redisplay_attr_position_loc, 3, GL_FLOAT, - GL_FALSE, 5 * sizeof (GLfloat), vVertices); - - //Load the texture coordinate - glVertexAttribPointer (display->redisplay_attr_texture_loc, 2, GL_FLOAT, - GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); - - glEnableVertexAttribArray (display->redisplay_attr_position_loc); - glEnableVertexAttribArray (display->redisplay_attr_texture_loc); - - glActiveTexture (GL_TEXTURE0); - glBindTexture (GL_TEXTURE_2D, display->redisplay_texture); - gst_gl_shader_set_uniform_1i (display->redisplay_shader, "s_texture", 0); - - glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + glDisable (GL_TEXTURE_RECTANGLE_ARB); + } #endif +#if HAVE_GLES2 + if (USING_GLES2(display)) { + const GLfloat vVertices[] = { 1.0f, 1.0f, 0.0f, + 1.0f, 0.0f, + -1.0f, 1.0f, 0.0f, + 0.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, -1.0f, 0.0f, + 1.0f, 1.0f + }; - } //end default opengl scene + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + glClear (GL_COLOR_BUFFER_BIT); + + gst_gl_shader_use (display->redisplay_shader); + + /* Load the vertex position */ + glVertexAttribPointer (display->redisplay_attr_position_loc, 3, GL_FLOAT, + GL_FALSE, 5 * sizeof (GLfloat), vVertices); + + /* Load the texture coordinate */ + glVertexAttribPointer (display->redisplay_attr_texture_loc, 2, GL_FLOAT, + GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (display->redisplay_attr_position_loc); + glEnableVertexAttribArray (display->redisplay_attr_texture_loc); + + glActiveTexture (GL_TEXTURE0); + glBindTexture (GL_TEXTURE_2D, display->redisplay_texture); + gst_gl_shader_set_uniform_1i (display->redisplay_shader, "s_texture", 0); + + glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + } +#endif + } /* end default opengl scene */ } @@ -941,7 +1226,8 @@ gst_gl_display_gen_texture_thread (GstGLDisplay * display, GLuint * pTexture, glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); break; -/* case GST_GL_DISPLAY_CONVERSION_MESA: +#if 0 + case GST_GL_DISPLAY_CONVERSION_MESA: if (display->upload_width != display->upload_data_width || display->upload_height != display->upload_data_height) glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, @@ -949,7 +1235,8 @@ gst_gl_display_gen_texture_thread (GstGLDisplay * display, GLuint * pTexture, else glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width, height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL); - break;*/ + break; +#endif default: gst_gl_display_set_error (display, "Unknow colorspace conversion %d", display->colorspace_conversion); @@ -962,8 +1249,8 @@ gst_gl_display_gen_texture_thread (GstGLDisplay * display, GLuint * pTexture, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); break; default: -// gst_gl_display_set_error (display, "Unsupported upload video format %d", -// display->upload_video_format); + gst_gl_display_set_error (display, "Unsupported upload video format %d", + v_format); break; } @@ -984,14 +1271,14 @@ gst_gl_display_del_texture_thread (GstGLDisplay * display, GLuint * pTexture) } -//------------------------------------------------------------ -//--------------------- END PRIVATE ------------------------- -//------------------------------------------------------------ +/*------------------------------------------------------------ + --------------------- END PRIVATE ------------------------- + ----------------------------------------------------------*/ -//------------------------------------------------------------ -//---------------------- BEGIN PUBLIC ------------------------ -//------------------------------------------------------------ +/*------------------------------------------------------------ + --------------------- BEGIN PUBLIC ------------------------- + ----------------------------------------------------------*/ void gst_gl_display_lock (GstGLDisplay * display) @@ -999,7 +1286,6 @@ gst_gl_display_lock (GstGLDisplay * display) g_mutex_lock (display->mutex); } - void gst_gl_display_unlock (GstGLDisplay * display) { @@ -1030,7 +1316,7 @@ gst_gl_display_check_framebuffer_status (void) case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); break; -#ifndef OPENGL_ES2 +#if HAVE_OPENGL case GL_FRAMEBUFFER_UNDEFINED: GST_ERROR ("GL_FRAMEBUFFER_UNDEFINED"); break; @@ -1044,7 +1330,7 @@ gst_gl_display_check_framebuffer_status (void) GstGLDisplay * gst_gl_display_new (void) { - return g_object_new (GST_TYPE_GL_DISPLAY, NULL); + return g_object_new (GST_GL_TYPE_DISPLAY, NULL); } @@ -1083,16 +1369,17 @@ gst_gl_display_redisplay (GstGLDisplay * display, GLuint texture, gint gl_width, gint gl_height, gint window_width, gint window_height, gboolean keep_aspect_ratio) { - gboolean isAlive = TRUE; + gboolean isAlive; gst_gl_display_lock (display); - isAlive = display->isAlive; - if (isAlive) { + if (display->isAlive) { -#ifdef OPENGL_ES2 - if (!display->redisplay_shader) { - gst_gl_window_send_message (display->gl_window, +#if HAVE_GLES2 + if (USING_GLES2(display)) { + if (!display->redisplay_shader) { + gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (gst_gl_display_thread_init_redisplay), display); + } } #endif @@ -1104,8 +1391,8 @@ gst_gl_display_redisplay (GstGLDisplay * display, GLuint texture, display->keep_aspect_ratio = keep_aspect_ratio; if (display->gl_window) gst_gl_window_draw (display->gl_window, window_width, window_height); - isAlive = display->isAlive; } + isAlive = display->isAlive; gst_gl_display_unlock (display); return isAlive; @@ -1167,11 +1454,11 @@ gst_gl_display_gen_fbo (GstGLDisplay * display, gint width, gint height, display->gen_fbo_width = width; display->gen_fbo_height = height; gst_gl_window_send_message (display->gl_window, - GST_GL_WINDOW_CB (gst_gl_display_thread_gen_fbo), display); + GST_GL_WINDOW_CB (display->priv->vtable.gen_fbo), display); *fbo = display->generated_fbo; *depthbuffer = display->generated_depth_buffer; - isAlive = display->isAlive; } + isAlive = display->isAlive; gst_gl_display_unlock (display); return isAlive; @@ -1194,11 +1481,10 @@ gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width, gdouble proj_param2, gdouble proj_param3, gdouble proj_param4, GstGLDisplayProjection projection, gpointer * stuff) { - gboolean isAlive = TRUE; + gboolean isAlive; gst_gl_display_lock (display); - isAlive = display->isAlive; - if (isAlive) { + if (display->isAlive) { display->use_fbo = fbo; display->use_depth_buffer = depth_buffer; display->use_fbo_texture = texture_fbo; @@ -1214,10 +1500,9 @@ gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width, display->input_texture_width = input_texture_width; display->input_texture_height = input_texture_height; display->input_texture = input_texture; - gst_gl_window_send_message (display->gl_window, - GST_GL_WINDOW_CB (gst_gl_display_thread_use_fbo), display); - isAlive = display->isAlive; + gst_gl_window_send_message (display->gl_window, display->priv->vtable.use_fbo, display); } + isAlive = display->isAlive; gst_gl_display_unlock (display); return isAlive; @@ -1228,11 +1513,10 @@ gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width, gint texture_fbo_height, GLuint fbo, GLuint depth_buffer, GLuint texture_fbo, GLCB_V2 cb, gpointer * stuff) { - gboolean isAlive = TRUE; + gboolean isAlive; gst_gl_display_lock (display); - isAlive = display->isAlive; - if (isAlive) { + if (display->isAlive) { display->use_fbo = fbo; display->use_depth_buffer = depth_buffer; display->use_fbo_texture = texture_fbo; @@ -1240,10 +1524,9 @@ gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width, display->use_fbo_height = texture_fbo_height; display->use_fbo_scene_cb_v2 = cb; display->use_fbo_stuff = stuff; - gst_gl_window_send_message (display->gl_window, - GST_GL_WINDOW_CB (gst_gl_display_thread_use_fbo_v2), display); - isAlive = display->isAlive; + gst_gl_window_send_message (display->gl_window, display->priv->vtable.use_fbo_v2, display); } + isAlive = display->isAlive; gst_gl_display_unlock (display); return isAlive; @@ -1254,10 +1537,11 @@ void gst_gl_display_del_fbo (GstGLDisplay * display, GLuint fbo, GLuint depth_buffer) { gst_gl_display_lock (display); - display->del_fbo = fbo; - display->del_depth_buffer = depth_buffer; - gst_gl_window_send_message (display->gl_window, - GST_GL_WINDOW_CB (gst_gl_display_thread_del_fbo), display); + if (display->isAlive) { + display->del_fbo = fbo; + display->del_depth_buffer = depth_buffer; + gst_gl_window_send_message (display->gl_window, display->priv->vtable.del_fbo, display); + } gst_gl_display_unlock (display); } @@ -1268,19 +1552,20 @@ gst_gl_display_gen_shader (GstGLDisplay * display, const gchar * shader_vertex_source, const gchar * shader_fragment_source, GstGLShader ** shader) { - gboolean isAlive = FALSE; + gboolean isAlive; gst_gl_display_lock (display); - display->gen_shader_vertex_source = shader_vertex_source; - display->gen_shader_fragment_source = shader_fragment_source; - gst_gl_window_send_message (display->gl_window, - GST_GL_WINDOW_CB (gst_gl_display_thread_gen_shader), display); + if (display->isAlive) { + display->gen_shader_vertex_source = shader_vertex_source; + display->gen_shader_fragment_source = shader_fragment_source; + gst_gl_window_send_message (display->gl_window, display->priv->vtable.gen_shader, display); + if (shader) + *shader = display->gen_shader; + display->gen_shader = NULL; + display->gen_shader_vertex_source = NULL; + display->gen_shader_fragment_source = NULL; + } isAlive = display->isAlive; - if (shader) - *shader = display->gen_shader; - display->gen_shader = NULL; - display->gen_shader_vertex_source = NULL; - display->gen_shader_fragment_source = NULL; gst_gl_display_unlock (display); return isAlive; @@ -1292,9 +1577,10 @@ void gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader) { gst_gl_display_lock (display); - display->del_shader = shader; - gst_gl_window_send_message (display->gl_window, - GST_GL_WINDOW_CB (gst_gl_display_thread_del_shader), display); + if (display->isAlive) { + display->del_shader = shader; + gst_gl_window_send_message (display->gl_window, display->priv->vtable.del_shader, display); + } gst_gl_display_unlock (display); } @@ -1356,6 +1642,24 @@ gst_gl_display_activate_gl_context (GstGLDisplay * display, gboolean activate) gst_gl_display_unlock (display); } +GstGLAPI +gst_gl_display_get_gl_api_unlocked (GstGLDisplay * display) +{ + return display->gl_api; +} + +GstGLAPI +gst_gl_display_get_gl_api (GstGLDisplay * display) +{ + GstGLAPI api; + + gst_gl_display_lock (display); + api = gst_gl_display_get_gl_api_unlocked (display); + gst_gl_display_unlock (display); + + return api; +} + //------------------------------------------------------------ //------------------------ END PUBLIC ------------------------ //------------------------------------------------------------ diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index 54b4d5b2da..313880f85d 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -25,8 +25,11 @@ #include +typedef struct _GstGLUpload GstGLUpload; +typedef struct _GstGLDownload GstGLDownload; +typedef struct _GstGLShader GstGLShader; + #include "gstglwindow.h" -#include "gstglrenderer.h" #include "gstglshader.h" #include "gstglupload.h" #include "gstgldownload.h" @@ -34,18 +37,19 @@ G_BEGIN_DECLS GType gst_gl_display_get_type (void); -#define GST_TYPE_GL_DISPLAY (gst_gl_display_get_type()) -#define GST_GL_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_DISPLAY,GstGLDisplay)) +#define GST_GL_TYPE_DISPLAY (gst_gl_display_get_type()) +#define GST_GL_DISPLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_GL_TYPE_DISPLAY,GstGLDisplay)) #define GST_GL_DISPLAY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_DISPLAY,GstGLDisplayClass)) + (G_TYPE_CHECK_CLASS_CAST((klass),GST_GL_TYPE_DISPLAY,GstGLDisplayClass)) #define GST_IS_GL_DISPLAY(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_DISPLAY)) + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_GL_TYPE_DISPLAY)) #define GST_IS_GL_DISPLAY_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_DISPLAY)) + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_GL_TYPE_DISPLAY)) #define GST_GL_DISPLAY_CAST(obj) ((GstGLDisplay*)(obj)) typedef struct _GstGLDisplay GstGLDisplay; typedef struct _GstGLDisplayClass GstGLDisplayClass; +typedef struct _GstGLDisplayPrivate GstGLDisplayPrivate; /** * GstGLDisplayConversion: @@ -139,6 +143,9 @@ struct _GstGLDisplay GstGLWindow *gl_window; gboolean isAlive; + /* gl API we are using */ + GstGLAPI gl_api; + /* conditions */ GCond *cond_create_context; GCond *cond_destroy_context; @@ -152,10 +159,10 @@ struct _GstGLDisplay GLuint redisplay_texture_width; GLuint redisplay_texture_height; gboolean keep_aspect_ratio; -#ifdef OPENGL_ES2 +#if HAVE_GLES2 GstGLShader *redisplay_shader; - gchar *redisplay_vertex_shader_str; - gchar *redisplay_fragment_shader_str; + gchar *redisplay_vertex_shader_str_gles2; + gchar *redisplay_fragment_shader_str_gles2; GLint redisplay_attr_position_loc; GLint redisplay_attr_texture_loc; #endif @@ -214,6 +221,8 @@ struct _GstGLDisplay GstGLShader *del_shader; gchar *error_message; + + GstGLDisplayPrivate *priv; }; @@ -277,6 +286,8 @@ void gst_gl_display_check_framebuffer_status (void); void gst_gl_display_lock (GstGLDisplay * display); void gst_gl_display_unlock (GstGLDisplay * display); +GstGLAPI gst_gl_display_get_gl_api (GstGLDisplay * display); +GstGLAPI gst_gl_display_get_gl_api_unlocked (GstGLDisplay * display); G_END_DECLS diff --git a/gst-libs/gst/gl/gstgldownload.c b/gst-libs/gst/gl/gstgldownload.c index 74454d19e8..87dbb39275 100644 --- a/gst-libs/gst/gl/gstgldownload.c +++ b/gst-libs/gst/gl/gstgldownload.c @@ -43,11 +43,13 @@ * calling thread. */ +#define USING_OPENGL(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL3) +#define USING_GLES(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES) +#define USING_GLES2(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES2) +#define USING_GLES3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES3) + static void _do_download (GstGLDisplay * display, GstGLDownload * download); -static void _do_download_draw_rgb (GstGLDisplay * display, - GstGLDownload * download); -static void _do_download_draw_yuv (GstGLDisplay * display, - GstGLDownload * download); static void _init_download (GstGLDisplay * display, GstGLDownload * download); static void _init_download_shader (GstGLDisplay * display, GstGLDownload * download); @@ -56,18 +58,29 @@ static gboolean gst_gl_download_perform_with_data_unlocked (GstGLDownload * static gboolean gst_gl_download_perform_with_data_unlocked_thread (GstGLDownload * download, GLuint texture_id, gpointer data[GST_VIDEO_MAX_PLANES]); +#if HAVE_OPENGL +static void _do_download_draw_rgb_opengl (GstGLDisplay * display, + GstGLDownload * download); +static void _do_download_draw_yuv_opengl (GstGLDisplay * display, + GstGLDownload * download); +#endif +#if HAVE_GLES2 +static void _do_download_draw_rgb_gles2 (GstGLDisplay * display, + GstGLDownload * download); +static void _do_download_draw_yuv_gles2 (GstGLDisplay * display, + GstGLDownload * download); +#endif + +/* *INDENT-OFF* */ + /* YUY2:y2,u,y1,v UYVY:v,y1,u,y2 */ -static gchar *text_shader_download_YUY2_UYVY = -#ifndef OPENGL_ES2 +#if HAVE_OPENGL +static gchar *text_shader_YUY2_UYVY_opengl = "#extension GL_ARB_texture_rectangle : enable\n" "uniform sampler2DRect tex;\n" -#else - "precision mediump float;\n" - "varying vec2 v_texCoord;\n" "uniform sampler2D tex;\n" -#endif - "void main(void) {\n" " float fx,fy,r,g,b,r2,g2,b2,y1,y2,u,v;\n" -#ifndef OPENGL_ES2 + "void main(void) {\n" + " float fx,fy,r,g,b,r2,g2,b2,y1,y2,u,v;\n" " fx = gl_TexCoord[0].x;\n" " fy = gl_TexCoord[0].y;\n" " r=texture2DRect(tex,vec2(fx*2.0,fy)).r;\n" @@ -76,28 +89,18 @@ static gchar *text_shader_download_YUY2_UYVY = " r2=texture2DRect(tex,vec2(fx*2.0+1.0,fy)).r;\n" " g2=texture2DRect(tex,vec2(fx*2.0+1.0,fy)).g;\n" " b2=texture2DRect(tex,vec2(fx*2.0+1.0,fy)).b;\n" -#else - " fx = v_texCoord.x;\n" - " fy = v_texCoord.y;\n" - " r=texture2D(tex,vec2(fx*2.0,fy)).r;\n" - " g=texture2D(tex,vec2(fx*2.0,fy)).g;\n" - " b=texture2D(tex,vec2(fx*2.0,fy)).b;\n" - " r2=texture2D(tex,vec2(fx*2.0+1.0,fy)).r;\n" - " g2=texture2D(tex,vec2(fx*2.0+1.0,fy)).g;\n" - " b2=texture2D(tex,vec2(fx*2.0+1.0,fy)).b;\n" -#endif " y1=0.299011*r + 0.586987*g + 0.114001*b;\n" " y2=0.299011*r2 + 0.586987*g2 + 0.114001*b2;\n" " u=-0.148246*r -0.29102*g + 0.439266*b;\n" " v=0.439271*r - 0.367833*g - 0.071438*b ;\n" " y1=0.858885*y1 + 0.0625;\n" " y2=0.858885*y2 + 0.0625;\n" - " u=u + 0.5;\n" " v=v + 0.5;\n" " gl_FragColor=vec4(%s);\n" "}\n"; + " u=u + 0.5;\n" + " v=v + 0.5;\n" + " gl_FragColor=vec4(%s);\n" + "}\n"; -/* no OpenGL ES 2.0 support because for now it's not possible - * to attach multiple textures to a frame buffer object - */ -static gchar *text_shader_download_I420_YV12 = +static gchar *text_shader_I420_YV12_opengl = "#extension GL_ARB_texture_rectangle : enable\n" "uniform sampler2DRect tex;\n" "uniform float w, h;\n" @@ -119,48 +122,91 @@ static gchar *text_shader_download_I420_YV12 = " v=v + 0.5;\n" " gl_FragData[0] = vec4(y, 0.0, 0.0, 1.0);\n" " gl_FragData[1] = vec4(u, 0.0, 0.0, 1.0);\n" - " gl_FragData[2] = vec4(v, 0.0, 0.0, 1.0);\n" "}\n"; + " gl_FragData[2] = vec4(v, 0.0, 0.0, 1.0);\n" + "}\n"; -static gchar *text_shader_download_AYUV = -#ifndef OPENGL_ES2 +static gchar *text_shader_AYUV_opengl = "#extension GL_ARB_texture_rectangle : enable\n" "uniform sampler2DRect tex;\n" -#else - "precision mediump float;\n" - "varying vec2 v_texCoord;\n" "uniform sampler2D tex;\n" -#endif - "void main(void) {\n" " float r,g,b,y,u,v;\n" -#ifndef OPENGL_ES2 + "void main(void) {\n" + " float r,g,b,y,u,v;\n" " vec2 nxy=gl_TexCoord[0].xy;\n" " r=texture2DRect(tex,nxy).r;\n" - " g=texture2DRect(tex,nxy).g;\n" " b=texture2DRect(tex,nxy).b;\n" -#else - " vec2 nxy=v_texCoord.xy;\n" - " r=texture2D(tex,nxy).r;\n" - " g=texture2D(tex,nxy).g;\n" " b=texture2D(tex,nxy).b;\n" -#endif + " g=texture2DRect(tex,nxy).g;\n" + " b=texture2DRect(tex,nxy).b;\n" " y=0.299011*r + 0.586987*g + 0.114001*b;\n" " u=-0.148246*r -0.29102*g + 0.439266*b;\n" " v=0.439271*r - 0.367833*g - 0.071438*b ;\n" - " y=0.858885*y + 0.0625;\n" " u=u + 0.5;\n" " v=v + 0.5;\n" -#ifndef OPENGL_ES2 + " y=0.858885*y + 0.0625;\n" + " u=u + 0.5;\n" + " v=v + 0.5;\n" " gl_FragColor=vec4(y,u,v,1.0);\n" -#else - " gl_FragColor=vec4(1.0,y,u,v);\n" -#endif "}\n"; -#ifdef OPENGL_ES2 -static gchar *text_vertex_shader_download = +#define text_vertex_shader_opengl NULL +#endif /* HAVE_OPENGL */ + +#if HAVE_GLES2 +static gchar *text_shader_YUY2_UYVY_gles2 = + "precision mediump float;\n" + "varying vec2 v_texCoord;\n" + "uniform sampler2D tex;\n" + "void main(void) {\n" + " float fx,fy,r,g,b,r2,g2,b2,y1,y2,u,v;\n" + " fx = v_texCoord.x;\n" + " fy = v_texCoord.y;\n" + " r=texture2D(tex,vec2(fx*2.0,fy)).r;\n" + " g=texture2D(tex,vec2(fx*2.0,fy)).g;\n" + " b=texture2D(tex,vec2(fx*2.0,fy)).b;\n" + " r2=texture2D(tex,vec2(fx*2.0+1.0,fy)).r;\n" + " g2=texture2D(tex,vec2(fx*2.0+1.0,fy)).g;\n" + " b2=texture2D(tex,vec2(fx*2.0+1.0,fy)).b;\n" + " y1=0.299011*r + 0.586987*g + 0.114001*b;\n" + " y2=0.299011*r2 + 0.586987*g2 + 0.114001*b2;\n" + " u=-0.148246*r -0.29102*g + 0.439266*b;\n" + " v=0.439271*r - 0.367833*g - 0.071438*b ;\n" + " y1=0.858885*y1 + 0.0625;\n" + " y2=0.858885*y2 + 0.0625;\n" + " u=u + 0.5;\n" + " v=v + 0.5;\n" + " gl_FragColor=vec4(%s);\n" + "}\n"; + +/* no OpenGL ES 2.0 support because for now it's not possible + * to attach multiple textures to a frame buffer object + */ +#define text_shader_I420_YV12_gles2 NULL + +static gchar *text_shader_AYUV_gles2 = + "precision mediump float;\n" + "varying vec2 v_texCoord;\n" + "uniform sampler2D tex;\n" + "void main(void) {\n" + " float r,g,b,y,u,v;\n" + " vec2 nxy=v_texCoord.xy;\n" + " r=texture2D(tex,nxy).r;\n" + " g=texture2D(tex,nxy).g;\n" + " b=texture2D(tex,nxy).b;\n" + " y=0.299011*r + 0.586987*g + 0.114001*b;\n" + " u=-0.148246*r -0.29102*g + 0.439266*b;\n" + " v=0.439271*r - 0.367833*g - 0.071438*b ;\n" + " y=0.858885*y + 0.0625;\n" + " u=u + 0.5;\n" + " v=v + 0.5;\n" + " gl_FragColor=vec4(1.0,y,u,v);\n" + "}\n"; + +static gchar *text_vertex_shader_gles2 = "attribute vec4 a_position; \n" "attribute vec2 a_texCoord; \n" "varying vec2 v_texCoord; \n" "void main() \n" "{ \n" " gl_Position = a_position; \n" - " v_texCoord = a_texCoord; \n" "} \n"; + " v_texCoord = a_texCoord; \n" + "} \n"; -static gchar *text_fragment_shader_download_RGB = +static gchar *text_shader_RGB_gles2 = "precision mediump float; \n" "varying vec2 v_texCoord; \n" "uniform sampler2D s_texture; \n" @@ -168,7 +214,20 @@ static gchar *text_fragment_shader_download_RGB = "{ \n" " gl_FragColor = texture2D( s_texture, v_texCoord );\n" "} \n"; -#endif +#endif /* HAVE_GLES2 */ + +/* *INDENT-ON* */ + +struct _GstGLDownloadPrivate +{ + const gchar *YUY2_UYVY; + const gchar *I420_YV12; + const gchar *AYUV; + const gchar *vert_shader; + + void (*do_rgb) (GstGLDisplay * display, GstGLDownload * download); + void (*do_yuv) (GstGLDisplay * display, GstGLDownload * download); +}; GST_DEBUG_CATEGORY_STATIC (gst_gl_download_debug); #define GST_CAT_DEFAULT gst_gl_download_debug @@ -186,12 +245,17 @@ static void gst_gl_download_finalize (GObject * object); static void gst_gl_download_class_init (GstGLDownloadClass * klass) { + g_type_class_add_private (klass, sizeof (GstGLDownloadPrivate)); + G_OBJECT_CLASS (klass)->finalize = gst_gl_download_finalize; } static void gst_gl_download_init (GstGLDownload * download) { + + download->priv = GST_GL_DOWNLOAD_GET_PRIVATE (download); + download->display = NULL; g_mutex_init (&download->lock); @@ -201,10 +265,8 @@ gst_gl_download_init (GstGLDownload * download) download->in_texture = 0; download->shader = NULL; -#ifdef OPENGL_ES2 download->shader_attr_position_loc = 0; download->shader_attr_texture_loc = 0; -#endif gst_video_info_init (&download->info); } @@ -219,10 +281,33 @@ GstGLDownload * gst_gl_download_new (GstGLDisplay * display) { GstGLDownload *download; + GstGLDownloadPrivate *priv; download = g_object_new (GST_TYPE_GL_DOWNLOAD, NULL); download->display = g_object_ref (display); + priv = download->priv; + +#if HAVE_OPENGL + if (USING_OPENGL (display)) { + priv->YUY2_UYVY = text_shader_YUY2_UYVY_opengl; + priv->I420_YV12 = text_shader_I420_YV12_opengl; + priv->AYUV = text_shader_AYUV_opengl; + priv->vert_shader = text_vertex_shader_opengl; + priv->do_rgb = _do_download_draw_rgb_opengl; + priv->do_yuv = _do_download_draw_yuv_opengl; + } +#endif +#if HAVE_GLES2 + if (USING_GLES2 (display)) { + priv->YUY2_UYVY = text_shader_YUY2_UYVY_gles2; + priv->I420_YV12 = text_shader_I420_YV12_gles2; + priv->AYUV = text_shader_AYUV_gles2; + priv->vert_shader = text_vertex_shader_gles2; + priv->do_rgb = _do_download_draw_rgb_gles2; + priv->do_yuv = _do_download_draw_yuv_gles2; + } +#endif return download; } @@ -574,7 +659,7 @@ GstGLDownload * gst_gl_display_find_download_unlocked (GstGLDisplay * display, GstVideoFormat v_format, guint out_width, guint out_height) { - GstGLDownload *ret; + GstGLDownload *ret = NULL; GSList *walk; walk = display->downloads; @@ -641,6 +726,25 @@ _init_download (GstGLDisplay * display, GstGLDownload * download) GST_TRACE ("initializing texture download for format %d", v_format); + if (USING_OPENGL (display)) { + switch (v_format) { + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + goto no_convert; + break; + default: + break; + } + } + switch (v_format) { case GST_VIDEO_FORMAT_RGBx: case GST_VIDEO_FORMAT_BGRx: @@ -652,10 +756,6 @@ _init_download (GstGLDisplay * display, GstGLDownload * download) case GST_VIDEO_FORMAT_ABGR: case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: - /* color space conversion is not needed */ -#ifndef OPENGL_ES2 - break; -#endif case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_UYVY: case GST_VIDEO_FORMAT_I420: @@ -681,14 +781,19 @@ _init_download (GstGLDisplay * display, GstGLDownload * download) /* setup the render buffer for depth */ glGenRenderbuffersEXT (1, &download->depth_buffer); glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, download->depth_buffer); -#ifndef OPENGL_ES2 - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, - out_width, out_height); - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, - out_width, out_height); -#else - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, - out_width, out_height); +#if HAVE_OPENGL + if (USING_OPENGL (display)) { + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, + out_width, out_height); + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, + out_width, out_height); + } +#endif +#if HAVE_GLES2 + if (USING_GLES2 (display)) { + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, + out_width, out_height); + } #endif /* setup a first texture to render to */ @@ -754,10 +859,12 @@ _init_download (GstGLDisplay * display, GstGLDownload * download) glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, download->depth_buffer); -#ifndef OPENGL_ES2 - glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, - GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, - download->depth_buffer); +#if HAVE_GLES2 + if (USING_GLES2 (display)) { + glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, + GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, + download->depth_buffer); + } #endif gst_gl_display_check_framebuffer_status (); @@ -778,9 +885,38 @@ _init_download (GstGLDisplay * display, GstGLDownload * download) g_assert_not_reached (); } +no_convert: _init_download_shader (display, download); } +static gboolean +_create_shader (GstGLDisplay * display, const gchar * vertex_src, + const gchar * fragment_src, GstGLShader ** out_shader) +{ + GstGLShader *shader; + GError *error; + + g_return_val_if_fail (vertex_src != NULL || fragment_src != NULL, FALSE); + + shader = gst_gl_shader_new (display); + + if (vertex_src) + gst_gl_shader_set_vertex_source (shader, vertex_src); + if (fragment_src) + gst_gl_shader_set_fragment_source (shader, fragment_src); + + if (!gst_gl_shader_compile (shader, &error)) { + gst_gl_display_set_error (display, "%s", error->message); + g_error_free (error); + gst_gl_shader_use (NULL); + g_object_unref (G_OBJECT (shader)); + return FALSE; + } + + *out_shader = shader; + return TRUE; +} + static void _init_download_shader (GstGLDisplay * display, GstGLDownload * download) { @@ -800,32 +936,19 @@ _init_download_shader (GstGLDisplay * display, GstGLDownload * download) case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: /* color space conversion is not needed */ -#ifdef OPENGL_ES2 +#if HAVE_GLES2 { - /* glGetTexImage2D not available in OpenGL ES 2.0 */ - GError *error = NULL; - download->shader = gst_gl_shader_new (); - - gst_gl_shader_set_vertex_source (download->shader, - text_vertex_shader_download); - gst_gl_shader_set_fragment_source (download->shader, - text_fragment_shader_download_RGB); - - gst_gl_shader_compile (download->shader, &error); - if (error) { - gst_gl_display_set_error (display, "%s", error->message); - g_error_free (error); - error = NULL; - gst_gl_shader_use (NULL); - g_object_unref (G_OBJECT (download->shader)); - download->shader = NULL; - } else { - download->shader_attr_position_loc = - gst_gl_shader_get_attribute_location (download->shader, - "a_position"); - download->shader_attr_texture_loc = - gst_gl_shader_get_attribute_location (download->shader, - "a_texCoord"); + if (USING_GLES2 (display)) { + /* glGetTexImage2D not available in OpenGL ES 2.0 */ + if (_create_shader (display, text_vertex_shader_gles2, + text_shader_RGB_gles2, &download->shader)) { + download->shader_attr_position_loc = + gst_gl_shader_get_attribute_location (download->shader, + "a_position"); + download->shader_attr_texture_loc = + gst_gl_shader_get_attribute_location (download->shader, + "a_texCoord"); + } } } #endif @@ -837,9 +960,6 @@ _init_download_shader (GstGLDisplay * display, GstGLDownload * download) case GST_VIDEO_FORMAT_AYUV: /* color space conversion is needed */ { -#ifdef OPENGL_ES2 - GError *error = NULL; -#endif /* check if fragment shader is available, then load them * GLSL is a requirement for download */ @@ -854,132 +974,65 @@ _init_download_shader (GstGLDisplay * display, GstGLDownload * download) case GST_VIDEO_FORMAT_YUY2: { gchar text_shader_download_YUY2[2048]; + sprintf (text_shader_download_YUY2, - text_shader_download_YUY2_UYVY, "y2,u,y1,v"); + download->priv->YUY2_UYVY, "y2,u,y1,v"); - download->shader = gst_gl_shader_new (); -#ifndef OPENGL_ES2 - if (!gst_gl_shader_compile_and_check (download->shader, - text_shader_download_YUY2, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_display_set_error (display, - "Failed to initialize shader for downloading YUY2"); - g_object_unref (G_OBJECT (download->shader)); - download->shader = NULL; + if (_create_shader (display, download->priv->vert_shader, + text_shader_download_YUY2, &download->shader)) { + if (USING_GLES2 (display)) { + download->shader_attr_position_loc = + gst_gl_shader_get_attribute_location (download->shader, + "a_position"); + download->shader_attr_texture_loc = + gst_gl_shader_get_attribute_location (download->shader, + "a_texCoord"); + } } -#else - gst_gl_shader_set_vertex_source (download->shader, - text_vertex_shader_download); - gst_gl_shader_set_fragment_source (download->shader, - text_shader_download_YUY2); - - gst_gl_shader_compile (download->shader, &error); - if (error) { - gst_gl_display_set_error (display, "%s", error->message); - g_error_free (error); - error = NULL; - gst_gl_shader_use (NULL); - g_object_unref (G_OBJECT (download->shader)); - download->shader = NULL; - } else { - download->shader_attr_position_loc = - gst_gl_shader_get_attribute_location - (download->shader, "a_position"); - download->shader_attr_texture_loc = - gst_gl_shader_get_attribute_location - (download->shader, "a_texCoord"); - } -#endif } break; case GST_VIDEO_FORMAT_UYVY: { gchar text_shader_download_UYVY[2048]; + sprintf (text_shader_download_UYVY, - text_shader_download_YUY2_UYVY, "v,y1,u,y2"); + download->priv->YUY2_UYVY, "v,y1,u,y2"); - download->shader = gst_gl_shader_new (); - -#ifndef OPENGL_ES2 - if (!gst_gl_shader_compile_and_check (download->shader, - text_shader_download_UYVY, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_display_set_error (display, - "Failed to initialize shader for downloading UYVY"); - g_object_unref (G_OBJECT (download->shader)); - download->shader = NULL; + if (_create_shader (display, download->priv->vert_shader, + text_shader_download_UYVY, &download->shader)) { + if (USING_GLES2 (display)) { + download->shader_attr_position_loc = + gst_gl_shader_get_attribute_location (download->shader, + "a_position"); + download->shader_attr_texture_loc = + gst_gl_shader_get_attribute_location (download->shader, + "a_texCoord"); + } } -#else - gst_gl_shader_set_vertex_source (download->shader, - text_vertex_shader_download); - gst_gl_shader_set_fragment_source (download->shader, - text_shader_download_UYVY); - - gst_gl_shader_compile (download->shader, &error); - if (error) { - gst_gl_display_set_error (display, "%s", error->message); - g_error_free (error); - error = NULL; - gst_gl_shader_use (NULL); - g_object_unref (G_OBJECT (download->shader)); - download->shader = NULL; - } else { - download->shader_attr_position_loc = - gst_gl_shader_get_attribute_location - (download->shader, "a_position"); - download->shader_attr_texture_loc = - gst_gl_shader_get_attribute_location - (download->shader, "a_texCoord"); - } -#endif - } break; case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: - download->shader = gst_gl_shader_new (); - if (!gst_gl_shader_compile_and_check (download->shader, - text_shader_download_I420_YV12, - GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_display_set_error (display, - "Failed to initialize shader for downloading I420 or YV12"); - g_object_unref (G_OBJECT (download->shader)); - download->shader = NULL; - } + { + _create_shader (display, download->priv->vert_shader, + download->priv->I420_YV12, &download->shader); break; + } case GST_VIDEO_FORMAT_AYUV: - download->shader = gst_gl_shader_new (); - -#ifndef OPENGL_ES2 - if (!gst_gl_shader_compile_and_check (download->shader, - text_shader_download_AYUV, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_display_set_error (display, - "Failed to initialize shader for downloading AYUV"); - g_object_unref (G_OBJECT (download->shader)); - download->shader = NULL; + { + if (_create_shader (display, download->priv->vert_shader, + download->priv->AYUV, &download->shader)) { + if (USING_GLES2 (display)) { + download->shader_attr_position_loc = + gst_gl_shader_get_attribute_location (download->shader, + "a_position"); + download->shader_attr_texture_loc = + gst_gl_shader_get_attribute_location (download->shader, + "a_texCoord"); + } } -#else - gst_gl_shader_set_vertex_source (download->shader, - text_vertex_shader_download); - gst_gl_shader_set_fragment_source (download->shader, - text_shader_download_AYUV); - - gst_gl_shader_compile (download->shader, &error); - if (error) { - gst_gl_display_set_error (display, "%s", error->message); - g_error_free (error); - error = NULL; - gst_gl_shader_use (NULL); - g_object_unref (G_OBJECT (download->shader)); - download->shader = NULL; - } else { - download->shader_attr_position_loc = - gst_gl_shader_get_attribute_location - (download->shader, "a_position"); - download->shader_attr_texture_loc = - gst_gl_shader_get_attribute_location - (download->shader, "a_texCoord"); - } -#endif break; + } default: gst_gl_display_set_error (display, "Unsupported download video format %d", v_format); @@ -1022,7 +1075,7 @@ _do_download (GstGLDisplay * display, GstGLDownload * download) case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: /* color space conversion is not needed */ - _do_download_draw_rgb (display, download); + download->priv->do_rgb (display, download); break; case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_UYVY: @@ -1030,7 +1083,7 @@ _do_download (GstGLDisplay * display, GstGLDownload * download) case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_AYUV: /* color space conversion is needed */ - _do_download_draw_yuv (display, download); + download->priv->do_yuv (display, download); break; default: gst_gl_display_set_error (display, "Unsupported download video format %d", @@ -1040,19 +1093,77 @@ _do_download (GstGLDisplay * display, GstGLDownload * download) } } -/* called by _do_download (in the gl thread) */ +#if HAVE_OPENGL static void -_do_download_draw_rgb (GstGLDisplay * display, GstGLDownload * download) +_do_download_draw_rgb_opengl (GstGLDisplay * display, GstGLDownload * download) { GstVideoFormat v_format; -#ifndef OPENGL_ES2 if (download->display->colorspace_conversion == GST_GL_DISPLAY_CONVERSION_GLSL) glUseProgramObjectARB (0); glEnable (GL_TEXTURE_RECTANGLE_ARB); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->in_texture); + + v_format = GST_VIDEO_INFO_FORMAT (&download->info); + + switch (v_format) { + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_RGBx: + glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, + GL_UNSIGNED_BYTE, download->data[0]); + break; + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_ARGB: +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8, download->data[0]); #else + glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]); +#endif /* G_BYTE_ORDER */ + break; + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_BGRA: + glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA, + GL_UNSIGNED_BYTE, download->data[0]); + break; + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_ABGR: +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, + GL_UNSIGNED_INT_8_8_8_8, download->data[0]); +#else + glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, + GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]); +#endif /* G_BYTE_ORDER */ + break; + case GST_VIDEO_FORMAT_RGB: + glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, + GL_UNSIGNED_BYTE, download->data[0]); + break; + case GST_VIDEO_FORMAT_BGR: + glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGR, + GL_UNSIGNED_BYTE, download->data[0]); + break; + default: + gst_gl_display_set_error (display, + "Download video format inconsistency %d", v_format); + g_assert_not_reached (); + break; + } + + glReadBuffer (GL_NONE); + glDisable (GL_TEXTURE_RECTANGLE_ARB); +} +#endif + + +#if HAVE_GLES2 +static void +_do_download_draw_rgb_gles2 (GstGLDisplay * display, GstGLDownload * download) +{ + GstVideoFormat v_format; guint out_width, out_height; const GLfloat vVertices[] = { 1.0f, -1.0f, 0.0f, @@ -1094,32 +1205,17 @@ _do_download_draw_rgb (GstGLDisplay * display, GstGLDownload * download) glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); glUseProgramObjectARB (0); -#endif v_format = GST_VIDEO_INFO_FORMAT (&download->info); switch (v_format) { case GST_VIDEO_FORMAT_RGBA: case GST_VIDEO_FORMAT_RGBx: -#ifndef OPENGL_ES2 - glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, - GL_UNSIGNED_BYTE, download->data[0]); -#else glReadPixels (0, 0, out_width, out_height, GL_RGBA, GL_UNSIGNED_BYTE, download->data[0]); -#endif break; case GST_VIDEO_FORMAT_xRGB: case GST_VIDEO_FORMAT_ARGB: -#ifndef OPENGL_ES2 -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA, - GL_UNSIGNED_INT_8_8_8_8, download->data[0]); -#else - glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA, - GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]); -#endif /* G_BYTE_ORDER */ -#else /* OPENGL_ES2 */ #if G_BYTE_ORDER == G_LITTLE_ENDIAN glReadPixels (0, 0, out_width, out_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, download->data[0]); @@ -1127,41 +1223,16 @@ _do_download_draw_rgb (GstGLDisplay * display, GstGLDownload * download) glReadPixels (0, 0, out_width, out_eight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]); #endif /* G_BYTE_ORDER */ -#endif /* !OPENGL_ES2 */ + break; + case GST_VIDEO_FORMAT_RGB: + glReadPixels (0, 0, out_width, out_height, GL_RGB, GL_UNSIGNED_BYTE, + download->data[0]); break; case GST_VIDEO_FORMAT_BGRx: case GST_VIDEO_FORMAT_BGRA: -#ifndef OPENGL_ES2 - glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA, - GL_UNSIGNED_BYTE, download->data[0]); -#endif - break; case GST_VIDEO_FORMAT_xBGR: case GST_VIDEO_FORMAT_ABGR: -#ifndef OPENGL_ES2 -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, - GL_UNSIGNED_INT_8_8_8_8, download->data[0]); -#else - glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, - GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]); -#endif /* G_BYTE_ORDER */ -#endif /* !OPENGL_ES2 */ - break; - case GST_VIDEO_FORMAT_RGB: -#ifndef OPENGL_ES2 - glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, - GL_UNSIGNED_BYTE, download->data[0]); -#else - glReadPixels (0, 0, out_width, out_height, GL_RGB, GL_UNSIGNED_BYTE, - download->data[0]); -#endif - break; case GST_VIDEO_FORMAT_BGR: -#ifndef OPENGL_ES2 - glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGR, - GL_UNSIGNED_BYTE, download->data[0]); -#endif break; default: gst_gl_display_set_error (display, @@ -1169,42 +1240,21 @@ _do_download_draw_rgb (GstGLDisplay * display, GstGLDownload * download) g_assert_not_reached (); break; } - -#ifndef OPENGL_ES2 - glReadBuffer (GL_NONE); - glDisable (GL_TEXTURE_RECTANGLE_ARB); -#endif } +#endif - -/* called by _do_download (in the gl thread) */ +#if HAVE_OPENGL static void -_do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download) +_do_download_draw_yuv_opengl (GstGLDisplay * display, GstGLDownload * download) { GstVideoFormat v_format; guint out_width, out_height; -#ifndef OPENGL_ES2 GLenum multipleRT[] = { GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT }; -#else - GLint viewport_dim[4]; - - const GLfloat vVertices[] = { 1.0f, -1.0f, 0.0f, - 1.0f, 0.0f, - -1.0f, -1.0f, 0.0f, - 0.0f, .0f, - -1.0f, 1.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 1.0f, 0.0f, - 1.0f, 1.0f - }; - - GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; -#endif out_width = GST_VIDEO_INFO_WIDTH (&download->info); out_height = GST_VIDEO_INFO_HEIGHT (&download->info); @@ -1215,7 +1265,6 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download) glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, download->fbo); -#ifndef OPENGL_ES2 glPushAttrib (GL_VIEWPORT_BIT); glMatrixMode (GL_PROJECTION); @@ -1226,9 +1275,6 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download) glMatrixMode (GL_MODELVIEW); glPushMatrix (); glLoadIdentity (); -#else /* OPENGL_ES2 */ - glGetIntegerv (GL_VIEWPORT, viewport_dim); -#endif glViewport (0, 0, out_width, out_height); @@ -1237,27 +1283,15 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download) case GST_VIDEO_FORMAT_UYVY: case GST_VIDEO_FORMAT_AYUV: { -#ifndef OPENGL_ES2 glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT); -#endif glClearColor (0.0, 0.0, 0.0, 0.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); gst_gl_shader_use (download->shader); -#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); -#else - glVertexAttribPointer (download->shader_attr_position_loc, 3, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); - glVertexAttribPointer (download->shader_attr_texture_loc, 2, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); - - glEnableVertexAttribArray (download->shader_attr_position_loc); - glEnableVertexAttribArray (download->shader_attr_texture_loc); -#endif glActiveTextureARB (GL_TEXTURE0_ARB); gst_gl_shader_set_uniform_1i (download->shader, "tex", 0); @@ -1268,19 +1302,15 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download) case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: { -#ifndef OPENGL_ES2 glDrawBuffers (3, multipleRT); -#endif glClearColor (0.0, 0.0, 0.0, 0.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); gst_gl_shader_use (download->shader); -#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); -#endif glActiveTextureARB (GL_TEXTURE0_ARB); gst_gl_shader_set_uniform_1i (download->shader, "tex", 0); @@ -1297,7 +1327,6 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download) } -#ifndef OPENGL_ES2 glBegin (GL_QUADS); glTexCoord2i (0, 0); glVertex2f (-1.0f, -1.0f); @@ -1310,9 +1339,6 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download) glEnd (); glDrawBuffer (GL_NONE); -#else /* OPENGL_ES2 */ - glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); -#endif /* don't check if GLSL is available * because download yuv is not available @@ -1320,24 +1346,17 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download) */ glUseProgramObjectARB (0); -#ifndef OPENGL_ES2 glDisable (GL_TEXTURE_RECTANGLE_ARB); glMatrixMode (GL_PROJECTION); glPopMatrix (); glMatrixMode (GL_MODELVIEW); glPopMatrix (); glPopAttrib (); -#else - glViewport (viewport_dim[0], viewport_dim[1], viewport_dim[2], - viewport_dim[3]); -#endif gst_gl_display_check_framebuffer_status (); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, download->fbo); -#ifndef OPENGL_ES2 glReadBuffer (GL_COLOR_ATTACHMENT0_EXT); -#endif switch (v_format) { case GST_VIDEO_FORMAT_AYUV: @@ -1364,17 +1383,13 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download) glReadPixels (0, 0, out_width, out_height, GL_LUMINANCE, GL_UNSIGNED_BYTE, download->data[0]); -#ifndef OPENGL_ES2 glReadBuffer (GL_COLOR_ATTACHMENT1_EXT); -#endif glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, download->data[1]); -#ifndef OPENGL_ES2 glReadBuffer (GL_COLOR_ATTACHMENT2_EXT); -#endif glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, @@ -1386,17 +1401,13 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download) glReadPixels (0, 0, out_width, out_height, GL_LUMINANCE, GL_UNSIGNED_BYTE, download->data[0]); -#ifndef OPENGL_ES2 glReadBuffer (GL_COLOR_ATTACHMENT1_EXT); -#endif glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, download->data[2]); -#ifndef OPENGL_ES2 glReadBuffer (GL_COLOR_ATTACHMENT2_EXT); -#endif glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, @@ -1409,11 +1420,167 @@ _do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download) "Download video format inconsistensy %d", v_format); g_assert_not_reached (); } -#ifndef OPENGL_ES2 glReadBuffer (GL_NONE); -#endif gst_gl_display_check_framebuffer_status (); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); } +#endif + +#if HAVE_GLES2 +static void +_do_download_draw_yuv_gles2 (GstGLDisplay * display, GstGLDownload * download) +{ + GstVideoFormat v_format; + guint out_width, out_height; + + GLint viewport_dim[4]; + + const GLfloat vVertices[] = { 1.0f, -1.0f, 0.0f, + 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 0.0f, .0f, + -1.0f, 1.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f + }; + + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + out_width = GST_VIDEO_INFO_WIDTH (&download->info); + out_height = GST_VIDEO_INFO_HEIGHT (&download->info); + v_format = GST_VIDEO_INFO_FORMAT (&download->info); + + GST_TRACE ("doing YUV download of texture:%u (%ux%u) using fbo:%u", + download->in_texture, out_width, out_height, download->fbo); + + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, download->fbo); + + glGetIntegerv (GL_VIEWPORT, viewport_dim); + + glViewport (0, 0, out_width, out_height); + + switch (v_format) { + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_AYUV: + { + glClearColor (0.0, 0.0, 0.0, 0.0); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + gst_gl_shader_use (download->shader); + + glVertexAttribPointer (download->shader_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); + glVertexAttribPointer (download->shader_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (download->shader_attr_position_loc); + glEnableVertexAttribArray (download->shader_attr_texture_loc); + + glActiveTextureARB (GL_TEXTURE0_ARB); + gst_gl_shader_set_uniform_1i (download->shader, "tex", 0); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->in_texture); + } + break; + + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + { + glClearColor (0.0, 0.0, 0.0, 0.0); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + gst_gl_shader_use (download->shader); + + glActiveTextureARB (GL_TEXTURE0_ARB); + gst_gl_shader_set_uniform_1i (download->shader, "tex", 0); + gst_gl_shader_set_uniform_1f (download->shader, "w", (gfloat) out_width); + gst_gl_shader_set_uniform_1f (download->shader, "h", (gfloat) out_height); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->in_texture); + } + break; + + default: + break; + gst_gl_display_set_error (display, + "Download video format inconsistensy %d", v_format); + + } + + glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + + /* don't check if GLSL is available + * because download yuv is not available + * without GLSL (whereas rgb is) + */ + glUseProgramObjectARB (0); + + glViewport (viewport_dim[0], viewport_dim[1], viewport_dim[2], + viewport_dim[3]); + + gst_gl_display_check_framebuffer_status (); + + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, download->fbo); + + switch (v_format) { + case GST_VIDEO_FORMAT_AYUV: +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + glReadPixels (0, 0, out_width, out_height, GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8, download->data[0]); +#else + glReadPixels (0, 0, out_width, out_height, GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]); +#endif + break; + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, out_height, GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]); +#else + glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, out_height, GL_BGRA, + GL_UNSIGNED_INT_8_8_8_8, download->data[0]); +#endif + break; + case GST_VIDEO_FORMAT_I420: + { + glReadPixels (0, 0, out_width, out_height, GL_LUMINANCE, GL_UNSIGNED_BYTE, + download->data[0]); + + glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, + GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, + download->data[1]); + + glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, + GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, + download->data[2]); + } + break; + case GST_VIDEO_FORMAT_YV12: + { + glReadPixels (0, 0, out_width, out_height, GL_LUMINANCE, GL_UNSIGNED_BYTE, + download->data[0]); + + glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, + GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, + download->data[2]); + + glReadPixels (0, 0, GST_ROUND_UP_2 (out_width) / 2, + GST_ROUND_UP_2 (out_height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE, + download->data[1]); + } + break; + default: + break; + gst_gl_display_set_error (display, + "Download video format inconsistensy %d", v_format); + g_assert_not_reached (); + } + + gst_gl_display_check_framebuffer_status (); + + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); +} +#endif diff --git a/gst-libs/gst/gl/gstgldownload.h b/gst-libs/gst/gl/gstgldownload.h index ed94728399..a06677361e 100644 --- a/gst-libs/gst/gl/gstgldownload.h +++ b/gst-libs/gst/gl/gstgldownload.h @@ -24,8 +24,8 @@ #include #include -#include "gstglshader.h" #include "gstgldisplay.h" +#include "gstglshader.h" G_BEGIN_DECLS @@ -43,6 +43,7 @@ GType gst_gl_download_get_type (void); typedef struct _GstGLDownload GstGLDownload; typedef struct _GstGLDownloadClass GstGLDownloadClass; +typedef struct _GstGLDownloadPrivate GstGLDownloadPrivate; /** * GstGLDownload @@ -74,10 +75,10 @@ struct _GstGLDownload GLuint in_texture; GLuint out_texture[GST_VIDEO_MAX_PLANES]; GstGLShader *shader; -#ifdef OPENGL_ES2 GLint shader_attr_position_loc; GLint shader_attr_texture_loc; -#endif + + GstGLDownloadPrivate *priv; gpointer _reserved[GST_PADDING]; }; @@ -97,12 +98,12 @@ struct _GstGLDownloadClass * * The currently supported formats that can be downloaded */ -#ifndef OPENGL_ES2 +#if !HAVE_GLES2 # define GST_GL_DOWNLOAD_FORMATS "{ RGB, RGBx, RGBA, BGR, BGRx, BGRA, xRGB, " \ "xBGR, ARGB, ABGR, I420, YV12, YUY2, UYVY, AYUV }" -#else /* OPENGL_ES2 */ +#else /* HAVE_GLES2 */ # define GST_GL_DOWNLOAD_FORMATS "{ RGB, RGBx, RGBA, I420, YV12, YUY2, UYVY, AYUV }" -#endif /* !OPENGL_ES2 */ +#endif /* !HAVE_GLES2 */ /** * GST_GL_DOWNLOAD_VIDEO_CAPS: diff --git a/gst-libs/gst/gl/gstglfilter.c b/gst-libs/gst/gl/gstglfilter.c index 4c80b90b90..9a91a99679 100644 --- a/gst-libs/gst/gl/gstglfilter.c +++ b/gst-libs/gst/gl/gstglfilter.c @@ -1075,7 +1075,7 @@ gst_gl_filter_render_to_target (GstGLFilter * filter, gboolean resize, in_width, 0, in_height, GST_GL_DISPLAY_PROJECTION_ORTHO2D, data); } -#ifndef OPENGL_ES2 +#if HAVE_OPENGL static void _draw_with_shader_cb (gint width, gint height, guint texture, gpointer stuff) { @@ -1116,6 +1116,9 @@ void gst_gl_filter_render_to_target_with_shader (GstGLFilter * filter, gboolean resize, GLuint input, GLuint target, GstGLShader * shader) { + g_return_if_fail (gst_gl_display_get_gl_api (filter->display) & + GST_GL_API_OPENGL); + filter->default_shader = shader; gst_gl_filter_render_to_target (filter, resize, input, target, _draw_with_shader_cb, filter); @@ -1153,4 +1156,4 @@ gst_gl_filter_draw_texture (GstGLFilter * filter, GLuint texture, glEnd (); } -#endif +#endif /* HAVE_OPENGL */ diff --git a/gst-libs/gst/gl/gstglfilter.h b/gst-libs/gst/gl/gstglfilter.h index 6d6d9b95dd..405960393d 100644 --- a/gst-libs/gst/gl/gstglfilter.h +++ b/gst-libs/gst/gl/gstglfilter.h @@ -124,12 +124,12 @@ gboolean gst_gl_filter_filter_texture (GstGLFilter * filter, GstBuffer * inbuf, void gst_gl_filter_render_to_target (GstGLFilter *filter, gboolean resize, GLuint input, GLuint target, GLCB func, gpointer data); -#ifndef OPENGL_ES2 +#if HAVE_OPENGL void gst_gl_filter_render_to_target_with_shader (GstGLFilter * filter, gboolean resize, GLuint input, GLuint target, GstGLShader *shader); void gst_gl_filter_draw_texture (GstGLFilter *filter, GLuint texture, guint width, guint height); -#endif /* !OPENGL_ES2 */ +#endif /* HAVE_OPENGL */ G_END_DECLS diff --git a/gst-libs/gst/gl/gstglmemory.c b/gst-libs/gst/gl/gstglmemory.c index 611929bec2..25db723bec 100644 --- a/gst-libs/gst/gl/gstglmemory.c +++ b/gst-libs/gst/gl/gstglmemory.c @@ -40,6 +40,12 @@ * Data is uploaded or downloaded from the GPU as is necessary. */ +#define USING_OPENGL(display) (display->gl_api & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (display->gl_api & GST_GL_API_OPENGL3) +#define USING_GLES(display) (display->gl_api & GST_GL_API_GLES) +#define USING_GLES2(display) (display->gl_api & GST_GL_API_GLES2) +#define USING_GLES3(display) (display->gl_api & GST_GL_API_GLES3) + GST_DEBUG_CATEGORY_STATIC (GST_CAT_GL_MEMORY); #define GST_CAT_DEFUALT GST_CAT_GL_MEMORY @@ -220,22 +226,29 @@ _gl_mem_copy_thread (GstGLDisplay * display, gpointer data) glGenRenderbuffersEXT (1, &rboId); glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, rboId); -#ifndef OPENGL_ES2 - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, - height); - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, - width, height); -#else - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, - width, height); +#if HAVE_OPENGL + if (USING_OPENGL (display)) { + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, + height); + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, + width, height); + } +#endif +#if HAVE_GLES2 + if (USING_GLES2 (display)) { + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, + width, height); + } #endif /* attach the renderbuffer to depth attachment point */ glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId); -#ifndef OPENGL_ES2 - glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, - GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId); +#if HAVE_OPENGL + if (USING_OPENGL (display)) { + glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, + GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rboId); + } #endif glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, @@ -264,7 +277,7 @@ _gl_mem_copy_thread (GstGLDisplay * display, gpointer data) GST_CAT_ERROR (GST_CAT_GL_MEMORY, "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); break; -#ifndef OPENGL_ES2 +#if HAVE_OPENGL case GL_FRAMEBUFFER_UNDEFINED: GST_CAT_ERROR (GST_CAT_GL_MEMORY, "GL_FRAMEBUFFER_UNDEFINED"); break; diff --git a/gst-libs/gst/gl/gstglshader.c b/gst-libs/gst/gl/gstglshader.c index 89087fe922..ddbaa3b852 100644 --- a/gst-libs/gst/gl/gstglshader.c +++ b/gst-libs/gst/gl/gstglshader.c @@ -27,6 +27,12 @@ #define GST_GL_SHADER_GET_PRIVATE(o) \ (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_SHADER, GstGLShaderPrivate)) +#define USING_OPENGL(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL3) +#define USING_GLES(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES) +#define USING_GLES2(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES2) +#define USING_GLES3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES3) + enum { PROP_0, @@ -251,9 +257,13 @@ gst_gl_shader_init (GstGLShader * self) } GstGLShader * -gst_gl_shader_new (void) +gst_gl_shader_new (GstGLDisplay * display) { - return g_object_new (GST_GL_TYPE_SHADER, NULL); + GstGLShader *shader = g_object_new (GST_GL_TYPE_SHADER, NULL); + + shader->display = display; + + return shader; } gboolean @@ -270,7 +280,7 @@ gst_gl_shader_compile (GstGLShader * shader, GError ** error) GstGLShaderPrivate *priv; gchar info_buffer[2048]; - GLsizei len = 0; + gint len = 0; GLint status = GL_FALSE; g_return_val_if_fail (GST_GL_IS_SHADER (shader), FALSE); @@ -293,12 +303,15 @@ gst_gl_shader_compile (GstGLShader * shader, GError ** error) glGetObjectParameterivARB (priv->vertex_handle, GL_OBJECT_COMPILE_STATUS_ARB, &status); -#ifndef OPENGL_ES2 - glGetInfoLogARB (priv->vertex_handle, - sizeof (info_buffer) - 1, &len, info_buffer); -#else - glGetShaderInfoLog (priv->vertex_handle, - sizeof (info_buffer) - 1, &len, info_buffer); +#if HAVE_OPENGL + if (USING_OPENGL (shader->display)) + glGetInfoLogARB (priv->vertex_handle, + sizeof (info_buffer) - 1, &len, info_buffer); +#endif +#if HAVE_GLES2 + if (USING_GLES2 (shader->display)) + glGetShaderInfoLog (priv->vertex_handle, + sizeof (info_buffer) - 1, &len, info_buffer); #endif info_buffer[len] = '\0'; @@ -329,12 +342,15 @@ gst_gl_shader_compile (GstGLShader * shader, GError ** error) glGetObjectParameterivARB (priv->fragment_handle, GL_OBJECT_COMPILE_STATUS_ARB, &status); -#ifndef OPENGL_ES2 - glGetInfoLogARB (priv->fragment_handle, - sizeof (info_buffer) - 1, &len, info_buffer); -#else - glGetShaderInfoLog (priv->fragment_handle, - sizeof (info_buffer) - 1, &len, info_buffer); +#if HAVE_OPENGL + if (USING_OPENGL (shader->display)) + glGetInfoLogARB (priv->fragment_handle, + sizeof (info_buffer) - 1, &len, info_buffer); +#endif +#if HAVE_GLES2 + if (USING_GLES2 (shader->display)) + glGetShaderInfoLog (priv->fragment_handle, + sizeof (info_buffer) - 1, &len, info_buffer); #endif info_buffer[len] = '\0'; if (status != GL_TRUE) { @@ -356,10 +372,13 @@ gst_gl_shader_compile (GstGLShader * shader, GError ** error) /* if nothing failed link shaders */ glLinkProgramARB (priv->program_handle); -#ifndef OPENGL_ES2 - glGetObjectParameterivARB (priv->program_handle, GL_LINK_STATUS, &status); -#else - glGetProgramiv (priv->program_handle, GL_LINK_STATUS, &status); +#if HAVE_OPENGL + if (USING_OPENGL (shader->display)) + glGetObjectParameterivARB (priv->program_handle, GL_LINK_STATUS, &status); +#endif +#if HAVE_GLES2 + if (USING_GLES2 (shader->display)) + glGetProgramiv (priv->program_handle, GL_LINK_STATUS, &status); #endif glGetInfoLogARB (priv->program_handle, @@ -400,10 +419,13 @@ gst_gl_shader_release (GstGLShader * shader) if (priv->vertex_handle) { /* not needed but nvidia doesn't care to respect the spec */ GST_TRACE ("finalizing vertex shader %u", priv->vertex_handle); -#ifndef OPENGL_ES2 - glDeleteObjectARB (priv->vertex_handle); -#else - glDeleteShader (priv->vertex_handle); +#if HAVE_OPENGL + if (USING_OPENGL (shader->display)) + glDeleteObjectARB (priv->vertex_handle); +#endif +#if HAVE_GLES2 + if (USING_GLES2 (shader->display)) + glDeleteShader (priv->vertex_handle); #endif /* err = glGetError (); */ @@ -415,10 +437,14 @@ gst_gl_shader_release (GstGLShader * shader) if (priv->fragment_handle) { GST_TRACE ("finalizing fragment shader %u", priv->fragment_handle); -#ifndef OPENGL_ES2 - glDeleteObjectARB (priv->fragment_handle); -#else - glDeleteShader (priv->fragment_handle); + +#if HAVE_OPENGL + if (USING_OPENGL (shader->display)) + glDeleteObjectARB (priv->fragment_handle); +#endif +#if HAVE_GLES2 + if (USING_GLES2 (shader->display)) + glDeleteShader (priv->fragment_handle); #endif /* err = glGetError (); */ @@ -748,7 +774,7 @@ gst_gl_shader_set_uniform_4iv (GstGLShader * shader, const gchar * name, void gst_gl_shader_set_uniform_matrix_2fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat * value) + gint count, gboolean transpose, const gfloat * value) { GstGLShaderPrivate *priv; GLint location = -1; @@ -762,11 +788,42 @@ gst_gl_shader_set_uniform_matrix_2fv (GstGLShader * shader, const gchar * name, glUniformMatrix2fvARB (location, count, transpose, value); } -#ifndef OPENGL_ES2 +void +gst_gl_shader_set_uniform_matrix_3fv (GstGLShader * shader, const gchar * name, + gint count, gboolean transpose, const gfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniformMatrix3fvARB (location, count, transpose, value); +} + +void +gst_gl_shader_set_uniform_matrix_4fv (GstGLShader * shader, const gchar * name, + gint count, gboolean transpose, const gfloat * value) +{ + GstGLShaderPrivate *priv; + GLint location = -1; + + priv = shader->priv; + + g_return_if_fail (priv->program_handle != 0); + + location = glGetUniformLocationARB (priv->program_handle, name); + + glUniformMatrix4fvARB (location, count, transpose, value); +} + +#if HAVE_OPENGL void gst_gl_shader_set_uniform_matrix_2x3fv (GstGLShader * shader, - const gchar * name, GLsizei count, GLboolean transpose, - const GLfloat * value) + const gchar * name, gint count, gboolean transpose, const gfloat * value) { GstGLShaderPrivate *priv; GLint location = -1; @@ -782,8 +839,7 @@ gst_gl_shader_set_uniform_matrix_2x3fv (GstGLShader * shader, void gst_gl_shader_set_uniform_matrix_2x4fv (GstGLShader * shader, - const gchar * name, GLsizei count, GLboolean transpose, - const GLfloat * value) + const gchar * name, gint count, gboolean transpose, const gfloat * value) { GstGLShaderPrivate *priv; GLint location = -1; @@ -796,29 +852,10 @@ gst_gl_shader_set_uniform_matrix_2x4fv (GstGLShader * shader, glUniformMatrix2x4fv (location, count, transpose, value); } -#endif -void -gst_gl_shader_set_uniform_matrix_3fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat * value) -{ - GstGLShaderPrivate *priv; - GLint location = -1; - - priv = shader->priv; - - g_return_if_fail (priv->program_handle != 0); - - location = glGetUniformLocationARB (priv->program_handle, name); - - glUniformMatrix3fvARB (location, count, transpose, value); -} - -#ifndef OPENGL_ES2 void gst_gl_shader_set_uniform_matrix_3x2fv (GstGLShader * shader, - const gchar * name, GLsizei count, GLboolean transpose, - const GLfloat * value) + const gchar * name, gint count, gboolean transpose, const gfloat * value) { GstGLShaderPrivate *priv; GLint location = -1; @@ -834,8 +871,7 @@ gst_gl_shader_set_uniform_matrix_3x2fv (GstGLShader * shader, void gst_gl_shader_set_uniform_matrix_3x4fv (GstGLShader * shader, - const gchar * name, GLsizei count, GLboolean transpose, - const GLfloat * value) + const gchar * name, gint count, gboolean transpose, const gfloat * value) { GstGLShaderPrivate *priv; GLint location = -1; @@ -848,29 +884,10 @@ gst_gl_shader_set_uniform_matrix_3x4fv (GstGLShader * shader, glUniformMatrix3x4fv (location, count, transpose, value); } -#endif -void -gst_gl_shader_set_uniform_matrix_4fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat * value) -{ - GstGLShaderPrivate *priv; - GLint location = -1; - - priv = shader->priv; - - g_return_if_fail (priv->program_handle != 0); - - location = glGetUniformLocationARB (priv->program_handle, name); - - glUniformMatrix4fvARB (location, count, transpose, value); -} - -#ifndef OPENGL_ES2 void gst_gl_shader_set_uniform_matrix_4x2fv (GstGLShader * shader, - const gchar * name, GLsizei count, GLboolean transpose, - const GLfloat * value) + const gchar * name, gint count, gboolean transpose, const gfloat * value) { GstGLShaderPrivate *priv; GLint location = -1; @@ -886,8 +903,7 @@ gst_gl_shader_set_uniform_matrix_4x2fv (GstGLShader * shader, void gst_gl_shader_set_uniform_matrix_4x3fv (GstGLShader * shader, - const gchar * name, GLsizei count, GLboolean transpose, - const GLfloat * value) + const gchar * name, gint count, gboolean transpose, const gfloat * value) { GstGLShaderPrivate *priv; GLint location = -1; @@ -900,7 +916,7 @@ gst_gl_shader_set_uniform_matrix_4x3fv (GstGLShader * shader, glUniformMatrix4x3fv (location, count, transpose, value); } -#endif +#endif /* HAVE_OPENGL */ GLint gst_gl_shader_get_attribute_location (GstGLShader * shader, const gchar * name) diff --git a/gst-libs/gst/gl/gstglshader.h b/gst-libs/gst/gl/gstglshader.h index c193d489ec..27ba5830f2 100644 --- a/gst-libs/gst/gl/gstglshader.h +++ b/gst-libs/gst/gl/gstglshader.h @@ -21,18 +21,17 @@ #ifndef __GST_GL_SHADER_H__ #define __GST_GL_SHADER_H__ -/* OpenGL 2.0 for Embedded Systems */ -#ifdef OPENGL_ES2 -#include -#include "gstgles2.h" -/* OpenGL for usual systems */ -#else -#include +#ifdef HAVE_CONFIG_H +#include "config.h" #endif + +#include "gstgldisplay.h" #include G_BEGIN_DECLS +typedef struct _GstGLDisplay GstGLDisplay; + #define GST_GL_TYPE_SHADER (gst_gl_shader_get_type()) #define GST_GL_SHADER(o) (G_TYPE_CHECK_INSTANCE_CAST((o), GST_GL_TYPE_SHADER, GstGLShader)) #define GST_GL_SHADER_CLASS(k) (G_TYPE_CHECK_CLASS((k), GST_GL_TYPE_SHADER, GstGLShaderClass)) @@ -60,6 +59,9 @@ typedef struct _GstGLShaderClass GstGLShaderClass; struct _GstGLShader { /*< private >*/ GObject parent; + + GstGLDisplay *display; + GstGLShaderPrivate *priv; }; @@ -73,68 +75,51 @@ struct _GstGLShaderClass { GQuark gst_gl_shader_error_quark (void); GType gst_gl_shader_get_type (void); -GstGLShader * gst_gl_shader_new (void); +GstGLShader * gst_gl_shader_new (GstGLDisplay *display); -void gst_gl_shader_set_vertex_source (GstGLShader *shader, - const gchar *src); -void gst_gl_shader_set_fragment_source (GstGLShader *shader, - const gchar *src); -const gchar * gst_gl_shader_get_vertex_source (GstGLShader *shader); +void gst_gl_shader_set_vertex_source (GstGLShader *shader, const gchar *src); +void gst_gl_shader_set_fragment_source (GstGLShader *shader, const gchar *src); +const gchar * gst_gl_shader_get_vertex_source (GstGLShader *shader); const gchar * gst_gl_shader_get_fragment_source (GstGLShader *shader); -void gst_gl_shader_set_active (GstGLShader *shader, - gboolean active); - -gboolean gst_gl_shader_is_compiled (GstGLShader *shader); - -gboolean gst_gl_shader_compile (GstGLShader *shader, GError **error); +void gst_gl_shader_set_active (GstGLShader *shader, gboolean active); +gboolean gst_gl_shader_is_compiled (GstGLShader *shader); +gboolean gst_gl_shader_compile (GstGLShader *shader, GError **error); gboolean gst_gl_shader_compile_and_check (GstGLShader *shader, const gchar *source, GstGLShaderSourceType type); + void gst_gl_shader_release (GstGLShader *shader); -void gst_gl_shader_use (GstGLShader *shader); +void gst_gl_shader_use (GstGLShader *shader); -void gst_gl_shader_set_uniform_1i (GstGLShader *shader, const gchar *name, gint value); -void gst_gl_shader_set_uniform_1iv (GstGLShader *shader, const gchar *name, guint count, gint * value); -void gst_gl_shader_set_uniform_1f (GstGLShader *shader, const gchar *name, gfloat value); -void gst_gl_shader_set_uniform_1fv (GstGLShader *shader, const gchar *name, guint count, gfloat * value); -void gst_gl_shader_set_uniform_2i (GstGLShader *shader, const gchar *name, gint v0, gint v1); -void gst_gl_shader_set_uniform_2iv (GstGLShader *shader, const gchar *name, guint count, gint * value); -void gst_gl_shader_set_uniform_2f (GstGLShader *shader, const gchar *name, gfloat v0, gfloat v1); -void gst_gl_shader_set_uniform_2fv (GstGLShader *shader, const gchar *name, guint count, gfloat * value); -void gst_gl_shader_set_uniform_3i (GstGLShader *shader, const gchar *name, gint v0, gint v1, gint v2); -void gst_gl_shader_set_uniform_3iv (GstGLShader *shader, const gchar *name, guint count, gint * value); -void gst_gl_shader_set_uniform_3f (GstGLShader *shader, const gchar *name, gfloat v0, gfloat v1, gfloat v2); -void gst_gl_shader_set_uniform_3fv (GstGLShader *shader, const gchar *name, guint count, gfloat * value); -void gst_gl_shader_set_uniform_4i (GstGLShader *shader, const gchar *name, gint v0, gint v1, gint v2, gint v3); -void gst_gl_shader_set_uniform_4iv (GstGLShader *shader, const gchar *name, guint count, gint * value); -void gst_gl_shader_set_uniform_4f (GstGLShader *shader, const gchar *name, gfloat v0, gfloat v1, gfloat v2, gfloat v3); -void gst_gl_shader_set_uniform_4fv (GstGLShader *shader, const gchar *name, guint count, gfloat * value); -void gst_gl_shader_set_uniform_matrix_2fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat* value); -#ifndef OPENGL_ES2 -void gst_gl_shader_set_uniform_matrix_2x3fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat* value); -void gst_gl_shader_set_uniform_matrix_2x4fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat* value); -#endif -void gst_gl_shader_set_uniform_matrix_3fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat* value); -#ifndef OPENGL_ES2 -void gst_gl_shader_set_uniform_matrix_3x2fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat* value); -void gst_gl_shader_set_uniform_matrix_3x4fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat* value); -#endif -void gst_gl_shader_set_uniform_matrix_4fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat* value); -#ifndef OPENGL_ES2 -void gst_gl_shader_set_uniform_matrix_4x2fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat* value); -void gst_gl_shader_set_uniform_matrix_4x3fv (GstGLShader * shader, const gchar * name, - GLsizei count, GLboolean transpose, const GLfloat* value); +void gst_gl_shader_set_uniform_1i (GstGLShader *shader, const gchar *name, gint value); +void gst_gl_shader_set_uniform_1iv (GstGLShader *shader, const gchar *name, guint count, gint *value); +void gst_gl_shader_set_uniform_1f (GstGLShader *shader, const gchar *name, gfloat value); +void gst_gl_shader_set_uniform_1fv (GstGLShader *shader, const gchar *name, guint count, gfloat *value); +void gst_gl_shader_set_uniform_2i (GstGLShader *shader, const gchar *name, gint v0, gint v1); +void gst_gl_shader_set_uniform_2iv (GstGLShader *shader, const gchar *name, guint count, gint *value); +void gst_gl_shader_set_uniform_2f (GstGLShader *shader, const gchar *name, gfloat v0, gfloat v1); +void gst_gl_shader_set_uniform_2fv (GstGLShader *shader, const gchar *name, guint count, gfloat *value); +void gst_gl_shader_set_uniform_3i (GstGLShader *shader, const gchar *name, gint v0, gint v1, gint v2); +void gst_gl_shader_set_uniform_3iv (GstGLShader *shader, const gchar *name, guint count, gint * value); +void gst_gl_shader_set_uniform_3f (GstGLShader *shader, const gchar *name, gfloat v0, gfloat v1, gfloat v2); +void gst_gl_shader_set_uniform_3fv (GstGLShader *shader, const gchar *name, guint count, gfloat *value); +void gst_gl_shader_set_uniform_4i (GstGLShader *shader, const gchar *name, gint v0, gint v1, gint v2, gint v3); +void gst_gl_shader_set_uniform_4iv (GstGLShader *shader, const gchar *name, guint count, gint *value); +void gst_gl_shader_set_uniform_4f (GstGLShader *shader, const gchar *name, gfloat v0, gfloat v1, gfloat v2, gfloat v3); +void gst_gl_shader_set_uniform_4fv (GstGLShader *shader, const gchar *name, guint count, gfloat *value); +void gst_gl_shader_set_uniform_matrix_2fv (GstGLShader *shader, const gchar *name, gint count, gboolean transpose, const gfloat* value); +void gst_gl_shader_set_uniform_matrix_3fv (GstGLShader *shader, const gchar *name, gint count, gboolean transpose, const gfloat* value); +void gst_gl_shader_set_uniform_matrix_4fv (GstGLShader *shader, const gchar *name, gint count, gboolean transpose, const gfloat* value); +#if HAVE_OPENGL +void gst_gl_shader_set_uniform_matrix_2x3fv (GstGLShader *shader, const gchar *name, gint count, gboolean transpose, const gfloat* value); +void gst_gl_shader_set_uniform_matrix_2x4fv (GstGLShader *shader, const gchar *name, gint count, gboolean transpose, const gfloat* value); +void gst_gl_shader_set_uniform_matrix_3x2fv (GstGLShader *shader, const gchar *name, gint count, gboolean transpose, const gfloat* value); +void gst_gl_shader_set_uniform_matrix_3x4fv (GstGLShader *shader, const gchar *name, gint count, gboolean transpose, const gfloat* value); +void gst_gl_shader_set_uniform_matrix_4x2fv (GstGLShader *shader, const gchar *name, gint count, gboolean transpose, const gfloat* value); +void gst_gl_shader_set_uniform_matrix_4x3fv (GstGLShader *shader, const gchar *name, gint count, gboolean transpose, const gfloat* value); #endif -GLint gst_gl_shader_get_attribute_location (GstGLShader *shader, const gchar *name); -void gst_gl_shader_bind_attribute_location (GstGLShader * shader, GLuint index, const gchar * name); +gint gst_gl_shader_get_attribute_location (GstGLShader *shader, const gchar *name); +void gst_gl_shader_bind_attribute_location (GstGLShader * shader, guint index, const gchar * name); G_END_DECLS diff --git a/gst-libs/gst/gl/gstglshadervariables.c b/gst-libs/gst/gl/gstglshadervariables.c index f97ef09a0e..1125105124 100644 --- a/gst-libs/gst/gl/gstglshadervariables.c +++ b/gst-libs/gst/gl/gstglshadervariables.c @@ -554,7 +554,19 @@ gst_gl_shadervariable_set (GstGLShader * shader, (float *) ret->value); break; -#ifndef OPENGL_ES2 + case _mat3: + case _mat3x3: + gst_gl_shader_set_uniform_matrix_3fv (shader, ret->name, ret->count, 0, + (float *) ret->value); + break; + + case _mat4: + case _mat4x4: + gst_gl_shader_set_uniform_matrix_4fv (shader, ret->name, ret->count, 0, + (float *) ret->value); + break; + +#if HAVE_OPENGL case _mat2x3: gst_gl_shader_set_uniform_matrix_2x3fv (shader, ret->name, ret->count, 0, (float *) ret->value); @@ -574,13 +586,7 @@ gst_gl_shadervariable_set (GstGLShader * shader, gst_gl_shader_set_uniform_matrix_4x2fv (shader, ret->name, ret->count, 0, (float *) ret->value); break; -#endif - case _mat3: - case _mat3x3: - gst_gl_shader_set_uniform_matrix_3fv (shader, ret->name, ret->count, 0, - (float *) ret->value); - break; -#ifndef OPENGL_ES2 + case _mat3x4: gst_gl_shader_set_uniform_matrix_3x4fv (shader, ret->name, ret->count, 0, (float *) ret->value); @@ -591,11 +597,6 @@ gst_gl_shadervariable_set (GstGLShader * shader, (float *) ret->value); break; #endif - case _mat4: - case _mat4x4: - gst_gl_shader_set_uniform_matrix_4fv (shader, ret->name, ret->count, 0, - (float *) ret->value); - break; default: return -1; diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c index b72bcf88f5..d1ed9398e3 100644 --- a/gst-libs/gst/gl/gstglupload.c +++ b/gst-libs/gst/gl/gstglupload.c @@ -43,8 +43,13 @@ * calling thread. */ +#define USING_OPENGL(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_OPENGL3) +#define USING_GLES(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES) +#define USING_GLES2(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES2) +#define USING_GLES3(display) (gst_gl_display_get_gl_api_unlocked (display) & GST_GL_API_GLES3) + static void _do_upload (GstGLDisplay * display, GstGLUpload * upload); -static void _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload); static void _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload); static void _do_upload_make (GstGLDisplay * display, GstGLUpload * upload); static void _init_upload (GstGLDisplay * display, GstGLUpload * upload); @@ -54,100 +59,164 @@ static gboolean gst_gl_upload_perform_with_data_unlocked (GstGLUpload * upload, static gboolean gst_gl_upload_perform_with_data_unlocked_thread (GstGLUpload * upload, GLuint texture_id, gpointer data[GST_VIDEO_MAX_PLANES]); +#if HAVE_OPENGL +static void _do_upload_draw_opengl (GstGLDisplay * display, + GstGLUpload * upload); +#endif +#if HAVE_GLES2 +static void _do_upload_draw_gles2 (GstGLDisplay * display, + GstGLUpload * upload); +#endif + +/* *INDENT-OFF* */ + +#if HAVE_OPENGL /* YUY2:r,g,a UYVY:a,b,r */ -static gchar *text_shader_YUY2_UYVY = -#ifndef OPENGL_ES2 +static gchar *text_shader_YUY2_UYVY_opengl = "#extension GL_ARB_texture_rectangle : enable\n" "uniform sampler2DRect Ytex, UVtex;\n" -#else - "precision mediump float;\n" - "varying vec2 v_texCoord;\n" "uniform sampler2D Ytex, UVtex;\n" -#endif - "void main(void) {\n" " float fx, fy, y, u, v, r, g, b;\n" -#ifndef OPENGL_ES2 + "void main(void) {\n" + " float fx, fy, y, u, v, r, g, b;\n" " fx = gl_TexCoord[0].x;\n" " fy = gl_TexCoord[0].y;\n" " y = texture2DRect(Ytex,vec2(fx,fy)).%c;\n" " u = texture2DRect(UVtex,vec2(fx*0.5,fy)).%c;\n" " v = texture2DRect(UVtex,vec2(fx*0.5,fy)).%c;\n" -#else - " fx = v_texCoord.x;\n" - " fy = v_texCoord.y;\n" - " y = texture2D(Ytex,vec2(fx,fy)).%c;\n" - " u = texture2D(UVtex,vec2(fx*0.5,fy)).%c;\n" - " v = texture2D(UVtex,vec2(fx*0.5,fy)).%c;\n" -#endif " y=1.164*(y-0.0627);\n" " u=u-0.5;\n" " v=v-0.5;\n" " r = y+1.5958*v;\n" " g = y-0.39173*u-0.81290*v;\n" - " b = y+2.017*u;\n" " gl_FragColor = vec4(r, g, b, 1.0);\n" "}\n"; + " b = y+2.017*u;\n" + " gl_FragColor = vec4(r, g, b, 1.0);\n" + "}\n"; /* ATI: "*0.5", "" normal: "", "*0.5" */ -static gchar *text_shader_I420_YV12 = -#ifndef OPENGL_ES2 +static gchar *text_shader_I420_YV12_opengl = "#extension GL_ARB_texture_rectangle : enable\n" "uniform sampler2DRect Ytex,Utex,Vtex;\n" -#else - "precision mediump float;\n" - "varying vec2 v_texCoord;\n" "uniform sampler2D Ytex,Utex,Vtex;\n" -#endif - "void main(void) {\n" " float r,g,b,y,u,v;\n" -#ifndef OPENGL_ES2 + "void main(void) {\n" + " float r,g,b,y,u,v;\n" " vec2 nxy = gl_TexCoord[0].xy;\n" " y=texture2DRect(Ytex,nxy%s).r;\n" - " u=texture2DRect(Utex,nxy%s).r;\n" " v=texture2DRect(Vtex,nxy*0.5).r;\n" -#else - " vec2 nxy = v_texCoord.xy;\n" - " y=texture2D(Ytex,nxy).r;\n" - " u=texture2D(Utex,nxy).r;\n" " v=texture2D(Vtex,nxy).r;\n" -#endif + " u=texture2DRect(Utex,nxy%s).r;\n" + " v=texture2DRect(Vtex,nxy*0.5).r;\n" " y=1.1643*(y-0.0625);\n" " u=u-0.5;\n" " v=v-0.5;\n" " r=y+1.5958*v;\n" " g=y-0.39173*u-0.81290*v;\n" - " b=y+2.017*u;\n" " gl_FragColor=vec4(r,g,b,1.0);\n" "}\n"; + " b=y+2.017*u;\n" + " gl_FragColor=vec4(r,g,b,1.0);\n" + "}\n"; -static gchar *text_shader_AYUV = -#ifndef OPENGL_ES2 +static gchar *text_shader_AYUV_opengl = "#extension GL_ARB_texture_rectangle : enable\n" "uniform sampler2DRect tex;\n" -#else - "precision mediump float;\n" - "varying vec2 v_texCoord;\n" "uniform sampler2D tex;\n" -#endif - "void main(void) {\n" " float r,g,b,y,u,v;\n" -#ifndef OPENGL_ES2 + "void main(void) {\n" + " float r,g,b,y,u,v;\n" " vec2 nxy=gl_TexCoord[0].xy;\n" " y=texture2DRect(tex,nxy).r;\n" - " u=texture2DRect(tex,nxy).g;\n" " v=texture2DRect(tex,nxy).b;\n" -#else - " vec2 nxy = v_texCoord.xy;\n" - " y=texture2D(tex,nxy).g;\n" - " u=texture2D(tex,nxy).b;\n" " v=texture2D(tex,nxy).a;\n" -#endif + " u=texture2DRect(tex,nxy).g;\n" + " v=texture2DRect(tex,nxy).b;\n" " y=1.1643*(y-0.0625);\n" " u=u-0.5;\n" " v=v-0.5;\n" " r=y+1.5958*v;\n" " g=y-0.39173*u-0.81290*v;\n" - " b=y+2.017*u;\n" " gl_FragColor=vec4(r,g,b,1.0);\n" "}\n"; + " b=y+2.017*u;\n" + " gl_FragColor=vec4(r,g,b,1.0);\n" + "}\n"; -#ifdef OPENGL_ES2 -static gchar *text_vertex_shader = +#define text_vertex_shader_opengl NULL +#endif + +#ifdef HAVE_GLES2 +/* YUY2:r,g,a + UYVY:a,b,r */ +static gchar *text_shader_YUY2_UYVY_gles2 = + "precision mediump float;\n" + "varying vec2 v_texCoord;\n" + "uniform sampler2D Ytex, UVtex;\n" + "void main(void) {\n" + " float fx, fy, y, u, v, r, g, b;\n" + " fx = v_texCoord.x;\n" + " fy = v_texCoord.y;\n" + " y = texture2D(Ytex,vec2(fx,fy)).%c;\n" + " u = texture2D(UVtex,vec2(fx*0.5,fy)).%c;\n" + " v = texture2D(UVtex,vec2(fx*0.5,fy)).%c;\n" + " y=1.164*(y-0.0627);\n" + " u=u-0.5;\n" + " v=v-0.5;\n" + " r = y+1.5958*v;\n" + " g = y-0.39173*u-0.81290*v;\n" + " b = y+2.017*u;\n" + " gl_FragColor = vec4(r, g, b, 1.0);\n" + "}\n"; + +static gchar *text_shader_I420_YV12_gles2 = + "precision mediump float;\n" + "varying vec2 v_texCoord;\n" + "uniform sampler2D Ytex,Utex,Vtex;\n" + "void main(void) {\n" + " float r,g,b,y,u,v;\n" + " vec2 nxy = v_texCoord.xy;\n" + " y=texture2D(Ytex,nxy).r;\n" + " u=texture2D(Utex,nxy).r;\n" + " v=texture2D(Vtex,nxy).r;\n" + " y=1.1643*(y-0.0625);\n" + " u=u-0.5;\n" + " v=v-0.5;\n" + " r=y+1.5958*v;\n" + " g=y-0.39173*u-0.81290*v;\n" + " b=y+2.017*u;\n" + " gl_FragColor=vec4(r,g,b,1.0);\n" + "}\n"; + +static gchar *text_shader_AYUV_gles2 = + "precision mediump float;\n" + "varying vec2 v_texCoord;\n" + "uniform sampler2D tex;\n" + "void main(void) {\n" + " float r,g,b,y,u,v;\n" + " vec2 nxy = v_texCoord.xy;\n" + " y=texture2D(tex,nxy).g;\n" + " u=texture2D(tex,nxy).b;\n" + " v=texture2D(tex,nxy).a;\n" + " y=1.1643*(y-0.0625);\n" + " u=u-0.5;\n" + " v=v-0.5;\n" + " r=y+1.5958*v;\n" + " g=y-0.39173*u-0.81290*v;\n" + " b=y+2.017*u;\n" + " gl_FragColor=vec4(r,g,b,1.0);\n" + "}\n"; + +static gchar *text_vertex_shader_gles2 = "attribute vec4 a_position; \n" "attribute vec2 a_texCoord; \n" "varying vec2 v_texCoord; \n" "void main() \n" "{ \n" " gl_Position = a_position; \n" - " v_texCoord = a_texCoord; \n" "} \n"; + " v_texCoord = a_texCoord; \n" + "} \n"; #endif +/* *INDENT-ON* */ + +struct _GstGLUploadPrivate +{ + const gchar *YUY2_UYVY; + const gchar *I420_YV12; + const gchar *AYUV; + const gchar *vert_shader; + + void (*draw) (GstGLDisplay * display, GstGLUpload * download); +}; + GST_DEBUG_CATEGORY_STATIC (gst_gl_upload_debug); #define GST_CAT_DEFAULT gst_gl_upload_debug @@ -163,12 +232,16 @@ static void gst_gl_upload_finalize (GObject * object); static void gst_gl_upload_class_init (GstGLUploadClass * klass) { + g_type_class_add_private (klass, sizeof (GstGLUploadPrivate)); + G_OBJECT_CLASS (klass)->finalize = gst_gl_upload_finalize; } static void gst_gl_upload_init (GstGLUpload * upload) { + upload->priv = GST_GL_UPLOAD_GET_PRIVATE (upload); + upload->display = NULL; g_mutex_init (&upload->lock); @@ -178,10 +251,8 @@ gst_gl_upload_init (GstGLUpload * upload) upload->out_texture = 0; upload->shader = NULL; -#ifdef OPENGL_ES2 upload->shader_attr_position_loc = 0; upload->shader_attr_texture_loc = 0; -#endif gst_video_info_init (&upload->info); } @@ -196,13 +267,34 @@ GstGLUpload * gst_gl_upload_new (GstGLDisplay * display) { GstGLUpload *upload; + GstGLUploadPrivate *priv; upload = g_object_new (GST_TYPE_GL_UPLOAD, NULL); upload->display = g_object_ref (display); + priv = upload->priv; g_mutex_init (&upload->lock); +#if HAVE_OPENGL + if (USING_OPENGL (display)) { + priv->YUY2_UYVY = text_shader_YUY2_UYVY_opengl; + priv->I420_YV12 = text_shader_I420_YV12_opengl; + priv->AYUV = text_shader_AYUV_opengl; + priv->vert_shader = text_vertex_shader_opengl; + priv->draw = _do_upload_draw_opengl; + } +#endif +#if HAVE_GLES2 + if (USING_GLES2 (display)) { + priv->YUY2_UYVY = text_shader_YUY2_UYVY_gles2; + priv->I420_YV12 = text_shader_I420_YV12_gles2; + priv->AYUV = text_shader_AYUV_gles2; + priv->vert_shader = text_vertex_shader_gles2; + priv->draw = _do_upload_draw_gles2; + } +#endif + return upload; } @@ -547,7 +639,7 @@ gst_gl_display_find_upload_unlocked (GstGLDisplay * display, GstVideoFormat v_format, guint in_width, guint in_height, guint out_width, guint out_height) { - GstGLUpload *ret; + GstGLUpload *ret = NULL; GSList *walk; walk = display->uploads; @@ -606,6 +698,34 @@ gst_gl_display_find_upload (GstGLDisplay * display, GstVideoFormat v_format, return ret; } +static gboolean +_create_shader (GstGLDisplay * display, const gchar * vertex_src, + const gchar * fragment_src, GstGLShader ** out_shader) +{ + GstGLShader *shader; + GError *error; + + g_return_val_if_fail (vertex_src != NULL || fragment_src != NULL, FALSE); + + shader = gst_gl_shader_new (display); + + if (vertex_src) + gst_gl_shader_set_vertex_source (shader, vertex_src); + if (fragment_src) + gst_gl_shader_set_fragment_source (shader, fragment_src); + + if (!gst_gl_shader_compile (shader, &error)) { + gst_gl_display_set_error (display, "%s", error->message); + g_error_free (error); + gst_gl_shader_use (NULL); + g_object_unref (G_OBJECT (shader)); + return FALSE; + } + + *out_shader = shader; + return TRUE; +} + /* Called in the gl thread */ void _init_upload (GstGLDisplay * display, GstGLUpload * upload) @@ -647,10 +767,6 @@ _init_upload (GstGLDisplay * display, GstGLUpload * upload) /* shouldn't we require ARB_shading_language_100? --Filippo */ if (GLEW_ARB_fragment_shader) { -#ifdef OPENGL_ES2 - GError *error = NULL; -#endif - GST_INFO ("Context, ARB_fragment_shader supported: yes"); display->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_GLSL; @@ -661,173 +777,100 @@ _init_upload (GstGLDisplay * display, GstGLUpload * upload) case GST_VIDEO_FORMAT_YUY2: { gchar text_shader_YUY2[2048]; - sprintf (text_shader_YUY2, text_shader_YUY2_UYVY, 'r', 'g', 'a'); + sprintf (text_shader_YUY2, upload->priv->YUY2_UYVY, 'r', 'g', 'a'); - upload->shader = gst_gl_shader_new (); -#ifndef OPENGL_ES2 - if (!gst_gl_shader_compile_and_check (upload->shader, - text_shader_YUY2, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_display_set_error (display, - "Failed to initialize shader for uploading YUY2"); - g_object_unref (G_OBJECT (upload->shader)); - upload->shader = NULL; + if (_create_shader (display, upload->priv->vert_shader, + text_shader_YUY2, &upload->shader)) { + if (USING_GLES2 (display)) { + upload->shader_attr_position_loc = + gst_gl_shader_get_attribute_location + (upload->shader, "a_position"); + upload->shader_attr_texture_loc = + gst_gl_shader_get_attribute_location + (upload->shader, "a_texCoord"); + } } -#else - gst_gl_shader_set_vertex_source (upload->shader, - text_vertex_shader); - gst_gl_shader_set_fragment_source (upload->shader, - text_shader_YUY2); - - gst_gl_shader_compile (upload->shader, &error); - if (error) { - gst_gl_display_set_error (display, "%s", error->message); - g_error_free (error); - error = NULL; - gst_gl_shader_use (NULL); - g_object_unref (G_OBJECT (upload->shader)); - upload->shader = NULL; - } else { - upload->shader_attr_position_loc = - gst_gl_shader_get_attribute_location - (upload->shader, "a_position"); - upload->shader_attr_texture_loc = - gst_gl_shader_get_attribute_location - (upload->shader, "a_texCoord"); - } -#endif } break; case GST_VIDEO_FORMAT_UYVY: { gchar text_shader_UYVY[2048]; - sprintf (text_shader_UYVY, -#ifndef OPENGL_ES2 - text_shader_YUY2_UYVY, 'a', 'b', 'r'); -#else - text_shader_YUY2_UYVY, 'a', 'r', 'b'); -#endif - - upload->shader = gst_gl_shader_new (); - -#ifndef OPENGL_ES2 - if (!gst_gl_shader_compile_and_check (upload->shader, - text_shader_UYVY, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_display_set_error (display, - "Failed to initialize shader for uploading UYVY"); - g_object_unref (G_OBJECT (upload->shader)); - upload->shader = NULL; - } -#else - gst_gl_shader_set_vertex_source (upload->shader, - text_vertex_shader); - gst_gl_shader_set_fragment_source (upload->shader, - text_shader_UYVY); - - gst_gl_shader_compile (upload->shader, &error); - if (error) { - gst_gl_display_set_error (display, "%s", error->message); - g_error_free (error); - error = NULL; - gst_gl_shader_use (NULL); - g_object_unref (G_OBJECT (upload->shader)); - upload->shader = NULL; - } else { - upload->shader_attr_position_loc = - gst_gl_shader_get_attribute_location - (upload->shader, "a_position"); - upload->shader_attr_texture_loc = - gst_gl_shader_get_attribute_location - (upload->shader, "a_texCoord"); +#if HAVE_OPENGL + if (USING_GLES2 (display)) { + sprintf (text_shader_UYVY, upload->priv->YUY2_UYVY, + 'a', 'b', 'r'); } #endif +#if HAVE_GLES2 + if (USING_GLES2 (display)) { + sprintf (text_shader_UYVY, upload->priv->YUY2_UYVY, + 'a', 'r', 'b'); + } +#endif + + if (_create_shader (display, upload->priv->vert_shader, + text_shader_UYVY, &upload->shader)) { + if (USING_GLES2 (display)) { + upload->shader_attr_position_loc = + gst_gl_shader_get_attribute_location + (upload->shader, "a_position"); + upload->shader_attr_texture_loc = + gst_gl_shader_get_attribute_location + (upload->shader, "a_texCoord"); + } + } } break; case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: { -#ifndef OPENGL_ES2 - gchar text_shader[2048]; - if ((g_ascii_strncasecmp ("ATI", (gchar *) glGetString (GL_VENDOR), - 3) == 0) - && (g_ascii_strncasecmp ("ATI Mobility Radeon HD", - (gchar *) glGetString (GL_RENDERER), 22) != 0) - && (g_ascii_strncasecmp ("ATI Radeon HD", - (gchar *) glGetString (GL_RENDERER), 13) != 0)) - sprintf (text_shader, text_shader_I420_YV12, "*0.5", ""); - else - sprintf (text_shader, text_shader_I420_YV12, "", "*0.5"); -#endif - - upload->shader = gst_gl_shader_new (); - -#ifndef OPENGL_ES2 - if (!gst_gl_shader_compile_and_check - (upload->shader, text_shader, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_display_set_error (display, - "Failed to initialize shader for uploading I420 or YV12"); - g_object_unref (G_OBJECT (upload->shader)); - upload->shader = NULL; - } -#else - gst_gl_shader_set_vertex_source (upload->shader, - text_vertex_shader); - gst_gl_shader_set_fragment_source (upload->shader, - text_shader_I420_YV12); - - gst_gl_shader_compile (upload->shader, &error); - if (error) { - gst_gl_display_set_error (display, "%s", error->message); - g_error_free (error); - error = NULL; - gst_gl_shader_use (NULL); - g_object_unref (G_OBJECT (upload->shader)); - upload->shader = NULL; - } else { - upload->shader_attr_position_loc = - gst_gl_shader_get_attribute_location - (upload->shader, "a_position"); - upload->shader_attr_texture_loc = - gst_gl_shader_get_attribute_location - (upload->shader, "a_texCoord"); + gchar text_shader_I420_YV12[2048]; +#if HAVE_OPENGL + if (USING_OPENGL (display)) { + if ((g_ascii_strncasecmp ("ATI", + (gchar *) glGetString (GL_VENDOR), 3) == 0) + && (g_ascii_strncasecmp ("ATI Mobility Radeon HD", + (gchar *) glGetString (GL_RENDERER), 22) != 0) + && (g_ascii_strncasecmp ("ATI Radeon HD", + (gchar *) glGetString (GL_RENDERER), 13) != 0)) + sprintf (text_shader_I420_YV12, upload->priv->I420_YV12, "*0.5", + ""); + else + sprintf (text_shader_I420_YV12, upload->priv->I420_YV12, "", + "*0.5"); } #endif +#if HAVE_GLES2 + if (USING_GLES2 (display)) + g_strlcpy (text_shader_I420_YV12, upload->priv->I420_YV12, 2048); +#endif + + if (_create_shader (display, upload->priv->vert_shader, + text_shader_I420_YV12, &upload->shader)) { + if (USING_GLES2 (display)) { + upload->shader_attr_position_loc = + gst_gl_shader_get_attribute_location + (upload->shader, "a_position"); + upload->shader_attr_texture_loc = + gst_gl_shader_get_attribute_location + (upload->shader, "a_texCoord"); + } + } } break; case GST_VIDEO_FORMAT_AYUV: { - upload->shader = gst_gl_shader_new (); - -#ifndef OPENGL_ES2 - if (!gst_gl_shader_compile_and_check (upload->shader, - text_shader_AYUV, GST_GL_SHADER_FRAGMENT_SOURCE)) { - gst_gl_display_set_error (display, - "Failed to initialize shader for uploading AYUV"); - g_object_unref (G_OBJECT (upload->shader)); - upload->shader = NULL; + if (_create_shader (display, upload->priv->vert_shader, + upload->priv->AYUV, &upload->shader)) { + if (USING_GLES2 (display)) { + upload->shader_attr_position_loc = + gst_gl_shader_get_attribute_location + (upload->shader, "a_position"); + upload->shader_attr_texture_loc = + gst_gl_shader_get_attribute_location + (upload->shader, "a_texCoord"); + } } -#else - gst_gl_shader_set_vertex_source (upload->shader, - text_vertex_shader); - gst_gl_shader_set_fragment_source (upload->shader, - text_shader_AYUV); - - gst_gl_shader_compile (upload->shader, &error); - if (error) { - gst_gl_display_set_error (display, "%s", error->message); - g_error_free (error); - error = NULL; - gst_gl_shader_use (NULL); - g_object_unref (G_OBJECT (upload->shader)); - upload->shader = NULL; - } else { - upload->shader_attr_position_loc = - gst_gl_shader_get_attribute_location - (upload->shader, "a_position"); - upload->shader_attr_texture_loc = - gst_gl_shader_get_attribute_location - (upload->shader, "a_texCoord"); - } -#endif } break; default: @@ -916,14 +959,19 @@ _init_upload_fbo (GstGLDisplay * display, GstGLUpload * upload) /* setup the render buffer for depth */ glGenRenderbuffersEXT (1, &upload->depth_buffer); glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, upload->depth_buffer); -#ifndef OPENGL_ES2 - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, - out_width, out_height); - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, - out_width, out_height); -#else - glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, - out_width, out_height); +#if HAVE_OPENGL + if (USING_OPENGL (display)) { + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, + out_width, out_height); + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, + out_width, out_height); + } +#endif +#if HAVE_GLES2 + if (USING_GLES2 (display)) { + glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, + out_width, out_height); + } #endif /* a fake texture is attached to the upload FBO (cannot init without it) */ @@ -946,9 +994,11 @@ _init_upload_fbo (GstGLDisplay * display, GstGLUpload * upload) glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, upload->depth_buffer); -#ifndef OPENGL_ES2 - glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, - GL_RENDERBUFFER_EXT, upload->depth_buffer); +#if HAVE_OPENGL + if (USING_OPENGL (display)) { + glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, + GL_RENDERBUFFER_EXT, upload->depth_buffer); + } #endif gst_gl_display_check_framebuffer_status (); @@ -995,7 +1045,7 @@ _do_upload (GstGLDisplay * display, GstGLUpload * upload) case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: if (in_width != out_width || in_height != out_height) - _do_upload_draw (display, upload); + upload->priv->draw (display, upload); /* color space conversion is not needed */ break; case GST_VIDEO_FORMAT_YUY2: @@ -1007,7 +1057,7 @@ _do_upload (GstGLDisplay * display, GstGLUpload * upload) switch (display->colorspace_conversion) { case GST_GL_DISPLAY_CONVERSION_GLSL: /* color space conversion is needed */ - _do_upload_draw (display, upload); + upload->priv->draw (display, upload); break; case GST_GL_DISPLAY_CONVERSION_MATRIX: /* color space conversion is needed */ @@ -1015,7 +1065,7 @@ _do_upload (GstGLDisplay * display, GstGLUpload * upload) break; case GST_GL_DISPLAY_CONVERSION_MESA: if (in_width != out_width || in_height != out_height) - _do_upload_draw (display, upload); + upload->priv->draw (display, upload); /* color space conversion is not needed */ break; default: @@ -1329,31 +1379,14 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload) glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0); } - +#if HAVE_OPENGL /* called by _do_upload (in the gl thread) */ -void -_do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) +static void +_do_upload_draw_opengl (GstGLDisplay * display, GstGLUpload * upload) { GstVideoFormat v_format; guint out_width, out_height; - -#ifndef OPENGL_ES2 guint in_width, in_height; -#else - GLint viewport_dim[4]; - - const GLfloat vVertices[] = { 1.0f, -1.0f, 0.0f, - 1.0f, 0.0f, - -1.0f, -1.0f, 0.0f, - 0.0f, .0f, - -1.0f, 1.0f, 0.0f, - 0.0f, 1.0f, - 1.0f, 1.0f, 0.0f, - 1.0f, 1.0f - }; - - GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; -#endif out_width = GST_VIDEO_INFO_WIDTH (&upload->info); out_height = GST_VIDEO_INFO_HEIGHT (&upload->info); @@ -1362,12 +1395,10 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, upload->fbo); /* setup a texture to render to */ -#ifndef OPENGL_ES2 in_width = upload->in_width; in_height = upload->in_height; glEnable (GL_TEXTURE_RECTANGLE_ARB); -#endif glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->out_texture); /* attach the texture to the FBO to renderer to */ @@ -1377,7 +1408,6 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) if (GLEW_ARB_fragment_shader) gst_gl_shader_use (NULL); -#ifndef OPENGL_ES2 glPushAttrib (GL_VIEWPORT_BIT); glMatrixMode (GL_PROJECTION); @@ -1388,15 +1418,10 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) glMatrixMode (GL_MODELVIEW); glPushMatrix (); glLoadIdentity (); -#else /* OPENGL_ES2 */ - glGetIntegerv (GL_VIEWPORT, viewport_dim); -#endif glViewport (0, 0, out_width, out_height); -#ifndef OPENGL_ES2 glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT); -#endif glClearColor (0.0, 0.0, 0.0, 0.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -1413,22 +1438,10 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: { -#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); -#else - glVertexAttribPointer (upload->shader_attr_position_loc, 3, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); - glVertexAttribPointer (upload->shader_attr_texture_loc, 2, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); - glEnableVertexAttribArray (upload->shader_attr_position_loc); - glEnableVertexAttribArray (upload->shader_attr_texture_loc); -#endif - -#ifndef OPENGL_ES2 glEnable (GL_TEXTURE_RECTANGLE_ARB); -#endif glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -1438,9 +1451,7 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -#ifndef OPENGL_ES2 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); -#endif } break; @@ -1453,18 +1464,8 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) { gst_gl_shader_use (upload->shader); -#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); -#else - glVertexAttribPointer (upload->shader_attr_position_loc, 3, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); - glVertexAttribPointer (upload->shader_attr_texture_loc, 2, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); - - glEnableVertexAttribArray (upload->shader_attr_position_loc); - glEnableVertexAttribArray (upload->shader_attr_texture_loc); -#endif glActiveTextureARB (GL_TEXTURE1_ARB); gst_gl_shader_set_uniform_1i (upload->shader, "UVtex", 1); @@ -1494,11 +1495,9 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) case GST_GL_DISPLAY_CONVERSION_MESA: { -#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); glEnable (GL_TEXTURE_RECTANGLE_ARB); -#endif glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -1508,9 +1507,7 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) GL_CLAMP_TO_EDGE); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); -#ifndef OPENGL_ES2 glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); -#endif } break; default: @@ -1527,18 +1524,8 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) { gst_gl_shader_use (upload->shader); -#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); -#else - glVertexAttribPointer (upload->shader_attr_position_loc, 3, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); - glVertexAttribPointer (upload->shader_attr_texture_loc, 2, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); - - glEnableVertexAttribArray (upload->shader_attr_position_loc); - glEnableVertexAttribArray (upload->shader_attr_texture_loc); -#endif glActiveTextureARB (GL_TEXTURE1_ARB); gst_gl_shader_set_uniform_1i (upload->shader, "Utex", 1); @@ -1582,18 +1569,8 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) { gst_gl_shader_use (upload->shader); -#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); -#else - glVertexAttribPointer (upload->shader_attr_position_loc, 3, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); - glVertexAttribPointer (upload->shader_attr_texture_loc, 2, - GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); - - glEnableVertexAttribArray (upload->shader_attr_position_loc); - glEnableVertexAttribArray (upload->shader_attr_texture_loc); -#endif glActiveTextureARB (GL_TEXTURE0_ARB); gst_gl_shader_set_uniform_1i (upload->shader, "tex", 0); @@ -1617,7 +1594,6 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) } /* end switch display->currentVideo_format */ -#ifndef OPENGL_ES2 glBegin (GL_QUADS); glTexCoord2i (in_width, 0); glVertex2f (1.0f, -1.0f); @@ -1630,15 +1606,11 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) glEnd (); glDrawBuffer (GL_NONE); -#else /* OPENGL_ES2 */ - glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); -#endif /* we are done with the shader */ if (display->colorspace_conversion == GST_GL_DISPLAY_CONVERSION_GLSL) glUseProgramObjectARB (0); -#ifndef OPENGL_ES2 glDisable (GL_TEXTURE_RECTANGLE_ARB); glMatrixMode (GL_PROJECTION); @@ -1646,12 +1618,250 @@ _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload) glMatrixMode (GL_MODELVIEW); glPopMatrix (); glPopAttrib (); -#else - glViewport (viewport_dim[0], viewport_dim[1], viewport_dim[2], - viewport_dim[3]); -#endif gst_gl_display_check_framebuffer_status (); glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); } +#endif + +#if HAVE_GLES2 +static void +_do_upload_draw_gles2 (GstGLDisplay * display, GstGLUpload * upload) +{ + GstVideoFormat v_format; + guint out_width, out_height; + + GLint viewport_dim[4]; + + const GLfloat vVertices[] = { 1.0f, -1.0f, 0.0f, + 1.0f, 0.0f, + -1.0f, -1.0f, 0.0f, + 0.0f, .0f, + -1.0f, 1.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, 0.0f, + 1.0f, 1.0f + }; + + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + + out_width = GST_VIDEO_INFO_WIDTH (&upload->info); + out_height = GST_VIDEO_INFO_HEIGHT (&upload->info); + v_format = GST_VIDEO_INFO_FORMAT (&upload->info); + + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, upload->fbo); + + /* setup a texture to render to */ + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->out_texture); + + /* attach the texture to the FBO to renderer to */ + glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, + GL_TEXTURE_RECTANGLE_ARB, upload->out_texture, 0); + + if (GLEW_ARB_fragment_shader) + gst_gl_shader_use (NULL); + + glGetIntegerv (GL_VIEWPORT, viewport_dim); + + glViewport (0, 0, out_width, out_height); + + glClearColor (0.0, 0.0, 0.0, 0.0); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + switch (v_format) { + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + { + glVertexAttribPointer (upload->shader_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); + glVertexAttribPointer (upload->shader_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (upload->shader_attr_position_loc); + glEnableVertexAttribArray (upload->shader_attr_texture_loc); + + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + } + break; + + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + { + switch (display->colorspace_conversion) { + case GST_GL_DISPLAY_CONVERSION_GLSL: + case GST_GL_DISPLAY_CONVERSION_MATRIX: + { + gst_gl_shader_use (upload->shader); + + glVertexAttribPointer (upload->shader_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); + glVertexAttribPointer (upload->shader_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (upload->shader_attr_position_loc); + glEnableVertexAttribArray (upload->shader_attr_texture_loc); + + glActiveTextureARB (GL_TEXTURE1_ARB); + gst_gl_shader_set_uniform_1i (upload->shader, "UVtex", 1); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + + glActiveTextureARB (GL_TEXTURE0_ARB); + gst_gl_shader_set_uniform_1i (upload->shader, "Ytex", 0); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + } + break; + case GST_GL_DISPLAY_CONVERSION_MESA: + { + + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + } + break; + default: + gst_gl_display_set_error (display, "Unknow colorspace conversion %d", + display->colorspace_conversion); + g_assert_not_reached (); + break; + } + } + break; + + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + { + gst_gl_shader_use (upload->shader); + + glVertexAttribPointer (upload->shader_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); + glVertexAttribPointer (upload->shader_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (upload->shader_attr_position_loc); + glEnableVertexAttribArray (upload->shader_attr_texture_loc); + + glActiveTextureARB (GL_TEXTURE1_ARB); + gst_gl_shader_set_uniform_1i (upload->shader, "Utex", 1); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + + glActiveTextureARB (GL_TEXTURE2_ARB); + gst_gl_shader_set_uniform_1i (upload->shader, "Vtex", 2); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[2]); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + + glActiveTextureARB (GL_TEXTURE0_ARB); + gst_gl_shader_set_uniform_1i (upload->shader, "Ytex", 0); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + } + break; + + case GST_VIDEO_FORMAT_AYUV: + { + gst_gl_shader_use (upload->shader); + + glVertexAttribPointer (upload->shader_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices); + glVertexAttribPointer (upload->shader_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (upload->shader_attr_position_loc); + glEnableVertexAttribArray (upload->shader_attr_texture_loc); + + glActiveTextureARB (GL_TEXTURE0_ARB); + gst_gl_shader_set_uniform_1i (upload->shader, "tex", 0); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + } + break; + + default: + gst_gl_display_set_error (display, "Unsupported upload video format %d", + v_format); + g_assert_not_reached (); + break; + + } /* end switch display->currentVideo_format */ + + glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + + /* we are done with the shader */ + if (display->colorspace_conversion == GST_GL_DISPLAY_CONVERSION_GLSL) + glUseProgramObjectARB (0); + + glViewport (viewport_dim[0], viewport_dim[1], viewport_dim[2], + viewport_dim[3]); + + gst_gl_display_check_framebuffer_status (); + + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); +} +#endif diff --git a/gst-libs/gst/gl/gstglupload.h b/gst-libs/gst/gl/gstglupload.h index 9ab9ce7e96..cc3d10c8c5 100644 --- a/gst-libs/gst/gl/gstglupload.h +++ b/gst-libs/gst/gl/gstglupload.h @@ -43,6 +43,7 @@ GType gst_gl_upload_get_type (void); typedef struct _GstGLUpload GstGLUpload; typedef struct _GstGLUploadClass GstGLUploadClass; +typedef struct _GstGLUploadPrivate GstGLUploadPrivate; /** * GstGLUpload @@ -76,12 +77,12 @@ struct _GstGLUpload guint in_width; guint in_height; GstGLShader *shader; -#ifdef OPENGL_ES2 GLint shader_attr_position_loc; GLint shader_attr_texture_loc; -#endif /* */ + GstGLUploadPrivate *priv; + gpointer _reserved[GST_PADDING]; }; @@ -100,12 +101,12 @@ struct _GstGLUploadClass * * The currently supported formats that can be uploaded */ -#ifndef OPENGL_ES2 -# define GST_GL_UPLOAD_FORMATS "{ RGB, RGBx, RGBA, BGR, BGRx, BGRA, xRGB, " \ +#if !HAVE_GLES2 +#define GST_GL_UPLOAD_FORMATS "{ RGB, RGBx, RGBA, BGR, BGRx, BGRA, xRGB, " \ "xBGR, ARGB, ABGR, I420, YV12, YUY2, UYVY, AYUV }" -#else /* OPENGL_ES2 */ +#else /* HAVE_GLES2 */ # define GST_GL_UPLOAD_FORMATS "{ RGB, RGBx, RGBA, I420, YV12, YUY2, UYVY, AYUV }" -#endif +#endif /* !HAVE_GLES2 */ /** * GST_GL_UPLOAD_VIDEO_CAPS: