2008-06-19 23:38:36 +00:00
|
|
|
/*
|
2008-05-19 16:57:39 +00:00
|
|
|
* GStreamer
|
|
|
|
* Copyright (C) 2008 Julien Isorce <julien.isorce@gmail.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "gstgldisplay.h"
|
|
|
|
#include <gst/gst.h>
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
GST_BOILERPLATE (GstGLDisplay, gst_gl_display, GObject, G_TYPE_OBJECT);
|
|
|
|
static void gst_gl_display_finalize (GObject* object);
|
|
|
|
|
|
|
|
/* GL thread loop */
|
|
|
|
static gpointer gst_gl_display_thread_func (GstGLDisplay* display);
|
|
|
|
static void gst_gl_display_thread_loop (void);
|
|
|
|
static void gst_gl_display_thread_dispatch_action (GstGLDisplayMsg *msg);
|
|
|
|
static gboolean gst_gl_display_thread_check_msg_validity (GstGLDisplayMsg *msg);
|
|
|
|
|
|
|
|
/* Called in the gl thread, protected by lock and unlock */
|
|
|
|
static void gst_gl_display_thread_create_context (GstGLDisplay* display);
|
|
|
|
static void gst_gl_display_thread_destroy_context (GstGLDisplay* display);
|
|
|
|
static void gst_gl_display_thread_set_visible_context (GstGLDisplay* display);
|
|
|
|
static void gst_gl_display_thread_resize_context (GstGLDisplay* display);
|
|
|
|
static void gst_gl_display_thread_redisplay (GstGLDisplay* display);
|
|
|
|
static void gst_gl_display_thread_gen_texture (GstGLDisplay* display);
|
|
|
|
static void gst_gl_display_thread_del_texture (GstGLDisplay* display);
|
|
|
|
static void gst_gl_display_thread_init_upload (GstGLDisplay* display);
|
|
|
|
static void gst_gl_display_thread_do_upload (GstGLDisplay* display);
|
|
|
|
static void gst_gl_display_thread_init_download (GstGLDisplay *display);
|
|
|
|
static void gst_gl_display_thread_do_download (GstGLDisplay* display);
|
|
|
|
static void gst_gl_display_thread_gen_fbo (GstGLDisplay *display);
|
|
|
|
static void gst_gl_display_thread_use_fbo (GstGLDisplay *display);
|
|
|
|
static void gst_gl_display_thread_use_fbo_2 (GstGLDisplay *display);
|
|
|
|
static void gst_gl_display_thread_del_fbo (GstGLDisplay *display);
|
|
|
|
static void gst_gl_display_thread_gen_shader (GstGLDisplay *display);
|
|
|
|
static void gst_gl_display_thread_del_shader (GstGLDisplay *display);
|
|
|
|
|
|
|
|
/* private methods */
|
2008-05-18 11:12:46 +00:00
|
|
|
void gst_gl_display_lock (GstGLDisplay* display);
|
|
|
|
void gst_gl_display_unlock (GstGLDisplay* display);
|
2008-06-29 17:27:43 +00:00
|
|
|
void gst_gl_display_post_message (GstGLDisplayAction action, GstGLDisplay* display);
|
|
|
|
void gst_gl_display_on_resize(gint width, gint height);
|
|
|
|
void gst_gl_display_on_draw (void);
|
|
|
|
void gst_gl_display_on_close (void);
|
|
|
|
void gst_gl_display_glgen_texture (GstGLDisplay* display, guint* pTexture);
|
|
|
|
void gst_gl_display_gldel_texture (GstGLDisplay* display, guint* pTexture);
|
|
|
|
GLhandleARB gst_gl_display_load_fragment_shader (gchar* textFProgram);
|
|
|
|
void gst_gl_display_check_framebuffer_status (void);
|
|
|
|
|
|
|
|
/* To not make gst_gl_display_thread_do_upload
|
|
|
|
* and gst_gl_display_thread_do_download too big */
|
2008-06-30 00:38:39 +00:00
|
|
|
static void gst_gl_display_thread_do_upload_make (GstGLDisplay* display, GLuint* pTexture,
|
|
|
|
GLuint* pTexture_u, GLuint* pTexture_v);
|
|
|
|
static void gst_gl_display_thread_do_upload_fill (GstGLDisplay* display, GLuint* pTexture,
|
|
|
|
GLuint* pTexture_u, GLuint* pTexture_v,
|
|
|
|
GstVideoFormat* pVideo_format);
|
|
|
|
static void gst_gl_display_thread_do_upload_draw (GstGLDisplay* display, GLuint texture,
|
|
|
|
GLuint texture_u, GLuint texture_v,
|
|
|
|
GstVideoFormat video_format);
|
2008-06-29 17:27:43 +00:00
|
|
|
static void gst_gl_display_thread_do_download_draw (GstGLDisplay* display);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
//-------------------- Glut context management ---------------
|
2008-06-19 23:38:36 +00:00
|
|
|
//------------------------------------------------------------
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
//(key=int glutWinId) and (value=GstGLDisplay *display)
|
|
|
|
static GHashTable *gst_gl_display_map = NULL;
|
|
|
|
|
|
|
|
//all glut functions and opengl primitives are called in this thread
|
|
|
|
static GThread *gst_gl_display_glutThread = NULL;
|
|
|
|
|
|
|
|
//-timepoped by glutIdleFunc
|
|
|
|
static GAsyncQueue *gst_gl_display_messageQueue = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
//---------------------- For klass GstGLDisplay ---------------
|
|
|
|
//------------------------------------------------------------
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_gl_display_base_init (gpointer g_class)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_gl_display_class_init (GstGLDisplayClass * klass)
|
2008-06-19 23:38:36 +00:00
|
|
|
{
|
2008-05-18 11:12:46 +00:00
|
|
|
G_OBJECT_CLASS (klass)->finalize = gst_gl_display_finalize;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_gl_display_init (GstGLDisplay *display, GstGLDisplayClass *klass)
|
|
|
|
{
|
2008-06-30 00:38:39 +00:00
|
|
|
//thread safe
|
2008-05-20 17:40:20 +00:00
|
|
|
display->mutex = g_mutex_new ();
|
2008-06-30 00:38:39 +00:00
|
|
|
|
|
|
|
//gl context
|
|
|
|
display->glutWinId = -1;
|
|
|
|
display->winId = 0;
|
|
|
|
display->title = g_string_new ("OpenGL renderer ");
|
|
|
|
display->win_xpos = 0;
|
|
|
|
display->win_ypos = 0;
|
|
|
|
display->visible = FALSE;
|
|
|
|
display->isAlive = TRUE;
|
2008-05-20 17:40:20 +00:00
|
|
|
display->texturePool = g_queue_new ();
|
2008-06-29 17:27:43 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
//conditions
|
2008-06-29 17:27:43 +00:00
|
|
|
display->cond_create_context = g_cond_new ();
|
|
|
|
display->cond_destroy_context = g_cond_new ();
|
|
|
|
display->cond_gen_texture = g_cond_new ();
|
|
|
|
display->cond_del_texture = g_cond_new ();
|
|
|
|
display->cond_init_upload = g_cond_new ();
|
|
|
|
display->cond_do_upload = g_cond_new ();
|
2008-06-28 23:28:11 +00:00
|
|
|
display->cond_init_download = g_cond_new ();
|
2008-06-29 17:27:43 +00:00
|
|
|
display->cond_do_download = g_cond_new ();
|
|
|
|
display->cond_gen_fbo = g_cond_new ();
|
|
|
|
display->cond_use_fbo = g_cond_new ();
|
|
|
|
display->cond_use_fbo_2 = g_cond_new ();
|
|
|
|
display->cond_del_fbo = g_cond_new ();
|
|
|
|
display->cond_gen_shader = g_cond_new ();
|
|
|
|
display->cond_del_shader = g_cond_new ();
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
//action redisplay
|
|
|
|
display->redisplay_texture = 0;
|
|
|
|
display->redisplay_texture_width = 0;
|
|
|
|
display->redisplay_texture_height = 0;
|
2008-06-07 21:56:00 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
//action resize
|
2008-06-23 18:56:29 +00:00
|
|
|
display->resize_width = 0;
|
|
|
|
display->resize_height = 0;
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
//action gen and del texture
|
|
|
|
display->gen_texture = 0;
|
|
|
|
display->del_texture = 0;
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
//client callbacks
|
2008-05-18 11:12:46 +00:00
|
|
|
display->clientReshapeCallback = NULL;
|
|
|
|
display->clientDrawCallback = NULL;
|
2008-05-20 17:40:20 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
//upload
|
|
|
|
display->upload_fbo = 0;
|
|
|
|
display->upload_depth_buffer = 0;
|
|
|
|
display->upload_texture = 0;
|
|
|
|
display->upload_width = 0;
|
|
|
|
display->upload_height = 0;
|
|
|
|
display->upload_video_format = 0;
|
2008-06-28 15:38:41 +00:00
|
|
|
display->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_GLSL;
|
2008-06-30 00:38:39 +00:00
|
|
|
display->upload_data_with = 0;
|
|
|
|
display->upload_data_height = 0;
|
|
|
|
display->upload_data = NULL;
|
|
|
|
|
|
|
|
//filter gen fbo
|
|
|
|
display->gen_fbo_width = 0;
|
|
|
|
display->gen_fbo_height = 0;
|
|
|
|
display->generated_fbo = 0;
|
|
|
|
display->generated_depth_buffer = 0;
|
|
|
|
|
|
|
|
//filter use fbo
|
|
|
|
display->use_fbo = 0;
|
|
|
|
display->use_depth_buffer = 0;
|
|
|
|
display->use_fbo_texture = 0;
|
|
|
|
display->use_fbo_width = 0;
|
|
|
|
display->use_fbo_height = 0;
|
|
|
|
display->use_fbo_scene_cb = NULL;
|
|
|
|
display->use_shader = 0;
|
|
|
|
display->use_fbo_scene_cb_2 = NULL;
|
|
|
|
display->p1 = NULL;
|
|
|
|
display->p2 = NULL;
|
|
|
|
display->input_texture_width = 0;
|
|
|
|
display->input_texture_height = 0;
|
|
|
|
display->input_texture = 0;
|
|
|
|
|
|
|
|
//filter del fbo
|
|
|
|
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_data = NULL;
|
|
|
|
display->ouput_texture = 0;
|
|
|
|
display->ouput_texture_width = 0;
|
|
|
|
display->ouput_texture_height = 0;
|
|
|
|
|
|
|
|
//action gen and del shader
|
|
|
|
display->gen_text_shader = NULL;
|
|
|
|
display->gen_handle_shader = 0;
|
|
|
|
display->del_handle_shader = 0;
|
|
|
|
|
|
|
|
//fragement shader upload
|
2008-05-20 17:40:20 +00:00
|
|
|
display->GLSLProgram_YUY2 = 0;
|
|
|
|
display->GLSLProgram_UYVY = 0;
|
|
|
|
display->GLSLProgram_I420_YV12 = 0;
|
|
|
|
display->GLSLProgram_AYUV = 0;
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
//fragement shader download
|
2008-05-18 11:12:46 +00:00
|
|
|
display->GLSLProgram_to_YUY2 = 0;
|
2008-05-20 17:40:20 +00:00
|
|
|
display->GLSLProgram_to_UYVY = 0;
|
2008-05-18 11:12:46 +00:00
|
|
|
display->GLSLProgram_to_I420_YV12 = 0;
|
|
|
|
display->GLSLProgram_to_AYUV = 0;
|
2008-05-20 17:40:20 +00:00
|
|
|
|
|
|
|
//YUY2:r,g,a
|
|
|
|
//UYVY:a,b,r
|
|
|
|
display->textFProgram_YUY2_UYVY =
|
|
|
|
"uniform sampler2DRect Ytex, UVtex;\n"
|
|
|
|
"void main(void) {\n"
|
|
|
|
" float fx, fy, y, u, v, r, g, b;\n"
|
2008-06-19 23:38:36 +00:00
|
|
|
" fx = gl_TexCoord[0].x;\n"
|
2008-05-20 17:40:20 +00:00
|
|
|
" 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"
|
|
|
|
" 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";
|
|
|
|
|
|
|
|
display->textFProgram_I420_YV12 =
|
|
|
|
"uniform sampler2DRect Ytex,Utex,Vtex;\n"
|
|
|
|
"void main(void) {\n"
|
|
|
|
" float r,g,b,y,u,v;\n"
|
|
|
|
" vec2 nxy=gl_TexCoord[0].xy;\n"
|
2008-06-24 22:28:03 +00:00
|
|
|
" y=texture2DRect(Ytex,nxy).r;\n"
|
|
|
|
" u=texture2DRect(Utex,nxy*0.5).r;\n"
|
2008-05-20 17:40:20 +00:00
|
|
|
" v=texture2DRect(Vtex,nxy*0.5).r;\n"
|
|
|
|
" y=1.1643*(y-0.0625);\n"
|
|
|
|
" u=u-0.5;\n"
|
|
|
|
" v=v-0.5;\n"
|
|
|
|
" r=y+1.5958*v;\n"
|
|
|
|
" g=y-0.39173*u-0.81290*v;\n"
|
|
|
|
" b=y+2.017*u;\n"
|
|
|
|
" gl_FragColor=vec4(r,g,b,1.0);\n"
|
|
|
|
"}\n";
|
|
|
|
|
|
|
|
display->textFProgram_AYUV =
|
|
|
|
"uniform sampler2DRect tex;\n"
|
|
|
|
"void main(void) {\n"
|
|
|
|
" float r,g,b,y,u,v;\n"
|
|
|
|
" vec2 nxy=gl_TexCoord[0].xy;\n"
|
|
|
|
" y=texture2DRect(tex,nxy).r;\n"
|
|
|
|
" u=texture2DRect(tex,nxy).g;\n"
|
|
|
|
" v=texture2DRect(tex,nxy).b;\n"
|
|
|
|
" 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";
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
//YUY2:y2,u,y1,v
|
2008-05-20 17:40:20 +00:00
|
|
|
//UYVY:v,y1,u,y2
|
2008-05-18 11:12:46 +00:00
|
|
|
display->textFProgram_to_YUY2_UYVY =
|
2008-05-20 17:40:20 +00:00
|
|
|
"uniform sampler2DRect tex;\n"
|
|
|
|
"void main(void) {\n"
|
|
|
|
" float fx,fy,r,g,b,r2,g2,b2,y1,y2,u,v;\n"
|
2008-06-19 23:38:36 +00:00
|
|
|
" fx = gl_TexCoord[0].x;\n"
|
2008-05-20 17:40:20 +00:00
|
|
|
" fy = gl_TexCoord[0].y;\n"
|
2008-05-18 11:12:46 +00:00
|
|
|
" r=texture2DRect(tex,vec2(fx*2.0,fy)).r;\n"
|
2008-05-20 17:40:20 +00:00
|
|
|
" g=texture2DRect(tex,vec2(fx*2.0,fy)).g;\n"
|
|
|
|
" b=texture2DRect(tex,vec2(fx*2.0,fy)).b;\n"
|
2008-05-18 11:12:46 +00:00
|
|
|
" r2=texture2DRect(tex,vec2(fx*2.0+1.0,fy)).r;\n"
|
2008-05-20 17:40:20 +00:00
|
|
|
" g2=texture2DRect(tex,vec2(fx*2.0+1.0,fy)).g;\n"
|
|
|
|
" b2=texture2DRect(tex,vec2(fx*2.0+1.0,fy)).b;\n"
|
2008-05-18 11:12:46 +00:00
|
|
|
" 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"
|
2008-05-20 17:40:20 +00:00
|
|
|
" u=u + 0.5;\n"
|
|
|
|
" v=v + 0.5;\n"
|
2008-05-18 11:12:46 +00:00
|
|
|
" gl_FragColor=vec4(%s);\n"
|
2008-05-20 17:40:20 +00:00
|
|
|
"}\n";
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
display->textFProgram_to_I420_YV12 =
|
|
|
|
"uniform sampler2DRect tex;\n"
|
|
|
|
"uniform float w, h;\n"
|
2008-05-20 17:40:20 +00:00
|
|
|
"void main(void) {\n"
|
|
|
|
" float r,g,b,r2,b2,g2,y,u,v;\n"
|
|
|
|
" vec2 nxy=gl_TexCoord[0].xy;\n"
|
2008-05-18 11:12:46 +00:00
|
|
|
" vec2 nxy2=mod(2.0*nxy, vec2(w, h));\n"
|
|
|
|
" r=texture2DRect(tex,nxy).r;\n"
|
2008-05-20 17:40:20 +00:00
|
|
|
" g=texture2DRect(tex,nxy).g;\n"
|
|
|
|
" b=texture2DRect(tex,nxy).b;\n"
|
2008-05-18 11:12:46 +00:00
|
|
|
" r2=texture2DRect(tex,nxy2).r;\n"
|
2008-05-20 17:40:20 +00:00
|
|
|
" g2=texture2DRect(tex,nxy2).g;\n"
|
|
|
|
" b2=texture2DRect(tex,nxy2).b;\n"
|
2008-05-18 11:12:46 +00:00
|
|
|
" 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"
|
2008-05-20 17:40:20 +00:00
|
|
|
" u=u + 0.5;\n"
|
|
|
|
" v=v + 0.5;\n"
|
|
|
|
" gl_FragData[0] = vec4(y, 0.0, 0.0, 1.0);\n"
|
2008-05-18 11:12:46 +00:00
|
|
|
" gl_FragData[1] = vec4(u, 0.0, 0.0, 1.0);\n"
|
|
|
|
" gl_FragData[2] = vec4(v, 0.0, 0.0, 1.0);\n"
|
2008-05-20 17:40:20 +00:00
|
|
|
"}\n";
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
display->textFProgram_to_AYUV =
|
2008-05-20 17:40:20 +00:00
|
|
|
"uniform sampler2DRect tex;\n"
|
|
|
|
"void main(void) {\n"
|
|
|
|
" float r,g,b,y,u,v;\n"
|
|
|
|
" vec2 nxy=gl_TexCoord[0].xy;\n"
|
|
|
|
" r=texture2DRect(tex,nxy).r;\n"
|
|
|
|
" g=texture2DRect(tex,nxy).g;\n"
|
|
|
|
" b=texture2DRect(tex,nxy).b;\n"
|
2008-05-18 11:12:46 +00:00
|
|
|
" 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"
|
2008-05-20 17:40:20 +00:00
|
|
|
" u=u + 0.5;\n"
|
|
|
|
" v=v + 0.5;\n"
|
|
|
|
" gl_FragColor=vec4(y,u,v,1.0);\n"
|
|
|
|
"}\n";
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_gl_display_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
GstGLDisplay *display = GST_GL_DISPLAY (object);
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
//request glut window destruction
|
|
|
|
//blocking call because display must be alive
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_DESTROY_CONTEXT, display);
|
|
|
|
g_cond_wait (display->cond_destroy_context, display->mutex);
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
|
|
|
|
if (display->texturePool) {
|
|
|
|
g_queue_free (display->texturePool);
|
|
|
|
display->texturePool = NULL;
|
2008-06-19 23:38:36 +00:00
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
if (display->title) {
|
|
|
|
g_string_free (display->title, TRUE);
|
|
|
|
display->title = NULL;
|
2008-06-19 23:38:36 +00:00
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
if (display->mutex) {
|
|
|
|
g_mutex_free (display->mutex);
|
|
|
|
display->mutex = NULL;
|
|
|
|
}
|
2008-06-29 17:27:43 +00:00
|
|
|
if (display->cond_del_shader) {
|
|
|
|
g_cond_free (display->cond_del_shader);
|
|
|
|
display->cond_del_shader = NULL;
|
|
|
|
}
|
|
|
|
if (display->cond_gen_shader) {
|
|
|
|
g_cond_free (display->cond_gen_shader);
|
|
|
|
display->cond_gen_shader = NULL;
|
2008-06-28 15:38:41 +00:00
|
|
|
}
|
2008-06-29 17:27:43 +00:00
|
|
|
if (display->cond_del_fbo) {
|
|
|
|
g_cond_free (display->cond_del_fbo);
|
|
|
|
display->cond_del_fbo = NULL;
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
2008-06-29 17:27:43 +00:00
|
|
|
if (display->cond_use_fbo_2) {
|
|
|
|
g_cond_free (display->cond_use_fbo_2);
|
|
|
|
display->cond_use_fbo_2 = NULL;
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
2008-06-29 17:27:43 +00:00
|
|
|
if (display->cond_use_fbo) {
|
|
|
|
g_cond_free (display->cond_use_fbo);
|
|
|
|
display->cond_use_fbo = NULL;
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
2008-06-29 17:27:43 +00:00
|
|
|
if (display->cond_gen_fbo) {
|
|
|
|
g_cond_free (display->cond_gen_fbo);
|
|
|
|
display->cond_gen_fbo = NULL;
|
|
|
|
}
|
|
|
|
if (display->cond_do_download) {
|
|
|
|
g_cond_free (display->cond_do_download);
|
|
|
|
display->cond_do_download = NULL;
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
2008-06-28 23:28:11 +00:00
|
|
|
if (display->cond_init_download) {
|
|
|
|
g_cond_free (display->cond_init_download);
|
|
|
|
display->cond_init_download = NULL;
|
2008-06-10 19:07:43 +00:00
|
|
|
}
|
2008-06-29 17:27:43 +00:00
|
|
|
if (display->cond_do_upload) {
|
|
|
|
g_cond_free (display->cond_do_upload);
|
|
|
|
display->cond_do_upload = NULL;
|
2008-06-13 00:01:26 +00:00
|
|
|
}
|
2008-06-29 17:27:43 +00:00
|
|
|
if (display->cond_init_upload) {
|
|
|
|
g_cond_free (display->cond_init_upload);
|
|
|
|
display->cond_init_upload = NULL;
|
2008-06-07 15:27:12 +00:00
|
|
|
}
|
2008-06-29 17:27:43 +00:00
|
|
|
if (display->cond_del_texture) {
|
|
|
|
g_cond_free (display->cond_del_texture);
|
|
|
|
display->cond_del_texture = NULL;
|
2008-06-11 23:04:52 +00:00
|
|
|
}
|
2008-06-29 17:27:43 +00:00
|
|
|
if (display->cond_gen_texture) {
|
|
|
|
g_cond_free (display->cond_gen_texture);
|
|
|
|
display->cond_gen_texture = NULL;
|
2008-06-07 15:27:12 +00:00
|
|
|
}
|
2008-06-29 17:27:43 +00:00
|
|
|
if (display->cond_destroy_context) {
|
|
|
|
g_cond_free (display->cond_destroy_context);
|
|
|
|
display->cond_destroy_context = NULL;
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
2008-06-29 17:27:43 +00:00
|
|
|
if (display->cond_create_context) {
|
|
|
|
g_cond_free (display->cond_create_context);
|
|
|
|
display->cond_create_context = NULL;
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
if (display->clientReshapeCallback)
|
|
|
|
display->clientReshapeCallback = NULL;
|
|
|
|
if (display->clientDrawCallback)
|
|
|
|
display->clientDrawCallback = NULL;
|
2008-06-30 00:38:39 +00:00
|
|
|
if (display->use_fbo_scene_cb)
|
|
|
|
display->use_fbo_scene_cb = NULL;
|
|
|
|
if (display->use_fbo_scene_cb_2)
|
|
|
|
display->use_fbo_scene_cb_2 = NULL;
|
2008-06-11 23:04:52 +00:00
|
|
|
if (display->p1)
|
|
|
|
display->p1 = NULL;
|
|
|
|
if (display->p2)
|
|
|
|
display->p2 = NULL;
|
2008-06-19 23:38:36 +00:00
|
|
|
|
|
|
|
//at this step, the next condition imply that the last display has been pushed
|
2008-05-18 11:12:46 +00:00
|
|
|
if (g_hash_table_size (gst_gl_display_map) == 0)
|
|
|
|
{
|
|
|
|
g_thread_join (gst_gl_display_glutThread);
|
2008-06-29 17:27:43 +00:00
|
|
|
g_print ("gl thread joined\n");
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_glutThread = NULL;
|
|
|
|
g_async_queue_unref (gst_gl_display_messageQueue);
|
|
|
|
g_hash_table_unref (gst_gl_display_map);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
//------------------------------------------------------------
|
|
|
|
//----------------- BEGIN GL THREAD LOOP ---------------------
|
|
|
|
//------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
/* The gl thread handles GstGLDisplayMsg messages
|
|
|
|
* Every OpenGL code lines are called in the gl thread */
|
2008-05-18 11:12:46 +00:00
|
|
|
static gpointer
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_func (GstGLDisplay *display)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-05-19 21:36:59 +00:00
|
|
|
static char *argv = "gst-launch-0.10";
|
2008-06-19 23:38:36 +00:00
|
|
|
static gint argc = 1;
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-05-19 21:36:59 +00:00
|
|
|
//-display DISPLAY
|
|
|
|
//Specify the X server to connect to. If not specified, the value of the DISPLAY environment variable is used.
|
|
|
|
//Should be pass through a glimagesink property
|
2008-05-18 11:12:46 +00:00
|
|
|
glutInit(&argc, &argv);
|
|
|
|
glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION);
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
glutIdleFunc (gst_gl_display_thread_loop);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_create_context (display);
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
|
2008-06-28 15:38:41 +00:00
|
|
|
g_print ("gl mainLoop started\n");
|
2008-05-18 11:12:46 +00:00
|
|
|
glutMainLoop ();
|
2008-06-28 15:38:41 +00:00
|
|
|
g_print ("gl mainLoop exited\n");
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called in the gl thread */
|
|
|
|
static void
|
|
|
|
gst_gl_display_thread_loop (void)
|
|
|
|
{
|
|
|
|
GTimeVal timeout;
|
|
|
|
GstGLDisplayMsg *msg;
|
|
|
|
|
|
|
|
//check for pending actions that require a glut context
|
|
|
|
g_get_current_time (&timeout);
|
|
|
|
g_time_val_add (&timeout, 1000000L); //timeout 1 sec
|
|
|
|
msg = g_async_queue_timed_pop (gst_gl_display_messageQueue, &timeout);
|
|
|
|
if (msg)
|
|
|
|
{
|
|
|
|
if (gst_gl_display_thread_check_msg_validity (msg))
|
|
|
|
gst_gl_display_thread_dispatch_action (msg);
|
|
|
|
while (g_async_queue_length (gst_gl_display_messageQueue))
|
|
|
|
{
|
|
|
|
msg = g_async_queue_pop (gst_gl_display_messageQueue);
|
|
|
|
if (gst_gl_display_thread_check_msg_validity (msg))
|
|
|
|
gst_gl_display_thread_dispatch_action (msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else g_print ("timeout reached in idle func\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called in the gl thread loop */
|
|
|
|
static void
|
|
|
|
gst_gl_display_thread_dispatch_action (GstGLDisplayMsg* msg)
|
|
|
|
{
|
|
|
|
gst_gl_display_lock (msg->display);
|
|
|
|
switch (msg->action)
|
|
|
|
{
|
|
|
|
case GST_GL_DISPLAY_ACTION_CREATE_CONTEXT:
|
|
|
|
gst_gl_display_thread_create_context (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_DESTROY_CONTEXT:
|
|
|
|
gst_gl_display_thread_destroy_context (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_VISIBLE_CONTEXT:
|
|
|
|
gst_gl_display_thread_set_visible_context (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_RESIZE_CONTEXT:
|
|
|
|
gst_gl_display_thread_resize_context (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_REDISPLAY_CONTEXT:
|
|
|
|
gst_gl_display_thread_redisplay (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_GEN_TEXTURE:
|
|
|
|
gst_gl_display_thread_gen_texture (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_DEL_TEXTURE:
|
|
|
|
gst_gl_display_thread_del_texture (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_INIT_UPLOAD:
|
|
|
|
gst_gl_display_thread_init_upload (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_DO_UPLOAD:
|
|
|
|
gst_gl_display_thread_do_upload (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_INIT_DOWNLOAD:
|
|
|
|
gst_gl_display_thread_init_download (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_DO_DOWNLOAD:
|
|
|
|
gst_gl_display_thread_do_download (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_GEN_FBO:
|
|
|
|
gst_gl_display_thread_gen_fbo (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_USE_FBO:
|
|
|
|
gst_gl_display_thread_use_fbo (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_USE_FBO2:
|
|
|
|
gst_gl_display_thread_use_fbo_2 (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_DEL_FBO:
|
|
|
|
gst_gl_display_thread_del_fbo (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_GEN_SHADER:
|
|
|
|
gst_gl_display_thread_gen_shader (msg->display);
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_DEL_SHADER:
|
|
|
|
gst_gl_display_thread_del_shader (msg->display);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
gst_gl_display_unlock (msg->display);
|
|
|
|
g_free (msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called in the gl thread loop
|
|
|
|
* Return false if the message is out of date */
|
|
|
|
static gboolean
|
|
|
|
gst_gl_display_thread_check_msg_validity (GstGLDisplayMsg *msg)
|
|
|
|
{
|
|
|
|
gboolean valid = TRUE;
|
|
|
|
|
|
|
|
switch (msg->action)
|
|
|
|
{
|
|
|
|
case GST_GL_DISPLAY_ACTION_CREATE_CONTEXT:
|
|
|
|
valid = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_GL_DISPLAY_ACTION_DESTROY_CONTEXT:
|
|
|
|
case GST_GL_DISPLAY_ACTION_VISIBLE_CONTEXT:
|
|
|
|
case GST_GL_DISPLAY_ACTION_RESIZE_CONTEXT:
|
|
|
|
case GST_GL_DISPLAY_ACTION_REDISPLAY_CONTEXT:
|
|
|
|
case GST_GL_DISPLAY_ACTION_GEN_TEXTURE:
|
|
|
|
case GST_GL_DISPLAY_ACTION_DEL_TEXTURE:
|
|
|
|
case GST_GL_DISPLAY_ACTION_INIT_UPLOAD:
|
|
|
|
case GST_GL_DISPLAY_ACTION_DO_UPLOAD:
|
|
|
|
case GST_GL_DISPLAY_ACTION_INIT_DOWNLOAD:
|
|
|
|
case GST_GL_DISPLAY_ACTION_DO_DOWNLOAD:
|
|
|
|
case GST_GL_DISPLAY_ACTION_GEN_FBO:
|
|
|
|
case GST_GL_DISPLAY_ACTION_USE_FBO:
|
|
|
|
case GST_GL_DISPLAY_ACTION_USE_FBO2:
|
|
|
|
case GST_GL_DISPLAY_ACTION_DEL_FBO:
|
|
|
|
case GST_GL_DISPLAY_ACTION_GEN_SHADER:
|
|
|
|
case GST_GL_DISPLAY_ACTION_DEL_SHADER:
|
|
|
|
//msg is out of date if the associated display is not in the map
|
|
|
|
if (!g_hash_table_lookup (gst_gl_display_map, GINT_TO_POINTER (msg->glutWinId)))
|
|
|
|
valid = FALSE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
return valid;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
//------------------ END GL THREAD LOOP ----------------------
|
|
|
|
//------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
//------------------ BEGIN GL THREAD ACTIONS -----------------
|
|
|
|
//------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
/* Called in the gl thread */
|
2008-05-18 11:12:46 +00:00
|
|
|
static void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_create_context (GstGLDisplay *display)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
|
|
|
gint glutWinId = 0;
|
|
|
|
gchar buffer[5];
|
2008-05-18 19:18:04 +00:00
|
|
|
GLenum err = 0;
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
//prepare opengl context
|
2008-05-18 19:18:04 +00:00
|
|
|
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
|
2008-05-18 11:12:46 +00:00
|
|
|
glutInitWindowPosition(display->win_xpos, display->win_ypos);
|
2008-06-30 00:38:39 +00:00
|
|
|
glutInitWindowSize(display->upload_width, display->upload_height);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
//create opengl context
|
2008-05-18 19:18:04 +00:00
|
|
|
sprintf(buffer, "%d", glutWinId);
|
2008-05-19 16:57:39 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
display->title = g_string_append (display->title, buffer);
|
|
|
|
glutWinId = glutCreateWindow (display->title->str, display->winId);
|
|
|
|
|
2008-06-07 00:01:18 +00:00
|
|
|
g_print ("Context %d created\n", glutWinId);
|
2008-05-21 21:15:47 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
if (display->visible)
|
|
|
|
glutShowWindow ();
|
|
|
|
else
|
|
|
|
glutHideWindow ();
|
|
|
|
|
2008-05-18 19:18:04 +00:00
|
|
|
//Init glew
|
2008-05-18 11:12:46 +00:00
|
|
|
err = glewInit();
|
|
|
|
if (err != GLEW_OK)
|
2008-06-28 15:38:41 +00:00
|
|
|
{
|
2008-05-20 17:40:20 +00:00
|
|
|
GST_DEBUG ("Error: %s", glewGetErrorString(err));
|
2008-06-28 15:38:41 +00:00
|
|
|
display->isAlive = FALSE;
|
|
|
|
}
|
2008-05-18 19:18:04 +00:00
|
|
|
else
|
2008-05-21 21:15:47 +00:00
|
|
|
{
|
|
|
|
//OpenGL > 2.1.0 and Glew > 1.5.0
|
2008-06-15 18:31:12 +00:00
|
|
|
GString* opengl_version = g_string_truncate (g_string_new ((gchar*) glGetString (GL_VERSION)), 3);
|
2008-06-21 21:38:42 +00:00
|
|
|
gint opengl_version_major = 0;
|
2008-06-19 23:38:36 +00:00
|
|
|
gint opengl_version_minor = 0;
|
2008-06-15 18:31:12 +00:00
|
|
|
GString* glew_version = g_string_truncate (g_string_new ((gchar*) glewGetString (GLEW_VERSION)), 3);
|
2008-06-21 21:38:42 +00:00
|
|
|
gint glew_version_major = 0;
|
2008-06-19 23:38:36 +00:00
|
|
|
gint glew_version_minor = 0;
|
|
|
|
|
|
|
|
sscanf(opengl_version->str, "%d.%d", &opengl_version_major, &opengl_version_minor);
|
|
|
|
sscanf(glew_version->str, "%d.%d", &glew_version_major, &glew_version_minor);
|
2008-05-21 21:15:47 +00:00
|
|
|
|
2008-06-19 23:38:36 +00:00
|
|
|
g_print ("GL_VERSION: %s\n", glGetString (GL_VERSION));
|
|
|
|
g_print ("GLEW_VERSION: %s\n", glewGetString (GLEW_VERSION));
|
2008-05-21 21:15:47 +00:00
|
|
|
|
2008-06-19 23:38:36 +00:00
|
|
|
g_print ("GL_VENDOR: %s\n", glGetString (GL_VENDOR));
|
|
|
|
g_print ("GL_RENDERER: %s\n", glGetString (GL_RENDERER));
|
2008-05-21 21:15:47 +00:00
|
|
|
|
|
|
|
g_string_free (opengl_version, TRUE);
|
|
|
|
g_string_free (glew_version, TRUE);
|
|
|
|
|
2008-06-28 15:38:41 +00:00
|
|
|
if ((opengl_version_major < 1 && opengl_version_minor < 4) ||
|
|
|
|
(glew_version_major < 1 && glew_version_minor < 4) )
|
2008-05-21 21:15:47 +00:00
|
|
|
{
|
2008-06-28 15:38:41 +00:00
|
|
|
//turn off the pipeline, the old drivers are not yet supported
|
2008-06-19 23:38:36 +00:00
|
|
|
g_print ("Required OpenGL >= 1.4.0 and Glew >= 1.4.0\n");
|
2008-06-28 15:38:41 +00:00
|
|
|
display->isAlive = FALSE;
|
2008-05-21 21:15:47 +00:00
|
|
|
}
|
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-28 15:38:41 +00:00
|
|
|
//setup callbacks
|
2008-06-29 17:27:43 +00:00
|
|
|
glutReshapeFunc (gst_gl_display_on_resize);
|
|
|
|
glutDisplayFunc (gst_gl_display_on_draw);
|
|
|
|
glutCloseFunc (gst_gl_display_on_close);
|
2008-06-28 15:38:41 +00:00
|
|
|
|
|
|
|
//insert glut context to the map
|
|
|
|
display->glutWinId = glutWinId;
|
|
|
|
g_hash_table_insert (gst_gl_display_map, GUINT_TO_POINTER (glutWinId), display);
|
|
|
|
|
|
|
|
//check glut id validity
|
|
|
|
g_assert (glutGetWindow() == glutWinId);
|
|
|
|
GST_DEBUG ("Context %d initialized", display->glutWinId);
|
|
|
|
|
|
|
|
//release display constructor
|
2008-06-29 17:27:43 +00:00
|
|
|
g_cond_signal (display->cond_create_context);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called in the gl thread */
|
|
|
|
static void
|
|
|
|
gst_gl_display_thread_destroy_context (GstGLDisplay *display)
|
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
|
|
|
glutReshapeFunc (NULL);
|
|
|
|
glutDestroyWindow (display->glutWinId);
|
|
|
|
glUseProgramObjectARB (0);
|
|
|
|
|
|
|
|
glDeleteObjectARB (display->GLSLProgram_YUY2);
|
|
|
|
glDeleteObjectARB (display->GLSLProgram_UYVY);
|
|
|
|
glDeleteObjectARB (display->GLSLProgram_I420_YV12);
|
|
|
|
glDeleteObjectARB (display->GLSLProgram_AYUV);
|
|
|
|
|
|
|
|
glDeleteObjectARB (display->GLSLProgram_to_YUY2);
|
|
|
|
glDeleteObjectARB (display->GLSLProgram_to_UYVY);
|
|
|
|
glDeleteObjectARB (display->GLSLProgram_to_I420_YV12);
|
|
|
|
glDeleteObjectARB (display->GLSLProgram_to_AYUV);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glDeleteFramebuffersEXT (1, &display->upload_fbo);
|
|
|
|
glDeleteRenderbuffersEXT(1, &display->upload_depth_buffer);
|
2008-06-29 17:27:43 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glDeleteFramebuffersEXT (1, &display->download_fbo);
|
|
|
|
glDeleteRenderbuffersEXT(1, &display->download_depth_buffer);
|
|
|
|
glDeleteTextures (1, &display->download_texture);
|
|
|
|
glDeleteTextures (1, &display->download_texture_u);
|
|
|
|
glDeleteTextures (1, &display->download_texture_v);
|
2008-06-29 17:27:43 +00:00
|
|
|
|
|
|
|
//clean up the texture pool
|
|
|
|
while (g_queue_get_length (display->texturePool))
|
|
|
|
{
|
|
|
|
GstGLDisplayTex* tex = g_queue_pop_head (display->texturePool);
|
|
|
|
glDeleteTextures (1, &tex->texture);
|
|
|
|
g_free (tex);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_hash_table_remove (gst_gl_display_map, GINT_TO_POINTER (display->glutWinId));
|
|
|
|
g_print ("Context %d destroyed\n", display->glutWinId);
|
|
|
|
|
|
|
|
//if the map is empty, leaveMainloop and join the thread
|
|
|
|
if (g_hash_table_size (gst_gl_display_map) == 0)
|
|
|
|
glutLeaveMainLoop ();
|
|
|
|
|
|
|
|
//release display destructor
|
|
|
|
g_cond_signal (display->cond_destroy_context);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called in the gl thread */
|
|
|
|
static void
|
|
|
|
gst_gl_display_thread_set_visible_context (GstGLDisplay *display)
|
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
|
|
|
if (display->visible)
|
|
|
|
glutShowWindow ();
|
|
|
|
else
|
|
|
|
glutHideWindow ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called by the idle function */
|
|
|
|
static void
|
|
|
|
gst_gl_display_thread_resize_context (GstGLDisplay* display)
|
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
|
|
|
glutReshapeWindow (display->resize_width, display->resize_height);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called in the gl thread */
|
|
|
|
static void
|
|
|
|
gst_gl_display_thread_redisplay (GstGLDisplay * display)
|
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
|
|
|
glutPostRedisplay ();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called in the gl thread */
|
|
|
|
static void
|
|
|
|
gst_gl_display_thread_gen_texture (GstGLDisplay * display)
|
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
|
|
|
//setup a texture to render to (this one will be in a gl buffer)
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_glgen_texture (display, &display->gen_texture);
|
2008-06-29 17:27:43 +00:00
|
|
|
g_cond_signal (display->cond_gen_texture);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called in the gl thread */
|
|
|
|
static void
|
|
|
|
gst_gl_display_thread_del_texture (GstGLDisplay* display)
|
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_gldel_texture (display, &display->del_texture);
|
2008-06-29 17:27:43 +00:00
|
|
|
g_cond_signal (display->cond_del_texture);
|
2008-06-28 15:38:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called in the gl thread */
|
|
|
|
static void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_init_upload (GstGLDisplay *display)
|
2008-06-28 15:38:41 +00:00
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
|
|
|
|
|
|
|
//Frame buffer object is a requirement for every cases
|
2008-05-18 11:12:46 +00:00
|
|
|
if (GLEW_EXT_framebuffer_object)
|
|
|
|
{
|
2008-06-21 21:38:42 +00:00
|
|
|
//a texture must be attached to the FBO
|
|
|
|
guint fake_texture = 0;
|
2008-06-24 22:28:03 +00:00
|
|
|
|
2008-06-28 15:38:41 +00:00
|
|
|
g_print ("Context %d, EXT_framebuffer_object supported: yes\n", display->glutWinId);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
//-- init intput frame buffer object (video -> GL)
|
2008-05-20 17:40:20 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
//setup FBO
|
2008-06-30 00:38:39 +00:00
|
|
|
glGenFramebuffersEXT (1, &display->upload_fbo);
|
|
|
|
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->upload_fbo);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-19 23:38:36 +00:00
|
|
|
//setup the render buffer for depth
|
2008-06-30 00:38:39 +00:00
|
|
|
glGenRenderbuffersEXT(1, &display->upload_depth_buffer);
|
|
|
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, display->upload_depth_buffer);
|
2008-05-18 19:18:04 +00:00
|
|
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->upload_width, display->upload_height);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-28 15:38:41 +00:00
|
|
|
//a fake texture is attached to the upload FBO (cannot init without it)
|
2008-06-21 21:38:42 +00:00
|
|
|
glGenTextures (1, &fake_texture);
|
|
|
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fake_texture);
|
2008-06-19 23:38:36 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->upload_width, display->upload_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
//attach the texture to the FBO to renderer to
|
2008-06-19 23:38:36 +00:00
|
|
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
2008-06-21 21:38:42 +00:00
|
|
|
GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
//attach the depth render buffer to the FBO
|
2008-06-19 23:38:36 +00:00
|
|
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
2008-06-30 00:38:39 +00:00
|
|
|
GL_RENDERBUFFER_EXT, display->upload_depth_buffer);
|
2008-05-20 17:40:20 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_check_framebuffer_status();
|
2008-06-24 22:28:03 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
|
|
|
|
GL_FRAMEBUFFER_COMPLETE_EXT);
|
|
|
|
|
|
|
|
//unbind the FBO
|
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
|
|
|
2008-06-21 21:38:42 +00:00
|
|
|
glDeleteTextures (1, &fake_texture);
|
2008-06-10 19:07:43 +00:00
|
|
|
}
|
2008-06-19 23:38:36 +00:00
|
|
|
else
|
2008-06-10 19:07:43 +00:00
|
|
|
{
|
2008-06-28 15:38:41 +00:00
|
|
|
//turn off the pipeline because Frame buffer object is a requirement
|
|
|
|
g_print ("Context %d, EXT_framebuffer_object supported: no\n", display->glutWinId);
|
|
|
|
display->isAlive = FALSE;
|
2008-06-10 19:07:43 +00:00
|
|
|
}
|
|
|
|
|
2008-06-28 15:38:41 +00:00
|
|
|
switch (display->upload_video_format)
|
2008-06-10 19:07:43 +00:00
|
|
|
{
|
2008-06-28 15:38:41 +00:00
|
|
|
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
|
|
|
|
if (GLEW_ARB_fragment_shader)
|
|
|
|
{
|
|
|
|
g_print ("Context %d, ARB_fragment_shader supported: yes\n", display->glutWinId);
|
|
|
|
|
|
|
|
display->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_GLSL;
|
|
|
|
|
|
|
|
switch (display->upload_video_format)
|
|
|
|
{
|
|
|
|
case GST_VIDEO_FORMAT_YUY2:
|
|
|
|
{
|
|
|
|
gchar program[2048];
|
|
|
|
sprintf (program, display->textFProgram_YUY2_UYVY, 'r', 'g', 'a');
|
2008-06-29 17:27:43 +00:00
|
|
|
display->GLSLProgram_YUY2 = gst_gl_display_load_fragment_shader (program);
|
2008-06-28 15:38:41 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_UYVY:
|
|
|
|
{
|
|
|
|
gchar program[2048];
|
|
|
|
sprintf (program, display->textFProgram_YUY2_UYVY, 'a', 'b', 'r');
|
2008-06-29 17:27:43 +00:00
|
|
|
display->GLSLProgram_UYVY = gst_gl_display_load_fragment_shader (program);
|
2008-06-28 15:38:41 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_I420:
|
|
|
|
case GST_VIDEO_FORMAT_YV12:
|
2008-06-29 17:27:43 +00:00
|
|
|
display->GLSLProgram_I420_YV12 = gst_gl_display_load_fragment_shader (display->textFProgram_I420_YV12);
|
2008-06-28 15:38:41 +00:00
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_AYUV:
|
2008-06-29 17:27:43 +00:00
|
|
|
display->GLSLProgram_AYUV = gst_gl_display_load_fragment_shader (display->textFProgram_AYUV);
|
2008-06-28 15:38:41 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//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
|
|
|
|
g_print ("Context %d, ARB_fragment_shader supported: no\n", display->glutWinId);
|
|
|
|
g_print ("Context %d, GLEW_ARB_imaging supported: no\n", display->glutWinId);
|
|
|
|
g_print ("Context %d, GLEW_MESA_ycbcr_texture supported: yes\n", display->glutWinId);
|
|
|
|
|
|
|
|
display->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_MESA;
|
|
|
|
|
|
|
|
switch (display->upload_video_format)
|
|
|
|
{
|
|
|
|
case GST_VIDEO_FORMAT_YUY2:
|
|
|
|
case GST_VIDEO_FORMAT_UYVY:
|
|
|
|
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
|
|
|
|
display->isAlive = FALSE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//check if color matrix is available
|
|
|
|
else if (GLEW_ARB_imaging)
|
|
|
|
{
|
|
|
|
//GLSL is not available on your drivers, switch to Color Matrix
|
|
|
|
g_print ("Context %d, ARB_fragment_shader supported: no\n", display->glutWinId);
|
|
|
|
g_print ("Context %d, GLEW_ARB_imaging supported: yes\n", display->glutWinId);
|
|
|
|
|
|
|
|
display->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_MATRIX;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_print ("Context %d, ARB_fragment_shader supported: no\n", display->glutWinId);
|
|
|
|
g_print ("Context %d, GLEW_ARB_imaging supported: no\n", display->glutWinId);
|
|
|
|
g_print ("Context %d, GLEW_MESA_ycbcr_texture supported: no\n", display->glutWinId);
|
|
|
|
|
|
|
|
//turn off the pipeline because colorspace conversion is not possible
|
|
|
|
display->isAlive = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2008-06-10 19:07:43 +00:00
|
|
|
}
|
|
|
|
|
2008-06-28 15:38:41 +00:00
|
|
|
g_cond_signal (display->cond_init_upload);
|
2008-06-10 19:07:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by the idle function */
|
|
|
|
static void
|
|
|
|
gst_gl_display_thread_do_upload (GstGLDisplay * display)
|
|
|
|
{
|
2008-06-30 00:38:39 +00:00
|
|
|
GLuint texture = 0;
|
|
|
|
GLuint texture_u = 0;
|
|
|
|
GLuint texture_v = 0;
|
|
|
|
GstVideoFormat video_format = 0;
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
glutSetWindow (display->glutWinId);
|
2008-06-30 00:38:39 +00:00
|
|
|
|
|
|
|
gst_gl_display_thread_do_upload_make (display, &texture, &texture_u, &texture_v);
|
|
|
|
gst_gl_display_thread_do_upload_fill (display, &texture, &texture_u, &texture_v,
|
|
|
|
&video_format);
|
|
|
|
gst_gl_display_thread_do_upload_draw (display, texture, texture_u, texture_v,
|
|
|
|
video_format);
|
|
|
|
|
|
|
|
gst_gl_display_gldel_texture (display, &texture);
|
|
|
|
if (texture_u)
|
|
|
|
gst_gl_display_gldel_texture (display, &texture_u);
|
|
|
|
if (texture_v)
|
|
|
|
gst_gl_display_gldel_texture (display, &texture_v);
|
2008-06-29 17:27:43 +00:00
|
|
|
g_cond_signal (display->cond_do_upload);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called in the gl thread */
|
2008-06-10 19:07:43 +00:00
|
|
|
static void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_init_download (GstGLDisplay *display)
|
2008-06-10 19:07:43 +00:00
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-06-10 19:07:43 +00:00
|
|
|
if (GLEW_EXT_framebuffer_object)
|
|
|
|
{
|
|
|
|
GST_DEBUG ("Context %d, EXT_framebuffer_object supported: yes", display->glutWinId);
|
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
//-- init output frame buffer object (GL -> video)
|
|
|
|
|
|
|
|
//setup FBO
|
2008-06-30 00:38:39 +00:00
|
|
|
glGenFramebuffersEXT (1, &display->download_fbo);
|
|
|
|
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->download_fbo);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-19 23:38:36 +00:00
|
|
|
//setup the render buffer for depth
|
2008-06-30 00:38:39 +00:00
|
|
|
glGenRenderbuffersEXT(1, &display->download_depth_buffer);
|
|
|
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, display->download_depth_buffer);
|
2008-06-19 23:38:36 +00:00
|
|
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->download_width, display->download_height);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
//setup a first texture to render to
|
2008-06-30 00:38:39 +00:00
|
|
|
glGenTextures (1, &display->download_texture);
|
|
|
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->download_texture);
|
2008-06-19 23:38:36 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->download_width, display->download_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2008-05-18 11:12:46 +00:00
|
|
|
glTexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
2008-05-20 17:40:20 +00:00
|
|
|
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);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
//attach the first texture to the FBO to renderer to
|
2008-06-19 23:38:36 +00:00
|
|
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
2008-06-30 00:38:39 +00:00
|
|
|
GL_TEXTURE_RECTANGLE_ARB, display->download_texture, 0);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
switch (display->download_video_format)
|
2008-06-28 23:28:11 +00:00
|
|
|
{
|
|
|
|
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:
|
|
|
|
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
|
2008-06-30 00:38:39 +00:00
|
|
|
glGenTextures (1, &display->download_texture_u);
|
|
|
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->download_texture_u);
|
2008-06-28 23:28:11 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->download_width, display->download_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2008-06-28 23:28:11 +00:00
|
|
|
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,
|
2008-06-30 00:38:39 +00:00
|
|
|
GL_TEXTURE_RECTANGLE_ARB, display->download_texture_u, 0);
|
2008-06-28 23:28:11 +00:00
|
|
|
|
|
|
|
//setup a third texture to render to
|
2008-06-30 00:38:39 +00:00
|
|
|
glGenTextures (1, &display->download_texture_v);
|
|
|
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->download_texture_v);
|
2008-06-28 23:28:11 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->download_width, display->download_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2008-06-28 23:28:11 +00:00
|
|
|
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,
|
2008-06-30 00:38:39 +00:00
|
|
|
GL_TEXTURE_RECTANGLE_ARB, display->download_texture_v, 0);
|
2008-06-28 23:28:11 +00:00
|
|
|
|
|
|
|
display->multipleRT[0] = GL_COLOR_ATTACHMENT0_EXT;
|
|
|
|
display->multipleRT[1] = GL_COLOR_ATTACHMENT1_EXT;
|
|
|
|
display->multipleRT[2] = GL_COLOR_ATTACHMENT2_EXT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
//attach the depth render buffer to the FBO
|
2008-06-19 23:38:36 +00:00
|
|
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
2008-06-30 00:38:39 +00:00
|
|
|
GL_RENDERBUFFER_EXT, display->download_depth_buffer);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_check_framebuffer_status();
|
2008-05-20 17:40:20 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
|
|
|
|
GL_FRAMEBUFFER_COMPLETE_EXT);
|
|
|
|
|
|
|
|
//unbind the FBO
|
2008-06-28 23:28:11 +00:00
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
2008-06-19 23:38:36 +00:00
|
|
|
else
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-28 23:28:11 +00:00
|
|
|
//turn off the pipeline because Frame buffer object is a requirement
|
|
|
|
g_print ("Context %d, EXT_framebuffer_object supported: no\n", display->glutWinId);
|
|
|
|
display->isAlive = FALSE;
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
switch (display->download_video_format)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-28 23:28:11 +00:00
|
|
|
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
|
|
|
|
//GLSL is a requirement for donwload
|
|
|
|
if (GLEW_ARB_fragment_shader)
|
|
|
|
{
|
2008-06-30 00:38:39 +00:00
|
|
|
switch (display->download_video_format)
|
2008-06-28 23:28:11 +00:00
|
|
|
{
|
|
|
|
case GST_VIDEO_FORMAT_YUY2:
|
|
|
|
{
|
|
|
|
gchar program[2048];
|
|
|
|
sprintf (program, display->textFProgram_to_YUY2_UYVY, "y2,u,y1,v");
|
2008-06-29 17:27:43 +00:00
|
|
|
display->GLSLProgram_to_YUY2 = gst_gl_display_load_fragment_shader (program);
|
2008-06-28 23:28:11 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_UYVY:
|
|
|
|
{
|
|
|
|
gchar program[2048];
|
|
|
|
sprintf (program, display->textFProgram_to_YUY2_UYVY, "v,y1,u,y2");
|
2008-06-29 17:27:43 +00:00
|
|
|
display->GLSLProgram_to_UYVY = gst_gl_display_load_fragment_shader (program);
|
2008-06-28 23:28:11 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_I420:
|
|
|
|
case GST_VIDEO_FORMAT_YV12:
|
2008-06-29 17:27:43 +00:00
|
|
|
display->GLSLProgram_to_I420_YV12 = gst_gl_display_load_fragment_shader (display->textFProgram_to_I420_YV12);
|
2008-06-28 23:28:11 +00:00
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_AYUV:
|
2008-06-29 17:27:43 +00:00
|
|
|
display->GLSLProgram_to_AYUV = gst_gl_display_load_fragment_shader (display->textFProgram_to_AYUV);
|
2008-06-28 23:28:11 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//turn off the pipeline because colorspace conversion is not possible
|
|
|
|
GST_DEBUG ("Context %d, ARB_fragment_shader supported: no", display->glutWinId);
|
|
|
|
display->isAlive = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
2008-06-28 23:28:11 +00:00
|
|
|
g_cond_signal (display->cond_init_download);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called in the gl thread */
|
|
|
|
static void
|
|
|
|
gst_gl_display_thread_do_download (GstGLDisplay * display)
|
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
|
|
|
gst_gl_display_thread_do_download_draw (display);
|
|
|
|
g_cond_signal (display->cond_do_download);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Called in the gl thread */
|
2008-06-07 00:01:18 +00:00
|
|
|
static void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_gen_fbo (GstGLDisplay *display)
|
2008-06-07 00:01:18 +00:00
|
|
|
{
|
2008-06-21 21:38:42 +00:00
|
|
|
//a texture must be attached to the FBO
|
|
|
|
guint fake_texture = 0;
|
2008-06-24 22:28:03 +00:00
|
|
|
|
2008-06-07 00:01:18 +00:00
|
|
|
glutSetWindow (display->glutWinId);
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-06-07 00:01:18 +00:00
|
|
|
//-- generate frame buffer object
|
|
|
|
|
|
|
|
//setup FBO
|
2008-06-30 00:38:39 +00:00
|
|
|
glGenFramebuffersEXT (1, &display->generated_fbo);
|
|
|
|
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, display->generated_fbo);
|
2008-06-07 00:01:18 +00:00
|
|
|
|
2008-06-19 23:38:36 +00:00
|
|
|
//setup the render buffer for depth
|
2008-06-30 00:38:39 +00:00
|
|
|
glGenRenderbuffersEXT(1, &display->generated_depth_buffer);
|
|
|
|
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, display->generated_depth_buffer);
|
2008-06-07 00:01:18 +00:00
|
|
|
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->gen_fbo_width, display->gen_fbo_height);
|
2008-06-07 00:01:18 +00:00
|
|
|
|
|
|
|
//setup a texture to render to
|
2008-06-21 21:38:42 +00:00
|
|
|
glGenTextures (1, &fake_texture);
|
|
|
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fake_texture);
|
2008-06-19 23:38:36 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->gen_fbo_width, display->gen_fbo_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2008-06-07 00:01:18 +00:00
|
|
|
|
|
|
|
//attach the texture to the FBO to renderer to
|
2008-06-19 23:38:36 +00:00
|
|
|
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
|
2008-06-21 21:38:42 +00:00
|
|
|
GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0);
|
2008-06-07 00:01:18 +00:00
|
|
|
|
|
|
|
//attach the depth render buffer to the FBO
|
2008-06-19 23:38:36 +00:00
|
|
|
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
|
2008-06-30 00:38:39 +00:00
|
|
|
GL_RENDERBUFFER_EXT, display->generated_depth_buffer);
|
2008-06-07 00:01:18 +00:00
|
|
|
|
|
|
|
g_assert (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) ==
|
|
|
|
GL_FRAMEBUFFER_COMPLETE_EXT);
|
|
|
|
|
|
|
|
//unbind the FBO
|
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
|
|
|
2008-06-21 21:38:42 +00:00
|
|
|
glDeleteTextures (1, &fake_texture);
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
g_cond_signal (display->cond_gen_fbo);
|
2008-06-07 15:27:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called in the gl thread */
|
2008-06-07 15:27:12 +00:00
|
|
|
static void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_use_fbo (GstGLDisplay *display)
|
2008-06-07 15:27:12 +00:00
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, display->use_fbo);
|
2008-06-07 15:27:12 +00:00
|
|
|
|
2008-06-21 21:38:42 +00:00
|
|
|
//setup a texture to render to
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture);
|
2008-06-21 21:38:42 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->use_fbo_width, display->use_fbo_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2008-06-21 21:38:42 +00:00
|
|
|
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,
|
2008-06-30 00:38:39 +00:00
|
|
|
GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture, 0);
|
2008-06-21 21:38:42 +00:00
|
|
|
|
2008-06-07 15:27:12 +00:00
|
|
|
glPushAttrib(GL_VIEWPORT_BIT);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
2008-06-30 00:38:39 +00:00
|
|
|
gluPerspective(45, (gfloat)display->use_fbo_width/(gfloat)display->use_fbo_height, 0.1, 100);
|
|
|
|
//gluOrtho2D(0.0, display->use_fbo_width, 0.0, display->use_fbo_height);
|
2008-06-07 15:27:12 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glViewport(0, 0, display->use_fbo_width, display->use_fbo_height);
|
2008-06-07 15:27:12 +00:00
|
|
|
|
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
//the opengl scene
|
2008-06-30 00:38:39 +00:00
|
|
|
display->use_fbo_scene_cb (display->input_texture_width, display->input_texture_height,
|
|
|
|
display->input_texture, display->use_shader);
|
2008-06-07 15:27:12 +00:00
|
|
|
|
|
|
|
glDrawBuffer(GL_NONE);
|
|
|
|
|
|
|
|
glUseProgramObjectARB (0);
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPopAttrib();
|
|
|
|
|
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
g_cond_signal (display->cond_use_fbo);
|
2008-06-07 15:27:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called in the gl thread */
|
2008-06-11 23:04:52 +00:00
|
|
|
static void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_use_fbo_2 (GstGLDisplay *display)
|
2008-06-11 23:04:52 +00:00
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, display->use_fbo);
|
2008-06-11 23:04:52 +00:00
|
|
|
|
2008-06-21 21:38:42 +00:00
|
|
|
//setup a texture to render to
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture);
|
2008-06-21 21:38:42 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->use_fbo_width, display->use_fbo_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2008-06-21 21:38:42 +00:00
|
|
|
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,
|
2008-06-30 00:38:39 +00:00
|
|
|
GL_TEXTURE_RECTANGLE_ARB, display->use_fbo_texture, 0);
|
2008-06-21 21:38:42 +00:00
|
|
|
|
2008-06-11 23:04:52 +00:00
|
|
|
glPushAttrib(GL_VIEWPORT_BIT);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
2008-06-30 00:38:39 +00:00
|
|
|
gluOrtho2D(0.0, display->use_fbo_width, 0.0, display->use_fbo_height);
|
2008-06-11 23:04:52 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glViewport(0, 0, display->use_fbo_width, display->use_fbo_height);
|
2008-06-11 23:04:52 +00:00
|
|
|
|
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
//the opengl scene
|
2008-06-30 00:38:39 +00:00
|
|
|
display->use_fbo_scene_cb_2 (display->p1, display->p2,
|
|
|
|
display->use_fbo_width, display->use_fbo_height);
|
2008-06-11 23:04:52 +00:00
|
|
|
|
|
|
|
glDrawBuffer(GL_NONE);
|
|
|
|
|
|
|
|
glUseProgramObjectARB (0);
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPopAttrib();
|
|
|
|
|
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
g_cond_signal (display->cond_use_fbo_2);
|
2008-06-11 23:04:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called in the gl thread */
|
2008-06-07 15:27:12 +00:00
|
|
|
static void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_del_fbo (GstGLDisplay* display)
|
2008-06-07 15:27:12 +00:00
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glDeleteFramebuffersEXT (1, &display->del_fbo);
|
|
|
|
glDeleteRenderbuffersEXT(1, &display->del_depth_buffer);
|
|
|
|
display->del_fbo = 0;
|
|
|
|
display->del_depth_buffer = 0;
|
2008-06-07 15:27:12 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
g_cond_signal (display->cond_del_fbo);
|
2008-06-07 00:01:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called in the gl thread */
|
2008-06-13 00:01:26 +00:00
|
|
|
static void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_gen_shader (GstGLDisplay* display)
|
2008-06-13 00:01:26 +00:00
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
2008-06-30 00:38:39 +00:00
|
|
|
display->gen_handle_shader =
|
|
|
|
gst_gl_display_load_fragment_shader (display->gen_text_shader);
|
2008-06-29 17:27:43 +00:00
|
|
|
g_cond_signal (display->cond_gen_shader);
|
2008-06-13 00:01:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called in the gl thread */
|
2008-06-13 00:01:26 +00:00
|
|
|
static void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_del_shader (GstGLDisplay* display)
|
2008-06-13 00:01:26 +00:00
|
|
|
{
|
|
|
|
glutSetWindow (display->glutWinId);
|
2008-06-30 00:38:39 +00:00
|
|
|
glDeleteObjectARB (display->del_handle_shader);
|
2008-06-29 17:27:43 +00:00
|
|
|
g_cond_signal (display->cond_del_shader);
|
2008-06-13 00:01:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
//------------------------------------------------------------
|
|
|
|
//------------------ BEGIN GL THREAD ACTIONS -----------------
|
|
|
|
//------------------------------------------------------------
|
2008-06-13 00:01:26 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
//------------------------------------------------------------
|
|
|
|
//---------------------- BEGIN PRIVATE -----------------------
|
|
|
|
//------------------------------------------------------------
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
void
|
|
|
|
gst_gl_display_lock (GstGLDisplay * display)
|
|
|
|
{
|
|
|
|
g_mutex_lock (display->mutex);
|
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
void
|
|
|
|
gst_gl_display_unlock (GstGLDisplay * display)
|
|
|
|
{
|
|
|
|
g_mutex_unlock (display->mutex);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Post a message that will be handled by the gl thread
|
|
|
|
* Must be preceded by gst_gl_display_lock
|
|
|
|
* and followed by gst_gl_display_unlock
|
|
|
|
* Called in the public functions */
|
|
|
|
void
|
|
|
|
gst_gl_display_post_message (GstGLDisplayAction action, GstGLDisplay* display)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
GstGLDisplayMsg* msg = g_new0 (GstGLDisplayMsg, 1);
|
|
|
|
msg->action = action;
|
|
|
|
msg->glutWinId = display->glutWinId;
|
|
|
|
msg->display = display;
|
|
|
|
g_async_queue_push (gst_gl_display_messageQueue, msg);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* glutReshapeFunc callback */
|
|
|
|
void
|
|
|
|
gst_gl_display_on_resize (gint width, gint height)
|
2008-06-10 19:07:43 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
gint glutWinId = 0;
|
|
|
|
GstGLDisplay *display = NULL;
|
2008-06-10 19:07:43 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
//retrieve the display associated to the glut context
|
|
|
|
glutWinId = glutGetWindow ();
|
|
|
|
display = g_hash_table_lookup (gst_gl_display_map, GINT_TO_POINTER (glutWinId));
|
2008-06-10 19:07:43 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
//glutGetWindow return 0 if no windows exists, then g_hash_table_lookup return NULL
|
|
|
|
if (display == NULL) return;
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_lock (display);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
//check if a client reshape callback is registered
|
|
|
|
if (display->clientReshapeCallback)
|
|
|
|
display->clientReshapeCallback(width, height);
|
|
|
|
|
|
|
|
//default reshape
|
|
|
|
else
|
|
|
|
{
|
|
|
|
glViewport(0, 0, width, height);
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glLoadIdentity();
|
|
|
|
gluOrtho2D(0, width, 0, height);
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* glutDisplayFunc callback */
|
|
|
|
void gst_gl_display_on_draw(void)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
gint glutWinId = 0;
|
|
|
|
GstGLDisplay *display = NULL;
|
|
|
|
|
|
|
|
//retrieve the display associated to the glut context
|
|
|
|
glutWinId = glutGetWindow ();
|
|
|
|
display = g_hash_table_lookup (gst_gl_display_map, GINT_TO_POINTER (glutWinId));
|
|
|
|
|
|
|
|
//glutGetWindow return 0 if no windows exists, then g_hash_table_lookup return NULL
|
|
|
|
if (display == NULL) return;
|
|
|
|
|
|
|
|
//lock the display because gstreamer elements
|
|
|
|
//(and so the main thread) may modify it
|
|
|
|
gst_gl_display_lock (display);
|
|
|
|
|
|
|
|
//check if video format has been setup
|
2008-06-30 00:38:39 +00:00
|
|
|
if (!display->redisplay_texture)
|
2008-06-29 17:27:43 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
//opengl scene
|
|
|
|
|
|
|
|
glUseProgramObjectARB (0);
|
|
|
|
glDisable (GL_TEXTURE_RECTANGLE_ARB);
|
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0);
|
|
|
|
|
|
|
|
//check if a client draw callback is registered
|
|
|
|
if (display->clientDrawCallback)
|
|
|
|
{
|
|
|
|
gboolean doRedisplay =
|
2008-06-30 00:38:39 +00:00
|
|
|
display->clientDrawCallback(display->redisplay_texture,
|
|
|
|
display->redisplay_texture_width, display->redisplay_texture_height);
|
2008-06-29 17:27:43 +00:00
|
|
|
|
|
|
|
glFlush();
|
|
|
|
glutSwapBuffers();
|
|
|
|
|
|
|
|
if (doRedisplay)
|
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_REDISPLAY_CONTEXT, display);
|
|
|
|
}
|
|
|
|
//default opengl scene
|
|
|
|
else
|
|
|
|
{
|
|
|
|
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
glMatrixMode (GL_PROJECTION);
|
|
|
|
glLoadIdentity ();
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->redisplay_texture);
|
2008-06-29 17:27:43 +00:00
|
|
|
glEnable (GL_TEXTURE_RECTANGLE_ARB);
|
|
|
|
|
|
|
|
glBegin (GL_QUADS);
|
2008-06-30 00:38:39 +00:00
|
|
|
glTexCoord2i (display->redisplay_texture_width, 0);
|
2008-06-29 17:27:43 +00:00
|
|
|
glVertex2f (1.0f, 1.0f);
|
|
|
|
glTexCoord2i (0, 0);
|
|
|
|
glVertex2f (-1.0f, 1.0f);
|
2008-06-30 00:38:39 +00:00
|
|
|
glTexCoord2i (0, display->redisplay_texture_height);
|
2008-06-29 17:27:43 +00:00
|
|
|
glVertex2f (-1.0f, -1.0f);
|
2008-06-30 00:38:39 +00:00
|
|
|
glTexCoord2i (display->redisplay_texture_width, display->redisplay_texture_height);
|
2008-06-29 17:27:43 +00:00
|
|
|
glVertex2f (1.0f, -1.0f);
|
|
|
|
glEnd ();
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
|
|
|
|
|
|
|
glFlush();
|
|
|
|
glutSwapBuffers();
|
|
|
|
|
|
|
|
}//end default opengl scene
|
|
|
|
|
|
|
|
gst_gl_display_unlock (display);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* glutCloseFunc callback */
|
|
|
|
void gst_gl_display_on_close (void)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
gint glutWinId = 0;
|
|
|
|
GstGLDisplay* display = NULL;
|
|
|
|
|
|
|
|
//retrieve the display associated to the glut context
|
|
|
|
glutWinId = glutGetWindow ();
|
|
|
|
display = g_hash_table_lookup (gst_gl_display_map, GINT_TO_POINTER (glutWinId));
|
|
|
|
|
|
|
|
//glutGetWindow return 0 if no windows exists, then g_hash_table_lookup return NULL
|
|
|
|
if (display == NULL) return;
|
|
|
|
|
|
|
|
GST_DEBUG ("on close");
|
|
|
|
|
|
|
|
gst_gl_display_lock (display);
|
|
|
|
display->isAlive = FALSE;
|
|
|
|
gst_gl_display_unlock (display);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Generate a texture if no one is available in the pool
|
|
|
|
* Called in the gl thread */
|
|
|
|
void
|
|
|
|
gst_gl_display_glgen_texture (GstGLDisplay* display, guint* pTexture)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
//check if there is a texture available in the pool
|
|
|
|
GstGLDisplayTex* tex = g_queue_pop_head (display->texturePool);
|
|
|
|
if (tex)
|
|
|
|
{
|
|
|
|
*pTexture = tex->texture;
|
|
|
|
g_free (tex);
|
|
|
|
}
|
|
|
|
//otherwise one more texture is generated
|
|
|
|
//note that this new texture is added in the pool
|
|
|
|
//only after being used
|
|
|
|
else
|
|
|
|
glGenTextures (1, pTexture);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Delete a texture, actually the texture is just added to the pool
|
|
|
|
* Called in the gl thread */
|
|
|
|
void
|
|
|
|
gst_gl_display_gldel_texture (GstGLDisplay* display, guint* pTexture)
|
2008-06-19 23:38:36 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
//Each existing texture is destroyed only when the pool is destroyed
|
|
|
|
//The pool of textures is deleted in the GstGLDisplay destructor
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
//contruct a texture pool element
|
|
|
|
GstGLDisplayTex* tex = g_new0 (GstGLDisplayTex, 1);
|
|
|
|
tex->texture = *pTexture;
|
|
|
|
*pTexture = 0;
|
|
|
|
|
|
|
|
//add tex to the pool, it makes texture allocation reusable
|
|
|
|
g_queue_push_tail (display->texturePool, tex);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* called in the gl thread */
|
|
|
|
GLhandleARB
|
|
|
|
gst_gl_display_load_fragment_shader (gchar* textFProgram)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
GLhandleARB FHandle = 0;
|
|
|
|
GLhandleARB PHandle = 0;
|
|
|
|
gchar s[32768];
|
|
|
|
gint i = 0;
|
|
|
|
|
|
|
|
//Set up program objects
|
|
|
|
PHandle = glCreateProgramObjectARB ();
|
|
|
|
|
|
|
|
//Compile the shader
|
|
|
|
FHandle = glCreateShaderObjectARB (GL_FRAGMENT_SHADER_ARB);
|
|
|
|
glShaderSourceARB (FHandle, 1, (const GLcharARB**)&textFProgram, NULL);
|
|
|
|
glCompileShaderARB (FHandle);
|
|
|
|
|
|
|
|
//Print the compilation log
|
|
|
|
glGetObjectParameterivARB (FHandle, GL_OBJECT_COMPILE_STATUS_ARB, &i);
|
|
|
|
glGetInfoLogARB (FHandle, sizeof(s)/sizeof(char), NULL, s);
|
|
|
|
GST_DEBUG ("Compile Log: %s", s);
|
|
|
|
|
|
|
|
//link the shader
|
|
|
|
glAttachObjectARB (PHandle, FHandle);
|
|
|
|
glLinkProgramARB (PHandle);
|
|
|
|
|
|
|
|
//Print the link log
|
|
|
|
glGetInfoLogARB (PHandle, sizeof(s)/sizeof(char), NULL, s);
|
|
|
|
GST_DEBUG ("Link Log: %s", s);
|
|
|
|
|
|
|
|
return PHandle;
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* called in the gl thread */
|
|
|
|
void
|
|
|
|
gst_gl_display_check_framebuffer_status(void)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
switch(status)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
case GL_FRAMEBUFFER_COMPLETE_EXT:
|
2008-05-18 11:12:46 +00:00
|
|
|
break;
|
2008-06-29 17:27:43 +00:00
|
|
|
|
|
|
|
case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
|
|
|
|
g_print ("GL_FRAMEBUFFER_UNSUPPORTED_EXT\n");
|
2008-05-18 11:12:46 +00:00
|
|
|
break;
|
2008-06-29 17:27:43 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
default:
|
2008-06-29 17:27:43 +00:00
|
|
|
g_print ("General FBO error\n");
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
2008-06-29 17:27:43 +00:00
|
|
|
//--------------------- END PRIVATE -------------------------
|
|
|
|
//------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------
|
|
|
|
//---------------------- BEGIN PUBLIC ------------------------
|
2008-05-18 11:12:46 +00:00
|
|
|
//------------------------------------------------------------
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
|
|
|
|
/* Called by the first gl element of a video/x-raw-gl flow */
|
|
|
|
GstGLDisplay*
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_new (void)
|
|
|
|
{
|
|
|
|
return g_object_new (GST_TYPE_GL_DISPLAY, NULL);
|
|
|
|
}
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
|
|
|
|
/* Create an opengl context (one context for one GstGLDisplay)
|
|
|
|
* Called by the first gl element of a video/x-raw-gl flow */
|
2008-05-18 11:12:46 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_create_context (GstGLDisplay *display,
|
|
|
|
GLint x, GLint y,
|
|
|
|
GLint width, GLint height,
|
|
|
|
gulong winId,
|
|
|
|
gboolean visible)
|
2008-06-19 23:38:36 +00:00
|
|
|
{
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_lock (display);
|
|
|
|
|
|
|
|
display->winId = winId;
|
|
|
|
display->win_xpos = x;
|
|
|
|
display->win_ypos = y;
|
2008-06-30 00:38:39 +00:00
|
|
|
display->upload_width = width;
|
|
|
|
display->upload_height = height;
|
2008-05-18 11:12:46 +00:00
|
|
|
display->visible = visible;
|
|
|
|
|
|
|
|
//if no glut_thread exists, create it with a window associated to the display
|
|
|
|
if (!gst_gl_display_map)
|
|
|
|
{
|
|
|
|
gst_gl_display_messageQueue = g_async_queue_new ();
|
|
|
|
gst_gl_display_map = g_hash_table_new (g_direct_hash, g_direct_equal);
|
|
|
|
gst_gl_display_glutThread = g_thread_create (
|
2008-06-29 17:27:43 +00:00
|
|
|
(GThreadFunc) gst_gl_display_thread_func, display, TRUE, NULL);
|
|
|
|
g_cond_wait (display->cond_create_context, display->mutex);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
//request glut window creation
|
2008-06-19 23:38:36 +00:00
|
|
|
else
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
|
|
|
//blocking call because glut context must be alive
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_CREATE_CONTEXT, display);
|
|
|
|
g_cond_wait (display->cond_create_context, display->mutex);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
2008-06-19 23:38:36 +00:00
|
|
|
gst_gl_display_unlock (display);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by the glimagesink element */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_set_visible_context (GstGLDisplay* display, gboolean visible)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_lock (display);
|
|
|
|
if (display->visible != visible)
|
|
|
|
{
|
|
|
|
display->visible = visible;
|
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_VISIBLE_CONTEXT, display);
|
|
|
|
}
|
|
|
|
gst_gl_display_unlock (display);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by the glimagesink element */
|
2008-05-18 11:12:46 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_resize_context (GstGLDisplay* display, gint width, gint height)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-29 17:27:43 +00:00
|
|
|
display->resize_width = width;
|
|
|
|
display->resize_height = height;
|
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_RESIZE_CONTEXT, display);
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by the glimagesink element */
|
|
|
|
gboolean
|
|
|
|
gst_gl_display_redisplay (GstGLDisplay* display, GLuint texture, gint width , gint height)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
gboolean isAlive = TRUE;
|
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_lock (display);
|
2008-06-29 17:27:43 +00:00
|
|
|
isAlive = display->isAlive;
|
|
|
|
if (texture)
|
|
|
|
{
|
2008-06-30 00:38:39 +00:00
|
|
|
display->redisplay_texture = texture;
|
|
|
|
display->redisplay_texture_width = width;
|
|
|
|
display->redisplay_texture_height = height;
|
2008-06-29 17:27:43 +00:00
|
|
|
}
|
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_REDISPLAY_CONTEXT, display);
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_unlock (display);
|
2008-06-29 17:27:43 +00:00
|
|
|
|
|
|
|
return isAlive;
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by gst_gl_buffer_new */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_gen_texture (GstGLDisplay* display, guint* pTexture)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_lock (display);
|
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_GEN_TEXTURE, display);
|
|
|
|
g_cond_wait (display->cond_gen_texture, display->mutex);
|
2008-06-30 00:38:39 +00:00
|
|
|
*pTexture = display->gen_texture;
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by gst_gl_buffer_finalize */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_del_texture (GstGLDisplay* display, guint texture)
|
2008-06-10 19:07:43 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-30 00:38:39 +00:00
|
|
|
display->del_texture = texture;
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_DEL_TEXTURE, display);
|
|
|
|
g_cond_wait (display->cond_del_texture, display->mutex);
|
2008-06-10 19:07:43 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
|
|
|
|
/* Called by the first gl element of a video/x-raw-gl flow */
|
2008-06-28 15:38:41 +00:00
|
|
|
void
|
|
|
|
gst_gl_display_init_upload (GstGLDisplay* display, GstVideoFormat video_format,
|
|
|
|
guint gl_width, guint gl_height)
|
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
|
|
|
display->upload_video_format = video_format;
|
2008-06-30 00:38:39 +00:00
|
|
|
display->upload_width = gl_width;
|
|
|
|
display->upload_height = gl_height;
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_INIT_UPLOAD, display);
|
2008-06-28 15:38:41 +00:00
|
|
|
g_cond_wait (display->cond_init_upload, display->mutex);
|
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
2008-06-10 19:07:43 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by the first gl element of a video/x-raw-gl flow */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_do_upload (GstGLDisplay* display, guint texture,
|
|
|
|
gint data_width, gint data_height,
|
|
|
|
gpointer data)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-30 00:38:39 +00:00
|
|
|
display->upload_texture = texture;
|
|
|
|
display->upload_data_with = data_width;
|
|
|
|
display->upload_data_height = data_height;
|
|
|
|
display->upload_data = data;
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_DO_UPLOAD, display);
|
|
|
|
g_cond_wait (display->cond_do_upload, display->mutex);
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by the gldownload and glcolorscale element */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_init_download (GstGLDisplay* display, GstVideoFormat video_format,
|
|
|
|
gint width, gint height)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-30 00:38:39 +00:00
|
|
|
display->download_video_format = video_format;
|
|
|
|
display->download_width = width;
|
|
|
|
display->download_height = height;
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_INIT_DOWNLOAD, display);
|
|
|
|
g_cond_wait (display->cond_init_download, display->mutex);
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by the gldownload and glcolorscale element */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_do_download (GstGLDisplay* display, GLuint texture,
|
|
|
|
gint width, gint height,
|
|
|
|
gpointer data)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
|
|
|
//data size is aocciated to the glcontext size
|
2008-06-30 00:38:39 +00:00
|
|
|
display->download_data = data;
|
|
|
|
display->ouput_texture = texture;
|
|
|
|
display->ouput_texture_width = width;
|
|
|
|
display->ouput_texture_height = height;
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_DO_DOWNLOAD, display);
|
|
|
|
g_cond_wait (display->cond_do_download, display->mutex);
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by gltestsrc and glfilter */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_gen_fbo (GstGLDisplay* display, gint width, gint height,
|
|
|
|
guint* fbo, guint* depthbuffer)
|
2008-06-07 00:01:18 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-30 00:38:39 +00:00
|
|
|
display->gen_fbo_width = width;
|
|
|
|
display->gen_fbo_height = height;
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_GEN_FBO, display);
|
|
|
|
g_cond_wait (display->cond_gen_fbo, display->mutex);
|
2008-06-30 00:38:39 +00:00
|
|
|
*fbo = display->generated_fbo;
|
|
|
|
*depthbuffer = display->generated_depth_buffer;
|
2008-06-07 00:01:18 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by glfilter */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_use_fbo (GstGLDisplay* display, gint texture_fbo_width, gint texture_fbo_height,
|
|
|
|
guint fbo, guint depth_buffer, guint texture_fbo, GLCB cb,
|
|
|
|
guint input_texture_width, guint input_texture_height, guint input_texture,
|
|
|
|
GLhandleARB shader)
|
2008-06-07 15:27:12 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-30 00:38:39 +00:00
|
|
|
display->use_fbo = fbo;
|
|
|
|
display->use_depth_buffer = depth_buffer;
|
|
|
|
display->use_fbo_texture = texture_fbo;
|
|
|
|
display->use_fbo_width = texture_fbo_width;
|
|
|
|
display->use_fbo_height = texture_fbo_height;
|
|
|
|
display->use_fbo_scene_cb = cb;
|
|
|
|
display->use_shader = shader;
|
|
|
|
display->input_texture_width = input_texture_width;
|
|
|
|
display->input_texture_height = input_texture_height;
|
|
|
|
display->input_texture = input_texture;
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_USE_FBO, display);
|
|
|
|
g_cond_wait (display->cond_use_fbo, display->mutex);
|
2008-06-07 15:27:12 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by gltestsrc */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_use_fbo_2 (GstGLDisplay* display, gint texture_fbo_width, gint texture_fbo_height,
|
|
|
|
guint fbo, guint depth_buffer, guint texture_fbo, GLCB2 cb2,
|
2008-06-29 17:27:43 +00:00
|
|
|
gpointer* p1, gpointer* p2)
|
2008-06-11 23:04:52 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-30 00:38:39 +00:00
|
|
|
display->use_fbo = fbo;
|
|
|
|
display->use_depth_buffer = depth_buffer;
|
|
|
|
display->use_fbo_texture = texture_fbo;
|
|
|
|
display->use_fbo_width = texture_fbo_width;
|
|
|
|
display->use_fbo_height = texture_fbo_height;
|
|
|
|
display->use_fbo_scene_cb_2 = cb2;
|
2008-06-21 21:38:42 +00:00
|
|
|
display->p1 = p1;
|
|
|
|
display->p2 = p2;
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_USE_FBO2, display);
|
|
|
|
g_cond_wait (display->cond_use_fbo_2, display->mutex);
|
2008-06-11 23:04:52 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by gltestsrc and glfilter */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_del_fbo (GstGLDisplay* display, guint fbo,
|
2008-06-30 00:38:39 +00:00
|
|
|
guint depth_buffer)
|
2008-06-07 15:27:12 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-30 00:38:39 +00:00
|
|
|
display->del_fbo = fbo;
|
|
|
|
display->del_depth_buffer = depth_buffer;
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_DEL_FBO, display);
|
|
|
|
g_cond_wait (display->cond_del_fbo, display->mutex);
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_unlock (display);
|
2008-06-08 02:19:43 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by glfilter */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_gen_shader (GstGLDisplay* display, gchar* textShader, GLhandleARB* handleShader)
|
2008-06-13 00:01:26 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-30 00:38:39 +00:00
|
|
|
display->gen_text_shader = textShader;
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_GEN_SHADER, display);
|
|
|
|
g_cond_wait (display->cond_gen_shader, display->mutex);
|
2008-06-30 00:38:39 +00:00
|
|
|
*handleShader = display->gen_handle_shader;
|
2008-06-13 00:01:26 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by glfilter */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_del_shader (GstGLDisplay* display, GLhandleARB shader)
|
2008-06-13 00:01:26 +00:00
|
|
|
{
|
|
|
|
gst_gl_display_lock (display);
|
2008-06-30 00:38:39 +00:00
|
|
|
display->del_handle_shader = shader;
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_DEL_SHADER, display);
|
|
|
|
g_cond_wait (display->cond_del_shader, display->mutex);
|
2008-06-13 00:01:26 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by the glimagesink */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_set_window_id (GstGLDisplay* display, gulong winId)
|
2008-06-08 02:19:43 +00:00
|
|
|
{
|
2008-06-23 18:56:29 +00:00
|
|
|
static gint y_pos = 0;
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-08 02:19:43 +00:00
|
|
|
gst_gl_display_lock (display);
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_post_message (GST_GL_DISPLAY_ACTION_DESTROY_CONTEXT, display);
|
|
|
|
g_cond_wait (display->cond_destroy_context, display->mutex);
|
2008-06-08 02:19:43 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
|
|
|
|
if (g_hash_table_size (gst_gl_display_map) == 0)
|
|
|
|
{
|
|
|
|
g_thread_join (gst_gl_display_glutThread);
|
2008-06-29 17:27:43 +00:00
|
|
|
g_print ("gl thread joined when setting winId\n");
|
2008-06-08 02:19:43 +00:00
|
|
|
gst_gl_display_glutThread = NULL;
|
|
|
|
g_async_queue_unref (gst_gl_display_messageQueue);
|
|
|
|
g_hash_table_unref (gst_gl_display_map);
|
|
|
|
gst_gl_display_map = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//init opengl context
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_create_context (display,
|
2008-06-30 00:38:39 +00:00
|
|
|
50, y_pos++ * (display->upload_height+50) + 50,
|
|
|
|
display->upload_width, display->upload_height,
|
2008-06-10 19:07:43 +00:00
|
|
|
winId,
|
|
|
|
TRUE);
|
2008-06-28 15:38:41 +00:00
|
|
|
|
|
|
|
//init colorspace conversion if needed
|
|
|
|
gst_gl_display_init_upload (display, display->upload_video_format,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->upload_width, display->upload_height);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by the glimagesink */
|
2008-06-19 23:38:36 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_set_client_reshape_callback (GstGLDisplay * display, CRCB cb)
|
2008-06-19 23:38:36 +00:00
|
|
|
{
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_lock (display);
|
2008-06-29 17:27:43 +00:00
|
|
|
display->clientReshapeCallback = cb;
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_unlock (display);
|
2008-06-19 23:38:36 +00:00
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* Called by the glimagesink */
|
|
|
|
void
|
|
|
|
gst_gl_display_set_client_draw_callback (GstGLDisplay * display, CDCB cb)
|
|
|
|
{
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_lock (display);
|
2008-06-29 17:27:43 +00:00
|
|
|
display->clientDrawCallback = cb;
|
2008-05-18 11:12:46 +00:00
|
|
|
gst_gl_display_unlock (display);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
//------------------------------------------------------------
|
|
|
|
//------------------------ END PUBLIC ------------------------
|
|
|
|
//------------------------------------------------------------
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* called by gst_gl_display_thread_do_upload (in the gl thread) */
|
2008-06-30 00:38:39 +00:00
|
|
|
void gst_gl_display_thread_do_upload_make (GstGLDisplay* display, GLuint* pTexture,
|
|
|
|
GLuint* pTexture_u, GLuint* pTexture_v)
|
2008-06-19 23:38:36 +00:00
|
|
|
{
|
2008-06-30 00:38:39 +00:00
|
|
|
gint width = display->upload_data_with;
|
|
|
|
gint height = display->upload_data_height;
|
2008-06-24 22:28:03 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_glgen_texture (display, pTexture);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture);
|
|
|
|
switch (display->upload_video_format)
|
2008-06-21 21:38:42 +00:00
|
|
|
{
|
2008-05-20 17:40:20 +00:00
|
|
|
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_AYUV:
|
|
|
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA,
|
2008-06-21 21:38:42 +00:00
|
|
|
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2008-05-20 17:40:20 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GST_VIDEO_FORMAT_RGB:
|
|
|
|
case GST_VIDEO_FORMAT_BGR:
|
|
|
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB,
|
2008-06-21 21:38:42 +00:00
|
|
|
width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
2008-05-20 17:40:20 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GST_VIDEO_FORMAT_YUY2:
|
2008-06-28 15:38:41 +00:00
|
|
|
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);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_glgen_texture (display, pTexture_u);
|
2008-06-28 15:38:41 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture_u);
|
2008-06-28 15:38:41 +00:00
|
|
|
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:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
break;
|
2008-05-20 17:40:20 +00:00
|
|
|
case GST_VIDEO_FORMAT_UYVY:
|
2008-06-28 15:38:41 +00:00
|
|
|
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);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_glgen_texture (display, pTexture_u);
|
2008-06-28 15:38:41 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture_u);
|
2008-06-28 15:38:41 +00:00
|
|
|
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:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
2008-05-20 17:40:20 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GST_VIDEO_FORMAT_I420:
|
|
|
|
case GST_VIDEO_FORMAT_YV12:
|
|
|
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
|
2008-06-21 21:38:42 +00:00
|
|
|
width, height,
|
2008-05-20 17:40:20 +00:00
|
|
|
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_glgen_texture (display, pTexture_u);
|
2008-05-20 17:40:20 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture_u);
|
2008-05-20 17:40:20 +00:00
|
|
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
|
2008-06-21 21:38:42 +00:00
|
|
|
GST_ROUND_UP_2 (width) / 2,
|
|
|
|
GST_ROUND_UP_2 (height) / 2,
|
2008-05-20 17:40:20 +00:00
|
|
|
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_glgen_texture (display, pTexture_v);
|
2008-05-20 17:40:20 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture_v);
|
2008-05-20 17:40:20 +00:00
|
|
|
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE,
|
2008-06-21 21:38:42 +00:00
|
|
|
GST_ROUND_UP_2 (width) / 2,
|
|
|
|
GST_ROUND_UP_2 (height) / 2,
|
2008-05-20 17:40:20 +00:00
|
|
|
0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
}
|
2008-06-24 22:28:03 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* called by gst_gl_display_thread_do_upload (in the gl thread) */
|
2008-05-18 11:12:46 +00:00
|
|
|
void
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_thread_do_upload_fill (GstGLDisplay* display, GLuint* pTexture,
|
|
|
|
GLuint* pTexture_u, GLuint* pTexture_v,
|
|
|
|
GstVideoFormat* pVideo_format)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-30 00:38:39 +00:00
|
|
|
gint width = display->upload_data_with;
|
|
|
|
gint height = display->upload_data_height;
|
|
|
|
GstVideoFormat video_format = display->upload_video_format;
|
|
|
|
gpointer data = display->upload_data;
|
|
|
|
*pVideo_format = video_format;
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
switch (video_format) {
|
|
|
|
case GST_VIDEO_FORMAT_RGBx:
|
|
|
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
|
|
|
GL_RGBA, GL_UNSIGNED_BYTE, data);
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_BGRx:
|
|
|
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
|
|
|
GL_BGRA, GL_UNSIGNED_BYTE, data);
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_AYUV:
|
|
|
|
case GST_VIDEO_FORMAT_xRGB:
|
|
|
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
|
|
|
GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, data);
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_xBGR:
|
|
|
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
|
|
|
GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, data);
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_YUY2:
|
2008-06-28 15:38:41 +00:00
|
|
|
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, data);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture_u);
|
2008-06-28 15:38:41 +00:00
|
|
|
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, data);
|
|
|
|
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, data);
|
2008-06-30 00:38:39 +00:00
|
|
|
*pVideo_format = GST_VIDEO_FORMAT_RGBx;
|
2008-06-28 15:38:41 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
break;
|
2008-05-18 11:12:46 +00:00
|
|
|
case GST_VIDEO_FORMAT_UYVY:
|
2008-06-28 15:38:41 +00:00
|
|
|
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, data);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture_u);
|
2008-06-28 15:38:41 +00:00
|
|
|
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, data);
|
|
|
|
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, data);
|
2008-06-30 00:38:39 +00:00
|
|
|
*pVideo_format = GST_VIDEO_FORMAT_RGBx;
|
2008-06-28 15:38:41 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_I420:
|
|
|
|
case GST_VIDEO_FORMAT_YV12:
|
|
|
|
{
|
|
|
|
gint offsetU = 0;
|
|
|
|
gint offsetV = 0;
|
|
|
|
|
2008-06-19 23:38:36 +00:00
|
|
|
switch (video_format)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
|
|
|
case GST_VIDEO_FORMAT_I420:
|
|
|
|
offsetU = 1;
|
|
|
|
offsetV = 2;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_YV12:
|
|
|
|
offsetU = 2;
|
|
|
|
offsetV = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
glTexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, width, height,
|
|
|
|
GL_LUMINANCE, GL_UNSIGNED_BYTE, data);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture_u);
|
2008-05-18 11:12:46 +00:00
|
|
|
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,
|
|
|
|
(guint8 *) data +
|
|
|
|
gst_video_format_get_component_offset (video_format, offsetU, width, height));
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture_v);
|
2008-05-18 11:12:46 +00:00
|
|
|
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,
|
|
|
|
(guint8 *) data +
|
2008-06-19 23:38:36 +00:00
|
|
|
gst_video_format_get_component_offset (video_format, offsetV, width, height));
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* called by gst_gl_display_thread_do_upload (in the gl thread) */
|
2008-05-18 11:12:46 +00:00
|
|
|
void
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_gl_display_thread_do_upload_draw (GstGLDisplay* display, GLuint texture,
|
|
|
|
GLuint texture_u, GLuint texture_v,
|
|
|
|
GstVideoFormat video_format)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, display->upload_fbo);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, display->upload_texture);
|
2008-06-21 21:38:42 +00:00
|
|
|
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8,
|
2008-06-30 00:38:39 +00:00
|
|
|
display->upload_width, display->upload_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
2008-06-21 21:38:42 +00:00
|
|
|
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,
|
2008-06-30 00:38:39 +00:00
|
|
|
GL_TEXTURE_RECTANGLE_ARB, display->upload_texture, 0);
|
2008-06-21 21:38:42 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
glPushAttrib(GL_VIEWPORT_BIT);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
2008-06-30 00:38:39 +00:00
|
|
|
gluOrtho2D(0.0, display->upload_width, 0.0, display->upload_height);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glViewport(0, 0, display->upload_width, display->upload_height);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
switch (video_format)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
|
|
|
case GST_VIDEO_FORMAT_RGBx:
|
|
|
|
case GST_VIDEO_FORMAT_BGRx:
|
|
|
|
case GST_VIDEO_FORMAT_xRGB:
|
|
|
|
case GST_VIDEO_FORMAT_xBGR:
|
|
|
|
{
|
|
|
|
glMatrixMode (GL_PROJECTION);
|
|
|
|
glLoadIdentity ();
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
|
2008-05-18 11:12:46 +00:00
|
|
|
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);
|
|
|
|
glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GST_VIDEO_FORMAT_YUY2:
|
|
|
|
case GST_VIDEO_FORMAT_UYVY:
|
|
|
|
{
|
2008-06-28 15:38:41 +00:00
|
|
|
gint i=0;
|
|
|
|
GLhandleARB GLSLProgram_YUY2_UYVY = 0;
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
switch (video_format)
|
2008-06-28 15:38:41 +00:00
|
|
|
{
|
|
|
|
case GST_VIDEO_FORMAT_YUY2:
|
|
|
|
GLSLProgram_YUY2_UYVY = display->GLSLProgram_YUY2;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_UYVY:
|
|
|
|
GLSLProgram_YUY2_UYVY = display->GLSLProgram_UYVY;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
glUseProgramObjectARB (GLSLProgram_YUY2_UYVY);
|
|
|
|
|
2008-06-28 15:38:41 +00:00
|
|
|
glMatrixMode (GL_PROJECTION);
|
|
|
|
glLoadIdentity ();
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-06-28 15:38:41 +00:00
|
|
|
glActiveTextureARB(GL_TEXTURE1_ARB);
|
|
|
|
i = glGetUniformLocationARB (GLSLProgram_YUY2_UYVY, "UVtex");
|
|
|
|
glUniform1iARB (i, 1);
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture_u);
|
2008-06-28 15:38:41 +00:00
|
|
|
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);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
glActiveTextureARB(GL_TEXTURE0_ARB);
|
2008-06-28 15:38:41 +00:00
|
|
|
i = glGetUniformLocationARB (GLSLProgram_YUY2_UYVY, "Ytex");
|
|
|
|
glUniform1iARB (i, 0);
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
|
2008-06-28 15:38:41 +00:00
|
|
|
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);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GST_VIDEO_FORMAT_I420:
|
|
|
|
case GST_VIDEO_FORMAT_YV12:
|
|
|
|
{
|
|
|
|
gint i=0;
|
|
|
|
|
|
|
|
glUseProgramObjectARB (display->GLSLProgram_I420_YV12);
|
|
|
|
|
|
|
|
glMatrixMode (GL_PROJECTION);
|
|
|
|
glLoadIdentity ();
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
glActiveTextureARB(GL_TEXTURE1_ARB);
|
|
|
|
i = glGetUniformLocationARB (display->GLSLProgram_I420_YV12, "Utex");
|
|
|
|
glUniform1iARB (i, 1);
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture_u);
|
2008-05-18 11:12:46 +00:00
|
|
|
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);
|
|
|
|
i = glGetUniformLocationARB (display->GLSLProgram_I420_YV12, "Vtex");
|
|
|
|
glUniform1iARB (i, 2);
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture_v);
|
2008-05-18 11:12:46 +00:00
|
|
|
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);
|
|
|
|
i = glGetUniformLocationARB (display->GLSLProgram_I420_YV12, "Ytex");
|
|
|
|
glUniform1iARB (i, 0);
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
|
2008-05-18 11:12:46 +00:00
|
|
|
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:
|
|
|
|
{
|
2008-06-28 15:38:41 +00:00
|
|
|
gint i=0;
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-28 15:38:41 +00:00
|
|
|
glUseProgramObjectARB (display->GLSLProgram_AYUV);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-28 15:38:41 +00:00
|
|
|
glMatrixMode (GL_PROJECTION);
|
|
|
|
glLoadIdentity ();
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
glActiveTextureARB(GL_TEXTURE0_ARB);
|
2008-06-28 15:38:41 +00:00
|
|
|
i = glGetUniformLocationARB (display->GLSLProgram_AYUV, "tex");
|
|
|
|
glUniform1iARB (i, 0);
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, texture);
|
2008-06-28 15:38:41 +00:00
|
|
|
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);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
|
|
|
}//end switch display->currentVideo_format
|
|
|
|
|
|
|
|
glBegin (GL_QUADS);
|
2008-06-30 00:38:39 +00:00
|
|
|
glTexCoord2i (display->upload_data_with, 0);
|
2008-05-18 11:12:46 +00:00
|
|
|
glVertex2f (1.0f, -1.0f);
|
|
|
|
glTexCoord2i (0, 0);
|
|
|
|
glVertex2f (-1.0f, -1.0f);
|
2008-06-30 00:38:39 +00:00
|
|
|
glTexCoord2i (0, display->upload_data_height);
|
2008-05-18 11:12:46 +00:00
|
|
|
glVertex2f (-1.0f, 1.0f);
|
2008-06-30 00:38:39 +00:00
|
|
|
glTexCoord2i (display->upload_data_with, display->upload_data_height);
|
2008-05-18 11:12:46 +00:00
|
|
|
glVertex2f (1.0f, 1.0f);
|
|
|
|
glEnd ();
|
|
|
|
|
|
|
|
glDrawBuffer(GL_NONE);
|
|
|
|
|
|
|
|
glUseProgramObjectARB (0);
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPopAttrib();
|
|
|
|
|
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_check_framebuffer_status();
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
/* called by gst_gl_display_thread_do_download (in the gl thread) */
|
2008-05-18 11:12:46 +00:00
|
|
|
void
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_thread_do_download_draw (GstGLDisplay* display)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
2008-06-30 00:38:39 +00:00
|
|
|
gint width = display->download_width;
|
|
|
|
gint height = display->download_height;
|
|
|
|
GstVideoFormat video_format = display->download_video_format;
|
|
|
|
gpointer data = display->download_data;
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, display->download_fbo);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
glPushAttrib(GL_VIEWPORT_BIT);
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
2008-06-28 23:28:11 +00:00
|
|
|
gluOrtho2D(0.0, width, 0.0, height);
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPushMatrix();
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
glViewport(0, 0, width, height);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
switch (video_format)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
|
|
|
case GST_VIDEO_FORMAT_RGBx:
|
|
|
|
case GST_VIDEO_FORMAT_BGRx:
|
|
|
|
case GST_VIDEO_FORMAT_xRGB:
|
|
|
|
case GST_VIDEO_FORMAT_xBGR:
|
2008-06-19 23:38:36 +00:00
|
|
|
{
|
2008-05-18 11:12:46 +00:00
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
|
|
|
|
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
glMatrixMode (GL_PROJECTION);
|
|
|
|
glLoadIdentity ();
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->ouput_texture);
|
2008-05-18 11:12:46 +00:00
|
|
|
glEnable(GL_TEXTURE_RECTANGLE_ARB);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GST_VIDEO_FORMAT_YUY2:
|
|
|
|
case GST_VIDEO_FORMAT_UYVY:
|
|
|
|
{
|
|
|
|
gint i=0;
|
|
|
|
GLhandleARB GLSLProgram_to_YUY2_UYVY = 0;
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
switch (video_format)
|
2008-05-18 11:12:46 +00:00
|
|
|
{
|
|
|
|
case GST_VIDEO_FORMAT_YUY2:
|
|
|
|
GLSLProgram_to_YUY2_UYVY = display->GLSLProgram_to_YUY2;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_UYVY:
|
|
|
|
GLSLProgram_to_YUY2_UYVY = display->GLSLProgram_to_UYVY;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
2008-06-19 23:38:36 +00:00
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
|
|
|
|
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
glUseProgramObjectARB (GLSLProgram_to_YUY2_UYVY);
|
|
|
|
|
|
|
|
glMatrixMode (GL_PROJECTION);
|
|
|
|
glLoadIdentity ();
|
|
|
|
|
|
|
|
glActiveTextureARB(GL_TEXTURE0_ARB);
|
|
|
|
i = glGetUniformLocationARB (GLSLProgram_to_YUY2_UYVY, "tex");
|
|
|
|
glUniform1iARB (i, 0);
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->ouput_texture);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GST_VIDEO_FORMAT_I420:
|
|
|
|
case GST_VIDEO_FORMAT_YV12:
|
|
|
|
{
|
|
|
|
gint i=0;
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
glDrawBuffers(3, display->multipleRT);
|
2008-06-19 23:38:36 +00:00
|
|
|
|
2008-05-18 11:12:46 +00:00
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
glUseProgramObjectARB (display->GLSLProgram_to_I420_YV12);
|
|
|
|
|
|
|
|
glMatrixMode (GL_PROJECTION);
|
|
|
|
glLoadIdentity ();
|
|
|
|
|
|
|
|
glActiveTextureARB(GL_TEXTURE0_ARB);
|
|
|
|
i = glGetUniformLocationARB (display->GLSLProgram_to_I420_YV12, "tex");
|
|
|
|
glUniform1iARB (i, 0);
|
|
|
|
i = glGetUniformLocationARB (display->GLSLProgram_to_I420_YV12, "w");
|
2008-06-30 00:38:39 +00:00
|
|
|
glUniform1fARB (i, (gfloat)display->ouput_texture_width);
|
2008-05-18 11:12:46 +00:00
|
|
|
i = glGetUniformLocationARB (display->GLSLProgram_to_I420_YV12, "h");
|
2008-06-30 00:38:39 +00:00
|
|
|
glUniform1fARB (i, (gfloat)display->ouput_texture_height);
|
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->ouput_texture);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GST_VIDEO_FORMAT_AYUV:
|
|
|
|
{
|
|
|
|
gint i=0;
|
|
|
|
|
|
|
|
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
|
|
|
|
|
|
|
glClearColor(0.0, 0.0, 0.0, 0.0);
|
|
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
|
|
|
|
glUseProgramObjectARB (display->GLSLProgram_to_AYUV);
|
|
|
|
|
|
|
|
glMatrixMode (GL_PROJECTION);
|
|
|
|
glLoadIdentity ();
|
|
|
|
|
|
|
|
glActiveTextureARB(GL_TEXTURE0_ARB);
|
|
|
|
i = glGetUniformLocationARB (display->GLSLProgram_to_AYUV, "tex");
|
|
|
|
glUniform1iARB (i, 0);
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindTexture (GL_TEXTURE_RECTANGLE_ARB, display->ouput_texture);
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
|
|
|
|
}//end switch display->currentVideo_format
|
|
|
|
|
|
|
|
glBegin (GL_QUADS);
|
|
|
|
glTexCoord2i (0, 0);
|
|
|
|
glVertex2f (-1.0f, -1.0f);
|
2008-06-23 18:56:29 +00:00
|
|
|
glTexCoord2i (width, 0);
|
2008-05-18 11:12:46 +00:00
|
|
|
glVertex2f (1.0f, -1.0f);
|
2008-06-23 18:56:29 +00:00
|
|
|
glTexCoord2i (width, height);
|
|
|
|
glVertex2f (1.0f, 1.0f);
|
|
|
|
glTexCoord2i (0, height);
|
|
|
|
glVertex2f (-1.0f, 1.0f);
|
2008-06-19 23:38:36 +00:00
|
|
|
glEnd ();
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
glDrawBuffer(GL_NONE);
|
|
|
|
|
|
|
|
glUseProgramObjectARB (0);
|
|
|
|
|
|
|
|
glDisable(GL_TEXTURE_RECTANGLE_ARB);
|
|
|
|
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
glPopMatrix();
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
glPopAttrib();
|
|
|
|
|
|
|
|
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
|
|
|
|
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_check_framebuffer_status();
|
2008-05-18 11:12:46 +00:00
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, display->download_fbo);
|
2008-05-18 11:12:46 +00:00
|
|
|
glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
switch (video_format)
|
|
|
|
{
|
2008-05-18 11:12:46 +00:00
|
|
|
case GST_VIDEO_FORMAT_RGBx:
|
|
|
|
glReadPixels (0, 0, width, height, GL_RGBA,
|
|
|
|
GL_UNSIGNED_BYTE, data);
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_BGRx:
|
|
|
|
glReadPixels (0, 0, width, height, GL_BGRA,
|
|
|
|
GL_UNSIGNED_BYTE, data);
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_xBGR:
|
|
|
|
glReadPixels (0, 0, width, height, GL_RGBA,
|
|
|
|
GL_UNSIGNED_INT_8_8_8_8, data);
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_AYUV:
|
|
|
|
case GST_VIDEO_FORMAT_xRGB:
|
|
|
|
glReadPixels (0, 0, width, height, GL_BGRA,
|
|
|
|
GL_UNSIGNED_INT_8_8_8_8, data);
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_YUY2:
|
|
|
|
case GST_VIDEO_FORMAT_UYVY:
|
|
|
|
glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2, height, GL_BGRA,
|
|
|
|
GL_UNSIGNED_INT_8_8_8_8_REV, data);
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_I420:
|
|
|
|
case GST_VIDEO_FORMAT_YV12:
|
|
|
|
{
|
|
|
|
gint offsetU = 0;
|
|
|
|
gint offsetV = 0;
|
|
|
|
|
2008-06-30 00:38:39 +00:00
|
|
|
switch (video_format)
|
2008-05-20 17:40:20 +00:00
|
|
|
{
|
|
|
|
case GST_VIDEO_FORMAT_I420:
|
|
|
|
offsetU = 1;
|
|
|
|
offsetV = 2;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_YV12:
|
|
|
|
offsetU = 2;
|
|
|
|
offsetV = 1;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
glReadPixels (0, 0, width, height, GL_LUMINANCE,
|
|
|
|
GL_UNSIGNED_BYTE, data);
|
|
|
|
|
|
|
|
glReadBuffer(GL_COLOR_ATTACHMENT1_EXT);
|
2008-06-19 23:38:36 +00:00
|
|
|
glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
|
2008-05-18 11:12:46 +00:00
|
|
|
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
|
|
|
(guint8 *) data +
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_video_format_get_component_offset (video_format, offsetU, width, height));
|
2008-05-18 11:12:46 +00:00
|
|
|
|
|
|
|
glReadBuffer(GL_COLOR_ATTACHMENT2_EXT);
|
2008-06-19 23:38:36 +00:00
|
|
|
glReadPixels (0, 0, GST_ROUND_UP_2 (width) / 2, GST_ROUND_UP_2 (height) / 2,
|
2008-05-18 11:12:46 +00:00
|
|
|
GL_LUMINANCE, GL_UNSIGNED_BYTE,
|
|
|
|
(guint8 *) data +
|
2008-06-30 00:38:39 +00:00
|
|
|
gst_video_format_get_component_offset (video_format, offsetV, width, height));
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached ();
|
|
|
|
}
|
|
|
|
|
|
|
|
glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);
|
2008-06-29 17:27:43 +00:00
|
|
|
gst_gl_display_check_framebuffer_status();
|
2008-05-18 11:12:46 +00:00
|
|
|
}
|