summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/interface-changes.rst5
-rw-r--r--common/common.c6
-rw-r--r--common/common.h1
-rw-r--r--video/out/opengl/common.c4
-rw-r--r--video/out/opengl/common.h1
-rw-r--r--video/out/opengl/hwdec.h2
-rw-r--r--video/out/opengl/hwdec_rpi.c8
-rw-r--r--video/out/opengl/ra.c8
-rw-r--r--video/out/opengl/ra.h12
-rw-r--r--video/out/opengl/ra_gl.c52
-rw-r--r--video/out/opengl/ra_gl.h5
-rw-r--r--video/out/opengl/video.c123
-rw-r--r--video/out/opengl/video.h12
-rw-r--r--video/out/vo_opengl.c28
-rw-r--r--video/out/vo_opengl_cb.c27
15 files changed, 172 insertions, 122 deletions
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;
}