diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2012-05-15 23:16:53 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2012-05-16 16:00:41 -0400 |
commit | 0b0c2bb3e94ce11c2717f7670fa66f9cba675151 (patch) | |
tree | e1d6c26e659d4e9d17b93f0603d0c7013e13bbb9 | |
parent | fb6c6d90f316689c88531eddd341a97383b7b79f (diff) |
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.
-rw-r--r-- | src/compositor.c | 11 | ||||
-rw-r--r-- | src/compositor.h | 2 | ||||
-rw-r--r-- | src/xserver-launcher.c | 18 |
3 files changed, 31 insertions, 0 deletions
diff --git a/src/compositor.c b/src/compositor.c index 622db58..c26a31e 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -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; } diff --git a/src/compositor.h b/src/compositor.h index 2e66f22..e8edbb4 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -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; diff --git a/src/xserver-launcher.c b/src/xserver-launcher.c index 551030f..070ffb4 100644 --- a/src/xserver-launcher.c +++ b/src/xserver-launcher.c @@ -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, |