[PATCH weston 2/7] pixman-renderer: Move shadow buffer into renderer
Vasily Khoruzhick
anarsoul at gmail.com
Tue Jan 22 23:25:27 PST 2013
On Tue, Jan 22, 2013 at 7:07 PM, Ander Conselvan de Oliveira
<ander.conselvan.de.oliveira at intel.com> wrote:
> The X11 backend uses a shadow buffer to be able to support transformed
> outputs. However, this belongs in the renderer, since otherwise this
> code would have to be copied into every backend that uses the pixman
> renderer and supports transformed outputs.
It's not a good idea, because with that change you won't be able to
implement pageflips.
Regards
Vasily
> ---
> src/compositor-x11.c | 104 +------------------------------------------------
> src/pixman-renderer.c | 99 ++++++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 97 insertions(+), 106 deletions(-)
>
> diff --git a/src/compositor-x11.c b/src/compositor-x11.c
> index 7ae2b75..b3c7fc5 100644
> --- a/src/compositor-x11.c
> +++ b/src/compositor-x11.c
> @@ -116,10 +116,8 @@ struct x11_output {
> xcb_gc_t gc;
> xcb_shm_seg_t segment;
> pixman_image_t *hw_surface;
> - pixman_image_t *shadow_surface;
> int shm_id;
> void *buf;
> - void *shadow_buf;
> uint8_t depth;
> };
>
> @@ -342,59 +340,12 @@ x11_output_repaint_shm(struct weston_output *output_base,
> 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;
> - int nrects, i, src_x, src_y, x1, y1, x2, y2, width, height;
> xcb_void_cookie_t cookie;
> xcb_generic_error_t *err;
>
> - pixman_renderer_output_set_buffer(output_base, output->shadow_surface);
> + pixman_renderer_output_set_buffer(output_base, output->hw_surface);
> ec->renderer->repaint_output(output_base, damage);
>
> - width = pixman_image_get_width(output->shadow_surface);
> - height = pixman_image_get_height(output->shadow_surface);
> - rects = pixman_region32_rectangles(damage, &nrects);
> - for (i = 0; i < nrects; i++) {
> - switch (output_base->transform) {
> - default:
> - case WL_OUTPUT_TRANSFORM_NORMAL:
> - x1 = rects[i].x1;
> - x2 = rects[i].x2;
> - y1 = rects[i].y1;
> - y2 = rects[i].y2;
> - break;
> - case WL_OUTPUT_TRANSFORM_180:
> - x1 = width - rects[i].x2;
> - x2 = width - rects[i].x1;
> - y1 = height - rects[i].y2;
> - y2 = height - rects[i].y1;
> - break;
> - case WL_OUTPUT_TRANSFORM_90:
> - x1 = height - rects[i].y2;
> - x2 = height - rects[i].y1;
> - y1 = rects[i].x1;
> - y2 = rects[i].x2;
> - break;
> - case WL_OUTPUT_TRANSFORM_270:
> - x1 = rects[i].y1;
> - x2 = rects[i].y2;
> - y1 = width - rects[i].x2;
> - y2 = width - rects[i].x1;
> - break;
> - }
> - src_x = x1;
> - src_y = y1;
> -
> - pixman_image_composite32(PIXMAN_OP_SRC,
> - output->shadow_surface, /* src */
> - NULL /* mask */,
> - output->hw_surface, /* dest */
> - src_x, src_y, /* src_x, src_y */
> - 0, 0, /* mask_x, mask_y */
> - x1, y1, /* dest_x, dest_y */
> - x2 - x1, /* width */
> - y2 - y1 /* height */);
> - }
> -
> pixman_region32_subtract(&ec->primary_plane.damage,
> &ec->primary_plane.damage, damage);
> cookie = xcb_shm_put_image_checked(c->conn, output->window, output->gc,
> @@ -444,10 +395,6 @@ x11_output_deinit_shm(struct x11_compositor *c, struct x11_output *output)
> free(err);
> }
> shmdt(output->buf);
> -
> - pixman_image_unref(output->shadow_surface);
> - output->shadow_surface = NULL;
> - free(output->shadow_buf);
> }
>
> static void
> @@ -622,8 +569,6 @@ x11_output_init_shm(struct x11_compositor *c, struct x11_output *output,
> xcb_format_iterator_t fmt;
> xcb_void_cookie_t cookie;
> xcb_generic_error_t *err;
> - int shadow_width, shadow_height;
> - pixman_transform_t transform;
> const xcb_query_extension_reply_t *ext;
> int bitsperpixel = 0;
> pixman_format_code_t pixman_format;
> @@ -701,53 +646,6 @@ x11_output_init_shm(struct x11_compositor *c, struct x11_output *output,
> /* Now create pixman image */
> output->hw_surface = pixman_image_create_bits(pixman_format, width, height, output->buf,
> width * (bitsperpixel / 8));
> - pixman_transform_init_identity(&transform);
> - switch (output->base.transform) {
> - default:
> - case WL_OUTPUT_TRANSFORM_NORMAL:
> - shadow_width = width;
> - shadow_height = height;
> - pixman_transform_rotate(&transform,
> - NULL, 0, 0);
> - pixman_transform_translate(&transform, NULL,
> - 0, 0);
> - break;
> - case WL_OUTPUT_TRANSFORM_180:
> - shadow_width = width;
> - shadow_height = height;
> - pixman_transform_rotate(&transform,
> - NULL, -pixman_fixed_1, 0);
> - pixman_transform_translate(NULL, &transform,
> - pixman_int_to_fixed(shadow_width),
> - pixman_int_to_fixed(shadow_height));
> - break;
> - case WL_OUTPUT_TRANSFORM_270:
> - shadow_width = height;
> - shadow_height = width;
> - pixman_transform_rotate(&transform,
> - NULL, 0, pixman_fixed_1);
> - pixman_transform_translate(&transform,
> - NULL,
> - pixman_int_to_fixed(shadow_width),
> - 0);
> - break;
> - case WL_OUTPUT_TRANSFORM_90:
> - shadow_width = height;
> - shadow_height = width;
> - pixman_transform_rotate(&transform,
> - NULL, 0, -pixman_fixed_1);
> - pixman_transform_translate(&transform,
> - NULL,
> - 0,
> - pixman_int_to_fixed(shadow_height));
> - break;
> - }
> - output->shadow_buf = malloc(width * height * (bitsperpixel / 8));
> - output->shadow_surface = pixman_image_create_bits(pixman_format, shadow_width, shadow_height,
> - output->shadow_buf, shadow_width * (bitsperpixel / 8));
> - /* No need in transform for normal output */
> - if (output->base.transform != WL_OUTPUT_TRANSFORM_NORMAL)
> - pixman_image_set_transform(output->shadow_surface, &transform);
>
> output->gc = xcb_generate_id(c->conn);
> xcb_create_gc(c->conn, output->gc, output->window, 0, NULL);
> diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c
> index 8391cc6..77ae99e 100644
> --- a/src/pixman-renderer.c
> +++ b/src/pixman-renderer.c
> @@ -31,6 +31,8 @@
> #include <linux/input.h>
>
> struct pixman_output_state {
> + void *shadow_buffer;
> + pixman_image_t *shadow_image;
> pixman_image_t *hw_buffer;
> };
>
> @@ -140,7 +142,7 @@ repaint_region(struct weston_surface *es, struct weston_output *output,
> pixman_image_composite32(pixman_op,
> ps->image, /* src */
> NULL /* mask */,
> - po->hw_buffer, /* dest */
> + po->shadow_image, /* dest */
> src_x, src_y, /* src_x, src_y */
> 0, 0, /* mask_x, mask_y */
> rects[i].x1, rects[i].y1, /* dest_x, dest_y */
> @@ -153,7 +155,7 @@ repaint_region(struct weston_surface *es, struct weston_output *output,
> pixman_image_composite32(PIXMAN_OP_OVER,
> pr->debug_color, /* src */
> NULL /* mask */,
> - po->hw_buffer, /* dest */
> + po->shadow_image, /* dest */
> src_x, src_y, /* src_x, src_y */
> 0, 0, /* mask_x, mask_y */
> rects[i].x1, rects[i].y1, /* dest_x, dest_y */
> @@ -220,6 +222,35 @@ repaint_surfaces(struct weston_output *output, pixman_region32_t *damage)
> }
>
> static void
> +copy_to_hw_buffer(struct weston_output *output, pixman_region32_t *region)
> +{
> + struct pixman_output_state *po = get_output_state(output);
> + int nrects, i, width, height;
> + pixman_box32_t *rects;
> + pixman_box32_t b;
> +
> + width = pixman_image_get_width(po->shadow_image);
> + height = pixman_image_get_height(po->shadow_image);
> +
> + rects = pixman_region32_rectangles(region, &nrects);
> + for (i = 0; i < nrects; i++) {
> + b = weston_transformed_rect(width, height,
> + output->transform, rects[i]);
> +
> + pixman_image_composite32(PIXMAN_OP_SRC,
> + po->shadow_image, /* src */
> + NULL /* mask */,
> + po->hw_buffer, /* dest */
> + b.x1, b.y1, /* src_x, src_y */
> + 0, 0, /* mask_x, mask_y */
> + b.x1, b.y1, /* dest_x, dest_y */
> + b.x2 - b.x1, /* width */
> + b.y2 - b.y1 /* height */);
> + }
> +
> +}
> +
> +static void
> pixman_renderer_repaint_output(struct weston_output *output,
> pixman_region32_t *output_damage)
> {
> @@ -229,6 +260,7 @@ pixman_renderer_repaint_output(struct weston_output *output,
> return;
>
> repaint_surfaces(output, output_damage);
> + copy_to_hw_buffer(output, output_damage);
>
> pixman_region32_copy(&output->previous_damage, output_damage);
> wl_signal_emit(&output->frame_signal, output);
> @@ -402,10 +434,68 @@ WL_EXPORT int
> pixman_renderer_output_create(struct weston_output *output)
> {
> struct pixman_output_state *po = calloc(1, sizeof *po);
> + pixman_transform_t transform;
> + pixman_fixed_t fw, fh;
> + int w, h;
> + int rotated = 0;
>
> if (!po)
> return -1;
> -
> +
> + /* set shadow image transformation */
> + w = output->current->width;
> + h = output->current->height;
> +
> + fw = pixman_int_to_fixed(w);
> + fh = pixman_int_to_fixed(h);
> +
> + pixman_transform_init_identity(&transform);
> +
> + switch (output->transform) {
> + default:
> + case WL_OUTPUT_TRANSFORM_NORMAL:
> + break;
> + case WL_OUTPUT_TRANSFORM_180:
> + pixman_transform_rotate(&transform, NULL, -pixman_fixed_1, 0);
> + pixman_transform_translate(NULL, &transform, fw, fh);
> + break;
> + case WL_OUTPUT_TRANSFORM_270:
> + rotated = 1;
> + pixman_transform_rotate(&transform, NULL, 0, pixman_fixed_1);
> + pixman_transform_translate(&transform, NULL, fh, 0);
> + break;
> + case WL_OUTPUT_TRANSFORM_90:
> + rotated = 1;
> + pixman_transform_rotate(&transform, NULL, 0, -pixman_fixed_1);
> + pixman_transform_translate(&transform, NULL, 0, fw);
> + break;
> + }
> +
> + if (rotated) {
> + int tmp = w;
> + w = h;
> + h = tmp;
> + }
> +
> + po->shadow_buffer = malloc(w * h * 4);
> +
> + if (!po->shadow_buffer) {
> + free(po);
> + return -1;
> + }
> +
> + po->shadow_image =
> + pixman_image_create_bits(PIXMAN_x8r8g8b8, w, h,
> + po->shadow_buffer, w * 4);
> +
> + if (!po->shadow_image) {
> + free(po->shadow_buffer);
> + free(po);
> + return -1;
> + }
> +
> + pixman_image_set_transform(po->shadow_image, &transform);
> +
> output->renderer_state = po;
>
> return 0;
> @@ -416,7 +506,10 @@ pixman_renderer_output_destroy(struct weston_output *output)
> {
> struct pixman_output_state *po = get_output_state(output);
>
> + pixman_image_unref(po->shadow_image);
> pixman_image_unref(po->hw_buffer);
> +
> + po->shadow_image = NULL;
> po->hw_buffer = NULL;
>
> free(po);
> --
> 1.7.10.4
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the wayland-devel
mailing list