From 488b5e3ac3986d20cd6184668252cce70bb23760 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 1 May 2015 18:25:29 +0200 Subject: cocoa: don't accidentally drop initial screen drawing With --idle --force-window, or when started from the bundle, the cocoa code dropped the first frame. This resulted in a black frame on start sometimes. The reason was that the live resizing/redrawing code was invoked, which simply set skip_swap_buffer to false, blocking redrawing whatever was going to be rendered next. Normally this is done so that the following works: 1. vo_opengl draw a frame, releases GL lock 2. live resizing kicks in, redraw the frame 3. vo_opengl wants to call SwapBuffers, drawing a stale buffer overwritten by the live resizing code This is solved by setting skip_swap_buffer in 2., and querying it in 3. Fix this by resetting the skip_swap_buffer at a known good point: when vo_opengl starts drawing a new frame. The start_frame function returns bool, so that it can be merged with is_active in a following commit. (cherry picked from commit e23e4c7c603fc1cd911621d0f833031be4a6f7c7) --- video/out/cocoa_common.h | 1 + video/out/cocoa_common.m | 10 +++++++++- video/out/gl_cocoa.c | 6 ++++++ video/out/gl_common.h | 5 +++++ video/out/vo_opengl.c | 6 ++++++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/video/out/cocoa_common.h b/video/out/cocoa_common.h index 30792a674e..e2bed88d08 100644 --- a/video/out/cocoa_common.h +++ b/video/out/cocoa_common.h @@ -30,6 +30,7 @@ void vo_cocoa_uninit(struct vo *vo); int vo_cocoa_config_window(struct vo *vo, uint32_t flags, void *gl_ctx); void vo_cocoa_set_current_context(struct vo *vo, bool current); +bool vo_cocoa_start_frame(struct vo *vo); void vo_cocoa_swap_buffers(struct vo *vo); int vo_cocoa_check_events(struct vo *vo); int vo_cocoa_control(struct vo *vo, int *events, int request, void *arg); diff --git a/video/out/cocoa_common.m b/video/out/cocoa_common.m index e768e06e7d..8a0473e729 100644 --- a/video/out/cocoa_common.m +++ b/video/out/cocoa_common.m @@ -632,13 +632,21 @@ static void draw_changes_after_next_frame(struct vo *vo) } } +bool vo_cocoa_start_frame(struct vo *vo) +{ + struct vo_cocoa_state *s = vo->cocoa; + + s->skip_swap_buffer = false; + return true; +} + void vo_cocoa_swap_buffers(struct vo *vo) { struct vo_cocoa_state *s = vo->cocoa; if (s->skip_swap_buffer && !s->waiting_frame) { s->skip_swap_buffer = false; - return; + s->pending_events |= VO_EVENT_EXPOSE; } else { [s->gl_ctx flushBuffer]; } diff --git a/video/out/gl_cocoa.c b/video/out/gl_cocoa.c index fd12ef4621..014bf38204 100644 --- a/video/out/gl_cocoa.c +++ b/video/out/gl_cocoa.c @@ -153,6 +153,11 @@ static void releaseGlContext_cocoa(MPGLContext *ctx) CGLReleaseContext(p->ctx); } +static bool start_frame_cocoa(MPGLContext *ctx) +{ + return vo_cocoa_start_frame(ctx->vo); +} + static void swapGlBuffers_cocoa(MPGLContext *ctx) { vo_cocoa_swap_buffers(ctx->vo); @@ -169,6 +174,7 @@ void mpgl_set_backend_cocoa(MPGLContext *ctx) ctx->config_window = config_window_cocoa; ctx->releaseGlContext = releaseGlContext_cocoa; ctx->swapGlBuffers = swapGlBuffers_cocoa; + ctx->start_frame = start_frame_cocoa; ctx->vo_init = vo_cocoa_init; ctx->register_resize_callback = vo_cocoa_register_resize_callback; ctx->vo_uninit = vo_cocoa_uninit; diff --git a/video/out/gl_common.h b/video/out/gl_common.h index 8a133784c7..1c908cfa2b 100644 --- a/video/out/gl_common.h +++ b/video/out/gl_common.h @@ -118,6 +118,11 @@ typedef struct MPGLContext { // If false, OpenGL renderers should not draw anything. bool (*is_active)(struct MPGLContext *); + // Optional callback on the beginning of a frame. The frame will be finished + // with swapGlBuffers(). Like is_active, this returns false if use of the + // OpenGL context should be avoided. + bool (*start_frame)(struct MPGLContext *); + // For free use by the backend. void *priv; } MPGLContext; diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index e409eaa18d..43b2b9e04b 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -184,6 +184,12 @@ static void draw_image_timed(struct vo *vo, mp_image_t *mpi, if (mpi) gl_video_upload_image(p->renderer, mpi); + + if (p->glctx->start_frame && !p->glctx->start_frame(p->glctx)) { + mpgl_unlock(p->glctx); + return; + } + gl_video_render_frame(p->renderer, 0, t); // The playloop calls this last before waiting some time until it decides -- cgit v1.2.3