summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2013-05-21 17:17:05 +0200
committerAlexander Larsson <alexl@redhat.com>2013-05-22 14:29:53 +0200
commit176f83afb5e63e493d67cf4fb55153f5e2aad1e7 (patch)
tree0ab9a3b4d9b4a6fb3ced606367f405c8ac380a1c
parent475d71added29864986ce6ee2c117955fc74b6ad (diff)
compositor-x11: Only repaint the damaged region
Set a clip on the GC when painting the damaged region so that we don't copy the entire shadow buffer each time.
-rw-r--r--src/compositor-x11.c106
1 files changed, 106 insertions, 0 deletions
diff --git a/src/compositor-x11.c b/src/compositor-x11.c
index 58ccc16..9d6b6e7 100644
--- a/src/compositor-x11.c
+++ b/src/compositor-x11.c
@@ -355,6 +355,111 @@ x11_output_repaint_gl(struct weston_output *output_base,
}
static void
+set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region)
+{
+ struct x11_output *output = (struct x11_output *)output_base;
+ struct weston_compositor *ec = output->base.compositor;
+ struct x11_compositor *c = (struct x11_compositor *)ec;
+ pixman_box32_t *rects;
+ xcb_rectangle_t *output_rects;
+ pixman_box32_t rect, transformed_rect;
+ xcb_void_cookie_t cookie;
+ int width, height, nrects, i;
+ xcb_generic_error_t *err;
+
+ rects = pixman_region32_rectangles(region, &nrects);
+ output_rects = calloc(nrects, sizeof(xcb_rectangle_t));
+
+ if (output_rects == NULL)
+ return;
+
+ width = output_base->width;
+ height = output_base->height;
+
+ for (i = 0; i < nrects; i++) {
+ rect = rects[i];
+ rect.x1 -= output_base->x;
+ rect.y1 -= output_base->y;
+ rect.x2 -= output_base->x;
+ rect.y2 -= output_base->y;
+
+ switch (output_base->transform) {
+ default:
+ case WL_OUTPUT_TRANSFORM_NORMAL:
+ transformed_rect.x1 = rect.x1;
+ transformed_rect.y1 = rect.y1;
+ transformed_rect.x2 = rect.x2;
+ transformed_rect.y2 = rect.y2;
+ break;
+ case WL_OUTPUT_TRANSFORM_90:
+ transformed_rect.x1 = height - rect.y2;
+ transformed_rect.y1 = rect.x1;
+ transformed_rect.x2 = height - rect.y1;
+ transformed_rect.y2 = rect.x2;
+ break;
+ case WL_OUTPUT_TRANSFORM_180:
+ transformed_rect.x1 = width - rect.x2;
+ transformed_rect.y1 = height - rect.y2;
+ transformed_rect.x2 = width - rect.x1;
+ transformed_rect.y2 = height - rect.y1;
+ break;
+ case WL_OUTPUT_TRANSFORM_270:
+ transformed_rect.x1 = rect.y1;
+ transformed_rect.y1 = width - rect.x2;
+ transformed_rect.x2 = rect.y2;
+ transformed_rect.y2 = width - rect.x1;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED:
+ transformed_rect.x1 = width - rect.x2;
+ transformed_rect.y1 = rect.y1;
+ transformed_rect.x2 = width - rect.x1;
+ transformed_rect.y2 = rect.y2;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_90:
+ transformed_rect.x1 = height - rect.y2;
+ transformed_rect.y1 = width - rect.x2;
+ transformed_rect.x2 = height - rect.y1;
+ transformed_rect.y2 = width - rect.x1;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_180:
+ transformed_rect.x1 = rect.x1;
+ transformed_rect.y1 = height - rect.y2;
+ transformed_rect.x2 = rect.x2;
+ transformed_rect.y2 = height - rect.y1;
+ break;
+ case WL_OUTPUT_TRANSFORM_FLIPPED_270:
+ transformed_rect.x1 = rect.y1;
+ transformed_rect.y1 = rect.x1;
+ transformed_rect.x2 = rect.y2;
+ transformed_rect.y2 = rect.x2;
+ break;
+ }
+
+ transformed_rect.x1 *= output_base->scale;
+ transformed_rect.y1 *= output_base->scale;
+ transformed_rect.x2 *= output_base->scale;
+ transformed_rect.y2 *= output_base->scale;
+
+ output_rects[i].x = transformed_rect.x1;
+ output_rects[i].y = transformed_rect.y1;
+ output_rects[i].width = transformed_rect.x2 - transformed_rect.x1;
+ output_rects[i].height = transformed_rect.y2 - transformed_rect.y1;
+ }
+
+ cookie = xcb_set_clip_rectangles_checked(c->conn, XCB_CLIP_ORDERING_UNSORTED,
+ output->gc,
+ 0, 0, nrects,
+ output_rects);
+ err = xcb_request_check(c->conn, cookie);
+ if (err != NULL) {
+ weston_log("Failed to set clip rects, err: %d\n", err->error_code);
+ free(err);
+ }
+ free(output_rects);
+}
+
+
+static void
x11_output_repaint_shm(struct weston_output *output_base,
pixman_region32_t *damage)
{
@@ -369,6 +474,7 @@ x11_output_repaint_shm(struct weston_output *output_base,
pixman_region32_subtract(&ec->primary_plane.damage,
&ec->primary_plane.damage, damage);
+ set_clip_for_output(output_base, damage);
cookie = xcb_shm_put_image_checked(c->conn, output->window, output->gc,
pixman_image_get_width(output->hw_surface),
pixman_image_get_height(output->hw_surface),