gl-renderer: Add generic shader tinting support

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 <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2024-05-07 11:58:34 +02:00 committed by Derek Foreman
parent 6634849dd5
commit fb03b825f2
4 changed files with 38 additions and 11 deletions

View File

@ -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();

View File

@ -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;

View File

@ -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. */

View File

@ -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);