mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2026-05-02 10:48:04 +02:00
gl-renderer: do not skip output color effect for solid color buffers
When repainting a paint node, if the buffer is a solid color buffer we may skip the rendering pipeline and directly call glClear() with the solid color, for optimization purposes. Currently there's a bug where if the output has an output color effect set, it is skipped when we have a solid color buffer (as we don't go through the rendering pipeline, where the effects are implemented). When we have color-management and the paint node contains a color xform, we've opted for skipping this optimization and going through the rendering pipeline for now. However, output color effects are simple, so let's add the logic to apply them on CPU when we have a solid color buffer. Reported-by: Christopher Healy <healych@amazon.com> Signed-off-by: Leandro Ribeiro <leandro.ribeiro@collabora.com>
This commit is contained in:
parent
99f3a92f4a
commit
d3fee82090
2 changed files with 67 additions and 2 deletions
|
|
@ -127,6 +127,24 @@ weston_v3f_clamp(struct weston_vec3f v, float a, float b)
|
|||
v.z >= a ? (v.z <= b ? v.z : b) : a);
|
||||
}
|
||||
|
||||
/** Element-wise vector subtraction a - b */
|
||||
static inline struct weston_vec3f
|
||||
weston_v3f_sub_v3f(struct weston_vec3f a, struct weston_vec3f b)
|
||||
{
|
||||
return WESTON_VEC3F(a.x - b.x,
|
||||
a.y - b.y,
|
||||
a.z - b.z);
|
||||
}
|
||||
|
||||
/** Element-wise vector sum a + b */
|
||||
static inline struct weston_vec3f
|
||||
weston_v3f_add_v3f(struct weston_vec3f a, struct weston_vec3f b)
|
||||
{
|
||||
return WESTON_VEC3F(a.x + b.x,
|
||||
a.y + b.y,
|
||||
a.z + b.z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Matrix infinity-norm
|
||||
*
|
||||
|
|
|
|||
|
|
@ -2195,6 +2195,47 @@ repaint_region(struct gl_renderer *gr,
|
|||
gr->barycentric_stream.size = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
apply_color_effect(struct weston_output *output, float *r, float *g, float *b, const float a)
|
||||
{
|
||||
struct weston_compositor *compositor = output->compositor;
|
||||
struct weston_output_color_effect *effect = output->color_effect;
|
||||
struct weston_vec3f input = WESTON_VEC3F(*r, *g, *b);
|
||||
struct weston_vec3f res, err;
|
||||
|
||||
/*
|
||||
* Caller guarantees alpha is always 0.0f (fully transparent) or 1.0f
|
||||
* (fully opaque). If alpha is 0.0f, no color effect needed. Otherwise
|
||||
* assert that alpha is 1.0f, and in such case we don't have to worry
|
||||
* if values are alpha premultiplied or not.
|
||||
*/
|
||||
if (!output->color_effect || a == 0.0f) {
|
||||
return;
|
||||
}
|
||||
weston_assert_f32_eq(compositor, a, 1.0f);
|
||||
|
||||
switch (effect->type) {
|
||||
case WESTON_OUTPUT_COLOR_EFFECT_TYPE_INVERSION:
|
||||
*r = 1.0f - *r;
|
||||
*g = 1.0f - *g;
|
||||
*b = 1.0f - *b;
|
||||
return;
|
||||
case WESTON_OUTPUT_COLOR_EFFECT_TYPE_CVD_CORRECTION:
|
||||
/**
|
||||
* See weston_output_color_effect_cvd_correction() for more details.
|
||||
*/
|
||||
res = weston_m3f_mul_v3f(effect->u.cvd.simulation, input);
|
||||
err = weston_v3f_sub_v3f(input, res);
|
||||
res = weston_v3f_add_v3f(input, weston_m3f_mul_v3f(effect->u.cvd.redistribution, err));
|
||||
res = weston_v3f_clamp(res, 0.0f, 1.0f);
|
||||
*r = res.el[0];
|
||||
*g = res.el[1];
|
||||
*b = res.el[2];
|
||||
return;
|
||||
};
|
||||
weston_assert_not_reached(compositor, "unknown color effect type");
|
||||
}
|
||||
|
||||
static void
|
||||
clear_region(struct gl_renderer *gr, struct weston_paint_node *pnode,
|
||||
pixman_region32_t *repaint)
|
||||
|
|
@ -2203,6 +2244,7 @@ clear_region(struct gl_renderer *gr, struct weston_paint_node *pnode,
|
|||
struct gl_output_state *go = get_output_state(pnode->output);
|
||||
EGLint *rects;
|
||||
EGLint nrects;
|
||||
float r, g, b, a;
|
||||
int i;
|
||||
|
||||
pixman_region_to_egl(output, repaint, go->border_status,
|
||||
|
|
@ -2213,8 +2255,13 @@ clear_region(struct gl_renderer *gr, struct weston_paint_node *pnode,
|
|||
* underlay - or fully opaque, to use clear rather than blending. */
|
||||
assert(pnode->solid.a == 0.0f || pnode->solid.a == 1.0f);
|
||||
set_blend_state(gr, false);
|
||||
glClearColor(pnode->solid.r, pnode->solid.g, pnode->solid.b,
|
||||
pnode->solid.a);
|
||||
|
||||
r = pnode->solid.r;
|
||||
g = pnode->solid.g;
|
||||
b = pnode->solid.b;
|
||||
a = pnode->solid.a;
|
||||
apply_color_effect(output, &r, &g, &b, a);
|
||||
glClearColor(r, g, b, a);
|
||||
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
for (i = 0; i < nrects; i++) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue