screenshooter: Move buffer assembly to client side
This commit is contained in:
committed by
Kristian Høgsberg
parent
062be7ec93
commit
72c2372148
+31
-13
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-22
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user