[PATCH weston 2/7] pixman-renderer: Move shadow buffer into renderer
Vasily Khoruzhick
anarsoul at gmail.com
Wed Jan 23 02:15:15 PST 2013
On Wed, Jan 23, 2013 at 12:02 PM, Ander Conselvan de Oliveira
<conselvan2 at gmail.com> wrote:
> On 01/23/2013 09:25 AM, Vasily Khoruzhick wrote:
>>
>> 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.
>
>
> Can you elaborate on that? On the drm backend, I implemented page flips by
> calling pixman_renderer_output_set_buffer() prior to rendering, alternating
> between two dumb buffers. See drm_output_render_pixman() in the last patch
> of this series.
When doing pageflip you definitely don't need shadow buffer, do you?
Why to do extra copy?
> Thanks,
> Ander
>
>
>
>> 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
>>
>> _______________________________________________
>> 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