[321/906] add OpenGL ES 2.x support.
authorJulien Isorce <julien.isorce@gmail.com>
Sun, 15 Mar 2009 13:48:19 +0000 (14:48 +0100)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:21 +0000 (19:31 +0000)
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
gst-libs/gst/gl/gstgldisplay.h
gst-libs/gst/gl/gstgles2.h [new file with mode: 0644]
gst-libs/gst/gl/gstglshader.c
gst-libs/gst/gl/gstglshader.h
gst-libs/gst/gl/gstglwindow.h
gst-libs/gst/gl/gstglwindow_winCE.c [new file with mode: 0644]

index e250117..42f3abf 100644 (file)
@@ -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 ();
 }
index 3f9eb1b..6ff308a 100644 (file)
@@ -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 (file)
index 0000000..76ef4b1
--- /dev/null
@@ -0,0 +1,117 @@
+/* 
+ * GStreamer
+ * Copyright (C) 2009 Julien Isorce <julien.isorce@gmail.com>
+ *
+ * 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__ */
index 04cbbf4..8ed11a8 100644 (file)
@@ -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)
 {
index 3506997..6a547cb 100644 (file)
 #ifndef __GST_GL_SHADER_H__
 #define __GST_GL_SHADER_H__
 
+/* OpenGL 2.0 for Embedded Systems */
+#ifdef OPENGL_ES2
+#include <GLES2/gl2.h>
+#include "gstgles2.h"
+/* OpenGL for usual systems */
+#else
 #include <GL/glew.h>
+#endif
 #include <gst/gst.h>
 
 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);
 
index 10cdd90..e68333c 100644 (file)
 #ifndef __GST_GL_WINDOW_H__
 #define __GST_GL_WINDOW_H__
 
+/* OpenGL 2.0 for Embedded Systems */
+#ifdef OPENGL_ES2
+#undef UNICODE
+#include <EGL/egl.h>
+#define UNICODE
+#include <GLES2/gl2.h>
+#include "gstgles2.h"
+/* OpenGL for usual systems */
+#else
 #if (!GNUSTEP && MACOS)
 #include <OpenGL/glew.h>
 #include <OpenGL/OpenGL.h>
@@ -29,6 +38,7 @@
 #include <GL/glew.h>
 #include <GL/gl.h>
 #endif
+#endif
 
 #include <gst/gst.h>
 
diff --git a/gst-libs/gst/gl/gstglwindow_winCE.c b/gst-libs/gst/gl/gstglwindow_winCE.c
new file mode 100644 (file)
index 0000000..be736f8
--- /dev/null
@@ -0,0 +1,610 @@
+/*
+ * GStreamer
+ * Copyright (C) 2009 Julien Isorce <julien.isorce@gmail.com>
+ *
+ * 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";
+  }
+}