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:
Kristian Høgsberg 2012-05-15 23:16:53 -04:00
parent fb6c6d90f3
commit 0b0c2bb3e9
3 changed files with 31 additions and 0 deletions

View File

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

View File

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

View File

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