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:
@@ -228,6 +228,10 @@ weston_surface_create(struct weston_compositor *compositor)
|
|||||||
surface->alpha = 255;
|
surface->alpha = 255;
|
||||||
surface->brightness = 255;
|
surface->brightness = 255;
|
||||||
surface->saturation = 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->pitch = 1;
|
||||||
|
|
||||||
surface->buffer = NULL;
|
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->saturation_uniform, es->saturation / 255.0);
|
||||||
glUniform1f(es->shader->texwidth_uniform,
|
glUniform1f(es->shader->texwidth_uniform,
|
||||||
(GLfloat)es->geometry.width / es->pitch);
|
(GLfloat)es->geometry.width / es->pitch);
|
||||||
|
glUniform4fv(es->shader->opaque_uniform, 1, es->opaque_rect);
|
||||||
|
|
||||||
if (es->transform.enabled || output->zoom.active)
|
if (es->transform.enabled || output->zoom.active)
|
||||||
filter = GL_LINEAR;
|
filter = GL_LINEAR;
|
||||||
@@ -2325,6 +2330,7 @@ static const char texture_fragment_shader[] =
|
|||||||
"uniform float bright;\n"
|
"uniform float bright;\n"
|
||||||
"uniform float saturation;\n"
|
"uniform float saturation;\n"
|
||||||
"uniform float texwidth;\n"
|
"uniform float texwidth;\n"
|
||||||
|
"uniform vec4 opaque;\n"
|
||||||
"void main()\n"
|
"void main()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" if (v_texcoord.x < 0.0 || v_texcoord.x > texwidth ||\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"
|
" 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(gray + range), gl_FragColor.a);\n"
|
||||||
" gl_FragColor = vec4(vec3(bright, bright, bright) * gl_FragColor.rgb, 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"
|
" gl_FragColor = alpha * gl_FragColor;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
||||||
@@ -2401,6 +2410,8 @@ weston_shader_init(struct weston_shader *shader,
|
|||||||
shader->color_uniform = glGetUniformLocation(shader->program, "color");
|
shader->color_uniform = glGetUniformLocation(shader->program, "color");
|
||||||
shader->texwidth_uniform = glGetUniformLocation(shader->program,
|
shader->texwidth_uniform = glGetUniformLocation(shader->program,
|
||||||
"texwidth");
|
"texwidth");
|
||||||
|
shader->opaque_uniform =
|
||||||
|
glGetUniformLocation(shader->program, "opaque");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -166,6 +166,7 @@ struct weston_shader {
|
|||||||
GLint saturation_uniform;
|
GLint saturation_uniform;
|
||||||
GLint color_uniform;
|
GLint color_uniform;
|
||||||
GLint texwidth_uniform;
|
GLint texwidth_uniform;
|
||||||
|
GLint opaque_uniform;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct weston_animation {
|
struct weston_animation {
|
||||||
@@ -326,6 +327,7 @@ struct weston_surface {
|
|||||||
struct wl_list layer_link;
|
struct wl_list layer_link;
|
||||||
struct weston_shader *shader;
|
struct weston_shader *shader;
|
||||||
GLfloat color[4];
|
GLfloat color[4];
|
||||||
|
GLfloat opaque_rect[4];
|
||||||
uint32_t alpha;
|
uint32_t alpha;
|
||||||
uint32_t brightness;
|
uint32_t brightness;
|
||||||
uint32_t saturation;
|
uint32_t saturation;
|
||||||
|
|||||||
@@ -841,6 +841,22 @@ weston_wm_window_draw_decoration(void *data)
|
|||||||
|
|
||||||
cairo_destroy(cr);
|
cairo_destroy(cr);
|
||||||
cairo_surface_destroy(surface);
|
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
|
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,
|
wl_signal_add(&surface->resource.destroy_signal,
|
||||||
&window->surface_destroy_listener);
|
&window->surface_destroy_listener);
|
||||||
|
|
||||||
|
weston_wm_window_schedule_repaint(window);
|
||||||
|
|
||||||
if (shell_interface->create_shell_surface) {
|
if (shell_interface->create_shell_surface) {
|
||||||
shell_interface->create_shell_surface(shell_interface->shell,
|
shell_interface->create_shell_surface(shell_interface->shell,
|
||||||
window->surface,
|
window->surface,
|
||||||
|
|||||||
Reference in New Issue
Block a user