[vlc-devel] [PATCH 2/2] vout_opengl: opengl: add support for dithering

Niklas Haas vlc at haasn.xyz
Thu Dec 28 04:48:56 CET 2017

This uses libplacebo's high quality blue noise algorithm. The lut_size
is chosen as 4 because the method of embedding (literal LUT) is not that
great. Larger texture sizes would require OpenGL/RA support, which is
not currently in the scope of VLC+libplacebo. (Alternatively, we could
try and use a uniform float array instead of a constant array - but it
doesn't seem to matter much)

This commit includes a `FIXME` note, since ideally it would be best to
dither to the true output depth. However, always dithering to 8 bits is
more than adequate, since framebuffers with fewer than 8 bits don't
exist. The main downside is that it could be an unnecessary (minor)
performance hit in cases where the source is already 8-bit (and no color
conversion is being performed), or when the user has a 10-bit
framebuffer (unlikely).

This would probably also benefit from being exposed as a user setting,
so users could choose between ordered dither, blue noise and white
noise. In theory, we could also try making VLC forwards-compatible with
GLSL 130+ and then enabling the fixed-function ordered dither where
 modules/video_output/opengl/fragment_shaders.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/modules/video_output/opengl/fragment_shaders.c b/modules/video_output/opengl/fragment_shaders.c
index cbd0a52858..251faccc9c 100644
--- a/modules/video_output/opengl/fragment_shaders.c
+++ b/modules/video_output/opengl/fragment_shaders.c
@@ -609,7 +609,15 @@ opengl_fragment_shader_init_impl(opengl_tex_converter_t *tc, GLenum tex_target,
                 pl_color_space_unknown, NULL, false);
+        struct pl_shader_obj *dither_state = NULL;
+        const int out_bits = 8; // FIXME: query actual framebuffer depth?
+        pl_shader_dither(sh, out_bits, &dither_state, &(struct pl_dither_params) {
+            .method   = PL_DITHER_BLUE_NOISE,
+            .lut_size = 4, // avoid too large values, since this gets embedded
+        });
         const struct pl_shader_res *res = tc->pl_sh_res = pl_shader_finalize(sh);
+        pl_shader_obj_destroy(&dither_state);
         tc->uloc.pl_vars = calloc(res->num_variables, sizeof(GLint));

More information about the vlc-devel mailing list