screenshooter: Move buffer assembly to client side
authorScott Moreau <oreaus@gmail.com>
Fri, 20 Apr 2012 19:37:34 +0000 (13:37 -0600)
committerKristian Høgsberg <krh@bitplanet.net>
Fri, 20 Apr 2012 20:16:05 +0000 (16:16 -0400)
clients/screenshot.c
src/screenshooter.c

index 328d106..a23ef13 100644 (file)
@@ -47,6 +47,7 @@ struct screenshooter_output {
        struct wl_output *output;
        struct wl_buffer *buffer;
        int width, height, offset_x, offset_y;
+       void *data;
        struct wl_list link;
 };
 
@@ -165,23 +166,45 @@ create_shm_buffer(int width, int height, void **data_out)
 }
 
 static void
-write_png(int width, int height, void *data)
+write_png(int width, int height)
 {
+       int output_stride, buffer_stride, i;
        cairo_surface_t *surface;
+       void *data, *d, *s;
+       struct screenshooter_output *output, *next;
+
+       buffer_stride = width * 4;
+
+       data = malloc(buffer_stride * height);
+       if (!data)
+               return;
+
+       wl_list_for_each_safe(output, next, &output_list, link) {
+               output_stride = output->width * 4;
+               s = output->data;
+               d = data + output->offset_y * buffer_stride + output->offset_x * 4;
+
+               for (i = 0; i < output->height; i++) {
+                       memcpy(d, s, output_stride);
+                       d += buffer_stride;
+                       s += output_stride;
+               }
+
+               free(output);
+       }
 
        surface = cairo_image_surface_create_for_data(data,
                                                      CAIRO_FORMAT_ARGB32,
-                                                     width, height, width * 4);
+                                                     width, height, buffer_stride);
        cairo_surface_write_to_png(surface, "wayland-screenshot.png");
        cairo_surface_destroy(surface);
+       free(data);
 }
 
 int main(int argc, char *argv[])
 {
        struct wl_display *display;
-       struct wl_buffer *buffer;
-       void *data = NULL;
-       struct screenshooter_output *output, *next;
+       struct screenshooter_output *output;
        int width = 0, height = 0;
 
        display = wl_display_connect(NULL);
@@ -203,21 +226,16 @@ int main(int argc, char *argv[])
 
 
        wl_list_for_each(output, &output_list, link) {
+               output->buffer = create_shm_buffer(output->width, output->height, &output->data);
+               screenshooter_shoot(screenshooter, output->output, output->buffer);
                width = MAX(width, output->offset_x + output->width);
                height = MAX(height, output->offset_y + output->height);
-       }
-
-       buffer = create_shm_buffer(width, height, &data);
-
-       wl_list_for_each_safe(output, next, &output_list, link) {
-               screenshooter_shoot(screenshooter, output->output, buffer);
                buffer_copy_done = 0;
                while (!buffer_copy_done)
                        wl_display_roundtrip(display);
-               free(output);
        }
 
-       write_png(width, height, data);
+       write_png(width, height);
 
        return 0;
 }
index 7ba475d..90dd497 100644 (file)
@@ -43,16 +43,15 @@ struct screenshooter_read_pixels {
 };
 
 static void
-copy_bgra_yflip(uint8_t *dst, uint8_t *src, int height,
-               int dst_stride, int src_stride)
+copy_bgra_yflip(uint8_t *dst, uint8_t *src, int height, int stride)
 {
        uint8_t *end;
 
-       end = dst + height * dst_stride;
+       end = dst + height * stride;
        while (dst < end) {
-               memcpy(dst, src, src_stride);
-               dst += dst_stride;
-               src -= src_stride;
+               memcpy(dst, src, stride);
+               dst += stride;
+               src -= stride;
        }
 }
 
@@ -74,16 +73,15 @@ copy_row_swap_RB(void *vdst, void *vsrc, int bytes)
 }
 
 static void
-copy_rgba_yflip(uint8_t *dst, uint8_t *src, int height,
-               int dst_stride, int src_stride)
+copy_rgba_yflip(uint8_t *dst, uint8_t *src, int height, int stride)
 {
        uint8_t *end;
 
-       end = dst + height * dst_stride;
+       end = dst + height * stride;
        while (dst < end) {
-               copy_row_swap_RB(dst, src, src_stride);
-               dst += dst_stride;
-               src -= src_stride;
+               copy_row_swap_RB(dst, src, stride);
+               dst += stride;
+               src -= stride;
        }
 }
 
@@ -93,24 +91,20 @@ screenshooter_read_pixels_done(struct weston_read_pixels *base,
 {
        struct screenshooter_read_pixels *r =
                (struct screenshooter_read_pixels *) base;
-       int32_t buffer_stride, output_stride;
+       int32_t stride;
        uint8_t *d, *s;
 
-       buffer_stride = wl_shm_buffer_get_stride(r->buffer);
-       output_stride = output->current->width * 4;
+       stride = wl_shm_buffer_get_stride(r->buffer);
 
-       d = wl_shm_buffer_get_data(r->buffer) +
-               output->y * buffer_stride + output->x * 4;
-       s = r->base.data + output_stride * (output->current->height - 1);
+       d = wl_shm_buffer_get_data(r->buffer);
+       s = r->base.data + stride * (r->buffer->height - 1);
 
        switch (output->compositor->read_format) {
        case GL_BGRA_EXT:
-               copy_bgra_yflip(d, s, output->current->height,
-                               buffer_stride, output_stride);
+               copy_bgra_yflip(d, s, output->current->height, stride);
                break;
        case GL_RGBA:
-               copy_rgba_yflip(d, s, output->current->height,
-                               buffer_stride, output_stride);
+               copy_rgba_yflip(d, s, output->current->height, stride);
                break;
        default:
                break;