eagl: fix handling of surface dimension changes
Detect when the eagl surface changed its dimension (when the user rotates the device for example) and adapt the egl internals to draw to that, preventing that ios resizes the image again when drawing. This is particularly harmful when eagl would scale down a image to draw and the ios screen would scale it back up because the surface is now bigger than when the element was configured.
This commit is contained in:
parent
27d726fbfa
commit
ef66e39d03
@ -56,11 +56,15 @@ struct _GstEaglContext
|
|||||||
EAGLContext *eagl_context;
|
EAGLContext *eagl_context;
|
||||||
GLuint framebuffer;
|
GLuint framebuffer;
|
||||||
GLuint color_renderbuffer;
|
GLuint color_renderbuffer;
|
||||||
|
GLuint depth_renderbuffer;
|
||||||
|
|
||||||
UIView *window;
|
UIView *window;
|
||||||
UIView *used_window;
|
UIView *used_window;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_egl_adaptation_update_surface (GstEglAdaptationContext * ctx);
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_egl_adaptation_init (GstEglAdaptationContext * ctx)
|
gst_egl_adaptation_init (GstEglAdaptationContext * ctx)
|
||||||
{
|
{
|
||||||
@ -179,8 +183,13 @@ gst_egl_adaptation_create_surface (GstEglAdaptationContext * ctx)
|
|||||||
__block CAEAGLLayer *eaglLayer = (CAEAGLLayer *)[ctx->eaglctx->window layer];
|
__block CAEAGLLayer *eaglLayer = (CAEAGLLayer *)[ctx->eaglctx->window layer];
|
||||||
|
|
||||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||||
|
|
||||||
|
if (ctx->eaglctx->framebuffer) {
|
||||||
|
framebuffer = ctx->eaglctx->framebuffer;
|
||||||
|
} else {
|
||||||
/* Allocate framebuffer */
|
/* Allocate framebuffer */
|
||||||
glGenFramebuffers(1, &framebuffer);
|
glGenFramebuffers(1, &framebuffer);
|
||||||
|
}
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
|
||||||
|
|
||||||
/* Allocate color render buffer */
|
/* Allocate color render buffer */
|
||||||
@ -212,6 +221,9 @@ gst_egl_adaptation_create_surface (GstEglAdaptationContext * ctx)
|
|||||||
|
|
||||||
ctx->eaglctx->framebuffer = framebuffer;
|
ctx->eaglctx->framebuffer = framebuffer;
|
||||||
ctx->eaglctx->color_renderbuffer = colorRenderbuffer;
|
ctx->eaglctx->color_renderbuffer = colorRenderbuffer;
|
||||||
|
ctx->eaglctx->depth_renderbuffer = colorRenderbuffer;
|
||||||
|
ctx->surface_width = width;
|
||||||
|
ctx->surface_height = height;
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, ctx->eaglctx->color_renderbuffer);
|
glBindRenderbuffer(GL_RENDERBUFFER, ctx->eaglctx->color_renderbuffer);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -260,18 +272,18 @@ gboolean
|
|||||||
gst_egl_adaptation_update_surface_dimensions (GstEglAdaptationContext *
|
gst_egl_adaptation_update_surface_dimensions (GstEglAdaptationContext *
|
||||||
ctx)
|
ctx)
|
||||||
{
|
{
|
||||||
GLint width;
|
CAEAGLLayer *layer = (CAEAGLLayer *)[ctx->eaglctx->window layer];
|
||||||
GLint height;
|
CGSize size = layer.frame.size;
|
||||||
|
|
||||||
/* Get renderbuffer width/height */
|
if (size.width != ctx->surface_width || size.height != ctx->surface_height) {
|
||||||
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);
|
ctx->surface_width = size.width;
|
||||||
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &height);
|
ctx->surface_height = size.height;
|
||||||
|
GST_INFO_OBJECT (ctx->element, "Got surface of %dx%d pixels",
|
||||||
if (width != ctx->surface_width || height != ctx->surface_height) {
|
(gint) size.width, (gint) size.height);
|
||||||
ctx->surface_width = width;
|
if (!gst_egl_adaptation_update_surface (ctx)) {
|
||||||
ctx->surface_height = height;
|
GST_WARNING_OBJECT (ctx->element, "Failed to update surface "
|
||||||
GST_INFO_OBJECT (ctx->element, "Got surface of %dx%d pixels", width,
|
"to new dimensions");
|
||||||
height);
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,6 +314,23 @@ gst_egl_adaptation_destroy_surface (GstEglAdaptationContext * ctx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_egl_adaptation_update_surface (GstEglAdaptationContext * ctx)
|
||||||
|
{
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, ctx->eaglctx->framebuffer);
|
||||||
|
|
||||||
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
|
||||||
|
GL_RENDERBUFFER, 0);
|
||||||
|
glDeleteRenderbuffers(1, &ctx->eaglctx->depth_renderbuffer);
|
||||||
|
|
||||||
|
glBindRenderbuffer (GL_RENDERBUFFER, 0);
|
||||||
|
glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||||
|
GL_RENDERBUFFER, 0);
|
||||||
|
glDeleteRenderbuffers(1, &ctx->eaglctx->color_renderbuffer);
|
||||||
|
|
||||||
|
return gst_egl_adaptation_create_surface (ctx);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
gst_egl_adaptation_destroy_context (GstEglAdaptationContext * ctx)
|
gst_egl_adaptation_destroy_context (GstEglAdaptationContext * ctx)
|
||||||
{
|
{
|
||||||
|
@ -204,8 +204,7 @@ static void gst_eglglessink_set_render_rectangle (GstVideoOverlay * overlay,
|
|||||||
/* Utility */
|
/* Utility */
|
||||||
static gboolean gst_eglglessink_create_window (GstEglGlesSink *
|
static gboolean gst_eglglessink_create_window (GstEglGlesSink *
|
||||||
eglglessink, gint width, gint height);
|
eglglessink, gint width, gint height);
|
||||||
static gboolean gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink,
|
static gboolean gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink);
|
||||||
gboolean reset);
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_eglglessink_configure_caps (GstEglGlesSink * eglglessink, GstCaps * caps);
|
gst_eglglessink_configure_caps (GstEglGlesSink * eglglessink, GstCaps * caps);
|
||||||
static GstFlowReturn gst_eglglessink_upload (GstEglGlesSink * sink,
|
static GstFlowReturn gst_eglglessink_upload (GstEglGlesSink * sink,
|
||||||
@ -740,17 +739,17 @@ gst_eglglessink_expose (GstVideoOverlay * overlay)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink, gboolean reset)
|
gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink)
|
||||||
{
|
{
|
||||||
gdouble render_width, render_height;
|
gdouble render_width, render_height;
|
||||||
gdouble texture_width, texture_height;
|
gdouble texture_width, texture_height;
|
||||||
gdouble x1, x2, y1, y2;
|
gdouble x1, x2, y1, y2;
|
||||||
gdouble tx1, tx2, ty1, ty2;
|
gdouble tx1, tx2, ty1, ty2;
|
||||||
|
|
||||||
GST_INFO_OBJECT (eglglessink, "VBO setup. have_vbo:%d, should reset %d",
|
GST_INFO_OBJECT (eglglessink, "VBO setup. have_vbo:%d",
|
||||||
eglglessink->egl_context->have_vbo, reset);
|
eglglessink->egl_context->have_vbo);
|
||||||
|
|
||||||
if (eglglessink->egl_context->have_vbo && reset) {
|
if (eglglessink->egl_context->have_vbo) {
|
||||||
glDeleteBuffers (1, &eglglessink->egl_context->position_buffer);
|
glDeleteBuffers (1, &eglglessink->egl_context->position_buffer);
|
||||||
glDeleteBuffers (1, &eglglessink->egl_context->index_buffer);
|
glDeleteBuffers (1, &eglglessink->egl_context->index_buffer);
|
||||||
eglglessink->egl_context->have_vbo = FALSE;
|
eglglessink->egl_context->have_vbo = FALSE;
|
||||||
@ -929,6 +928,7 @@ gst_eglglessink_setup_vbo (GstEglGlesSink * eglglessink, gboolean reset)
|
|||||||
goto HANDLE_ERROR_LOCKED;
|
goto HANDLE_ERROR_LOCKED;
|
||||||
|
|
||||||
eglglessink->egl_context->have_vbo = TRUE;
|
eglglessink->egl_context->have_vbo = TRUE;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (eglglessink, "VBO setup done");
|
GST_DEBUG_OBJECT (eglglessink, "VBO setup done");
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -1673,7 +1673,7 @@ gst_eglglessink_render (GstEglGlesSink * eglglessink)
|
|||||||
glClear (GL_COLOR_BUFFER_BIT);
|
glClear (GL_COLOR_BUFFER_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!gst_eglglessink_setup_vbo (eglglessink, FALSE)) {
|
if (!gst_eglglessink_setup_vbo (eglglessink)) {
|
||||||
GST_OBJECT_UNLOCK (eglglessink);
|
GST_OBJECT_UNLOCK (eglglessink);
|
||||||
GST_ERROR_OBJECT (eglglessink, "VBO setup failed");
|
GST_ERROR_OBJECT (eglglessink, "VBO setup failed");
|
||||||
goto HANDLE_ERROR;
|
goto HANDLE_ERROR;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user