diff options
-rw-r--r-- | DOCS/interface-changes.rst | 3 | ||||
-rw-r--r-- | video/out/opengl/ra.c | 9 | ||||
-rw-r--r-- | video/out/opengl/ra.h | 8 | ||||
-rw-r--r-- | video/out/opengl/ra_gl.c | 37 | ||||
-rw-r--r-- | video/out/opengl/ra_gl.h | 1 | ||||
-rw-r--r-- | video/out/opengl/utils.c | 118 | ||||
-rw-r--r-- | video/out/opengl/utils.h | 19 | ||||
-rw-r--r-- | video/out/opengl/video.c | 99 | ||||
-rw-r--r-- | video/out/opengl/video.h | 2 |
9 files changed, 161 insertions, 135 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index ea4545bdc3..452e30ed73 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -27,6 +27,9 @@ Interface changes warning) - drop deprecated --video-aspect-method=hybrid option choice - rename --hdr-tone-mapping to --tone-mapping (and generalize it) + - --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. --- mpv 0.26.0 --- - remove remaining deprecated audio device options, like --alsa-device Some of them were removed in earlier releases. diff --git a/video/out/opengl/ra.c b/video/out/opengl/ra.c index 73f2915f95..9096a50148 100644 --- a/video/out/opengl/ra.c +++ b/video/out/opengl/ra.c @@ -80,6 +80,15 @@ const struct ra_format *ra_find_float16_format(struct ra *ra, int n_components) return NULL; } +const struct ra_format *ra_find_named_format(struct ra *ra, const char *name) +{ + for (int n = 0; n < ra->num_formats; n++) { + const struct ra_format *fmt = ra->formats[n]; + if (strcmp(fmt->name, name) == 0) + return fmt; + } + return NULL; +} // Like ra_find_unorm_format(), but if no fixed point format is available, // return an unsigned integer format. diff --git a/video/out/opengl/ra.h b/video/out/opengl/ra.h index 866039a828..bd7a904860 100644 --- a/video/out/opengl/ra.h +++ b/video/out/opengl/ra.h @@ -76,6 +76,13 @@ struct ra_tex_params { void *initial_data; }; +// Conflates the following typical GPU API concepts: +// - texture itself +// - sampler state +// - staging buffers for texture upload +// - framebuffer objects +// - wrappers for swapchain framebuffers +// - synchronization needed for upload/rendering/etc. struct ra_tex { // All fields are read-only after creation. struct ra_tex_params params; @@ -149,6 +156,7 @@ const struct ra_format *ra_find_uint_format(struct ra *ra, int bytes_per_component, int n_components); const struct ra_format *ra_find_float16_format(struct ra *ra, int n_components); +const struct ra_format *ra_find_named_format(struct ra *ra, const char *name); struct ra_imgfmt_desc { int num_planes; diff --git a/video/out/opengl/ra_gl.c b/video/out/opengl/ra_gl.c index 46cbbda987..a52eeec94b 100644 --- a/video/out/opengl/ra_gl.c +++ b/video/out/opengl/ra_gl.c @@ -42,7 +42,8 @@ int ra_init_gl(struct ra *ra, GL *gl) .pixel_size = gl_bytes_per_pixel(gl_fmt->format, gl_fmt->type), .luminance_alpha = gl_fmt->format == GL_LUMINANCE_ALPHA, .linear_filter = gl_fmt->flags & F_TF, - .renderable = gl_fmt->flags & F_CR, + .renderable = (gl_fmt->flags & F_CR) && + (gl->mpgl_caps & MPGL_CAP_FB), }; int csize = gl_component_size(gl_fmt->type) * 8; @@ -100,6 +101,9 @@ static void gl_tex_destroy(struct ra *ra, struct ra_tex *tex) struct ra_gl *p = ra->priv; struct ra_tex_gl *tex_gl = tex->priv; + if (tex_gl->fbo) + p->gl->DeleteFramebuffers(1, &tex_gl->fbo); + p->gl->DeleteTextures(1, &tex_gl->texture); gl_pbo_upload_uninit(&tex_gl->pbo); talloc_free(tex_gl); @@ -167,6 +171,36 @@ static struct ra_tex *gl_tex_create(struct ra *ra, tex->params.initial_data = NULL; + gl_check_error(gl, ra->log, "after creating texture"); + + if (tex->params.render_dst) { + if (!tex->params.format->renderable) { + MP_ERR(ra, "Trying to create renderable texture with unsupported " + "format.\n"); + ra_tex_free(ra, &tex); + return NULL; + } + + assert(gl->mpgl_caps & MPGL_CAP_FB); + + gl->GenFramebuffers(1, &tex_gl->fbo); + gl->BindFramebuffer(GL_FRAMEBUFFER, tex_gl->fbo); + gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, tex_gl->texture, 0); + GLenum err = gl->CheckFramebufferStatus(GL_FRAMEBUFFER); + gl->BindFramebuffer(GL_FRAMEBUFFER, 0); + + if (err != GL_FRAMEBUFFER_COMPLETE) { + MP_ERR(ra, "Error: framebuffer completeness check failed (error=%d).\n", + (int)err); + ra_tex_free(ra, &tex); + return NULL; + } + + + gl_check_error(gl, ra->log, "after creating framebuffer"); + } + return tex; } @@ -294,4 +328,3 @@ static struct ra_fns ra_fns_gl = { .destroy_mapped_buffer = gl_destroy_mapped_buffer, .poll_mapped_buffer = gl_poll_mapped_buffer, }; - diff --git a/video/out/opengl/ra_gl.h b/video/out/opengl/ra_gl.h index 9d5cb23fb7..d17b576afc 100644 --- a/video/out/opengl/ra_gl.h +++ b/video/out/opengl/ra_gl.h @@ -13,6 +13,7 @@ struct ra_gl { struct ra_tex_gl { GLenum target; GLuint texture; + GLuint fbo; // 0 if no rendering requested // These 3 fields can be 0 if unknown. GLint internal_format; GLenum format; diff --git a/video/out/opengl/utils.c b/video/out/opengl/utils.c index c38b7bbcbc..239009d4ac 100644 --- a/video/out/opengl/utils.c +++ b/video/out/opengl/utils.c @@ -254,37 +254,36 @@ static void gl_vao_draw_data(struct gl_vao *vao, GLenum prim, void *ptr, size_t } // Create a texture and a FBO using the texture as color attachments. -// iformat: texture internal format +// fmt: texture internal format // Returns success. -bool fbotex_init(struct fbotex *fbo, GL *gl, struct mp_log *log, int w, int h, - GLenum iformat) +bool fbotex_init(struct fbotex *fbo, struct ra *ra, struct mp_log *log, + int w, int h, const struct ra_format *fmt) { - assert(!fbo->fbo); - assert(!fbo->texture); - return fbotex_change(fbo, gl, log, w, h, iformat, 0); + assert(!fbo->tex); + return fbotex_change(fbo, ra, log, w, h, fmt, 0); } // Like fbotex_init(), except it can be called on an already initialized FBO; // and if the parameters are the same as the previous call, do not touch it. // flags can be 0, or a combination of FBOTEX_FUZZY_W and FBOTEX_FUZZY_H. // Enabling FUZZY for W or H means the w or h does not need to be exact. -bool fbotex_change(struct fbotex *fbo, GL *gl, struct mp_log *log, int w, int h, - GLenum iformat, int flags) -{ - bool res = true; - - int cw = w, ch = h; - - if ((flags & FBOTEX_FUZZY_W) && cw < fbo->rw) - cw = fbo->rw; - if ((flags & FBOTEX_FUZZY_H) && ch < fbo->rh) - ch = fbo->rh; - - if (fbo->rw == cw && fbo->rh == ch && fbo->iformat == iformat) { - fbo->lw = w; - fbo->lh = h; - fbotex_invalidate(fbo); - return true; +bool fbotex_change(struct fbotex *fbo, struct ra *ra, struct mp_log *log, + int w, int h, const struct ra_format *fmt, int flags) +{ + if (fbo->tex) { + int cw = w, ch = h; + int rw = fbo->tex->params.w, rh = fbo->tex->params.h; + + if ((flags & FBOTEX_FUZZY_W) && cw < rw) + cw = rw; + if ((flags & FBOTEX_FUZZY_H) && ch < rh) + ch = rh; + + if (rw == cw && rh == ch && fbo->tex->params.format == fmt) { + fbo->lw = w; + fbo->lh = h; + return true; + } } int lw = w, lh = h; @@ -296,80 +295,51 @@ bool fbotex_change(struct fbotex *fbo, GL *gl, struct mp_log *log, int w, int h, mp_verbose(log, "Create FBO: %dx%d (%dx%d)\n", lw, lh, w, h); - const struct gl_format *format = gl_find_internal_format(gl, iformat); - if (!format || (format->flags & F_CF) != F_CF) { - mp_verbose(log, "Format 0x%x not supported.\n", (unsigned)iformat); + if (!fmt || !fmt->renderable || !fmt->linear_filter) { + mp_err(log, "Format %s not supported.\n", fmt ? fmt->name : "(unset)"); return false; } - assert(gl->mpgl_caps & MPGL_CAP_FB); fbotex_uninit(fbo); *fbo = (struct fbotex) { - .gl = gl, + .ra = ra, .rw = w, .rh = h, .lw = lw, .lh = lh, - .iformat = iformat, }; - gl->GenFramebuffers(1, &fbo->fbo); - gl->GenTextures(1, &fbo->texture); - gl->BindTexture(GL_TEXTURE_2D, fbo->texture); - gl->TexImage2D(GL_TEXTURE_2D, 0, format->internal_format, fbo->rw, fbo->rh, 0, - format->format, format->type, NULL); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gl->BindTexture(GL_TEXTURE_2D, 0); - - gl_check_error(gl, log, "after creating framebuffer texture"); - - gl->BindFramebuffer(GL_FRAMEBUFFER, fbo->fbo); - gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - GL_TEXTURE_2D, fbo->texture, 0); - - GLenum err = gl->CheckFramebufferStatus(GL_FRAMEBUFFER); - if (err != GL_FRAMEBUFFER_COMPLETE) { - mp_err(log, "Error: framebuffer completeness check failed (error=%d).\n", - (int)err); - res = false; - } + struct ra_tex_params params = { + .dimensions = 2, + .w = w, + .h = h, + .d = 1, + .format = fmt, + .src_linear = true, + .render_src = true, + .render_dst = true, + }; - gl->BindFramebuffer(GL_FRAMEBUFFER, 0); + fbo->tex = ra_tex_create(fbo->ra, ¶ms); - gl_check_error(gl, log, "after creating framebuffer"); + if (!fbo->tex) { + mp_err(log, "Error: framebuffer could not be created.\n"); + fbotex_uninit(fbo); + return false; + } - return res; + return true; } void fbotex_uninit(struct fbotex *fbo) { - GL *gl = fbo->gl; - - if (gl && (gl->mpgl_caps & MPGL_CAP_FB)) { - gl->DeleteFramebuffers(1, &fbo->fbo); - gl->DeleteTextures(1, &fbo->texture); + if (fbo->ra) { + ra_tex_free(fbo->ra, &fbo->tex); *fbo = (struct fbotex) {0}; } } -// Mark framebuffer contents as unneeded. -void fbotex_invalidate(struct fbotex *fbo) -{ - GL *gl = fbo->gl; - - if (!fbo->fbo || !gl->InvalidateFramebuffer) - return; - - gl->BindFramebuffer(GL_FRAMEBUFFER, fbo->fbo); - gl->InvalidateFramebuffer(GL_FRAMEBUFFER, 1, - (GLenum[]){GL_COLOR_ATTACHMENT0}); - gl->BindFramebuffer(GL_FRAMEBUFFER, 0); -} - // Standard parallel 2D projection, except y1 < y0 means that the coordinate // system is flipped, not the projection. void gl_transform_ortho(struct gl_transform *t, float x0, float x1, diff --git a/video/out/opengl/utils.h b/video/out/opengl/utils.h index ba36a59316..491c0da209 100644 --- a/video/out/opengl/utils.h +++ b/video/out/opengl/utils.h @@ -51,23 +51,20 @@ struct gl_vao_entry { }; struct fbotex { - GL *gl; - GLuint fbo; - GLuint texture; - GLenum iformat; - int rw, rh; // real (texture) size - int lw, lh; // logical (configured) size + struct ra *ra; + struct ra_tex *tex; + int rw, rh; // real (texture) size, same as tex->params.w/h + int lw, lh; // logical (configured) size, <= than texture size }; -bool fbotex_init(struct fbotex *fbo, GL *gl, struct mp_log *log, int w, int h, - GLenum iformat); +bool fbotex_init(struct fbotex *fbo, struct ra *ra, struct mp_log *log, + int w, int h, const struct ra_format *fmt); void fbotex_uninit(struct fbotex *fbo); -bool fbotex_change(struct fbotex *fbo, GL *gl, struct mp_log *log, int w, int h, - GLenum iformat, int flags); +bool fbotex_change(struct fbotex *fbo, struct ra *ra, struct mp_log *log, + int w, int h, const struct ra_format *fmt, int flags); #define FBOTEX_FUZZY_W 1 #define FBOTEX_FUZZY_H 2 #define FBOTEX_FUZZY (FBOTEX_FUZZY_W | FBOTEX_FUZZY_H) -void fbotex_invalidate(struct fbotex *fbo); // A 3x2 matrix, with the translation part separate. struct gl_transform { diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c index ecb0cba183..3fa85019df 100644 --- a/video/out/opengl/video.c +++ b/video/out/opengl/video.c @@ -227,6 +227,7 @@ struct gl_video { bool dumb_mode; bool forced_dumb_mode; + const struct ra_format *fbo_format; struct fbotex merge_fbo[4]; struct fbotex scale_fbo[4]; struct fbotex integer_fbo[4]; @@ -307,7 +308,7 @@ static const struct gl_video_opts gl_video_opts_def = { .dither_depth = -1, .dither_size = 6, .temporal_dither_period = 1, - .fbo_format = 0, + .fbo_format = "auto", .sigmoid_center = 0.75, .sigmoid_slope = 6.5, .scaler = { @@ -385,19 +386,7 @@ const struct m_sub_options gl_video_conf = { OPT_FLAG("sigmoid-upscaling", sigmoid_upscaling, 0), OPT_FLOATRANGE("sigmoid-center", sigmoid_center, 0, 0.0, 1.0), OPT_FLOATRANGE("sigmoid-slope", sigmoid_slope, 0, 1.0, 20.0), - OPT_CHOICE("opengl-fbo-format", fbo_format, 0, - ({"rgb8", GL_RGB8}, - {"rgba8", GL_RGBA8}, - {"rgb10", GL_RGB10}, - {"rgb10_a2", GL_RGB10_A2}, - {"rgb16", GL_RGB16}, - {"rgb16f", GL_RGB16F}, - {"rgb32f", GL_RGB32F}, - {"rgba12", GL_RGBA12}, - {"rgba16", GL_RGBA16}, - {"rgba16f", GL_RGBA16F}, - {"rgba32f", GL_RGBA32F}, - {"auto", 0})), + OPT_STRING("opengl-fbo-format", fbo_format, 0), OPT_CHOICE_OR_INT("dither-depth", dither_depth, 0, -1, 16, ({"no", -1}, {"auto", 0})), OPT_CHOICE("dither", dither_algo, 0, @@ -453,6 +442,14 @@ static void gl_video_setup_hooks(struct gl_video *p); #define GLSLHF(...) gl_sc_haddf(p->sc, __VA_ARGS__) #define PRELUDE(...) gl_sc_paddf(p->sc, __VA_ARGS__) +static GLuint get_fbo(struct fbotex *fbo) +{ + if (!fbo->tex) + return -1; + struct ra_tex_gl *tex_gl = fbo->tex->priv; + return tex_gl->fbo ? tex_gl->fbo : -1; +} + static struct bstr load_cached_file(struct gl_video *p, const char *path) { if (!path || !path[0]) @@ -644,9 +641,10 @@ static struct img_tex img_tex_fbo(struct fbotex *fbo, enum plane_type type, int components) { assert(type != PLANE_NONE); + struct ra_tex_gl *tex_gl = fbo->tex->priv; return (struct img_tex){ .type = type, - .gl_tex = fbo->texture, + .gl_tex = tex_gl->texture, .gl_target = GL_TEXTURE_2D, .multiplier = 1.0, .tex_w = fbo->rw, @@ -1267,11 +1265,14 @@ static void finish_pass_direct(struct gl_video *p, GLint fbo, int vp_w, int vp_h static void finish_pass_fbo(struct gl_video *p, struct fbotex *dst_fbo, int w, int h, int flags) { - fbotex_change(dst_fbo, p->gl, p->log, w, h, p->opts.fbo_format, flags); + fbotex_change(dst_fbo, p->ra, p->log, w, h, p->fbo_format, flags); if (p->pass_compute.active) { - gl_sc_uniform_image2D(p->sc, "out_image", dst_fbo->texture, - dst_fbo->iformat, GL_WRITE_ONLY); + if (!dst_fbo->tex) + return; + struct ra_tex_gl *tex_gl = dst_fbo->tex->priv; + gl_sc_uniform_image2D(p->sc, "out_image", tex_gl->texture, + tex_gl->internal_format, GL_WRITE_ONLY); if (!p->pass_compute.directly_writes) GLSL(imageStore(out_image, ivec2(gl_GlobalInvocationID), color);) @@ -1279,7 +1280,7 @@ static void finish_pass_fbo(struct gl_video *p, struct fbotex *dst_fbo, p->gl->MemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT); p->pass_compute = (struct compute_info){0}; } else { - finish_pass_direct(p, dst_fbo->fbo, dst_fbo->rw, dst_fbo->rh, + finish_pass_direct(p, get_fbo(dst_fbo), dst_fbo->rw, dst_fbo->rh, &(struct mp_rect){0, 0, w, h}); } } @@ -2762,7 +2763,7 @@ static bool pass_render_frame(struct gl_video *p, struct mp_image *mpi, uint64_t }; finish_pass_fbo(p, &p->blend_subs_fbo, rect.w, rect.h, 0); pass_draw_osd(p, OSD_DRAW_SUB_ONLY, vpts, rect, - rect.w, rect.h, p->blend_subs_fbo.fbo, false); + rect.w, rect.h, get_fbo(&p->blend_subs_fbo), false); pass_read_fbo(p, &p->blend_subs_fbo); pass_describe(p, "blend subs video"); } @@ -2792,7 +2793,8 @@ static bool pass_render_frame(struct gl_video *p, struct mp_image *mpi, uint64_t } finish_pass_fbo(p, &p->blend_subs_fbo, p->texture_w, p->texture_h, 0); pass_draw_osd(p, OSD_DRAW_SUB_ONLY, vpts, rect, - p->texture_w, p->texture_h, p->blend_subs_fbo.fbo, false); + p->texture_w, p->texture_h, get_fbo(&p->blend_subs_fbo), + false); pass_read_fbo(p, &p->blend_subs_fbo); pass_describe(p, "blend subs"); } @@ -3134,10 +3136,10 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo) if (frame->num_vsyncs > 1 && frame->display_synced && !p->dumb_mode && gl->BlitFramebuffer) { - fbotex_change(&p->output_fbo, p->gl, p->log, + fbotex_change(&p->output_fbo, p->ra, p->log, p->vp_w, abs(p->vp_h), - p->opts.fbo_format, FBOTEX_FUZZY); - dest_fbo = p->output_fbo.fbo; + p->fbo_format, FBOTEX_FUZZY); + dest_fbo = get_fbo(&p->output_fbo); p->output_fbo_valid = true; } pass_draw_to_screen(p, dest_fbo); @@ -3147,7 +3149,7 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo) if (p->output_fbo_valid) { pass_info_reset(p, true); pass_describe(p, "redraw cached frame"); - gl->BindFramebuffer(GL_READ_FRAMEBUFFER, p->output_fbo.fbo); + gl->BindFramebuffer(GL_READ_FRAMEBUFFER, get_fbo(&p->output_fbo)); gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); struct mp_rect rc = p->dst_rect; if (p->vp_h < 0) { @@ -3276,14 +3278,21 @@ static void reinterleave_vdpau(struct gl_video *p, struct gl_hwdec_frame *frame) GLSLF(" ? texture(texture%d, texcoord%d)\n", ids[0], ids[0]); GLSLF(" : texture(texture%d, texcoord%d);", ids[1], ids[1]); - fbotex_change(fbo, p->gl, p->log, w, h * 2, n == 0 ? GL_R8 : GL_RG8, 0); + const struct ra_format *fmt = + ra_find_unorm_format(p->ra, 1, n == 0 ? 1 : 2); + fbotex_change(fbo, p->ra, p->log, w, h * 2, fmt, 0); pass_describe(p, "vdpau reinterleaving"); - finish_pass_direct(p, fbo->fbo, fbo->rw, fbo->rh, + finish_pass_direct(p, get_fbo(fbo), fbo->rw, fbo->rh, &(struct mp_rect){0, 0, w, h * 2}); + GLuint tex = 0; + if (fbo->tex) { + struct ra_tex_gl *tex_gl = fbo->tex->priv; + tex = tex_gl->texture; + } res.planes[n] = (struct gl_hwdec_plane){ - .gl_texture = fbo->texture, + .gl_texture = tex, .gl_target = GL_TEXTURE_2D, .tex_w = w, .tex_h = h * 2, @@ -3385,19 +3394,12 @@ error: return false; } -static bool test_fbo(struct gl_video *p, GLint format) +static bool test_fbo(struct gl_video *p, const struct ra_format *fmt) { - GL *gl = p->gl; - bool success = false; - MP_VERBOSE(p, "Testing FBO format 0x%x\n", (unsigned)format); + MP_VERBOSE(p, "Testing FBO format %s\n", fmt->name); struct fbotex fbo = {0}; - if (fbotex_init(&fbo, p->gl, p->log, 16, 16, format)) { - gl->BindFramebuffer(GL_FRAMEBUFFER, fbo.fbo); - gl->BindFramebuffer(GL_FRAMEBUFFER, 0); - success = true; - } + bool success = fbotex_init(&fbo, p->ra, p->log, 16, 16, fmt); fbotex_uninit(&fbo); - gl_check_error(gl, p->log, "FBO test"); return success; } @@ -3443,18 +3445,21 @@ static void check_gl_features(struct gl_video *p) bool have_compute = gl->mpgl_caps & MPGL_CAP_COMPUTE_SHADER; bool have_ssbo = gl->mpgl_caps & MPGL_CAP_SSBO; - const GLint auto_fbo_fmts[] = {GL_RGBA16, GL_RGBA16F, GL_RGB10_A2, - GL_RGBA8, 0}; - GLint user_fbo_fmts[] = {p->opts.fbo_format, 0}; - const GLint *fbo_fmts = user_fbo_fmts[0] ? user_fbo_fmts : auto_fbo_fmts; + const char *auto_fbo_fmts[] = {"rgba16", "rgba16f", "rgb10_a2", "rgba8", 0}; + const char *user_fbo_fmts[] = {p->opts.fbo_format, 0}; + const char **fbo_fmts = user_fbo_fmts[0] && strcmp(user_fbo_fmts[0], "auto") + ? user_fbo_fmts : auto_fbo_fmts; bool have_fbo = false; + p->fbo_format = NULL; for (int n = 0; fbo_fmts[n]; n++) { - GLint fmt = fbo_fmts[n]; - const struct gl_format *f = gl_find_internal_format(gl, fmt); - if (f && (f->flags & F_CF) == F_CF && test_fbo(p, fmt)) { - MP_VERBOSE(p, "Using FBO format 0x%x.\n", (unsigned)fmt); + const char *fmt = fbo_fmts[n]; + const struct ra_format *f = ra_find_named_format(p->ra, fmt); + if (!f && fbo_fmts == user_fbo_fmts) + MP_WARN(p, "FBO format '%s' not found!\n", fmt); + if (f && f->renderable && f->linear_filter && test_fbo(p, f)) { + MP_VERBOSE(p, "Using FBO format %s.\n", f->name); have_fbo = true; - p->opts.fbo_format = fmt; + p->fbo_format = f; break; } } diff --git a/video/out/opengl/video.h b/video/out/opengl/video.h index d74f3cf576..4f0c535af7 100644 --- a/video/out/opengl/video.h +++ b/video/out/opengl/video.h @@ -126,7 +126,7 @@ struct gl_video_opts { int dither_size; int temporal_dither; int temporal_dither_period; - int fbo_format; + char *fbo_format; int alpha_mode; int use_rectangle; struct m_color background; |