xwm: Use empty opaque region for windows with alpha

Window contents cannot be assumed to be fully opaque for windows drawn with
a RGBA visual. The optimization of setting a full opaque region is limited to
windows with a color depth != 32.
dev
MoD 12 years ago committed by Kristian Høgsberg
parent 7e5b57e7b8
commit 384a11aeac
  1. 38
      src/xwayland/window-manager.c

@ -116,6 +116,7 @@ struct weston_wm_window {
int decorate; int decorate;
int override_redirect; int override_redirect;
int fullscreen; int fullscreen;
int has_alpha;
}; };
static struct weston_wm_window * static struct weston_wm_window *
@ -901,13 +902,17 @@ weston_wm_window_draw_decoration(void *data)
if (window->surface) { if (window->surface) {
pixman_region32_fini(&window->surface->pending.opaque); pixman_region32_fini(&window->surface->pending.opaque);
/* We leave an extra pixel around the X window area to if(window->has_alpha) {
* make sure we don't sample from the undefined alpha pixman_region32_init(&window->surface->pending.opaque);
* channel when filtering. */ } else {
pixman_region32_init_rect(&window->surface->pending.opaque, /* We leave an extra pixel around the X window area to
x - 1, y - 1, * make sure we don't sample from the undefined alpha
window->width + 2, * channel when filtering. */
window->height + 2); pixman_region32_init_rect(&window->surface->pending.opaque,
x - 1, y - 1,
window->width + 2,
window->height + 2);
}
weston_surface_geometry_dirty(window->surface); weston_surface_geometry_dirty(window->surface);
} }
@ -930,8 +935,12 @@ weston_wm_window_schedule_repaint(struct weston_wm_window *window)
if (window->surface != NULL) { if (window->surface != NULL) {
weston_wm_window_get_frame_size(window, &width, &height); weston_wm_window_get_frame_size(window, &width, &height);
pixman_region32_fini(&window->surface->pending.opaque); pixman_region32_fini(&window->surface->pending.opaque);
pixman_region32_init_rect(&window->surface->pending.opaque, 0, 0, if(window->has_alpha) {
width, height); pixman_region32_init(&window->surface->pending.opaque);
} else {
pixman_region32_init_rect(&window->surface->pending.opaque, 0, 0,
width, height);
}
weston_surface_geometry_dirty(window->surface); weston_surface_geometry_dirty(window->surface);
} }
return; return;
@ -977,6 +986,8 @@ weston_wm_window_create(struct weston_wm *wm,
{ {
struct weston_wm_window *window; struct weston_wm_window *window;
uint32_t values[1]; uint32_t values[1];
xcb_get_geometry_cookie_t geometry_cookie;
xcb_get_geometry_reply_t *geometry_reply;
window = malloc(sizeof *window); window = malloc(sizeof *window);
if (window == NULL) { if (window == NULL) {
@ -984,6 +995,8 @@ weston_wm_window_create(struct weston_wm *wm,
return; return;
} }
geometry_cookie = xcb_get_geometry(wm->conn, id);
values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE; values[0] = XCB_EVENT_MASK_PROPERTY_CHANGE;
xcb_change_window_attributes(wm->conn, id, XCB_CW_EVENT_MASK, values); xcb_change_window_attributes(wm->conn, id, XCB_CW_EVENT_MASK, values);
@ -995,6 +1008,13 @@ weston_wm_window_create(struct weston_wm *wm,
window->width = width; window->width = width;
window->height = height; window->height = height;
geometry_reply = xcb_get_geometry_reply(wm->conn, geometry_cookie, NULL);
/* technically we should use XRender and check the visual format's
alpha_mask, but checking depth is simpler and works in all known cases */
if(geometry_reply != NULL)
window->has_alpha = geometry_reply->depth == 32;
free(geometry_reply);
hash_table_insert(wm->window_hash, id, window); hash_table_insert(wm->window_hash, id, window);
} }

Loading…
Cancel
Save