diff options
Diffstat (limited to 'video/out')
-rw-r--r-- | video/out/opengl/osd.c | 8 | ||||
-rw-r--r-- | video/out/opengl/osd.h | 4 | ||||
-rw-r--r-- | video/out/opengl/ra.h | 12 | ||||
-rw-r--r-- | video/out/opengl/ra_gl.c | 7 | ||||
-rw-r--r-- | video/out/opengl/utils.c | 30 | ||||
-rw-r--r-- | video/out/opengl/utils.h | 9 | ||||
-rw-r--r-- | video/out/opengl/video.c | 71 |
7 files changed, 76 insertions, 65 deletions
diff --git a/video/out/opengl/osd.c b/video/out/opengl/osd.c index a656451c2e..2678e12774 100644 --- a/video/out/opengl/osd.c +++ b/video/out/opengl/osd.c @@ -282,8 +282,8 @@ static void get_3d_side_by_side(int stereo_mode, int div[2]) } } -void mpgl_osd_draw_finish(struct mpgl_osd *ctx, int vp_w, int vp_h, int index, - struct gl_shader_cache *sc, struct ra_tex *target) +void mpgl_osd_draw_finish(struct mpgl_osd *ctx, int index, + struct gl_shader_cache *sc, struct fbodst target) { struct mpgl_osd_part *part = ctx->parts[index]; @@ -295,7 +295,7 @@ void mpgl_osd_draw_finish(struct mpgl_osd *ctx, int vp_w, int vp_h, int index, for (int x = 0; x < div[0]; x++) { for (int y = 0; y < div[1]; y++) { struct gl_transform t; - gl_transform_ortho(&t, 0, vp_w, 0, vp_h); + gl_transform_ortho_fbodst(&t, target); float a_x = ctx->osd_res.w * x; float a_y = ctx->osd_res.h * y; @@ -309,7 +309,7 @@ void mpgl_osd_draw_finish(struct mpgl_osd *ctx, int vp_w, int vp_h, int index, const int *factors = &blend_factors[part->format][0]; gl_sc_blend(sc, factors[0], factors[1], factors[2], factors[3]); - gl_sc_dispatch_draw(sc, target, part->vertices, part->num_vertices); + gl_sc_dispatch_draw(sc, target.tex, part->vertices, part->num_vertices); } static void set_res(struct mpgl_osd *ctx, struct mp_osd_res res, int stereo_mode) diff --git a/video/out/opengl/osd.h b/video/out/opengl/osd.h index 08c143ac0e..9763d7e03a 100644 --- a/video/out/opengl/osd.h +++ b/video/out/opengl/osd.h @@ -17,8 +17,8 @@ void mpgl_osd_generate(struct mpgl_osd *ctx, struct mp_osd_res res, double pts, void mpgl_osd_resize(struct mpgl_osd *ctx, struct mp_osd_res res, int stereo_mode); bool mpgl_osd_draw_prepare(struct mpgl_osd *ctx, int index, struct gl_shader_cache *sc); -void mpgl_osd_draw_finish(struct mpgl_osd *ctx, int vp_w, int vp_h, int index, - struct gl_shader_cache *sc, struct ra_tex *target); +void mpgl_osd_draw_finish(struct mpgl_osd *ctx, int index, + struct gl_shader_cache *sc, struct fbodst target); int64_t mpgl_get_change_counter(struct mpgl_osd *ctx); #endif diff --git a/video/out/opengl/ra.h b/video/out/opengl/ra.h index e93061eb61..cf18b110a5 100644 --- a/video/out/opengl/ra.h +++ b/video/out/opengl/ra.h @@ -349,17 +349,17 @@ struct ra_fns { // Copy a sub-rectangle from one texture to another. The source/dest region // is always within the texture bounds. Areas outside the dest region are - // preserved. The formats of the textures will be losely compatible (this - // probably has to be defined strictly). The dst texture can be a swapchain - // framebuffer, but src can not. Only 2D textures are supported. + // preserved. The formats of the textures must be losely compatible. The + // dst texture can be a swapchain framebuffer, but src can not. Only 2D + // textures are supported. // Both textures must have tex->params.render_dst==true (even src, which is // an odd GL requirement). - // A rectangle with negative width or height means a flipped copy should be - // done. Coordinates are always in pixels. + // Rectangle with negative width/height lead to flipping, different src/dst + // sizes lead to point scaling. Coordinates are always in pixels. // Optional. Only available if RA_CAP_BLIT is set (if it's not set, the must // not be called, even if it's non-NULL). void (*blit)(struct ra *ra, struct ra_tex *dst, struct ra_tex *src, - int dst_x, int dst_y, struct mp_rect *src_rc); + struct mp_rect *dst_rc, struct mp_rect *src_rc); // Compile a shader and create a pipeline. This is a rare operation. // The params pointer and anything it points to must stay valid until diff --git a/video/out/opengl/ra_gl.c b/video/out/opengl/ra_gl.c index 3966afcebb..bc38a60e53 100644 --- a/video/out/opengl/ra_gl.c +++ b/video/out/opengl/ra_gl.c @@ -498,7 +498,7 @@ static void gl_clear(struct ra *ra, struct ra_tex *dst, float color[4], } static void gl_blit(struct ra *ra, struct ra_tex *dst, struct ra_tex *src, - int dst_x, int dst_y, struct mp_rect *src_rc) + struct mp_rect *dst_rc, struct mp_rect *src_rc) { GL *gl = ra_gl_get(ra); @@ -508,13 +508,10 @@ static void gl_blit(struct ra *ra, struct ra_tex *dst, struct ra_tex *src, struct ra_tex_gl *src_gl = src->priv; struct ra_tex_gl *dst_gl = dst->priv; - int w = mp_rect_w(*src_rc); - int h = mp_rect_h(*src_rc); - gl->BindFramebuffer(GL_READ_FRAMEBUFFER, src_gl->fbo); gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, dst_gl->fbo); gl->BlitFramebuffer(src_rc->x0, src_rc->y0, src_rc->x1, src_rc->y1, - dst_x, dst_y, dst_x + w, dst_y + h, + dst_rc->x0, dst_rc->y0, dst_rc->x1, dst_rc->y1, GL_COLOR_BUFFER_BIT, GL_NEAREST); gl->BindFramebuffer(GL_READ_FRAMEBUFFER, 0); gl->BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); diff --git a/video/out/opengl/utils.c b/video/out/opengl/utils.c index ffc2fb3fce..a0174e8063 100644 --- a/video/out/opengl/utils.c +++ b/video/out/opengl/utils.c @@ -33,6 +33,12 @@ void gl_transform_trans(struct gl_transform t, struct gl_transform *x) gl_transform_vec(t, &x->t[0], &x->t[1]); } +void gl_transform_ortho_fbodst(struct gl_transform *t, struct fbodst fbo) +{ + int y_dir = fbo.flip ? -1 : 1; + gl_transform_ortho(t, 0, fbo.tex->params.w, 0, fbo.tex->params.h * y_dir); +} + // Create a texture and a FBO using the texture as color attachments. // fmt: texture internal format // If the parameters are the same as the previous call, do not touch it. @@ -41,6 +47,8 @@ void gl_transform_trans(struct gl_transform t, struct gl_transform *x) bool fbotex_change(struct fbotex *fbo, struct ra *ra, struct mp_log *log, int w, int h, const struct ra_format *fmt, int flags) { + int lw = w, lh = h; + if (fbo->tex) { int cw = w, ch = h; int rw = fbo->tex->params.w, rh = fbo->tex->params.h; @@ -50,15 +58,10 @@ bool fbotex_change(struct fbotex *fbo, struct ra *ra, struct mp_log *log, 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; - } + if (rw == cw && rh == ch && fbo->tex->params.format == fmt) + goto done; } - int lw = w, lh = h; - if (flags & FBOTEX_FUZZY_W) w = MP_ALIGN_UP(w, 256); if (flags & FBOTEX_FUZZY_H) @@ -75,10 +78,6 @@ bool fbotex_change(struct fbotex *fbo, struct ra *ra, struct mp_log *log, *fbo = (struct fbotex) { .ra = ra, - .rw = w, - .rh = h, - .lw = lw, - .lh = lh, }; struct ra_tex_params params = { @@ -100,6 +99,15 @@ bool fbotex_change(struct fbotex *fbo, struct ra *ra, struct mp_log *log, return false; } +done: + + fbo->lw = lw; + fbo->lh = lh; + + fbo->fbo = (struct fbodst){ + .tex = fbo->tex, + }; + return true; } diff --git a/video/out/opengl/utils.h b/video/out/opengl/utils.h index 12d77efbf8..5f6efc9299 100644 --- a/video/out/opengl/utils.h +++ b/video/out/opengl/utils.h @@ -62,11 +62,18 @@ static inline bool gl_transform_eq(struct gl_transform a, struct gl_transform b) void gl_transform_trans(struct gl_transform t, struct gl_transform *x); +struct fbodst { + struct ra_tex *tex; + bool flip; // mirror vertically +}; + +void gl_transform_ortho_fbodst(struct gl_transform *t, struct fbodst fbo); + struct fbotex { 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 + struct fbodst fbo; }; void fbotex_uninit(struct fbotex *fbo); diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c index 6300ea84ea..57c1c5b18f 100644 --- a/video/out/opengl/video.c +++ b/video/out/opengl/video.c @@ -1162,14 +1162,14 @@ static void dispatch_compute(struct gl_video *p, int w, int h, p->pass_tex_num = 0; } -static struct mp_pass_perf render_pass_quad(struct gl_video *p, int vp_w, int vp_h, - struct ra_tex *target, +static struct mp_pass_perf render_pass_quad(struct gl_video *p, + struct fbodst target, const struct mp_rect *dst) { struct vertex va[6] = {0}; struct gl_transform t; - gl_transform_ortho(&t, 0, vp_w, 0, vp_h); + gl_transform_ortho_fbodst(&t, target); float x[2] = {dst->x0, dst->x1}; float y[2] = {dst->y0, dst->y1}; @@ -1197,15 +1197,15 @@ static struct mp_pass_perf render_pass_quad(struct gl_video *p, int vp_w, int vp va[4] = va[2]; va[5] = va[1]; - return gl_sc_dispatch_draw(p->sc, target, va, 6); + return gl_sc_dispatch_draw(p->sc, target.tex, va, 6); } -static void finish_pass_direct(struct gl_video *p, struct ra_tex *target, - int vp_w, int vp_h, const struct mp_rect *dst) +static void finish_pass_direct(struct gl_video *p, struct fbodst target, + const struct mp_rect *dst) { pass_prepare_src_tex(p); gl_sc_set_vertex_format(p->sc, vertex_vao, sizeof(struct vertex)); - pass_record(p, render_pass_quad(p, vp_w, vp_h, target, dst)); + pass_record(p, render_pass_quad(p, target, dst)); debug_check_gl(p, "after rendering"); memset(&p->pass_tex, 0, sizeof(p->pass_tex)); p->pass_tex_num = 0; @@ -1234,8 +1234,7 @@ static void finish_pass_fbo(struct gl_video *p, struct fbotex *dst_fbo, debug_check_gl(p, "after dispatching compute shader"); } else { - finish_pass_direct(p, dst_fbo->tex, dst_fbo->rw, dst_fbo->rh, - &(struct mp_rect){0, 0, w, h}); + finish_pass_direct(p, dst_fbo->fbo, &(struct mp_rect){0, 0, w, h}); } } @@ -2607,8 +2606,7 @@ static void pass_dither(struct gl_video *p) // Draws the OSD, in scene-referred colors.. If cms is true, subtitles are // instead adapted to the display's gamut. static void pass_draw_osd(struct gl_video *p, int draw_flags, double pts, - struct mp_osd_res rect, int vp_w, int vp_h, - struct ra_tex *target, bool cms) + struct mp_osd_res rect, struct fbodst target, bool cms) { mpgl_osd_generate(p->osd, rect, pts, p->image_params.stereo_out, draw_flags); @@ -2628,7 +2626,7 @@ static void pass_draw_osd(struct gl_video *p, int draw_flags, double pts, pass_colormanage(p, csp_srgb, true); } - mpgl_osd_draw_finish(p->osd, vp_w, vp_h, n, p->sc, target); + mpgl_osd_draw_finish(p->osd, n, p->sc, target); } timer_pool_stop(p->osd_timer); @@ -2719,7 +2717,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.tex, false); + p->blend_subs_fbo.fbo, false); pass_read_fbo(p, &p->blend_subs_fbo); pass_describe(p, "blend subs video"); } @@ -2749,8 +2747,7 @@ 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.tex, - false); + p->blend_subs_fbo.fbo, false); pass_read_fbo(p, &p->blend_subs_fbo); pass_describe(p, "blend subs"); } @@ -2760,7 +2757,7 @@ static bool pass_render_frame(struct gl_video *p, struct mp_image *mpi, uint64_t return true; } -static void pass_draw_to_screen(struct gl_video *p, struct ra_tex *fbo) +static void pass_draw_to_screen(struct gl_video *p, struct fbodst fbo) { if (p->dumb_mode) pass_render_frame_dumb(p); @@ -2805,7 +2802,7 @@ static void pass_draw_to_screen(struct gl_video *p, struct ra_tex *fbo) pass_dither(p); pass_describe(p, "output to screen"); - finish_pass_direct(p, fbo, p->vp_w, p->vp_h, &p->dst_rect); + finish_pass_direct(p, fbo, &p->dst_rect); } static bool update_fbosurface(struct gl_video *p, struct mp_image *mpi, @@ -2834,7 +2831,7 @@ static bool update_fbosurface(struct gl_video *p, struct mp_image *mpi, // Draws an interpolate frame to fbo, based on the frame timing in t static void gl_video_interpolate_frame(struct gl_video *p, struct vo_frame *t, - struct ra_tex *fbo) + struct fbodst fbo) { bool is_new = false; @@ -3025,8 +3022,10 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo) } } - struct ra_tex *target = - ra_create_wrapped_fb(p->ra, fbo, p->vp_w, abs(p->vp_h)); + 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)}; p->broken_frame = false; @@ -3038,13 +3037,13 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo) { 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, color, &target_rc); + p->ra->fns->clear(p->ra, target.tex, color, &target_rc); } if (p->hwdec_active && p->hwdec->driver->overlay_frame) { if (has_frame) { float *color = p->hwdec->overlay_colorkey; - p->ra->fns->clear(p->ra, target, color, &p->dst_rect); + p->ra->fns->clear(p->ra, target.tex, color, &p->dst_rect); } if (frame->frame_id != p->image.id || !frame->current) @@ -3084,14 +3083,14 @@ void gl_video_render_frame(struct gl_video *p, struct vo_frame *frame, int fbo) // For the non-interpolation case, we draw to a single "cache" // FBO to speed up subsequent re-draws (if any exist) - struct ra_tex *dest_fbo = target; + struct fbodst dest_fbo = target; if (frame->num_vsyncs > 1 && frame->display_synced && !p->dumb_mode && (p->ra->caps & RA_CAP_BLIT)) { fbotex_change(&p->output_fbo, p->ra, p->log, - p->vp_w, abs(p->vp_h), + target.tex->params.w, target.tex->params.h, p->fbo_format, FBOTEX_FUZZY); - dest_fbo = p->output_fbo.tex; + dest_fbo = p->output_fbo.fbo; p->output_fbo_valid = true; } pass_draw_to_screen(p, dest_fbo); @@ -3101,14 +3100,15 @@ 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"); - struct mp_rect rc = p->dst_rect; - if (p->vp_h < 0) { - rc.y1 = -p->vp_h - p->dst_rect.y0; - rc.y0 = -p->vp_h - p->dst_rect.y1; + struct mp_rect src = p->dst_rect; + struct mp_rect dst = src; + if (target.flip) { + dst.y0 = target.tex->params.h - src.y0; + dst.y1 = target.tex->params.h - src.y1; } timer_pool_start(p->blit_timer); - p->ra->fns->blit(p->ra, target, p->output_fbo.tex, - rc.x0, rc.y0, &rc); + p->ra->fns->blit(p->ra, target.tex, p->output_fbo.tex, + &dst, &src); timer_pool_stop(p->blit_timer); pass_record(p, timer_pool_measure(p->blit_timer)); } @@ -3129,7 +3129,7 @@ done: pass_info_reset(p, true); pass_draw_osd(p, p->opts.blend_subs ? OSD_DRAW_OSD_ONLY : 0, - p->osd_pts, p->osd_rect, p->vp_w, p->vp_h, target, true); + p->osd_pts, p->osd_rect, target, true); debug_check_gl(p, "after OSD rendering"); } @@ -3137,10 +3137,10 @@ done: // Make the screen solid blue to make it visually clear that an // error has occurred float color[4] = {0.0, 0.05, 0.5, 1.0}; - p->ra->fns->clear(p->ra, target, color, &target_rc); + p->ra->fns->clear(p->ra, target.tex, color, &target_rc); } - ra_tex_free(p->ra, &target); + 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 @@ -3228,8 +3228,7 @@ static void reinterleave_vdpau(struct gl_video *p, struct gl_hwdec_frame *frame, fbotex_change(fbo, p->ra, p->log, w, h * 2, fmt, 0); pass_describe(p, "vdpau reinterleaving"); - finish_pass_direct(p, fbo->tex, fbo->rw, fbo->rh, - &(struct mp_rect){0, 0, w, h * 2}); + finish_pass_direct(p, fbo->fbo, &(struct mp_rect){0, 0, w, h * 2}); for (int t = 0; t < 2; t++) ra_tex_free(p->ra, &tmp[t]); |