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 e23e4c7c60)
This commit is contained in:
wm4 authored and Diogo Franco (Kovensky) committed 2015-05-07 10:41:57 +09:00
1 parent afb97c517d
commit 488b5e3ac3
5 files changed
+27 -1

No files matched your search

+1
View File
@@ -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);
+9 -1
View File
@@ -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];
}
+6
View File
@@ -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;
+5
View File
@@ -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;
+6
View File
@@ -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