screenshooter: Move buffer assembly to client side

Scott Moreau 13 years ago committed by Kristian Høgsberg
parent 062be7ec93
commit 72c2372148
  1. 44
      clients/screenshot.c
  2. 38
      src/screenshooter.c

@ -47,6 +47,7 @@ struct screenshooter_output {
struct wl_output *output; struct wl_output *output;
struct wl_buffer *buffer; struct wl_buffer *buffer;
int width, height, offset_x, offset_y; int width, height, offset_x, offset_y;
void *data;
struct wl_list link; struct wl_list link;
}; };
@ -165,23 +166,45 @@ create_shm_buffer(int width, int height, void **data_out)
} }
static void 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; 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, surface = cairo_image_surface_create_for_data(data,
CAIRO_FORMAT_ARGB32, CAIRO_FORMAT_ARGB32,
width, height, width * 4); width, height, buffer_stride);
cairo_surface_write_to_png(surface, "wayland-screenshot.png"); cairo_surface_write_to_png(surface, "wayland-screenshot.png");
cairo_surface_destroy(surface); cairo_surface_destroy(surface);
free(data);
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
struct wl_display *display; struct wl_display *display;
struct wl_buffer *buffer; struct screenshooter_output *output;
void *data = NULL;
struct screenshooter_output *output, *next;
int width = 0, height = 0; int width = 0, height = 0;
display = wl_display_connect(NULL); display = wl_display_connect(NULL);
@ -203,21 +226,16 @@ int main(int argc, char *argv[])
wl_list_for_each(output, &output_list, link) { 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); width = MAX(width, output->offset_x + output->width);
height = MAX(height, output->offset_y + output->height); 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; buffer_copy_done = 0;
while (!buffer_copy_done) while (!buffer_copy_done)
wl_display_roundtrip(display); wl_display_roundtrip(display);
free(output);
} }
write_png(width, height, data); write_png(width, height);
return 0; return 0;
} }

@ -43,16 +43,15 @@ struct screenshooter_read_pixels {
}; };
static void static void
copy_bgra_yflip(uint8_t *dst, uint8_t *src, int height, copy_bgra_yflip(uint8_t *dst, uint8_t *src, int height, int stride)
int dst_stride, int src_stride)
{ {
uint8_t *end; uint8_t *end;
end = dst + height * dst_stride; end = dst + height * stride;
while (dst < end) { while (dst < end) {
memcpy(dst, src, src_stride); memcpy(dst, src, stride);
dst += dst_stride; dst += stride;
src -= src_stride; src -= stride;
} }
} }
@ -74,16 +73,15 @@ copy_row_swap_RB(void *vdst, void *vsrc, int bytes)
} }
static void static void
copy_rgba_yflip(uint8_t *dst, uint8_t *src, int height, copy_rgba_yflip(uint8_t *dst, uint8_t *src, int height, int stride)
int dst_stride, int src_stride)
{ {
uint8_t *end; uint8_t *end;
end = dst + height * dst_stride; end = dst + height * stride;
while (dst < end) { while (dst < end) {
copy_row_swap_RB(dst, src, src_stride); copy_row_swap_RB(dst, src, stride);
dst += dst_stride; dst += stride;
src -= src_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 *r =
(struct screenshooter_read_pixels *) base; (struct screenshooter_read_pixels *) base;
int32_t buffer_stride, output_stride; int32_t stride;
uint8_t *d, *s; uint8_t *d, *s;
buffer_stride = wl_shm_buffer_get_stride(r->buffer); stride = wl_shm_buffer_get_stride(r->buffer);
output_stride = output->current->width * 4;
d = wl_shm_buffer_get_data(r->buffer) + d = wl_shm_buffer_get_data(r->buffer);
output->y * buffer_stride + output->x * 4; s = r->base.data + stride * (r->buffer->height - 1);
s = r->base.data + output_stride * (output->current->height - 1);
switch (output->compositor->read_format) { switch (output->compositor->read_format) {
case GL_BGRA_EXT: case GL_BGRA_EXT:
copy_bgra_yflip(d, s, output->current->height, copy_bgra_yflip(d, s, output->current->height, stride);
buffer_stride, output_stride);
break; break;
case GL_RGBA: case GL_RGBA:
copy_rgba_yflip(d, s, output->current->height, copy_rgba_yflip(d, s, output->current->height, stride);
buffer_stride, output_stride);
break; break;
default: default:
break; break;

Loading…
Cancel
Save