From 5b1ce84350d78fa1bf7dc8ff421ae7c919542346 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Mon, 14 Aug 2017 16:30:53 -0400 Subject: [PATCH] implement buffer transform --- include/wlr/types/wlr_surface.h | 2 +- types/wlr_surface.c | 107 +++++++++++++++++++++++++++++--- 2 files changed, 98 insertions(+), 11 deletions(-) diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index d3104741..6dbee113 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -23,7 +23,7 @@ struct wlr_surface_state { int32_t sx, sy; pixman_region32_t surface_damage, buffer_damage; pixman_region32_t opaque, input; - uint32_t transform; + enum wl_output_transform transform; int32_t scale; }; diff --git a/types/wlr_surface.c b/types/wlr_surface.c index 2345bfd1..1872ac3b 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -91,11 +91,33 @@ static void surface_set_input_region(struct wl_client *client, } } +static void wlr_surface_get_effective_size(struct wlr_surface *surface, + int swidth, int sheight, int *width, int *height) { + int scale = surface->current.scale; + enum wl_output_transform transform = surface->current.transform; + int _width = swidth / scale; + int _height = sheight / scale; + + if (transform == WL_OUTPUT_TRANSFORM_90 || + transform == WL_OUTPUT_TRANSFORM_270 || + transform == WL_OUTPUT_TRANSFORM_FLIPPED_90 || + transform == WL_OUTPUT_TRANSFORM_FLIPPED_270) { + int tmp = _width; + _width = _height; + _height = tmp; + } + + *width = _width; + *height = _height; +} + static void wlr_surface_to_buffer_region(struct wlr_surface *surface, - pixman_region32_t *surface_region, pixman_region32_t *buffer_region) { + pixman_region32_t *surface_region, pixman_region32_t *buffer_region, + int width, int height) { pixman_box32_t *src_rects, *dest_rects; int nrects, i; int scale = surface->current.scale; + enum wl_output_transform transform = surface->current.transform; src_rects = pixman_region32_rectangles(surface_region, &nrects); dest_rects = malloc(nrects * sizeof(*dest_rects)); @@ -104,10 +126,66 @@ static void wlr_surface_to_buffer_region(struct wlr_surface *surface, } for (i = 0; i < nrects; i++) { - dest_rects[i].x1 = src_rects[i].x1 * scale; - dest_rects[i].y1 = src_rects[i].y1 * scale; - dest_rects[i].x2 = src_rects[i].x2 * scale; - dest_rects[i].y2 = src_rects[i].y2 * scale; + switch (transform) { + default: + case WL_OUTPUT_TRANSFORM_NORMAL: + dest_rects[i].x1 = src_rects[i].x1; + dest_rects[i].y1 = src_rects[i].y1; + dest_rects[i].x2 = src_rects[i].x2; + dest_rects[i].y2 = src_rects[i].y2; + break; + case WL_OUTPUT_TRANSFORM_90: + dest_rects[i].x1 = height - src_rects[i].y2; + dest_rects[i].y1 = src_rects[i].x1; + dest_rects[i].x2 = height - src_rects[i].y1; + dest_rects[i].y2 = src_rects[i].x2; + break; + case WL_OUTPUT_TRANSFORM_180: + dest_rects[i].x1 = width - src_rects[i].x2; + dest_rects[i].y1 = height - src_rects[i].y2; + dest_rects[i].x2 = width - src_rects[i].x1; + dest_rects[i].y2 = height - src_rects[i].y1; + break; + case WL_OUTPUT_TRANSFORM_270: + dest_rects[i].x1 = src_rects[i].y1; + dest_rects[i].y1 = width - src_rects[i].x2; + dest_rects[i].x2 = src_rects[i].y2; + dest_rects[i].y2 = width - src_rects[i].x1; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED: + dest_rects[i].x1 = width - src_rects[i].x2; + dest_rects[i].y1 = src_rects[i].y1; + dest_rects[i].x2 = width - src_rects[i].x1; + dest_rects[i].y2 = src_rects[i].y2; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + dest_rects[i].x1 = height - src_rects[i].y2; + dest_rects[i].y1 = width - src_rects[i].x2; + dest_rects[i].x2 = height - src_rects[i].y1; + dest_rects[i].y2 = width - src_rects[i].x1; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + dest_rects[i].x1 = src_rects[i].x1; + dest_rects[i].y1 = height - src_rects[i].y2; + dest_rects[i].x2 = src_rects[i].x2; + dest_rects[i].y2 = height - src_rects[i].y1; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + dest_rects[i].x1 = src_rects[i].y1; + dest_rects[i].y1 = src_rects[i].x1; + dest_rects[i].x2 = src_rects[i].y2; + dest_rects[i].y2 = src_rects[i].x2; + break; + } + } + + if (scale != 1) { + for (i = 0; i < nrects; i++) { + dest_rects[i].x1 *= scale; + dest_rects[i].x2 *= scale; + dest_rects[i].y1 *= scale; + dest_rects[i].y2 *= scale; + } } pixman_region32_fini(buffer_region); @@ -119,20 +197,26 @@ static void surface_commit(struct wl_client *client, struct wl_resource *resource) { struct wlr_surface *surface = wl_resource_get_user_data(resource); surface->current.scale = surface->pending.scale; + surface->current.transform = surface->pending.transform; if ((surface->pending.invalid & WLR_SURFACE_INVALID_BUFFER)) { surface->current.buffer = surface->pending.buffer; } if ((surface->pending.invalid & WLR_SURFACE_INVALID_SURFACE_DAMAGE)) { int width, height; - wlr_texture_get_buffer_size(surface->texture, surface->current.buffer, &width, &height); + wlr_texture_get_buffer_size(surface->texture, surface->current.buffer, + &width, &height); + + int surface_width, surface_height; + wlr_surface_get_effective_size(surface, width, height, &surface_width, + &surface_height); pixman_region32_union(&surface->current.surface_damage, &surface->current.surface_damage, &surface->pending.surface_damage); pixman_region32_intersect_rect(&surface->current.surface_damage, - &surface->current.surface_damage, 0, 0, width / - surface->current.scale, height / surface->current.scale); + &surface->current.surface_damage, 0, 0, surface_width, + surface_height); pixman_region32_union(&surface->current.buffer_damage, &surface->current.buffer_damage, @@ -141,7 +225,7 @@ static void surface_commit(struct wl_client *client, pixman_region32_t buffer_damage; pixman_region32_init(&buffer_damage); wlr_surface_to_buffer_region(surface, &surface->current.surface_damage, - &buffer_damage); + &buffer_damage, surface_width, surface_height); pixman_region32_union(&surface->current.buffer_damage, &surface->current.buffer_damage, &buffer_damage); @@ -203,7 +287,8 @@ release: static void surface_set_buffer_transform(struct wl_client *client, struct wl_resource *resource, int transform) { - wlr_log(L_DEBUG, "TODO: surface surface buffer transform"); + struct wlr_surface *surface = wl_resource_get_user_data(resource); + surface->pending.transform = transform; } static void surface_set_buffer_scale(struct wl_client *client, @@ -260,6 +345,8 @@ struct wlr_surface *wlr_surface_create(struct wl_resource *res, surface->resource = res; surface->current.scale = 1; surface->pending.scale = 1; + surface->current.transform = WL_OUTPUT_TRANSFORM_NORMAL; + surface->pending.transform = WL_OUTPUT_TRANSFORM_NORMAL; wl_signal_init(&surface->signals.commit); wl_list_init(&surface->frame_callback_list); wl_resource_set_implementation(res, &surface_interface,