From fb03b825f28972713ddc444896ecdd14bfc3b240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20Molinari?= Date: Tue, 7 May 2024 11:58:34 +0200 Subject: [PATCH] gl-renderer: Add generic shader tinting support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current green tint support is a hard-coded Porter-Duff premultiplied blending of a green source (slightly skewed on the green channel) over the updated damaged destination. This commit makes green tinting generic by letting the shader user provide a custom tint color. The goal is to reuse that system for the upcoming debug modes. Signed-off-by: Loïc Molinari --- libweston/renderer-gl/fragment.glsl | 7 ++++--- libweston/renderer-gl/gl-renderer-internal.h | 3 ++- libweston/renderer-gl/gl-renderer.c | 21 +++++++++++++++++--- libweston/renderer-gl/gl-shaders.c | 18 +++++++++++++---- 4 files changed, 38 insertions(+), 11 deletions(-) diff --git a/libweston/renderer-gl/fragment.glsl b/libweston/renderer-gl/fragment.glsl index 1eed4b321..492a01085 100644 --- a/libweston/renderer-gl/fragment.glsl +++ b/libweston/renderer-gl/fragment.glsl @@ -87,7 +87,7 @@ compile_const int c_color_post_curve = DEF_COLOR_POST_CURVE; compile_const int c_color_channel_order = DEF_COLOR_CHANNEL_ORDER; compile_const bool c_input_is_premult = DEF_INPUT_IS_PREMULT; -compile_const bool c_green_tint = DEF_GREEN_TINT; +compile_const bool c_tint = DEF_TINT; compile_const bool c_wireframe = DEF_WIREFRAME; compile_const bool c_need_color_pipeline = c_color_pre_curve != SHADER_COLOR_CURVE_IDENTITY || @@ -138,6 +138,7 @@ uniform sampler2D tex2; uniform sampler2D tex_wireframe; uniform float view_alpha; uniform vec4 unicolor; +uniform vec4 tint; #define MAX_CURVE_PARAMS 10 #define MAX_CURVESET_PARAMS (MAX_CURVE_PARAMS * 3) @@ -459,8 +460,8 @@ main() color *= view_alpha; - if (c_green_tint) - color = vec4(0.0, 0.3, 0.0, 0.2) + color * 0.8; + if (c_tint) + color = color * vec4(1.0 - tint.a) + tint; if (c_wireframe) { vec4 src = wireframe(); diff --git a/libweston/renderer-gl/gl-renderer-internal.h b/libweston/renderer-gl/gl-renderer-internal.h index 421d596a9..81fb13540 100644 --- a/libweston/renderer-gl/gl-renderer-internal.h +++ b/libweston/renderer-gl/gl-renderer-internal.h @@ -94,7 +94,7 @@ struct gl_shader_requirements unsigned variant:4; /* enum gl_shader_texture_variant */ bool input_is_premult:1; - bool green_tint:1; + bool tint:1; bool wireframe:1; unsigned color_pre_curve:2; /* enum gl_shader_color_curve */ @@ -125,6 +125,7 @@ struct gl_shader_config { struct weston_matrix surface_to_buffer; float view_alpha; GLfloat unicolor[4]; + GLfloat tint[4]; GLint input_tex_filter; /* GL_NEAREST or GL_LINEAR */ GLuint input_tex[GL_SHADER_INPUT_TEX_MAX]; GLuint wireframe_tex; diff --git a/libweston/renderer-gl/gl-renderer.c b/libweston/renderer-gl/gl-renderer.c index 539de9aff..10ada10c1 100644 --- a/libweston/renderer-gl/gl-renderer.c +++ b/libweston/renderer-gl/gl-renderer.c @@ -254,6 +254,12 @@ dump_format(uint32_t format, char out[4]) return out; } +static inline void +copy_uniform4f(float dst[4], const float src[4]) +{ + memcpy(dst, src, 4 * sizeof(float)); +} + static inline struct gl_output_state * get_output_state(struct weston_output *output) { @@ -1145,8 +1151,7 @@ gl_shader_config_set_input_textures(struct gl_shader_config *sconf, sconf->req.input_is_premult = gl_shader_texture_variant_can_be_premult(gb->shader_variant); - for (i = 0; i < 4; i++) - sconf->unicolor[i] = gb->color[i]; + copy_uniform4f(sconf->unicolor, gb->color); assert(gb->num_textures <= GL_SHADER_INPUT_TEX_MAX); for (i = 0; i < gb->num_textures; i++) @@ -1400,7 +1405,17 @@ draw_mesh(struct gl_renderer *gr, sconf->req.wireframe = wireframe; sconf->wireframe_tex = gr->wireframe_tex; } - sconf->req.green_tint = gr->debug_mode == DEBUG_MODE_SHADERS; + + if (gr->debug_mode == DEBUG_MODE_SHADERS) { + /* While tints are meant to be premultiplied, the shaders tint + * has its green component greater than alpha for saturation + * purpose. */ + static const float debug_mode_shaders[] = + { 0.0f, 0.3f, 0.0f, 0.2f }; + + copy_uniform4f(sconf->tint, debug_mode_shaders); + sconf->req.tint = true; + } if (!gl_renderer_use_program(gr, sconf)) gl_renderer_send_shader_error(pnode); /* Use fallback shader. */ diff --git a/libweston/renderer-gl/gl-shaders.c b/libweston/renderer-gl/gl-shaders.c index b5b2fe454..9538db04d 100644 --- a/libweston/renderer-gl/gl-shaders.c +++ b/libweston/renderer-gl/gl-shaders.c @@ -64,6 +64,7 @@ struct gl_shader { GLint tex_uniform_wireframe; GLint view_alpha_uniform; GLint color_uniform; + GLint tint_uniform; union { struct { GLint tex_2d_uniform; @@ -235,7 +236,7 @@ create_shader_description_string(const struct gl_shader_requirements *req) int size; char *str; - size = asprintf(&str, "%s %s %s %s %s %s %cinput_is_premult %cgreen", + size = asprintf(&str, "%s %s %s %s %s %s %cinput_is_premult %ctint", gl_shader_texcoord_input_to_string(req->texcoord_input), gl_shader_texture_variant_to_string(req->variant), gl_shader_color_curve_to_string(req->color_pre_curve), @@ -243,7 +244,7 @@ create_shader_description_string(const struct gl_shader_requirements *req) gl_shader_color_curve_to_string(req->color_post_curve), gl_shader_color_order_to_string(req->color_channel_order), req->input_is_premult ? '+' : '-', - req->green_tint ? '+' : '-'); + req->tint ? '+' : '-'); if (size < 0) return NULL; return str; @@ -277,7 +278,7 @@ create_fragment_shader_config_string(const struct gl_shader_requirements *req) req->color_channel_order == SHADER_CHANNEL_ORDER_RGBA); size = asprintf(&str, - "#define DEF_GREEN_TINT %s\n" + "#define DEF_TINT %s\n" "#define DEF_INPUT_IS_PREMULT %s\n" "#define DEF_WIREFRAME %s\n" "#define DEF_COLOR_PRE_CURVE %s\n" @@ -285,7 +286,7 @@ create_fragment_shader_config_string(const struct gl_shader_requirements *req) "#define DEF_COLOR_POST_CURVE %s\n" "#define DEF_COLOR_CHANNEL_ORDER %s\n" "#define DEF_VARIANT %s\n", - req->green_tint ? "true" : "false", + req->tint ? "true" : "false", req->input_is_premult ? "true" : "false", req->wireframe ? "true" : "false", gl_shader_color_curve_to_string(req->color_pre_curve), @@ -396,6 +397,13 @@ gl_shader_create(struct gl_renderer *gr, } else { shader->color_uniform = -1; } + if (requirements->tint) { + shader->tint_uniform = glGetUniformLocation(shader->program, + "tint"); + assert(shader->tint_uniform != -1); + } else { + shader->tint_uniform = -1; + } switch(requirements->color_pre_curve) { case SHADER_COLOR_CURVE_IDENTITY: @@ -670,6 +678,8 @@ gl_shader_load_config(struct gl_shader *shader, if (shader->color_uniform != -1) glUniform4fv(shader->color_uniform, 1, sconf->unicolor); + if (shader->tint_uniform != -1) + glUniform4fv(shader->tint_uniform, 1, sconf->tint); glUniform1f(shader->view_alpha_uniform, sconf->view_alpha);