summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-08-07 19:14:18 +0200
committerwm4 <wm4@nowhere>2017-08-07 19:17:28 +0200
commit47ea771b7a29b04e35276d38733f72970b4dd448 (patch)
tree2a9f9c52acba9f662d62a290f739c502c6ca0ff8 /video
parent1adf324d8b1261abfc02d905f98055991b29ac11 (diff)
downloadmpv-47ea771b7a29b04e35276d38733f72970b4dd448.tar.bz2
mpv-47ea771b7a29b04e35276d38733f72970b4dd448.tar.xz
vo_opengl: further GL API use separation
Move multiple GL-specific things from the renderer to other places like vo_opengl.c, vo_opengl_cb.c, and ra_gl.c. The vp_w/vp_h parameters to gl_video_resize() make no sense anymore, and are implicitly part of struct fbodst. Checking the main framebuffer depth is moved to vo_opengl.c. For vo_opengl_cb.c it always assumes 8. The API user now has to override this manually. The previous heuristic didn't make much sense anyway. The only remaining dependency on GL is the hwdec stuff, which is harder to change.
Diffstat (limited to 'video')
-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
12 files changed, 160 insertions, 122 deletions
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;
}