[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