From 8494fdadaeb25b3c1a42c71559be5bd74d1d4638 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 29 Jul 2017 20:14:48 +0200 Subject: [PATCH] vo_opengl: manage dither texture via ra Also add some more helpers. Fix the broken math.h include statement. utils.c uses ra_gl.h internals, which it shouldn't, and which will be removed again as soon as this code gets converted to ra fully. --- video/out/opengl/ra.c | 12 +++++++++ video/out/opengl/ra.h | 6 +++++ video/out/opengl/ra_gl.c | 11 ++++++--- video/out/opengl/utils.c | 12 +++++++++ video/out/opengl/utils.h | 6 ++++- video/out/opengl/video.c | 53 +++++++++++++++++----------------------- 6 files changed, 66 insertions(+), 34 deletions(-) diff --git a/video/out/opengl/ra.c b/video/out/opengl/ra.c index df27f723c2..57734afd81 100644 --- a/video/out/opengl/ra.c +++ b/video/out/opengl/ra.c @@ -4,6 +4,18 @@ #include "ra.h" +struct ra_tex *ra_tex_create(struct ra *ra, const struct ra_tex_params *params) +{ + return ra->fns->tex_create(ra, params); +} + +void ra_tex_free(struct ra *ra, struct ra_tex **tex) +{ + if (*tex) + ra->fns->tex_destroy(ra, *tex); + *tex = NULL; +} + // Return whether this is a tightly packed format with no external padding and // with the same bit size/depth in all components. static bool ra_format_is_regular(const struct ra_format *fmt) diff --git a/video/out/opengl/ra.h b/video/out/opengl/ra.h index 211f87077b..11b458b616 100644 --- a/video/out/opengl/ra.h +++ b/video/out/opengl/ra.h @@ -71,6 +71,9 @@ struct ra_tex_params { // if true, repeat texture coordinates bool non_normalized; // hack for GL_TEXTURE_RECTANGLE OSX idiocy // always set to false, except in OSX code + // If non-NULL, the texture will be created with these contents, and is + // considered immutable afterwards (no upload, mapping, or rendering to it). + void *initial_data; }; struct ra_tex { @@ -137,6 +140,9 @@ struct ra_fns { bool (*poll_mapped_buffer)(struct ra *ra, struct ra_mapped_buffer *buf); }; +struct ra_tex *ra_tex_create(struct ra *ra, const struct ra_tex_params *params); +void ra_tex_free(struct ra *ra, struct ra_tex **tex); + 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 01f1fcd6e5..faf8812df7 100644 --- a/video/out/opengl/ra_gl.c +++ b/video/out/opengl/ra_gl.c @@ -144,24 +144,29 @@ static struct ra_tex *gl_tex_create(struct ra *ra, if (params->dimensions > 2) gl->TexParameteri(tex_gl->target, GL_TEXTURE_WRAP_R, wrap); + gl->PixelStorei(GL_UNPACK_ALIGNMENT, 1); switch (params->dimensions) { case 1: gl->TexImage1D(tex_gl->target, 0, tex_gl->internal_format, params->w, - 0, tex_gl->format, tex_gl->type, NULL); + 0, tex_gl->format, tex_gl->type, params->initial_data); break; case 2: gl->TexImage2D(tex_gl->target, 0, tex_gl->internal_format, params->w, - params->h, 0, tex_gl->format, tex_gl->type, NULL); + params->h, 0, tex_gl->format, tex_gl->type, + params->initial_data); break; case 3: gl->TexImage3D(tex_gl->target, 0, tex_gl->internal_format, params->w, params->h, params->d, 0, tex_gl->format, tex_gl->type, - NULL); + params->initial_data); break; } + gl->PixelStorei(GL_UNPACK_ALIGNMENT, 4); gl->BindTexture(tex_gl->target, 0); + tex->params.initial_data = NULL; + return tex; } diff --git a/video/out/opengl/utils.c b/video/out/opengl/utils.c index 8c52b61cba..024b8d4bbe 100644 --- a/video/out/opengl/utils.c +++ b/video/out/opengl/utils.c @@ -33,6 +33,7 @@ #include "options/path.h" #include "stream/stream.h" #include "formats.h" +#include "ra_gl.h" #include "utils.h" // GLU has this as gluErrorString (we don't use GLU, as it is legacy-OpenGL) @@ -746,6 +747,17 @@ void gl_sc_uniform_tex_ui(struct gl_shader_cache *sc, char *name, GLuint texture u->tex_handle = texture; } +void gl_sc_uniform_texture(struct gl_shader_cache *sc, char *name, + struct ra_tex *tex) +{ + struct ra_tex_gl *tex_gl = tex->priv; + if (tex->params.format->ctype == RA_CTYPE_UINT) { + gl_sc_uniform_tex_ui(sc, name, tex_gl->texture); + } else { + gl_sc_uniform_tex(sc, name, tex_gl->target, tex_gl->texture); + } +} + static const char *mp_image2D_type(GLenum access) { switch (access) { diff --git a/video/out/opengl/utils.h b/video/out/opengl/utils.h index 7e5f8f5931..2a15d85b71 100644 --- a/video/out/opengl/utils.h +++ b/video/out/opengl/utils.h @@ -19,8 +19,10 @@ #ifndef MP_GL_UTILS_ #define MP_GL_UTILS_ +#include + #include "common.h" -#include "math.h" +#include "ra.h" struct mp_log; @@ -145,6 +147,8 @@ void gl_sc_paddf(struct gl_shader_cache *sc, const char *textf, ...) PRINTF_ATTRIBUTE(2, 3); void gl_sc_uniform_tex(struct gl_shader_cache *sc, char *name, GLenum target, GLuint texture); +void gl_sc_uniform_texture(struct gl_shader_cache *sc, char *name, + struct ra_tex *tex); void gl_sc_uniform_tex_ui(struct gl_shader_cache *sc, char *name, GLuint texture); void gl_sc_uniform_image2D(struct gl_shader_cache *sc, char *name, GLuint texture, GLuint iformat, GLenum access); diff --git a/video/out/opengl/video.c b/video/out/opengl/video.c index 2cf0d11783..2cbf99bad8 100644 --- a/video/out/opengl/video.c +++ b/video/out/opengl/video.c @@ -205,8 +205,7 @@ struct gl_video { bool use_lut_3d; int lut_3d_size[3]; - GLuint dither_texture; - int dither_size; + struct ra_tex *dither_texture; struct mp_image_params real_image_params; // configured format struct mp_image_params image_params; // texture format (mind hwdec case) @@ -531,13 +530,10 @@ static void reinit_osd(struct gl_video *p) static void uninit_rendering(struct gl_video *p) { - GL *gl = p->gl; - for (int n = 0; n < SCALER_COUNT; n++) uninit_scaler(p, &p->scaler[n]); - gl->DeleteTextures(1, &p->dither_texture); - p->dither_texture = 0; + ra_tex_free(p->ra, &p->dither_texture); for (int n = 0; n < 4; n++) { fbotex_uninit(&p->merge_fbo[n]); @@ -2582,8 +2578,6 @@ static void pass_colormanage(struct gl_video *p, struct mp_colorspace src, bool static void pass_dither(struct gl_video *p) { - GL *gl = p->gl; - // Assume 8 bits per component if unknown. int dst_depth = p->fb_depth; if (p->opts.dither_depth > 0) @@ -2597,7 +2591,7 @@ static void pass_dither(struct gl_video *p) int tex_size = 0; void *tex_data = NULL; - const struct gl_format *fmt = NULL; + const struct ra_format *fmt = NULL; void *temp = NULL; if (p->opts.dither_algo == DITHER_FRUIT) { @@ -2612,13 +2606,13 @@ static void pass_dither(struct gl_video *p) } // Prefer R16 texture since they provide higher precision. - fmt = gl_find_unorm_format(gl, 2, 1); + fmt = ra_find_unorm_format(p->ra, 2, 1); if (!fmt) - fmt = gl_find_float16_format(gl, 1); + fmt = ra_find_float16_format(p->ra, 1); if (fmt) { tex_size = size; tex_data = p->last_dither_matrix; - if (fmt->type == GL_UNSIGNED_SHORT) { + if (fmt->ctype == RA_CTYPE_UNORM) { uint16_t *t = temp = talloc_array(NULL, uint16_t, size * size); for (int n = 0; n < size * size; n++) t[n] = p->last_dither_matrix[n] * UINT16_MAX; @@ -2634,24 +2628,23 @@ static void pass_dither(struct gl_video *p) temp = talloc_array(NULL, char, 8 * 8); mp_make_ordered_dither_matrix(temp, 8); - fmt = gl_find_unorm_format(gl, 1, 1); + fmt = ra_find_unorm_format(p->ra, 1, 1); tex_size = 8; tex_data = temp; } - p->dither_size = tex_size; - - gl->GenTextures(1, &p->dither_texture); - gl->BindTexture(GL_TEXTURE_2D, p->dither_texture); - gl->PixelStorei(GL_UNPACK_ALIGNMENT, 1); - gl->TexImage2D(GL_TEXTURE_2D, 0, fmt->internal_format, tex_size, tex_size, - 0, fmt->format, fmt->type, tex_data); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - gl->PixelStorei(GL_UNPACK_ALIGNMENT, 4); - gl->BindTexture(GL_TEXTURE_2D, 0); + struct ra_tex_params params = { + .dimensions = 2, + .w = tex_size, + .h = tex_size, + .d = 1, + .format = fmt, + .render_src = true, + .src_linear = true, + .src_repeat = true, + .initial_data = tex_data, + }; + p->dither_texture = ra_tex_create(p->ra, ¶ms); debug_check_gl(p, "dither setup"); @@ -2665,10 +2658,11 @@ static void pass_dither(struct gl_video *p) // dither matrix. The precision of the source implicitly decides how many // dither patterns can be visible. int dither_quantization = (1 << dst_depth) - 1; + int dither_size = p->dither_texture->params.w; - gl_sc_uniform_tex(p->sc, "dither", GL_TEXTURE_2D, p->dither_texture); + gl_sc_uniform_texture(p->sc, "dither", p->dither_texture); - GLSLF("vec2 dither_pos = gl_FragCoord.xy * 1.0/%d.0;\n", p->dither_size); + GLSLF("vec2 dither_pos = gl_FragCoord.xy * 1.0/%d.0;\n", dither_size); if (p->opts.temporal_dither) { int phase = (p->frames_rendered / p->opts.temporal_dither_period) % 8u; @@ -2684,8 +2678,7 @@ static void pass_dither(struct gl_video *p) GLSL(float dither_value = texture(dither, dither_pos).r;) GLSLF("color = floor(color * %d.0 + dither_value + 0.5 / %d.0) * 1.0/%d.0;\n", - dither_quantization, p->dither_size * p->dither_size, - dither_quantization); + dither_quantization, dither_size * dither_size, dither_quantization); } // Draws the OSD, in scene-referred colors.. If cms is true, subtitles are