diff --git a/clients/screenshot.c b/clients/screenshot.c index 328d106c..a23ef13b 100644 --- a/clients/screenshot.c +++ b/clients/screenshot.c @@ -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; } diff --git a/src/screenshooter.c b/src/screenshooter.c index 7ba475d9..90dd4979 100644 --- a/src/screenshooter.c +++ b/src/screenshooter.c @@ -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;