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:
1 parent
afb97c517d
commit
488b5e3ac3
5 files changed
+27
-1
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user