#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
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);
#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);
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);
//------------------------------------------------------------
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 ();
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;
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 =
"{ \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
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;
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;
+ }
}
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));
}
#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");
}
}
#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);
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);
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
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,
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:
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);
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)
}
}
-
-//------------------------------------------------------------
-//--------------------- END PRIVATE -------------------------
-//------------------------------------------------------------
-
-
-//------------------------------------------------------------
-//---------------------- BEGIN PUBLIC ------------------------
-//------------------------------------------------------------
-
-
/* Called by the first gl element of a video/x-raw-gl flow */
GstGLDisplay *
gst_gl_display_new (void)
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)
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);
-}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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);
+}