gstglupload.c \
gstglwindow.c \
gstglapi.c \
- gstglfeature.c
+ gstglfeature.c \
+ gstglutils.c
libgstgl_@GST_API_VERSION@_la_LIBADD = \
$(GST_PLUGINS_BASE_LIBS) \
gstgldownload.h \
gstglupload.h \
gstglapi.h \
- gstglfeature.h
+ gstglfeature.h \
+ gstglutils.h
libgstgl_@GST_API_VERSION@_la_CFLAGS = \
$(GL_CFLAGS) \
#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)
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
{
/* 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;
};
/*------------------------------------------------------------
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;
}
}
-
-//------------------------------------------------------------
-//------------------ 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)
{
}
}
-
-/* Called in the gl thread */
void
gst_gl_display_thread_destroy_context (GstGLDisplay * display)
{
GST_INFO ("Context destroyed");
}
-
-void
-gst_gl_display_thread_run_generic (GstGLDisplay * display)
-{
- GST_TRACE ("running function:%p data:%p",
- display->priv->generic_callback, display->priv->data);
-
- 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;
- }
-}
+//------------------------------------------------------------
+//------------------ BEGIN GL THREAD PROCS -------------------
+//------------------------------------------------------------
/* 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_gl_display_set_error (GstGLDisplay * display, const char *format, ...)
{
- 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;
- }
-}
+ va_list args;
-//------------------------------------------------------------
-//------------------ BEGIN GL THREAD ACTIONS -----------------
-//------------------------------------------------------------
+ if (display->error_message)
+ g_free (display->error_message);
+ va_start (args, format);
+ display->error_message = g_strdup_vprintf (format, args);
+ va_end (args);
-//------------------------------------------------------------
-//---------------------- BEGIN PRIVATE -----------------------
-//------------------------------------------------------------
+ GST_WARNING ("%s", display->error_message);
-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);
+ display->isAlive = FALSE;
}
-/* 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)
+gst_gl_display_thread_run_generic (GstGLDisplay * display)
{
- 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);
-}
+ GST_TRACE ("running function:%p data:%p",
+ display->priv->generic_callback, display->priv->data);
-void
-gst_gl_display_del_texture_thread (GstGLDisplay * display, GLuint * pTexture)
-{
- //glDeleteTextures (1, pTexture);
+ display->priv->generic_callback (display, display->priv->data);
}
-
-/*------------------------------------------------------------
- --------------------- END PRIVATE -------------------------
- ----------------------------------------------------------*/
-
-
/*------------------------------------------------------------
--------------------- BEGIN PUBLIC -------------------------
----------------------------------------------------------*/
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)
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,
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;
#include "gstglwindow.h"
#include "gstglshader.h"
+#include "gstglutils.h"
G_BEGIN_DECLS
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
* @data: user data
*/
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)
/**
/* 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;
GObjectClass object_class;
};
-
-/*-----------------------------------------------------------*\
- -------------------- Public declarations -------------------
-\*-----------------------------------------------------------*/
GstGLDisplay *gst_gl_display_new (void);
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);
GST_INFO ("We have OpenGL shaders");
- display->colorspace_conversion = GST_GL_DISPLAY_CONVERSION_GLSL;
-
_init_upload_fbo (display, upload);
switch (v_format) {
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 */
g_assert_not_reached ();
break;
}
+#endif
}
break;
default:
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);
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,
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);
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,
g_assert_not_reached ();
break;
}
+#endif
break;
case GST_VIDEO_FORMAT_I420:
case GST_VIDEO_FORMAT_YV12:
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)
g_assert_not_reached ();
break;
}
+#endif
break;
default:
gst_gl_display_set_error (display, "Unsupported upload video format %d",
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]);
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,
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]);
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,
g_assert_not_reached ();
break;
}
+#endif
break;
case GST_VIDEO_FORMAT_I420:
{
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);
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:
g_assert_not_reached ();
break;
}
+#endif
}
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
gst_gl_shader_use (upload->shader);
gl->VertexAttribPointer (upload->shader_attr_position_loc, 3,
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:
g_assert_not_reached ();
break;
}
+#endif
}
break;
--- /dev/null
+/*
+ * GStreamer
+ * Copyright (C) 2013 Matthew Waters <ystreet00@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., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <stdio.h>
+
+#include <gst/gst.h>
+
+#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;
+ }
+}
--- /dev/null
+/*
+ * GStreamer
+ * Copyright (C) 2013 Matthew Waters <ystreet00@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., 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__ */