gl: Don't restore the viewport on function exit

Doing so involves retrieving the current viewport from OpenGL which as
with any glGet operation, is expensive.

This means that the various sinks need to reset the viewport on draw.

In the process, fix resizing on cocoa.
This commit is contained in:
Matthew Waters 2019-03-05 16:13:15 +11:00
parent 7bcd72f5b6
commit 6a37bf9bb9
10 changed files with 93 additions and 29 deletions

View file

@ -2187,6 +2187,16 @@ gst_glimage_sink_on_resize (GstGLImageSink * gl_sink, gint width, gint height)
GST_DEBUG_OBJECT (gl_sink, "GL output area now %u,%u %ux%u",
gl_sink->display_rect.x, gl_sink->display_rect.y,
gl_sink->display_rect.w, gl_sink->display_rect.h);
} else {
gint viewport_dims[4];
/* save the viewport for use later */
gl->GetIntegerv (GL_VIEWPORT, viewport_dims);
gl_sink->display_rect.x = viewport_dims[0];
gl_sink->display_rect.y = viewport_dims[1];
gl_sink->display_rect.w = viewport_dims[2];
gl_sink->display_rect.h = viewport_dims[3];
}
GST_GLIMAGE_SINK_UNLOCK (gl_sink);
}
@ -2234,6 +2244,10 @@ gst_glimage_sink_on_draw (GstGLImageSink * gl_sink)
gst_gl_context_clear_shader (gl_sink->context);
gl->BindTexture (gl_target, 0);
if (!gst_gl_window_controls_viewport (window))
gl->Viewport (gl_sink->display_rect.x, gl_sink->display_rect.y,
gl_sink->display_rect.w, gl_sink->display_rect.h);
sample = gst_sample_new (gl_sink->stored_buffer[0],
gl_sink->out_caps, &GST_BASE_SINK (gl_sink)->segment, NULL);
g_signal_emit (gl_sink, gst_glimage_sink_signals[CLIENT_DRAW_SIGNAL], 0,

View file

@ -206,15 +206,21 @@ _context_ready (gpointer data)
* the CA viewport set up on entry to this function */
gl->GetIntegerv (GL_VIEWPORT, ca_viewport);
GST_TRACE ("retrieved viewport from CA %u,%u %ux%u", self->expected_dims[0],
self->expected_dims[1], self->expected_dims[2], self->expected_dims[3]);
gst_gl_context_activate (self->draw_context, TRUE);
if (self->queue_resize || self->last_bounds.size.width != self.bounds.size.width
|| self->last_bounds.size.height != self.bounds.size.height) {
if (self->resize_cb) {
self->resize_cb (self->resize_data,
self->resize_cb (self->resize_data,
self.bounds.size.width*self.contentsScale,
self.bounds.size.height*self.contentsScale);
gl->GetIntegerv (GL_VIEWPORT, self->expected_dims);
GST_LOG ("resize callback wants viewport %u,%u %ux%u",
self->expected_dims[0], self->expected_dims[1],
self->expected_dims[2], self->expected_dims[3]);
} else {
/* default to whatever ca gives us */
self->expected_dims[0] = ca_viewport[0];
@ -239,6 +245,8 @@ _context_ready (gpointer data)
gst_video_sink_center_rect (src, dst, &result, TRUE);
GST_TRACE ("Using viewport %u,%u %ux%u", result.x, result.y, result.w,
result.h);
gl->Viewport (result.x, result.y, result.w, result.h);
if (self->draw_cb)

View file

@ -81,6 +81,8 @@ static void gst_gl_window_cocoa_send_message_async (GstGLWindow * window,
GstGLWindowCB callback, gpointer data, GDestroyNotify destroy);
static gboolean gst_gl_window_cocoa_set_render_rectangle (GstGLWindow * window,
gint x, gint y, gint width, gint height);
static gboolean gst_gl_window_cocoa_controls_viewport (GstGLWindow * window);
struct _GstGLWindowCocoaPrivate
{
@ -125,6 +127,8 @@ gst_gl_window_cocoa_class_init (GstGLWindowCocoaClass * klass)
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_send_message_async);
window_class->set_render_rectangle =
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_set_render_rectangle);
window_class->controls_viewport =
GST_DEBUG_FUNCPTR (gst_gl_window_cocoa_controls_viewport);
gobject_class->finalize = gst_gl_window_cocoa_finalize;
}
@ -387,9 +391,11 @@ gst_gl_cocoa_draw_cb (GstGLWindowCocoa *window_cocoa)
GstGLNSWindow *internal_win_id = (__bridge GstGLNSWindow *)priv->internal_win_id;
if (internal_win_id && ![internal_win_id isClosed]) {
GstGLWindow *window = GST_GL_WINDOW (window_cocoa);
GstGLWindow *window = GST_GL_WINDOW (window_cocoa);
/* draw opengl scene in the back buffer */
/* We do not need to change viewports like in other window implementations
* as the caopengllayer will take care of that for us. */
if (window->draw)
window->draw (window->draw_data);
}
@ -409,6 +415,7 @@ gst_gl_cocoa_resize_cb (GstGLNSView * view, guint width, guint height)
NSRect bounds = [view bounds];
NSRect visibleRect = [view visibleRect];
gint viewport_dim[4];
GstVideoRectangle viewport;
gl = context->gl_vtable;
@ -417,19 +424,30 @@ gst_gl_cocoa_resize_cb (GstGLNSView * view, guint width, guint height)
visibleRect = [view convertRectToBacking:visibleRect];
#endif
/* don't use the default gst_gl_window_resize() as that will marshal through
* the GL thread. We are being called from the main thread by the
* caopengllayer */
if (window->resize)
window->resize (window->resize_data, width, height);
gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
GST_DEBUG_OBJECT (window, "Window resized: bounds %lf %lf %lf %lf "
"visibleRect %lf %lf %lf %lf",
"visibleRect %lf %lf %lf %lf, "
"viewport dimensions %i %i %i %i",
bounds.origin.x, bounds.origin.y,
bounds.size.width, bounds.size.height,
visibleRect.origin.x, visibleRect.origin.y,
visibleRect.size.width, visibleRect.size.height);
visibleRect.size.width, visibleRect.size.height,
viewport_dim[0], viewport_dim[1], viewport_dim[2],
viewport_dim[3]);
gst_gl_window_resize (window, width, height);
gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
viewport.x = viewport_dim[0] - visibleRect.origin.x;
viewport.x = viewport_dim[1] - visibleRect.origin.y;
viewport.w = viewport_dim[2];
viewport.h = viewport_dim[3];
gl->Viewport (viewport_dim[0] - visibleRect.origin.x,
viewport_dim[1] - visibleRect.origin.y,
viewport_dim[2], viewport_dim[3]);
gl->Viewport (viewport.x, viewport.y, viewport.w, viewport.h);
}
gst_object_unref (context);
@ -532,6 +550,12 @@ gst_gl_window_cocoa_set_render_rectangle (GstGLWindow * window, gint x, gint y,
return TRUE;
}
static gboolean
gst_gl_window_cocoa_controls_viewport (GstGLWindow * window)
{
return TRUE;
}
/* =============================================================*/
/* */
/* GstGLNSWindow implementation */

View file

@ -2531,8 +2531,6 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
gint i;
gboolean ret = TRUE;
GLint viewport_dim[4] = { 0 };
GLenum multipleRT[] = {
GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
@ -2555,8 +2553,6 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
else if (gl->DrawBuffer)
gl->DrawBuffer (GL_COLOR_ATTACHMENT0);
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);
@ -2598,9 +2594,6 @@ _do_convert_draw (GstGLContext * context, GstGLColorConvert * convert)
/* we are done with the shader */
gst_gl_context_clear_shader (context);
gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
viewport_dim[3]);
if (!gst_gl_context_check_framebuffer_status (context, GL_FRAMEBUFFER))
ret = FALSE;

View file

@ -269,7 +269,6 @@ gboolean
gst_gl_framebuffer_draw_to_texture (GstGLFramebuffer * fb, GstGLMemory * mem,
GstGLFramebufferFunc func, gpointer user_data)
{
GLint viewport_dim[4] = { 0 };
const GstGLFuncs *gl;
gboolean ret;
@ -285,7 +284,6 @@ gst_gl_framebuffer_draw_to_texture (GstGLFramebuffer * fb, GstGLMemory * mem,
gst_gl_framebuffer_bind (fb);
gst_gl_framebuffer_attach (fb, GL_COLOR_ATTACHMENT0, (GstGLBaseMemory *) mem);
gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
gl->Viewport (0, 0, fb->priv->effective_width, fb->priv->effective_height);
if (gst_gl_context_get_gl_api (fb->context) & (GST_GL_API_OPENGL |
GST_GL_API_OPENGL3))
@ -296,8 +294,6 @@ gst_gl_framebuffer_draw_to_texture (GstGLFramebuffer * fb, GstGLMemory * mem,
if (gst_gl_context_get_gl_api (fb->context) & (GST_GL_API_OPENGL |
GST_GL_API_OPENGL3))
gl->DrawBuffer (GL_COLOR_ATTACHMENT0);
gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
viewport_dim[3]);
gst_gl_context_clear_framebuffer (fb->context);
return ret;

View file

@ -1850,7 +1850,6 @@ _do_view_convert_draw (GstGLContext * context, GstGLViewConvert * viewconvert)
GstGLFuncs *gl;
guint out_width, out_height;
gint out_views, i;
GLint viewport_dim[4] = { 0 };
GLenum multipleRT[] = {
GL_COLOR_ATTACHMENT0,
GL_COLOR_ATTACHMENT1,
@ -1886,7 +1885,6 @@ _do_view_convert_draw (GstGLContext * context, GstGLViewConvert * viewconvert)
gst_gl_framebuffer_get_effective_dimensions (viewconvert->fbo, &out_width,
&out_height);
gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
gl->Viewport (0, 0, out_width, out_height);
gst_gl_shader_use (viewconvert->shader);
@ -1934,8 +1932,6 @@ _do_view_convert_draw (GstGLContext * context, GstGLViewConvert * viewconvert)
gl->DrawBuffer (GL_COLOR_ATTACHMENT0);
/* we are done with the shader */
gst_gl_context_clear_shader (context);
gl->Viewport (viewport_dim[0], viewport_dim[1], viewport_dim[2],
viewport_dim[3]);
gst_gl_context_clear_framebuffer (context);
return TRUE;

View file

@ -975,6 +975,20 @@ gst_gl_window_resize (GstGLWindow * window, guint width, guint height)
window->queue_resize = FALSE;
}
gboolean
gst_gl_window_controls_viewport (GstGLWindow * window)
{
GstGLWindowClass *window_class;
g_return_val_if_fail (GST_IS_GL_WINDOW (window), FALSE);
window_class = GST_GL_WINDOW_GET_CLASS (window);
if (!window_class->controls_viewport)
return FALSE;
return window_class->controls_viewport (window);
}
static GType gst_gl_dummy_window_get_type (void);
G_DEFINE_TYPE (GstGLDummyWindow, gst_gl_dummy_window, GST_TYPE_GL_WINDOW);

View file

@ -148,6 +148,8 @@ struct _GstGLWindow {
* @show: request that the window be shown to the user
* @set_render_rectangle: request a rectangle to render into. See #GstVideoOverlay
* @queue_resize: request a resize to occur when possible
* @controls_viewport: Whether the window takes care of glViewport setup.
* and the user does not need to deal with viewports
*/
struct _GstGLWindowClass {
GstObjectClass parent_class;
@ -168,9 +170,10 @@ struct _GstGLWindowClass {
void (*show) (GstGLWindow *window);
gboolean (*set_render_rectangle)(GstGLWindow *window, gint x, gint y, gint width, gint height);
void (*queue_resize) (GstGLWindow *window);
gboolean (*controls_viewport) (GstGLWindow *window);
/*< private >*/
gpointer _reserved[GST_PADDING];
gpointer _reserved[GST_PADDING-1];
};
GST_GL_API
@ -250,6 +253,8 @@ gboolean gst_gl_window_set_render_rectangle (GstGLWindow * window,
gint y,
gint width,
gint height);
GST_GL_API
gboolean gst_gl_window_controls_viewport (GstGLWindow * window);
/* subclass usage only */
GST_GL_API

View file

@ -46,6 +46,8 @@ static void gst_gl_window_viv_fb_egl_draw (GstGLWindow * window);
static gboolean
gst_gl_window_viv_fb_egl_set_render_rectangle (GstGLWindow * window,
gint x, gint y, gint width, gint height);
static gboolean gst_gl_window_viv_fb_egl_controls_viewport (GstGLWindow *
window);
static void
gst_gl_window_viv_fb_egl_class_init (GstGLWindowVivFBEGLClass * klass)
@ -63,6 +65,8 @@ gst_gl_window_viv_fb_egl_class_init (GstGLWindowVivFBEGLClass * klass)
window_class->draw = GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_draw);
window_class->set_render_rectangle =
GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_set_render_rectangle);
window_class->controls_viewport =
GST_DEBUG_FUNCPTR (gst_gl_window_viv_fb_egl_controls_viewport);
}
static void
@ -179,12 +183,15 @@ draw_cb (gpointer data)
gst_gl_window_resize (window, width, height);
gl->GetIntegerv (GL_VIEWPORT, viewport_dim);
viewport_dim[0] += window_egl->render_rectangle.x;
viewport_dim[1] += window_egl->render_rectangle.y;
gl->Viewport (viewport_dim[0],
viewport_dim[1], viewport_dim[2], viewport_dim[3]);
window_egl->viewport.x = viewport_dim[0] + window_egl->render_rectangle.x;
window_egl->viewport.y = viewport_dim[1] + window_egl->render_rectangle.y;
window_egl->viewport.w = viewport_dim[2];
window_egl->viewport.h = viewport_dim[2];
}
gl->Viewport (window_egl->viewport.x, window_egl->viewport.y,
window_egl->viewport.w, window_egl->viewport.h);
if (window->draw)
window->draw (window->draw_data);
@ -263,3 +270,9 @@ gst_gl_window_viv_fb_egl_set_render_rectangle (GstGLWindow * window,
return TRUE;
}
static gboolean
gst_gl_window_viv_fb_egl_controls_viewport (GstGLWindow * window)
{
return TRUE;
}

View file

@ -47,6 +47,7 @@ struct _GstGLWindowVivFBEGL {
gint window_width, window_height;
GstVideoRectangle render_rectangle;
GstVideoRectangle viewport;
};
struct _GstGLWindowVivFBEGLClass {