diff --git a/gst-libs/gst/gl/Makefile.am b/gst-libs/gst/gl/Makefile.am index b5ece57cd7..4de26fe20f 100644 --- a/gst-libs/gst/gl/Makefile.am +++ b/gst-libs/gst/gl/Makefile.am @@ -15,7 +15,8 @@ libgstgl_@GST_API_VERSION@_la_SOURCES = \ gstglupload.c \ gstglwindow.c \ gstglapi.c \ - gstglfeature.c + gstglfeature.c \ + gstglutils.c libgstgl_@GST_API_VERSION@_la_LIBADD = \ $(GST_PLUGINS_BASE_LIBS) \ @@ -59,7 +60,8 @@ libgstgl_@GST_API_VERSION@include_HEADERS = \ gstgldownload.h \ gstglupload.h \ gstglapi.h \ - gstglfeature.h + gstglfeature.h \ + gstglutils.h libgstgl_@GST_API_VERSION@_la_CFLAGS = \ $(GL_CFLAGS) \ diff --git a/gst-libs/gst/gl/gstgldisplay.c b/gst-libs/gst/gl/gstgldisplay.c index 3fd3fd26f6..6566b75a72 100644 --- a/gst-libs/gst/gl/gstgldisplay.c +++ b/gst-libs/gst/gl/gstgldisplay.c @@ -35,22 +35,6 @@ #include "gstgldisplay.h" -#ifndef GL_FRAMEBUFFER_UNDEFINED -#define GL_FRAMEBUFFER_UNDEFINED 0x8219 -#endif -#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 -#endif -#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 -#endif -#ifndef GL_FRAMEBUFFER_UNSUPPORTED -#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD -#endif -#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 -#endif - #define USING_OPENGL(display) (display->gl_api & GST_GL_API_OPENGL) #define USING_OPENGL3(display) (display->gl_api & GST_GL_API_OPENGL3) #define USING_GLES(display) (display->gl_api & GST_GL_API_GLES) @@ -75,27 +59,6 @@ static void gst_gl_display_finalize (GObject * object); gpointer gst_gl_display_thread_create_context (GstGLDisplay * display); void gst_gl_display_thread_destroy_context (GstGLDisplay * display); void gst_gl_display_thread_run_generic (GstGLDisplay * display); -void gst_gl_display_thread_gen_fbo (GstGLDisplay * display); -void gst_gl_display_thread_use_fbo (GstGLDisplay * display); -void gst_gl_display_thread_use_fbo_v2 (GstGLDisplay * display); -void gst_gl_display_thread_del_fbo (GstGLDisplay * display); -void gst_gl_display_thread_gen_shader (GstGLDisplay * display); -void gst_gl_display_thread_del_shader (GstGLDisplay * display); - -/* private methods */ -void gst_gl_display_lock (GstGLDisplay * display); -void gst_gl_display_unlock (GstGLDisplay * display); -void gst_gl_display_del_texture_thread (GstGLDisplay * display, - GLuint * pTexture); - -void gst_gl_display_gen_texture_window_cb (GstGLDisplay * display); - -void _gen_fbo (GstGLDisplay * display); -void _del_fbo (GstGLDisplay * display); -void _gen_shader (GstGLDisplay * display); -void _del_shader (GstGLDisplay * display); -void _use_fbo (GstGLDisplay * display); -void _use_fbo_v2 (GstGLDisplay * display); struct _GstGLDisplayPrivate { @@ -106,51 +69,6 @@ struct _GstGLDisplayPrivate /* generic gl code */ GstGLDisplayThreadFunc generic_callback; gpointer data; - - /* action gen and del texture */ - GLuint gen_texture; - GLuint gen_texture_width; - GLuint gen_texture_height; - GstVideoFormat gen_texture_video_format; - - /* client callbacks */ - CRCB clientReshapeCallback; - CDCB clientDrawCallback; - gpointer client_data; - - /* filter gen fbo */ - GLuint gen_fbo_width; - GLuint gen_fbo_height; - GLuint generated_fbo; - GLuint generated_depth_buffer; - - /* filter use fbo */ - GLuint use_fbo; - GLuint use_depth_buffer; - GLuint use_fbo_texture; - GLuint use_fbo_width; - GLuint use_fbo_height; - GLCB use_fbo_scene_cb; - GLCB_V2 use_fbo_scene_cb_v2; - gdouble use_fbo_proj_param1; - gdouble use_fbo_proj_param2; - gdouble use_fbo_proj_param3; - gdouble use_fbo_proj_param4; - GstGLDisplayProjection use_fbo_projection; - gpointer *use_fbo_stuff; - GLuint input_texture_width; - GLuint input_texture_height; - GLuint input_texture; - - /* filter del fbo */ - GLuint del_fbo; - GLuint del_depth_buffer; - - /* action gen and del shader */ - const gchar *gen_shader_fragment_source; - const gchar *gen_shader_vertex_source; - GstGLShader *gen_shader; - GstGLShader *del_shader; }; /*------------------------------------------------------------ @@ -221,19 +139,6 @@ gst_gl_display_finalize (GObject * object) g_cond_clear (&display->priv->cond_destroy_context); g_cond_clear (&display->priv->cond_create_context); - if (display->priv->clientReshapeCallback) - display->priv->clientReshapeCallback = NULL; - if (display->priv->clientDrawCallback) - display->priv->clientDrawCallback = NULL; - if (display->priv->client_data) - display->priv->client_data = NULL; - if (display->priv->use_fbo_scene_cb) - display->priv->use_fbo_scene_cb = NULL; - if (display->priv->use_fbo_scene_cb_v2) - display->priv->use_fbo_scene_cb_v2 = NULL; - if (display->priv->use_fbo_stuff) - display->priv->use_fbo_stuff = NULL; - if (display->error_message) { g_free (display->error_message); display->error_message = NULL; @@ -245,30 +150,6 @@ gst_gl_display_finalize (GObject * object) } } - -//------------------------------------------------------------ -//------------------ BEGIN GL THREAD PROCS ------------------- -//------------------------------------------------------------ - -/* Called in the gl thread */ - -void -gst_gl_display_set_error (GstGLDisplay * display, const char *format, ...) -{ - va_list args; - - if (display->error_message) - g_free (display->error_message); - - va_start (args, format); - display->error_message = g_strdup_vprintf (format, args); - va_end (args); - - GST_WARNING ("%s", display->error_message); - - display->isAlive = FALSE; -} - static gboolean _create_context_gles2 (GstGLDisplay * display, gint * gl_major, gint * gl_minor) { @@ -528,14 +409,34 @@ failure: } } - -/* Called in the gl thread */ void gst_gl_display_thread_destroy_context (GstGLDisplay * display) { GST_INFO ("Context destroyed"); } +//------------------------------------------------------------ +//------------------ BEGIN GL THREAD PROCS ------------------- +//------------------------------------------------------------ + +/* Called in the gl thread */ + +void +gst_gl_display_set_error (GstGLDisplay * display, const char *format, ...) +{ + va_list args; + + if (display->error_message) + g_free (display->error_message); + + va_start (args, format); + display->error_message = g_strdup_vprintf (format, args); + va_end (args); + + GST_WARNING ("%s", display->error_message); + + display->isAlive = FALSE; +} void gst_gl_display_thread_run_generic (GstGLDisplay * display) @@ -546,402 +447,6 @@ gst_gl_display_thread_run_generic (GstGLDisplay * display) display->priv->generic_callback (display, display->priv->data); } -void -_gen_fbo (GstGLDisplay * display) -{ - /* a texture must be attached to the FBO */ - const GstGLFuncs *gl = display->gl_vtable; - GLuint fake_texture = 0; - - GST_TRACE ("creating FBO dimensions:%ux%u", display->priv->gen_fbo_width, - display->priv->gen_fbo_height); - - /* -- generate frame buffer object */ - - if (!gl->GenFramebuffers) { - gst_gl_display_set_error (display, - "Context, EXT_framebuffer_object not supported"); - return; - } - /* setup FBO */ - gl->GenFramebuffers (1, &display->priv->generated_fbo); - gl->BindFramebuffer (GL_FRAMEBUFFER, display->priv->generated_fbo); - - /* setup the render buffer for depth */ - gl->GenRenderbuffers (1, &display->priv->generated_depth_buffer); - gl->BindRenderbuffer (GL_RENDERBUFFER, display->priv->generated_depth_buffer); - - if (USING_OPENGL (display)) { - gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, - display->priv->gen_fbo_width, display->priv->gen_fbo_height); - gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, - display->priv->gen_fbo_width, display->priv->gen_fbo_height); - } - if (USING_GLES2 (display)) { - gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, - display->priv->gen_fbo_width, display->priv->gen_fbo_height); - } - - /* setup a texture to render to */ - gl->GenTextures (1, &fake_texture); - gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, fake_texture); - gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, - display->priv->gen_fbo_width, display->priv->gen_fbo_height, 0, GL_RGBA, - GL_UNSIGNED_BYTE, NULL); - gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, - GL_LINEAR); - gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, - GL_LINEAR); - gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - - /* attach the texture to the FBO to renderer to */ - gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0); - - /* attach the depth render buffer to the FBO */ - gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, - GL_RENDERBUFFER, display->priv->generated_depth_buffer); - - if (USING_OPENGL (display)) { - gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, display->priv->generated_depth_buffer); - } - - if (gl->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) - gst_gl_display_set_error (display, "GL framebuffer status incomplete"); - - /* unbind the FBO */ - gl->BindFramebuffer (GL_FRAMEBUFFER, 0); - - gl->DeleteTextures (1, &fake_texture); -} - -void -_use_fbo (GstGLDisplay * display) -{ - const GstGLFuncs *gl = display->gl_vtable; -#if GST_GL_HAVE_GLES2 - GLint viewport_dim[4]; -#endif - - GST_TRACE ("Binding v1 FBO %u dimensions:%ux%u with texture:%u " - "dimensions:%ux%u", display->priv->use_fbo, display->priv->use_fbo_width, - display->priv->use_fbo_height, display->priv->use_fbo_texture, - display->priv->input_texture_width, display->priv->input_texture_height); - - gl->BindFramebuffer (GL_FRAMEBUFFER, display->priv->use_fbo); - - /*setup a texture to render to */ - gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, display->priv->use_fbo_texture); - - /* attach the texture to the FBO to renderer to */ - gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_RECTANGLE_ARB, display->priv->use_fbo_texture, 0); - - gst_gl_display_clear_shader (display); - - -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (display)) { - gl->PushAttrib (GL_VIEWPORT_BIT); - gl->MatrixMode (GL_PROJECTION); - gl->PushMatrix (); - gl->LoadIdentity (); - - switch (display->priv->use_fbo_projection) { - case GST_GL_DISPLAY_PROJECTION_ORTHO2D: - gluOrtho2D (display->priv->use_fbo_proj_param1, - display->priv->use_fbo_proj_param2, - display->priv->use_fbo_proj_param3, - display->priv->use_fbo_proj_param4); - break; - case GST_GL_DISPLAY_PROJECTION_PERSPECTIVE: - gluPerspective (display->priv->use_fbo_proj_param1, - display->priv->use_fbo_proj_param2, - display->priv->use_fbo_proj_param3, - display->priv->use_fbo_proj_param4); - break; - default: - gst_gl_display_set_error (display, "Unknow fbo projection %d", - display->priv->use_fbo_projection); - } - - gl->MatrixMode (GL_MODELVIEW); - gl->PushMatrix (); - gl->LoadIdentity (); - } -#endif -#if GST_GL_HAVE_GLES2 - if (USING_GLES2 (display)) - gl->GetIntegerv (GL_VIEWPORT, viewport_dim); -#endif - - gl->Viewport (0, 0, display->priv->use_fbo_width, - display->priv->use_fbo_height); - -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (display)) { - const GLenum rt[] = { GL_COLOR_ATTACHMENT0 }; - gl->DrawBuffers (1, rt); - } -#endif - - gl->ClearColor (0.0, 0.0, 0.0, 0.0); - gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - display->priv->use_fbo_scene_cb (display->priv->input_texture_width, - display->priv->input_texture_height, display->priv->input_texture, - display->priv->use_fbo_stuff); - -#if GST_GL_HAVE_OPENGL - if (USING_OPENGL (display)) { - const GLenum rt[] = { GL_NONE }; - gl->DrawBuffers (1, rt); - gl->MatrixMode (GL_PROJECTION); - gl->PopMatrix (); - gl->MatrixMode (GL_MODELVIEW); - gl->PopMatrix (); - gl->PopAttrib (); - } -#endif -#if GST_GL_HAVE_GLES2 - if (USING_GLES2 (display)) { - gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2], - viewport_dim[3]); - } -#endif - - gl->BindFramebuffer (GL_FRAMEBUFFER, 0); -} - -/* Called in a gl thread - * Need full shader support */ -void -_use_fbo_v2 (GstGLDisplay * display) -{ - const GstGLFuncs *gl = display->gl_vtable; - GLint viewport_dim[4]; - - GST_TRACE ("Binding v2 FBO %u dimensions:%ux%u with texture:%u ", - display->priv->use_fbo, display->priv->use_fbo_width, - display->priv->use_fbo_height, display->priv->use_fbo_texture); - - gl->BindFramebuffer (GL_FRAMEBUFFER, display->priv->use_fbo); - - /* setup a texture to render to */ - gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, display->priv->use_fbo_texture); - - /* attach the texture to the FBO to renderer to */ - gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_RECTANGLE_ARB, display->priv->use_fbo_texture, 0); - - gl->GetIntegerv (GL_VIEWPORT, viewport_dim); - - gl->Viewport (0, 0, display->priv->use_fbo_width, - display->priv->use_fbo_height); - - gl->DrawBuffer (GL_COLOR_ATTACHMENT0); - - gl->ClearColor (0.0, 0.0, 0.0, 0.0); - gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - /* the opengl scene */ - display->priv->use_fbo_scene_cb_v2 (display->priv->use_fbo_stuff); - - gl->DrawBuffer (GL_NONE); - - gl->Viewport (viewport_dim[0], viewport_dim[1], - viewport_dim[2], viewport_dim[3]); - - gl->BindFramebuffer (GL_FRAMEBUFFER, 0); -} - -/* Called in the gl thread */ -void -_del_fbo (GstGLDisplay * display) -{ - const GstGLFuncs *gl = display->gl_vtable; - - GST_TRACE ("Deleting FBO %u", display->priv->del_fbo); - - if (display->priv->del_fbo) { - gl->DeleteFramebuffers (1, &display->priv->del_fbo); - display->priv->del_fbo = 0; - } - if (display->priv->del_depth_buffer) { - gl->DeleteRenderbuffers (1, &display->priv->del_depth_buffer); - display->priv->del_depth_buffer = 0; - } -} - -/* Called in the gl thread */ -void -_gen_shader (GstGLDisplay * display) -{ - const GstGLFuncs *gl = display->gl_vtable; - - GST_TRACE ("Generating shader %" GST_PTR_FORMAT, display->priv->gen_shader); - - if (gl->CreateProgramObject || gl->CreateProgram) { - if (display->priv->gen_shader_vertex_source || - display->priv->gen_shader_fragment_source) { - GError *error = NULL; - - display->priv->gen_shader = gst_gl_shader_new (display); - - if (display->priv->gen_shader_vertex_source) - gst_gl_shader_set_vertex_source (display->priv->gen_shader, - display->priv->gen_shader_vertex_source); - - if (display->priv->gen_shader_fragment_source) - gst_gl_shader_set_fragment_source (display->priv->gen_shader, - display->priv->gen_shader_fragment_source); - - gst_gl_shader_compile (display->priv->gen_shader, &error); - if (error) { - gst_gl_display_set_error (display, "%s", error->message); - g_error_free (error); - error = NULL; - gst_gl_display_clear_shader (display); - g_object_unref (G_OBJECT (display->priv->gen_shader)); - display->priv->gen_shader = NULL; - } - } - } else { - gst_gl_display_set_error (display, - "One of the filter required ARB_fragment_shader"); - display->priv->gen_shader = NULL; - } -} - -/* Called in the gl thread */ -void -_del_shader (GstGLDisplay * display) -{ - GST_TRACE ("Deleting shader %" GST_PTR_FORMAT, display->priv->del_shader); - - if (display->priv->del_shader) { - g_object_unref (G_OBJECT (display->priv->del_shader)); - display->priv->del_shader = NULL; - } -} - -//------------------------------------------------------------ -//------------------ BEGIN GL THREAD ACTIONS ----------------- -//------------------------------------------------------------ - - -//------------------------------------------------------------ -//---------------------- BEGIN PRIVATE ----------------------- -//------------------------------------------------------------ - -void -gst_gl_display_gen_texture_window_cb (GstGLDisplay * display) -{ - gst_gl_display_gen_texture_thread (display, &display->priv->gen_texture, - display->priv->gen_texture_video_format, display->priv->gen_texture_width, - display->priv->gen_texture_height); -} - -/* Generate a texture if no one is available in the pool - * Called in the gl thread */ -void -gst_gl_display_gen_texture_thread (GstGLDisplay * display, GLuint * pTexture, - GstVideoFormat v_format, GLint width, GLint height) -{ - const GstGLFuncs *gl = display->gl_vtable; - - GST_TRACE ("Generating texture format:%u dimensions:%ux%u", v_format, - width, height); - - gl->GenTextures (1, pTexture); - gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture); - - switch (v_format) { - case GST_VIDEO_FORMAT_RGB: - case GST_VIDEO_FORMAT_BGR: - case GST_VIDEO_FORMAT_RGBx: - case GST_VIDEO_FORMAT_BGRx: - case GST_VIDEO_FORMAT_xRGB: - case GST_VIDEO_FORMAT_xBGR: - case GST_VIDEO_FORMAT_RGBA: - case GST_VIDEO_FORMAT_BGRA: - case GST_VIDEO_FORMAT_ARGB: - case GST_VIDEO_FORMAT_ABGR: - { - gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, - width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - break; - } - case GST_VIDEO_FORMAT_YUY2: - case GST_VIDEO_FORMAT_UYVY: - { - switch (display->colorspace_conversion) { - case GST_GL_DISPLAY_CONVERSION_GLSL: - case GST_GL_DISPLAY_CONVERSION_MATRIX: - gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, - width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - break; -#if 0 - case GST_GL_DISPLAY_CONVERSION_MESA: - if (display->upload_width != display->upload_data_width || - display->upload_height != display->upload_data_height) - gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, - width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - else - gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width, - height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL); - break; -#endif - default: - gst_gl_display_set_error (display, "Unknow colorspace conversion %d", - display->colorspace_conversion); - } - break; - } - case GST_VIDEO_FORMAT_I420: - case GST_VIDEO_FORMAT_YV12: - case GST_VIDEO_FORMAT_AYUV: - { - gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, - width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); - break; - } - default: - { - gst_gl_display_set_error (display, "Unsupported upload video format %d", - v_format); - break; - } - } - - gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, - GL_LINEAR); - gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, - GL_LINEAR); - gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, - GL_CLAMP_TO_EDGE); - gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, - GL_CLAMP_TO_EDGE); - - GST_LOG ("generated texture id:%d", *pTexture); -} - -void -gst_gl_display_del_texture_thread (GstGLDisplay * display, GLuint * pTexture) -{ - //glDeleteTextures (1, pTexture); -} - - -/*------------------------------------------------------------ - --------------------- END PRIVATE ------------------------- - ----------------------------------------------------------*/ - - /*------------------------------------------------------------ --------------------- BEGIN PUBLIC ------------------------- ----------------------------------------------------------*/ @@ -958,44 +463,6 @@ gst_gl_display_unlock (GstGLDisplay * display) g_mutex_unlock (&display->mutex); } -/* called in the gl thread */ -gboolean -gst_gl_display_check_framebuffer_status (GstGLDisplay * display) -{ - GLenum status = 0; - status = display->gl_vtable->CheckFramebufferStatus (GL_FRAMEBUFFER); - - switch (status) { - case GL_FRAMEBUFFER_COMPLETE: - return TRUE; - break; - - case GL_FRAMEBUFFER_UNSUPPORTED: - GST_ERROR ("GL_FRAMEBUFFER_UNSUPPORTED"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); - break; - case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); - break; -#if GST_GL_HAVE_OPENGL - case GL_FRAMEBUFFER_UNDEFINED: - GST_ERROR ("GL_FRAMEBUFFER_UNDEFINED"); - break; -#endif - default: - GST_ERROR ("General FBO error"); - } - - return FALSE; -} - /* Called by the first gl element of a video/x-raw-gl flow */ GstGLDisplay * gst_gl_display_new (void) @@ -1003,7 +470,6 @@ gst_gl_display_new (void) return g_object_new (GST_GL_TYPE_DISPLAY, NULL); } - /* Create an opengl context (one context for one GstGLDisplay) */ gboolean gst_gl_display_create_context (GstGLDisplay * display, @@ -1045,182 +511,7 @@ gst_gl_display_thread_add (GstGLDisplay * display, gst_gl_display_unlock (display); } -void -gst_gl_display_gen_texture (GstGLDisplay * display, GLuint * pTexture, - GstVideoFormat v_format, GLint width, GLint height) -{ - gst_gl_display_lock (display); - - if (display->isAlive) { - display->priv->gen_texture_width = width; - display->priv->gen_texture_height = height; - display->priv->gen_texture_video_format = v_format; - gst_gl_window_send_message (display->gl_window, - GST_GL_WINDOW_CB (gst_gl_display_gen_texture_window_cb), display); - *pTexture = display->priv->gen_texture; - } else - *pTexture = 0; - - gst_gl_display_unlock (display); -} - -void -gst_gl_display_del_texture (GstGLDisplay * display, GLuint * pTexture) -{ - gst_gl_display_lock (display); - if (*pTexture) { - gst_gl_display_del_texture_thread (display, pTexture); - } - gst_gl_display_unlock (display); -} - -gboolean -gst_gl_display_gen_fbo (GstGLDisplay * display, gint width, gint height, - GLuint * fbo, GLuint * depthbuffer) -{ - gboolean isAlive = FALSE; - - gst_gl_display_lock (display); - if (display->isAlive) { - display->priv->gen_fbo_width = width; - display->priv->gen_fbo_height = height; - gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_gen_fbo), - display); - *fbo = display->priv->generated_fbo; - *depthbuffer = display->priv->generated_depth_buffer; - } - isAlive = display->isAlive; - gst_gl_display_unlock (display); - - return isAlive; -} - - -/* Called by glfilter */ -/* this function really has to be simplified... do we really need to - set projection this way? Wouldn't be better a set_projection - separate call? or just make glut functions available out of - gst-libs and call it if needed on drawcallback? -- Filippo */ -/* GLCB too.. I think that only needed parameters should be - * GstGLDisplay *display and gpointer data, or just gpointer data */ -/* ..everything here has to be simplified! */ -gboolean -gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width, - gint texture_fbo_height, GLuint fbo, GLuint depth_buffer, - GLuint texture_fbo, GLCB cb, gint input_texture_width, - gint input_texture_height, GLuint input_texture, gdouble proj_param1, - gdouble proj_param2, gdouble proj_param3, gdouble proj_param4, - GstGLDisplayProjection projection, gpointer * stuff) -{ - gboolean isAlive; - - gst_gl_display_lock (display); - if (display->isAlive) { - display->priv->use_fbo = fbo; - display->priv->use_depth_buffer = depth_buffer; - display->priv->use_fbo_texture = texture_fbo; - display->priv->use_fbo_width = texture_fbo_width; - display->priv->use_fbo_height = texture_fbo_height; - display->priv->use_fbo_scene_cb = cb; - display->priv->use_fbo_proj_param1 = proj_param1; - display->priv->use_fbo_proj_param2 = proj_param2; - display->priv->use_fbo_proj_param3 = proj_param3; - display->priv->use_fbo_proj_param4 = proj_param4; - display->priv->use_fbo_projection = projection; - display->priv->use_fbo_stuff = stuff; - display->priv->input_texture_width = input_texture_width; - display->priv->input_texture_height = input_texture_height; - display->priv->input_texture = input_texture; - gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_use_fbo), - display); - } - isAlive = display->isAlive; - gst_gl_display_unlock (display); - - return isAlive; -} - -gboolean -gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width, - gint texture_fbo_height, GLuint fbo, GLuint depth_buffer, - GLuint texture_fbo, GLCB_V2 cb, gpointer * stuff) -{ - gboolean isAlive; - - gst_gl_display_lock (display); - if (display->isAlive) { - display->priv->use_fbo = fbo; - display->priv->use_depth_buffer = depth_buffer; - display->priv->use_fbo_texture = texture_fbo; - display->priv->use_fbo_width = texture_fbo_width; - display->priv->use_fbo_height = texture_fbo_height; - display->priv->use_fbo_scene_cb_v2 = cb; - display->priv->use_fbo_stuff = stuff; - gst_gl_window_send_message (display->gl_window, - GST_GL_WINDOW_CB (_use_fbo_v2), display); - } - isAlive = display->isAlive; - gst_gl_display_unlock (display); - - return isAlive; -} - -/* Called by gltestsrc and glfilter */ -void -gst_gl_display_del_fbo (GstGLDisplay * display, GLuint fbo, GLuint depth_buffer) -{ - gst_gl_display_lock (display); - if (display->isAlive) { - display->priv->del_fbo = fbo; - display->priv->del_depth_buffer = depth_buffer; - gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_del_fbo), - display); - } - gst_gl_display_unlock (display); -} - - -/* Called by glfilter */ -gboolean -gst_gl_display_gen_shader (GstGLDisplay * display, - const gchar * shader_vertex_source, - const gchar * shader_fragment_source, GstGLShader ** shader) -{ - gboolean isAlive; - - gst_gl_display_lock (display); - if (display->isAlive) { - display->priv->gen_shader_vertex_source = shader_vertex_source; - display->priv->gen_shader_fragment_source = shader_fragment_source; - gst_gl_window_send_message (display->gl_window, - GST_GL_WINDOW_CB (_gen_shader), display); - if (shader) - *shader = display->priv->gen_shader; - display->priv->gen_shader = NULL; - display->priv->gen_shader_vertex_source = NULL; - display->priv->gen_shader_fragment_source = NULL; - } - isAlive = display->isAlive; - gst_gl_display_unlock (display); - - return isAlive; -} - - -/* Called by glfilter */ -void -gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader) -{ - gst_gl_display_lock (display); - if (display->isAlive) { - display->priv->del_shader = shader; - gst_gl_window_send_message (display->gl_window, - GST_GL_WINDOW_CB (_del_shader), display); - } - gst_gl_display_unlock (display); -} - -gulong +guintptr gst_gl_display_get_internal_gl_context (GstGLDisplay * display) { gulong external_gl_context = 0; diff --git a/gst-libs/gst/gl/gstgldisplay.h b/gst-libs/gst/gl/gstgldisplay.h index a9778c5f32..6ea77101f3 100644 --- a/gst-libs/gst/gl/gstgldisplay.h +++ b/gst-libs/gst/gl/gstgldisplay.h @@ -31,6 +31,7 @@ typedef struct _GstGLShader GstGLShader; #include "gstglwindow.h" #include "gstglshader.h" +#include "gstglutils.h" G_BEGIN_DECLS @@ -63,37 +64,7 @@ typedef enum GST_GL_DISPLAY_CONVERSION_MESA, } GstGLDisplayConversion; -/** - * GstGLDisplayProjection: - * - * %GST_GL_DISPLAY_PROJECTION_ORTHO2D: Orthogonal projection - * %GST_GL_DISPLAY_CONVERSION_MATRIX: Perspective projection - */ -typedef enum -{ - GST_GL_DISPLAY_PROJECTION_ORTHO2D, - GST_GL_DISPLAY_PROJECTION_PERSPECTIVE -} GstGLDisplayProjection; -/** - * CRCB: - * @width: new width - * @height: new height: - * @data: user data - * - * client reshape callback - */ -typedef void (*CRCB) (GLuint width, GLuint height, gpointer data); -/** - * CDCB: - * @texture: texture to draw - * @width: new width - * @height: new height: - * @data: user data - * - * client draw callback - */ -typedef gboolean (*CDCB) (GLuint texture, GLuint width, GLuint height, gpointer data); /** * GstGLDisplayThreadFunc: * @display: a #GstGLDisplay @@ -103,24 +74,6 @@ typedef gboolean (*CDCB) (GLuint texture, GLuint width, GLuint height, gpointer */ typedef void (*GstGLDisplayThreadFunc) (GstGLDisplay * display, gpointer data); -/** - * GLCB: - * @width: the width - * @height: the height - * @texture: texture - * @stuff: user data - * - * callback definition for operating on textures - */ -typedef void (*GLCB) (gint, gint, guint, gpointer stuff); -/** - * GLCB_V2: - * @stuff: user data - * - * callback definition for operating through a Framebuffer object - */ -typedef void (*GLCB_V2) (gpointer stuff); - #define GST_GL_DISPLAY_ERR_MSG(obj) ("%s", GST_GL_DISPLAY_CAST(obj)->error_message) /** @@ -144,13 +97,9 @@ struct _GstGLDisplay /* gl API we are using */ GstGLAPI gl_api; - gboolean keep_aspect_ratio; - /* foreign gl context */ gulong external_gl_context; - GstGLDisplayConversion colorspace_conversion; - gchar *error_message; GstGLFuncs *gl_vtable; @@ -164,10 +113,6 @@ struct _GstGLDisplayClass GObjectClass object_class; }; - -/*-----------------------------------------------------------*\ - -------------------- Public declarations ------------------- -\*-----------------------------------------------------------*/ GstGLDisplay *gst_gl_display_new (void); gboolean gst_gl_display_create_context (GstGLDisplay * display, @@ -176,31 +121,6 @@ gboolean gst_gl_display_create_context (GstGLDisplay * display, void gst_gl_display_thread_add (GstGLDisplay * display, GstGLDisplayThreadFunc func, gpointer data); -void gst_gl_display_gen_texture (GstGLDisplay * display, GLuint * pTexture, - GstVideoFormat v_format, GLint width, GLint height); -void gst_gl_display_gen_texture_thread (GstGLDisplay * display, GLuint * pTexture, - GstVideoFormat v_format, GLint width, GLint height); -void gst_gl_display_del_texture (GstGLDisplay * display, GLuint * pTexture); - -gboolean gst_gl_display_gen_fbo (GstGLDisplay * display, gint width, gint height, - GLuint * fbo, GLuint * depthbuffer); -gboolean gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width, - gint texture_fbo_height, GLuint fbo, GLuint depth_buffer, - GLuint texture_fbo, GLCB cb, gint input_texture_width, - gint input_texture_height, GLuint input_texture, gdouble proj_param1, - gdouble proj_param2, gdouble proj_param3, gdouble proj_param4, - GstGLDisplayProjection projection, gpointer * stuff); -gboolean gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width, - gint texture_fbo_height, GLuint fbo, GLuint depth_buffer, - GLuint texture_fbo, GLCB_V2 cb, gpointer * stuff); -void gst_gl_display_del_fbo (GstGLDisplay * display, GLuint fbo, - GLuint depth_buffer); - -gboolean gst_gl_display_gen_shader (GstGLDisplay * display, - const gchar * shader_vertex_source, - const gchar * shader_fragment_source, GstGLShader ** shader); -void gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader); - gulong gst_gl_display_get_internal_gl_context (GstGLDisplay * display); void gst_gl_display_activate_gl_context (GstGLDisplay * display, gboolean activate); diff --git a/gst-libs/gst/gl/gstglupload.c b/gst-libs/gst/gl/gstglupload.c index d12692d3ca..18cb3696c7 100644 --- a/gst-libs/gst/gl/gstglupload.c +++ b/gst-libs/gst/gl/gstglupload.c @@ -692,8 +692,6 @@ _init_upload (GstGLDisplay * display, GstGLUpload * upload) GST_INFO ("We have OpenGL shaders"); - display->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_GLSL; - _init_upload_fbo (display, upload); switch (v_format) { @@ -977,10 +975,13 @@ _do_upload (GstGLDisplay * display, GstGLUpload * upload) case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_AYUV: { +#if 0 switch (display->colorspace_conversion) { case GST_GL_DISPLAY_CONVERSION_GLSL: /* color space conversion is needed */ +#endif upload->priv->draw (display, upload); +#if 0 break; case GST_GL_DISPLAY_CONVERSION_MATRIX: /* color space conversion is needed */ @@ -997,6 +998,7 @@ _do_upload (GstGLDisplay * display, GstGLUpload * upload) g_assert_not_reached (); break; } +#endif } break; default: @@ -1046,9 +1048,11 @@ _do_upload_make (GstGLDisplay * display, GstGLUpload * upload) in_width, in_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, NULL); break; case GST_VIDEO_FORMAT_YUY2: +#if 0 switch (display->colorspace_conversion) { case GST_GL_DISPLAY_CONVERSION_GLSL: case GST_GL_DISPLAY_CONVERSION_MATRIX: +#endif gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA, in_width, in_height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); @@ -1057,6 +1061,7 @@ _do_upload_make (GstGLDisplay * display, GstGLUpload * upload) gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, in_width, in_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); +#if 0 break; case GST_GL_DISPLAY_CONVERSION_MESA: gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, in_width, @@ -1068,11 +1073,14 @@ _do_upload_make (GstGLDisplay * display, GstGLUpload * upload) g_assert_not_reached (); break; } +#endif break; case GST_VIDEO_FORMAT_UYVY: +#if 0 switch (display->colorspace_conversion) { case GST_GL_DISPLAY_CONVERSION_GLSL: case GST_GL_DISPLAY_CONVERSION_MATRIX: +#endif glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_LUMINANCE_ALPHA, in_width, in_height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL); @@ -1081,6 +1089,7 @@ _do_upload_make (GstGLDisplay * display, GstGLUpload * upload) glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, in_width, in_height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL); +#if 0 break; case GST_GL_DISPLAY_CONVERSION_MESA: glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, in_width, @@ -1092,6 +1101,7 @@ _do_upload_make (GstGLDisplay * display, GstGLUpload * upload) g_assert_not_reached (); break; } +#endif break; case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: @@ -1160,10 +1170,13 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload) case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: case GST_VIDEO_FORMAT_AYUV: +#if 0 switch (display->colorspace_conversion) { case GST_GL_DISPLAY_CONVERSION_GLSL: case GST_GL_DISPLAY_CONVERSION_MATRIX: +#endif gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, upload->in_texture[0]); +#if 0 break; case GST_GL_DISPLAY_CONVERSION_MESA: if (in_width != out_width || in_height != out_height) @@ -1177,6 +1190,7 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload) g_assert_not_reached (); break; } +#endif break; default: gst_gl_display_set_error (display, "Unsupported upload video format %d", @@ -1216,9 +1230,11 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload) GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, upload->data[0]); break; case GST_VIDEO_FORMAT_YUY2: +#if 0 switch (display->colorspace_conversion) { case GST_GL_DISPLAY_CONVERSION_GLSL: case GST_GL_DISPLAY_CONVERSION_MATRIX: +#endif gl->TexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, in_height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, upload->data[0]); @@ -1226,6 +1242,7 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload) gl->TexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GST_ROUND_UP_2 (in_width) / 2, in_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, upload->data[0]); +#if 0 break; case GST_GL_DISPLAY_CONVERSION_MESA: gl->TexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, @@ -1238,11 +1255,14 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload) g_assert_not_reached (); break; } +#endif break; case GST_VIDEO_FORMAT_UYVY: +#if 0 switch (display->colorspace_conversion) { case GST_GL_DISPLAY_CONVERSION_GLSL: case GST_GL_DISPLAY_CONVERSION_MATRIX: +#endif gl->TexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, in_height, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, upload->data[0]); @@ -1250,6 +1270,7 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload) gl->TexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, GST_ROUND_UP_2 (in_width) / 2, in_height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, upload->data[0]); +#if 0 break; case GST_GL_DISPLAY_CONVERSION_MESA: gl->TexSubImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, in_width, @@ -1262,6 +1283,7 @@ _do_upload_fill (GstGLDisplay * display, GstGLUpload * upload) g_assert_not_reached (); break; } +#endif break; case GST_VIDEO_FORMAT_I420: { @@ -1399,10 +1421,12 @@ _do_upload_draw_opengl (GstGLDisplay * display, GstGLUpload * upload) case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_UYVY: { +#if 0 switch (display->colorspace_conversion) { case GST_GL_DISPLAY_CONVERSION_GLSL: case GST_GL_DISPLAY_CONVERSION_MATRIX: { +#endif gst_gl_shader_use (upload->shader); gl->MatrixMode (GL_PROJECTION); @@ -1431,6 +1455,7 @@ _do_upload_draw_opengl (GstGLDisplay * display, GstGLUpload * upload) GL_CLAMP_TO_EDGE); gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#if 0 } break; case GST_GL_DISPLAY_CONVERSION_MESA: @@ -1457,6 +1482,7 @@ _do_upload_draw_opengl (GstGLDisplay * display, GstGLUpload * upload) g_assert_not_reached (); break; } +#endif } break; @@ -1645,10 +1671,12 @@ _do_upload_draw_gles2 (GstGLDisplay * display, GstGLUpload * upload) case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_UYVY: { +#if 0 switch (display->colorspace_conversion) { case GST_GL_DISPLAY_CONVERSION_GLSL: case GST_GL_DISPLAY_CONVERSION_MATRIX: { +#endif gst_gl_shader_use (upload->shader); gl->VertexAttribPointer (upload->shader_attr_position_loc, 3, @@ -1682,6 +1710,7 @@ _do_upload_draw_gles2 (GstGLDisplay * display, GstGLUpload * upload) GL_CLAMP_TO_EDGE); gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); +#if 0 } break; case GST_GL_DISPLAY_CONVERSION_MESA: @@ -1704,6 +1733,7 @@ _do_upload_draw_gles2 (GstGLDisplay * display, GstGLUpload * upload) g_assert_not_reached (); break; } +#endif } break; diff --git a/gst-libs/gst/gl/gstglutils.c b/gst-libs/gst/gl/gstglutils.c new file mode 100644 index 0000000000..3e29c96888 --- /dev/null +++ b/gst-libs/gst/gl/gstglutils.c @@ -0,0 +1,677 @@ +/* + * GStreamer + * Copyright (C) 2013 Matthew Waters + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include + +#include + +#include "gstglutils.h" +#include "gstglfeature.h" + +#ifndef GL_FRAMEBUFFER_UNDEFINED +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#endif +#ifndef GL_FRAMEBUFFER_UNSUPPORTED +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#endif +#ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#endif + +#define USING_OPENGL(display) (display->gl_api & GST_GL_API_OPENGL) +#define USING_OPENGL3(display) (display->gl_api & GST_GL_API_OPENGL3) +#define USING_GLES(display) (display->gl_api & GST_GL_API_GLES) +#define USING_GLES2(display) (display->gl_api & GST_GL_API_GLES2) +#define USING_GLES3(display) (display->gl_api & GST_GL_API_GLES3) + +static GLuint gen_texture; +static GLuint gen_texture_width; +static GLuint gen_texture_height; +static GstVideoFormat gen_texture_video_format; + +/* filter gen fbo */ +static GLuint gen_fbo_width; +static GLuint gen_fbo_height; +static GLuint generated_fbo; +static GLuint generated_depth_buffer; + +/* filter use fbo */ +static GLuint use_fbo; +static GLuint use_depth_buffer; +static GLuint use_fbo_texture; +static GLuint use_fbo_width; +static GLuint use_fbo_height; +static GLCB use_fbo_scene_cb; +static GLCB_V2 use_fbo_scene_cb_v2; +static gdouble use_fbo_proj_param1; +static gdouble use_fbo_proj_param2; +static gdouble use_fbo_proj_param3; +static gdouble use_fbo_proj_param4; +static GstGLDisplayProjection use_fbo_projection; +static gpointer *use_fbo_stuff; +static GLuint input_texture_width; +static GLuint input_texture_height; +static GLuint input_texture; + +/* filter del fbo */ +static GLuint del_fbo; +static GLuint del_depth_buffer; + +/* action gen and del shader */ +static const gchar *gen_shader_fragment_source; +static const gchar *gen_shader_vertex_source; +static GstGLShader *gen_shader; +static GstGLShader *del_shader; + +static void _gen_fbo (GstGLDisplay * display); +static void _use_fbo (GstGLDisplay * display); +static void _use_fbo_v2 (GstGLDisplay * display); +static void _del_fbo (GstGLDisplay * display); +static void _gen_shader (GstGLDisplay * display); +static void _del_shader (GstGLDisplay * display); + +static void +gst_gl_display_gen_texture_window_cb (GstGLDisplay * display) +{ + gst_gl_display_gen_texture_thread (display, &gen_texture, + gen_texture_video_format, gen_texture_width, gen_texture_height); +} + +/* Generate a texture if no one is available in the pool + * Called in the gl thread */ +void +gst_gl_display_gen_texture_thread (GstGLDisplay * display, GLuint * pTexture, + GstVideoFormat v_format, GLint width, GLint height) +{ + const GstGLFuncs *gl = display->gl_vtable; + + GST_TRACE ("Generating texture format:%u dimensions:%ux%u", v_format, + width, height); + + gl->GenTextures (1, pTexture); + gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, *pTexture); + + switch (v_format) { + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + { + gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, + width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + break; + } + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_UYVY: + { +#if 0 + switch (display->colorspace_conversion) { + case GST_GL_DISPLAY_CONVERSION_GLSL: + case GST_GL_DISPLAY_CONVERSION_MATRIX: +#endif + gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, + width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); +#if 0 + break; + case GST_GL_DISPLAY_CONVERSION_MESA: + if (display->upload_width != display->upload_data_width || + display->upload_height != display->upload_data_height) + gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, + width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + else + gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_YCBCR_MESA, width, + height, 0, GL_YCBCR_MESA, GL_UNSIGNED_SHORT_8_8_MESA, NULL); + break; + default: + gst_gl_display_set_error (display, "Unknow colorspace conversion %d", + display->colorspace_conversion); + } +#endif + break; + } + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_AYUV: + { + gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, + width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + break; + } + default: + { + gst_gl_display_set_error (display, "Unsupported upload video format %d", + v_format); + break; + } + } + + gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + + GST_LOG ("generated texture id:%d", *pTexture); +} + +void +gst_gl_display_del_texture_thread (GstGLDisplay * display, GLuint * pTexture) +{ + //glDeleteTextures (1, pTexture); +} + +/* called in the gl thread */ +gboolean +gst_gl_display_check_framebuffer_status (GstGLDisplay * display) +{ + GLenum status = 0; + status = display->gl_vtable->CheckFramebufferStatus (GL_FRAMEBUFFER); + + switch (status) { + case GL_FRAMEBUFFER_COMPLETE: + return TRUE; + break; + + case GL_FRAMEBUFFER_UNSUPPORTED: + GST_ERROR ("GL_FRAMEBUFFER_UNSUPPORTED"); + break; + + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"); + break; + + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"); + break; + case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: + GST_ERROR ("GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"); + break; +#if GST_GL_HAVE_OPENGL + case GL_FRAMEBUFFER_UNDEFINED: + GST_ERROR ("GL_FRAMEBUFFER_UNDEFINED"); + break; +#endif + default: + GST_ERROR ("General FBO error"); + } + + return FALSE; +} + +void +gst_gl_display_gen_texture (GstGLDisplay * display, GLuint * pTexture, + GstVideoFormat v_format, GLint width, GLint height) +{ + gst_gl_display_lock (display); + + if (display->isAlive) { + gen_texture_width = width; + gen_texture_height = height; + gen_texture_video_format = v_format; + gst_gl_window_send_message (display->gl_window, + GST_GL_WINDOW_CB (gst_gl_display_gen_texture_window_cb), display); + *pTexture = gen_texture; + } else + *pTexture = 0; + + gst_gl_display_unlock (display); +} + +void +gst_gl_display_del_texture (GstGLDisplay * display, GLuint * pTexture) +{ + gst_gl_display_lock (display); + if (*pTexture) { + gst_gl_display_del_texture_thread (display, pTexture); + } + gst_gl_display_unlock (display); +} + +gboolean +gst_gl_display_gen_fbo (GstGLDisplay * display, gint width, gint height, + GLuint * fbo, GLuint * depthbuffer) +{ + gboolean isAlive = FALSE; + + gst_gl_display_lock (display); + if (display->isAlive) { + gen_fbo_width = width; + gen_fbo_height = height; + gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_gen_fbo), + display); + *fbo = generated_fbo; + *depthbuffer = generated_depth_buffer; + } + isAlive = display->isAlive; + gst_gl_display_unlock (display); + + return isAlive; +} + + +/* Called by glfilter */ +/* this function really has to be simplified... do we really need to + set projection this way? Wouldn't be better a set_projection + separate call? or just make glut functions available out of + gst-libs and call it if needed on drawcallback? -- Filippo */ +/* GLCB too.. I think that only needed parameters should be + * GstGLDisplay *display and gpointer data, or just gpointer data */ +/* ..everything here has to be simplified! */ +gboolean +gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width, + gint texture_fbo_height, GLuint fbo, GLuint depth_buffer, + GLuint texture_fbo, GLCB cb, gint input_tex_width, + gint input_tex_height, GLuint input_tex, gdouble proj_param1, + gdouble proj_param2, gdouble proj_param3, gdouble proj_param4, + GstGLDisplayProjection projection, gpointer * stuff) +{ + gboolean isAlive; + + gst_gl_display_lock (display); + if (display->isAlive) { + use_fbo = fbo; + use_depth_buffer = depth_buffer; + use_fbo_texture = texture_fbo; + use_fbo_width = texture_fbo_width; + use_fbo_height = texture_fbo_height; + use_fbo_scene_cb = cb; + use_fbo_proj_param1 = proj_param1; + use_fbo_proj_param2 = proj_param2; + use_fbo_proj_param3 = proj_param3; + use_fbo_proj_param4 = proj_param4; + use_fbo_projection = projection; + use_fbo_stuff = stuff; + input_texture_width = input_tex_width; + input_texture_height = input_tex_height; + input_texture = input_tex; + gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_use_fbo), + display); + } + isAlive = display->isAlive; + gst_gl_display_unlock (display); + + return isAlive; +} + +gboolean +gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width, + gint texture_fbo_height, GLuint fbo, GLuint depth_buffer, + GLuint texture_fbo, GLCB_V2 cb, gpointer * stuff) +{ + gboolean isAlive; + + gst_gl_display_lock (display); + if (display->isAlive) { + use_fbo = fbo; + use_depth_buffer = depth_buffer; + use_fbo_texture = texture_fbo; + use_fbo_width = texture_fbo_width; + use_fbo_height = texture_fbo_height; + use_fbo_scene_cb_v2 = cb; + use_fbo_stuff = stuff; + gst_gl_window_send_message (display->gl_window, + GST_GL_WINDOW_CB (_use_fbo_v2), display); + } + isAlive = display->isAlive; + gst_gl_display_unlock (display); + + return isAlive; +} + +/* Called by gltestsrc and glfilter */ +void +gst_gl_display_del_fbo (GstGLDisplay * display, GLuint fbo, GLuint depth_buffer) +{ + gst_gl_display_lock (display); + if (display->isAlive) { + del_fbo = fbo; + del_depth_buffer = depth_buffer; + gst_gl_window_send_message (display->gl_window, GST_GL_WINDOW_CB (_del_fbo), + display); + } + gst_gl_display_unlock (display); +} + + +/* Called by glfilter */ +gboolean +gst_gl_display_gen_shader (GstGLDisplay * display, + const gchar * shader_vertex_source, + const gchar * shader_fragment_source, GstGLShader ** shader) +{ + gboolean isAlive; + + gst_gl_display_lock (display); + if (display->isAlive) { + gen_shader_vertex_source = shader_vertex_source; + gen_shader_fragment_source = shader_fragment_source; + gst_gl_window_send_message (display->gl_window, + GST_GL_WINDOW_CB (_gen_shader), display); + if (shader) + *shader = gen_shader; + gen_shader = NULL; + gen_shader_vertex_source = NULL; + gen_shader_fragment_source = NULL; + } + isAlive = display->isAlive; + gst_gl_display_unlock (display); + + return isAlive; +} + + +/* Called by glfilter */ +void +gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader) +{ + gst_gl_display_lock (display); + if (display->isAlive) { + del_shader = shader; + gst_gl_window_send_message (display->gl_window, + GST_GL_WINDOW_CB (_del_shader), display); + } + gst_gl_display_unlock (display); +} + +void +_gen_fbo (GstGLDisplay * display) +{ + /* a texture must be attached to the FBO */ + const GstGLFuncs *gl = display->gl_vtable; + GLuint fake_texture = 0; + + GST_TRACE ("creating FBO dimensions:%ux%u", gen_fbo_width, gen_fbo_height); + + /* -- generate frame buffer object */ + + if (!gl->GenFramebuffers) { + gst_gl_display_set_error (display, + "Context, EXT_framebuffer_object not supported"); + return; + } + /* setup FBO */ + gl->GenFramebuffers (1, &generated_fbo); + gl->BindFramebuffer (GL_FRAMEBUFFER, generated_fbo); + + /* setup the render buffer for depth */ + gl->GenRenderbuffers (1, &generated_depth_buffer); + gl->BindRenderbuffer (GL_RENDERBUFFER, generated_depth_buffer); + + if (USING_OPENGL (display)) { + gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT, + gen_fbo_width, gen_fbo_height); + gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, + gen_fbo_width, gen_fbo_height); + } + if (USING_GLES2 (display)) { + gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, + gen_fbo_width, gen_fbo_height); + } + + /* setup a texture to render to */ + gl->GenTextures (1, &fake_texture); + gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, fake_texture); + gl->TexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA8, + gen_fbo_width, gen_fbo_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + GL_LINEAR); + gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + GL_LINEAR); + gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, + GL_CLAMP_TO_EDGE); + gl->TexParameteri (GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, + GL_CLAMP_TO_EDGE); + + /* attach the texture to the FBO to renderer to */ + gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_RECTANGLE_ARB, fake_texture, 0); + + /* attach the depth render buffer to the FBO */ + gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, generated_depth_buffer); + + if (USING_OPENGL (display)) { + gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, generated_depth_buffer); + } + + if (gl->CheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + gst_gl_display_set_error (display, "GL framebuffer status incomplete"); + + /* unbind the FBO */ + gl->BindFramebuffer (GL_FRAMEBUFFER, 0); + + gl->DeleteTextures (1, &fake_texture); +} + +static void +_use_fbo (GstGLDisplay * display) +{ + const GstGLFuncs *gl = display->gl_vtable; +#if GST_GL_HAVE_GLES2 + GLint viewport_dim[4]; +#endif + + GST_TRACE ("Binding v1 FBO %u dimensions:%ux%u with texture:%u " + "dimensions:%ux%u", use_fbo, use_fbo_width, + use_fbo_height, use_fbo_texture, + input_texture_width, input_texture_height); + + gl->BindFramebuffer (GL_FRAMEBUFFER, use_fbo); + + /*setup a texture to render to */ + gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, use_fbo_texture); + + /* attach the texture to the FBO to renderer to */ + gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_RECTANGLE_ARB, use_fbo_texture, 0); + + gst_gl_display_clear_shader (display); + + +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (display)) { + gl->PushAttrib (GL_VIEWPORT_BIT); + gl->MatrixMode (GL_PROJECTION); + gl->PushMatrix (); + gl->LoadIdentity (); + + switch (use_fbo_projection) { + case GST_GL_DISPLAY_PROJECTION_ORTHO2D: + gluOrtho2D (use_fbo_proj_param1, + use_fbo_proj_param2, use_fbo_proj_param3, use_fbo_proj_param4); + break; + case GST_GL_DISPLAY_PROJECTION_PERSPECTIVE: + gluPerspective (use_fbo_proj_param1, + use_fbo_proj_param2, use_fbo_proj_param3, use_fbo_proj_param4); + break; + default: + gst_gl_display_set_error (display, "Unknow fbo projection %d", + use_fbo_projection); + } + + gl->MatrixMode (GL_MODELVIEW); + gl->PushMatrix (); + gl->LoadIdentity (); + } +#endif +#if GST_GL_HAVE_GLES2 + if (USING_GLES2 (display)) + gl->GetIntegerv (GL_VIEWPORT, viewport_dim); +#endif + + gl->Viewport (0, 0, use_fbo_width, use_fbo_height); + +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (display)) { + const GLenum rt[] = { GL_COLOR_ATTACHMENT0 }; + gl->DrawBuffers (1, rt); + } +#endif + + gl->ClearColor (0.0, 0.0, 0.0, 0.0); + gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + use_fbo_scene_cb (input_texture_width, + input_texture_height, input_texture, use_fbo_stuff); + +#if GST_GL_HAVE_OPENGL + if (USING_OPENGL (display)) { + const GLenum rt[] = { GL_NONE }; + gl->DrawBuffers (1, rt); + gl->MatrixMode (GL_PROJECTION); + gl->PopMatrix (); + gl->MatrixMode (GL_MODELVIEW); + gl->PopMatrix (); + gl->PopAttrib (); + } +#endif +#if GST_GL_HAVE_GLES2 + if (USING_GLES2 (display)) { + gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2], + viewport_dim[3]); + } +#endif + + gl->BindFramebuffer (GL_FRAMEBUFFER, 0); +} + +/* Called in a gl thread + * Need full shader support */ +static void +_use_fbo_v2 (GstGLDisplay * display) +{ + const GstGLFuncs *gl = display->gl_vtable; + GLint viewport_dim[4]; + + GST_TRACE ("Binding v2 FBO %u dimensions:%ux%u with texture:%u ", + use_fbo, use_fbo_width, use_fbo_height, use_fbo_texture); + + gl->BindFramebuffer (GL_FRAMEBUFFER, use_fbo); + + /* setup a texture to render to */ + gl->BindTexture (GL_TEXTURE_RECTANGLE_ARB, use_fbo_texture); + + /* attach the texture to the FBO to renderer to */ + gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_RECTANGLE_ARB, use_fbo_texture, 0); + + gl->GetIntegerv (GL_VIEWPORT, viewport_dim); + + gl->Viewport (0, 0, use_fbo_width, use_fbo_height); + + gl->DrawBuffer (GL_COLOR_ATTACHMENT0); + + gl->ClearColor (0.0, 0.0, 0.0, 0.0); + gl->Clear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + /* the opengl scene */ + use_fbo_scene_cb_v2 (use_fbo_stuff); + + gl->DrawBuffer (GL_NONE); + + gl->Viewport (viewport_dim[0], viewport_dim[1], + viewport_dim[2], viewport_dim[3]); + + gl->BindFramebuffer (GL_FRAMEBUFFER, 0); +} + +/* Called in the gl thread */ +static void +_del_fbo (GstGLDisplay * display) +{ + const GstGLFuncs *gl = display->gl_vtable; + + GST_TRACE ("Deleting FBO %u", del_fbo); + + if (del_fbo) { + gl->DeleteFramebuffers (1, &del_fbo); + del_fbo = 0; + } + if (del_depth_buffer) { + gl->DeleteRenderbuffers (1, &del_depth_buffer); + del_depth_buffer = 0; + } +} + +/* Called in the gl thread */ +static void +_gen_shader (GstGLDisplay * display) +{ + const GstGLFuncs *gl = display->gl_vtable; + + GST_TRACE ("Generating shader %" GST_PTR_FORMAT, gen_shader); + + if (gl->CreateProgramObject || gl->CreateProgram) { + if (gen_shader_vertex_source || gen_shader_fragment_source) { + GError *error = NULL; + + gen_shader = gst_gl_shader_new (display); + + if (gen_shader_vertex_source) + gst_gl_shader_set_vertex_source (gen_shader, gen_shader_vertex_source); + + if (gen_shader_fragment_source) + gst_gl_shader_set_fragment_source (gen_shader, + gen_shader_fragment_source); + + gst_gl_shader_compile (gen_shader, &error); + if (error) { + gst_gl_display_set_error (display, "%s", error->message); + g_error_free (error); + error = NULL; + gst_gl_display_clear_shader (display); + g_object_unref (G_OBJECT (gen_shader)); + gen_shader = NULL; + } + } + } else { + gst_gl_display_set_error (display, + "One of the filter required ARB_fragment_shader"); + gen_shader = NULL; + } +} + +/* Called in the gl thread */ +static void +_del_shader (GstGLDisplay * display) +{ + GST_TRACE ("Deleting shader %" GST_PTR_FORMAT, del_shader); + + if (del_shader) { + g_object_unref (G_OBJECT (del_shader)); + del_shader = NULL; + } +} diff --git a/gst-libs/gst/gl/gstglutils.h b/gst-libs/gst/gl/gstglutils.h new file mode 100644 index 0000000000..69a02b74c1 --- /dev/null +++ b/gst-libs/gst/gl/gstglutils.h @@ -0,0 +1,102 @@ +/* + * GStreamer + * Copyright (C) 2013 Matthew Waters + * + * 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., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __GST_GL_UTILS_H__ +#define __GST_GL_UTILS_H__ + +typedef struct _GstGLDisplay GstGLDisplay; + +#include "gstgldisplay.h" + +/** + * GstGLDisplayProjection: + * + * %GST_GL_DISPLAY_PROJECTION_ORTHO2D: Orthogonal projection + * %GST_GL_DISPLAY_CONVERSION_MATRIX: Perspective projection + */ +typedef enum +{ + GST_GL_DISPLAY_PROJECTION_ORTHO2D, + GST_GL_DISPLAY_PROJECTION_PERSPECTIVE +} GstGLDisplayProjection; + +/** + * CRCB: + * @width: new width + * @height: new height: + * @data: user data + * + * client reshape callback + */ +typedef void (*CRCB) (GLuint width, GLuint height, gpointer data); +/** + * CDCB: + * @texture: texture to draw + * @width: new width + * @height: new height: + * @data: user data + * + * client draw callback + */ +typedef gboolean (*CDCB) (GLuint texture, GLuint width, GLuint height, gpointer data); +/** + * GLCB: + * @width: the width + * @height: the height + * @texture: texture + * @stuff: user data + * + * callback definition for operating on textures + */ +typedef void (*GLCB) (gint, gint, guint, gpointer stuff); +/** + * GLCB_V2: + * @stuff: user data + * + * callback definition for operating through a Framebuffer object + */ +typedef void (*GLCB_V2) (gpointer stuff); + +void gst_gl_display_gen_texture (GstGLDisplay * display, GLuint * pTexture, + GstVideoFormat v_format, GLint width, GLint height); +void gst_gl_display_gen_texture_thread (GstGLDisplay * display, GLuint * pTexture, + GstVideoFormat v_format, GLint width, GLint height); +void gst_gl_display_del_texture (GstGLDisplay * display, GLuint * pTexture); + +gboolean gst_gl_display_gen_fbo (GstGLDisplay * display, gint width, gint height, + GLuint * fbo, GLuint * depthbuffer); +gboolean gst_gl_display_use_fbo (GstGLDisplay * display, gint texture_fbo_width, + gint texture_fbo_height, GLuint fbo, GLuint depth_buffer, + GLuint texture_fbo, GLCB cb, gint input_texture_width, + gint input_texture_height, GLuint input_texture, gdouble proj_param1, + gdouble proj_param2, gdouble proj_param3, gdouble proj_param4, + GstGLDisplayProjection projection, gpointer * stuff); +gboolean gst_gl_display_use_fbo_v2 (GstGLDisplay * display, gint texture_fbo_width, + gint texture_fbo_height, GLuint fbo, GLuint depth_buffer, + GLuint texture_fbo, GLCB_V2 cb, gpointer * stuff); +void gst_gl_display_del_fbo (GstGLDisplay * display, GLuint fbo, + GLuint depth_buffer); + +gboolean gst_gl_display_gen_shader (GstGLDisplay * display, + const gchar * shader_vertex_source, + const gchar * shader_fragment_source, GstGLShader ** shader); +void gst_gl_display_del_shader (GstGLDisplay * display, GstGLShader * shader); + +#endif /* __GST_GL_UTILS_H__ */