[PATCH weston 2/7] pixman-renderer: Move shadow buffer into renderer

Ander Conselvan de Oliveira conselvan2 at gmail.com
Wed Jan 23 01:02:20 PST 2013


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.

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