Exemplo n.º 1
0
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);
}
Exemplo n.º 2
0
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();
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
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;
}
Exemplo n.º 6
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);
        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;
}
Exemplo n.º 7
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;
}