[573/906] add upload and download library objects
authorMatthew Waters <ystreet00@gmail.com>
Sun, 16 Sep 2012 11:23:09 +0000 (21:23 +1000)
committerTim-Philipp Müller <tim@centricular.com>
Sat, 9 Dec 2017 19:31:25 +0000 (19:31 +0000)
allows multiple upload pipelines that previously wasn't possible
 (i.e. upload RGB and I420 and ... on the same GstGLDisplay)

gst-libs/gst/gl/gstgldisplay.c
gst-libs/gst/gl/gstgldisplay.h
gst-libs/gst/gl/gstgldownload.c [new file with mode: 0644]
gst-libs/gst/gl/gstgldownload.h [new file with mode: 0644]
gst-libs/gst/gl/gstglupload.c [new file with mode: 0644]
gst-libs/gst/gl/gstglupload.h [new file with mode: 0644]

index fbdb12a..e65234f 100644 (file)
 
 #include <stdio.h>
 
+#include <gst/gst.h>
 #include <gst/video/gstvideosink.h>
 #include "gstgldisplay.h"
+#include "gstgldownload.h"
+#include "gstglmemory.h"
 
 #ifndef GLEW_VERSION_MAJOR
 #define GLEW_VERSION_MAJOR 4
@@ -57,7 +60,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_gl_display_debug);
 G_DEFINE_TYPE_WITH_CODE (GstGLDisplay, gst_gl_display, G_TYPE_OBJECT,
     DEBUG_INIT);
 static void gst_gl_display_finalize (GObject * object);
-void gst_gl_display_check_framebuffer_status (void);
 
 /* Called in the gl thread, protected by lock and unlock */
 gpointer gst_gl_display_thread_create_context (GstGLDisplay * display);
@@ -66,10 +68,6 @@ void gst_gl_display_thread_run_generic (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);
-void gst_gl_display_thread_do_download (GstGLDisplay * display);
 void gst_gl_display_thread_gen_fbo (GstGLDisplay * display);
 void gst_gl_display_thread_use_fbo (GstGLDisplay * display);
 void gst_gl_display_thread_use_fbo_v2 (GstGLDisplay * display);
@@ -86,14 +84,6 @@ void gst_gl_display_on_close (GstGLDisplay * display);
 void gst_gl_display_del_texture_thread (GstGLDisplay * display,
     GLuint * pTexture);
 
-/* To not make gst_gl_display_thread_do_upload
- * and gst_gl_display_thread_do_download too big */
-void gst_gl_display_thread_init_upload_fbo (GstGLDisplay * display);
-void gst_gl_display_thread_do_upload_make (GstGLDisplay * display);
-void gst_gl_display_thread_do_upload_fill (GstGLDisplay * display);
-void gst_gl_display_thread_do_upload_draw (GstGLDisplay * display);
-void gst_gl_display_thread_do_download_draw_rgb (GstGLDisplay * display);
-void gst_gl_display_thread_do_download_draw_yuv (GstGLDisplay * display);
 void gst_gl_display_gen_texture_window_cb (GstGLDisplay * display);
 
 //------------------------------------------------------------
@@ -118,7 +108,6 @@ gst_gl_display_init (GstGLDisplay * display)
   display->gl_thread = NULL;
   display->gl_window = NULL;
   display->isAlive = TRUE;
-  display->texture_pool = g_hash_table_new (g_direct_hash, g_direct_equal);
 
   //conditions
   display->cond_create_context = g_cond_new ();
@@ -146,20 +135,7 @@ gst_gl_display_init (GstGLDisplay * display)
   display->clientDrawCallback = NULL;
   display->client_data = NULL;
 
-  //upload
-  display->upload_fbo = 0;
-  display->upload_depth_buffer = 0;
-  display->upload_outtex = 0;
-  display->upload_intex = 0;
-  display->upload_intex_u = 0;
-  display->upload_intex_v = 0;
-  display->upload_width = 0;
-  display->upload_height = 0;
-  display->upload_video_format = GST_VIDEO_FORMAT_RGBx;
-  display->upload_colorspace_conversion = GST_GL_DISPLAY_CONVERSION_GLSL;
-  display->upload_data_width = 0;
-  display->upload_data_height = 0;
-  display->upload_frame = NULL;
+  display->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_GLSL;
 
   //foreign gl context
   display->external_gl_context = 0;
@@ -192,225 +168,17 @@ gst_gl_display_init (GstGLDisplay * display)
   display->del_fbo = 0;
   display->del_depth_buffer = 0;
 
-  //download
-  display->download_fbo = 0;
-  display->download_depth_buffer = 0;
-  display->download_texture = 0;
-  display->download_texture_u = 0;
-  display->download_texture_v = 0;
-  display->download_width = 0;
-  display->download_height = 0;
-  display->download_video_format = 0;
-  display->download_frame = NULL;
-  display->ouput_texture = 0;
-  display->ouput_texture_width = 0;
-  display->ouput_texture_height = 0;
-
   //action gen and del shader
   display->gen_shader_fragment_source = NULL;
   display->gen_shader_vertex_source = NULL;
   display->gen_shader = NULL;
   display->del_shader = NULL;
 
-  //fragment shader upload
-  display->shader_upload_YUY2 = NULL;
-  display->shader_upload_UYVY = NULL;
-  display->shader_upload_I420_YV12 = NULL;
-  display->shader_upload_AYUV = NULL;
-
-#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"
-#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";
-
-  //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"
-#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";
-
-  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=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"
-      "  g=texture2DRect(tex,vec2(fx*2.0,fy)).g;\n"
-      "  b=texture2DRect(tex,vec2(fx*2.0,fy)).b;\n"
-      "  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";
-
-  //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"
-      "uniform float w, h;\n"
-      "void main(void) {\n"
-      "  float r,g,b,r2,b2,g2,y,u,v;\n"
-      "  vec2 nxy=gl_TexCoord[0].xy;\n"
-      "  vec2 nxy2=nxy*2.0;\n"
-      "  r=texture2DRect(tex,nxy).r;\n"
-      "  g=texture2DRect(tex,nxy).g;\n"
-      "  b=texture2DRect(tex,nxy).b;\n"
-      "  r2=texture2DRect(tex,nxy2).r;\n"
-      "  g2=texture2DRect(tex,nxy2).g;\n"
-      "  b2=texture2DRect(tex,nxy2).b;\n"
-      "  y=0.299011*r + 0.586987*g + 0.114001*b;\n"
-      "  u=-0.148246*r2 -0.29102*g2 + 0.439266*b2;\n"
-      "  v=0.439271*r2 - 0.367833*g2 - 0.071438*b2 ;\n"
-      "  y=0.858885*y + 0.0625;\n"
-      "  u=u + 0.5;\n"
-      "  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";
-
-  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"
-#ifndef OPENGL_ES2
-      "  gl_FragColor=vec4(y,u,v,1.0);\n"
-#else
-      "  gl_FragColor=vec4(1.0,y,u,v);\n"
-#endif
-      "}\n";
+  display->uploads = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free,
+      g_object_unref);
+  display->downloads =
+      g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free,
+      g_object_unref);
 
 #ifdef OPENGL_ES2
   display->redisplay_vertex_shader_str =
@@ -430,36 +198,11 @@ gst_gl_display_init (GstGLDisplay * display)
       "{                                                   \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
 
   display->error_message = NULL;
+
+  gst_gl_memory_init ();
 }
 
 static void
@@ -494,14 +237,6 @@ gst_gl_display_finalize (GObject * object)
       GST_ERROR ("gl thread returned a not null pointer");
     display->gl_thread = NULL;
   }
-
-  if (display->texture_pool) {
-    //texture pool is empty after destroying the gl context
-    if (g_hash_table_size (display->texture_pool) != 0)
-      GST_ERROR ("texture pool is not empty");
-    g_hash_table_unref (display->texture_pool);
-    display->texture_pool = NULL;
-  }
   if (display->mutex) {
     g_mutex_free (display->mutex);
     display->mutex = NULL;
@@ -531,6 +266,14 @@ gst_gl_display_finalize (GObject * object)
     g_free (display->error_message);
     display->error_message = NULL;
   }
+  if (display->uploads) {
+    g_hash_table_destroy (display->uploads);
+    display->uploads = NULL;
+  }
+  if (display->downloads) {
+    g_hash_table_destroy (display->downloads);
+    display->downloads = NULL;
+  }
 }
 
 
@@ -679,99 +422,6 @@ gst_gl_display_thread_create_context (GstGLDisplay * display)
 void
 gst_gl_display_thread_destroy_context (GstGLDisplay * display)
 {
-  //colorspace_conversion specific
-  switch (display->upload_colorspace_conversion) {
-    case GST_GL_DISPLAY_CONVERSION_MESA:
-    case GST_GL_DISPLAY_CONVERSION_MATRIX:
-      break;
-    case GST_GL_DISPLAY_CONVERSION_GLSL:
-    {
-      glUseProgramObjectARB (0);
-      if (display->shader_upload_YUY2) {
-        g_object_unref (G_OBJECT (display->shader_upload_YUY2));
-        display->shader_upload_YUY2 = NULL;
-      }
-      if (display->shader_upload_UYVY) {
-        g_object_unref (G_OBJECT (display->shader_upload_UYVY));
-        display->shader_upload_UYVY = NULL;
-      }
-      if (display->shader_upload_I420_YV12) {
-        g_object_unref (G_OBJECT (display->shader_upload_I420_YV12));
-        display->shader_upload_I420_YV12 = NULL;
-      }
-      if (display->shader_upload_AYUV) {
-        g_object_unref (G_OBJECT (display->shader_upload_AYUV));
-        display->shader_upload_AYUV = NULL;
-      }
-      if (display->shader_download_YUY2) {
-        g_object_unref (G_OBJECT (display->shader_download_YUY2));
-        display->shader_download_YUY2 = NULL;
-      }
-      if (display->shader_download_UYVY) {
-        g_object_unref (G_OBJECT (display->shader_download_UYVY));
-        display->shader_download_UYVY = NULL;
-      }
-      if (display->shader_download_I420_YV12) {
-        g_object_unref (G_OBJECT (display->shader_download_I420_YV12));
-        display->shader_download_I420_YV12 = NULL;
-      }
-      if (display->shader_download_AYUV) {
-        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:
-      GST_ERROR ("Unknow colorspace conversion %d",
-          display->upload_colorspace_conversion);
-  }
-
-  if (display->upload_fbo) {
-    glDeleteFramebuffersEXT (1, &display->upload_fbo);
-    display->upload_fbo = 0;
-  }
-  if (display->upload_depth_buffer) {
-    glDeleteRenderbuffersEXT (1, &display->upload_depth_buffer);
-    display->upload_depth_buffer = 0;
-  }
-  if (display->download_fbo) {
-    glDeleteFramebuffersEXT (1, &display->download_fbo);
-    display->download_fbo = 0;
-  }
-  if (display->download_depth_buffer) {
-    glDeleteRenderbuffersEXT (1, &display->download_depth_buffer);
-    display->download_depth_buffer = 0;
-  }
-  if (display->download_texture) {
-    glDeleteTextures (1, &display->download_texture);
-    display->download_texture = 0;
-  }
-  if (display->download_texture_u) {
-    glDeleteTextures (1, &display->download_texture_u);
-    display->download_texture_u = 0;
-  }
-  if (display->download_texture_v) {
-    glDeleteTextures (1, &display->download_texture_v);
-    display->download_texture_v = 0;
-  }
-  if (display->upload_intex != 0) {
-    glDeleteTextures (1, &display->upload_intex);
-    display->upload_intex = 0;
-  }
-  if (display->upload_intex_u != 0) {
-    glDeleteTextures (1, &display->upload_intex_u);
-    display->upload_intex_u = 0;
-  }
-  if (display->upload_intex_v != 0) {
-    glDeleteTextures (1, &display->upload_intex_v);
-    display->upload_intex_v = 0;
-  }
 #ifdef OPENGL_ES2
   if (display->redisplay_shader) {
     g_object_unref (G_OBJECT (display->redisplay_shader));
@@ -779,12 +429,6 @@ gst_gl_display_thread_destroy_context (GstGLDisplay * display)
   }
 #endif
 
-/*  GST_INFO ("Cleaning texture pool");
-
-  //clean up the texture pool
-  g_hash_table_foreach_remove (display->texture_pool,
-      gst_gl_display_texture_pool_func_clean, NULL);*/
-
   GST_INFO ("Context destroyed");
 }
 
@@ -828,866 +472,99 @@ gst_gl_display_thread_init_redisplay (GstGLDisplay * display)
 }
 #endif
 
-
 /* Called in the gl thread */
 void
-gst_gl_display_thread_init_upload (GstGLDisplay * display)
+gst_gl_display_thread_gen_fbo (GstGLDisplay * display)
 {
-  GST_TRACE ("initializing upload for format:%i", display->upload_video_format);
-
-  switch (display->upload_video_format) {
-    case GST_VIDEO_FORMAT_RGBx:
-    case GST_VIDEO_FORMAT_BGRx:
-    case GST_VIDEO_FORMAT_xRGB:
-    case GST_VIDEO_FORMAT_xBGR:
-    case GST_VIDEO_FORMAT_RGBA:
-    case GST_VIDEO_FORMAT_BGRA:
-    case GST_VIDEO_FORMAT_ARGB:
-    case GST_VIDEO_FORMAT_ABGR:
-    case GST_VIDEO_FORMAT_RGB:
-    case GST_VIDEO_FORMAT_BGR:
-      //color space conversion is not needed
-      //but if the size is different we need to redraw it
-      //using fbo
-      if (display->upload_width != display->upload_data_width ||
-          display->upload_height != display->upload_data_height)
-        gst_gl_display_thread_init_upload_fbo (display);
-      break;
-    case GST_VIDEO_FORMAT_YUY2:
-    case GST_VIDEO_FORMAT_UYVY:
-    case GST_VIDEO_FORMAT_I420:
-    case GST_VIDEO_FORMAT_YV12:
-    case GST_VIDEO_FORMAT_AYUV:
-      //color space conversion is needed
-    {
-      //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");
+  //a texture must be attached to the FBO
+  GLuint fake_texture = 0;
 
-        display->upload_colorspace_conversion = GST_GL_DISPLAY_CONVERSION_GLSL;
+  GST_TRACE ("creating FBO dimensions:%ux%u", display->gen_fbo_width,
+      display->gen_fbo_height);
 
-        gst_gl_display_thread_init_upload_fbo (display);
-        if (!display->isAlive)
-          break;
+  //-- generate frame buffer object
 
-        switch (display->upload_video_format) {
-          case GST_VIDEO_FORMAT_YUY2:
-          {
-            gchar text_shader_upload_YUY2[2048];
-            sprintf (text_shader_upload_YUY2,
-                display->text_shader_upload_YUY2_UYVY, 'r', 'g', 'a');
+  if (!GLEW_EXT_framebuffer_object) {
+    //turn off the pipeline because Frame buffer object is a not present
+    gst_gl_display_set_error (display,
+        "Context, EXT_framebuffer_object not supported");
+    return;
+  }
+  //setup FBO
+  glGenFramebuffersEXT (1, &display->generated_fbo);
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->generated_fbo);
 
-            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)) {
-              gst_gl_display_set_error (display,
-                  "Failed to initialize shader for uploading YUY2");
-              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_gl_display_set_error (display, "%s", error->message);
-              g_error_free (error);
-              error = NULL;
-              gst_gl_shader_use (NULL);
-              g_object_unref (G_OBJECT (display->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,
+  //setup the render buffer for depth
+  glGenRenderbuffersEXT (1, &display->generated_depth_buffer);
+  glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, display->generated_depth_buffer);
 #ifndef OPENGL_ES2
-                display->text_shader_upload_YUY2_UYVY, 'a', 'b', 'r');
+  glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
+      display->gen_fbo_width, display->gen_fbo_height);
+  glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
+      display->gen_fbo_width, display->gen_fbo_height);
 #else
-                display->text_shader_upload_YUY2_UYVY, 'a', 'r', 'b');
+  glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
+      display->gen_fbo_width, display->gen_fbo_height);
 #endif
 
-            display->shader_upload_UYVY = gst_gl_shader_new ();
+  //setup a texture to render to
+  glGenTextures (1, &fake_texture);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fake_texture);
+  glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+      display->gen_fbo_width, display->gen_fbo_height, 0, GL_RGBA,
+      GL_UNSIGNED_BYTE, NULL);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+      GL_CLAMP_TO_EDGE);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+      GL_CLAMP_TO_EDGE);
 
-#ifndef OPENGL_ES2
-            if (!gst_gl_shader_compile_and_check (display->shader_upload_UYVY,
-                    text_shader_upload_UYVY, GST_GL_SHADER_FRAGMENT_SOURCE)) {
-              gst_gl_display_set_error (display,
-                  "Failed to initialize shader for uploading UYVY");
-              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_gl_display_set_error (display, "%s", error->message);
-              g_error_free (error);
-              error = NULL;
-              gst_gl_shader_use (NULL);
-              g_object_unref (G_OBJECT (display->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)
-                && (g_ascii_strncasecmp ("ATI Mobility Radeon HD",
-                        (gchar *) glGetString (GL_RENDERER), 22) != 0)
-                && (g_ascii_strncasecmp ("ATI Radeon HD",
-                        (gchar *) glGetString (GL_RENDERER), 13) != 0))
-              sprintf (text_shader_upload_I420_YV12,
-                  display->text_shader_upload_I420_YV12, "*0.5", "");
-            else
-              sprintf (text_shader_upload_I420_YV12,
-                  display->text_shader_upload_I420_YV12, "", "*0.5");
-#endif
+  //attach the texture to the FBO to renderer to
+  glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+      GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0);
 
-            display->shader_upload_I420_YV12 = gst_gl_shader_new ();
+  //attach the depth render buffer to the FBO
+  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+      GL_RENDERBUFFER_EXT, display->generated_depth_buffer);
 
 #ifndef OPENGL_ES2
-            if (!gst_gl_shader_compile_and_check
-                (display->shader_upload_I420_YV12, text_shader_upload_I420_YV12,
-                    GST_GL_SHADER_FRAGMENT_SOURCE)) {
-              gst_gl_display_set_error (display,
-                  "Failed to initialize shader for uploading I420 or YV12");
-              g_object_unref (G_OBJECT (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_gl_display_set_error (display, "%s", error->message);
-              g_error_free (error);
-              error = NULL;
-              gst_gl_shader_use (NULL);
-              g_object_unref (G_OBJECT (display->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");
-            }
+  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
+      GL_RENDERBUFFER_EXT, display->generated_depth_buffer);
 #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)) {
-              gst_gl_display_set_error (display,
-                  "Failed to initialize shader for uploading AYUV");
-              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_gl_display_set_error (display, "%s", error->message);
-              g_error_free (error);
-              error = NULL;
-              gst_gl_shader_use (NULL);
-              g_object_unref (G_OBJECT (display->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:
-            gst_gl_display_set_error (display,
-                "Unsupported upload video format %d",
-                display->upload_video_format);
-        }
-      }
-      //check if YCBCR MESA is available
-      else if (GLEW_MESA_ycbcr_texture) {
-        //GLSL and Color Matrix are not available on your drivers, switch to YCBCR MESA
-        GST_INFO ("Context, ARB_fragment_shader supported: no");
-        GST_INFO ("Context, GLEW_MESA_ycbcr_texture supported: yes");
-
-        display->upload_colorspace_conversion = GST_GL_DISPLAY_CONVERSION_MESA;
-
-        switch (display->upload_video_format) {
-          case GST_VIDEO_FORMAT_YUY2:
-          case GST_VIDEO_FORMAT_UYVY:
-            //color space conversion is not needed
-            //but if the size is different we need to redraw it
-            //using fbo
-            if (display->upload_width != display->upload_data_width ||
-                display->upload_height != display->upload_data_height)
-              gst_gl_display_thread_init_upload_fbo (display);
-            break;
-          case GST_VIDEO_FORMAT_I420:
-          case GST_VIDEO_FORMAT_YV12:
-          case GST_VIDEO_FORMAT_AYUV:
-            //turn off the pipeline because
-            //MESA only support YUY2 and UYVY
-            gst_gl_display_set_error (display,
-                "Your MESA version only supports YUY2 and UYVY (GLSL is required for others yuv formats)");
-            break;
-          default:
-            gst_gl_display_set_error (display,
-                "Unsupported upload video format %d",
-                display->upload_video_format);
-        }
-      }
-      //check if color matrix is available
-      else if (GLEW_ARB_imaging) {
-        //GLSL is not available on your drivers, switch to Color Matrix
-        GST_INFO ("Context, ARB_fragment_shader supported: no");
-        GST_INFO ("Context, GLEW_MESA_ycbcr_texture supported: no");
-        GST_INFO ("Context, GLEW_ARB_imaging supported: yes");
+  if (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) !=
+      GL_FRAMEBUFFER_COMPLETE_EXT)
+    gst_gl_display_set_error (display, "GL framebuffer status incomplete");
 
-        display->upload_colorspace_conversion =
-            GST_GL_DISPLAY_CONVERSION_MATRIX;
+  //unbind the FBO
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
 
-        //turn off the pipeline because we do not support it yet
-        gst_gl_display_set_error (display,
-            "Colorspace conversion using Color Matrix is not yet supported");
-      } else {
-        //turn off the pipeline because colorspace conversion is not possible
-        gst_gl_display_set_error (display,
-            "ARB_fragment_shader supported, GLEW_ARB_imaging supported, GLEW_MESA_ycbcr_texture supported, not supported");
-      }
-    }
-      break;
-    default:
-      gst_gl_display_set_error (display, "Unsupported upload video format %d",
-          display->upload_video_format);
-  }
+  glDeleteTextures (1, &fake_texture);
 }
 
 
-/* Called by the idle function */
+/* Called in the gl thread */
 void
-gst_gl_display_thread_do_upload (GstGLDisplay * display)
+gst_gl_display_thread_use_fbo (GstGLDisplay * display)
 {
-  GST_TRACE ("uploading video frame %" GST_PTR_FORMAT " with dimensions: %ix%i",
-      display->upload_frame, display->upload_data_width,
-      display->upload_data_height);
+#ifdef OPENGL_ES2
+  GLint viewport_dim[4];
+#endif
 
-  gst_gl_display_thread_do_upload_fill (display);
+  GST_TRACE ("Binding v1 FBO %u dimensions:%ux%u with texture:%u "
+      "dimensions:%ux%u", display->use_fbo, display->use_fbo_width,
+      display->use_fbo_height, display->use_fbo_texture,
+      display->input_texture_width, display->input_texture_height);
 
-  switch (display->upload_video_format) {
-    case GST_VIDEO_FORMAT_RGBx:
-    case GST_VIDEO_FORMAT_BGRx:
-    case GST_VIDEO_FORMAT_xRGB:
-    case GST_VIDEO_FORMAT_xBGR:
-    case GST_VIDEO_FORMAT_RGBA:
-    case GST_VIDEO_FORMAT_BGRA:
-    case GST_VIDEO_FORMAT_ARGB:
-    case GST_VIDEO_FORMAT_ABGR:
-    case GST_VIDEO_FORMAT_RGB:
-    case GST_VIDEO_FORMAT_BGR:
-      //color space conversion is not needed
-      //but if the size is different we need to redraw it
-      //using fbo
-      if (display->upload_width != display->upload_data_width ||
-          display->upload_height != display->upload_data_height)
-        gst_gl_display_thread_do_upload_draw (display);
-      break;
-    case GST_VIDEO_FORMAT_YUY2:
-    case GST_VIDEO_FORMAT_UYVY:
-    case GST_VIDEO_FORMAT_I420:
-    case GST_VIDEO_FORMAT_YV12:
-    case GST_VIDEO_FORMAT_AYUV:
-    {
-      switch (display->upload_colorspace_conversion) {
-        case GST_GL_DISPLAY_CONVERSION_GLSL:
-          //color space conversion is needed
-          gst_gl_display_thread_do_upload_draw (display);
-          break;
-        case GST_GL_DISPLAY_CONVERSION_MATRIX:
-          //color space conversion is needed
-          //not yet supported
-          break;
-        case GST_GL_DISPLAY_CONVERSION_MESA:
-          //color space conversion is not needed
-          //but if the size is different we need to redraw it
-          //using fbo
-          if (display->upload_width != display->upload_data_width ||
-              display->upload_height != display->upload_data_height)
-            gst_gl_display_thread_do_upload_draw (display);
-          break;
-        default:
-          gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
-              display->upload_colorspace_conversion);
-      }
-    }
-      break;
-    default:
-      gst_gl_display_set_error (display, "Unsupported upload video format %d",
-          display->upload_video_format);
-  }
-}
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->use_fbo);
 
+  //setup a texture to render to
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture);
 
-/* Called in the gl thread */
-void
-gst_gl_display_thread_init_download (GstGLDisplay * display)
-{
-  GST_TRACE ("initializing download for format %i",
-      display->download_video_format);
-
-  switch (display->download_video_format) {
-    case GST_VIDEO_FORMAT_RGBx:
-    case GST_VIDEO_FORMAT_BGRx:
-    case GST_VIDEO_FORMAT_xRGB:
-    case GST_VIDEO_FORMAT_xBGR:
-    case GST_VIDEO_FORMAT_RGBA:
-    case GST_VIDEO_FORMAT_BGRA:
-    case GST_VIDEO_FORMAT_ARGB:
-    case GST_VIDEO_FORMAT_ABGR:
-    case GST_VIDEO_FORMAT_RGB:
-    case GST_VIDEO_FORMAT_BGR:
-      //color space conversion is not needed
-      break;
-    case GST_VIDEO_FORMAT_YUY2:
-    case GST_VIDEO_FORMAT_UYVY:
-    case GST_VIDEO_FORMAT_I420:
-    case GST_VIDEO_FORMAT_YV12:
-    case GST_VIDEO_FORMAT_AYUV:
-      //color space conversion is needed
-    {
-
-      if (GLEW_EXT_framebuffer_object) {
-        GST_INFO ("Context, EXT_framebuffer_object supported: yes");
-
-        //-- init output frame buffer object (GL -> video)
-
-        //setup FBO
-        glGenFramebuffersEXT (1, &display->download_fbo);
-        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->download_fbo);
-
-        //setup the render buffer for depth
-        glGenRenderbuffersEXT (1, &display->download_depth_buffer);
-        glBindRenderbufferEXT (GL_RENDERBUFFER_EXT,
-            display->download_depth_buffer);
-#ifndef OPENGL_ES2
-        glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
-            display->download_width, display->download_height);
-        glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
-            display->download_width, display->download_height);
-#else
-        glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
-            display->download_width, display->download_height);
-#endif
-
-        //setup a first texture to render to
-        glGenTextures (1, &display->download_texture);
-        glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->download_texture);
-        glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
-            display->download_width, display->download_height, 0, GL_RGBA,
-            GL_UNSIGNED_BYTE, NULL);
-        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-            GL_LINEAR);
-        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-            GL_LINEAR);
-        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-            GL_CLAMP_TO_EDGE);
-        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-            GL_CLAMP_TO_EDGE);
-
-        //attach the first texture to the FBO to renderer to
-        glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-            GL_TEXTURE_RECTANGLE_ARB, display->download_texture, 0);
-
-        switch (display->download_video_format) {
-          case GST_VIDEO_FORMAT_YUY2:
-          case GST_VIDEO_FORMAT_UYVY:
-          case GST_VIDEO_FORMAT_AYUV:
-            //only one attached texture is needed
-            break;
-
-          case GST_VIDEO_FORMAT_I420:
-          case GST_VIDEO_FORMAT_YV12:
-            //setup a second texture to render to
-            glGenTextures (1, &display->download_texture_u);
-            glBindTexture (GL_TEXTURE_RECTANGLE_ARB,
-                display->download_texture_u);
-            glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
-                display->download_width, display->download_height, 0, GL_RGBA,
-                GL_UNSIGNED_BYTE, NULL);
-            glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-                GL_LINEAR);
-            glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-                GL_LINEAR);
-            glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-                GL_CLAMP_TO_EDGE);
-            glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-                GL_CLAMP_TO_EDGE);
-
-            //attach the second texture to the FBO to renderer to
-            glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
-                GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB,
-                display->download_texture_u, 0);
-
-            //setup a third texture to render to
-            glGenTextures (1, &display->download_texture_v);
-            glBindTexture (GL_TEXTURE_RECTANGLE_ARB,
-                display->download_texture_v);
-            glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
-                display->download_width, display->download_height, 0, GL_RGBA,
-                GL_UNSIGNED_BYTE, NULL);
-            glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-                GL_LINEAR);
-            glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-                GL_LINEAR);
-            glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-                GL_CLAMP_TO_EDGE);
-            glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-                GL_CLAMP_TO_EDGE);
-
-            //attach the third texture to the FBO to renderer to
-            glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
-                GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_RECTANGLE_ARB,
-                display->download_texture_v, 0);
-
-            display->multipleRT[0] = GL_COLOR_ATTACHMENT0_EXT;
-            display->multipleRT[1] = GL_COLOR_ATTACHMENT1_EXT;
-            display->multipleRT[2] = GL_COLOR_ATTACHMENT2_EXT;
-            break;
-          default:
-            gst_gl_display_set_error (display,
-                "Unsupported download video format %d",
-                display->download_video_format);
-        }
-
-        //attach the depth render buffer to the FBO
-        glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
-            GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
-            display->download_depth_buffer);
-
-#ifndef OPENGL_ES2
-        glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
-            GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
-            display->download_depth_buffer);
-#endif
-
-        gst_gl_display_check_framebuffer_status ();
-
-        if (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) !=
-            GL_FRAMEBUFFER_COMPLETE_EXT)
-          gst_gl_display_set_error (display,
-              "GL framebuffer status incomplete");
-
-        //unbind the FBO
-        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
-      } else {
-        //turn off the pipeline because Frame buffer object is a requirement when using filters
-        //or when using GLSL colorspace conversion
-        gst_gl_display_set_error (display,
-            "Context, EXT_framebuffer_object supported: no");
-      }
-    }
-      break;
-    default:
-      gst_gl_display_set_error (display, "Unsupported download video format %d",
-          display->download_video_format);
-  }
-
-  switch (display->download_video_format) {
-    case GST_VIDEO_FORMAT_RGBx:
-    case GST_VIDEO_FORMAT_BGRx:
-    case GST_VIDEO_FORMAT_xRGB:
-    case GST_VIDEO_FORMAT_xBGR:
-    case GST_VIDEO_FORMAT_RGBA:
-    case GST_VIDEO_FORMAT_BGRA:
-    case GST_VIDEO_FORMAT_ARGB:
-    case GST_VIDEO_FORMAT_ABGR:
-    case GST_VIDEO_FORMAT_RGB:
-    case GST_VIDEO_FORMAT_BGR:
-      //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_gl_display_set_error (display, "%s", error->message);
-        g_error_free (error);
-        error = NULL;
-        gst_gl_shader_use (NULL);
-        g_object_unref (G_OBJECT (display->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:
-    case GST_VIDEO_FORMAT_I420:
-    case GST_VIDEO_FORMAT_YV12:
-    case GST_VIDEO_FORMAT_AYUV:
-      //color space conversion is needed
-    {
-      //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:
-          {
-            gchar text_shader_download_YUY2[2048];
-            sprintf (text_shader_download_YUY2,
-                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)) {
-              gst_gl_display_set_error (display,
-                  "Failed to initialize shader for downloading YUY2");
-              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_gl_display_set_error (display, "%s", error->message);
-              g_error_free (error);
-              error = NULL;
-              gst_gl_shader_use (NULL);
-              g_object_unref (G_OBJECT (display->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:
-          {
-            gchar text_shader_download_UYVY[2048];
-            sprintf (text_shader_download_UYVY,
-                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)) {
-              gst_gl_display_set_error (display,
-                  "Failed to initialize shader for downloading UYVY");
-              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_gl_display_set_error (display, "%s", error->message);
-              g_error_free (error);
-              error = NULL;
-              gst_gl_shader_use (NULL);
-              g_object_unref (G_OBJECT (display->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:
-          case GST_VIDEO_FORMAT_YV12:
-            display->shader_download_I420_YV12 = gst_gl_shader_new ();
-            if (!gst_gl_shader_compile_and_check
-                (display->shader_download_I420_YV12,
-                    display->text_shader_download_I420_YV12,
-                    GST_GL_SHADER_FRAGMENT_SOURCE)) {
-              gst_gl_display_set_error (display,
-                  "Failed to initialize shader for downloading I420 or YV12");
-              g_object_unref (G_OBJECT (display->shader_download_I420_YV12));
-              display->shader_download_I420_YV12 = NULL;
-            }
-            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)) {
-              gst_gl_display_set_error (display,
-                  "Failed to initialize shader for downloading AYUV");
-              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_gl_display_set_error (display, "%s", error->message);
-              g_error_free (error);
-              error = NULL;
-              gst_gl_shader_use (NULL);
-              g_object_unref (G_OBJECT (display->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:
-            gst_gl_display_set_error (display,
-                "Unsupported download video format %d",
-                display->download_video_format);
-        }
-      } else {
-        //turn off the pipeline because colorspace conversion is not possible
-        gst_gl_display_set_error (display,
-            "Context, ARB_fragment_shader supported: no");
-      }
-    }
-      break;
-    default:
-      gst_gl_display_set_error (display, "Unsupported download video format %d",
-          display->download_video_format);
-  }
-}
-
-
-/* Called in the gl thread */
-void
-gst_gl_display_thread_do_download (GstGLDisplay * display)
-{
-  GstVideoFormat video_format =
-      GST_VIDEO_INFO_FORMAT (&display->download_frame->info);
-
-  GST_TRACE ("downloading image format:%i, dimensions:%ux%u", video_format,
-      GST_VIDEO_INFO_WIDTH (&display->download_frame->info),
-      GST_VIDEO_INFO_HEIGHT (&display->download_frame->info));
-
-  switch (video_format) {
-    case GST_VIDEO_FORMAT_RGBx:
-    case GST_VIDEO_FORMAT_BGRx:
-    case GST_VIDEO_FORMAT_xRGB:
-    case GST_VIDEO_FORMAT_xBGR:
-    case GST_VIDEO_FORMAT_RGBA:
-    case GST_VIDEO_FORMAT_BGRA:
-    case GST_VIDEO_FORMAT_ARGB:
-    case GST_VIDEO_FORMAT_ABGR:
-    case GST_VIDEO_FORMAT_RGB:
-    case GST_VIDEO_FORMAT_BGR:
-      //color space conversion is not needed
-      gst_gl_display_thread_do_download_draw_rgb (display);
-      break;
-    case GST_VIDEO_FORMAT_YUY2:
-    case GST_VIDEO_FORMAT_UYVY:
-    case GST_VIDEO_FORMAT_I420:
-    case GST_VIDEO_FORMAT_YV12:
-    case GST_VIDEO_FORMAT_AYUV:
-      //color space conversion is needed
-      gst_gl_display_thread_do_download_draw_yuv (display);
-      break;
-    default:
-      gst_gl_display_set_error (display, "Unsupported download video format %d",
-          video_format);
-  }
-}
-
-
-/* Called in the gl thread */
-void
-gst_gl_display_thread_gen_fbo (GstGLDisplay * display)
-{
-  //a texture must be attached to the FBO
-  GLuint fake_texture = 0;
-
-  GST_TRACE ("creating FBO dimensions:%ux%u", display->gen_fbo_width,
-      display->gen_fbo_height);
-
-  //-- generate frame buffer object
-
-  if (!GLEW_EXT_framebuffer_object) {
-    //turn off the pipeline because Frame buffer object is a not present
-    gst_gl_display_set_error (display,
-        "Context, EXT_framebuffer_object not supported");
-    return;
-  }
-  //setup FBO
-  glGenFramebuffersEXT (1, &display->generated_fbo);
-  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->generated_fbo);
-
-  //setup the render buffer for depth
-  glGenRenderbuffersEXT (1, &display->generated_depth_buffer);
-  glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, display->generated_depth_buffer);
-#ifndef OPENGL_ES2
-  glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
-      display->gen_fbo_width, display->gen_fbo_height);
-  glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
-      display->gen_fbo_width, display->gen_fbo_height);
-#else
-  glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
-      display->gen_fbo_width, display->gen_fbo_height);
-#endif
-
-  //setup a texture to render to
-  glGenTextures (1, &fake_texture);
-  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fake_texture);
-  glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
-      display->gen_fbo_width, display->gen_fbo_height, 0, GL_RGBA,
-      GL_UNSIGNED_BYTE, NULL);
-  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-      GL_CLAMP_TO_EDGE);
-  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-      GL_CLAMP_TO_EDGE);
-
-  //attach the texture to the FBO to renderer to
-  glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-      GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0);
-
-  //attach the depth render buffer to the FBO
-  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
-      GL_RENDERBUFFER_EXT, display->generated_depth_buffer);
-
-#ifndef OPENGL_ES2
-  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
-      GL_RENDERBUFFER_EXT, display->generated_depth_buffer);
-#endif
-
-  if (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) !=
-      GL_FRAMEBUFFER_COMPLETE_EXT)
-    gst_gl_display_set_error (display, "GL framebuffer status incomplete");
-
-  //unbind the FBO
-  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
-
-  glDeleteTextures (1, &fake_texture);
-}
-
-
-/* Called in the gl thread */
-void
-gst_gl_display_thread_use_fbo (GstGLDisplay * display)
-{
-#ifdef OPENGL_ES2
-  GLint viewport_dim[4];
-#endif
-
-  GST_TRACE ("Binding v1 FBO %u dimensions:%ux%u with texture:%u "
-      "dimensions:%ux%u", display->use_fbo, display->use_fbo_width,
-      display->use_fbo_height, display->use_fbo_texture,
-      display->input_texture_width, display->input_texture_height);
-
-  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->use_fbo);
-
-  //setup a texture to render to
-  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture);
-
-  //attach the texture to the FBO to renderer to
-  glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-      GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture, 0);
+  //attach the texture to the FBO to renderer to
+  glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+      GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture, 0);
 
   if (GLEW_ARB_fragment_shader)
     gst_gl_shader_use (NULL);
@@ -1875,20 +752,6 @@ gst_gl_display_thread_del_shader (GstGLDisplay * display)
 
 
 void
-gst_gl_display_lock (GstGLDisplay * display)
-{
-  g_mutex_lock (display->mutex);
-}
-
-
-void
-gst_gl_display_unlock (GstGLDisplay * display)
-{
-  g_mutex_unlock (display->mutex);
-}
-
-
-void
 gst_gl_display_on_resize (GstGLDisplay * display, gint width, gint height)
 {
   GST_TRACE ("GL Window resized to %ux%u", width, height);
@@ -1938,7 +801,7 @@ gst_gl_display_on_draw (GstGLDisplay * display)
   GST_TRACE ("on draw");
 
   //make sure that the environnement is clean
-  if (display->upload_colorspace_conversion == GST_GL_DISPLAY_CONVERSION_GLSL)
+  if (display->colorspace_conversion == GST_GL_DISPLAY_CONVERSION_GLSL)
     glUseProgramObjectARB (0);
 
 #ifndef OPENGL_ES2
@@ -2076,13 +939,13 @@ gst_gl_display_gen_texture_thread (GstGLDisplay * display, GLuint * pTexture,
       break;
     case GST_VIDEO_FORMAT_YUY2:
     case GST_VIDEO_FORMAT_UYVY:
-      switch (display->upload_colorspace_conversion) {
+      switch (display->colorspace_conversion) {
         case GST_GL_DISPLAY_CONVERSION_GLSL:
         case GST_GL_DISPLAY_CONVERSION_MATRIX:
           glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
               width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
           break;
-        case GST_GL_DISPLAY_CONVERSION_MESA:
+/*        case GST_GL_DISPLAY_CONVERSION_MESA:
           if (display->upload_width != display->upload_data_width ||
               display->upload_height != display->upload_data_height)
             glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
@@ -2090,10 +953,10 @@ gst_gl_display_gen_texture_thread (GstGLDisplay * display, GLuint * pTexture,
           else
             glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width,
                 height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL);
-          break;
+          break;*/
         default:
           gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
-              display->upload_colorspace_conversion);
+              display->colorspace_conversion);
       }
       break;
     case GST_VIDEO_FORMAT_I420:
@@ -2103,8 +966,9 @@ gst_gl_display_gen_texture_thread (GstGLDisplay * display, GLuint * pTexture,
           width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
       break;
     default:
-      gst_gl_display_set_error (display, "Unsupported upload video format %d",
-          display->upload_video_format);
+//      gst_gl_display_set_error (display, "Unsupported upload video format %d",
+//          display->upload_video_format);
+      break;
   }
 
   glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -2123,6 +987,29 @@ gst_gl_display_del_texture_thread (GstGLDisplay * display, GLuint * pTexture)
   glDeleteTextures (1, pTexture);
 }
 
+
+//------------------------------------------------------------
+//---------------------  END PRIVATE -------------------------
+//------------------------------------------------------------
+
+
+//------------------------------------------------------------
+//---------------------- BEGIN PUBLIC ------------------------
+//------------------------------------------------------------
+
+void
+gst_gl_display_lock (GstGLDisplay * display)
+{
+  g_mutex_lock (display->mutex);
+}
+
+
+void
+gst_gl_display_unlock (GstGLDisplay * display)
+{
+  g_mutex_unlock (display->mutex);
+}
+
 /* called in the gl thread */
 void
 gst_gl_display_check_framebuffer_status (void)
@@ -2157,17 +1044,6 @@ gst_gl_display_check_framebuffer_status (void)
   }
 }
 
-
-//------------------------------------------------------------
-//---------------------  END PRIVATE -------------------------
-//------------------------------------------------------------
-
-
-//------------------------------------------------------------
-//---------------------- BEGIN PUBLIC ------------------------
-//------------------------------------------------------------
-
-
 /* Called by the first gl element of a video/x-raw-gl flow */
 GstGLDisplay *
 gst_gl_display_new (void)
@@ -2283,95 +1159,7 @@ gst_gl_display_del_texture (GstGLDisplay * display, GLuint * pTexture)
   gst_gl_display_unlock (display);
 }
 
-
-/* Called by the first gl element of a video/x-raw-gl flow */
-gboolean
-gst_gl_display_init_upload (GstGLDisplay * display, GstVideoFormat video_format,
-    guint gl_width, guint gl_height, gint video_width, gint video_height)
-{
-  gboolean isAlive = FALSE;
-
-  gst_gl_display_lock (display);
-  display->upload_video_format = video_format;
-  display->upload_width = gl_width;
-  display->upload_height = gl_height;
-  display->upload_data_width = video_width;
-  display->upload_data_height = video_height;
-  gst_gl_window_send_message (display->gl_window,
-      GST_GL_WINDOW_CB (gst_gl_display_thread_init_upload), display);
-  isAlive = display->isAlive;
-  gst_gl_display_unlock (display);
-
-  return isAlive;
-}
-
-
-/* Called by the first gl element of a video/x-raw-gl flow */
-gboolean
-gst_gl_display_do_upload (GstGLDisplay * display, GLuint texture,
-    GstVideoFrame * frame)
-{
-  gboolean isAlive = TRUE;
-
-  gst_gl_display_lock (display);
-  isAlive = display->isAlive;
-  if (isAlive) {
-    display->upload_outtex = texture;
-    display->upload_frame = frame;
-    gst_gl_window_send_message (display->gl_window,
-        GST_GL_WINDOW_CB (gst_gl_display_thread_do_upload), display);
-    isAlive = display->isAlive;
-  }
-  gst_gl_display_unlock (display);
-
-  return isAlive;
-}
-
-
-/* Called by the gldownload and glcolorscale element */
-gboolean
-gst_gl_display_init_download (GstGLDisplay * display,
-    GstVideoFormat video_format, gint width, gint height)
-{
-  gboolean isAlive = FALSE;
-
-  gst_gl_display_lock (display);
-  display->download_video_format = video_format;
-  display->download_width = width;
-  display->download_height = height;
-  gst_gl_window_send_message (display->gl_window,
-      GST_GL_WINDOW_CB (gst_gl_display_thread_init_download), display);
-  isAlive = display->isAlive;
-  gst_gl_display_unlock (display);
-
-  return isAlive;
-}
-
-
-/* Called by the gldownload and glcolorscale element */
-gboolean
-gst_gl_display_do_download (GstGLDisplay * display, GLuint texture,
-    GstVideoFrame * frame)
-{
-  gboolean isAlive = TRUE;
-
-  gst_gl_display_lock (display);
-  isAlive = display->isAlive;
-  if (isAlive) {
-    //data size is aocciated to the glcontext size
-    display->download_frame = frame;
-    display->ouput_texture = texture;
-    gst_gl_window_send_message (display->gl_window,
-        GST_GL_WINDOW_CB (gst_gl_display_thread_do_download), display);
-    isAlive = display->isAlive;
-  }
-  gst_gl_display_unlock (display);
-
-  return isAlive;
-}
-
-
-/* Called by gltestsrc and glfilter */
+/* Called by gltestsrc and glfilter */
 gboolean
 gst_gl_display_gen_fbo (GstGLDisplay * display, gint width, gint height,
     GLuint * fbo, GLuint * depthbuffer)
@@ -2573,1056 +1361,6 @@ gst_gl_display_activate_gl_context (GstGLDisplay * display, gboolean activate)
     gst_gl_display_unlock (display);
 }
 
-
 //------------------------------------------------------------
 //------------------------ END PUBLIC ------------------------
 //------------------------------------------------------------
-
-/* called by gst_gl_display_thread_init_upload (in the gl thread) */
-void
-gst_gl_display_thread_init_upload_fbo (GstGLDisplay * display)
-{
-  //Frame buffer object is a requirement for every cases
-  if (GLEW_EXT_framebuffer_object) {
-    //a texture must be attached to the FBO
-    GLuint fake_texture = 0;
-
-    GST_INFO ("Context, EXT_framebuffer_object supported: yes");
-
-    //-- init intput frame buffer object (video -> GL)
-
-    //setup FBO
-    glGenFramebuffersEXT (1, &display->upload_fbo);
-    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->upload_fbo);
-
-    //setup the render buffer for depth
-    glGenRenderbuffersEXT (1, &display->upload_depth_buffer);
-    glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, display->upload_depth_buffer);
-#ifndef OPENGL_ES2
-    glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
-        display->upload_width, display->upload_height);
-    glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
-        display->upload_width, display->upload_height);
-#else
-    glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
-        display->upload_width, display->upload_height);
-#endif
-
-    //a fake texture is attached to the upload FBO (cannot init without it)
-    glGenTextures (1, &fake_texture);
-    glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fake_texture);
-    glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
-        display->upload_width, display->upload_height, 0, GL_RGBA,
-        GL_UNSIGNED_BYTE, NULL);
-    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-        GL_LINEAR);
-    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-        GL_LINEAR);
-    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-        GL_CLAMP_TO_EDGE);
-    glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-        GL_CLAMP_TO_EDGE);
-
-    //attach the texture to the FBO to renderer to
-    glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-        GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0);
-
-    //attach the depth render buffer to the FBO
-    glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
-        GL_RENDERBUFFER_EXT, display->upload_depth_buffer);
-
-#ifndef OPENGL_ES2
-    glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
-        GL_RENDERBUFFER_EXT, display->upload_depth_buffer);
-#endif
-
-    gst_gl_display_check_framebuffer_status ();
-
-    if (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) !=
-        GL_FRAMEBUFFER_COMPLETE_EXT)
-      gst_gl_display_set_error (display, "GL framebuffer status incomplete");
-
-    //unbind the FBO
-    glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
-
-    glDeleteTextures (1, &fake_texture);
-
-    //alloc texture (related to upload) memory only on time
-    gst_gl_display_thread_do_upload_make (display);
-  } else {
-    //turn off the pipeline because Frame buffer object is a not present
-    gst_gl_display_set_error (display,
-        "Context, EXT_framebuffer_object supported: no");
-  }
-}
-
-/* called by gst_gl_display_thread_do_upload (in the gl thread) */
-void
-gst_gl_display_thread_do_upload_make (GstGLDisplay * display)
-{
-  gint width = display->upload_data_width;
-  gint height = display->upload_data_height;
-
-  glGenTextures (1, &display->upload_intex);
-
-  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex);
-  switch (display->upload_video_format) {
-    case GST_VIDEO_FORMAT_RGBx:
-    case GST_VIDEO_FORMAT_BGRx:
-    case GST_VIDEO_FORMAT_xRGB:
-    case GST_VIDEO_FORMAT_xBGR:
-    case GST_VIDEO_FORMAT_RGBA:
-    case GST_VIDEO_FORMAT_BGRA:
-    case GST_VIDEO_FORMAT_ARGB:
-    case GST_VIDEO_FORMAT_ABGR:
-      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
-          width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
-      break;
-    case GST_VIDEO_FORMAT_RGB:
-    case GST_VIDEO_FORMAT_BGR:
-      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
-          width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
-      break;
-    case GST_VIDEO_FORMAT_AYUV:
-      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
-          width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, NULL);
-      break;
-    case GST_VIDEO_FORMAT_YUY2:
-      switch (display->upload_colorspace_conversion) {
-        case GST_GL_DISPLAY_CONVERSION_GLSL:
-        case GST_GL_DISPLAY_CONVERSION_MATRIX:
-          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA,
-              width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
-          glGenTextures (1, &display->upload_intex_u);
-          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex_u);
-          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
-              width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
-          break;
-        case GST_GL_DISPLAY_CONVERSION_MESA:
-          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width,
-              height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL);
-          break;
-        default:
-          gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
-              display->upload_colorspace_conversion);
-      }
-      break;
-    case GST_VIDEO_FORMAT_UYVY:
-      switch (display->upload_colorspace_conversion) {
-        case GST_GL_DISPLAY_CONVERSION_GLSL:
-        case GST_GL_DISPLAY_CONVERSION_MATRIX:
-          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA,
-              width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
-          glGenTextures (1, &display->upload_intex_u);
-          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex_u);
-          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
-              width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
-          break;
-        case GST_GL_DISPLAY_CONVERSION_MESA:
-          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width,
-              height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL);
-          break;
-        default:
-          gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
-              display->upload_colorspace_conversion);
-      }
-      break;
-    case GST_VIDEO_FORMAT_I420:
-    case GST_VIDEO_FORMAT_YV12:
-      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
-          width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
-
-      glGenTextures (1, &display->upload_intex_u);
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex_u);
-      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
-          GST_ROUND_UP_2 (width) / 2,
-          GST_ROUND_UP_2 (height) / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
-
-      glGenTextures (1, &display->upload_intex_v);
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex_v);
-      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
-          GST_ROUND_UP_2 (width) / 2,
-          GST_ROUND_UP_2 (height) / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
-      break;
-
-    default:
-      gst_gl_display_set_error (display, "Unsupported upload video format %d",
-          display->upload_video_format);
-  }
-}
-
-
-/* called by gst_gl_display_thread_do_upload (in the gl thread) */
-void
-gst_gl_display_thread_do_upload_fill (GstGLDisplay * display)
-{
-  GstVideoInfo vinfo;
-  gint width, height;
-  GstVideoFrame *frame;
-
-  frame = display->upload_frame;
-  vinfo = frame->info;
-  width = GST_VIDEO_INFO_WIDTH (&vinfo);
-  height = GST_VIDEO_INFO_HEIGHT (&vinfo);
-
-  switch (display->upload_video_format) {
-    case GST_VIDEO_FORMAT_RGB:
-    case GST_VIDEO_FORMAT_BGR:
-    case GST_VIDEO_FORMAT_RGBx:
-    case GST_VIDEO_FORMAT_BGRx:
-    case GST_VIDEO_FORMAT_xRGB:
-    case GST_VIDEO_FORMAT_xBGR:
-    case GST_VIDEO_FORMAT_RGBA:
-    case GST_VIDEO_FORMAT_BGRA:
-    case GST_VIDEO_FORMAT_ARGB:
-    case GST_VIDEO_FORMAT_ABGR:
-      //color space conversion is not needed
-      if (display->upload_width != display->upload_data_width ||
-          display->upload_height != display->upload_data_height)
-        glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex);
-      else
-        glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_outtex);
-      break;
-    case GST_VIDEO_FORMAT_YUY2:
-    case GST_VIDEO_FORMAT_UYVY:
-    case GST_VIDEO_FORMAT_I420:
-    case GST_VIDEO_FORMAT_YV12:
-    case GST_VIDEO_FORMAT_AYUV:
-      switch (display->upload_colorspace_conversion) {
-        case GST_GL_DISPLAY_CONVERSION_GLSL:
-        case GST_GL_DISPLAY_CONVERSION_MATRIX:
-          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex);
-          break;
-        case GST_GL_DISPLAY_CONVERSION_MESA:
-          if (display->upload_width != display->upload_data_width ||
-              display->upload_height != display->upload_data_height)
-            glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex);
-          else
-            glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_outtex);
-          break;
-        default:
-          gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
-              display->upload_colorspace_conversion);
-      }
-      break;
-    default:
-      gst_gl_display_set_error (display, "Unsupported upload video format %d",
-          display->upload_video_format);
-  }
-
-  switch (display->upload_video_format) {
-    case GST_VIDEO_FORMAT_RGB:
-      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
-          GL_RGB, GL_UNSIGNED_BYTE, frame->data[0]);
-      break;
-    case GST_VIDEO_FORMAT_BGR:
-      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
-          GL_BGR, GL_UNSIGNED_BYTE, frame->data[0]);
-      break;
-    case GST_VIDEO_FORMAT_RGBx:
-    case GST_VIDEO_FORMAT_RGBA:
-      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
-          GL_RGBA, GL_UNSIGNED_BYTE, frame->data[0]);
-      break;
-    case GST_VIDEO_FORMAT_BGRx:
-    case GST_VIDEO_FORMAT_BGRA:
-      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
-          GL_BGRA, GL_UNSIGNED_BYTE, frame->data[0]);
-      break;
-    case GST_VIDEO_FORMAT_AYUV:
-    case GST_VIDEO_FORMAT_xRGB:
-    case GST_VIDEO_FORMAT_ARGB:
-      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
-          GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, frame->data[0]);
-      break;
-    case GST_VIDEO_FORMAT_xBGR:
-    case GST_VIDEO_FORMAT_ABGR:
-      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
-          GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, frame->data[0]);
-      break;
-    case GST_VIDEO_FORMAT_YUY2:
-      switch (display->upload_colorspace_conversion) {
-        case GST_GL_DISPLAY_CONVERSION_GLSL:
-        case GST_GL_DISPLAY_CONVERSION_MATRIX:
-          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
-              GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, frame->data[0]);
-
-          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex_u);
-          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
-              GST_ROUND_UP_2 (width) / 2, height,
-              GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, frame->data[0]);
-          break;
-        case GST_GL_DISPLAY_CONVERSION_MESA:
-          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
-              GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, frame->data[0]);
-          break;
-        default:
-          gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
-              display->upload_colorspace_conversion);
-      }
-      break;
-    case GST_VIDEO_FORMAT_UYVY:
-      switch (display->upload_colorspace_conversion) {
-        case GST_GL_DISPLAY_CONVERSION_GLSL:
-        case GST_GL_DISPLAY_CONVERSION_MATRIX:
-          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
-              GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, frame->data[0]);
-
-          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex_u);
-          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
-              GST_ROUND_UP_2 (width) / 2, height,
-              GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, frame->data[0]);
-          break;
-        case GST_GL_DISPLAY_CONVERSION_MESA:
-          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
-              GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, frame->data[0]);
-          break;
-        default:
-          gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
-              display->upload_colorspace_conversion);
-      }
-      break;
-    case GST_VIDEO_FORMAT_I420:
-    case GST_VIDEO_FORMAT_YV12:
-    {
-      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
-          GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[0]);
-
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex_u);
-      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
-          GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
-          GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[1]);
-
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex_v);
-      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
-          GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
-          GL_LUMINANCE, GL_UNSIGNED_BYTE, frame->data[2]);
-    }
-      break;
-    default:
-      gst_gl_display_set_error (display, "Unsupported upload video format %d",
-          display->upload_video_format);
-  }
-
-  //make sure no texture is in use in our opengl context
-  //in case we want to use the upload texture in an other opengl context
-  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0);
-}
-
-
-/* called by gst_gl_display_thread_do_upload (in the gl thread) */
-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
-#ifndef OPENGL_ES2
-  glEnable (GL_TEXTURE_RECTANGLE_ARB);
-#endif
-  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_outtex);
-
-  //attach the texture to the FBO to renderer to
-  glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-      GL_TEXTURE_RECTANGLE_ARB, display->upload_outtex, 0);
-
-  if (GLEW_ARB_fragment_shader)
-    gst_gl_shader_use (NULL);
-
-#ifndef OPENGL_ES2
-  glPushAttrib (GL_VIEWPORT_BIT);
-
-  glMatrixMode (GL_PROJECTION);
-  glPushMatrix ();
-  glLoadIdentity ();
-  gluOrtho2D (0.0, display->upload_width, 0.0, display->upload_height);
-
-  glMatrixMode (GL_MODELVIEW);
-  glPushMatrix ();
-  glLoadIdentity ();
-#else // OPENGL_ES2
-  glGetIntegerv (GL_VIEWPORT, viewport_dim);
-#endif
-
-  glViewport (0, 0, display->upload_width, display->upload_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);
-
-  switch (display->upload_video_format) {
-    case GST_VIDEO_FORMAT_RGBx:
-    case GST_VIDEO_FORMAT_BGRx:
-    case GST_VIDEO_FORMAT_xRGB:
-    case GST_VIDEO_FORMAT_xBGR:
-    case GST_VIDEO_FORMAT_RGBA:
-    case GST_VIDEO_FORMAT_BGRA:
-    case GST_VIDEO_FORMAT_ARGB:
-    case GST_VIDEO_FORMAT_ABGR:
-    case GST_VIDEO_FORMAT_RGB:
-    case GST_VIDEO_FORMAT_BGR:
-    {
-#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
-
-#ifndef OPENGL_ES2
-      glEnable (GL_TEXTURE_RECTANGLE_ARB);
-#endif
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-          GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-          GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-          GL_CLAMP_TO_EDGE);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-          GL_CLAMP_TO_EDGE);
-#ifndef OPENGL_ES2
-      glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-#endif
-    }
-      break;
-
-    case GST_VIDEO_FORMAT_YUY2:
-    case GST_VIDEO_FORMAT_UYVY:
-    {
-      switch (display->upload_colorspace_conversion) {
-        case GST_GL_DISPLAY_CONVERSION_GLSL:
-        case GST_GL_DISPLAY_CONVERSION_MATRIX:
-        {
-          GstGLShader *shader_upload_YUY2_UYVY = NULL;
-
-          switch (display->upload_video_format) {
-            case GST_VIDEO_FORMAT_YUY2:
-              shader_upload_YUY2_UYVY = display->shader_upload_YUY2;
-              break;
-            case GST_VIDEO_FORMAT_UYVY:
-              shader_upload_YUY2_UYVY = display->shader_upload_UYVY;
-              break;
-            default:
-              gst_gl_display_set_error (display,
-                  "Upload video format inconsistency %d",
-                  display->upload_video_format);
-          }
-
-          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);
-          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex_u);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-              GL_LINEAR);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-              GL_LINEAR);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-              GL_CLAMP_TO_EDGE);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-              GL_CLAMP_TO_EDGE);
-
-          glActiveTextureARB (GL_TEXTURE0_ARB);
-          gst_gl_shader_set_uniform_1i (shader_upload_YUY2_UYVY, "Ytex", 0);
-          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-              GL_LINEAR);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-              GL_LINEAR);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-              GL_CLAMP_TO_EDGE);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-              GL_CLAMP_TO_EDGE);
-        }
-          break;
-        case GST_GL_DISPLAY_CONVERSION_MESA:
-        {
-
-#ifndef OPENGL_ES2
-          glMatrixMode (GL_PROJECTION);
-          glLoadIdentity ();
-          glEnable (GL_TEXTURE_RECTANGLE_ARB);
-#endif
-          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-              GL_LINEAR);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-              GL_LINEAR);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-              GL_CLAMP_TO_EDGE);
-          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-              GL_CLAMP_TO_EDGE);
-#ifndef OPENGL_ES2
-          glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
-#endif
-        }
-          break;
-        default:
-          gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
-              display->upload_colorspace_conversion);
-      }
-    }
-      break;
-
-    case GST_VIDEO_FORMAT_I420:
-    case GST_VIDEO_FORMAT_YV12:
-    {
-      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",
-          1);
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex_u);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-          GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-          GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-          GL_CLAMP_TO_EDGE);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-          GL_CLAMP_TO_EDGE);
-
-      glActiveTextureARB (GL_TEXTURE2_ARB);
-      gst_gl_shader_set_uniform_1i (display->shader_upload_I420_YV12, "Vtex",
-          2);
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex_v);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-          GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-          GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-          GL_CLAMP_TO_EDGE);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-          GL_CLAMP_TO_EDGE);
-
-      glActiveTextureARB (GL_TEXTURE0_ARB);
-      gst_gl_shader_set_uniform_1i (display->shader_upload_I420_YV12, "Ytex",
-          0);
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-          GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-          GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-          GL_CLAMP_TO_EDGE);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-          GL_CLAMP_TO_EDGE);
-    }
-      break;
-
-    case GST_VIDEO_FORMAT_AYUV:
-    {
-      gst_gl_shader_use (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);
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->upload_intex);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
-          GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
-          GL_LINEAR);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
-          GL_CLAMP_TO_EDGE);
-      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
-          GL_CLAMP_TO_EDGE);
-    }
-      break;
-
-    default:
-      GST_ERROR ("Unsupported upload video format %d",
-          display->upload_video_format);
-
-  }                             //end switch display->currentVideo_format
-
-#ifndef OPENGL_ES2
-  glBegin (GL_QUADS);
-  glTexCoord2i (display->upload_data_width, 0);
-  glVertex2f (1.0f, -1.0f);
-  glTexCoord2i (0, 0);
-  glVertex2f (-1.0f, -1.0f);
-  glTexCoord2i (0, display->upload_data_height);
-  glVertex2f (-1.0f, 1.0f);
-  glTexCoord2i (display->upload_data_width, display->upload_data_height);
-  glVertex2f (1.0f, 1.0f);
-  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);
-  glPopMatrix ();
-  glMatrixMode (GL_MODELVIEW);
-  glPopMatrix ();
-  glPopAttrib ();
-#else
-  glViewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
-      viewport_dim[3]);
-#endif
-
-  gst_gl_display_check_framebuffer_status ();
-
-  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
-}
-
-
-/* called by gst_gl_display_thread_do_download (in the gl thread) */
-void
-gst_gl_display_thread_do_download_draw_rgb (GstGLDisplay * display)
-{
-  GstVideoFormat video_format = display->download_video_format;
-  GstVideoFrame *frame = display->download_frame;
-
-#ifndef OPENGL_ES2
-  if (display->upload_colorspace_conversion == GST_GL_DISPLAY_CONVERSION_GLSL)
-    glUseProgramObjectARB (0);
-  glEnable (GL_TEXTURE_RECTANGLE_ARB);
-  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->ouput_texture);
-#else
-  gint width = GST_VIDEO_INFO_WIDTH (&frame->info);
-  gint height = GST_VIDEO_INFO_HEIGHT (&frame->info);
-
-  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);
-#endif
-
-  switch (video_format) {
-    case GST_VIDEO_FORMAT_RGBA:
-    case GST_VIDEO_FORMAT_RGBx:
-#ifndef OPENGL_ES2
-      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
-          GL_UNSIGNED_BYTE, frame->data[0]);
-#else
-      glReadPixels (0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
-          frame->data[0]);
-#endif
-      break;
-    case GST_VIDEO_FORMAT_xRGB:
-    case GST_VIDEO_FORMAT_ARGB:
-#ifndef OPENGL_ES2
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
-          GL_UNSIGNED_INT_8_8_8_8, frame->data[0]);
-#else
-      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
-          GL_UNSIGNED_INT_8_8_8_8_REV, frame->data[0]);
-#endif /* G_BYTE_ORDER */
-#else /* OPENGL_ES2 */
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-      glReadPixels (0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8,
-          frame->data[0]);
-#else
-      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
-          GL_UNSIGNED_INT_8_8_8_8_REV, frame->data[0]);
-#endif /* G_BYTE_ORDER */
-#endif /* !OPENGL_ES2 */
-      break;
-    case GST_VIDEO_FORMAT_BGRx:
-    case GST_VIDEO_FORMAT_BGRA:
-#ifndef OPENGL_ES2
-      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
-          GL_UNSIGNED_BYTE, frame->data[0]);
-#endif
-      break;
-    case GST_VIDEO_FORMAT_xBGR:
-    case GST_VIDEO_FORMAT_ABGR:
-#ifndef OPENGL_ES2
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
-          GL_UNSIGNED_INT_8_8_8_8, frame->data[0]);
-#else
-      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
-          GL_UNSIGNED_INT_8_8_8_8_REV, frame->data[0]);
-#endif /* G_BYTE_ORDER */
-#endif /* !OPENGL_ES2 */
-      break;
-    case GST_VIDEO_FORMAT_RGB:
-#ifndef OPENGL_ES2
-      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
-          GL_UNSIGNED_BYTE, frame->data[0]);
-#else
-      glReadPixels (0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE,
-          frame->data[0]);
-#endif
-      break;
-    case GST_VIDEO_FORMAT_BGR:
-#ifndef OPENGL_ES2
-      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGR,
-          GL_UNSIGNED_BYTE, frame->data[0]);
-#endif
-      break;
-    default:
-      gst_gl_display_set_error (display,
-          "Download video format inconsistency %d", video_format);
-  }
-
-#ifndef OPENGL_ES2
-  glReadBuffer (GL_NONE);
-  glDisable (GL_TEXTURE_RECTANGLE_ARB);
-#endif
-}
-
-
-/* called by gst_gl_display_thread_do_download (in the gl thread) */
-void
-gst_gl_display_thread_do_download_draw_yuv (GstGLDisplay * display)
-{
-  gint width, height;
-  GstVideoFormat video_format;
-  GstVideoInfo vinfo;
-  GstVideoFrame *frame;
-
-#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
-
-  frame = display->download_frame;
-  vinfo = frame->info;
-  width = GST_VIDEO_INFO_WIDTH (&vinfo);
-  height = GST_VIDEO_INFO_HEIGHT (&vinfo);
-  video_format = GST_VIDEO_INFO_FORMAT (&vinfo);
-
-  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->download_fbo);
-
-#ifndef OPENGL_ES2
-  glPushAttrib (GL_VIEWPORT_BIT);
-
-  glMatrixMode (GL_PROJECTION);
-  glPushMatrix ();
-  glLoadIdentity ();
-  gluOrtho2D (0.0, width, 0.0, height);
-
-  glMatrixMode (GL_MODELVIEW);
-  glPushMatrix ();
-  glLoadIdentity ();
-#else // OPENGL_ES2
-  glGetIntegerv (GL_VIEWPORT, viewport_dim);
-#endif
-
-  glViewport (0, 0, width, height);
-
-  switch (video_format) {
-    case GST_VIDEO_FORMAT_YUY2:
-    case GST_VIDEO_FORMAT_UYVY:
-    {
-      GstGLShader *shader_download_YUY2_UYVY = NULL;
-
-      switch (video_format) {
-        case GST_VIDEO_FORMAT_YUY2:
-          shader_download_YUY2_UYVY = display->shader_download_YUY2;
-          break;
-        case GST_VIDEO_FORMAT_UYVY:
-          shader_download_YUY2_UYVY = display->shader_download_UYVY;
-          break;
-        default:
-          gst_gl_display_set_error (display,
-              "Download video format inconsistensy %d", video_format);
-      }
-#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);
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->ouput_texture);
-    }
-      break;
-
-    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",
-          0);
-      gst_gl_shader_set_uniform_1f (display->shader_download_I420_YV12, "w",
-          (gfloat) display->ouput_texture_width);
-      gst_gl_shader_set_uniform_1f (display->shader_download_I420_YV12, "h",
-          (gfloat) display->ouput_texture_height);
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->ouput_texture);
-    }
-      break;
-
-    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);
-      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->ouput_texture);
-    }
-      break;
-
-    default:
-      gst_gl_display_set_error (display,
-          "Download video format inconsistensy %d", video_format);
-
-  }                             //end switch display->currentVideo_format
-
-#ifndef OPENGL_ES2
-  glBegin (GL_QUADS);
-  glTexCoord2i (0, 0);
-  glVertex2f (-1.0f, -1.0f);
-  glTexCoord2i (width, 0);
-  glVertex2f (1.0f, -1.0f);
-  glTexCoord2i (width, height);
-  glVertex2f (1.0f, 1.0f);
-  glTexCoord2i (0, height);
-  glVertex2f (-1.0f, 1.0f);
-  glEnd ();
-
-  glDrawBuffer (GL_NONE);
-#else //OPENGL_ES2
-  glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
-#endif
-
-  //dot not check if GLSL is available
-  //because download yuv is not available
-  //without GLSL (whereas rgb is)
-  glUseProgramObjectARB (0);
-
-#ifndef OPENGL_ES2
-  glDisable (GL_TEXTURE_RECTANGLE_ARB);
-  glMatrixMode (GL_PROJECTION);
-  glPopMatrix ();
-  glMatrixMode (GL_MODELVIEW);
-  glPopMatrix ();
-  glPopAttrib ();
-#else
-  glViewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
-      viewport_dim[3]);
-#endif
-
-  gst_gl_display_check_framebuffer_status ();
-
-  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
-
-  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->download_fbo);
-#ifndef OPENGL_ES2
-  glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
-#endif
-
-  switch (video_format) {
-    case GST_VIDEO_FORMAT_AYUV:
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-      glReadPixels (0, 0, width, height, GL_BGRA,
-          GL_UNSIGNED_INT_8_8_8_8, GST_VIDEO_FRAME_PLANE_DATA (frame, 0));
-#else
-      glReadPixels (0, 0, width, height, GL_BGRA,
-          GL_UNSIGNED_INT_8_8_8_8_REV, GST_VIDEO_FRAME_PLANE_DATA (frame, 0));
-#endif
-      break;
-    case GST_VIDEO_FORMAT_YUY2:
-    case GST_VIDEO_FORMAT_UYVY:
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-      glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2, height, GL_BGRA,
-          GL_UNSIGNED_INT_8_8_8_8_REV, frame->data[0]);
-#else
-      glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2, height, GL_BGRA,
-          GL_UNSIGNED_INT_8_8_8_8, frame->data[0]);
-#endif
-      break;
-    case GST_VIDEO_FORMAT_I420:
-    case GST_VIDEO_FORMAT_YV12:
-    {
-      glReadPixels (0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE,
-          GST_VIDEO_FRAME_COMP_DATA (frame, 0));
-
-#ifndef OPENGL_ES2
-      glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
-#endif
-
-      glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2,
-          GST_ROUND_UP_2 (height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
-          GST_VIDEO_FRAME_COMP_DATA (frame, 1));
-
-#ifndef OPENGL_ES2
-      glReadBuffer (GL_COLOR_ATTACHMENT2_EXT);
-#endif
-
-      glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2,
-          GST_ROUND_UP_2 (height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
-          GST_VIDEO_FRAME_COMP_DATA (frame, 2));
-    }
-      break;
-    default:
-      gst_gl_display_set_error (display,
-          "Download video format inconsistensy %d", video_format);
-  }
-#ifndef OPENGL_ES2
-  glReadBuffer (GL_NONE);
-#endif
-
-  gst_gl_display_check_framebuffer_status ();
-
-  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
-}
index 8f77e53..5103ede 100644 (file)
@@ -27,6 +27,8 @@
 
 #include "gstglwindow.h"
 #include "gstglshader.h"
+#include "gstglupload.h"
+#include "gstgldownload.h"
 
 G_BEGIN_DECLS
 
@@ -125,20 +127,10 @@ struct _GstGLDisplay
   CDCB clientDrawCallback;
   gpointer client_data;
 
-  //upload
-  GLuint upload_fbo;
-  GLuint upload_depth_buffer;
-  GLuint upload_outtex;
-  GLuint upload_intex;
-  GLuint upload_intex_u;
-  GLuint upload_intex_v;
-  GLuint upload_width;
-  GLuint upload_height;
-  GstVideoFormat upload_video_format;
-  GstGLDisplayConversion upload_colorspace_conversion;
-  gint upload_data_width;
-  gint upload_data_height;
-  GstVideoFrame *upload_frame;
+  GstGLDisplayConversion colorspace_conversion;
+
+  GHashTable *uploads;
+  GHashTable *downloads;
 
   //foreign gl context
   gulong external_gl_context;
@@ -171,21 +163,6 @@ struct _GstGLDisplay
   GLuint del_fbo;
   GLuint del_depth_buffer;
 
-  //download
-  GLuint download_fbo;
-  GLuint download_depth_buffer;
-  GLuint download_texture;
-  GLuint download_texture_u;
-  GLuint download_texture_v;
-  gint download_width;
-  gint download_height;
-  GstVideoFormat download_video_format;
-  GstVideoFrame *download_frame;
-  GLenum multipleRT[3];
-  GLuint ouput_texture;
-  GLuint ouput_texture_width;
-  GLuint ouput_texture_height;
-
   //action gen and del shader
   const gchar *gen_shader_fragment_source;
   const gchar *gen_shader_vertex_source;
@@ -209,25 +186,6 @@ struct _GstGLDisplay
   GLint shader_upload_attr_texture_loc;
 #endif
 
-  //fragement shader download
-  gchar *text_shader_download_YUY2_UYVY;
-  GstGLShader *shader_download_YUY2;
-  GstGLShader *shader_download_UYVY;
-
-  gchar *text_shader_download_I420_YV12;
-  GstGLShader *shader_download_I420_YV12;
-
-  gchar *text_shader_download_AYUV;
-  GstGLShader *shader_download_AYUV;
-
-#ifdef OPENGL_ES2
-  gchar *text_vertex_shader_download;
-  GLint shader_download_attr_position_loc;
-  GLint shader_download_attr_texture_loc;
-  gchar *text_fragment_shader_download_RGB;
-  GstGLShader *shader_download_RGB;
-#endif
-
   gchar *error_message;
 
 };
@@ -266,10 +224,6 @@ gboolean gst_gl_display_init_upload (GstGLDisplay * display,
     gint video_width, gint video_height);
 gboolean gst_gl_display_do_upload (GstGLDisplay * display, GLuint texture,
     GstVideoFrame * frame);
-gboolean gst_gl_display_init_download (GstGLDisplay * display,
-    GstVideoFormat video_format, gint width, gint height);
-gboolean gst_gl_display_do_download (GstGLDisplay * display, GLuint texture,
-    GstVideoFrame *frame);
 
 gboolean gst_gl_display_gen_fbo (GstGLDisplay * display, gint width, gint height,
     GLuint * fbo, GLuint * depthbuffer);
@@ -301,6 +255,10 @@ void gst_gl_display_activate_gl_context (GstGLDisplay * display, gboolean activa
 
 /* Must be called inside a lock/unlock on display, or within the glthread */
 void gst_gl_display_set_error (GstGLDisplay * display, const char * format, ...);
+void gst_gl_display_check_framebuffer_status (void);
+
+void gst_gl_display_lock (GstGLDisplay * display);
+void gst_gl_display_unlock (GstGLDisplay * display);
 
 G_END_DECLS
 
diff --git a/gst-libs/gst/gl/gstgldownload.c b/gst-libs/gst/gl/gstgldownload.c
new file mode 100644 (file)
index 0000000..3a66533
--- /dev/null
@@ -0,0 +1,1136 @@
+/*
+ * GStreamer
+ * Copyright (C) 2012 Matthew Waters <ystree00@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 <stdio.h>
+
+#include "gstgldownload.h"
+#include "gstglmemory.h"
+
+static void _do_download (GstGLDisplay * display, GstGLDownload * download);
+static void _do_download_draw_rgb (GstGLDisplay * display,
+    GstGLDownload * download);
+static void _do_download_draw_yuv (GstGLDisplay * display,
+    GstGLDownload * download);
+static void _init_download (GstGLDisplay * display, GstGLDownload * download);
+static void _init_download_shader (GstGLDisplay * display,
+    GstGLDownload * download);
+static gboolean gst_gl_download_perform_with_data_unlocked (GstGLDownload *
+    download, GLuint texture_id, gpointer data[GST_VIDEO_MAX_PLANES]);
+
+/* YUY2:y2,u,y1,v
+   UYVY:v,y1,u,y2 */
+static gchar *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"
+    "  g=texture2DRect(tex,vec2(fx*2.0,fy)).g;\n"
+    "  b=texture2DRect(tex,vec2(fx*2.0,fy)).b;\n"
+    "  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";
+
+/* no OpenGL ES 2.0 support because for now it's not possible
+ * to attach multiple textures to a frame buffer object
+ */
+static gchar *text_shader_download_I420_YV12 =
+    "#extension GL_ARB_texture_rectangle : enable\n"
+    "uniform sampler2DRect tex;\n"
+    "uniform float w, h;\n"
+    "void main(void) {\n"
+    "  float r,g,b,r2,b2,g2,y,u,v;\n"
+    "  vec2 nxy=gl_TexCoord[0].xy;\n"
+    "  vec2 nxy2=nxy*2.0;\n"
+    "  r=texture2DRect(tex,nxy).r;\n"
+    "  g=texture2DRect(tex,nxy).g;\n"
+    "  b=texture2DRect(tex,nxy).b;\n"
+    "  r2=texture2DRect(tex,nxy2).r;\n"
+    "  g2=texture2DRect(tex,nxy2).g;\n"
+    "  b2=texture2DRect(tex,nxy2).b;\n"
+    "  y=0.299011*r + 0.586987*g + 0.114001*b;\n"
+    "  u=-0.148246*r2 -0.29102*g2 + 0.439266*b2;\n"
+    "  v=0.439271*r2 - 0.367833*g2 - 0.071438*b2 ;\n"
+    "  y=0.858885*y + 0.0625;\n"
+    "  u=u + 0.5;\n"
+    "  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";
+
+static gchar *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"
+#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
+static gchar *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";
+
+static gchar *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
+
+GST_DEBUG_CATEGORY_STATIC (gst_gl_download_debug);
+#define GST_CAT_DEFAULT gst_gl_download_debug
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_gl_download_debug, "gldownload", 0, "download");
+
+G_DEFINE_TYPE_WITH_CODE (GstGLDownload, gst_gl_download, G_TYPE_OBJECT,
+    DEBUG_INIT);
+static void gst_gl_download_finalize (GObject * object);
+
+#define GST_GL_DOWNLOAD_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+    GST_TYPE_GL_DOWNLOAD, GstGLDownloadPrivate))
+
+static void
+gst_gl_download_class_init (GstGLDownloadClass * klass)
+{
+  G_OBJECT_CLASS (klass)->finalize = gst_gl_download_finalize;
+}
+
+static void
+gst_gl_download_init (GstGLDownload * download)
+{
+  download->display = NULL;
+
+  g_mutex_init (&download->lock);
+
+  download->fbo = 0;
+  download->depth_buffer = 0;
+  download->in_texture = 0;
+  download->shader = NULL;
+
+#ifdef OPENGL_ES2
+  download->shader_attr_position_loc = 0;
+  download->shader_attr_texture_loc = 0;
+#endif
+
+  gst_video_info_init (&download->info);
+}
+
+GstGLDownload *
+gst_gl_download_new (GstGLDisplay * display)
+{
+  GstGLDownload *download;
+
+  download = g_object_new (GST_TYPE_GL_DOWNLOAD, NULL);
+
+  download->display = g_object_ref (display);
+
+  return download;
+}
+
+static void
+gst_gl_download_finalize (GObject * object)
+{
+  GstGLDownload *download;
+  guint i;
+
+  download = GST_GL_DOWNLOAD (object);
+
+  for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
+    if (download->out_texture[i]) {
+      gst_gl_display_del_texture (download->display, &download->out_texture[i]);
+      download->out_texture[i] = 0;
+    }
+  }
+  if (download->in_texture) {
+    gst_gl_display_del_texture (download->display, &download->in_texture);
+    download->in_texture = 0;
+  }
+  if (download->fbo || download->depth_buffer) {
+    gst_gl_display_del_fbo (download->display, download->fbo,
+        download->depth_buffer);
+    download->fbo = 0;
+    download->depth_buffer = 0;
+  }
+  if (download->shader) {
+    g_object_unref (G_OBJECT (download->shader));
+    download->shader = NULL;
+  }
+
+  if (download->display) {
+    g_object_unref (G_OBJECT (download->display));
+    download->display = NULL;
+  }
+
+  g_mutex_clear (&download->lock);
+}
+
+gboolean
+gst_gl_download_init_format (GstGLDownload * download, GstVideoFormat v_format,
+    guint width, guint height)
+{
+  GstVideoInfo info;
+
+  g_return_val_if_fail (download != NULL, FALSE);
+  g_return_val_if_fail (v_format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
+  g_return_val_if_fail (v_format != GST_VIDEO_FORMAT_ENCODED, FALSE);
+  g_return_val_if_fail (width > 0 && height > 0, FALSE);
+
+  g_mutex_lock (&download->lock);
+
+  gst_video_info_set_format (&info, v_format, width, height);
+
+  download->info = info;
+
+  gst_gl_display_thread_add (download->display,
+      (GstGLDisplayThreadFunc) _init_download, download);
+
+  g_mutex_unlock (&download->lock);
+
+  return TRUE;
+}
+
+gboolean
+gst_gl_download_perform_with_memory (GstGLDownload * download,
+    GstGLMemory * gl_mem)
+{
+  gpointer data[GST_VIDEO_MAX_PLANES];
+  guint i;
+  gboolean ret;
+
+  g_return_val_if_fail (download != NULL, FALSE);
+
+  if (!GST_GL_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_MEMORY_FLAG_DOWNLOAD_INITTED))
+    return FALSE;
+
+  if (!GST_GL_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_DOWNLOAD)) {
+    return FALSE;
+  }
+
+  g_mutex_lock (&download->lock);
+
+  for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&download->info); i++) {
+    data[i] = (guint8 *) gl_mem->data +
+        GST_VIDEO_INFO_PLANE_OFFSET (&download->info, i);
+  }
+
+  ret =
+      gst_gl_download_perform_with_data_unlocked (download, gl_mem->tex_id,
+      data);
+
+  GST_GL_MEMORY_FLAG_UNSET (gl_mem, GST_GL_MEMORY_FLAG_NEED_DOWNLOAD);
+
+  g_mutex_unlock (&download->lock);
+
+  return ret;
+}
+
+gboolean
+gst_gl_download_perform_with_data (GstGLDownload * download, GLuint texture_id,
+    gpointer data[GST_VIDEO_MAX_PLANES])
+{
+  gboolean ret;
+
+  g_return_val_if_fail (download != NULL, FALSE);
+
+  g_mutex_lock (&download->lock);
+
+  ret = gst_gl_download_perform_with_data_unlocked (download, texture_id, data);
+
+  g_mutex_unlock (&download->lock);
+
+  return ret;
+}
+
+static gboolean
+gst_gl_download_perform_with_data_unlocked (GstGLDownload * download,
+    GLuint texture_id, gpointer data[GST_VIDEO_MAX_PLANES])
+{
+  guint i;
+
+  g_return_val_if_fail (download != NULL, FALSE);
+  g_return_val_if_fail (texture_id > 0, FALSE);
+  g_return_val_if_fail (GST_VIDEO_INFO_FORMAT (&download->info) !=
+      GST_VIDEO_FORMAT_UNKNOWN
+      && GST_VIDEO_INFO_FORMAT (&download->info) != GST_VIDEO_FORMAT_ENCODED,
+      FALSE);
+
+  for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&download->info); i++) {
+    g_return_val_if_fail (data[i] != NULL, FALSE);
+  }
+
+  download->in_texture = texture_id;
+  for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&download->info); i++) {
+    download->data[i] = data[i];
+  }
+
+  gst_gl_display_thread_add (download->display,
+      (GstGLDisplayThreadFunc) _do_download, download);
+
+  return TRUE;
+}
+
+GstGLDownload *
+gst_gl_display_find_download (GstGLDisplay * display, GstVideoFormat v_format,
+    guint width, guint height)
+{
+  GstGLDownload *ret;
+  guint64 *key;
+
+  /* this limits the width and the height to 2^29-1 = 536870911 */
+  key = g_malloc (sizeof (guint64 *));
+  *key = v_format | ((guint64) width << 6) | ((guint64) height << 35);
+
+  gst_gl_display_lock (display);
+
+  ret = g_hash_table_lookup (display->downloads, key);
+
+  if (!ret) {
+    ret = gst_gl_download_new (display);
+
+    g_hash_table_insert (display->downloads, key, ret);
+  }
+
+  gst_gl_display_unlock (display);
+
+  return ret;
+}
+
+static void
+_init_download (GstGLDisplay * display, GstGLDownload * download)
+{
+  GstVideoFormat v_format;
+  guint width, height;
+
+  width = GST_VIDEO_INFO_WIDTH (&download->info);
+  height = GST_VIDEO_INFO_HEIGHT (&download->info);
+  v_format = GST_VIDEO_INFO_FORMAT (&download->info);
+
+  GST_TRACE ("initializing texture download for format %d", v_format);
+
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_RGBx:
+    case GST_VIDEO_FORMAT_BGRx:
+    case GST_VIDEO_FORMAT_xRGB:
+    case GST_VIDEO_FORMAT_xBGR:
+    case GST_VIDEO_FORMAT_RGBA:
+    case GST_VIDEO_FORMAT_BGRA:
+    case GST_VIDEO_FORMAT_ARGB:
+    case GST_VIDEO_FORMAT_ABGR:
+    case GST_VIDEO_FORMAT_RGB:
+    case GST_VIDEO_FORMAT_BGR:
+      /* color space conversion is not needed */
+      break;
+    case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_UYVY:
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+    case GST_VIDEO_FORMAT_AYUV:
+      /* color space conversion is needed */
+    {
+
+      if (!GLEW_EXT_framebuffer_object) {
+        /* Frame buffer object is a requirement 
+         * when using GLSL colorspace conversion
+         */
+        gst_gl_display_set_error (display,
+            "Context, EXT_framebuffer_object supported: no");
+      }
+      GST_INFO ("Context, EXT_framebuffer_object supported: yes");
+
+      /* setup FBO */
+      if (!download->fbo && !download->depth_buffer) {
+        glGenFramebuffersEXT (1, &download->fbo);
+        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, download->fbo);
+
+        /* setup the render buffer for depth */
+        glGenRenderbuffersEXT (1, &download->depth_buffer);
+        glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, download->depth_buffer);
+#ifndef OPENGL_ES2
+        glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
+            width, height);
+        glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
+            width, height);
+#else
+        glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
+            width, height);
+#endif
+      }
+
+      /* setup a first texture to render to */
+      glGenTextures (1, &download->out_texture[0]);
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->out_texture[0]);
+      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+          width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+          GL_CLAMP_TO_EDGE);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+          GL_CLAMP_TO_EDGE);
+
+      /* attach the first texture to the FBO to renderer to */
+      glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+          GL_TEXTURE_RECTANGLE_ARB, download->out_texture[0], 0);
+
+      if (v_format == GST_VIDEO_FORMAT_I420 ||
+          v_format == GST_VIDEO_FORMAT_YV12) {
+        /* setup a second texture to render to */
+        glGenTextures (1, &download->out_texture[1]);
+        glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->out_texture[1]);
+        glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+            width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+            GL_LINEAR);
+        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+            GL_LINEAR);
+        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+            GL_CLAMP_TO_EDGE);
+        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+            GL_CLAMP_TO_EDGE);
+
+        /* attach the second texture to the FBO to renderer to */
+        glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
+            GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB,
+            download->out_texture[1], 0);
+
+        /* setup a third texture to render to */
+        glGenTextures (1, &download->out_texture[2]);
+        glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->out_texture[2]);
+        glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+            width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+            GL_LINEAR);
+        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+            GL_LINEAR);
+        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+            GL_CLAMP_TO_EDGE);
+        glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+            GL_CLAMP_TO_EDGE);
+
+        /* attach the third texture to the FBO to renderer to */
+        glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT,
+            GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_RECTANGLE_ARB,
+            download->out_texture[2], 0);
+      }
+
+      /* attach the depth render buffer to the FBO */
+      glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
+          GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, download->depth_buffer);
+
+#ifndef OPENGL_ES2
+      glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
+          GL_STENCIL_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT,
+          download->depth_buffer);
+#endif
+
+      gst_gl_display_check_framebuffer_status ();
+
+      if (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) !=
+          GL_FRAMEBUFFER_COMPLETE_EXT) {
+        gst_gl_display_set_error (display, "GL framebuffer status incomplete");
+      }
+
+      /* unbind the FBO */
+      glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
+    }
+      break;
+    default:
+      break;
+      gst_gl_display_set_error (display, "Unsupported download video format %d",
+          v_format);
+      g_assert_not_reached ();
+  }
+
+  _init_download_shader (display, download);
+}
+
+static void
+_init_download_shader (GstGLDisplay * display, GstGLDownload * download)
+{
+  GstVideoFormat v_format;
+
+  v_format = GST_VIDEO_INFO_FORMAT (&download->info);
+
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_RGBx:
+    case GST_VIDEO_FORMAT_BGRx:
+    case GST_VIDEO_FORMAT_xRGB:
+    case GST_VIDEO_FORMAT_xBGR:
+    case GST_VIDEO_FORMAT_RGBA:
+    case GST_VIDEO_FORMAT_BGRA:
+    case GST_VIDEO_FORMAT_ARGB:
+    case GST_VIDEO_FORMAT_ABGR:
+    case GST_VIDEO_FORMAT_RGB:
+    case GST_VIDEO_FORMAT_BGR:
+      /* color space conversion is not needed */
+#ifdef OPENGL_ES2
+    {
+      /* glGetTexImage2D not available in OpenGL ES 2.0 */
+      GError *error = NULL;
+      download->shader = gst_gl_shader_new ();
+
+      gst_gl_shader_set_vertex_source (download->shader,
+          text_vertex_shader_download);
+      gst_gl_shader_set_fragment_source (download->shader,
+          text_fragment_shader_download_RGB);
+
+      gst_gl_shader_compile (download->shader, &error);
+      if (error) {
+        gst_gl_display_set_error (download, "%s", error->message);
+        g_error_free (error);
+        error = NULL;
+        gst_gl_shader_use (NULL);
+        g_object_unref (G_OBJECT (download->shader));
+        download->shader = NULL;
+      } else {
+        download->shader_attr_position_loc =
+            gst_gl_shader_get_attribute_location (download->shader,
+            "a_position");
+        download->shader_attr_texture_loc =
+            gst_gl_shader_get_attribute_location (download->shader,
+            "a_texCoord");
+      }
+    }
+#endif
+      break;
+    case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_UYVY:
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+    case GST_VIDEO_FORMAT_AYUV:
+      /* color space conversion is needed */
+    {
+      /* check if fragment shader is available, then load them
+       * GLSL is a requirement for donwload
+       */
+      if (!GLEW_ARB_fragment_shader) {
+        /* colorspace conversion is not possible */
+        gst_gl_display_set_error (display,
+            "Context, ARB_fragment_shader supported: no");
+        return;
+      }
+#ifdef OPENGL_ES2
+      GError *error = NULL;
+#endif
+
+      switch (v_format) {
+        case GST_VIDEO_FORMAT_YUY2:
+        {
+          gchar text_shader_download_YUY2[2048];
+          sprintf (text_shader_download_YUY2,
+              text_shader_download_YUY2_UYVY, "y2,u,y1,v");
+
+          download->shader = gst_gl_shader_new ();
+#ifndef OPENGL_ES2
+          if (!gst_gl_shader_compile_and_check (download->shader,
+                  text_shader_download_YUY2, GST_GL_SHADER_FRAGMENT_SOURCE)) {
+            gst_gl_display_set_error (display,
+                "Failed to initialize shader for downloading YUY2");
+            g_object_unref (G_OBJECT (download->shader));
+            download->shader = NULL;
+          }
+#else
+          gst_gl_shader_set_vertex_source (download->shader,
+              text_vertex_shader_download);
+          gst_gl_shader_set_fragment_source (download->shader,
+              text_shader_download_YUY2);
+
+          gst_gl_shader_compile (download->shader, &error);
+          if (error) {
+            gst_gl_display_set_error (display, "%s", error->message);
+            g_error_free (error);
+            error = NULL;
+            gst_gl_shader_use (NULL);
+            g_object_unref (G_OBJECT (download->shader));
+            download->shader = NULL;
+          } else {
+            download->shader_attr_position_loc =
+                gst_gl_shader_get_attribute_location
+                (download->shader, "a_position");
+            download->shader_attr_texture_loc =
+                gst_gl_shader_get_attribute_location
+                (download->shader, "a_texCoord");
+          }
+#endif
+        }
+          break;
+        case GST_VIDEO_FORMAT_UYVY:
+        {
+          gchar text_shader_download_UYVY[2048];
+          sprintf (text_shader_download_UYVY,
+              text_shader_download_YUY2_UYVY, "v,y1,u,y2");
+
+          download->shader = gst_gl_shader_new ();
+
+#ifndef OPENGL_ES2
+          if (!gst_gl_shader_compile_and_check (download->shader,
+                  text_shader_download_UYVY, GST_GL_SHADER_FRAGMENT_SOURCE)) {
+            gst_gl_display_set_error (display,
+                "Failed to initialize shader for downloading UYVY");
+            g_object_unref (G_OBJECT (download->shader));
+            download->shader = NULL;
+          }
+#else
+          gst_gl_shader_set_vertex_source (download->shader,
+              text_vertex_shader_download);
+          gst_gl_shader_set_fragment_source (download->shader,
+              text_shader_download_UYVY);
+
+          gst_gl_shader_compile (download->shader, &error);
+          if (error) {
+            gst_gl_display_set_error (display, "%s", error->message);
+            g_error_free (error);
+            error = NULL;
+            gst_gl_shader_use (NULL);
+            g_object_unref (G_OBJECT (download->shader));
+            download->shader = NULL;
+          } else {
+            download->shader_attr_position_loc =
+                gst_gl_shader_get_attribute_location
+                (download->shader, "a_position");
+            download->shader_attr_texture_loc =
+                gst_gl_shader_get_attribute_location
+                (download->shader, "a_texCoord");
+          }
+#endif
+
+        }
+          break;
+        case GST_VIDEO_FORMAT_I420:
+        case GST_VIDEO_FORMAT_YV12:
+          download->shader = gst_gl_shader_new ();
+          if (!gst_gl_shader_compile_and_check (download->shader,
+                  text_shader_download_I420_YV12,
+                  GST_GL_SHADER_FRAGMENT_SOURCE)) {
+            gst_gl_display_set_error (display,
+                "Failed to initialize shader for downloading I420 or YV12");
+            g_object_unref (G_OBJECT (download->shader));
+            download->shader = NULL;
+          }
+          break;
+        case GST_VIDEO_FORMAT_AYUV:
+          download->shader = gst_gl_shader_new ();
+
+#ifndef OPENGL_ES2
+          if (!gst_gl_shader_compile_and_check (download->shader,
+                  text_shader_download_AYUV, GST_GL_SHADER_FRAGMENT_SOURCE)) {
+            gst_gl_display_set_error (display,
+                "Failed to initialize shader for downloading AYUV");
+            g_object_unref (G_OBJECT (download->shader));
+            download->shader = NULL;
+          }
+#else
+          gst_gl_shader_set_vertex_source (download->shader,
+              text_vertex_shader_download);
+          gst_gl_shader_set_fragment_source (download->shader,
+              text_shader_download_AYUV);
+
+          gst_gl_shader_compile (download->shader, &error);
+          if (error) {
+            gst_gl_display_set_error (display, "%s", error->message);
+            g_error_free (error);
+            error = NULL;
+            gst_gl_shader_use (NULL);
+            g_object_unref (G_OBJECT (download->shader));
+            download->shader = NULL;
+          } else {
+            download->shader_attr_position_loc =
+                gst_gl_shader_get_attribute_location
+                (download->shader, "a_position");
+            download->shader_attr_texture_loc =
+                gst_gl_shader_get_attribute_location
+                (download->shader, "a_texCoord");
+          }
+#endif
+          break;
+        default:
+          gst_gl_display_set_error (display,
+              "Unsupported download video format %d", v_format);
+          g_assert_not_reached ();
+          break;
+      }
+    }
+      break;
+    default:
+      gst_gl_display_set_error (display, "Unsupported download video format %d",
+          v_format);
+      g_assert_not_reached ();
+      break;
+  }
+}
+
+/* Called in the gl thread */
+static void
+_do_download (GstGLDisplay * display, GstGLDownload * download)
+{
+  GstVideoFormat v_format;
+  guint width, height;
+
+  width = GST_VIDEO_INFO_WIDTH (&download->info);
+  height = GST_VIDEO_INFO_HEIGHT (&download->info);
+  v_format = GST_VIDEO_INFO_FORMAT (&download->info);
+
+  GST_TRACE ("downloading texture:%u format:%d, dimensions:%ux%u",
+      download->in_texture, v_format, width, height);
+
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_RGBx:
+    case GST_VIDEO_FORMAT_BGRx:
+    case GST_VIDEO_FORMAT_xRGB:
+    case GST_VIDEO_FORMAT_xBGR:
+    case GST_VIDEO_FORMAT_RGBA:
+    case GST_VIDEO_FORMAT_BGRA:
+    case GST_VIDEO_FORMAT_ARGB:
+    case GST_VIDEO_FORMAT_ABGR:
+    case GST_VIDEO_FORMAT_RGB:
+    case GST_VIDEO_FORMAT_BGR:
+      /* color space conversion is not needed */
+      _do_download_draw_rgb (display, download);
+      break;
+    case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_UYVY:
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+    case GST_VIDEO_FORMAT_AYUV:
+      /* color space conversion is needed */
+      _do_download_draw_yuv (display, download);
+      break;
+    default:
+      gst_gl_display_set_error (display, "Unsupported download video format %d",
+          v_format);
+      g_assert_not_reached ();
+      break;
+  }
+}
+
+/* called by _do_download (in the gl thread) */
+static void
+_do_download_draw_rgb (GstGLDisplay * display, GstGLDownload * download)
+{
+  GstVideoFormat v_format;
+
+#ifndef OPENGL_ES2
+  if (download->display->colorspace_conversion ==
+      GST_GL_DISPLAY_CONVERSION_GLSL)
+    glUseProgramObjectARB (0);
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->in_texture);
+#else
+  guint width, height;
+
+  width = GST_VIDEO_INFO_WIDTH (&download->info);
+  height = GST_VIDEO_INFO_HEIGHT (&download->info);
+
+  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 (download->shader);
+
+  glVertexAttribPointer (download->shader_attr_position_loc, 3,
+      GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices);
+  glVertexAttribPointer (download->shader_attr_texture_loc, 2,
+      GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]);
+
+  glEnableVertexAttribArray (download->shader_attr_position_loc);
+  glEnableVertexAttribArray (download->shader_attr_texture_loc);
+
+  glActiveTextureARB (GL_TEXTURE0_ARB);
+  gst_gl_shader_set_uniform_1i (download->shader, "s_texture", 0);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->in_texture);
+
+  glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+
+  glUseProgramObjectARB (0);
+#endif
+
+  v_format = GST_VIDEO_INFO_FORMAT (&download->info);
+
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_RGBA:
+    case GST_VIDEO_FORMAT_RGBx:
+#ifndef OPENGL_ES2
+      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
+          GL_UNSIGNED_BYTE, download->data[0]);
+#else
+      glReadPixels (0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
+          download->data[0]);
+#endif
+      break;
+    case GST_VIDEO_FORMAT_xRGB:
+    case GST_VIDEO_FORMAT_ARGB:
+#ifndef OPENGL_ES2
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
+          GL_UNSIGNED_INT_8_8_8_8, download->data[0]);
+#else
+      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
+          GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]);
+#endif /* G_BYTE_ORDER */
+#else /* OPENGL_ES2 */
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+      glReadPixels (0, 0, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8,
+          download->data[0]);
+#else
+      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
+          GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]);
+#endif /* G_BYTE_ORDER */
+#endif /* !OPENGL_ES2 */
+      break;
+    case GST_VIDEO_FORMAT_BGRx:
+    case GST_VIDEO_FORMAT_BGRA:
+#ifndef OPENGL_ES2
+      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
+          GL_UNSIGNED_BYTE, download->data[0]);
+#endif
+      break;
+    case GST_VIDEO_FORMAT_xBGR:
+    case GST_VIDEO_FORMAT_ABGR:
+#ifndef OPENGL_ES2
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
+          GL_UNSIGNED_INT_8_8_8_8, download->data[0]);
+#else
+      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
+          GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]);
+#endif /* G_BYTE_ORDER */
+#endif /* !OPENGL_ES2 */
+      break;
+    case GST_VIDEO_FORMAT_RGB:
+#ifndef OPENGL_ES2
+      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
+          GL_UNSIGNED_BYTE, download->data[0]);
+#else
+      glReadPixels (0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE,
+          download->data[0]);
+#endif
+      break;
+    case GST_VIDEO_FORMAT_BGR:
+#ifndef OPENGL_ES2
+      glGetTexImage (GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGR,
+          GL_UNSIGNED_BYTE, download->data[0]);
+#endif
+      break;
+    default:
+      gst_gl_display_set_error (display,
+          "Download video format inconsistency %d", v_format);
+      g_assert_not_reached ();
+      break;
+  }
+
+#ifndef OPENGL_ES2
+  glReadBuffer (GL_NONE);
+  glDisable (GL_TEXTURE_RECTANGLE_ARB);
+#endif
+}
+
+
+/* called by _do_download (in the gl thread) */
+static void
+_do_download_draw_yuv (GstGLDisplay * display, GstGLDownload * download)
+{
+  GstVideoFormat v_format;
+  guint width, height;
+
+  GLenum multipleRT[] = {
+    GL_COLOR_ATTACHMENT0_EXT,
+    GL_COLOR_ATTACHMENT1_EXT,
+    GL_COLOR_ATTACHMENT2_EXT
+  };
+
+#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
+
+  width = GST_VIDEO_INFO_WIDTH (&download->info);
+  height = GST_VIDEO_INFO_HEIGHT (&download->info);
+  v_format = GST_VIDEO_INFO_FORMAT (&download->info);
+
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, download->fbo);
+
+#ifndef OPENGL_ES2
+  glPushAttrib (GL_VIEWPORT_BIT);
+
+  glMatrixMode (GL_PROJECTION);
+  glPushMatrix ();
+  glLoadIdentity ();
+  gluOrtho2D (0.0, width, 0.0, height);
+
+  glMatrixMode (GL_MODELVIEW);
+  glPushMatrix ();
+  glLoadIdentity ();
+#else /* OPENGL_ES2 */
+  glGetIntegerv (GL_VIEWPORT, viewport_dim);
+#endif
+
+  glViewport (0, 0, width, height);
+
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_UYVY:
+    case GST_VIDEO_FORMAT_AYUV:
+    {
+#ifndef OPENGL_ES2
+      glDrawBuffer (GL_COLOR_ATTACHMENT0_EXT);
+#endif
+
+      glClearColor (0.0, 0.0, 0.0, 0.0);
+      glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+      gst_gl_shader_use (download->shader);
+
+#ifndef OPENGL_ES2
+      glMatrixMode (GL_PROJECTION);
+      glLoadIdentity ();
+#else
+      glVertexAttribPointer (download->shader_attr_position_loc, 3,
+          GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices);
+      glVertexAttribPointer (download->shader_attr_texture_loc, 2,
+          GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]);
+
+      glEnableVertexAttribArray (download->shader_attr_position_loc);
+      glEnableVertexAttribArray (download->shader_attr_texture_loc);
+#endif
+
+      glActiveTextureARB (GL_TEXTURE0_ARB);
+      gst_gl_shader_set_uniform_1i (download->shader, "tex", 0);
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->in_texture);
+    }
+      break;
+
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+    {
+#ifndef OPENGL_ES2
+      glDrawBuffers (3, multipleRT);
+#endif
+
+      glClearColor (0.0, 0.0, 0.0, 0.0);
+      glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+      gst_gl_shader_use (download->shader);
+
+#ifndef OPENGL_ES2
+      glMatrixMode (GL_PROJECTION);
+      glLoadIdentity ();
+#endif
+
+      glActiveTextureARB (GL_TEXTURE0_ARB);
+      gst_gl_shader_set_uniform_1i (download->shader, "tex", 0);
+      gst_gl_shader_set_uniform_1f (download->shader, "w", (gfloat) width);
+      gst_gl_shader_set_uniform_1f (download->shader, "h", (gfloat) height);
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, download->in_texture);
+    }
+      break;
+
+    default:
+      break;
+      gst_gl_display_set_error (display,
+          "Download video format inconsistensy %d", v_format);
+
+  }
+
+#ifndef OPENGL_ES2
+  glBegin (GL_QUADS);
+  glTexCoord2i (0, 0);
+  glVertex2f (-1.0f, -1.0f);
+  glTexCoord2i (width, 0);
+  glVertex2f (1.0f, -1.0f);
+  glTexCoord2i (width, height);
+  glVertex2f (1.0f, 1.0f);
+  glTexCoord2i (0, height);
+  glVertex2f (-1.0f, 1.0f);
+  glEnd ();
+
+  glDrawBuffer (GL_NONE);
+#else /* OPENGL_ES2 */
+  glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+#endif
+
+  /* don't check if GLSL is available
+   * because download yuv is not available
+   * without GLSL (whereas rgb is)
+   */
+  glUseProgramObjectARB (0);
+
+#ifndef OPENGL_ES2
+  glDisable (GL_TEXTURE_RECTANGLE_ARB);
+  glMatrixMode (GL_PROJECTION);
+  glPopMatrix ();
+  glMatrixMode (GL_MODELVIEW);
+  glPopMatrix ();
+  glPopAttrib ();
+#else
+  glViewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
+      viewport_dim[3]);
+#endif
+
+  gst_gl_display_check_framebuffer_status ();
+
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
+
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, download->fbo);
+#ifndef OPENGL_ES2
+  glReadBuffer (GL_COLOR_ATTACHMENT0_EXT);
+#endif
+
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_AYUV:
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+      glReadPixels (0, 0, width, height, GL_BGRA,
+          GL_UNSIGNED_INT_8_8_8_8, download->data[0]);
+#else
+      glReadPixels (0, 0, width, height, GL_BGRA,
+          GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]);
+#endif
+      break;
+    case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_UYVY:
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+      glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2, height, GL_BGRA,
+          GL_UNSIGNED_INT_8_8_8_8_REV, download->data[0]);
+#else
+      glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2, height, GL_BGRA,
+          GL_UNSIGNED_INT_8_8_8_8, download->data[0]);
+#endif
+      break;
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+    {
+      glReadPixels (0, 0, width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE,
+          download->data[0]);
+
+#ifndef OPENGL_ES2
+      glReadBuffer (GL_COLOR_ATTACHMENT1_EXT);
+#endif
+
+      glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2,
+          GST_ROUND_UP_2 (height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
+          download->data[1]);
+
+#ifndef OPENGL_ES2
+      glReadBuffer (GL_COLOR_ATTACHMENT2_EXT);
+#endif
+
+      glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2,
+          GST_ROUND_UP_2 (height) / 2, GL_LUMINANCE, GL_UNSIGNED_BYTE,
+          download->data[2]);
+    }
+      break;
+    default:
+      break;
+      gst_gl_display_set_error (display,
+          "Download video format inconsistensy %d", v_format);
+      g_assert_not_reached ();
+  }
+#ifndef OPENGL_ES2
+  glReadBuffer (GL_NONE);
+#endif
+
+  gst_gl_display_check_framebuffer_status ();
+
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
+}
diff --git a/gst-libs/gst/gl/gstgldownload.h b/gst-libs/gst/gl/gstgldownload.h
new file mode 100644 (file)
index 0000000..6fb9b45
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * GStreamer
+ * Copyright (C) 2012 Matthew Waters <ystree00@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.
+ */
+
+#ifndef __GST_GL_DOWNLOAD_H__
+#define __GST_GL_DOWNLOAD_H__
+
+#include <gst/video/video.h>
+#include <gst/gstmemory.h>
+
+#include "gstglshader.h"
+#include "gstgldisplay.h"
+
+G_BEGIN_DECLS
+
+/* forward declare */
+typedef struct _GstGLMemory GstGLMemory;
+typedef struct _GstGLDisplay GstGLDisplay;
+
+GType gst_gl_download_get_type (void);
+#define GST_TYPE_GL_DOWNLOAD (gst_gl_download_get_type())
+#define GST_GL_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_DOWNLOAD,GstGLDownload))
+#define GST_GL_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_DISPLAY,GstGLDownloadClass))
+#define GST_IS_GL_DOWNLOAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_DOWNLOAD))
+#define GST_IS_GL_DOWNLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_DOWNLOAD))
+#define GST_GL_DOWNLOAD_CAST(obj) ((GstGLDownload*)(obj))
+
+typedef struct _GstGLDownload GstGLDownload;
+typedef struct _GstGLDownloadClass GstGLDownloadClass;
+
+struct _GstGLDownload
+{
+  GObject          parent;
+
+  GMutex           lock;
+
+  GstGLDisplay     *display;
+
+  gpointer         data[GST_VIDEO_MAX_PLANES];
+
+  /* used for the conversion */
+  GLuint           fbo;
+  GLuint           depth_buffer;
+  GLuint           in_texture;
+  GLuint           out_texture[GST_VIDEO_MAX_PLANES];
+  GstGLShader     *shader;
+#ifdef OPENGL_ES2
+  GLint            shader_attr_position_loc;
+  GLint            shader_attr_texture_loc;
+#endif
+
+  /* output data */
+  GstVideoInfo     info;
+
+  /* <private> */
+  gpointer _reserved[GST_PADDING];
+};
+
+struct _GstGLDownloadClass
+{
+  GObjectClass object_class;
+};
+
+GstGLDownload * gst_gl_download_new          (GstGLDisplay * display);
+
+gboolean gst_gl_download_init_format         (GstGLDownload * download, GstVideoFormat v_format,
+                                              guint width, guint height);
+gboolean gst_gl_download_perform_with_memory (GstGLDownload * download, GstGLMemory * gl_mem);
+gboolean gst_gl_download_perform_with_data   (GstGLDownload * download, GLuint texture_id,
+                                              gpointer data[GST_VIDEO_MAX_PLANES]);
+
+GstGLDownload * gst_gl_display_find_download (GstGLDisplay * display, GstVideoFormat v_format,
+                                              guint width, guint height);
+
+G_END_DECLS
+
+#endif /* __GST_GL_DOWNLOAD_H__ */
diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c
new file mode 100644 (file)
index 0000000..fefe2b0
--- /dev/null
@@ -0,0 +1,1365 @@
+/*
+ * GStreamer
+ * Copyright (C) 2012 Matthew Waters <ystree00@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 <stdio.h>
+
+#include "gstglupload.h"
+#include "gstglmemory.h"
+
+static void _do_upload (GstGLDisplay * display, GstGLUpload * upload);
+static void _do_upload_draw (GstGLDisplay * display, GstGLUpload * upload);
+static void _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload);
+static void _do_upload_make (GstGLDisplay * display, GstGLUpload * upload);
+static void _init_upload (GstGLDisplay * display, GstGLUpload * upload);
+static void _init_upload_fbo (GstGLDisplay * display, GstGLUpload * upload);
+static gboolean gst_gl_upload_perform_with_data_unlocked (GstGLUpload * upload,
+    GLuint texture_id, gpointer data[GST_VIDEO_MAX_PLANES]);
+
+/* YUY2:r,g,a
+   UYVY:a,b,r */
+static gchar *text_shader_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"
+#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";
+
+/* ATI: "*0.5", ""
+   normal: "", "*0.5" */
+static gchar *text_shader_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"
+#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";
+
+static gchar *text_shader_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=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";
+
+#ifdef OPENGL_ES2
+static gchar *text_vertex_shader =
+    "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";
+#endif
+
+GST_DEBUG_CATEGORY_STATIC (gst_gl_upload_debug);
+#define GST_CAT_DEFAULT gst_gl_upload_debug
+
+#define DEBUG_INIT \
+  GST_DEBUG_CATEGORY_INIT (gst_gl_upload_debug, "glupload", 0, "upload");
+
+G_DEFINE_TYPE_WITH_CODE (GstGLUpload, gst_gl_upload, G_TYPE_OBJECT, DEBUG_INIT);
+static void gst_gl_upload_finalize (GObject * object);
+
+#define GST_GL_UPLOAD_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
+    GST_TYPE_GL_UPLOAD, GstGLUploadPrivate))
+
+static void
+gst_gl_upload_class_init (GstGLUploadClass * klass)
+{
+  G_OBJECT_CLASS (klass)->finalize = gst_gl_upload_finalize;
+}
+
+static void
+gst_gl_upload_init (GstGLUpload * upload)
+{
+  upload->display = NULL;
+
+  g_mutex_init (&upload->lock);
+
+  upload->fbo = 0;
+  upload->depth_buffer = 0;
+  upload->out_texture = 0;
+  upload->shader = NULL;
+
+#ifdef OPENGL_ES2
+  upload->shader_attr_position_loc = 0;
+  upload->shader_attr_texture_loc = 0;
+#endif
+
+  gst_video_info_init (&upload->info);
+}
+
+GstGLUpload *
+gst_gl_upload_new (GstGLDisplay * display)
+{
+  GstGLUpload *upload;
+
+  upload = g_object_new (GST_TYPE_GL_UPLOAD, NULL);
+
+  upload->display = g_object_ref (display);
+
+  g_mutex_init (&upload->lock);
+
+  return upload;
+}
+
+static void
+gst_gl_upload_finalize (GObject * object)
+{
+  GstGLUpload *upload;
+  guint i;
+
+  upload = GST_GL_UPLOAD (object);
+
+  for (i = 0; i < GST_VIDEO_MAX_PLANES; i++) {
+    if (upload->in_texture[i]) {
+      gst_gl_display_del_texture (upload->display, &upload->in_texture[i]);
+      upload->in_texture[i] = 0;
+    }
+  }
+  if (upload->out_texture) {
+    gst_gl_display_del_texture (upload->display, &upload->out_texture);
+    upload->out_texture = 0;
+  }
+  if (upload->fbo || upload->depth_buffer) {
+    gst_gl_display_del_fbo (upload->display, upload->fbo, upload->depth_buffer);
+    upload->fbo = 0;
+    upload->depth_buffer = 0;
+  }
+  if (upload->shader) {
+    g_object_unref (G_OBJECT (upload->shader));
+    upload->shader = NULL;
+  }
+
+  if (upload->display) {
+    g_object_unref (G_OBJECT (upload->display));
+    upload->display = NULL;
+  }
+}
+
+gboolean
+gst_gl_upload_init_format (GstGLUpload * upload, GstVideoFormat v_format,
+    guint width, guint height)
+{
+  GstVideoInfo info;
+
+  g_return_val_if_fail (upload != NULL, FALSE);
+  g_return_val_if_fail (v_format != GST_VIDEO_FORMAT_UNKNOWN, FALSE);
+  g_return_val_if_fail (v_format != GST_VIDEO_FORMAT_ENCODED, FALSE);
+  g_return_val_if_fail (width > 0 && height > 0, FALSE);
+
+  g_mutex_lock (&upload->lock);
+
+  if (upload->initted) {
+    g_mutex_unlock (&upload->lock);
+    return FALSE;
+  } else {
+    upload->initted = TRUE;
+  }
+
+  gst_video_info_set_format (&info, v_format, width, height);
+
+  upload->info = info;
+
+  gst_gl_display_thread_add (upload->display,
+      (GstGLDisplayThreadFunc) _init_upload, upload);
+
+  g_mutex_unlock (&upload->lock);
+
+  return TRUE;
+}
+
+gboolean
+gst_gl_upload_perform_with_memory (GstGLUpload * upload, GstGLMemory * gl_mem)
+{
+  gpointer data[GST_VIDEO_MAX_PLANES];
+  guint i;
+  gboolean ret;
+
+  g_return_val_if_fail (upload != NULL, FALSE);
+
+  if (!GST_GL_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_MEMORY_FLAG_UPLOAD_INITTED))
+    return FALSE;
+
+  if (!GST_GL_MEMORY_FLAG_IS_SET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD))
+    return FALSE;
+
+  g_mutex_lock (&upload->lock);
+
+  for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->info); i++) {
+    data[i] = (guint8 *) gl_mem->data +
+        GST_VIDEO_INFO_PLANE_OFFSET (&upload->info, i);
+  }
+
+  ret = gst_gl_upload_perform_with_data_unlocked (upload, gl_mem->tex_id, data);
+
+  GST_GL_MEMORY_FLAG_UNSET (gl_mem, GST_GL_MEMORY_FLAG_NEED_UPLOAD);
+
+  g_mutex_unlock (&upload->lock);
+
+  return ret;
+}
+
+gboolean
+gst_gl_upload_perform_with_data (GstGLUpload * upload, GLuint texture_id,
+    gpointer data[GST_VIDEO_MAX_PLANES])
+{
+  gboolean ret;
+
+  g_return_val_if_fail (upload != NULL, FALSE);
+
+  g_mutex_lock (&upload->lock);
+
+  ret = gst_gl_upload_perform_with_data_unlocked (upload, texture_id, data);
+
+  g_mutex_unlock (&upload->lock);
+
+  return ret;
+}
+
+static gboolean
+gst_gl_upload_perform_with_data_unlocked (GstGLUpload * upload,
+    GLuint texture_id, gpointer data[GST_VIDEO_MAX_PLANES])
+{
+  guint i;
+
+  g_return_val_if_fail (upload != NULL, FALSE);
+  g_return_val_if_fail (texture_id > 0, FALSE);
+  g_return_val_if_fail (GST_VIDEO_INFO_FORMAT (&upload->info) !=
+      GST_VIDEO_FORMAT_UNKNOWN
+      && GST_VIDEO_INFO_FORMAT (&upload->info) != GST_VIDEO_FORMAT_ENCODED,
+      FALSE);
+
+  for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->info); i++) {
+    g_return_val_if_fail (data[i] != NULL, FALSE);
+  }
+
+  upload->out_texture = texture_id;
+  for (i = 0; i < GST_VIDEO_INFO_N_PLANES (&upload->info); i++) {
+    upload->data[i] = data[i];
+  }
+
+  gst_gl_display_thread_add (upload->display,
+      (GstGLDisplayThreadFunc) _do_upload, upload);
+
+  return TRUE;
+}
+
+GstGLUpload *
+gst_gl_display_find_upload (GstGLDisplay * display, GstVideoFormat v_format,
+    guint width, guint height)
+{
+  GstGLUpload *ret;
+  guint64 *key;
+
+  key = g_malloc (sizeof (guint64 *));
+  *key = v_format | ((guint64) width << 6) | ((guint64) height << 35);
+
+  gst_gl_display_lock (display);
+
+  ret = g_hash_table_lookup (display->uploads, key);
+
+  if (!ret) {
+    ret = gst_gl_upload_new (display);
+
+    g_hash_table_insert (display->uploads, key, ret);
+  }
+
+  gst_gl_display_unlock (display);
+
+  return ret;
+}
+
+/* Called in the gl thread */
+void
+_init_upload (GstGLDisplay * display, GstGLUpload * upload)
+{
+  GstVideoFormat v_format;
+
+  v_format = GST_VIDEO_INFO_FORMAT (&upload->info);
+
+  GST_TRACE ("initializing texture upload for format:%d", v_format);
+
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_RGBx:
+    case GST_VIDEO_FORMAT_BGRx:
+    case GST_VIDEO_FORMAT_xRGB:
+    case GST_VIDEO_FORMAT_xBGR:
+    case GST_VIDEO_FORMAT_RGBA:
+    case GST_VIDEO_FORMAT_BGRA:
+    case GST_VIDEO_FORMAT_ARGB:
+    case GST_VIDEO_FORMAT_ABGR:
+    case GST_VIDEO_FORMAT_RGB:
+    case GST_VIDEO_FORMAT_BGR:
+      /* color space conversion is not needed */
+      break;
+    case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_UYVY:
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+    case GST_VIDEO_FORMAT_AYUV:
+      /* color space conversion is needed */
+    {
+      /* 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->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_GLSL;
+
+        _init_upload_fbo (display, upload);
+
+        switch (v_format) {
+          case GST_VIDEO_FORMAT_YUY2:
+          {
+            gchar text_shader_YUY2[2048];
+            sprintf (text_shader_YUY2, text_shader_YUY2_UYVY, 'r', 'g', 'a');
+
+            upload->shader = gst_gl_shader_new ();
+#ifndef OPENGL_ES2
+            if (!gst_gl_shader_compile_and_check (upload->shader,
+                    text_shader_YUY2, GST_GL_SHADER_FRAGMENT_SOURCE)) {
+              gst_gl_display_set_error (display,
+                  "Failed to initialize shader for uploading YUY2");
+              g_object_unref (G_OBJECT (upload->shader));
+              upload->shader = NULL;
+            }
+#else
+            gst_gl_shader_set_vertex_source (upload->shader,
+                text_vertex_shader);
+            gst_gl_shader_set_fragment_source (upload->shader,
+                text_shader_YUY2);
+
+            gst_gl_shader_compile (upload->shader, &error);
+            if (error) {
+              gst_gl_display_set_error (display, "%s", error->message);
+              g_error_free (error);
+              error = NULL;
+              gst_gl_shader_use (NULL);
+              g_object_unref (G_OBJECT (upload->shader));
+              display->shader = NULL;
+            } else {
+              upload->shader_attr_position_loc =
+                  gst_gl_shader_get_attribute_location
+                  (upload->shader, "a_position");
+              upload->shader_attr_texture_loc =
+                  gst_gl_shader_get_attribute_location
+                  (upload->shader, "a_texCoord");
+            }
+#endif
+          }
+            break;
+          case GST_VIDEO_FORMAT_UYVY:
+          {
+            gchar text_shader_UYVY[2048];
+            sprintf (text_shader_UYVY,
+#ifndef OPENGL_ES2
+                text_shader_YUY2_UYVY, 'a', 'b', 'r');
+#else
+                text_shader_YUY2_UYVY, 'a', 'r', 'b');
+#endif
+
+            upload->shader = gst_gl_shader_new ();
+
+#ifndef OPENGL_ES2
+            if (!gst_gl_shader_compile_and_check (upload->shader,
+                    text_shader_UYVY, GST_GL_SHADER_FRAGMENT_SOURCE)) {
+              gst_gl_display_set_error (display,
+                  "Failed to initialize shader for uploading UYVY");
+              g_object_unref (G_OBJECT (upload->shader));
+              upload->shader = NULL;
+            }
+#else
+            gst_gl_shader_set_vertex_source (upload->shader,
+                text_vertex_shader);
+            gst_gl_shader_set_fragment_source (upload->shader,
+                text_shader_UYVY);
+
+            gst_gl_shader_compile (upload->shader, &error);
+            if (error) {
+              gst_gl_display_set_error (display, "%s", error->message);
+              g_error_free (error);
+              error = NULL;
+              gst_gl_shader_use (NULL);
+              g_object_unref (G_OBJECT (display->shader));
+              display->shader = NULL;
+            } else {
+              display->shader_attr_position_loc =
+                  gst_gl_shader_get_attribute_location
+                  (upload->shader, "a_position");
+              display->shader_upload_attr_texture_loc =
+                  gst_gl_shader_get_attribute_location
+                  (upload->shader, "a_texCoord");
+            }
+#endif
+          }
+            break;
+          case GST_VIDEO_FORMAT_I420:
+          case GST_VIDEO_FORMAT_YV12:
+          {
+#ifndef OPENGL_ES2
+            gchar text_shader[2048];
+            if ((g_ascii_strncasecmp ("ATI", (gchar *) glGetString (GL_VENDOR),
+                        3) == 0)
+                && (g_ascii_strncasecmp ("ATI Mobility Radeon HD",
+                        (gchar *) glGetString (GL_RENDERER), 22) != 0)
+                && (g_ascii_strncasecmp ("ATI Radeon HD",
+                        (gchar *) glGetString (GL_RENDERER), 13) != 0))
+              sprintf (text_shader, text_shader_I420_YV12, "*0.5", "");
+            else
+              sprintf (text_shader, text_shader_I420_YV12, "", "*0.5");
+#endif
+
+            upload->shader = gst_gl_shader_new ();
+
+#ifndef OPENGL_ES2
+            if (!gst_gl_shader_compile_and_check
+                (upload->shader, text_shader, GST_GL_SHADER_FRAGMENT_SOURCE)) {
+              gst_gl_display_set_error (display,
+                  "Failed to initialize shader for uploading I420 or YV12");
+              g_object_unref (G_OBJECT (upload->shader));
+              upload->shader = NULL;
+            }
+#else
+            gst_gl_shader_set_vertex_source (upload->shader,
+                text_vertex_shader);
+            gst_gl_shader_set_fragment_source (upload->shader, text_shader);
+
+            gst_gl_shader_compile (upload->shader, &error);
+            if (error) {
+              gst_gl_display_set_error (display, "%s", error->message);
+              g_error_free (error);
+              error = NULL;
+              gst_gl_shader_use (NULL);
+              g_object_unref (G_OBJECT (upload->shader));
+              display->shader = NULL;
+            } else {
+              display->shader_attr_position_loc =
+                  gst_gl_shader_get_attribute_location
+                  (upload->shader, "a_position");
+              display->shader_attr_texture_loc =
+                  gst_gl_shader_get_attribute_location
+                  (upload->shader, "a_texCoord");
+            }
+#endif
+          }
+            break;
+          case GST_VIDEO_FORMAT_AYUV:
+          {
+            upload->shader = gst_gl_shader_new ();
+
+#ifndef OPENGL_ES2
+            if (!gst_gl_shader_compile_and_check (upload->shader,
+                    text_shader_AYUV, GST_GL_SHADER_FRAGMENT_SOURCE)) {
+              gst_gl_display_set_error (display,
+                  "Failed to initialize shader for uploading AYUV");
+              g_object_unref (G_OBJECT (upload->shader));
+              upload->shader = NULL;
+            }
+#else
+            gst_gl_shader_set_vertex_source (upload->shader,
+                text_vertex_shader);
+            gst_gl_shader_set_fragment_source (upload->shader,
+                text_shader_AYUV);
+
+            gst_gl_shader_compile (upload->shader, &error);
+            if (error) {
+              gst_gl_display_set_error (display, "%s", error->message);
+              g_error_free (error);
+              error = NULL;
+              gst_gl_shader_use (NULL);
+              g_object_unref (G_OBJECT (upload->shader));
+              upload->shader = NULL;
+            } else {
+              upload->shader_attr_position_loc =
+                  gst_gl_shader_get_attribute_location
+                  (upload->shader, "a_position");
+              upload->shader_upload_attr_texture_loc =
+                  gst_gl_shader_get_attribute_location
+                  (upload->shader, "a_texCoord");
+            }
+#endif
+          }
+            break;
+          default:
+            gst_gl_display_set_error (display,
+                "Unsupported upload video format %d", v_format);
+            break;
+        }
+      }
+      /* check if YCBCR MESA is available */
+      else if (GLEW_MESA_ycbcr_texture) {
+        /* GLSL and Color Matrix are not available on your drivers,
+         * switch to YCBCR MESA
+         */
+        GST_INFO ("Context, ARB_fragment_shader supported: no");
+        GST_INFO ("Context, GLEW_MESA_ycbcr_texture supported: yes");
+
+        display->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_MESA;
+
+        switch (v_format) {
+          case GST_VIDEO_FORMAT_YUY2:
+          case GST_VIDEO_FORMAT_UYVY:
+            /* color space conversion is not needed */
+            break;
+          case GST_VIDEO_FORMAT_I420:
+          case GST_VIDEO_FORMAT_YV12:
+          case GST_VIDEO_FORMAT_AYUV:
+            /* MESA only supports YUY2 and UYVY */
+            gst_gl_display_set_error (display,
+                "Your MESA version only supports YUY2 and UYVY (GLSL is required for others yuv formats)");
+            break;
+          default:
+            gst_gl_display_set_error (display,
+                "Unsupported upload video format %d", v_format);
+            break;
+        }
+      }
+      /* check if color matrix is available (not supported) */
+      else if (GLEW_ARB_imaging) {
+        /* GLSL is not available on your drivers, switch to Color Matrix */
+        GST_INFO ("Context, ARB_fragment_shader supported: no");
+        GST_INFO ("Context, GLEW_MESA_ycbcr_texture supported: no");
+        GST_INFO ("Context, GLEW_ARB_imaging supported: yes");
+
+        display->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_MATRIX;
+
+        gst_gl_display_set_error (display,
+            "Colorspace conversion using Color Matrix is not yet supported");
+      } else {
+        /* colorspace conversion is not possible */
+        gst_gl_display_set_error (display,
+            "ARB_fragment_shader supported, GLEW_ARB_imaging supported, GLEW_MESA_ycbcr_texture supported, not supported");
+      }
+    }
+      break;
+    default:
+      gst_gl_display_set_error (display, "Unsupported upload video format %d",
+          v_format);
+      break;
+  }
+}
+
+
+/* called by _init_upload (in the gl thread) */
+void
+_init_upload_fbo (GstGLDisplay * display, GstGLUpload * upload)
+{
+  guint width, height;
+  GLuint fake_texture = 0;      /* a FBO must hava texture to init */
+
+  width = GST_VIDEO_INFO_WIDTH (&upload->info);
+  height = GST_VIDEO_INFO_HEIGHT (&upload->info);
+
+  if (!GLEW_EXT_framebuffer_object) {
+    /* turn off the pipeline because Frame buffer object is a not present */
+    gst_gl_display_set_error (display,
+        "Context, EXT_framebuffer_object supported: no");
+    return;
+  }
+
+  GST_INFO ("Context, EXT_framebuffer_object supported: yes");
+
+  /* setup FBO */
+  glGenFramebuffersEXT (1, &upload->fbo);
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, upload->fbo);
+
+  /* setup the render buffer for depth */
+  glGenRenderbuffersEXT (1, &upload->depth_buffer);
+  glBindRenderbufferEXT (GL_RENDERBUFFER_EXT, upload->depth_buffer);
+#ifndef OPENGL_ES2
+  glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
+      width, height);
+  glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
+      width, height);
+#else
+  glRenderbufferStorageEXT (GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16,
+      width, height);
+#endif
+
+  /* a fake texture is attached to the upload FBO (cannot init without it) */
+  glGenTextures (1, &fake_texture);
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, fake_texture);
+  glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, width, height, 0,
+      GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+      GL_CLAMP_TO_EDGE);
+  glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+      GL_CLAMP_TO_EDGE);
+
+  /* attach the texture to the FBO to renderer to */
+  glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+      GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0);
+
+  /* attach the depth render buffer to the FBO */
+  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+      GL_RENDERBUFFER_EXT, upload->depth_buffer);
+
+#ifndef OPENGL_ES2
+  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
+      GL_RENDERBUFFER_EXT, upload->depth_buffer);
+#endif
+
+  gst_gl_display_check_framebuffer_status ();
+
+  if (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) !=
+      GL_FRAMEBUFFER_COMPLETE_EXT)
+    gst_gl_display_set_error (display, "GL framebuffer status incomplete");
+
+  /* unbind the FBO */
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
+
+  glDeleteTextures (1, &fake_texture);
+
+  _do_upload_make (display, upload);
+}
+
+/* Called by the idle function in the gl thread */
+void
+_do_upload (GstGLDisplay * display, GstGLUpload * upload)
+{
+  GstVideoFormat v_format;
+  guint width, height;
+
+  width = GST_VIDEO_INFO_WIDTH (&upload->info);
+  height = GST_VIDEO_INFO_HEIGHT (&upload->info);
+  v_format = GST_VIDEO_INFO_FORMAT (&upload->info);
+
+  GST_TRACE ("uploading texture:%u dimensions: %ux%u", upload->out_texture,
+      width, height);
+
+  _do_upload_fill (display, upload);
+
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_RGBx:
+    case GST_VIDEO_FORMAT_BGRx:
+    case GST_VIDEO_FORMAT_xRGB:
+    case GST_VIDEO_FORMAT_xBGR:
+    case GST_VIDEO_FORMAT_RGBA:
+    case GST_VIDEO_FORMAT_BGRA:
+    case GST_VIDEO_FORMAT_ARGB:
+    case GST_VIDEO_FORMAT_ABGR:
+    case GST_VIDEO_FORMAT_RGB:
+    case GST_VIDEO_FORMAT_BGR:
+      /* color space conversion is not needed */
+      break;
+    case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_UYVY:
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+    case GST_VIDEO_FORMAT_AYUV:
+    {
+      switch (display->colorspace_conversion) {
+        case GST_GL_DISPLAY_CONVERSION_GLSL:
+          /* color space conversion is needed */
+          _do_upload_draw (display, upload);
+          break;
+        case GST_GL_DISPLAY_CONVERSION_MATRIX:
+          /* color space conversion is needed */
+          /* not yet supported */
+          break;
+        case GST_GL_DISPLAY_CONVERSION_MESA:
+          /* color space conversion is not needed */
+          break;
+        default:
+          gst_gl_display_set_error (display, "Unknown colorspace conversion %d",
+              display->colorspace_conversion);
+          g_assert_not_reached ();
+          break;
+      }
+    }
+      break;
+    default:
+      gst_gl_display_set_error (display, "Unsupported upload video format %d",
+          v_format);
+      g_assert_not_reached ();
+      break;
+  }
+}
+
+/* called by gst_gl_display_thread_do_upload (in the gl thread) */
+void
+_do_upload_make (GstGLDisplay * display, GstGLUpload * upload)
+{
+  GstVideoFormat v_format;
+  guint width, height;
+
+  width = GST_VIDEO_INFO_WIDTH (&upload->info);
+  height = GST_VIDEO_INFO_HEIGHT (&upload->info);
+  v_format = GST_VIDEO_INFO_FORMAT (&upload->info);
+
+  glGenTextures (1, &upload->in_texture[0]);
+
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]);
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_RGBx:
+    case GST_VIDEO_FORMAT_BGRx:
+    case GST_VIDEO_FORMAT_xRGB:
+    case GST_VIDEO_FORMAT_xBGR:
+    case GST_VIDEO_FORMAT_RGBA:
+    case GST_VIDEO_FORMAT_BGRA:
+    case GST_VIDEO_FORMAT_ARGB:
+    case GST_VIDEO_FORMAT_ABGR:
+      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
+          width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+      break;
+    case GST_VIDEO_FORMAT_RGB:
+    case GST_VIDEO_FORMAT_BGR:
+      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
+          width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
+      break;
+    case GST_VIDEO_FORMAT_AYUV:
+      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
+          width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, NULL);
+      break;
+    case GST_VIDEO_FORMAT_YUY2:
+      switch (display->colorspace_conversion) {
+        case GST_GL_DISPLAY_CONVERSION_GLSL:
+        case GST_GL_DISPLAY_CONVERSION_MATRIX:
+          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA,
+              width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
+          glGenTextures (1, &upload->in_texture[1]);
+          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
+          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+              width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
+          break;
+        case GST_GL_DISPLAY_CONVERSION_MESA:
+          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width,
+              height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL);
+          break;
+        default:
+          gst_gl_display_set_error (display, "Unknown colorspace conversion %d",
+              display->colorspace_conversion);
+          g_assert_not_reached ();
+          break;
+      }
+      break;
+    case GST_VIDEO_FORMAT_UYVY:
+      switch (display->colorspace_conversion) {
+        case GST_GL_DISPLAY_CONVERSION_GLSL:
+        case GST_GL_DISPLAY_CONVERSION_MATRIX:
+          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA,
+              width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
+          glGenTextures (1, &upload->in_texture[1]);
+          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
+          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
+              width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
+          break;
+        case GST_GL_DISPLAY_CONVERSION_MESA:
+          glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width,
+              height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL);
+          break;
+        default:
+          gst_gl_display_set_error (display, "Unknown colorspace conversion %d",
+              display->colorspace_conversion);
+          g_assert_not_reached ();
+          break;
+      }
+      break;
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
+          width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
+
+      glGenTextures (1, &upload->in_texture[1]);
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
+      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
+          GST_ROUND_UP_2 (width) / 2,
+          GST_ROUND_UP_2 (height) / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
+
+      glGenTextures (1, &upload->in_texture[2]);
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[2]);
+      glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
+          GST_ROUND_UP_2 (width) / 2,
+          GST_ROUND_UP_2 (height) / 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
+      break;
+
+    default:
+      gst_gl_display_set_error (display, "Unsupported upload video format %d",
+          v_format);
+      g_assert_not_reached ();
+      break;
+  }
+}
+
+
+/* called by gst_gl_display_thread_do_upload (in the gl thread) */
+void
+_do_upload_fill (GstGLDisplay * display, GstGLUpload * upload)
+{
+  GstVideoFormat v_format;
+  guint width, height;
+
+  width = GST_VIDEO_INFO_WIDTH (&upload->info);
+  height = GST_VIDEO_INFO_HEIGHT (&upload->info);
+  v_format = GST_VIDEO_INFO_FORMAT (&upload->info);
+
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_RGB:
+    case GST_VIDEO_FORMAT_BGR:
+    case GST_VIDEO_FORMAT_RGBx:
+    case GST_VIDEO_FORMAT_BGRx:
+    case GST_VIDEO_FORMAT_xRGB:
+    case GST_VIDEO_FORMAT_xBGR:
+    case GST_VIDEO_FORMAT_RGBA:
+    case GST_VIDEO_FORMAT_BGRA:
+    case GST_VIDEO_FORMAT_ARGB:
+    case GST_VIDEO_FORMAT_ABGR:
+      /* color space conversion is not needed */
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->out_texture);
+      break;
+    case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_UYVY:
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+    case GST_VIDEO_FORMAT_AYUV:
+      switch (display->colorspace_conversion) {
+        case GST_GL_DISPLAY_CONVERSION_GLSL:
+        case GST_GL_DISPLAY_CONVERSION_MATRIX:
+          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]);
+          break;
+        case GST_GL_DISPLAY_CONVERSION_MESA:
+          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->out_texture);
+          break;
+        default:
+          gst_gl_display_set_error (display, "Unknown colorspace conversion %d",
+              display->colorspace_conversion);
+          g_assert_not_reached ();
+          break;
+      }
+      break;
+    default:
+      gst_gl_display_set_error (display, "Unsupported upload video format %d",
+          v_format);
+      g_assert_not_reached ();
+      break;
+  }
+
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_RGB:
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+          GL_RGB, GL_UNSIGNED_BYTE, upload->data[0]);
+      break;
+    case GST_VIDEO_FORMAT_BGR:
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+          GL_BGR, GL_UNSIGNED_BYTE, upload->data[0]);
+      break;
+    case GST_VIDEO_FORMAT_RGBx:
+    case GST_VIDEO_FORMAT_RGBA:
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+          GL_RGBA, GL_UNSIGNED_BYTE, upload->data[0]);
+      break;
+    case GST_VIDEO_FORMAT_BGRx:
+    case GST_VIDEO_FORMAT_BGRA:
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+          GL_BGRA, GL_UNSIGNED_BYTE, upload->data[0]);
+      break;
+    case GST_VIDEO_FORMAT_AYUV:
+    case GST_VIDEO_FORMAT_xRGB:
+    case GST_VIDEO_FORMAT_ARGB:
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+          GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, upload->data[0]);
+      break;
+    case GST_VIDEO_FORMAT_xBGR:
+    case GST_VIDEO_FORMAT_ABGR:
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+          GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, upload->data[0]);
+      break;
+    case GST_VIDEO_FORMAT_YUY2:
+      switch (display->colorspace_conversion) {
+        case GST_GL_DISPLAY_CONVERSION_GLSL:
+        case GST_GL_DISPLAY_CONVERSION_MATRIX:
+          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+              GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, upload->data[0]);
+
+          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
+          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
+              GST_ROUND_UP_2 (width) / 2, height,
+              GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, upload->data[0]);
+          break;
+        case GST_GL_DISPLAY_CONVERSION_MESA:
+          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+              GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_REV_MESA, upload->data[0]);
+          break;
+        default:
+          gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
+              display->colorspace_conversion);
+          g_assert_not_reached ();
+          break;
+      }
+      break;
+    case GST_VIDEO_FORMAT_UYVY:
+      switch (display->colorspace_conversion) {
+        case GST_GL_DISPLAY_CONVERSION_GLSL:
+        case GST_GL_DISPLAY_CONVERSION_MATRIX:
+          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+              GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, upload->data[0]);
+
+          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
+          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
+              GST_ROUND_UP_2 (width) / 2, height,
+              GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, upload->data[0]);
+          break;
+        case GST_GL_DISPLAY_CONVERSION_MESA:
+          glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+              GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, upload->data[0]);
+          break;
+        default:
+          gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
+              display->colorspace_conversion);
+          g_assert_not_reached ();
+          break;
+      }
+      break;
+    case GST_VIDEO_FORMAT_I420:
+    {
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+          GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[0]);
+
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
+          GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
+          GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[1]);
+
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[2]);
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
+          GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
+          GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[2]);
+    }
+      break;
+    case GST_VIDEO_FORMAT_YV12:        /* same as I420 except plane 1+2 swapped */
+    {
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
+          GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[0]);
+
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[2]);
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
+          GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
+          GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[1]);
+
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
+      glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0,
+          GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
+          GL_LUMINANCE, GL_UNSIGNED_BYTE, upload->data[2]);
+    }
+      break;
+    default:
+      gst_gl_display_set_error (display, "Unsupported upload video format %d",
+          v_format);
+      g_assert_not_reached ();
+      break;
+  }
+
+  /* make sure no texture is in use in our opengl context 
+   * in case we want to use the upload texture in an other opengl context
+   */
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0);
+}
+
+
+/* called by _do_upload (in the gl thread) */
+void
+_do_upload_draw (GstGLDisplay * display, GstGLUpload * upload)
+{
+  GstVideoFormat v_format;
+  guint width, height;
+
+#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
+
+  width = GST_VIDEO_INFO_WIDTH (&upload->info);
+  height = GST_VIDEO_INFO_HEIGHT (&upload->info);
+  v_format = GST_VIDEO_INFO_FORMAT (&upload->info);
+
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, upload->fbo);
+
+  /* setup a texture to render to */
+#ifndef OPENGL_ES2
+  glEnable (GL_TEXTURE_RECTANGLE_ARB);
+#endif
+  glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->out_texture);
+
+  /* attach the texture to the FBO to renderer to */
+  glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+      GL_TEXTURE_RECTANGLE_ARB, upload->out_texture, 0);
+
+  if (GLEW_ARB_fragment_shader)
+    gst_gl_shader_use (NULL);
+
+#ifndef OPENGL_ES2
+  glPushAttrib (GL_VIEWPORT_BIT);
+
+  glMatrixMode (GL_PROJECTION);
+  glPushMatrix ();
+  glLoadIdentity ();
+  gluOrtho2D (0.0, width, 0.0, height);
+
+  glMatrixMode (GL_MODELVIEW);
+  glPushMatrix ();
+  glLoadIdentity ();
+#else /* OPENGL_ES2 */
+  glGetIntegerv (GL_VIEWPORT, viewport_dim);
+#endif
+
+  glViewport (0, 0, width, 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);
+
+  switch (v_format) {
+    case GST_VIDEO_FORMAT_RGBx:
+    case GST_VIDEO_FORMAT_BGRx:
+    case GST_VIDEO_FORMAT_xRGB:
+    case GST_VIDEO_FORMAT_xBGR:
+    case GST_VIDEO_FORMAT_RGBA:
+    case GST_VIDEO_FORMAT_BGRA:
+    case GST_VIDEO_FORMAT_ARGB:
+    case GST_VIDEO_FORMAT_ABGR:
+    case GST_VIDEO_FORMAT_RGB:
+    case GST_VIDEO_FORMAT_BGR:
+    {
+#ifndef OPENGL_ES2
+      glMatrixMode (GL_PROJECTION);
+      glLoadIdentity ();
+#else
+      glVertexAttribPointer (upload->shader_attr_position_loc, 3,
+          GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices);
+      glVertexAttribPointer (upload->shader_attr_texture_loc, 2,
+          GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]);
+
+      glEnableVertexAttribArray (upload->shader_attr_position_loc);
+      glEnableVertexAttribArray (upload->shader_attr_texture_loc);
+#endif
+
+#ifndef OPENGL_ES2
+      glEnable (GL_TEXTURE_RECTANGLE_ARB);
+#endif
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+          GL_CLAMP_TO_EDGE);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+          GL_CLAMP_TO_EDGE);
+#ifndef OPENGL_ES2
+      glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+#endif
+    }
+      break;
+
+    case GST_VIDEO_FORMAT_YUY2:
+    case GST_VIDEO_FORMAT_UYVY:
+    {
+      switch (display->colorspace_conversion) {
+        case GST_GL_DISPLAY_CONVERSION_GLSL:
+        case GST_GL_DISPLAY_CONVERSION_MATRIX:
+        {
+          gst_gl_shader_use (upload->shader);
+
+#ifndef OPENGL_ES2
+          glMatrixMode (GL_PROJECTION);
+          glLoadIdentity ();
+#else
+          glVertexAttribPointer (upload->shader_attr_position_loc, 3,
+              GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices);
+          glVertexAttribPointer (upload->shader_attr_texture_loc, 2,
+              GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]);
+
+          glEnableVertexAttribArray (upload->shader_attr_position_loc);
+          glEnableVertexAttribArray (upload->shader_attr_texture_loc);
+#endif
+
+          glActiveTextureARB (GL_TEXTURE1_ARB);
+          gst_gl_shader_set_uniform_1i (upload->shader, "UVtex", 1);
+          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+              GL_LINEAR);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+              GL_LINEAR);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+              GL_CLAMP_TO_EDGE);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+              GL_CLAMP_TO_EDGE);
+
+          glActiveTextureARB (GL_TEXTURE0_ARB);
+          gst_gl_shader_set_uniform_1i (upload->shader, "Ytex", 0);
+          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+              GL_LINEAR);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+              GL_LINEAR);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+              GL_CLAMP_TO_EDGE);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+              GL_CLAMP_TO_EDGE);
+        }
+          break;
+        case GST_GL_DISPLAY_CONVERSION_MESA:
+        {
+
+#ifndef OPENGL_ES2
+          glMatrixMode (GL_PROJECTION);
+          glLoadIdentity ();
+          glEnable (GL_TEXTURE_RECTANGLE_ARB);
+#endif
+          glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+              GL_LINEAR);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+              GL_LINEAR);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+              GL_CLAMP_TO_EDGE);
+          glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+              GL_CLAMP_TO_EDGE);
+#ifndef OPENGL_ES2
+          glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
+#endif
+        }
+          break;
+        default:
+          gst_gl_display_set_error (display, "Unknow colorspace conversion %d",
+              display->colorspace_conversion);
+          g_assert_not_reached ();
+          break;
+      }
+    }
+      break;
+
+    case GST_VIDEO_FORMAT_I420:
+    case GST_VIDEO_FORMAT_YV12:
+    {
+      gst_gl_shader_use (upload->shader);
+
+#ifndef OPENGL_ES2
+      glMatrixMode (GL_PROJECTION);
+      glLoadIdentity ();
+#else
+      glVertexAttribPointer (upload->shader_attr_position_loc, 3,
+          GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices);
+      glVertexAttribPointer (upload->shader_attr_texture_loc, 2,
+          GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]);
+
+      glEnableVertexAttribArray (upload->shader_attr_position_loc);
+      glEnableVertexAttribArray (upload->shader_attr_texture_loc);
+#endif
+
+      glActiveTextureARB (GL_TEXTURE1_ARB);
+      gst_gl_shader_set_uniform_1i (upload->shader, "Utex", 1);
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[1]);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+          GL_CLAMP_TO_EDGE);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+          GL_CLAMP_TO_EDGE);
+
+      glActiveTextureARB (GL_TEXTURE2_ARB);
+      gst_gl_shader_set_uniform_1i (upload->shader, "Vtex", 2);
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[2]);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+          GL_CLAMP_TO_EDGE);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+          GL_CLAMP_TO_EDGE);
+
+      glActiveTextureARB (GL_TEXTURE0_ARB);
+      gst_gl_shader_set_uniform_1i (upload->shader, "Ytex", 0);
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+          GL_CLAMP_TO_EDGE);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+          GL_CLAMP_TO_EDGE);
+    }
+      break;
+
+    case GST_VIDEO_FORMAT_AYUV:
+    {
+      gst_gl_shader_use (upload->shader);
+
+#ifndef OPENGL_ES2
+      glMatrixMode (GL_PROJECTION);
+      glLoadIdentity ();
+#else
+      glVertexAttribPointer (upload->shader_attr_position_loc, 3,
+          GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), vVertices);
+      glVertexAttribPointer (upload->shader_attr_texture_loc, 2,
+          GL_FLOAT, GL_FALSE, 5 * sizeof (GLfloat), &vVertices[3]);
+
+      glEnableVertexAttribArray (upload->shader_attr_position_loc);
+      glEnableVertexAttribArray (upload->shader_attr_texture_loc);
+#endif
+
+      glActiveTextureARB (GL_TEXTURE0_ARB);
+      gst_gl_shader_set_uniform_1i (upload->shader, "tex", 0);
+      glBindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER,
+          GL_LINEAR);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S,
+          GL_CLAMP_TO_EDGE);
+      glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T,
+          GL_CLAMP_TO_EDGE);
+    }
+      break;
+
+    default:
+      gst_gl_display_set_error (display, "Unsupported upload video format %d",
+          v_format);
+      g_assert_not_reached ();
+      break;
+
+  }                             /* end switch display->currentVideo_format */
+
+#ifndef OPENGL_ES2
+  glBegin (GL_QUADS);
+  glTexCoord2i (width, 0);
+  glVertex2f (1.0f, -1.0f);
+  glTexCoord2i (0, 0);
+  glVertex2f (-1.0f, -1.0f);
+  glTexCoord2i (0, height);
+  glVertex2f (-1.0f, 1.0f);
+  glTexCoord2i (width, height);
+  glVertex2f (1.0f, 1.0f);
+  glEnd ();
+
+  glDrawBuffer (GL_NONE);
+#else /* OPENGL_ES2 */
+  glDrawElements (GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices);
+#endif
+
+  /* we are done with the shader */
+  if (display->colorspace_conversion == GST_GL_DISPLAY_CONVERSION_GLSL)
+    glUseProgramObjectARB (0);
+
+#ifndef OPENGL_ES2
+  glDisable (GL_TEXTURE_RECTANGLE_ARB);
+
+  glMatrixMode (GL_PROJECTION);
+  glPopMatrix ();
+  glMatrixMode (GL_MODELVIEW);
+  glPopMatrix ();
+  glPopAttrib ();
+#else
+  glViewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
+      viewport_dim[3]);
+#endif
+
+  gst_gl_display_check_framebuffer_status ();
+
+  glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
+}
diff --git a/gst-libs/gst/gl/gstglupload.h b/gst-libs/gst/gl/gstglupload.h
new file mode 100644 (file)
index 0000000..ebe63b0
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * GStreamer
+ * Copyright (C) 2012 Matthew Waters <ystree00@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.
+ */
+
+#ifndef __GST_GL_UPLOAD_H__
+#define __GST_GL_UPLOAD_H__
+
+#include <gst/video/video.h>
+#include <gst/gstmemory.h>
+
+#include "gstglshader.h"
+#include "gstgldisplay.h"
+
+G_BEGIN_DECLS
+
+/* forward declare */
+typedef struct _GstGLMemory GstGLMemory;
+typedef struct _GstGLDisplay GstGLDisplay;
+
+GType gst_gl_upload_get_type (void);
+#define GST_TYPE_GL_UPLOAD (gst_gl_upload_get_type())
+#define GST_GL_UPLOAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GL_UPLOAD,GstGLUpload))
+#define GST_GL_UPLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GL_DISPLAY,GstGLUploadClass))
+#define GST_IS_GL_UPLOAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GL_UPLOAD))
+#define GST_IS_GL_UPLOAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GL_UPLOAD))
+#define GST_GL_UPLOAD_CAST(obj) ((GstGLUpload*)(obj))
+
+typedef struct _GstGLUpload GstGLUpload;
+typedef struct _GstGLUploadClass GstGLUploadClass;
+
+struct _GstGLUpload
+{
+  GObject          parent;
+
+  GMutex           lock;
+
+  GstGLDisplay    *display;
+
+  gpointer         data[GST_VIDEO_MAX_PLANES];
+  gboolean         initted;
+
+  /* used for the conversion */
+  GLuint           fbo;
+  GLuint           depth_buffer;
+  GLuint           out_texture;
+  GLuint           in_texture[GST_VIDEO_MAX_PLANES];
+  GstGLShader     *shader;
+#ifdef OPENGL_ES2
+  GLint            shader_attr_position_loc;
+  GLint            shader_attr_texture_loc;
+#endif
+
+  /* output data */
+  GstVideoInfo    info;
+
+  /* <private> */
+  gpointer _reserved[GST_PADDING];
+};
+
+struct _GstGLUploadClass
+{
+  GObjectClass object_class;
+};
+
+GstGLUpload * gst_gl_upload_new            (GstGLDisplay * display);
+
+gboolean gst_gl_upload_init_format         (GstGLUpload * upload, GstVideoFormat v_format,
+                                            guint width, guint height);
+
+gboolean gst_gl_upload_perform_with_memory (GstGLUpload * upload, GstGLMemory * gl_mem);
+gboolean gst_gl_upload_perform_with_data   (GstGLUpload * upload, GLuint texture_id,
+                                            gpointer data[GST_VIDEO_MAX_PLANES]);
+
+GstGLUpload * gst_gl_display_find_upload   (GstGLDisplay * display, GstVideoFormat v_format,
+                                            guint width, guint height);
+
+G_END_DECLS
+
+#endif /* __GST_GL_UPLOAD_H__ */