gl-renderer: add shader bit input_is_premult

Add a new shader requirements bit input_is_premult which says whether
the texture sampling results in premultiplied alpha or not. Currently
this can be deduced fully from the shader texture variant, but in the
future there might a protocol extension to explicitly control it. Hence
the need for a new bit.

yuva2rgba() is changed to produce straight alpha always. This makes
sample_input_texture() sometimes produce straight or premultiplied
alpha. The input_is_premult bit needs to match sample_input_texture()
behavior. Doing this should save three multiplications in the shader for
straight alpha formats.

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.com>
dev
Pekka Paalanen 4 years ago committed by Pekka Paalanen
parent 1600431e80
commit 4d5b2f3410
  1. 13
      libweston/renderer-gl/fragment.glsl
  2. 6
      libweston/renderer-gl/gl-renderer-internal.h
  3. 6
      libweston/renderer-gl/gl-renderer.c
  4. 25
      libweston/renderer-gl/gl-shaders.c

@ -53,6 +53,7 @@ precision mediump float;
* snippet. * snippet.
*/ */
compile_const int c_variant = DEF_VARIANT; compile_const int c_variant = DEF_VARIANT;
compile_const bool c_input_is_premult = DEF_INPUT_IS_PREMULT;
compile_const bool c_green_tint = DEF_GREEN_TINT; compile_const bool c_green_tint = DEF_GREEN_TINT;
vec4 vec4
@ -79,7 +80,6 @@ yuva2rgba(vec4 yuva)
color_out.g = Y - 0.39176229 * su - 0.81296764 * sv; color_out.g = Y - 0.39176229 * su - 0.81296764 * sv;
color_out.b = Y + 2.01723214 * su; color_out.b = Y + 2.01723214 * su;
color_out.rgb *= yuva.w;
color_out.a = yuva.w; color_out.a = yuva.w;
return color_out; return color_out;
@ -146,11 +146,18 @@ main()
{ {
vec4 color; vec4 color;
/* Electrical (non-linear) RGBA values, pre-multiplied */ /* Electrical (non-linear) RGBA values, may be premult or not */
color = sample_input_texture(); color = sample_input_texture();
/* View alpha (opacity) */ /* Ensure premultiplied alpha, apply view alpha (opacity) */
if (c_input_is_premult) {
color *= alpha; color *= alpha;
} else {
color.a *= alpha;
color.rgb *= color.a;
}
/* color is guaranteed premult here */
if (c_green_tint) if (c_green_tint)
color = vec4(0.0, 0.3, 0.0, 0.2) + color * 0.8; color = vec4(0.0, 0.3, 0.0, 0.2) + color * 0.8;

@ -62,13 +62,14 @@ enum gl_shader_texture_variant {
struct gl_shader_requirements struct gl_shader_requirements
{ {
unsigned variant:4; /* enum gl_shader_texture_variant */ unsigned variant:4; /* enum gl_shader_texture_variant */
bool input_is_premult:1;
bool green_tint:1; bool green_tint:1;
/* /*
* The total size of all bitfields plus pad_bits_ must fill up exactly * The total size of all bitfields plus pad_bits_ must fill up exactly
* how many bytes the compiler allocates for them together. * how many bytes the compiler allocates for them together.
*/ */
unsigned pad_bits_:27; unsigned pad_bits_:26;
}; };
static_assert(sizeof(struct gl_shader_requirements) == static_assert(sizeof(struct gl_shader_requirements) ==
4 /* total bitfield size in bytes */, 4 /* total bitfield size in bytes */,
@ -202,6 +203,9 @@ gl_renderer_setup_egl_extensions(struct weston_compositor *ec);
GLenum GLenum
gl_shader_texture_variant_get_target(enum gl_shader_texture_variant v); gl_shader_texture_variant_get_target(enum gl_shader_texture_variant v);
bool
gl_shader_texture_variant_can_be_premult(enum gl_shader_texture_variant v);
void void
gl_shader_destroy(struct gl_renderer *gr, struct gl_shader *shader); gl_shader_destroy(struct gl_renderer *gr, struct gl_shader *shader);

@ -738,6 +738,7 @@ triangle_fan_debug(struct gl_renderer *gr,
alt = (struct gl_shader_config) { alt = (struct gl_shader_config) {
.req = { .req = {
.variant = SHADER_VARIANT_SOLID, .variant = SHADER_VARIANT_SOLID,
.input_is_premult = true,
}, },
.projection = sconf->projection, .projection = sconf->projection,
.view_alpha = 1.0f, .view_alpha = 1.0f,
@ -925,6 +926,7 @@ maybe_censor_override(struct gl_shader_config *sconf,
const struct gl_shader_config alt = { const struct gl_shader_config alt = {
.req = { .req = {
.variant = SHADER_VARIANT_SOLID, .variant = SHADER_VARIANT_SOLID,
.input_is_premult = true,
}, },
.projection = sconf->projection, .projection = sconf->projection,
.view_alpha = sconf->view_alpha, .view_alpha = sconf->view_alpha,
@ -960,6 +962,8 @@ gl_shader_config_set_input_textures(struct gl_shader_config *sconf,
int i; int i;
sconf->req.variant = gs->shader_variant; sconf->req.variant = gs->shader_variant;
sconf->req.input_is_premult =
gl_shader_texture_variant_can_be_premult(gs->shader_variant);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
sconf->unicolor[i] = gs->color[i]; sconf->unicolor[i] = gs->color[i];
@ -1264,6 +1268,7 @@ draw_output_borders(struct weston_output *output,
struct gl_shader_config sconf = { struct gl_shader_config sconf = {
.req = { .req = {
.variant = SHADER_VARIANT_RGBA, .variant = SHADER_VARIANT_RGBA,
.input_is_premult = true,
}, },
.view_alpha = 1.0f, .view_alpha = 1.0f,
}; };
@ -1488,6 +1493,7 @@ blit_shadow_to_output(struct weston_output *output,
const struct gl_shader_config sconf = { const struct gl_shader_config sconf = {
.req = { .req = {
.variant = SHADER_VARIANT_RGBA, .variant = SHADER_VARIANT_RGBA,
.input_is_premult = true,
}, },
.projection = { .projection = {
.d = { /* transpose */ .d = { /* transpose */

@ -147,8 +147,9 @@ create_shader_description_string(const struct gl_shader_requirements *req)
int size; int size;
char *str; char *str;
size = asprintf(&str, "%s %cgreen", size = asprintf(&str, "%s %cinput_is_premult %cgreen",
gl_shader_texture_variant_to_string(req->variant), gl_shader_texture_variant_to_string(req->variant),
req->input_is_premult ? '+' : '-',
req->green_tint ? '+' : '-'); req->green_tint ? '+' : '-');
if (size < 0) if (size < 0)
return NULL; return NULL;
@ -163,8 +164,10 @@ create_shader_config_string(const struct gl_shader_requirements *req)
size = asprintf(&str, size = asprintf(&str,
"#define DEF_GREEN_TINT %s\n" "#define DEF_GREEN_TINT %s\n"
"#define DEF_INPUT_IS_PREMULT %s\n"
"#define DEF_VARIANT %s\n", "#define DEF_VARIANT %s\n",
req->green_tint ? "true" : "false", req->green_tint ? "true" : "false",
req->input_is_premult ? "true" : "false",
gl_shader_texture_variant_to_string(req->variant)); gl_shader_texture_variant_to_string(req->variant));
if (size < 0) if (size < 0)
return NULL; return NULL;
@ -349,6 +352,7 @@ gl_renderer_create_fallback_shader(struct gl_renderer *gr)
{ {
static const struct gl_shader_requirements fallback_requirements = { static const struct gl_shader_requirements fallback_requirements = {
.variant = SHADER_VARIANT_SOLID, .variant = SHADER_VARIANT_SOLID,
.input_is_premult = true,
}; };
struct gl_shader *shader; struct gl_shader *shader;
@ -415,6 +419,25 @@ gl_renderer_garbage_collect_programs(struct gl_renderer *gr)
} }
} }
bool
gl_shader_texture_variant_can_be_premult(enum gl_shader_texture_variant v)
{
switch (v) {
case SHADER_VARIANT_SOLID:
case SHADER_VARIANT_RGBA:
case SHADER_VARIANT_EXTERNAL:
return true;
case SHADER_VARIANT_NONE:
case SHADER_VARIANT_RGBX:
case SHADER_VARIANT_Y_U_V:
case SHADER_VARIANT_Y_UV:
case SHADER_VARIANT_Y_XUXV:
case SHADER_VARIANT_XYUV:
return false;
}
return true;
}
GLenum GLenum
gl_shader_texture_variant_get_target(enum gl_shader_texture_variant v) gl_shader_texture_variant_get_target(enum gl_shader_texture_variant v)
{ {

Loading…
Cancel
Save