Commit 4bbda2b6 authored by Matthew Waters's avatar Matthew Waters 🐨 Committed by Tim-Philipp Müller

glframebuffer: rewrite for a more consistent API

Facilities are given to create fbo's and attach GL memory (renderbuffers
or textures).  It also keeps track of the renderable size for use with
effective use with glViewport().
parent 7f10822d
......@@ -184,35 +184,24 @@ gst_gl_filter_app_set_caps (GstGLFilter * filter, GstCaps * incaps,
return TRUE;
}
static void
_emit_draw_signal (guint tex, gint width, gint height, gpointer data)
{
GstGLFilterApp *app_filter = GST_GL_FILTER_APP (data);
gboolean drawn;
g_signal_emit (app_filter, gst_gl_filter_app_signals[CLIENT_DRAW_SIGNAL], 0,
tex, width, height, &drawn);
app_filter->default_draw = !drawn;
}
struct glcb2
{
GLCB func;
gpointer data;
GstGLFilterApp *app;
GstGLMemory *in_tex;
GstGLMemory *out_tex;
};
/* convenience functions to simplify filter development */
static void
_glcb2 (gpointer data)
static gboolean
_emit_draw_signal (gpointer data)
{
struct glcb2 *cb = data;
gboolean drawn;
g_signal_emit (cb->app, gst_gl_filter_app_signals[CLIENT_DRAW_SIGNAL], 0,
cb->in_tex->tex_id, gst_gl_memory_get_texture_width (cb->out_tex),
gst_gl_memory_get_texture_height (cb->out_tex), &drawn);
cb->func (gst_gl_memory_get_texture_width (cb->in_tex),
gst_gl_memory_get_texture_height (cb->in_tex), cb->in_tex->tex_id,
cb->data);
return !drawn;
}
static gboolean
......@@ -220,20 +209,18 @@ gst_gl_filter_app_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex,
GstGLMemory * out_tex)
{
GstGLFilterApp *app_filter = GST_GL_FILTER_APP (filter);
gboolean default_draw;
struct glcb2 cb;
cb.func = (GLCB) _emit_draw_signal;
cb.data = filter;
cb.app = app_filter;
cb.in_tex = in_tex;
cb.out_tex = out_tex;
//blocking call, use a FBO
gst_gl_context_use_fbo_v2 (GST_GL_BASE_FILTER (filter)->context,
GST_VIDEO_INFO_WIDTH (&filter->out_info),
GST_VIDEO_INFO_HEIGHT (&filter->out_info),
filter->fbo, filter->depthbuffer, out_tex->tex_id, _glcb2, &cb);
default_draw =
gst_gl_framebuffer_draw_to_texture (filter->fbo,
out_tex, _emit_draw_signal, &cb);
if (app_filter->default_draw) {
if (default_draw) {
gst_gl_filter_render_to_target_with_shader (filter, TRUE, in_tex, out_tex,
filter->default_shader);
}
......
......@@ -37,8 +37,6 @@ typedef struct _GstGLFilterAppClass GstGLFilterAppClass;
struct _GstGLFilterApp
{
GstGLFilter filter;
gboolean default_draw;
};
struct _GstGLFilterAppClass
......
......@@ -79,7 +79,7 @@ static gboolean gst_gl_filter_cube_set_caps (GstGLFilter * filter,
GstCaps * incaps, GstCaps * outcaps);
static void gst_gl_filter_cube_reset_gl (GstGLFilter * filter);
static gboolean gst_gl_filter_cube_init_shader (GstGLFilter * filter);
static void _callback (gpointer stuff);
static gboolean _callback (gpointer stuff);
static gboolean gst_gl_filter_cube_filter_texture (GstGLFilter * filter,
GstGLMemory * in_tex, GstGLMemory * out_tex);
......@@ -342,13 +342,8 @@ gst_gl_filter_cube_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex,
cube_filter->in_tex = in_tex;
/* blocking call, use a FBO */
gst_gl_context_use_fbo_v2 (GST_GL_BASE_FILTER (filter)->context,
GST_VIDEO_INFO_WIDTH (&filter->out_info),
GST_VIDEO_INFO_HEIGHT (&filter->out_info), filter->fbo,
filter->depthbuffer, out_tex->tex_id, _callback, (gpointer) cube_filter);
return TRUE;
return gst_gl_framebuffer_draw_to_texture (filter->fbo, out_tex, _callback,
cube_filter);
}
/* *INDENT-OFF* */
......@@ -440,7 +435,7 @@ _unbind_buffer (GstGLFilterCube * cube_filter)
gl->DisableVertexAttribArray (cube_filter->attr_texture);
}
static void
static gboolean
_callback (gpointer stuff)
{
GstGLFilter *filter = GST_GL_FILTER (stuff);
......@@ -516,4 +511,6 @@ _callback (gpointer stuff)
xrot += 0.3f;
yrot += 0.2f;
zrot += 0.4f;
return TRUE;
}
......@@ -73,7 +73,7 @@ static void gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter,
gint width, gint height, guint texture, gfloat center_x, gfloat center_y,
gfloat start_alpha, gfloat stop_alpha, gboolean reversed, gfloat rotation);
static void gst_gl_filter_glass_callback (gpointer stuff);
static gboolean gst_gl_filter_glass_callback (gpointer stuff);
/* *INDENT-OFF* */
static const gchar *glass_fragment_source =
......@@ -245,12 +245,8 @@ gst_gl_filter_glass_filter_texture (GstGLFilter * filter, GstGLMemory * in_tex,
glass_filter->in_tex = in_tex;
//blocking call, use a FBO
gst_gl_context_use_fbo_v2 (GST_GL_BASE_FILTER (filter)->context,
GST_VIDEO_INFO_WIDTH (&filter->out_info),
GST_VIDEO_INFO_HEIGHT (&filter->out_info),
filter->fbo, filter->depthbuffer, out_tex->tex_id,
gst_gl_filter_glass_callback, (gpointer) glass_filter);
gst_gl_framebuffer_draw_to_texture (filter->fbo, out_tex,
gst_gl_filter_glass_callback, glass_filter);
return TRUE;
}
......@@ -353,8 +349,7 @@ gst_gl_filter_glass_draw_video_plane (GstGLFilter * filter,
gl->DisableClientState (GL_COLOR_ARRAY);
}
//opengl scene, params: input texture (not the output filter->texture)
static void
static gboolean
gst_gl_filter_glass_callback (gpointer stuff)
{
static gint64 start_time = 0;
......@@ -376,7 +371,7 @@ gst_gl_filter_glass_callback (gpointer stuff)
time_left -= 1000000 / 25;
if (time_left > 2000) {
GST_LOG ("escape");
return;
return FALSE;
}
}
......@@ -408,4 +403,6 @@ gst_gl_filter_glass_callback (gpointer stuff)
gst_gl_context_clear_shader (GST_GL_BASE_FILTER (filter)->context);
gl->Disable (GL_BLEND);
return TRUE;
}
......@@ -410,8 +410,6 @@ static void
gst_gl_mixer_init (GstGLMixer * mix)
{
mix->priv = GST_GL_MIXER_GET_PRIVATE (mix);
mix->fbo = 0;
mix->depthbuffer = 0;
mix->priv->gl_resource_ready = FALSE;
g_mutex_init (&mix->priv->gl_resource_lock);
......@@ -512,33 +510,38 @@ gst_gl_mixer_get_output_buffer (GstVideoAggregator * videoaggregator,
return ret;
}
static void
_mixer_create_fbo (GstGLContext * context, GstGLMixer * mix)
{
GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix);
guint out_width = GST_VIDEO_INFO_WIDTH (&vagg->info);
guint out_height = GST_VIDEO_INFO_HEIGHT (&vagg->info);
mix->fbo =
gst_gl_framebuffer_new_with_default_depth (context, out_width,
out_height);
}
static gboolean
gst_gl_mixer_decide_allocation (GstGLBaseMixer * base_mix, GstQuery * query)
{
GstGLMixer *mix = GST_GL_MIXER (base_mix);
GstGLMixerClass *mixer_class = GST_GL_MIXER_GET_CLASS (mix);
GstVideoAggregator *vagg = GST_VIDEO_AGGREGATOR (mix);
GstGLContext *context = base_mix->context;
GstBufferPool *pool = NULL;
GstStructure *config;
GstCaps *caps;
guint min, max, size;
gboolean update_pool;
guint out_width, out_height;
out_width = GST_VIDEO_INFO_WIDTH (&vagg->info);
out_height = GST_VIDEO_INFO_HEIGHT (&vagg->info);
g_mutex_lock (&mix->priv->gl_resource_lock);
mix->priv->gl_resource_ready = FALSE;
if (mix->fbo) {
gst_gl_context_del_fbo (context, mix->fbo, mix->depthbuffer);
mix->fbo = 0;
mix->depthbuffer = 0;
}
if (mix->fbo)
gst_object_unref (mix->fbo);
if (!gst_gl_context_gen_fbo (context, out_width, out_height,
&mix->fbo, &mix->depthbuffer)) {
gst_gl_context_thread_add (context,
(GstGLContextThreadFunc) _mixer_create_fbo, mix);
if (!mix->fbo) {
g_cond_signal (&mix->priv->gl_resource_cond);
g_mutex_unlock (&mix->priv->gl_resource_lock);
goto context_error;
......@@ -735,14 +738,13 @@ gst_gl_mixer_stop (GstAggregator * agg)
{
GstGLMixer *mix = GST_GL_MIXER (agg);
GstGLMixerClass *mixer_class = GST_GL_MIXER_GET_CLASS (mix);
GstGLContext *context = GST_GL_BASE_MIXER (mix)->context;
if (mixer_class->reset)
mixer_class->reset (mix);
if (mix->fbo) {
gst_gl_context_del_fbo (context, mix->fbo, mix->depthbuffer);
mix->fbo = 0;
mix->depthbuffer = 0;
gst_object_unref (mix->fbo);
mix->fbo = NULL;
}
gst_gl_mixer_reset (mix);
......
......@@ -84,8 +84,7 @@ struct _GstGLMixer
{
GstGLBaseMixer vaggregator;
GLuint fbo;
GLuint depthbuffer;
GstGLFramebuffer *fbo;
GstCaps *out_caps;
......
......@@ -71,7 +71,7 @@ static gboolean gst_gl_mosaic_init_shader (GstGLMixer * mixer,
static gboolean gst_gl_mosaic_process_textures (GstGLMixer * mixer,
GstGLMemory * out_tex);
static void gst_gl_mosaic_callback (gpointer stuff);
static gboolean gst_gl_mosaic_callback (gpointer stuff);
//vertex source
static const gchar *mosaic_v_src =
......@@ -193,23 +193,31 @@ gst_gl_mosaic_init_shader (GstGLMixer * mixer, GstCaps * outcaps)
mosaic_v_src, mosaic_f_src, &mosaic->shader);
}
static void
_mosaic_render (GstGLContext * context, GstGLMosaic * mosaic)
{
GstGLMixer *mixer = GST_GL_MIXER (mosaic);
gst_gl_framebuffer_draw_to_texture (mixer->fbo, mosaic->out_tex,
gst_gl_mosaic_callback, mosaic);
}
static gboolean
gst_gl_mosaic_process_textures (GstGLMixer * mix, GstGLMemory * out_tex)
{
GstGLMosaic *mosaic = GST_GL_MOSAIC (mix);
GstGLContext *context = GST_GL_BASE_MIXER (mix)->context;
//blocking call, use a FBO
gst_gl_context_use_fbo_v2 (GST_GL_BASE_MIXER (mix)->context,
GST_VIDEO_INFO_WIDTH (&GST_VIDEO_AGGREGATOR (mix)->info),
GST_VIDEO_INFO_HEIGHT (&GST_VIDEO_AGGREGATOR (mix)->info), mix->fbo,
mix->depthbuffer, out_tex->tex_id, gst_gl_mosaic_callback,
(gpointer) mosaic);
mosaic->out_tex = out_tex;
gst_gl_context_thread_add (context, (GstGLContextThreadFunc) _mosaic_render,
mosaic);
return TRUE;
}
/* opengl scene, params: input texture (not the output mixer->texture) */
static void
static gboolean
gst_gl_mosaic_callback (gpointer stuff)
{
GstGLMosaic *mosaic = GST_GL_MOSAIC (stuff);
......@@ -345,4 +353,6 @@ gst_gl_mosaic_callback (gpointer stuff)
xrot += 0.6f;
yrot += 0.4f;
zrot += 0.8f;
return TRUE;
}
......@@ -107,7 +107,7 @@ static gboolean gst_gl_test_src_stop (GstBaseSrc * basesrc);
static gboolean gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc,
GstQuery * query);
static void gst_gl_test_src_callback (gpointer stuff);
static gboolean gst_gl_test_src_callback (gpointer stuff);
static gboolean gst_gl_test_src_init_shader (GstGLTestSrc * gltestsrc);
......@@ -454,22 +454,24 @@ gst_gl_test_src_init_shader (GstGLTestSrc * gltestsrc)
return TRUE;
}
static void
_fill_gl (GstGLContext * context, GstGLTestSrc * src)
{
src->gl_result = gst_gl_framebuffer_draw_to_texture (src->fbo, src->out_tex,
gst_gl_test_src_callback, src);
}
static GstFlowReturn
gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
{
GstGLTestSrc *src = GST_GL_TEST_SRC (psrc);
GstClockTime next_time;
gint width, height;
GstVideoFrame out_frame;
GstGLSyncMeta *sync_meta;
guint out_tex;
if (G_UNLIKELY (!src->negotiated || !src->context))
goto not_negotiated;
width = GST_VIDEO_INFO_WIDTH (&src->out_info);
height = GST_VIDEO_INFO_HEIGHT (&src->out_info);
/* 0 framerate and we are at the second frame, eos */
if (G_UNLIKELY (GST_VIDEO_INFO_FPS_N (&src->out_info) == 0
&& src->n_frames == 1))
......@@ -480,11 +482,11 @@ gst_gl_test_src_fill (GstPushSrc * psrc, GstBuffer * buffer)
return GST_FLOW_NOT_NEGOTIATED;
}
out_tex = *(guint *) out_frame.data[0];
src->out_tex = (GstGLMemory *) out_frame.map[0].memory;
if (!gst_gl_context_use_fbo_v2 (src->context, width, height, src->fbo,
src->depthbuffer, out_tex, gst_gl_test_src_callback,
(gpointer) src)) {
gst_gl_context_thread_add (src->context, (GstGLContextThreadFunc) _fill_gl,
src);
if (!src->gl_result) {
gst_video_frame_unmap (&out_frame);
goto gl_error;
}
......@@ -562,8 +564,11 @@ gst_gl_test_src_stop (GstBaseSrc * basesrc)
gst_object_unref (src->shader);
src->shader = NULL;
}
//blocking call, delete the FBO
gst_gl_context_del_fbo (src->context, src->fbo, src->depthbuffer);
if (src->fbo)
gst_object_unref (src->fbo);
src->fbo = NULL;
gst_object_unref (src->context);
src->context = NULL;
}
......@@ -615,6 +620,14 @@ _find_local_gl_context (GstGLTestSrc * src)
return FALSE;
}
static void
_src_generate_fbo_gl (GstGLContext * context, GstGLTestSrc * src)
{
src->fbo = gst_gl_framebuffer_new_with_default_depth (src->context,
GST_VIDEO_INFO_WIDTH (&src->out_info),
GST_VIDEO_INFO_HEIGHT (&src->out_info));
}
static gboolean
gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, GstQuery * query)
{
......@@ -625,7 +638,6 @@ gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, GstQuery * query)
guint min, max, size;
gboolean update_pool;
GError *error = NULL;
guint out_width, out_height;
if (!gst_gl_ensure_element_data (src, &src->display, &src->other_context))
return FALSE;
......@@ -658,11 +670,9 @@ gst_gl_test_src_decide_allocation (GstBaseSrc * basesrc, GstQuery * query)
if ((gst_gl_context_get_gl_api (src->context) & SUPPORTED_GL_APIS) == 0)
goto unsupported_gl_api;
out_width = GST_VIDEO_INFO_WIDTH (&src->out_info);
out_height = GST_VIDEO_INFO_HEIGHT (&src->out_info);
if (!gst_gl_context_gen_fbo (src->context, out_width, out_height,
&src->fbo, &src->depthbuffer))
gst_gl_context_thread_add (src->context,
(GstGLContextThreadFunc) _src_generate_fbo_gl, src);
if (!src->fbo)
goto context_error;
gst_query_parse_allocation (query, &caps, NULL);
......@@ -735,8 +745,7 @@ context_error:
}
}
//opengl scene
static void
static gboolean
gst_gl_test_src_callback (gpointer stuff)
{
GstGLTestSrc *src = GST_GL_TEST_SRC (stuff);
......@@ -752,21 +761,18 @@ gst_gl_test_src_callback (gpointer stuff)
if (funcs == NULL) {
GST_ERROR_OBJECT (src, "Could not find an implementation of the "
"requested pattern");
src->gl_result = FALSE;
return;
return FALSE;
}
src->src_impl = funcs->new (src);
if (!(src->gl_result =
funcs->init (src->src_impl, src->context, &src->out_info))) {
GST_ERROR_OBJECT (src, "Failed to initialize pattern");
return;
return FALSE;
}
src->active_pattern = src->set_pattern;
}
src->gl_result = funcs->fill_bound_fbo (src->src_impl);
if (!src->gl_result)
GST_ERROR_OBJECT (src, "Failed to render the pattern");
return funcs->fill_bound_fbo (src->src_impl);
}
static GstStateChangeReturn
......
......@@ -62,8 +62,8 @@ struct _GstGLTestSrc {
/* video state */
GstVideoInfo out_info;
GLuint fbo;
GLuint depthbuffer;
GstGLFramebuffer *fbo;
GstGLMemory *out_tex;
GstGLShader *shader;
......
......@@ -97,7 +97,7 @@ static gboolean gst_gl_transformation_decide_allocation (GstBaseTransform *
static void gst_gl_transformation_reset_gl (GstGLFilter * filter);
static gboolean gst_gl_transformation_stop (GstBaseTransform * trans);
static gboolean gst_gl_transformation_init_shader (GstGLFilter * filter);
static void gst_gl_transformation_callback (gpointer stuff);
static gboolean gst_gl_transformation_callback (gpointer stuff);
static void gst_gl_transformation_build_mvp (GstGLTransformation *
transformation);
......@@ -789,13 +789,8 @@ gst_gl_transformation_filter_texture (GstGLFilter * filter,
transformation->in_tex = in_tex;
/* blocking call, use a FBO */
gst_gl_context_use_fbo_v2 (GST_GL_BASE_FILTER (filter)->context,
GST_VIDEO_INFO_WIDTH (&filter->out_info),
GST_VIDEO_INFO_HEIGHT (&filter->out_info),
filter->fbo, filter->depthbuffer,
out_tex->tex_id, gst_gl_transformation_callback,
(gpointer) transformation);
gst_gl_framebuffer_draw_to_texture (filter->fbo, out_tex,
(GstGLFramebufferFunc) gst_gl_transformation_callback, transformation);
return TRUE;
}
......@@ -857,7 +852,7 @@ _unbind_buffer (GstGLTransformation * transformation)
gl->DisableVertexAttribArray (transformation->attr_texture);
}
static void
static gboolean
gst_gl_transformation_callback (gpointer stuff)
{
GstGLFilter *filter = GST_GL_FILTER (stuff);
......@@ -925,4 +920,6 @@ gst_gl_transformation_callback (gpointer stuff)
gst_gl_context_clear_shader (GST_GL_BASE_FILTER (filter)->context);
transformation->caps_change = FALSE;
return TRUE;
}
......@@ -475,7 +475,7 @@ static gboolean gst_gl_video_mixer_init_shader (GstGLMixer * mixer,
static gboolean gst_gl_video_mixer_process_textures (GstGLMixer * mixer,
GstGLMemory * out_tex);
static void gst_gl_video_mixer_callback (gpointer stuff);
static gboolean gst_gl_video_mixer_callback (gpointer stuff);
/* *INDENT-OFF* */
......@@ -1155,16 +1155,25 @@ gst_gl_video_mixer_init_shader (GstGLMixer * mixer, GstCaps * outcaps)
video_mixer_f_src, &video_mixer->shader);
}
static void
_video_mixer_process_gl (GstGLContext * context, GstGLVideoMixer * video_mixer)
{
GstGLMixer *mixer = GST_GL_MIXER (video_mixer);
gst_gl_framebuffer_draw_to_texture (mixer->fbo, video_mixer->out_tex,
gst_gl_video_mixer_callback, video_mixer);
}
static gboolean
gst_gl_video_mixer_process_textures (GstGLMixer * mix, GstGLMemory * out_tex)
{
GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (mix);
GstGLContext *context = GST_GL_BASE_MIXER (mix)->context;
video_mixer->out_tex = out_tex;
gst_gl_context_use_fbo_v2 (GST_GL_BASE_MIXER (mix)->context,
GST_VIDEO_INFO_WIDTH (&GST_VIDEO_AGGREGATOR (mix)->info),
GST_VIDEO_INFO_HEIGHT (&GST_VIDEO_AGGREGATOR (mix)->info),
mix->fbo, mix->depthbuffer,
out_tex->tex_id, gst_gl_video_mixer_callback, (gpointer) video_mixer);
gst_gl_context_thread_add (context,
(GstGLContextThreadFunc) _video_mixer_process_gl, video_mixer);
return TRUE;
}
......@@ -1383,7 +1392,7 @@ _set_blend_state (GstGLVideoMixer * video_mixer, GstGLVideoMixerPad * mix_pad)
}
/* opengl scene, params: input texture (not the output mixer->texture) */
static void
static gboolean
gst_gl_video_mixer_callback (gpointer stuff)
{
GstGLVideoMixer *video_mixer = GST_GL_VIDEO_MIXER (stuff);
......@@ -1411,7 +1420,7 @@ gst_gl_video_mixer_callback (gpointer stuff)
}
if (!_draw_background (video_mixer))
return;
return FALSE;
gst_gl_shader_use (video_mixer->shader);
......@@ -1546,4 +1555,6 @@ gst_gl_video_mixer_callback (gpointer stuff)
gl->Disable (GL_BLEND);
gst_gl_context_clear_shader (GST_GL_BASE_MIXER (mixer)->context);
return TRUE;
}
......@@ -125,6 +125,7 @@ struct _GstGLVideoMixer
GLuint vao;
GLuint vbo_indices;
GLuint checker_vbo;
GstGLMemory *out_tex;
};
struct _GstGLVideoMixerClass
......
......@@ -63,6 +63,10 @@ typedef struct _GstGLRenderbuffer GstGLRenderbuffer;
typedef struct _GstGLRenderbufferAllocator GstGLRenderbufferAllocator;
typedef struct _GstGLRenderbufferAllocatorClass GstGLRenderbufferAllocatorClass;
typedef struct _GstGLFramebuffer GstGLFramebuffer;
typedef struct _GstGLFramebufferAllocator GstGLFramebufferAllocator;
typedef struct _GstGLFramebufferAllocatorClass GstGLFramebufferAllocatorClass;
typedef struct _GstGLSLStage GstGLSLStage;
typedef struct _GstGLSLStagePrivate GstGLSLStagePrivate;
typedef struct _GstGLSLStageClass GstGLSLStageClass;
......
......@@ -549,11 +549,9 @@ gst_gl_color_convert_reset (GstGLColorConvert * convert)
{
guint i;
if (convert->fbo || convert->depth_buffer) {
gst_gl_context_del_fbo (convert->context, convert->fbo,
convert->depth_buffer);
convert->fbo = 0;
convert->depth_buffer = 0;
if (convert->fbo) {
gst_object_unref (convert->fbo);
convert->fbo = NULL;
}
for (i = 0; i < convert->priv->convert_info.out_n_textures; i++) {
......@@ -2027,7 +2025,7 @@ _init_convert (GstGLColorConvert * convert)
gst_gl_context_clear_shader (convert->context);
if (convert->fbo == 0 && !_init_convert_fbo (convert)) {
if (convert->fbo == NULL && !_init_convert_fbo (convert)) {
goto error;
}
......@@ -2088,82 +2086,16 @@ incompatible_api:
static gboolean
_init_convert_fbo (GstGLColorConvert * convert)
{
GstGLFuncs *gl;
guint out_width, out_height;
GLuint fake_texture = 0; /* a FBO must hava texture to init */
GLenum internal_format;
gl = convert->context->gl_vtable;
out_width = GST_VIDEO_INFO_WIDTH (&convert->out_info);
out_height = GST_VIDEO_INFO_HEIGHT (&convert->out_info);
if (!gl->GenFramebuffers) {
/* turn off the pipeline because Frame buffer object is a not present */
gst_gl_context_set_error (convert->context,
"Context, EXT_framebuffer_object supported: no");
return FALSE;
}
GST_INFO ("Context, EXT_framebuffer_object supported: yes");
/* setup FBO */
gl->GenFramebuffers (1, &convert->fbo);
gl->BindFramebuffer (GL_FRAMEBUFFER, convert->fbo);
convert->fbo =
gst_gl_framebuffer_new_with_default_depth (convert->context, out_width,
out_height);
/* setup the render buffer for depth */
gl->GenRenderbuffers (1, &convert->depth_buffer);
gl->BindRenderbuffer (GL_RENDERBUFFER, convert->depth_buffer);
if (USING_OPENGL (convert->context) || USING_OPENGL3 (convert->context)) {
gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH24_STENCIL8,
out_width, out_height);
}
if (USING_GLES2 (convert->context)) {
gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
out_width, out_height);
}
/* a fake texture is attached to the convert FBO (cannot init without it) */
gl->GenTextures (1, &fake_texture);
gl->BindTexture (GL_TEXTURE_2D, fake_texture);
internal_format =
gst_gl_sized_gl_format_from_gl_format_type (convert->context, GL_RGBA,
GL_UNSIGNED_BYTE);
gl->TexImage2D (GL_TEXTURE_2D, 0, internal_format, out_width, out_height, 0,
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl->TexParameteri (GL_TEXTURE_2D, 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_2D, fake_texture, 0);
/* attach the depth render buffer to the FBO */
gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, convert->depth_buffer);
if (USING_OPENGL (convert->context)) {
gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
GL_RENDERBUFFER, convert->depth_buffer);
}
if (!gst_gl_context_check_framebuffer_status (convert->context)) {
gst_gl_context_set_error (convert->context,
"GL framebuffer status incomplete");
gl->DeleteTextures (1, &fake_texture);
return FALSE;
}
/* unbind the FBO */
gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
gl->DeleteTextures (1, &fake_texture);
return TRUE;
return convert->fbo != NULL;
}
static gboolean
......@@ -2487,21 +2419,13 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
gl = context->gl_vtable;
out_width = GST_VIDEO_INFO_WIDTH (&convert->out_info);
out_height = GST_VIDEO_INFO_HEIGHT (&convert->out_info);
gl->BindFramebuffer (GL_FRAMEBUFFER, convert->fbo);
gst_gl_framebuffer_bind (convert->fbo);
/* attach the texture to the FBO to renderer to */
for (i = 0; i < c_info->out_n_textures; i++) {
guint gl_target =
gst_gl_texture_target_to_gl (convert->priv->to_texture_target);
/* needed? */
gl->BindTexture (gl_target, convert->priv->out_tex[i]->tex_id);
GstGLBaseMemory *tex = (GstGLBaseMemory *) convert->priv->out_tex[i];
gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i,
gl_target, convert->priv->out_tex[i]->tex_id, 0);
gst_gl_framebuffer_attach (convert->fbo, GL_COLOR_ATTACHMENT0 + i, tex);
}
if (gl->DrawBuffers)
......@@ -2511,6 +2435,8 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
gst_gl_framebuffer_get_effective_dimensions (convert->fbo, &out_width,
&out_height);
gl->Viewport (0, 0, out_width, out_height);