From ec0bb66fe9db10102f67b7413a56b9ffc490b912 Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Sun, 15 Mar 2009 14:48:19 +0100 Subject: [PATCH] [321/906] add OpenGL ES 2.x support. In OpenGL 2.x for Embedded System, a lot of basic scene/draw functions have been removed. It means that everything is made using vertex and fragment shaders. I have also added a gstglwindow backend for winCE that uses EGL (Native Platform Graphics Intercace) (which is a full part of OpenGL ES specification). It remove the use of wgl/glx functions. --- gst-libs/gst/gl/gstgldisplay.c | 730 +++++++++++++++++++++++++++- gst-libs/gst/gl/gstgldisplay.h | 22 + gst-libs/gst/gl/gstgles2.h | 117 +++++ gst-libs/gst/gl/gstglshader.c | 16 + gst-libs/gst/gl/gstglshader.h | 9 + gst-libs/gst/gl/gstglwindow.h | 10 + gst-libs/gst/gl/gstglwindow_winCE.c | 610 +++++++++++++++++++++++ gst/gl/gstgldownload.c | 36 +- gst/gl/gstglfiltercube.c | 207 +++++++- gst/gl/gstglfiltercube.h | 4 + gst/gl/gstglimagesink.c | 14 + gst/gl/gstglupload.c | 29 +- gst/gl/gstopengl.c | 44 +- 13 files changed, 1793 insertions(+), 55 deletions(-) create mode 100644 gst-libs/gst/gl/gstgles2.h create mode 100644 gst-libs/gst/gl/gstglwindow_winCE.c diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index e250117939..42f3abfdb9 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -51,6 +51,9 @@ void gst_gl_display_thread_destroy_context (GstGLDisplay * display); void gst_gl_display_thread_run_generic (GstGLDisplay * display); void gst_gl_display_thread_gen_texture (GstGLDisplay * display); void gst_gl_display_thread_del_texture (GstGLDisplay * display); +#ifdef OPENGL_ES2 +void gst_gl_display_thread_init_redisplay (GstGLDisplay * display); +#endif void gst_gl_display_thread_init_upload (GstGLDisplay * display); void gst_gl_display_thread_do_upload (GstGLDisplay * display); void gst_gl_display_thread_init_download (GstGLDisplay * display); @@ -122,6 +125,11 @@ gst_gl_display_init (GstGLDisplay * display, GstGLDisplayClass * klass) display->redisplay_texture = 0; display->redisplay_texture_width = 0; display->redisplay_texture_height = 0; +#ifdef OPENGL_ES2 + display->redisplay_shader = NULL; + display->redisplay_attr_position_loc = 0; + display->redisplay_attr_texture_loc = 0; +#endif //action gen and del texture display->gen_texture = 0; @@ -197,78 +205,142 @@ gst_gl_display_init (GstGLDisplay * display, GstGLDisplayClass * klass) display->gen_shader = NULL; display->del_shader = NULL; - //fragement shader upload + //fragment shader upload display->shader_upload_YUY2 = NULL; display->shader_upload_UYVY = NULL; display->shader_upload_I420_YV12 = NULL; display->shader_upload_AYUV = NULL; - //fragement shader download +#ifdef OPENGL_ES2 + display->shader_upload_attr_position_loc = 0; + display->shader_upload_attr_texture_loc = 0; +#endif + + //fragment shader download display->shader_download_YUY2 = NULL; display->shader_download_UYVY = NULL; display->shader_download_I420_YV12 = NULL; display->shader_download_AYUV = NULL; +#ifdef OPENGL_ES2 + display->shader_download_attr_position_loc = 0; + display->shader_download_attr_texture_loc = 0; + display->shader_download_RGB = NULL; +#endif + //YUY2:r,g,a //UYVY:a,b,r display->text_shader_upload_YUY2_UYVY = +#ifndef OPENGL_ES2 "#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" - " fx = gl_TexCoord[0].x;\n" - " fy = gl_TexCoord[0].y;\n" +#ifndef OPENGL_ES2 + " 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" display->text_shader_upload_I420_YV12 = +#ifndef OPENGL_ES2 "#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" - " vec2 nxy=gl_TexCoord[0].xy;\n" +#ifndef OPENGL_ES2 + " 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 " 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"; display->text_shader_upload_AYUV = +#ifndef OPENGL_ES2 "#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 " 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 " y=1.1643*(y-0.0625);\n" " u=u-0.5;\n" " v=v-0.5;\n" - " r=clamp(y+1.5958*v, 0, 1);\n" - " g=clamp(y-0.39173*u-0.81290*v, 0, 1);\n" - " b=clamp(y+2.017*u, 0, 1);\n" " gl_FragColor=vec4(r,g,b,1.0);\n" "}\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"; //YUY2:y2,u,y1,v //UYVY:v,y1,u,y2 display->text_shader_download_YUY2_UYVY = +#ifndef OPENGL_ES2 "#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 " fx = gl_TexCoord[0].x;\n" " fy = gl_TexCoord[0].y;\n" " r=texture2DRect(tex,vec2(fx*2.0,fy)).r;\n" @@ -277,14 +349,29 @@ gst_gl_display_init (GstGLDisplay * display, GstGLDisplayClass * klass) " 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 display->text_shader_download_I420_YV12 = "#extension GL_ARB_texture_rectangle : enable\n" "uniform sampler2DRect tex;\n" @@ -307,23 +394,93 @@ gst_gl_display_init (GstGLDisplay * display, GstGLDisplayClass * klass) " 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"; display->text_shader_download_AYUV = +#ifndef OPENGL_ES2 "#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 " 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 " 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(y,u,v,1.0);\n" "}\n"; + " v=v + 0.5;\n" +#ifndef OPENGL_ES2 + " gl_FragColor=vec4(y,u,v,1.0);\n" +#else + " gl_FragColor=vec4(1.0,y,u,v);\n" +#endif + "}\n"; + +#ifdef OPENGL_ES2 + display->redisplay_vertex_shader_str = + "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"; + + display->redisplay_fragment_shader_str = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" + "} \n"; + + display->text_vertex_shader_upload = + "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"; + + display->text_vertex_shader_download = + "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"; + + display->text_fragment_shader_download_RGB = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" + "} \n"; +#endif } static void @@ -441,6 +598,7 @@ gst_gl_display_thread_create_context (GstGLDisplay * display) g_string_free (opengl_version, TRUE); +#ifndef OPENGL_ES2 if ((opengl_version_major < 1) || (GLEW_VERSION_MAJOR < 1) || (opengl_version_major < 2 && opengl_version_major >= 1 @@ -450,6 +608,12 @@ gst_gl_display_thread_create_context (GstGLDisplay * display) GST_WARNING ("Required OpenGL >= 1.2.0 and Glew >= 1.4.0"); display->isAlive = FALSE; } +#else + if (!GL_ES_VERSION_2_0) { + GST_WARNING ("Required OpenGL ES > 2.0"); + display->isAlive = FALSE; + } +#endif } //setup callbacks @@ -526,6 +690,12 @@ gst_gl_display_thread_destroy_context (GstGLDisplay * display) g_object_unref (G_OBJECT (display->shader_download_AYUV)); display->shader_download_AYUV = NULL; } +#ifdef OPENGL_ES2 + if (display->shader_download_RGB) { + g_object_unref (G_OBJECT (display->shader_download_RGB)); + display->shader_download_RGB = NULL; + } +#endif } break; default: @@ -573,6 +743,13 @@ gst_gl_display_thread_destroy_context (GstGLDisplay * display) display->upload_intex_v = 0; } +#ifdef OPENGL_ES2 + if (display->redisplay_shader) { + g_object_unref (G_OBJECT (display->redisplay_shader)); + display->redisplay_shader = NULL; + } +#endif + GST_INFO ("Cleaning texture pool"); //clean up the texture pool @@ -608,6 +785,37 @@ gst_gl_display_thread_del_texture (GstGLDisplay * display) display->del_texture_width, display->del_texture_height); } +#ifdef OPENGL_ES2 +/* Called in the gl thread */ +void +gst_gl_display_thread_init_redisplay (GstGLDisplay * display) +{ + GError *error = NULL; + display->redisplay_shader = gst_gl_shader_new (); + + gst_gl_shader_set_vertex_source(display->redisplay_shader, + display->redisplay_vertex_shader_str); + gst_gl_shader_set_fragment_source(display->redisplay_shader, + display->redisplay_fragment_shader_str); + + gst_gl_shader_compile (display->redisplay_shader, &error); + if (error) { + GST_ERROR ("%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_shader_use (NULL); + display->isAlive = FALSE; + } else { + display->redisplay_attr_position_loc = + gst_gl_shader_get_attribute_location (display->redisplay_shader, + "a_position"); + display->redisplay_attr_texture_loc = + gst_gl_shader_get_attribute_location (display->redisplay_shader, + "a_texCoord"); + } +} +#endif + /* Called in the gl thread */ void @@ -641,6 +849,11 @@ gst_gl_display_thread_init_upload (GstGLDisplay * display) //check if fragment shader is available, then load them /* 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->upload_colorspace_conversion = GST_GL_DISPLAY_CONVERSION_GLSL; @@ -657,32 +870,88 @@ gst_gl_display_thread_init_upload (GstGLDisplay * display) display->text_shader_upload_YUY2_UYVY, 'r', 'g', 'a'); display->shader_upload_YUY2 = gst_gl_shader_new (); +#ifndef OPENGL_ES2 if (!gst_gl_shader_compile_and_check (display->shader_upload_YUY2, text_shader_upload_YUY2, GST_GL_SHADER_FRAGMENT_SOURCE)) { display->isAlive = FALSE; g_object_unref (G_OBJECT (display->shader_upload_YUY2)); display->shader_upload_YUY2 = NULL; } +#else + gst_gl_shader_set_vertex_source(display->shader_upload_YUY2, + display->text_vertex_shader_upload); + gst_gl_shader_set_fragment_source(display->shader_upload_YUY2, + text_shader_upload_YUY2); + + gst_gl_shader_compile (display->shader_upload_YUY2, &error); + if (error) { + GST_ERROR ("%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_shader_use (NULL); + display->isAlive = FALSE; + g_object_unref (G_OBJECT (display->shader_upload_YUY2)); + display->shader_upload_YUY2 = NULL; + } else { + display->shader_upload_attr_position_loc = + gst_gl_shader_get_attribute_location (display->shader_upload_YUY2, + "a_position"); + display->shader_upload_attr_texture_loc = + gst_gl_shader_get_attribute_location (display->shader_upload_YUY2, + "a_texCoord"); + } +#endif } break; case GST_VIDEO_FORMAT_UYVY: { gchar text_shader_upload_UYVY[2048]; sprintf (text_shader_upload_UYVY, +#ifndef OPENGL_ES2 display->text_shader_upload_YUY2_UYVY, 'a', 'b', 'r'); +#else + display->text_shader_upload_YUY2_UYVY, 'a', 'r', 'b'); +#endif display->shader_upload_UYVY = gst_gl_shader_new (); + +#ifndef OPENGL_ES2 if (!gst_gl_shader_compile_and_check (display->shader_upload_UYVY, text_shader_upload_UYVY, GST_GL_SHADER_FRAGMENT_SOURCE)) { display->isAlive = FALSE; g_object_unref (G_OBJECT (display->shader_upload_UYVY)); display->shader_upload_UYVY = NULL; } +#else + gst_gl_shader_set_vertex_source(display->shader_upload_UYVY, + display->text_vertex_shader_upload); + gst_gl_shader_set_fragment_source(display->shader_upload_UYVY, + text_shader_upload_UYVY); + + gst_gl_shader_compile (display->shader_upload_UYVY, &error); + if (error) { + GST_ERROR ("%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_shader_use (NULL); + display->isAlive = FALSE; + g_object_unref (G_OBJECT (display->shader_upload_UYVY)); + display->shader_upload_UYVY = NULL; + } else { + display->shader_upload_attr_position_loc = + gst_gl_shader_get_attribute_location (display->shader_upload_UYVY, + "a_position"); + display->shader_upload_attr_texture_loc = + gst_gl_shader_get_attribute_location (display->shader_upload_UYVY, + "a_texCoord"); + } +#endif } break; case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: { +#ifndef OPENGL_ES2 gchar text_shader_upload_I420_YV12[2048]; if (g_ascii_strncasecmp ("ATI", (gchar *) glGetString (GL_VENDOR), 3) == 0) @@ -691,8 +960,11 @@ gst_gl_display_thread_init_upload (GstGLDisplay * display) else sprintf (text_shader_upload_I420_YV12, display->text_shader_upload_I420_YV12, "", "*0.5"); +#endif display->shader_upload_I420_YV12 = gst_gl_shader_new (); + +#ifndef OPENGL_ES2 if (!gst_gl_shader_compile_and_check (display->shader_upload_I420_YV12, text_shader_upload_I420_YV12, GST_GL_SHADER_FRAGMENT_SOURCE)) { @@ -700,10 +972,37 @@ gst_gl_display_thread_init_upload (GstGLDisplay * display) g_object_unref (G_OBJECT (display->shader_upload_I420_YV12)); display->shader_upload_I420_YV12 = NULL; } +#else + gst_gl_shader_set_vertex_source(display->shader_upload_I420_YV12, + display->text_vertex_shader_upload); + gst_gl_shader_set_fragment_source(display->shader_upload_I420_YV12, + display->text_shader_upload_I420_YV12); + + gst_gl_shader_compile (display->shader_upload_I420_YV12, &error); + if (error) { + GST_ERROR ("%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_shader_use (NULL); + display->isAlive = FALSE; + g_object_unref (G_OBJECT (display->shader_upload_I420_YV12)); + display->shader_upload_I420_YV12 = NULL; + } else { + display->shader_upload_attr_position_loc = + gst_gl_shader_get_attribute_location (display->shader_upload_I420_YV12, + "a_position"); + display->shader_upload_attr_texture_loc = + gst_gl_shader_get_attribute_location (display->shader_upload_I420_YV12, + "a_texCoord"); + } +#endif } break; case GST_VIDEO_FORMAT_AYUV: + { display->shader_upload_AYUV = gst_gl_shader_new (); + +#ifndef OPENGL_ES2 if (!gst_gl_shader_compile_and_check (display->shader_upload_AYUV, display->text_shader_upload_AYUV, GST_GL_SHADER_FRAGMENT_SOURCE)) { @@ -711,6 +1010,31 @@ gst_gl_display_thread_init_upload (GstGLDisplay * display) g_object_unref (G_OBJECT (display->shader_upload_AYUV)); display->shader_upload_AYUV = NULL; } +#else + gst_gl_shader_set_vertex_source(display->shader_upload_AYUV, + display->text_vertex_shader_upload); + gst_gl_shader_set_fragment_source(display->shader_upload_AYUV, + display->text_shader_upload_AYUV); + + gst_gl_shader_compile (display->shader_upload_AYUV, &error); + if (error) { + GST_ERROR ("%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_shader_use (NULL); + display->isAlive = FALSE; + g_object_unref (G_OBJECT (display->shader_upload_AYUV)); + display->shader_upload_AYUV = NULL; + } else { + display->shader_upload_attr_position_loc = + gst_gl_shader_get_attribute_location (display->shader_upload_AYUV, + "a_position"); + display->shader_upload_attr_texture_loc = + gst_gl_shader_get_attribute_location (display->shader_upload_AYUV, + "a_texCoord"); + } +#endif + } break; default: g_assert_not_reached (); @@ -990,6 +1314,36 @@ gst_gl_display_thread_init_download (GstGLDisplay * display) case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: //color space conversion is not needed +#ifdef OPENGL_ES2 + { + //glGetTexImage2D no available in OpenGL ES 2.0 + GError *error = NULL; + display->shader_download_RGB = gst_gl_shader_new (); + + gst_gl_shader_set_vertex_source(display->shader_download_RGB, + display->text_vertex_shader_download); + gst_gl_shader_set_fragment_source(display->shader_download_RGB, + display->text_fragment_shader_download_RGB); + + gst_gl_shader_compile (display->shader_download_RGB, &error); + if (error) { + GST_ERROR ("%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_shader_use (NULL); + display->isAlive = FALSE; + g_object_unref (G_OBJECT (display->shader_download_RGB)); + display->shader_download_RGB = NULL; + } else { + display->shader_download_attr_position_loc = + gst_gl_shader_get_attribute_location (display->shader_download_RGB, + "a_position"); + display->shader_download_attr_texture_loc = + gst_gl_shader_get_attribute_location (display->shader_download_RGB, + "a_texCoord"); + } + } +#endif break; case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_UYVY: @@ -1001,6 +1355,11 @@ gst_gl_display_thread_init_download (GstGLDisplay * display) //check if fragment shader is available, then load them //GLSL is a requirement for donwload if (GLEW_ARB_fragment_shader) { + +#ifdef OPENGL_ES2 + GError *error = NULL; +#endif + switch (display->download_video_format) { case GST_VIDEO_FORMAT_YUY2: { @@ -1009,12 +1368,37 @@ gst_gl_display_thread_init_download (GstGLDisplay * display) display->text_shader_download_YUY2_UYVY, "y2,u,y1,v"); display->shader_download_YUY2 = gst_gl_shader_new (); +#ifndef OPENGL_ES2 if (!gst_gl_shader_compile_and_check (display->shader_download_YUY2, text_shader_download_YUY2, GST_GL_SHADER_FRAGMENT_SOURCE)) { display->isAlive = FALSE; g_object_unref (G_OBJECT (display->shader_download_YUY2)); display->shader_download_YUY2 = NULL; } +#else + gst_gl_shader_set_vertex_source(display->shader_download_YUY2, + display->text_vertex_shader_download); + gst_gl_shader_set_fragment_source(display->shader_download_YUY2, + text_shader_download_YUY2); + + gst_gl_shader_compile (display->shader_download_YUY2, &error); + if (error) { + GST_ERROR ("%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_shader_use (NULL); + display->isAlive = FALSE; + g_object_unref (G_OBJECT (display->shader_download_YUY2)); + display->shader_download_YUY2 = NULL; + } else { + display->shader_download_attr_position_loc = + gst_gl_shader_get_attribute_location (display->shader_download_YUY2, + "a_position"); + display->shader_download_attr_texture_loc = + gst_gl_shader_get_attribute_location (display->shader_download_YUY2, + "a_texCoord"); + } +#endif } break; case GST_VIDEO_FORMAT_UYVY: @@ -1024,12 +1408,39 @@ gst_gl_display_thread_init_download (GstGLDisplay * display) display->text_shader_download_YUY2_UYVY, "v,y1,u,y2"); display->shader_download_UYVY = gst_gl_shader_new (); + +#ifndef OPENGL_ES2 if (!gst_gl_shader_compile_and_check (display->shader_download_UYVY, text_shader_download_UYVY, GST_GL_SHADER_FRAGMENT_SOURCE)) { display->isAlive = FALSE; g_object_unref (G_OBJECT (display->shader_download_UYVY)); display->shader_download_UYVY = NULL; } +#else + gst_gl_shader_set_vertex_source(display->shader_download_UYVY, + display->text_vertex_shader_download); + gst_gl_shader_set_fragment_source(display->shader_download_UYVY, + text_shader_download_UYVY); + + gst_gl_shader_compile (display->shader_download_UYVY, &error); + if (error) { + GST_ERROR ("%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_shader_use (NULL); + display->isAlive = FALSE; + g_object_unref (G_OBJECT (display->shader_download_UYVY)); + display->shader_download_UYVY = NULL; + } else { + display->shader_download_attr_position_loc = + gst_gl_shader_get_attribute_location (display->shader_download_UYVY, + "a_position"); + display->shader_download_attr_texture_loc = + gst_gl_shader_get_attribute_location (display->shader_download_UYVY, + "a_texCoord"); + } +#endif + } break; case GST_VIDEO_FORMAT_I420: @@ -1046,6 +1457,8 @@ gst_gl_display_thread_init_download (GstGLDisplay * display) break; case GST_VIDEO_FORMAT_AYUV: display->shader_download_AYUV = gst_gl_shader_new (); + +#ifndef OPENGL_ES2 if (!gst_gl_shader_compile_and_check (display->shader_download_AYUV, display->text_shader_download_AYUV, GST_GL_SHADER_FRAGMENT_SOURCE)) { @@ -1053,6 +1466,30 @@ gst_gl_display_thread_init_download (GstGLDisplay * display) g_object_unref (G_OBJECT (display->shader_download_AYUV)); display->shader_download_AYUV = NULL; } +#else + gst_gl_shader_set_vertex_source(display->shader_download_AYUV, + display->text_vertex_shader_download); + gst_gl_shader_set_fragment_source(display->shader_download_AYUV, + display->text_shader_download_AYUV); + + gst_gl_shader_compile (display->shader_download_AYUV, &error); + if (error) { + GST_ERROR ("%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_shader_use (NULL); + display->isAlive = FALSE; + g_object_unref (G_OBJECT (display->shader_download_AYUV)); + display->shader_download_AYUV = NULL; + } else { + display->shader_download_attr_position_loc = + gst_gl_shader_get_attribute_location (display->shader_download_AYUV, + "a_position"); + display->shader_download_attr_texture_loc = + gst_gl_shader_get_attribute_location (display->shader_download_AYUV, + "a_texCoord"); + } +#endif break; default: g_assert_not_reached (); @@ -1156,6 +1593,10 @@ gst_gl_display_thread_gen_fbo (GstGLDisplay * display) void gst_gl_display_thread_use_fbo (GstGLDisplay * display) { +#ifdef OPENGL_ES2 + GLint viewport_dim[4]; +#endif + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->use_fbo); //setup a texture to render to @@ -1168,9 +1609,8 @@ gst_gl_display_thread_use_fbo (GstGLDisplay * display) if (GLEW_ARB_fragment_shader) gst_gl_shader_use (NULL); - +#ifndef OPENGL_ES2 glPushAttrib (GL_VIEWPORT_BIT); - glMatrixMode (GL_PROJECTION); glPushMatrix (); glLoadIdentity (); @@ -1192,10 +1632,16 @@ 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); @@ -1204,13 +1650,16 @@ gst_gl_display_thread_use_fbo (GstGLDisplay * display) 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); } @@ -1319,10 +1768,12 @@ gst_gl_display_on_resize (GstGLDisplay * display, gint width, gint height) //default reshape else { glViewport (0, 0, width, height); +#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); gluOrtho2D (0, width, 0, height); glMatrixMode (GL_MODELVIEW); +#endif } } @@ -1355,6 +1806,7 @@ gst_gl_display_on_draw (GstGLDisplay * display) //default opengl scene else { +#ifndef OPENGL_ES2 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_PROJECTION); @@ -1376,7 +1828,44 @@ gst_gl_display_on_draw (GstGLDisplay * display) glEnd (); glDisable (GL_TEXTURE_RECTANGLE_ARB); - } //end default opengl scene + +#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); +#endif + + }//end default opengl scene } @@ -1616,6 +2105,14 @@ gst_gl_display_redisplay (GstGLDisplay * display, GLuint texture, gint width, gst_gl_display_lock (display); isAlive = display->isAlive; if (isAlive) { + +#ifdef OPENGL_ES2 + if (!display->redisplay_shader) { + gst_gl_window_send_message (display->gl_window, + GST_GL_WINDOW_CB (gst_gl_display_thread_init_redisplay), display); + } +#endif + if (texture) { display->redisplay_texture = texture; display->redisplay_texture_width = width; @@ -2198,6 +2695,23 @@ gst_gl_display_thread_do_upload_fill (GstGLDisplay * display) void gst_gl_display_thread_do_upload_draw (GstGLDisplay * display) { + +#ifdef OPENGL_ES2 + 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 + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->upload_fbo); //setup a texture to render to @@ -2211,6 +2725,7 @@ gst_gl_display_thread_do_upload_draw (GstGLDisplay * display) if (GLEW_ARB_fragment_shader) gst_gl_shader_use (NULL); +#ifndef OPENGL_ES2 glPushAttrib (GL_VIEWPORT_BIT); glMatrixMode (GL_PROJECTION); @@ -2221,10 +2736,16 @@ gst_gl_display_thread_do_upload_draw (GstGLDisplay * display) glMatrixMode (GL_MODELVIEW); glPushMatrix (); glLoadIdentity (); +#else // OPENGL_ES2 + glGetIntegerv(GL_VIEWPORT, viewport_dim); +#endif glViewport (0, 0, display->upload_width, display->upload_height); - glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT); +#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); @@ -2240,9 +2761,18 @@ gst_gl_display_thread_do_upload_draw (GstGLDisplay * display) case GST_VIDEO_FORMAT_RGB: case GST_VIDEO_FORMAT_BGR: { +#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); +#else + glVertexAttribPointer (display->shader_upload_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices); + glVertexAttribPointer (display->shader_upload_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); + glEnableVertexAttribArray (display->shader_upload_attr_position_loc); + glEnableVertexAttribArray (display->shader_upload_attr_texture_loc); +#endif glEnable (GL_TEXTURE_RECTANGLE_ARB); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex); glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, @@ -2279,8 +2809,18 @@ gst_gl_display_thread_do_upload_draw (GstGLDisplay * display) gst_gl_shader_use (shader_upload_YUY2_UYVY); +#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); +#else + glVertexAttribPointer (display->shader_upload_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices); + glVertexAttribPointer (display->shader_upload_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (display->shader_upload_attr_position_loc); + glEnableVertexAttribArray (display->shader_upload_attr_texture_loc); +#endif glActiveTextureARB (GL_TEXTURE1_ARB); gst_gl_shader_set_uniform_1i (shader_upload_YUY2_UYVY, "UVtex", 1); @@ -2309,8 +2849,11 @@ gst_gl_display_thread_do_upload_draw (GstGLDisplay * display) break; case GST_GL_DISPLAY_CONVERSION_MESA: { + +#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); +#endif glEnable (GL_TEXTURE_RECTANGLE_ARB); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex); @@ -2336,8 +2879,18 @@ gst_gl_display_thread_do_upload_draw (GstGLDisplay * display) { gst_gl_shader_use (display->shader_upload_I420_YV12); +#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); +#else + glVertexAttribPointer (display->shader_upload_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices); + glVertexAttribPointer (display->shader_upload_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (display->shader_upload_attr_position_loc); + glEnableVertexAttribArray (display->shader_upload_attr_texture_loc); +#endif glActiveTextureARB (GL_TEXTURE1_ARB); gst_gl_shader_set_uniform_1i (display->shader_upload_I420_YV12, "Utex", @@ -2384,8 +2937,18 @@ gst_gl_display_thread_do_upload_draw (GstGLDisplay * display) { gst_gl_shader_use (display->shader_upload_AYUV); +#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); +#else + glVertexAttribPointer (display->shader_upload_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices); + glVertexAttribPointer (display->shader_upload_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (display->shader_upload_attr_position_loc); + glEnableVertexAttribArray (display->shader_upload_attr_texture_loc); +#endif glActiveTextureARB (GL_TEXTURE0_ARB); gst_gl_shader_set_uniform_1i (display->shader_upload_AYUV, "tex", 0); @@ -2406,6 +2969,7 @@ gst_gl_display_thread_do_upload_draw (GstGLDisplay * display) } //end switch display->currentVideo_format +#ifndef OPENGL_ES2 glBegin (GL_QUADS); glTexCoord2i (display->upload_data_width, 0); glVertex2f (1.0f, -1.0f); @@ -2418,11 +2982,15 @@ gst_gl_display_thread_do_upload_draw (GstGLDisplay * display) glEnd (); glDrawBuffer (GL_NONE); +#else //OPENGL_ES2 + glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); +#endif //we are done with the shader if (display->upload_colorspace_conversion == GST_GL_DISPLAY_CONVERSION_GLSL) glUseProgramObjectARB (0); +#ifndef OPENGL_ES2 glDisable (GL_TEXTURE_RECTANGLE_ARB); glMatrixMode (GL_PROJECTION); @@ -2430,6 +2998,9 @@ gst_gl_display_thread_do_upload_draw (GstGLDisplay * display) 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); @@ -2444,31 +3015,88 @@ gst_gl_display_thread_do_download_draw_rgb (GstGLDisplay * display) GstVideoFormat video_format = display->download_video_format; gpointer data = display->download_data; +#ifndef OPENGL_ES2 glEnable (GL_TEXTURE_RECTANGLE_ARB); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->ouput_texture); +#else + gint width = display->ouput_texture_width; + gint height = display->ouput_texture_height; + + 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 }; + + glViewport (0, 0, width, height); + + glClearColor (0.0, 0.0, 0.0, 0.0); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + gst_gl_shader_use (display->shader_download_RGB); + + glVertexAttribPointer (display->shader_download_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices); + glVertexAttribPointer (display->shader_download_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (display->shader_download_attr_position_loc); + glEnableVertexAttribArray (display->shader_download_attr_texture_loc); + + glActiveTextureARB (GL_TEXTURE0_ARB); + gst_gl_shader_set_uniform_1i (display->shader_download_RGB, "s_texture", 0); + glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->ouput_texture); + + glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); + + glUseProgramObjectARB (0); + glDisable (GL_TEXTURE_RECTANGLE_ARB); + + glReadBuffer (GL_BACK); +#endif switch (video_format) { case GST_VIDEO_FORMAT_RGBA: case GST_VIDEO_FORMAT_RGBx: case GST_VIDEO_FORMAT_xRGB: case GST_VIDEO_FORMAT_ARGB: +#ifndef OPENGL_ES2 glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); +#else + glReadPixels (0, 0, width, height, GL_RGBA, + GL_UNSIGNED_BYTE, data); +#endif break; case GST_VIDEO_FORMAT_BGRx: case GST_VIDEO_FORMAT_BGRA: case GST_VIDEO_FORMAT_xBGR: case GST_VIDEO_FORMAT_ABGR: +#ifndef OPENGL_ES2 glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA, GL_UNSIGNED_BYTE, data); +#endif break; case GST_VIDEO_FORMAT_RGB: +#ifndef OPENGL_ES2 glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, GL_UNSIGNED_BYTE, data); +#else + glReadPixels (0, 0, width, height, GL_RGB, + GL_UNSIGNED_BYTE, data); +#endif break; case GST_VIDEO_FORMAT_BGR: +#ifndef OPENGL_ES2 glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGR, GL_UNSIGNED_BYTE, data); +#endif break; default: g_assert_not_reached (); @@ -2485,8 +3113,25 @@ gst_gl_display_thread_do_download_draw_yuv (GstGLDisplay * display) GstVideoFormat video_format = display->download_video_format; gpointer data = display->download_data; +#ifdef OPENGL_ES2 + 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 + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->download_fbo); +#ifndef OPENGL_ES2 glPushAttrib (GL_VIEWPORT_BIT); glMatrixMode (GL_PROJECTION); @@ -2497,6 +3142,9 @@ gst_gl_display_thread_do_download_draw_yuv (GstGLDisplay * display) glMatrixMode (GL_MODELVIEW); glPushMatrix (); glLoadIdentity (); +#else // OPENGL_ES2 + glGetIntegerv(GL_VIEWPORT, viewport_dim); +#endif glViewport (0, 0, width, height); @@ -2516,16 +3164,26 @@ gst_gl_display_thread_do_download_draw_yuv (GstGLDisplay * display) default: g_assert_not_reached (); } - +#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 (shader_download_YUY2_UYVY); +#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); - glLoadIdentity (); +#else + glVertexAttribPointer (display->shader_download_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices); + glVertexAttribPointer (display->shader_download_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (display->shader_download_attr_position_loc); + glEnableVertexAttribArray (display->shader_download_attr_texture_loc); +#endif glActiveTextureARB (GL_TEXTURE0_ARB); gst_gl_shader_set_uniform_1i (shader_download_YUY2_UYVY, "tex", 0); @@ -2536,15 +3194,19 @@ gst_gl_display_thread_do_download_draw_yuv (GstGLDisplay * display) case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: { +#ifndef OPENGL_ES2 glDrawBuffers (3, display->multipleRT); +#endif glClearColor (0.0, 0.0, 0.0, 0.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); gst_gl_shader_use (display->shader_download_I420_YV12); +#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); +#endif glActiveTextureARB (GL_TEXTURE0_ARB); gst_gl_shader_set_uniform_1i (display->shader_download_I420_YV12, "tex", @@ -2559,15 +3221,27 @@ gst_gl_display_thread_do_download_draw_yuv (GstGLDisplay * display) 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 (display->shader_download_AYUV); +#ifndef OPENGL_ES2 glMatrixMode (GL_PROJECTION); glLoadIdentity (); +#else + glVertexAttribPointer (display->shader_download_attr_position_loc, 3, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices); + glVertexAttribPointer (display->shader_download_attr_texture_loc, 2, + GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3]); + + glEnableVertexAttribArray (display->shader_download_attr_position_loc); + glEnableVertexAttribArray (display->shader_download_attr_texture_loc); +#endif glActiveTextureARB (GL_TEXTURE0_ARB); gst_gl_shader_set_uniform_1i (display->shader_download_AYUV, "tex", 0); @@ -2580,6 +3254,7 @@ gst_gl_display_thread_do_download_draw_yuv (GstGLDisplay * display) } //end switch display->currentVideo_format +#ifndef OPENGL_ES2 glBegin (GL_QUADS); glTexCoord2i (0, 0); glVertex2f (-1.0f, -1.0f); @@ -2592,19 +3267,26 @@ gst_gl_display_thread_do_download_draw_yuv (GstGLDisplay * display) glEnd (); glDrawBuffer (GL_NONE); +#else //OPENGL_ES2 + glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices); +#endif //dot not check if GLSL is available - //because for now download is not available - //without GLSL + //because download yuv is not available + //without GLSL (whereas rgb is) glUseProgramObjectARB (0); glDisable (GL_TEXTURE_RECTANGLE_ARB); +#ifndef OPENGL_ES2 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); @@ -2646,6 +3328,8 @@ gst_gl_display_thread_do_download_draw_yuv (GstGLDisplay * display) g_assert_not_reached (); } + glReadBuffer (GL_NONE); + glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0); gst_gl_display_check_framebuffer_status (); } diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index 3f9eb1bfce..6ff308a97a 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -96,6 +96,13 @@ struct _GstGLDisplay { GLuint redisplay_texture; GLuint redisplay_texture_width; GLuint redisplay_texture_height; +#ifdef OPENGL_ES2 + GstGLShader* redisplay_shader; + GLbyte* redisplay_vertex_shader_str; + GLbyte* redisplay_fragment_shader_str; + GLint redisplay_attr_position_loc; + GLint redisplay_attr_texture_loc; +#endif //action gen and del texture GLuint gen_texture; @@ -183,6 +190,12 @@ struct _GstGLDisplay { gchar* text_shader_upload_AYUV; GstGLShader* shader_upload_AYUV; +#ifdef OPENGL_ES2 + GLbyte* text_vertex_shader_upload; + GLint shader_upload_attr_position_loc; + GLint shader_upload_attr_texture_loc; +#endif + //fragement shader download gchar* text_shader_download_YUY2_UYVY; GstGLShader* shader_download_YUY2; @@ -193,6 +206,15 @@ struct _GstGLDisplay { gchar* text_shader_download_AYUV; GstGLShader* shader_download_AYUV; + +#ifdef OPENGL_ES2 + GLbyte* text_vertex_shader_download; + GLint shader_download_attr_position_loc; + GLint shader_download_attr_texture_loc; + GLbyte* text_fragment_shader_download_RGB; + GstGLShader* shader_download_RGB; +#endif + }; diff --git a/gst-libs/gst/gl/gstgles2.h b/gst-libs/gst/gl/gstgles2.h new file mode 100644 index 0000000000..76ef4b1645 --- /dev/null +++ b/gst-libs/gst/gl/gstgles2.h @@ -0,0 +1,117 @@ +/* + * GStreamer + * Copyright (C) 2009 Julien Isorce + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* Compatibility for OpenGL ES 2.0 */ + +#ifndef __GST_GL_ES2__ +#define __GST_GL_ES2__ + +/* GLEW */ + +#define GLEW_OK 0 +#define GLEW_NO_ERROR 0 +static const char* glewGetString (GLenum name) { return "1.5.1"; }; +static unsigned int glewInit() { return GLEW_OK;}; +static const char* glewGetErrorString (GLenum error) { return GLEW_NO_ERROR; }; + +#define GLEW_VERSION 1 +#define GLEW_VERSION_MAJOR 5 +#define GLEW_VERSION_MINOR 1 +#define GLEW_VERSION_MICRO 0 + +/* SUPPORTED */ + +//FIXME: +#define GL_RGBA8 GL_RGBA +#define GL_BGRA GL_RGBA +#define GL_UNSIGNED_INT_8_8_8_8 GL_UNSIGNED_BYTE +#define GL_UNSIGNED_INT_8_8_8_8_REV GL_UNSIGNED_BYTE +//END FIXME + +#define GL_TEXTURE_RECTANGLE_ARB GL_TEXTURE_2D +#define GL_TEXTURE0_ARB GL_TEXTURE0 +#define GL_TEXTURE1_ARB GL_TEXTURE1 +#define GL_TEXTURE2_ARB GL_TEXTURE2 + +#define GLEW_EXT_framebuffer_object 1 +#define GL_FRAMEBUFFER_EXT GL_FRAMEBUFFER +#define GL_RENDERBUFFER_EXT GL_RENDERBUFFER +#define GL_DEPTH_ATTACHMENT_EXT GL_DEPTH_ATTACHMENT +#define GL_FRAMEBUFFER_COMPLETE_EXT GL_FRAMEBUFFER_COMPLETE +#define GL_FRAMEBUFFER_UNSUPPORTED_EXT GL_FRAMEBUFFER_UNSUPPORTED + +#define GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT0 + +#define glFramebufferTexture2DEXT glFramebufferTexture2D +#define glFramebufferRenderbufferEXT glFramebufferRenderbuffer +#define glGenFramebuffersEXT glGenFramebuffers +#define glBindFramebufferEXT glBindFramebuffer +#define glRenderbufferStorageEXT glRenderbufferStorage +#define glDeleteRenderbuffersEXT glDeleteRenderbuffers +#define glDeleteFramebuffersEXT glDeleteFramebuffers +#define glCheckFramebufferStatusEXT glCheckFramebufferStatus +#define glGenRenderbuffersEXT glGenRenderbuffers +#define glBindRenderbufferEXT glBindRenderbuffer +#define glFramebufferTexture2DEXT glFramebufferTexture2D + +#define glActiveTextureARB glActiveTexture + +#define GLEW_ARB_fragment_shader 1 +#define GLhandleARB GLuint +#define GL_FRAGMENT_SHADER_ARB GL_FRAGMENT_SHADER +#define GL_VERTEX_SHADER_ARB GL_VERTEX_SHADER +#define GL_OBJECT_COMPILE_STATUS_ARB GL_COMPILE_STATUS + +#define glUseProgramObjectARB glUseProgram +#define glCreateProgramObjectARB glCreateProgram +#define glCreateShaderObjectARB glCreateShader +#define glCompileShaderARB glCompileShader +#define glShaderSourceARB glShaderSource +#define glGetInfoLogARB glGetProgramInfoLog +#define glAttachObjectARB glAttachShader +#define glDetachObjectARB glDetachShader +#define glDeleteObjectARB glDeleteProgram +#define glLinkProgramARB glLinkProgram +#define glGetObjectParameterivARB glGetShaderiv +#define glUniform1fARB glUniform1f +#define glUniform1fvARB glUniform1fv +#define glUniform1iARB glUniform1i +#define glUniformMatrix4fvARB glUniformMatrix4fv +#define glGetUniformLocationARB glGetUniformLocation +#define glGetAttribLocationARB glGetAttribLocation + +/* UNSUPPORTED */ + +#define GLEW_ARB_imaging 0 +#define GLEW_MESA_ycbcr_texture 0 +#define GL_BGR 0 +#define GL_YCBCR_MESA 0 +#define GL_UNSIGNED_SHORT_8_8_MESA 0 +#define GL_UNSIGNED_SHORT_8_8_MESA 0 +#define GL_UNSIGNED_SHORT_8_8_REV_MESA 0 + +#define GL_COLOR_ATTACHMENT1_EXT 0 +#define GL_COLOR_ATTACHMENT2_EXT 0 +static void glReadBuffer(GLenum name) {}; +static void glTexEnvi(GLenum name1, GLenum name2, GLenum name3) {}; +#define GL_TEXTURE_ENV 0 +#define GL_TEXTURE_ENV_MODE 0 + +#endif /* __GST_GL_ES2__ */ diff --git a/gst-libs/gst/gl/gstglshader.c b/gst-libs/gst/gl/gstglshader.c index 04cbbf4487..8ed11a8f74 100644 --- a/gst-libs/gst/gl/gstglshader.c +++ b/gst-libs/gst/gl/gstglshader.c @@ -510,6 +510,22 @@ gst_gl_shader_set_uniform_1i (GstGLShader * shader, const gchar * name, glUniform1iARB (location, value); } +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); +} + 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 3506997d21..6a547cb55a 100644 --- a/gst-libs/gst/gl/gstglshader.h +++ b/gst-libs/gst/gl/gstglshader.h @@ -21,7 +21,14 @@ #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 +#endif #include G_BEGIN_DECLS @@ -88,6 +95,8 @@ 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_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_matrix_4fv (GstGLShader * shader, const gchar * name, + GLsizei count, GLboolean transpose, const GLfloat* value); GLint gst_gl_shader_get_attribute_location (GstGLShader *shader, const gchar *name); diff --git a/gst-libs/gst/gl/gstglwindow.h b/gst-libs/gst/gl/gstglwindow.h index 10cdd907b0..e68333c8a7 100644 --- a/gst-libs/gst/gl/gstglwindow.h +++ b/gst-libs/gst/gl/gstglwindow.h @@ -21,6 +21,15 @@ #ifndef __GST_GL_WINDOW_H__ #define __GST_GL_WINDOW_H__ +/* OpenGL 2.0 for Embedded Systems */ +#ifdef OPENGL_ES2 +#undef UNICODE +#include +#define UNICODE +#include +#include "gstgles2.h" +/* OpenGL for usual systems */ +#else #if (!GNUSTEP && MACOS) #include #include @@ -29,6 +38,7 @@ #include #include #endif +#endif #include diff --git a/gst-libs/gst/gl/gstglwindow_winCE.c b/gst-libs/gst/gl/gstglwindow_winCE.c new file mode 100644 index 0000000000..be736f81a2 --- /dev/null +++ b/gst-libs/gst/gl/gstglwindow_winCE.c @@ -0,0 +1,610 @@ +/* + * GStreamer + * Copyright (C) 2009 Julien Isorce + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstglwindow.h" + +#define WM_GST_GL_WINDOW_CUSTOM (WM_APP+1) +#define WM_GST_GL_WINDOW_QUIT (WM_APP+2) + +LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); +LRESULT FAR PASCAL sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + +const gchar* EGLErrorString(); + +#define GST_GL_WINDOW_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE((o), GST_GL_TYPE_WINDOW, GstGLWindowPrivate)) + +enum +{ + PROP_0 +}; + +struct _GstGLWindowPrivate +{ + EGLNativeWindowType internal_win_id; + EGLDisplay display; + EGLSurface surface; + EGLContext gl_context; + GstGLWindowCB draw_cb; + gpointer draw_data; + GstGLWindowCB2 resize_cb; + gpointer resize_data; + GstGLWindowCB close_cb; + gpointer close_data; + gboolean is_closed; + gboolean visible; +}; + +G_DEFINE_TYPE (GstGLWindow, gst_gl_window, G_TYPE_OBJECT); + +#undef G_LOG_DOMAIN +#define G_LOG_DOMAIN "GstGLWindow" + +gboolean _gst_gl_window_debug = FALSE; + +HHOOK hHook; + +/* Must be called in the gl thread */ +static void +gst_gl_window_finalize (GObject * object) +{ + GstGLWindow *window = GST_GL_WINDOW (object); + GstGLWindowPrivate *priv = window->priv; + + G_OBJECT_CLASS (gst_gl_window_parent_class)->finalize (object); +} + +static void +gst_gl_window_log_handler (const gchar *domain, GLogLevelFlags flags, + const gchar *message, gpointer user_data) +{ + if (_gst_gl_window_debug) { + g_log_default_handler (domain, flags, message, user_data); + } +} + +static void +gst_gl_window_base_init (gpointer g_class) +{ +} + +static void +gst_gl_window_class_init (GstGLWindowClass * klass) +{ + GObjectClass *obj_class = G_OBJECT_CLASS (klass); + WNDCLASS wc; + ATOM atom = 0; + HINSTANCE hinstance = GetModuleHandle (NULL); + + g_type_class_add_private (klass, sizeof (GstGLWindowPrivate)); + + obj_class->finalize = gst_gl_window_finalize; + + atom = GetClassInfo (hinstance, "GSTGL", &wc); + + if (atom == 0) + { + ZeroMemory (&wc, sizeof(WNDCLASS)); + + wc.lpfnWndProc = window_proc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hinstance; + wc.hIcon = LoadIcon (NULL, IDI_WINLOGO); + wc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW; + wc.hCursor = LoadCursor (NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = "GSTGL"; + + atom = RegisterClass (&wc); + + if (atom == 0) + g_error ("Failed to register window class %x\r\n", GetLastError()); + } +} + +static void +gst_gl_window_init (GstGLWindow *window) +{ + window->priv = GST_GL_WINDOW_GET_PRIVATE (window); + + if (g_getenv ("GST_GL_WINDOW_DEBUG") != NULL) + _gst_gl_window_debug = TRUE; + + g_log_set_handler ("GstGLWindow", G_LOG_LEVEL_DEBUG, + gst_gl_window_log_handler, NULL); +} + +/* Must be called in the gl thread */ +GstGLWindow * +gst_gl_window_new (gint width, gint height) +{ + GstGLWindow *window = g_object_new (GST_GL_TYPE_WINDOW, NULL); + GstGLWindowPrivate *priv = window->priv; + GstGLWindowClass* klass = GST_GL_WINDOW_GET_CLASS (window); + + HINSTANCE hinstance = GetModuleHandle (NULL); + + static gint x = 0; + static gint y = 0; + + x += 20; + y += 20; + + priv->internal_win_id = 0; + priv->display = 0; + priv->surface = 0; + priv->gl_context = 0; + priv->draw_cb = NULL; + priv->draw_data = NULL; + priv->resize_cb = NULL; + priv->resize_data = NULL; + priv->close_cb = NULL; + priv->close_data = NULL; + priv->is_closed = FALSE; + priv->visible = FALSE; + + width += 2 * GetSystemMetrics (SM_CXSIZEFRAME); + height += 2 * GetSystemMetrics (SM_CYSIZEFRAME) + GetSystemMetrics (SM_CYCAPTION); + + priv->internal_win_id = CreateWindow ( + "GSTGL", + "OpenGL renderer", + WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW, //WS_POPUP | WS_BORDER | WS_SYSMENU | WS_CAPTION + x, y, width, height, + (HWND) NULL, + (HMENU) NULL, + hinstance, + window + ); + + if (!priv->internal_win_id) + { + g_debug ("failed to create gl window: %d\n", priv->internal_win_id); + return NULL; + } + + g_debug ("gl window created: %d\n", priv->internal_win_id); + + //display is set in the window_proc + if (!priv->display) { + g_object_unref (G_OBJECT (window)); + return NULL; + } + + ShowCursor (TRUE); + + return window; +} + +GQuark +gst_gl_window_error_quark (void) +{ + return g_quark_from_static_string ("gst-gl-window-error"); +} + +void +gst_gl_window_set_external_window_id (GstGLWindow *window, guint64 id) +{ + GstGLWindowPrivate *priv = window->priv; + WNDPROC window_parent_proc = (WNDPROC) (guint64) GetWindowLongPtr((HWND)id, GWL_WNDPROC); + RECT rect; + + SetProp (priv->internal_win_id, "gl_window_parent_id", (HWND)id); + SetProp ((HWND)id, "gl_window_id", priv->internal_win_id); + SetProp ((HWND)id, "gl_window_parent_proc", (WNDPROC) window_parent_proc); + SetWindowLongPtr ((HWND)id, GWL_WNDPROC, (DWORD) (guint64) sub_class_proc); + + SetWindowLongPtr (priv->internal_win_id, GWL_STYLE, WS_CHILD | WS_MAXIMIZE); + SetParent (priv->internal_win_id, (HWND)id); + + //take changes into account: SWP_FRAMECHANGED + GetClientRect ((HWND)id, &rect); + SetWindowPos (priv->internal_win_id, HWND_TOP, rect.left, rect.top, rect.right, rect.bottom, + SWP_ASYNCWINDOWPOS | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED | SWP_NOACTIVATE); + MoveWindow (priv->internal_win_id, rect.left, rect.top, rect.right, rect.bottom, FALSE); +} + +void +gst_gl_window_set_external_gl_context (GstGLWindow *window, guint64 context) +{ + g_warning ("gst_gl_window_set_external_gl_context: not implemented\n"); +} + +/* Must be called in the gl thread */ +void +gst_gl_window_set_draw_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data) +{ + GstGLWindowPrivate *priv = window->priv; + + priv->draw_cb = callback; + priv->draw_data = data; +} + +/* Must be called in the gl thread */ +void +gst_gl_window_set_resize_callback (GstGLWindow *window, GstGLWindowCB2 callback , gpointer data) +{ + GstGLWindowPrivate *priv = window->priv; + + priv->resize_cb = callback; + priv->resize_data = data; +} + +/* Must be called in the gl thread */ +void +gst_gl_window_set_close_callback (GstGLWindow *window, GstGLWindowCB callback, gpointer data) +{ + GstGLWindowPrivate *priv = window->priv; + + priv->close_cb = callback; + priv->close_data = data; +} + +void +gst_gl_window_draw_unlocked (GstGLWindow *window) +{ + gst_gl_window_draw (window); +} + +/* Thread safe */ +void +gst_gl_window_draw (GstGLWindow *window) +{ + GstGLWindowPrivate *priv = window->priv; + + if (!priv->visible) + { + ShowWindowAsync (priv->internal_win_id, SW_SHOW); + priv->visible = TRUE; + } + + RedrawWindow (priv->internal_win_id, NULL, NULL, + RDW_NOERASE | RDW_INTERNALPAINT | RDW_INVALIDATE); +} + +void +gst_gl_window_run_loop (GstGLWindow *window) +{ + GstGLWindowPrivate *priv = window->priv; + gboolean running = TRUE; + gboolean bRet = FALSE; + MSG msg; + + g_debug ("begin loop\n"); + + while (running && (bRet = GetMessage (&msg, NULL, 0, 0)) != 0) + { + if (bRet == -1) + { + g_error ("Failed to get message %x\r\n", GetLastError()); + running = FALSE; + } + else + { + TranslateMessage (&msg); + DispatchMessage (&msg); + } + } + + g_debug ("end loop\n"); +} + +/* Thread safe */ +void +gst_gl_window_quit_loop (GstGLWindow *window, GstGLWindowCB callback, gpointer data) +{ + if (window) + { + GstGLWindowPrivate *priv = window->priv; + LRESULT res = PostMessage(priv->internal_win_id, WM_GST_GL_WINDOW_QUIT, (WPARAM) data, (LPARAM) callback); + g_assert (SUCCEEDED (res)); + g_debug ("end loop requested\n"); + } +} + +/* Thread safe */ +void +gst_gl_window_send_message (GstGLWindow *window, GstGLWindowCB callback, gpointer data) +{ + if (window) + { + GstGLWindowPrivate *priv = window->priv; + LRESULT res = SendMessage (priv->internal_win_id, WM_GST_GL_WINDOW_CUSTOM, (WPARAM) data, (LPARAM) callback); + g_assert (SUCCEEDED (res)); + } +} + +LRESULT CALLBACK window_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + if (uMsg == WM_CREATE) { + + GstGLWindow *window = (GstGLWindow *) (((LPCREATESTRUCT) lParam)->lpCreateParams); + + g_debug ("WM_CREATE\n"); + + g_assert (window); + + { + EGLint majorVersion; + EGLint minorVersion; + EGLint numConfigs; + EGLConfig config; + EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE }; + + EGLint attribList[] = + { + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 8, + EGL_STENCIL_SIZE, 8, + EGL_SAMPLE_BUFFERS, EGL_DONT_CARE, //1 + EGL_NONE + }; + + GstGLWindowPrivate *priv = window->priv; + + priv->display = eglGetDisplay (GetDC (hWnd)); + if (priv->display != EGL_NO_DISPLAY) + g_debug ("display retrieved: %d\n", priv->display); + else + g_debug ("failed to retrieve display %d, %s\n", hWnd, EGLErrorString()); + + if (eglInitialize (priv->display, &majorVersion, &minorVersion)) + g_debug ("egl initialized: %d.%d\n", majorVersion, minorVersion); + else + g_debug ("failed to initialize egl %d, %s\n", priv->display, EGLErrorString()); + + if (eglGetConfigs (priv->display, NULL, 0, &numConfigs)) + g_debug ("configs retrieved: %d\n", numConfigs); + else + g_debug ("failed to retrieve configs %d, %s\n", priv->display, EGLErrorString()); + + if (eglChooseConfig (priv->display, attribList, &config, 1, &numConfigs)) + g_debug ("config set: %d, %d\n", config, numConfigs); + else + g_debug ("failed to set config %d, %s\n", priv->display, EGLErrorString()); + + priv->surface = eglCreateWindowSurface (priv->display, config, (EGLNativeWindowType)hWnd, NULL); + if (priv->surface != EGL_NO_SURFACE) + g_debug ("surface created: %d\n", priv->surface); + else + g_debug ("failed to create surface %d, %d, %d, %s\n", priv->display, priv->surface, hWnd, EGLErrorString()); + + priv->gl_context = eglCreateContext (priv->display, config, EGL_NO_CONTEXT, contextAttribs); + if (priv->gl_context != EGL_NO_CONTEXT) + g_debug ("gl context created: %d\n", priv->gl_context); + else + g_debug ("failed to create glcontext %d, %d, s\n", priv->gl_context, hWnd, EGLErrorString()); + + ReleaseDC (hWnd, priv->display); + + if (!eglMakeCurrent (priv->display, priv->surface, priv->surface, priv->gl_context)) + g_debug ("failed to make opengl context current %d, %s\n", hWnd, EGLErrorString()); + } + + SetProp (hWnd, "gl_window", window); + + return 0; + } + else if (GetProp(hWnd, "gl_window")) { + + GstGLWindow *window = GetProp(hWnd, "gl_window"); + GstGLWindowPrivate *priv = NULL; + + g_assert (window); + + priv = window->priv; + + g_assert (priv); + + g_assert (priv->internal_win_id == hWnd); + + g_assert (priv->gl_context == eglGetCurrentContext()); + + switch ( uMsg ) { + + case WM_SIZE: + { + if (priv->resize_cb) + priv->resize_cb (priv->resize_data, LOWORD(lParam), HIWORD(lParam)); + break; + } + + case WM_PAINT: + { + if (priv->draw_cb) + { + priv->draw_cb (priv->draw_data); + eglSwapBuffers (priv->display, priv->surface); + ValidateRect (hWnd, NULL); + } + break; + } + + case WM_CLOSE: + { + ShowWindowAsync (priv->internal_win_id, SW_HIDE); + + if (priv->close_cb) + priv->close_cb (priv->close_data); + + priv->draw_cb = NULL; + priv->draw_data = NULL; + priv->resize_cb = NULL; + priv->resize_data = NULL; + priv->close_cb = NULL; + priv->close_data = NULL; + break; + } + + case WM_GST_GL_WINDOW_QUIT: + { + HWND parent_id = 0; + GstGLWindowCB destroy_cb = (GstGLWindowCB) lParam; + + g_debug ("WM_CLOSE\n"); + + destroy_cb ((gpointer) wParam); + + parent_id = GetProp (hWnd, "gl_window_parent_id"); + if (parent_id) + { + WNDPROC parent_proc = GetProp (parent_id, "gl_window_parent_proc"); + + g_assert (parent_proc); + + SetWindowLongPtr (parent_id, GWL_WNDPROC, (LONG) (guint64) parent_proc); + SetParent (hWnd, NULL); + + RemoveProp (parent_id, "gl_window_parent_proc"); + RemoveProp (hWnd, "gl_window_parent_id"); + } + + priv->is_closed = TRUE; + RemoveProp (hWnd, "gl_window"); + + if (!eglMakeCurrent (priv->display, priv->surface, priv->surface, EGL_NO_CONTEXT)) + g_debug ("failed to make current null context %d, %s\n", priv->display, EGLErrorString()); + + if (priv->gl_context) + { + if (!eglDestroyContext (priv->display, priv->gl_context)) + g_debug ("failed to destroy context %d, %s\n", priv->gl_context, EGLErrorString()); + priv->gl_context = NULL; + } + + if (priv->surface) + { + if (!eglDestroySurface (priv->display, priv->surface)) + g_debug ("failed to destroy surface %d, %s\n", priv->surface, EGLErrorString()); + priv->surface = NULL; + } + + if (priv->surface) + { + if (!eglTerminate (priv->display)) + g_debug ("failed to terminate display %d, %s\n", priv->display, EGLErrorString()); + priv->surface = NULL; + } + + if (priv->internal_win_id) + { + if (!DestroyWindow(priv->internal_win_id)) + g_debug ("failed to destroy window %d, 0x%x\n", hWnd, GetLastError()); + } + + PostQuitMessage (0); + break; + } + + case WM_CAPTURECHANGED: + { + g_debug ("WM_CAPTURECHANGED\n"); + if (priv->draw_cb) + priv->draw_cb (priv->draw_data); + break; + } + + case WM_GST_GL_WINDOW_CUSTOM: + { + if (!priv->is_closed) + { + GstGLWindowCB custom_cb = (GstGLWindowCB) lParam; + custom_cb ((gpointer) wParam); + } + break; + } + + case WM_ERASEBKGND: + return TRUE; + + default: + { + /* transmit messages to the parrent (ex: mouse/keyboard input) */ + HWND parent_id = GetProp (hWnd, "gl_window_parent_id"); + if (parent_id) + PostMessage (parent_id, uMsg, wParam, lParam); + return DefWindowProc (hWnd, uMsg, wParam, lParam); + } + } + + return 0; + } + else + return DefWindowProc( hWnd, uMsg, wParam, lParam ); +} + +LRESULT FAR PASCAL sub_class_proc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + WNDPROC window_parent_proc = GetProp (hWnd, "gl_window_parent_proc"); + + if (uMsg == WM_SIZE) + { + HWND gl_window_id = GetProp (hWnd, "gl_window_id"); + MoveWindow (gl_window_id, 0, 0, LOWORD(lParam), HIWORD(lParam), FALSE); + } + + return CallWindowProc (window_parent_proc, hWnd, uMsg, wParam, lParam); +} + +const gchar* EGLErrorString() +{ + EGLint nErr = eglGetError(); + switch(nErr){ + case EGL_SUCCESS: + return "EGL_SUCCESS"; + case EGL_BAD_DISPLAY: + return "EGL_BAD_DISPLAY"; + case EGL_NOT_INITIALIZED: + return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: + return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: + return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: + return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONFIG: + return "EGL_BAD_CONFIG"; + case EGL_BAD_CONTEXT: + return "EGL_BAD_CONTEXT"; + case EGL_BAD_CURRENT_SURFACE: + return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_MATCH: + return "EGL_BAD_MATCH"; + case EGL_BAD_NATIVE_PIXMAP: + return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: + return "EGL_BAD_NATIVE_WINDOW"; + case EGL_BAD_PARAMETER: + return "EGL_BAD_PARAMETER"; + case EGL_BAD_SURFACE: + return "EGL_BAD_SURFACE"; + default: + return "unknown"; + } +} diff --git a/gst/gl/gstgldownload.c b/gst/gl/gstgldownload.c index d1f05064fe..396cc58f42 100644 --- a/gst/gl/gstgldownload.c +++ b/gst/gl/gstgldownload.c @@ -74,17 +74,43 @@ GST_ELEMENT_DETAILS ("OpenGL video maker", "A from GL to video flow filter", "Julien Isorce "); +#ifndef OPENGL_ES2 +#define ADDITIONAL_CAPS \ + +#else +#define ADDITIONAL_CAPS +#endif + +#ifndef OPENGL_ES2 static GstStaticPadTemplate gst_gl_download_src_pad_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";" - GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx ";" - GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";" - GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA ";" - GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_ABGR ";" + GST_STATIC_CAPS ( + GST_VIDEO_CAPS_RGB ";" + GST_VIDEO_CAPS_RGBx ";" + GST_VIDEO_CAPS_RGBA ";" + GST_VIDEO_CAPS_BGR ";" + GST_VIDEO_CAPS_BGRx ";" + GST_VIDEO_CAPS_BGRA ";" + GST_VIDEO_CAPS_xRGB ";" + GST_VIDEO_CAPS_xBGR ";" + GST_VIDEO_CAPS_ARGB ";" + GST_VIDEO_CAPS_ABGR ";" GST_VIDEO_CAPS_YUV ("{ I420, YV12, YUY2, UYVY, AYUV }")) ); +#else +static GstStaticPadTemplate gst_gl_download_src_pad_template = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ( + GST_VIDEO_CAPS_RGB ";" + GST_VIDEO_CAPS_RGBx ";" + GST_VIDEO_CAPS_RGBA ";" + GST_VIDEO_CAPS_YUV ("{ YUY2, UYVY, AYUV }")) + ); +#endif static GstStaticPadTemplate gst_gl_download_sink_pad_template = GST_STATIC_PAD_TEMPLATE ("sink", diff --git a/gst/gl/gstglfiltercube.c b/gst/gl/gstglfiltercube.c index 386913903d..225b353d65 100644 --- a/gst/gl/gstglfiltercube.c +++ b/gst/gl/gstglfiltercube.c @@ -80,11 +80,59 @@ static void gst_gl_filter_cube_get_property (GObject * object, guint prop_id, static gboolean gst_gl_filter_cube_set_caps (GstGLFilter * filter, GstCaps * incaps, GstCaps * outcaps); +#ifdef OPENGL_ES2 +static void gst_gl_filter_cube_reset (GstGLFilter * filter); +static void gst_gl_filter_cube_init_shader (GstGLFilter * filter); +#endif static gboolean gst_gl_filter_cube_filter (GstGLFilter * filter, GstGLBuffer * inbuf, GstGLBuffer * outbuf); static void gst_gl_filter_cube_callback (gint width, gint height, guint texture, gpointer stuff); +#ifdef OPENGL_ES2 +//vertex source +static const gchar *cube_v_src = + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "uniform mat4 u_matrix; \n" + "uniform float xrot_degree, yrot_degree, zrot_degree; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " float PI = 3.14159265; \n" + " float xrot = xrot_degree*2.0*PI/360.0; \n" + " float yrot = yrot_degree*2.0*PI/360.0; \n" + " float zrot = zrot_degree*2.0*PI/360.0; \n" + " mat4 matX = mat4 ( \n" + " 1.0, 0.0, 0.0, 0.0, \n" + " 0.0, cos(xrot), sin(xrot), 0.0, \n" + " 0.0, -sin(xrot), cos(xrot), 0.0, \n" + " 0.0, 0.0, 0.0, 1.0 ); \n" + " mat4 matY = mat4 ( \n" + " cos(yrot), 0.0, -sin(yrot), 0.0, \n" + " 0.0, 1.0, 0.0, 0.0, \n" + " sin(yrot), 0.0, cos(yrot), 0.0, \n" + " 0.0, 0.0, 0.0, 1.0 ); \n" + " mat4 matZ = mat4 ( \n" + " cos(zrot), sin(zrot), 0.0, 0.0, \n" + " -sin(zrot), cos(zrot), 0.0, 0.0, \n" + " 0.0, 0.0, 1.0, 0.0, \n" + " 0.0, 0.0, 0.0, 1.0 ); \n" + + " gl_Position = matZ * matY * matX * u_matrix * a_position; \n" + " v_texCoord = a_texCoord; \n" + "} \n"; + +//fragment source +static const gchar *cube_f_src = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" + "} \n"; +#endif static void gst_gl_filter_cube_base_init (gpointer klass) @@ -103,6 +151,10 @@ gst_gl_filter_cube_class_init (GstGLFilterCubeClass * klass) gobject_class->set_property = gst_gl_filter_cube_set_property; gobject_class->get_property = gst_gl_filter_cube_get_property; +#ifdef OPENGL_ES2 + GST_GL_FILTER_CLASS (klass)->onInitFBO = gst_gl_filter_cube_init_shader; + GST_GL_FILTER_CLASS (klass)->onReset = gst_gl_filter_cube_reset; +#endif GST_GL_FILTER_CLASS (klass)->set_caps = gst_gl_filter_cube_set_caps; GST_GL_FILTER_CLASS (klass)->filter = gst_gl_filter_cube_filter; @@ -140,6 +192,9 @@ gst_gl_filter_cube_class_init (GstGLFilterCubeClass * klass) static void gst_gl_filter_cube_init (GstGLFilterCube * filter, GstGLFilterCubeClass * klass) { +#ifdef OPENGL_ES + filter->shader = NULL; +#endif filter->fovy = 45; filter->aspect = 0; filter->znear = 0.1; @@ -205,6 +260,27 @@ gst_gl_filter_cube_set_caps (GstGLFilter * filter, GstCaps * incaps, return TRUE; } +#ifdef OPENGL_ES2 +static void +gst_gl_filter_cube_reset (GstGLFilter * filter) +{ + GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (filter); + + //blocking call, wait the opengl thread has destroyed the shader + gst_gl_display_del_shader (filter->display, cube_filter->shader); +} + +static void +gst_gl_filter_cube_init_shader (GstGLFilter * filter) +{ + GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (filter); + + //blocking call, wait the opengl thread has compiled the shader + gst_gl_display_gen_shader (filter->display, cube_v_src, cube_f_src, + &cube_filter->shader); +} +#endif + static gboolean gst_gl_filter_cube_filter (GstGLFilter * filter, GstGLBuffer * inbuf, GstGLBuffer * outbuf) @@ -227,12 +303,13 @@ static void gst_gl_filter_cube_callback (gint width, gint height, guint texture, gpointer stuff) { + GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (stuff); + static GLfloat xrot = 0; static GLfloat yrot = 0; static GLfloat zrot = 0; - GstGLFilterCube *cube_filter = GST_GL_FILTER_CUBE (stuff); - +#ifndef OPENGL_ES2 glEnable (GL_DEPTH_TEST); glEnable (GL_TEXTURE_RECTANGLE_ARB); @@ -247,6 +324,7 @@ gst_gl_filter_cube_callback (gint width, gint height, guint texture, glClearColor (cube_filter->red, cube_filter->green, cube_filter->blue, 0.0); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glMatrixMode (GL_MODELVIEW); glLoadIdentity (); @@ -312,10 +390,131 @@ gst_gl_filter_cube_callback (gint width, gint height, guint texture, glTexCoord2f ((gfloat) width, (gfloat) height); glVertex3f (-1.0f, 1.0f, -1.0f); glEnd (); +#else + const GLfloat v_vertices [] = { + + //front face + 1.0f, 1.0f, -1.0f, + 1.0f, 0.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + 0.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + 0.0f, 0.0f, + //back face + 1.0f, 1.0f, 1.0f, + 1.0f, 0.0f, + -1.0f, 1.0f, 1.0f, + 0.0f, 0.0f, + -1.0f, -1.0f, 1.0f, + 0.0f, 1.0f, + 1.0f, -1.0f, 1.0f, + 1.0f, 1.0f, + //right face + 1.0f, 1.0f, 1.0f, + 1.0f, 0.0f, + 1.0f, -1.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, -1.0f, -1.0f, + 0.0f, 1.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, + //left face + -1.0f, 1.0f, 1.0f, + 1.0f, 0.0f, + -1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, + -1.0f, -1.0f, -1.0f, + 0.0f, 1.0f, + -1.0f, -1.0f, 1.0f, + 0.0f, 0.0f, + //top face + 1.0f, -1.0f, 1.0f, + 1.0f, 0.0f, + -1.0f, -1.0f, 1.0f, + 0.0f, 0.0f, + -1.0f, -1.0f, -1.0f, + 0.0f, 1.0f, + 1.0f, -1.0f, -1.0f, + 1.0f, 1.0f, + //bottom face + 1.0f, 1.0f, 1.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, -1.0f, + 1.0f, 1.0f, + -1.0f, 1.0f, -1.0f, + 0.0f, 1.0f, + -1.0f, 1.0f, 1.0f, + 0.0f, 0.0f + }; + + GLushort indices[] = { + 0, 1, 2, + 0, 2, 3, + 4, 5, 6, + 4, 6, 7, + 8, 9, 10, + 8, 10, 11, + 12, 13, 14, + 12, 14, 15, + 16, 17, 18, + 16, 18, 19, + 20, 21, 22, + 20, 22, 23 + }; + + GLint attr_position_loc = 0; + GLint attr_texture_loc = 0; + + const GLfloat matrix[] = { + 0.5f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.5f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.5f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f}; + + glEnable (GL_DEPTH_TEST); + + glClearColor (cube_filter->red, cube_filter->green, cube_filter->blue, 0.0); + glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + gst_gl_shader_use (cube_filter->shader); + + attr_position_loc = + gst_gl_shader_get_attribute_location (cube_filter->shader, + "a_position"); + attr_texture_loc = + gst_gl_shader_get_attribute_location (cube_filter->shader, + "a_texCoord"); + + //Load the vertex position + glVertexAttribPointer (attr_position_loc, 3, GL_FLOAT, + GL_FALSE, 5 * sizeof(GLfloat), v_vertices); + + //Load the texture coordinate + glVertexAttribPointer (attr_texture_loc, 2, GL_FLOAT, + GL_FALSE, 5 * sizeof(GLfloat), &v_vertices[3]); + + glEnableVertexAttribArray (attr_position_loc); + glEnableVertexAttribArray (attr_texture_loc); + + glActiveTexture (GL_TEXTURE0); + glBindTexture (GL_TEXTURE_2D, texture); + gst_gl_shader_set_uniform_1i (cube_filter->shader, "s_texture", 0); + gst_gl_shader_set_uniform_1f (cube_filter->shader, "xrot_degree", xrot); + gst_gl_shader_set_uniform_1f (cube_filter->shader, "yrot_degree", yrot); + gst_gl_shader_set_uniform_1f (cube_filter->shader, "zrot_degree", zrot); + gst_gl_shader_set_uniform_matrix_4fv (cube_filter->shader, "u_matrix", 1, GL_FALSE, matrix); + + glDrawElements (GL_TRIANGLES, 36, GL_UNSIGNED_SHORT, indices); + + glDisableVertexAttribArray (attr_position_loc); + glDisableVertexAttribArray (attr_texture_loc); +#endif + + glDisable (GL_DEPTH_TEST); xrot += 0.3f; yrot += 0.2f; zrot += 0.4f; - - glDisable (GL_DEPTH_TEST); } diff --git a/gst/gl/gstglfiltercube.h b/gst/gl/gstglfiltercube.h index 59c836f266..47e94d67d0 100644 --- a/gst/gl/gstglfiltercube.h +++ b/gst/gl/gstglfiltercube.h @@ -39,6 +39,10 @@ struct _GstGLFilterCube { GstGLFilter filter; +#ifdef OPENGL_ES2 + GstGLShader *shader; +#endif + //background color gfloat red; gfloat green; diff --git a/gst/gl/gstglimagesink.c b/gst/gl/gstglimagesink.c index d65db83040..547db010d4 100644 --- a/gst/gl/gstglimagesink.c +++ b/gst/gl/gstglimagesink.c @@ -124,6 +124,7 @@ GST_ELEMENT_DETAILS ("OpenGL video sink", "A videosink based on OpenGL", "Julien Isorce "); +#ifndef OPENGL_ES2 static GstStaticPadTemplate gst_glimage_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, @@ -136,6 +137,19 @@ static GstStaticPadTemplate gst_glimage_sink_template = GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_ABGR ";" GST_VIDEO_CAPS_YUV ("{ I420, YV12, YUY2, UYVY, AYUV }")) ); +#else +static GstStaticPadTemplate gst_glimage_sink_template = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ( + GST_GL_VIDEO_CAPS ";" + GST_VIDEO_CAPS_RGB ";" + GST_VIDEO_CAPS_RGBx ";" + GST_VIDEO_CAPS_RGBA ";" + GST_VIDEO_CAPS_YUV ("{ I420, YV12, YUY2, UYVY, AYUV }")) + ); +#endif enum { diff --git a/gst/gl/gstglupload.c b/gst/gl/gstglupload.c index 98813c0498..e8cf075875 100644 --- a/gst/gl/gstglupload.c +++ b/gst/gl/gstglupload.c @@ -89,17 +89,36 @@ GST_STATIC_PAD_TEMPLATE ("src", ); /* Source pad definition */ +#ifndef OPENGL_ES2 static GstStaticPadTemplate gst_gl_upload_sink_pad_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";" - GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx ";" - GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";" - GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA ";" - GST_VIDEO_CAPS_ARGB ";" GST_VIDEO_CAPS_ABGR ";" + GST_STATIC_CAPS ( + GST_VIDEO_CAPS_RGB ";" + GST_VIDEO_CAPS_RGBx ";" + GST_VIDEO_CAPS_RGBA ";" + GST_VIDEO_CAPS_BGR ";" + GST_VIDEO_CAPS_BGRx ";" + GST_VIDEO_CAPS_BGRA ";" + GST_VIDEO_CAPS_xRGB ";" + GST_VIDEO_CAPS_xBGR ";" + GST_VIDEO_CAPS_ARGB ";" + GST_VIDEO_CAPS_ABGR ";" GST_VIDEO_CAPS_YUV ("{ I420, YV12, YUY2, UYVY, AYUV }")) ); +#else +static GstStaticPadTemplate gst_gl_upload_sink_pad_template = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ( + GST_VIDEO_CAPS_RGB ";" + GST_VIDEO_CAPS_RGBx ";" + GST_VIDEO_CAPS_RGBA ";" + GST_VIDEO_CAPS_YUV ("{ I420, YV12, YUY2, UYVY, AYUV }")) + ); +#endif /* Properties */ enum diff --git a/gst/gl/gstopengl.c b/gst/gl/gstopengl.c index 5d07a50eb5..edc99493ba 100644 --- a/gst/gl/gstopengl.c +++ b/gst/gl/gstopengl.c @@ -43,21 +43,25 @@ #include "config.h" #endif -#include "gstgltestsrc.h" #include "gstglupload.h" +#include "gstgldownload.h" +#include "gstglimagesink.h" + #include "gstglfiltercube.h" + +GType gst_gl_filter_cube_get_type (void); + +#ifndef OPENGL_ES2 +#include "gstgltestsrc.h" #include "gstglfilterlaplacian.h" #include "gstglfilterglass.h" #include "gstglfilterapp.h" -#include "gstgldownload.h" -#include "gstglimagesink.h" #include "gstglcolorscale.h" #include "gstgleffects.h" #include "gstglbumper.h" GType gst_gl_effects_get_type (void); GType gst_gl_filter_app_get_type (void); -GType gst_gl_filter_cube_get_type (void); GType gst_gl_filterblur_get_type (void); GType gst_gl_filtersobel_get_type (void); GType gst_gl_filter_edge_get_type (void); @@ -66,6 +70,7 @@ GType gst_gl_filter_glass_get_type (void); GType gst_gl_overlay_get_type (void); GType gst_gl_differencematte_get_type (void); GType gst_gl_bumper_get_type (void); +#endif #define GST_CAT_DEFAULT gst_gl_gstgl_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); @@ -76,13 +81,18 @@ plugin_init (GstPlugin * plugin) { GST_DEBUG_CATEGORY_INIT (gst_gl_gstgl_debug, "gstopengl", 0, "gstopengl"); - if (!gst_element_register (plugin, "gltestsrc", - GST_RANK_NONE, GST_TYPE_GL_TEST_SRC)) { + if (!gst_element_register (plugin, "glupload", + GST_RANK_NONE, GST_TYPE_GL_UPLOAD)) { return FALSE; } - if (!gst_element_register (plugin, "glupload", - GST_RANK_NONE, GST_TYPE_GL_UPLOAD)) { + if (!gst_element_register (plugin, "gldownload", + GST_RANK_NONE, GST_TYPE_GL_DOWNLOAD)) { + return FALSE; + } + + if (!gst_element_register (plugin, "glimagesink", + GST_RANK_NONE, GST_TYPE_GLIMAGE_SINK)) { return FALSE; } @@ -90,6 +100,13 @@ plugin_init (GstPlugin * plugin) GST_RANK_NONE, GST_TYPE_GL_FILTER_CUBE)) { return FALSE; } + +#ifndef OPENGL_ES2 + if (!gst_element_register (plugin, "gltestsrc", + GST_RANK_NONE, GST_TYPE_GL_TEST_SRC)) { + return FALSE; + } + if (!gst_element_register (plugin, "gloverlay", GST_RANK_NONE, gst_gl_overlay_get_type ())) { return FALSE; @@ -133,20 +150,11 @@ plugin_init (GstPlugin * plugin) return FALSE; } - if (!gst_element_register (plugin, "gldownload", - GST_RANK_NONE, GST_TYPE_GL_DOWNLOAD)) { - return FALSE; - } - - if (!gst_element_register (plugin, "glimagesink", - GST_RANK_NONE, GST_TYPE_GLIMAGE_SINK)) { - return FALSE; - } - if (!gst_element_register (plugin, "glcolorscale", GST_RANK_NONE, GST_TYPE_GL_COLORSCALE)) { return FALSE; } +#endif return TRUE; }