Skip to content

Commit

Permalink
feat(draw): draw the screencopy buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
jtheoof committed Dec 6, 2019
1 parent c623939 commit 2344414
Showing 1 changed file with 57 additions and 11 deletions.
68 changes: 57 additions & 11 deletions src/draw.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,19 @@ static cairo_format_t get_cairo_format(enum wl_shm_format wl_fmt) {
}
}

static int get_output_flipped(enum wl_output_transform transform) {
return transform & WL_OUTPUT_TRANSFORM_FLIPPED ? -1 : 1;
}

static void apply_output_transform(enum wl_output_transform transform,
int32_t *width, int32_t *height) {
if (transform & WL_OUTPUT_TRANSFORM_90) {
int32_t tmp = *width;
*width = *height;
*height = tmp;
}
}

static void draw_buffer(cairo_t *cr, struct swappy_state *state) {
// FIXME This is wrong, the geometry here is not quite valid
// It must be based on output, but will work fine on single screen
Expand All @@ -22,21 +35,54 @@ static void draw_buffer(cairo_t *cr, struct swappy_state *state) {
wl_list_for_each(output, &state->outputs, link) {
struct swappy_buffer *buffer = output->buffer;
cairo_format_t format = get_cairo_format(buffer->format);
cairo_surface_t *image;

g_assert(format != CAIRO_FORMAT_INVALID);

image = cairo_image_surface_create_for_data(
buffer->data, format, geometry->height, geometry->width,
buffer->stride);
cairo_save(cr);
cairo_surface_flush(image);
cairo_surface_mark_dirty(image);
cairo_set_source_surface(cr, image, 0, 0);
cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_NEAREST);
int32_t output_x = output->logical_geometry.x - geometry->x;
int32_t output_y = output->logical_geometry.y - geometry->y;
int32_t output_width = output->logical_geometry.width;
int32_t output_height = output->logical_geometry.height;
int32_t scale = output->scale;

int32_t raw_output_width = output->geometry.width;
int32_t raw_output_height = output->geometry.height;
apply_output_transform(output->transform, &raw_output_width,
&raw_output_height);

int output_flipped_x = get_output_flipped(output->transform);
int output_flipped_y =
output->screencopy_frame_flags & ZWLR_SCREENCOPY_FRAME_V1_FLAGS_Y_INVERT
? -1
: 1;

cairo_surface_t *output_surface = cairo_image_surface_create_for_data(
buffer->data, format, buffer->width, buffer->height, buffer->stride);
cairo_pattern_t *output_pattern =
cairo_pattern_create_for_surface(output_surface);

// All transformations are in pattern-local coordinates
cairo_matrix_t matrix;
cairo_matrix_init_identity(&matrix);
cairo_matrix_translate(&matrix, (double)output->geometry.width / 2,
(double)output->geometry.height / 2);
// cairo_matrix_rotate(&matrix, -get_output_rotation(output->transform));
cairo_matrix_scale(
&matrix, (double)raw_output_width / output_width * output_flipped_x,
(double)raw_output_height / output_height * output_flipped_y);
cairo_matrix_translate(&matrix, -(double)output_width / 2,
-(double)output_height / 2);
cairo_matrix_translate(&matrix, -output_x, -output_y);
cairo_matrix_scale(&matrix, 1 / scale, 1 / scale);
cairo_pattern_set_matrix(output_pattern, &matrix);

cairo_pattern_set_filter(output_pattern, CAIRO_FILTER_BEST);

cairo_set_source(cr, output_pattern);
cairo_pattern_destroy(output_pattern);

cairo_paint(cr);
cairo_surface_destroy(image);
cairo_restore(cr);

cairo_surface_destroy(output_surface);
}
}

Expand Down

0 comments on commit 2344414

Please sign in to comment.