diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index 452e30ed73..1927c8b7b1 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -30,6 +30,11 @@ Interface changes - --opengl-fbo-format changes from a choice to a string. Also, its value will be checked only on renderer initialization, rather than when the option is set. + - Using opengl-cb now always assumes 8 bit per component depth, and dithers + to this size. Before, it tried to figure out the depth of the first + framebuffer that was ever passed to the renderer. Having GL framebuffers + with a size larger than 8 bit per component is quite rare. If you need + it, set the --dither-depth option instead. --- mpv 0.26.0 --- - remove remaining deprecated audio device options, like --alsa-device Some of them were removed in earlier releases. diff --git a/common/common.c b/common/common.c index a07af8c461..9ed63e1783 100644 --- a/common/common.c +++ b/common/common.c @@ -115,6 +115,12 @@ bool mp_rect_intersection(struct mp_rect *rc, const struct mp_rect *rc2) return rc->x1 > rc->x0 && rc->y1 > rc->y0; } +bool mp_rect_equals(struct mp_rect *rc1, struct mp_rect *rc2) +{ + return rc1->x0 == rc2->x0 && rc1->y0 == rc2->y0 && + rc1->x1 == rc2->x1 && rc1->y1 == rc2->y1; +} + // This works like snprintf(), except that it starts writing the first output // character to str[strlen(str)]. This returns the number of characters the // string would have *appended* assuming a large enough buffer, will make sure diff --git a/common/common.h b/common/common.h index fb40d251f1..cdd1d56ed5 100644 --- a/common/common.h +++ b/common/common.h @@ -82,6 +82,7 @@ struct mp_rect { void mp_rect_union(struct mp_rect *rc, const struct mp_rect *src); bool mp_rect_intersection(struct mp_rect *rc, const struct mp_rect *rc2); bool mp_rect_contains(struct mp_rect *rc, int x, int y); +bool mp_rect_equals(struct mp_rect *rc1, struct mp_rect *rc2); int mp_snprintf_cat(char *str, size_t size, const char *format, ...) PRINTF_ATTRIBUTE(3, 4); diff --git a/video/out/opengl/common.c b/video/out/opengl/common.c index f6202e2c8c..c7a714817a 100644 --- a/video/out/opengl/common.c +++ b/video/out/opengl/common.c @@ -625,10 +625,8 @@ void mpgl_load_functions2(GL *gl, void *(*get_fn)(void *ctx, const char *n), } // GL_ARB_compute_shader & GL_ARB_shader_image_load_store - if (gl->DispatchCompute && gl->BindImageTexture) { + if (gl->DispatchCompute && gl->BindImageTexture) gl->mpgl_caps |= MPGL_CAP_COMPUTE_SHADER; - gl->GetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &gl->max_shmem); - } // Provided for simpler handling if no framebuffer support is available. if (!gl->BindFramebuffer) diff --git a/video/out/opengl/common.h b/video/out/opengl/common.h index abc8f30192..6d8015c8b3 100644 --- a/video/out/opengl/common.h +++ b/video/out/opengl/common.h @@ -87,7 +87,6 @@ struct GL { int glsl_version; // e.g. 130 for GLSL 1.30 char *extensions; // Equivalent to GL_EXTENSIONS int mpgl_caps; // Bitfield of MPGL_CAP_* constants - int max_shmem; // Maximum shared memory for compute shaders bool debug_context; // use of e.g. GLX_CONTEXT_DEBUG_BIT_ARB // Use mpgl_get_native_display() instead. Also, this is set to use the diff --git a/video/out/opengl/hwdec.h b/video/out/opengl/hwdec.h index c97219d15b..95cbdadcf1 100644 --- a/video/out/opengl/hwdec.h +++ b/video/out/opengl/hwdec.h @@ -76,7 +76,7 @@ struct gl_hwdec_driver { int (*overlay_frame)(struct gl_hwdec *hw, struct mp_image *hw_image); // Move overlay position within the "window". - void (*overlay_adjust)(struct gl_hwdec *hw, int w, int h, + void (*overlay_adjust)(struct gl_hwdec *hw, struct mp_rect *src, struct mp_rect *dst); }; diff --git a/video/out/opengl/hwdec_rpi.c b/video/out/opengl/hwdec_rpi.c index 8611217c79..e8feb714fa 100644 --- a/video/out/opengl/hwdec_rpi.c +++ b/video/out/opengl/hwdec_rpi.c @@ -50,7 +50,6 @@ struct priv { struct mp_image *current_frame; - int w, h; struct mp_rect src, dst; int cur_window[4]; // raw user params }; @@ -131,9 +130,6 @@ static void update_overlay(struct gl_hwdec *hw, bool check_window_only) struct mp_rect src = p->src; struct mp_rect dst = p->dst; - if (!p->w || !p->h) - return; - int defs[4] = {0, 0, 0, 0}; int *z = mpgl_get_native_display(gl, "MPV_RPI_WINDOW"); if (!z) @@ -248,13 +244,11 @@ static int enable_renderer(struct gl_hwdec *hw) return 0; } -static void overlay_adjust(struct gl_hwdec *hw, int w, int h, +static void overlay_adjust(struct gl_hwdec *hw, struct mp_rect *src, struct mp_rect *dst) { struct priv *p = hw->priv; - p->w = w; - p->h = h; p->src = *src; p->dst = *dst; diff --git a/video/out/opengl/ra.c b/video/out/opengl/ra.c index 31f585fdf9..0ad70eeb47 100644 --- a/video/out/opengl/ra.c +++ b/video/out/opengl/ra.c @@ -28,6 +28,14 @@ void ra_buf_free(struct ra *ra, struct ra_buf **buf) *buf = NULL; } +void ra_free(struct ra **ra) +{ + if (*ra) + (*ra)->fns->destroy(*ra); + talloc_free(*ra); + *ra = NULL; +} + static size_t vartype_size(enum ra_vartype type) { switch (type) { diff --git a/video/out/opengl/ra.h b/video/out/opengl/ra.h index 785baf3f1d..a6c2461d89 100644 --- a/video/out/opengl/ra.h +++ b/video/out/opengl/ra.h @@ -21,6 +21,10 @@ struct ra { // at init time. int max_texture_wh; + // Maximum shared memory for compute shaders. Set by the RA backend at init + // time. + size_t max_shmem; + // Set of supported texture formats. Must be added by RA backend at init time. struct ra_format **formats; int num_formats; @@ -391,6 +395,12 @@ struct ra_fns { // always produce a value - and the values it does produce are typically // delayed by a few frames. When no value is available, this returns 0. uint64_t (*timer_stop)(struct ra *ra, ra_timer *timer); + + // Hint that possibly queued up commands should be sent to the GPU. Optional. + void (*flush)(struct ra *ra); + + // Optional. + void (*debug_marker)(struct ra *ra, const char *msg); }; struct ra_tex *ra_tex_create(struct ra *ra, const struct ra_tex_params *params); @@ -399,6 +409,8 @@ void ra_tex_free(struct ra *ra, struct ra_tex **tex); struct ra_buf *ra_buf_create(struct ra *ra, const struct ra_buf_params *params); void ra_buf_free(struct ra *ra, struct ra_buf **buf); +void ra_free(struct ra **ra); + const struct ra_format *ra_find_unorm_format(struct ra *ra, int bytes_per_component, int n_components); diff --git a/video/out/opengl/ra_gl.c b/video/out/opengl/ra_gl.c index a1373588fc..da6f5e92d1 100644 --- a/video/out/opengl/ra_gl.c +++ b/video/out/opengl/ra_gl.c @@ -6,7 +6,7 @@ static struct ra_fns ra_fns_gl; -int ra_init_gl(struct ra *ra, GL *gl) +static int ra_init_gl(struct ra *ra, GL *gl) { if (gl->version < 210 && gl->es < 200) { MP_ERR(ra, "At least OpenGL 2.1 or OpenGL ES 2.0 required.\n"); @@ -16,6 +16,8 @@ int ra_init_gl(struct ra *ra, GL *gl) struct ra_gl *p = ra->priv = talloc_zero(NULL, struct ra_gl); p->gl = gl; + ra_gl_set_debug(ra, true); + ra->fns = &ra_fns_gl; ra->caps = 0; if (gl->mpgl_caps & MPGL_CAP_1D_TEX) @@ -100,20 +102,46 @@ int ra_init_gl(struct ra *ra, GL *gl) MP_TARRAY_APPEND(ra, ra->formats, ra->num_formats, fmt); } - GLint max_wh; - gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &max_wh); - ra->max_texture_wh = max_wh; + GLint ival; + gl->GetIntegerv(GL_MAX_TEXTURE_SIZE, &ival); + ra->max_texture_wh = ival; + + if (ra->caps & RA_CAP_COMPUTE) { + gl->GetIntegerv(GL_MAX_COMPUTE_SHARED_MEMORY_SIZE, &ival); + ra->max_shmem = ival; + } gl->Disable(GL_DITHER); return 0; } +struct ra *ra_create_gl(GL *gl, struct mp_log *log) +{ + struct ra *ra = talloc_zero(NULL, struct ra); + ra->log = log; + if (ra_init_gl(ra, gl) < 0) { + talloc_free(ra); + return NULL; + } + return ra; +} + static void gl_destroy(struct ra *ra) { talloc_free(ra->priv); } +void ra_gl_set_debug(struct ra *ra, bool enable) +{ + struct ra_gl *p = ra->priv; + GL *gl = ra_gl_get(ra); + + p->debug_enable = enable; + if (gl->debug_context) + gl_set_debug_logger(gl, enable ? ra->log : NULL); +} + static void gl_tex_destroy(struct ra *ra, struct ra_tex *tex) { GL *gl = ra_gl_get(ra); @@ -949,6 +977,20 @@ static uint64_t gl_timer_stop(struct ra *ra, ra_timer *ratimer) return timer->result; } +static void gl_flush(struct ra *ra) +{ + GL *gl = ra_gl_get(ra); + gl->Flush(); +} + +static void gl_debug_marker(struct ra *ra, const char *msg) +{ + struct ra_gl *p = ra->priv; + + if (p->debug_enable) + gl_check_error(p->gl, ra->log, msg); +} + static struct ra_fns ra_fns_gl = { .destroy = gl_destroy, .tex_create = gl_tex_create, @@ -966,4 +1008,6 @@ static struct ra_fns ra_fns_gl = { .timer_destroy = gl_timer_destroy, .timer_start = gl_timer_start, .timer_stop = gl_timer_stop, + .flush = gl_flush, + .debug_marker = gl_debug_marker, }; diff --git a/video/out/opengl/ra_gl.h b/video/out/opengl/ra_gl.h index 3a48ca4556..08f0197433 100644 --- a/video/out/opengl/ra_gl.h +++ b/video/out/opengl/ra_gl.h @@ -7,6 +7,7 @@ // For ra.priv struct ra_gl { GL *gl; + bool debug_enable; }; // For ra_tex.priv @@ -37,11 +38,11 @@ struct ra_renderpass_gl { struct gl_vao vao; }; -int ra_init_gl(struct ra *ra, GL *gl); +struct ra *ra_create_gl(GL *gl, struct mp_log *log); struct ra_tex *ra_create_wrapped_texture(struct ra *ra, GLuint gl_texture, GLenum gl_target, GLint gl_iformat, GLenum gl_format, GLenum gl_type, int w, int h); struct ra_tex *ra_create_wrapped_fb(struct ra *ra, GLuint gl_fbo, int w, int h); - GL *ra_gl_get(struct ra *ra); +void ra_gl_set_debug(struct ra *ra, bool enable); diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c index 57c1c5b18f..408013fe22 100644 --- a/video/out/opengl/video.c +++ b/video/out/opengl/video.c @@ -176,7 +176,6 @@ struct dr_buffer { }; struct gl_video { - GL *gl; struct ra *ra; struct mpv_global *global; @@ -184,7 +183,6 @@ struct gl_video { struct gl_video_opts opts; struct m_config_cache *opts_cache; struct gl_lcms *cms; - bool gl_debug; int fb_depth; // actual bits available in GL main framebuffer @@ -252,7 +250,6 @@ struct gl_video { struct mp_rect src_rect; // displayed part of the source video struct mp_rect dst_rect; // video rectangle on output window struct mp_osd_res osd_rect; // OSD size/margins - int vp_w, vp_h; // temporary during rendering struct img_tex pass_tex[TEXUNIT_VIDEO_NUM]; @@ -459,17 +456,8 @@ static struct bstr load_cached_file(struct gl_video *p, const char *path) static void debug_check_gl(struct gl_video *p, const char *msg) { - if (p->gl_debug) - gl_check_error(p->gl, p->log, msg); -} - -void gl_video_set_debug(struct gl_video *p, bool enable) -{ - GL *gl = p->gl; - - p->gl_debug = enable; - if (p->gl->debug_context) - gl_set_debug_logger(gl, enable ? p->log : NULL); + if (p->ra->fns->debug_marker) + p->ra->fns->debug_marker(p->ra, msg); } static void gl_video_reset_surfaces(struct gl_video *p) @@ -1094,8 +1082,8 @@ static void pass_prepare_src_tex(struct gl_video *p) gl_sc_uniform_vec2(sc, texture_size, f); gl_sc_uniform_mat2(sc, texture_rot, true, (float *)s->transform.m); gl_sc_uniform_vec2(sc, texture_off, (float *)s->transform.t); - gl_sc_uniform_vec2(sc, pixel_size, (GLfloat[]){1.0f / f[0], - 1.0f / f[1]}); + gl_sc_uniform_vec2(sc, pixel_size, (float[]){1.0f / f[0], + 1.0f / f[1]}); } } @@ -1137,7 +1125,7 @@ static void dispatch_compute(struct gl_video *p, int w, int h, // We need to rescale the coordinates to the true texture size char tex_scale[32]; snprintf(tex_scale, sizeof(tex_scale), "tex_scale%d", n); - gl_sc_uniform_vec2(p->sc, tex_scale, (GLfloat[2]){ + gl_sc_uniform_vec2(p->sc, tex_scale, (float[2]){ (float)s->w / s->tex->params.w, (float)s->h / s->tex->params.h, }); @@ -1514,18 +1502,18 @@ static void load_shader(struct gl_video *p, struct bstr body) gl_sc_uniform_f(p->sc, "random", (double)av_lfg_get(&p->lfg) / UINT32_MAX); gl_sc_uniform_i(p->sc, "frame", p->frames_uploaded); gl_sc_uniform_vec2(p->sc, "input_size", - (GLfloat[]){(p->src_rect.x1 - p->src_rect.x0) * - p->texture_offset.m[0][0], - (p->src_rect.y1 - p->src_rect.y0) * - p->texture_offset.m[1][1]}); + (float[]){(p->src_rect.x1 - p->src_rect.x0) * + p->texture_offset.m[0][0], + (p->src_rect.y1 - p->src_rect.y0) * + p->texture_offset.m[1][1]}); gl_sc_uniform_vec2(p->sc, "target_size", - (GLfloat[]){p->dst_rect.x1 - p->dst_rect.x0, - p->dst_rect.y1 - p->dst_rect.y0}); + (float[]){p->dst_rect.x1 - p->dst_rect.x0, + p->dst_rect.y1 - p->dst_rect.y0}); gl_sc_uniform_vec2(p->sc, "tex_offset", - (GLfloat[]){p->src_rect.x0 * p->texture_offset.m[0][0] + - p->texture_offset.t[0], - p->src_rect.y0 * p->texture_offset.m[1][1] + - p->texture_offset.t[1]}); + (float[]){p->src_rect.x0 * p->texture_offset.m[0][0] + + p->texture_offset.t[0], + p->src_rect.y0 * p->texture_offset.m[1][1] + + p->texture_offset.t[1]}); } // Semantic equality @@ -1688,8 +1676,6 @@ static void pass_sample_separated(struct gl_video *p, struct img_tex src, static void pass_dispatch_sample_polar(struct gl_video *p, struct scaler *scaler, struct img_tex tex, int w, int h) { - GL *gl = p->gl; - uint64_t reqs = RA_CAP_COMPUTE | RA_CAP_NESTED_ARRAY; if ((p->ra->caps & reqs) != reqs) goto fallback; @@ -1713,8 +1699,8 @@ static void pass_dispatch_sample_polar(struct gl_video *p, struct scaler *scaler int iw = (int)ceil(bw / ratiox) + padding + 1, ih = (int)ceil(bh / ratioy) + padding + 1; - int shmem_req = iw * ih * tex.components * sizeof(GLfloat); - if (shmem_req > gl->max_shmem) + int shmem_req = iw * ih * tex.components * sizeof(float); + if (shmem_req > p->ra->max_shmem) goto fallback; pass_is_compute(p, bw, bh); @@ -2499,10 +2485,15 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, bool } } +void gl_video_set_fb_depth(struct gl_video *p, int fb_depth) +{ + p->fb_depth = fb_depth; +} + static void pass_dither(struct gl_video *p) { // Assume 8 bits per component if unknown. - int dst_depth = p->fb_depth; + int dst_depth = p->fb_depth > 0 ? p->fb_depth : 8; if (p->opts.dither_depth > 0) dst_depth = p->opts.dither_depth; @@ -3001,40 +2992,16 @@ static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t, p->frames_drawn += 1; } -// (fbo==0 makes BindFramebuffer select the screen backbuffer) -void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo) +void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, + struct fbodst target) { - GL *gl = p->gl; - - if (fbo && !(gl->mpgl_caps & MPGL_CAP_FB)) { - MP_FATAL(p, "Rendering to FBO requested, but no FBO extension found!\n"); - return; - } - - if (p->fb_depth == 0) { - debug_check_gl(p, "before retrieving framebuffer depth"); - p->fb_depth = gl_get_fb_depth(gl, fbo); - debug_check_gl(p, "retrieving framebuffer depth"); - if (p->fb_depth > 0) { - MP_VERBOSE(p, "Reported display depth: %d\n", p->fb_depth); - } else { - p->fb_depth = 8; - } - } - - struct fbodst target = { - .tex = ra_create_wrapped_fb(p->ra, fbo, p->vp_w, abs(p->vp_h)), - .flip = p->vp_h < 0, - }; - struct mp_rect target_rc = {0, 0, p->vp_w, abs(p->vp_h)}; + struct mp_rect target_rc = {0, 0, target.tex->params.w, target.tex->params.h}; p->broken_frame = false; bool has_frame = !!frame->current; - if (!has_frame || p->dst_rect.x0 > 0 || p->dst_rect.y0 > 0 || - p->dst_rect.x1 < p->vp_w || p->dst_rect.y1 < abs(p->vp_h)) - { + if (!has_frame || !mp_rect_equals(&p->dst_rect, &target_rc)) { struct m_color c = p->opts.background; float color[4] = {c.r / 255.0, c.g / 255.0, c.b / 255.0, c.a / 255.0}; p->ra->fns->clear(p->ra, target.tex, color, &target_rc); @@ -3140,32 +3107,27 @@ done: p->ra->fns->clear(p->ra, target.tex, color, &target_rc); } - ra_tex_free(p->ra, &target.tex); - // The playloop calls this last before waiting some time until it decides // to call flip_page(). Tell OpenGL to start execution of the GPU commands // while we sleep (this happens asynchronously). if ((p->opts.early_flush == -1 && !frame->display_synced) || p->opts.early_flush == 1) { - gl->Flush(); + if (p->ra->fns->flush) + p->ra->fns->flush(p->ra); } p->frames_rendered++; pass_report_performance(p); } -// vp_w/vp_h is the implicit size of the target framebuffer. -// vp_h can be negative to flip the screen. -void gl_video_resize(struct gl_video *p, int vp_w, int vp_h, +void gl_video_resize(struct gl_video *p, struct mp_rect *src, struct mp_rect *dst, struct mp_osd_res *osd) { p->src_rect = *src; p->dst_rect = *dst; p->osd_rect = *osd; - p->vp_w = vp_w; - p->vp_h = vp_h; gl_video_reset_surfaces(p); @@ -3173,7 +3135,7 @@ void gl_video_resize(struct gl_video *p, int vp_w, int vp_h, mpgl_osd_resize(p->osd, p->osd_rect, p->image_params.stereo_out); if (p->hwdec && p->hwdec->driver->overlay_adjust) - p->hwdec->driver->overlay_adjust(p->hwdec, vp_w, abs(vp_h), src, dst); + p->hwdec->driver->overlay_adjust(p->hwdec, src, dst); } static void frame_perf_data(struct pass_info pass[], struct mp_frame_perf *out) @@ -3375,10 +3337,10 @@ static bool check_dumb_mode(struct gl_video *p) static void check_gl_features(struct gl_video *p) { struct ra *ra = p->ra; - GL *gl = p->gl; bool have_float_tex = !!ra_find_float16_format(ra, 1); bool have_mglsl = ra->glsl_version >= 130; // modern GLSL - bool have_texrg = gl->mpgl_caps & MPGL_CAP_TEX_RG; + const struct ra_format *rg_tex = ra_find_unorm_format(p->ra, 1, 2); + bool have_texrg = rg_tex && !rg_tex->luminance_alpha; bool have_compute = ra->caps & RA_CAP_COMPUTE; bool have_ssbo = ra->caps & RA_CAP_BUF_RW; @@ -3512,8 +3474,6 @@ void gl_video_uninit(struct gl_video *p) if (!p) return; - GL *gl = p->gl; - uninit_video(p); gl_sc_destroy(p->sc); @@ -3532,8 +3492,6 @@ void gl_video_uninit(struct gl_video *p) mpgl_osd_destroy(p->osd); - gl_set_debug_logger(gl, NULL); - // Forcibly destroy possibly remaining image references. This should also // cause gl_video_dr_free_buffer() to be called for the remaining buffers. gc_pending_dr_fences(p, true); @@ -3541,8 +3499,7 @@ void gl_video_uninit(struct gl_video *p) // Should all have been unreffed already. assert(!p->num_dr_buffers); - p->ra->fns->destroy(p->ra); - talloc_free(p->ra); + ra_free(&p->ra); talloc_free(p); } @@ -3603,18 +3560,11 @@ void gl_video_set_osd_source(struct gl_video *p, struct osd_state *osd) reinit_osd(p); } -struct gl_video *gl_video_init(GL *gl, struct mp_log *log, struct mpv_global *g) +struct gl_video *gl_video_init(struct ra *ra, struct mp_log *log, + struct mpv_global *g) { - struct ra *ra = talloc_zero(NULL, struct ra); - ra->log = log; - if (ra_init_gl(ra, gl) < 0) { - talloc_free(ra); - return NULL; - } - struct gl_video *p = talloc_ptrtype(NULL, p); *p = (struct gl_video) { - .gl = gl, .ra = ra, .global = g, .log = log, @@ -3628,7 +3578,6 @@ struct gl_video *gl_video_init(GL *gl, struct mp_log *log, struct mpv_global *g) p->opts = *opts; for (int n = 0; n < SCALER_COUNT; n++) p->scaler[n] = (struct scaler){.index = n}; - gl_video_set_debug(p, true); init_gl(p); reinit_from_options(p); return p; diff --git a/video/out/opengl/video.h b/video/out/opengl/video.h index 8b6ca6e98f..db5837b12b 100644 --- a/video/out/opengl/video.h +++ b/video/out/opengl/video.h @@ -24,7 +24,6 @@ #include "sub/osd.h" #include "common.h" #include "utils.h" -#include "gl_utils.h" #include "lcms.h" #include "shader_cache.h" #include "video/out/filter_kernels.h" @@ -150,24 +149,25 @@ extern const struct m_sub_options gl_video_conf; struct gl_video; struct vo_frame; -struct gl_video *gl_video_init(GL *gl, struct mp_log *log, struct mpv_global *g); +struct gl_video *gl_video_init(struct ra *ra, struct mp_log *log, + struct mpv_global *g); void gl_video_uninit(struct gl_video *p); void gl_video_set_osd_source(struct gl_video *p, struct osd_state *osd); void gl_video_update_options(struct gl_video *p); bool gl_video_check_format(struct gl_video *p, int mp_format); void gl_video_config(struct gl_video *p, struct mp_image_params *params); void gl_video_set_output_depth(struct gl_video *p, int r, int g, int b); -void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo); -void gl_video_resize(struct gl_video *p, int vp_w, int vp_h, +void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, + struct fbodst target); +void gl_video_resize(struct gl_video *p, struct mp_rect *src, struct mp_rect *dst, struct mp_osd_res *osd); +void gl_video_set_fb_depth(struct gl_video *p, int fb_depth); void gl_video_perfdata(struct gl_video *p, struct voctrl_performance_data *out); struct mp_csp_equalizer; struct mp_csp_equalizer *gl_video_eq_ptr(struct gl_video *p); void gl_video_eq_update(struct gl_video *p); -void gl_video_set_debug(struct gl_video *p, bool enable); - float gl_video_scale_ambient_lux(float lmin, float lmax, float rmin, float rmax, float lux); void gl_video_set_ambient_lux(struct gl_video *p, int lux); diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index d3b8bbffa3..8a1e47bd48 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -45,6 +45,7 @@ #include "filter_kernels.h" #include "video/hwdec.h" #include "opengl/video.h" +#include "opengl/ra_gl.h" #define NUM_VSYNC_FENCES 10 @@ -65,6 +66,7 @@ struct gl_priv { struct mp_log *log; MPGLContext *glctx; GL *gl; + struct ra *ra; struct vo_opengl_opts opts; @@ -95,8 +97,7 @@ static void resize(struct gl_priv *p) struct mp_osd_res osd; vo_get_src_dst_rects(vo, &src, &dst, &osd); - int height = p->glctx->flip_v ? vo->dheight : -vo->dheight; - gl_video_resize(p->renderer, vo->dwidth, height, &src, &dst, &osd); + gl_video_resize(p->renderer, &src, &dst, &osd); vo->want_redraw = true; } @@ -130,7 +131,13 @@ static void draw_frame(struct vo *vo, struct vo_frame *frame) p->vsync_fences[p->num_vsync_fences++] = fence; } - gl_video_render_frame(p->renderer, frame, p->glctx->main_fb); + struct fbodst target = { + .tex = ra_create_wrapped_fb(p->ra, p->glctx->main_fb, + vo->dwidth, vo->dheight), + .flip = !p->glctx->flip_v, + }; + gl_video_render_frame(p->renderer, frame, target); + ra_tex_free(p->ra, &target.tex); if (p->opts.use_glFinish) gl->Finish(); @@ -145,7 +152,7 @@ static void flip_page(struct vo *vo) p->frames_rendered++; if (p->frames_rendered > 5 && !p->opts.use_gl_debug) - gl_video_set_debug(p->renderer, false); + ra_gl_set_debug(p->ra, false); if (p->opts.use_glFinish) gl->Finish(); @@ -422,9 +429,11 @@ static int preinit(struct vo *vo) MP_VERBOSE(vo, "swap_control extension missing.\n"); } - p->renderer = gl_video_init(p->gl, vo->log, vo->global); - if (!p->renderer) + p->ra = ra_create_gl(p->gl, vo->log); + if (!p->ra) goto err_out; + + p->renderer = gl_video_init(p->ra, vo->log, vo->global); gl_video_set_osd_source(p->renderer, vo->osd); gl_video_configure_queue(p->renderer, vo); @@ -438,6 +447,13 @@ static int preinit(struct vo *vo) vo->hwdec_devs, vo->opts->gl_hwdec_interop); gl_video_set_hwdec(p->renderer, p->hwdec); + gl_check_error(p->gl, p->log, "before retrieving framebuffer depth"); + int fb_depth = gl_get_fb_depth(p->gl, p->glctx->main_fb); + gl_check_error(p->gl, p->log, "retrieving framebuffer depth"); + if (fb_depth) + MP_VERBOSE(p, "Reported display depth: %d\n", fb_depth); + gl_video_set_fb_depth(p->renderer, fb_depth); + return 0; err_out: diff --git a/video/out/vo_opengl_cb.c b/video/out/vo_opengl_cb.c index 171b96406b..d9289d16f6 100644 --- a/video/out/vo_opengl_cb.c +++ b/video/out/vo_opengl_cb.c @@ -27,6 +27,7 @@ #include "opengl/common.h" #include "opengl/video.h" #include "opengl/hwdec.h" +#include "opengl/ra_gl.h" #include "libmpv/opengl_cb.h" @@ -87,6 +88,7 @@ struct mpv_opengl_cb_context { // application's OpenGL context is current - i.e. only while the // host application is calling certain mpv_opengl_cb_* APIs. GL *gl; + struct ra *ra; struct gl_video *renderer; struct gl_hwdec *hwdec; struct m_config_cache *vo_opts_cache; @@ -171,10 +173,12 @@ int mpv_opengl_cb_init_gl(struct mpv_opengl_cb_context *ctx, const char *exts, return MPV_ERROR_UNSUPPORTED; } - ctx->renderer = gl_video_init(ctx->gl, ctx->log, ctx->global); - if (!ctx->renderer) + ctx->ra = ra_create_gl(ctx->gl, ctx->log); + if (!ctx->ra) return MPV_ERROR_UNSUPPORTED; + ctx->renderer = gl_video_init(ctx->ra, ctx->log, ctx->global); + m_config_cache_update(ctx->vo_opts_cache); ctx->hwdec_devs = hwdec_devices_create(); @@ -223,6 +227,7 @@ int mpv_opengl_cb_uninit_gl(struct mpv_opengl_cb_context *ctx) ctx->hwdec = NULL; hwdec_devices_destroy(ctx->hwdec_devs); ctx->hwdec_devs = NULL; + ra_free(&ctx->ra); talloc_free(ctx->gl); ctx->gl = NULL; return 0; @@ -232,6 +237,16 @@ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h) { assert(ctx->renderer); + if (fbo && !(ctx->gl->mpgl_caps & MPGL_CAP_FB)) { + MP_FATAL(ctx, "Rendering to FBO requested, but no FBO extension found!\n"); + return MPV_ERROR_UNSUPPORTED; + } + + struct fbodst target = { + .tex = ra_create_wrapped_fb(ctx->ra, fbo, vp_w, abs(vp_h)), + .flip = vp_h < 0, + }; + reset_gl_state(ctx->gl); pthread_mutex_lock(&ctx->lock); @@ -256,7 +271,7 @@ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h) &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); + gl_video_resize(ctx->renderer, &src, &dst, &osd); } if (ctx->reconfigured) { @@ -272,7 +287,7 @@ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h) mp_read_option_raw(ctx->global, "opengl-debug", &m_option_type_flag, &debug); ctx->gl->debug_context = debug; - gl_video_set_debug(ctx->renderer, debug); + ra_gl_set_debug(ctx->ra, debug); if (gl_video_icc_auto_enabled(ctx->renderer)) MP_ERR(ctx, "icc-profile-auto is not available with opengl-cb\n"); } @@ -315,7 +330,7 @@ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h) pthread_mutex_unlock(&ctx->lock); MP_STATS(ctx, "glcb-render"); - gl_video_render_frame(ctx->renderer, frame, fbo); + gl_video_render_frame(ctx->renderer, frame, target); reset_gl_state(ctx->gl); @@ -327,6 +342,8 @@ int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int vp_w, int vp_h) pthread_cond_wait(&ctx->wakeup, &ctx->lock); pthread_mutex_unlock(&ctx->lock); + ra_tex_free(ctx->ra, &target.tex); + return 0; }