compositor: Add opaque rect shader feature
This lets us mark a rectangle in a texture and force the alpha to one inside. This is useful for textures coming from X windows, where the X window part is xRGB, that is 32 bit RGB with an undefined alpha channel and the decorations are rendered with a well-defined alpha channel.
This commit is contained in:
parent
fb6c6d90f3
commit
0b0c2bb3e9
@ -228,6 +228,10 @@ weston_surface_create(struct weston_compositor *compositor)
|
||||
surface->alpha = 255;
|
||||
surface->brightness = 255;
|
||||
surface->saturation = 255;
|
||||
surface->opaque_rect[0] = 0.0;
|
||||
surface->opaque_rect[1] = 0.0;
|
||||
surface->opaque_rect[2] = 0.0;
|
||||
surface->opaque_rect[3] = 0.0;
|
||||
surface->pitch = 1;
|
||||
|
||||
surface->buffer = NULL;
|
||||
@ -861,6 +865,7 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output,
|
||||
glUniform1f(es->shader->saturation_uniform, es->saturation / 255.0);
|
||||
glUniform1f(es->shader->texwidth_uniform,
|
||||
(GLfloat)es->geometry.width / es->pitch);
|
||||
glUniform4fv(es->shader->opaque_uniform, 1, es->opaque_rect);
|
||||
|
||||
if (es->transform.enabled || output->zoom.active)
|
||||
filter = GL_LINEAR;
|
||||
@ -2325,6 +2330,7 @@ static const char texture_fragment_shader[] =
|
||||
"uniform float bright;\n"
|
||||
"uniform float saturation;\n"
|
||||
"uniform float texwidth;\n"
|
||||
"uniform vec4 opaque;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" if (v_texcoord.x < 0.0 || v_texcoord.x > texwidth ||\n"
|
||||
@ -2335,6 +2341,9 @@ static const char texture_fragment_shader[] =
|
||||
" vec3 range = (gl_FragColor.rgb - vec3 (gray, gray, gray)) * saturation;\n"
|
||||
" gl_FragColor = vec4(vec3(gray + range), gl_FragColor.a);\n"
|
||||
" gl_FragColor = vec4(vec3(bright, bright, bright) * gl_FragColor.rgb, gl_FragColor.a);\n"
|
||||
" if (opaque.x <= v_texcoord.x && v_texcoord.x < opaque.y &&\n"
|
||||
" opaque.z <= v_texcoord.y && v_texcoord.y < opaque.w)\n"
|
||||
" gl_FragColor.a = 1.0;\n"
|
||||
" gl_FragColor = alpha * gl_FragColor;\n"
|
||||
"}\n";
|
||||
|
||||
@ -2401,6 +2410,8 @@ weston_shader_init(struct weston_shader *shader,
|
||||
shader->color_uniform = glGetUniformLocation(shader->program, "color");
|
||||
shader->texwidth_uniform = glGetUniformLocation(shader->program,
|
||||
"texwidth");
|
||||
shader->opaque_uniform =
|
||||
glGetUniformLocation(shader->program, "opaque");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -166,6 +166,7 @@ struct weston_shader {
|
||||
GLint saturation_uniform;
|
||||
GLint color_uniform;
|
||||
GLint texwidth_uniform;
|
||||
GLint opaque_uniform;
|
||||
};
|
||||
|
||||
struct weston_animation {
|
||||
@ -326,6 +327,7 @@ struct weston_surface {
|
||||
struct wl_list layer_link;
|
||||
struct weston_shader *shader;
|
||||
GLfloat color[4];
|
||||
GLfloat opaque_rect[4];
|
||||
uint32_t alpha;
|
||||
uint32_t brightness;
|
||||
uint32_t saturation;
|
||||
|
@ -841,6 +841,22 @@ weston_wm_window_draw_decoration(void *data)
|
||||
|
||||
cairo_destroy(cr);
|
||||
cairo_surface_destroy(surface);
|
||||
|
||||
if (window->surface) {
|
||||
/* We leave an extra pixel around the X window area to
|
||||
* make sure we don't sample from the undefined alpha
|
||||
* channel when filtering. */
|
||||
window->surface->opaque_rect[0] =
|
||||
(double) (t->margin + t->width - 1) / width;
|
||||
window->surface->opaque_rect[1] =
|
||||
(double) (t->margin + t->width +
|
||||
window->width + 1) / width;
|
||||
window->surface->opaque_rect[2] =
|
||||
(double) (t->margin + t->titlebar_height - 1) / height;
|
||||
window->surface->opaque_rect[3] =
|
||||
(double) (t->margin + t->titlebar_height +
|
||||
window->height + 1) / height;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -1767,6 +1783,8 @@ xserver_set_window_id(struct wl_client *client, struct wl_resource *resource,
|
||||
wl_signal_add(&surface->resource.destroy_signal,
|
||||
&window->surface_destroy_listener);
|
||||
|
||||
weston_wm_window_schedule_repaint(window);
|
||||
|
||||
if (shell_interface->create_shell_surface) {
|
||||
shell_interface->create_shell_surface(shell_interface->shell,
|
||||
window->surface,
|
||||
|
Loading…
Reference in New Issue
Block a user