static void draw_image(struct vo *vo, mp_image_t *mpi) { struct gl_priv *p = vo->priv; if (p->vo_flipped) mp_image_vflip(mpi); mpgl_lock(p->glctx); gl_video_upload_image(p->renderer, mpi); gl_video_render_frame(p->renderer); mpgl_unlock(p->glctx); }
static void draw_frame(struct vo *vo, struct vo_frame *frame) { struct gl_priv *p = vo->priv; GL *gl = p->gl; if (gl->FenceSync && p->num_vsync_fences < p->opt_vsync_fences) { GLsync fence = gl->FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);; if (fence) p->vsync_fences[p->num_vsync_fences++] = fence; } gl_video_render_frame(p->renderer, frame, 0); if (p->use_glFinish) gl->Finish(); }
static int control(struct vo *vo, uint32_t request, void *data) { struct gl_priv *p = vo->priv; switch (request) { case VOCTRL_GET_PANSCAN: return VO_TRUE; case VOCTRL_SET_PANSCAN: mpgl_lock(p->glctx); resize(p); mpgl_unlock(p->glctx); return VO_TRUE; case VOCTRL_GET_EQUALIZER: { struct voctrl_get_equalizer_args *args = data; mpgl_lock(p->glctx); bool r = gl_video_get_equalizer(p->renderer, args->name, args->valueptr); mpgl_unlock(p->glctx); return r ? VO_TRUE : VO_NOTIMPL; } case VOCTRL_SET_EQUALIZER: { struct voctrl_set_equalizer_args *args = data; mpgl_lock(p->glctx); bool r = gl_video_set_equalizer(p->renderer, args->name, args->value); mpgl_unlock(p->glctx); if (r) vo->want_redraw = true; return r ? VO_TRUE : VO_NOTIMPL; } case VOCTRL_SET_YUV_COLORSPACE: { mpgl_lock(p->glctx); gl_video_set_csp_override(p->renderer, data); mpgl_unlock(p->glctx); vo->want_redraw = true; return VO_TRUE; } case VOCTRL_GET_YUV_COLORSPACE: mpgl_lock(p->glctx); gl_video_get_csp_override(p->renderer, data); mpgl_unlock(p->glctx); return VO_TRUE; case VOCTRL_SCREENSHOT: { struct voctrl_screenshot_args *args = data; mpgl_lock(p->glctx); if (args->full_window) args->out_image = glGetWindowScreenshot(p->gl); else args->out_image = gl_video_download_image(p->renderer); mpgl_unlock(p->glctx); return true; } case VOCTRL_REDRAW_FRAME: mpgl_lock(p->glctx); gl_video_render_frame(p->renderer); mpgl_unlock(p->glctx); return true; case VOCTRL_SET_COMMAND_LINE: { char *arg = data; return reparse_cmdline(p, arg); } } mpgl_lock(p->glctx); int events = 0; int r = p->glctx->vo_control(vo, &events, request, data); if (events & VO_EVENT_RESIZE) resize(p); if (events & VO_EVENT_EXPOSE) vo->want_redraw = true; mpgl_unlock(p->glctx); return r; }
int mpv_opengl_cb_render(struct mpv_opengl_cb_context *ctx, int fbo, int vp[4]) { assert(ctx->renderer); gl_video_set_gl_state(ctx->renderer); pthread_mutex_lock(&ctx->lock); struct vo *vo = ctx->active; ctx->force_update |= ctx->reconfigured; int h = vp[3]; bool flip = h < 0 && h > INT_MIN; if (flip) h = -h; struct mp_rect wnd = {vp[0], vp[1], vp[0] + vp[2], vp[1] + h}; if (wnd.x0 != ctx->wnd.x0 || wnd.y0 != ctx->wnd.y0 || wnd.x1 != ctx->wnd.x1 || wnd.y1 != ctx->wnd.y1 || ctx->flip != flip) ctx->force_update = true; if (ctx->force_update && vo) { ctx->force_update = false; ctx->wnd = wnd; struct mp_rect src, dst; struct mp_osd_res osd; mp_get_src_dst_rects(ctx->log, &ctx->vo_opts, vo->driver->caps, &ctx->img_params, wnd.x1 - wnd.x0, wnd.y1 - wnd.y0, 1.0, &src, &dst, &osd); gl_video_resize(ctx->renderer, &wnd, &src, &dst, &osd, !ctx->flip); } if (vo) { struct vo_priv *p = vo->priv; if (ctx->reconfigured) gl_video_config(ctx->renderer, &ctx->img_params); if (ctx->reconfigured || ctx->update_new_opts) { struct vo_priv *opts = p->ctx->new_opts ? p->ctx->new_opts : p; gl_video_set_options(ctx->renderer, opts->renderer_opts); ctx->gl->debug_context = opts->use_gl_debug; gl_video_set_debug(ctx->renderer, opts->use_gl_debug); } ctx->reconfigured = false; ctx->update_new_opts = false; } struct mp_image *mpi = ctx->next_frame; ctx->next_frame = NULL; pthread_mutex_unlock(&ctx->lock); if (mpi) gl_video_upload_image(ctx->renderer, mpi); gl_video_render_frame(ctx->renderer, fbo); gl_video_unset_gl_state(ctx->renderer); return 0; }
int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h) { assert(ctx->renderer); gl_video_set_gl_state(ctx->renderer); pthread_mutex_lock(&ctx->lock); struct vo *vo = ctx->active; ctx->force_update |= ctx->reconfigured; if (ctx->vp_w != vp_w || ctx->vp_h != vp_h) ctx->force_update = true; if (ctx->force_update && vo) { ctx->force_update = false; ctx->vp_w = vp_w; ctx->vp_h = vp_h; struct mp_rect src, dst; struct mp_osd_res osd; mp_get_src_dst_rects(ctx->log, &ctx->vo_opts, vo->driver->caps, &ctx->img_params, vp_w, abs(vp_h), 1.0, &src, &dst, &osd); gl_video_resize(ctx->renderer, vp_w, vp_h, &src, &dst, &osd); } if (ctx->reconfigured) { gl_video_set_osd_source(ctx->renderer, vo ? vo->osd : NULL); gl_video_config(ctx->renderer, &ctx->img_params); } if (ctx->update_new_opts) { struct vo_priv *p = vo ? vo->priv : NULL; struct vo_priv *opts = ctx->new_opts ? ctx->new_opts : p; if (opts) { gl_video_set_options(ctx->renderer, opts->renderer_opts, NULL); ctx->gl->debug_context = opts->use_gl_debug; gl_video_set_debug(ctx->renderer, opts->use_gl_debug); frame_queue_shrink(ctx, opts->frame_queue_size); } } ctx->reconfigured = false; ctx->update_new_opts = false; struct mp_csp_equalizer *eq = gl_video_eq_ptr(ctx->renderer); if (ctx->eq_changed) { memcpy(eq->values, ctx->eq.values, sizeof(eq->values)); gl_video_eq_update(ctx->renderer); } ctx->eq_changed = false; ctx->eq = *eq; struct mp_image *mpi = frame_queue_pop(ctx); pthread_mutex_unlock(&ctx->lock); if (mpi) gl_video_set_image(ctx->renderer, mpi); gl_video_render_frame(ctx->renderer, fbo, NULL); gl_video_unset_gl_state(ctx->renderer); pthread_mutex_lock(&ctx->lock); const int left = ctx->queued_frames; if (vo && left > 0) update(vo->priv); pthread_mutex_unlock(&ctx->lock); return left; }
int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h) { assert(ctx->renderer); gl_video_set_gl_state(ctx->renderer); pthread_mutex_lock(&ctx->lock); struct vo *vo = ctx->active; ctx->force_update |= ctx->reconfigured; if (ctx->vp_w != vp_w || ctx->vp_h != vp_h) ctx->force_update = true; if (ctx->force_update && vo) { ctx->force_update = false; ctx->vp_w = vp_w; ctx->vp_h = vp_h; struct mp_rect src, dst; struct mp_osd_res osd; mp_get_src_dst_rects(ctx->log, &ctx->vo_opts, vo->driver->caps, &ctx->img_params, vp_w, abs(vp_h), 1.0, &src, &dst, &osd); gl_video_resize(ctx->renderer, vp_w, vp_h, &src, &dst, &osd); } if (ctx->reconfigured) { gl_video_set_osd_source(ctx->renderer, vo ? vo->osd : NULL); gl_video_config(ctx->renderer, &ctx->img_params); ctx->eq_changed = true; } if (ctx->update_new_opts) { struct vo_priv *p = vo ? vo->priv : NULL; struct vo_priv *opts = ctx->new_opts ? ctx->new_opts : p; if (opts) { gl_video_set_options(ctx->renderer, opts->renderer_opts); if (vo) gl_video_configure_queue(ctx->renderer, vo); ctx->gl->debug_context = opts->use_gl_debug; gl_video_set_debug(ctx->renderer, opts->use_gl_debug); } } ctx->reconfigured = false; ctx->update_new_opts = false; if (ctx->reset) { gl_video_reset(ctx->renderer); ctx->reset = false; if (ctx->cur_frame) ctx->cur_frame->still = true; } struct mp_csp_equalizer *eq = gl_video_eq_ptr(ctx->renderer); if (ctx->eq_changed) { memcpy(eq->values, ctx->eq.values, sizeof(eq->values)); gl_video_eq_update(ctx->renderer); } ctx->eq_changed = false; struct vo_frame *frame = ctx->next_frame; int64_t wait_present_count = ctx->present_count; if (frame) { ctx->next_frame = NULL; wait_present_count += 1; pthread_cond_signal(&ctx->wakeup); talloc_free(ctx->cur_frame); ctx->cur_frame = vo_frame_ref(frame); } else { frame = vo_frame_ref(ctx->cur_frame); if (frame) frame->redraw = true; MP_STATS(ctx, "glcb-noframe"); } struct vo_frame dummy = {0}; if (!frame) frame = &dummy; pthread_mutex_unlock(&ctx->lock); MP_STATS(ctx, "glcb-render"); gl_video_render_frame(ctx->renderer, frame, fbo); gl_video_unset_gl_state(ctx->renderer); if (frame != &dummy) talloc_free(frame); pthread_mutex_lock(&ctx->lock); while (wait_present_count > ctx->present_count) pthread_cond_wait(&ctx->wakeup, &ctx->lock); pthread_mutex_unlock(&ctx->lock); return 0; }
int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h) { assert(ctx->renderer); gl_video_set_gl_state(ctx->renderer); pthread_mutex_lock(&ctx->lock); struct vo *vo = ctx->active; ctx->force_update |= ctx->reconfigured; if (ctx->vp_w != vp_w || ctx->vp_h != vp_h) ctx->force_update = true; if (ctx->force_update && vo) { ctx->force_update = false; ctx->vp_w = vp_w; ctx->vp_h = vp_h; struct mp_rect src, dst; struct mp_osd_res osd; mp_get_src_dst_rects(ctx->log, &ctx->vo_opts, vo->driver->caps, &ctx->img_params, vp_w, abs(vp_h), 1.0, &src, &dst, &osd); gl_video_resize(ctx->renderer, vp_w, vp_h, &src, &dst, &osd); } if (ctx->reconfigured) { gl_video_set_osd_source(ctx->renderer, vo ? vo->osd : NULL); gl_video_config(ctx->renderer, &ctx->img_params); } if (ctx->update_new_opts) { struct vo_priv *p = vo ? vo->priv : NULL; struct vo_priv *opts = ctx->new_opts ? ctx->new_opts : p; if (opts) { int queue = 0; gl_video_set_options(ctx->renderer, opts->renderer_opts, &queue); ctx->vsync_timed = opts->renderer_opts->interpolation; if (ctx->vsync_timed) queue += 0.050 * 1e6; // disable video timing vo_set_flip_queue_params(vo, queue, false); ctx->gl->debug_context = opts->use_gl_debug; gl_video_set_debug(ctx->renderer, opts->use_gl_debug); frame_queue_shrink(ctx, opts->frame_queue_size); } } ctx->reconfigured = false; ctx->update_new_opts = false; struct mp_csp_equalizer *eq = gl_video_eq_ptr(ctx->renderer); if (ctx->eq_changed) { memcpy(eq->values, ctx->eq.values, sizeof(eq->values)); gl_video_eq_update(ctx->renderer); } ctx->eq_changed = false; ctx->eq = *eq; struct mp_image *mpi = frame_queue_pop(ctx); if (mpi) { struct frame_timing *t = mpi->priv; // set by draw_image_timed if (t) ctx->cur_pts = t->pts; } struct frame_timing timing = { .pts = ctx->cur_pts, }; if (ctx->approx_vsync > 0) { timing.prev_vsync = prev_sync(ctx, mp_time_us()); timing.next_vsync = timing.prev_vsync + ctx->approx_vsync; } pthread_mutex_unlock(&ctx->lock); if (mpi) gl_video_set_image(ctx->renderer, mpi); gl_video_render_frame(ctx->renderer, fbo, timing.pts ? &timing : NULL); gl_video_unset_gl_state(ctx->renderer); pthread_mutex_lock(&ctx->lock); const int left = ctx->queued_frames; if (vo && (left > 0 || ctx->vsync_timed)) update(vo->priv); pthread_mutex_unlock(&ctx->lock); return left; } int mpv_opengl_cb_report_flip(mpv_opengl_cb_context *ctx, int64_t time) { pthread_mutex_lock(&ctx->lock); int64_t next = time > 0 ? time : mp_time_us(); if (ctx->recent_flip) ctx->approx_vsync = next - ctx->recent_flip; ctx->recent_flip = next; pthread_mutex_unlock(&ctx->lock); return 0; }