diff options
Diffstat (limited to 'video/out/opengl/video.c')
-rw-r--r-- | video/out/opengl/video.c | 129 |
1 files changed, 63 insertions, 66 deletions
diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c index ae1800821f..085bc825af 100644 --- a/video/out/opengl/video.c +++ b/video/out/opengl/video.c @@ -217,7 +217,6 @@ struct gl_video { struct fbotex blend_subs_fbo; struct fbotex output_fbo; struct fbosurface surfaces[FBOSURFACES_MAX]; - struct fbotex prescale_fbo[MAX_PRESCALE_PASSES]; int surface_idx; int surface_now; @@ -602,9 +601,6 @@ static void uninit_rendering(struct gl_video *p) fbotex_uninit(&p->indirect_fbo); fbotex_uninit(&p->blend_subs_fbo); - for (int pass = 0; pass < MAX_PRESCALE_PASSES; pass++) - fbotex_uninit(&p->prescale_fbo[pass]); - for (int n = 0; n < FBOSURFACES_MAX; n++) fbotex_uninit(&p->surfaces[n].fbotex); @@ -910,9 +906,11 @@ static void pass_prepare_src_tex(struct gl_video *p) char texture_name[32]; char texture_size[32]; + char texture_rot[32]; char pixel_size[32]; snprintf(texture_name, sizeof(texture_name), "texture%d", n); snprintf(texture_size, sizeof(texture_size), "texture_size%d", n); + snprintf(texture_rot, sizeof(texture_rot), "texture_rot%d", n); snprintf(pixel_size, sizeof(pixel_size), "pixel_size%d", n); if (s->use_integer) { @@ -926,6 +924,7 @@ static void pass_prepare_src_tex(struct gl_video *p) f[1] = s->tex_h; } 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, pixel_size, (GLfloat[]){1.0f / f[0], 1.0f / f[1]}); @@ -1045,12 +1044,29 @@ static void uninit_scaler(struct gl_video *p, struct scaler *scaler) scaler->initialized = false; } -static void hook_prelude(struct gl_video *p, const char *name, int id) +static void hook_prelude(struct gl_video *p, const char *name, int id, + struct img_tex tex) { - GLSLHF("#define %s texture%d\n", name, id); + GLSLHF("#define %s_raw texture%d\n", name, id); GLSLHF("#define %s_pos texcoord%d\n", name, id); GLSLHF("#define %s_size texture_size%d\n", name, id); + GLSLHF("#define %s_rot texture_rot%d\n", name, id); GLSLHF("#define %s_pt pixel_size%d\n", name, id); + + // Set up the sampling functions + GLSLHF("#define %s_tex(pos) (%f * vec4(texture(%s_raw, pos)).%s)\n", + name, tex.multiplier, name, tex.swizzle[0] ? tex.swizzle : "rgba"); + + // Since the extra matrix multiplication impacts performance, + // skip it unless the texture was actually rotated + if (gl_transform_eq(tex.transform, identity_trans)) { + GLSLHF("#define %s_texOff(off) %s_tex(%s_pos + %s_pt * vec2(off))\n", + name, name, name, name); + } else { + GLSLHF("#define %s_texOff(off) " + "%s_tex(%s_pos + %s_rot * vec2(off)/%s_size)\n", + name, name, name, name, name); + } } static bool saved_tex_find(struct gl_video *p, const char *name, @@ -1116,8 +1132,8 @@ static struct img_tex pass_hook(struct gl_video *p, const char *name, // This is a special name that means "currently hooked texture" if (strcmp(bind_name, "HOOKED") == 0) { int id = pass_bind(p, tex); - hook_prelude(p, "HOOKED", id); - hook_prelude(p, name, id); + hook_prelude(p, "HOOKED", id, tex); + hook_prelude(p, name, id, tex); continue; } @@ -1130,7 +1146,7 @@ static struct img_tex pass_hook(struct gl_video *p, const char *name, return tex; } - hook_prelude(p, bind_name, pass_bind(p, bind_tex)); + hook_prelude(p, bind_name, pass_bind(p, bind_tex), bind_tex); } // Run the actual hook. This generates a series of GLSL shader @@ -1502,33 +1518,6 @@ static void upload_nnedi3_weights(struct gl_video *p) } } -// Applies a single pass of the prescaler, and accumulates the offset in -// pass_transform. -static void pass_prescale_luma_step(struct gl_video *p, struct img_tex tex, - struct gl_transform *step_transform, - int step) -{ - int id = pass_bind(p, tex); - int planes = tex.components; - - switch(p->opts.prescale_luma) { - case 1: - assert(planes == 1); - pass_superxbr(p->sc, id, step, tex.multiplier, - p->opts.superxbr_opts, step_transform); - break; - case 2: - upload_nnedi3_weights(p); - pass_nnedi3(p->gl, p->sc, planes, id, step, tex.multiplier, - p->opts.nnedi3_opts, step_transform, tex.gl_target); - break; - default: - abort(); - } - - skip_unused(p, planes); -} - // Returns true if two img_texs are semantically equivalent (same metadata) static bool img_tex_equiv(struct img_tex a, struct img_tex b) { @@ -1569,33 +1558,22 @@ static void pass_add_hooks(struct gl_video *p, struct tex_hook hook, static void deband_hook(struct gl_video *p, struct img_tex tex, struct gl_transform *trans, void *priv) { - // We could use the hook binding mechanism here but the existing code - // already assumes we just know an ID so just do this for simplicity - int id = pass_bind(p, tex); - pass_sample_deband(p->sc, p->opts.deband_opts, id, tex.multiplier, - tex.gl_target, &p->lfg); - skip_unused(p, tex.components); + pass_sample_deband(p->sc, p->opts.deband_opts, &p->lfg); } -static void prescale_hook(struct gl_video *p, struct img_tex tex, +static void superxbr_hook(struct gl_video *p, struct img_tex tex, struct gl_transform *trans, void *priv) { - struct gl_transform step_trans = identity_trans; - pass_prescale_luma_step(p, tex, &step_trans, 0); - gl_transform_trans(step_trans, trans); - - // We render out an FBO *inside* this hook, which is normally quite - // unusual but here it allows us to work around the lack of real closures. - // Unfortunately it means we need to duplicate some work to compute the - // new FBO size - struct fbotex *fbo = priv; - int w = tex.w * (int)step_trans.m[0][0], - h = tex.h * (int)step_trans.m[1][1]; - finish_pass_fbo(p, fbo, w, h, 0); - tex = img_tex_fbo(fbo, tex.type, tex.components); + int step = (uintptr_t)priv; + pass_superxbr(p->sc, step, p->opts.superxbr_opts, trans); +} - pass_prescale_luma_step(p, tex, &step_trans, 1); - gl_transform_trans(step_trans, trans); +static void nnedi3_hook(struct gl_video *p, struct img_tex tex, + struct gl_transform *trans, void *priv) +{ + int step = (uintptr_t)priv; + upload_nnedi3_weights(p); + pass_nnedi3(p->gl, p->sc, step, p->opts.nnedi3_opts, trans); } static void unsharp_hook(struct gl_video *p, struct img_tex tex, @@ -1617,7 +1595,7 @@ static void user_hook_old(struct gl_video *p, struct img_tex tex, load_shader(p, bstr0(body)); const char *fn_name = get_custom_shader_fn(p, body); GLSLF("// custom shader\n"); - GLSLF("color = %s(HOOKED, HOOKED_pos, HOOKED_size);\n", fn_name); + GLSLF("color = %s(HOOKED_raw, HOOKED_pos, HOOKED_size);\n", fn_name); } // Returns 1.0 on failure to at least create a legal FBO @@ -1784,17 +1762,36 @@ static void pass_hook_user_shaders(struct gl_video *p, char **shaders) static void gl_video_setup_hooks(struct gl_video *p) { if (p->opts.deband) { - pass_add_hooks(p, (struct tex_hook) {.hook = deband_hook}, + pass_add_hooks(p, (struct tex_hook) {.hook = deband_hook, + .bind_tex = {"HOOKED"}}, HOOKS("LUMA", "CHROMA", "RGB", "XYZ")); } int prescale_passes = get_prescale_passes(p); - for (int i = 0; i < prescale_passes; i++) { - pass_add_hook(p, (struct tex_hook) { - .hook_tex = "LUMA", - .hook = prescale_hook, - .priv = &p->prescale_fbo[i], - }); + if (p->opts.prescale_luma == 1) { // superxbr + for (int i = 0; i < prescale_passes; i++) { + for (int step = 0; step < 2; step++) { + pass_add_hook(p, (struct tex_hook) { + .hook_tex = "LUMA", + .bind_tex = {"HOOKED"}, + .hook = superxbr_hook, + .priv = (void *)(uintptr_t)step, + }); + } + } + } + + if (p->opts.prescale_luma == 2) { // nnedi3 + for (int i = 0; i < prescale_passes; i++) { + for (int step = 0; step < 2; step++) { + pass_add_hook(p, (struct tex_hook) { + .hook_tex = "LUMA", + .bind_tex = {"HOOKED"}, + .hook = nnedi3_hook, + .priv = (void *)(uintptr_t)step, + }); + } + } } if (p->opts.unsharp != 0.0) { |