From 409eebf34f751f33196cbc694c2a794e7a029f94 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Wed, 5 Dec 2012 15:14:04 +0200 Subject: [PATCH] compositor-drm: Support overlays with transformed buffers Make overlays work when the client uses a buffer with the same transformation as the output. In order to calculate the destination rectangle, the same logic in weston_surface_to_buffer_float() is needed, but with the output dimensions instead. For that reason, this patch generalizes this function into weston_transformed_{coord,rect} and moves it to util.c. The surface functions are then implemented using those. --- src/compositor-drm.c | 32 +++++++++++++------ src/compositor.c | 66 +++++--------------------------------- src/compositor.h | 9 ++++++ src/util.c | 75 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 113 insertions(+), 69 deletions(-) diff --git a/src/compositor-drm.c b/src/compositor-drm.c index 11d99818..c44da97d 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -572,11 +572,11 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base, int found = 0; struct gbm_bo *bo; pixman_region32_t dest_rect, src_rect; - pixman_box32_t *box; + pixman_box32_t *box, tbox; uint32_t format; wl_fixed_t sx1, sy1, sx2, sy2; - if (output_base->transform != WL_OUTPUT_TRANSFORM_NORMAL) + if (es->buffer_transform != output_base->transform) return NULL; if (c->sprites_are_broken) @@ -645,10 +645,13 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base, &output_base->region); pixman_region32_translate(&dest_rect, -output_base->x, -output_base->y); box = pixman_region32_extents(&dest_rect); - s->dest_x = box->x1; - s->dest_y = box->y1; - s->dest_w = box->x2 - box->x1; - s->dest_h = box->y2 - box->y1; + tbox = weston_transformed_rect(output_base->width, + output_base->height, + output_base->transform, *box); + s->dest_x = tbox.x1; + s->dest_y = tbox.y1; + s->dest_w = tbox.x2 - tbox.x1; + s->dest_h = tbox.y2 - tbox.y1; pixman_region32_fini(&dest_rect); pixman_region32_init(&src_rect); @@ -674,10 +677,19 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base, if (sy2 > wl_fixed_from_int(es->geometry.height)) sy2 = wl_fixed_from_int(es->geometry.height); - s->src_x = sx1 << 8; - s->src_y = sy1 << 8; - s->src_w = (sx2 - sx1) << 8; - s->src_h = (sy2 - sy1) << 8; + tbox.x1 = sx1; + tbox.y1 = sy1; + tbox.x2 = sx2; + tbox.y2 = sy2; + + tbox = weston_transformed_rect(wl_fixed_from_int(es->geometry.width), + wl_fixed_from_int(es->geometry.height), + es->buffer_transform, tbox); + + s->src_x = tbox.x1 << 8; + s->src_y = tbox.y1 << 8; + s->src_w = (tbox.x2 - tbox.x1) << 8; + s->src_h = (tbox.y2 - tbox.y1) << 8; pixman_region32_fini(&src_rect); return &s->plane; diff --git a/src/compositor.c b/src/compositor.c index f56e515a..d62a7400 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -294,71 +294,19 @@ WL_EXPORT void weston_surface_to_buffer_float(struct weston_surface *surface, float sx, float sy, float *bx, float *by) { - switch (surface->buffer_transform) { - case WL_OUTPUT_TRANSFORM_NORMAL: - default: - *bx = sx; - *by = sy; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED: - *bx = surface->geometry.width - sx; - *by = sy; - break; - case WL_OUTPUT_TRANSFORM_90: - *bx = surface->geometry.height - sy; - *by = sx; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_90: - *bx = surface->geometry.height - sy; - *by = surface->geometry.width - sx; - break; - case WL_OUTPUT_TRANSFORM_180: - *bx = surface->geometry.width - sx; - *by = surface->geometry.height - sy; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_180: - *bx = sx; - *by = surface->geometry.height - sy; - break; - case WL_OUTPUT_TRANSFORM_270: - *bx = sy; - *by = surface->geometry.width - sx; - break; - case WL_OUTPUT_TRANSFORM_FLIPPED_270: - *bx = sy; - *by = sx; - break; - } + weston_transformed_coord(surface->geometry.width, + surface->geometry.height, + surface->buffer_transform, + sx, sy, bx, by); } WL_EXPORT pixman_box32_t weston_surface_to_buffer_rect(struct weston_surface *surface, pixman_box32_t rect) { - float x1, x2, y1, y2; - - pixman_box32_t ret; - - weston_surface_to_buffer_float(surface, rect.x1, rect.y1, &x1, &y1); - weston_surface_to_buffer_float(surface, rect.x2, rect.y2, &x2, &y2); - - if (x1 <= x2) { - ret.x1 = x1; - ret.x2 = x2; - } else { - ret.x1 = x2; - ret.x2 = x1; - } - - if (y1 <= y2) { - ret.y1 = y1; - ret.y2 = y2; - } else { - ret.y1 = y2; - ret.y2 = y1; - } - - return ret; + return weston_transformed_rect(surface->geometry.width, + surface->geometry.height, + surface->buffer_transform, rect); } WL_EXPORT void diff --git a/src/compositor.h b/src/compositor.h index 6aa411db..15d69390 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -831,4 +831,13 @@ backend_init(struct wl_display *display, int argc, char *argv[], int module_init(struct weston_compositor *compositor); +void +weston_transformed_coord(int width, int height, + enum wl_output_transform transform, + float sx, float sy, float *bx, float *by); +pixman_box32_t +weston_transformed_rect(int width, int height, + enum wl_output_transform transform, + pixman_box32_t rect); + #endif diff --git a/src/util.c b/src/util.c index 21343924..5f8e9c87 100644 --- a/src/util.c +++ b/src/util.c @@ -557,3 +557,78 @@ weston_environment_get_fd(const char *env) return fd; } + +WL_EXPORT void +weston_transformed_coord(int width, int height, + enum wl_output_transform transform, + float sx, float sy, float *bx, float *by) +{ + switch (transform) { + case WL_OUTPUT_TRANSFORM_NORMAL: + default: + *bx = sx; + *by = sy; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED: + *bx = width - sx; + *by = sy; + break; + case WL_OUTPUT_TRANSFORM_90: + *bx = height - sy; + *by = sx; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_90: + *bx = height - sy; + *by = width - sx; + break; + case WL_OUTPUT_TRANSFORM_180: + *bx = width - sx; + *by = height - sy; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_180: + *bx = sx; + *by = height - sy; + break; + case WL_OUTPUT_TRANSFORM_270: + *bx = sy; + *by = width - sx; + break; + case WL_OUTPUT_TRANSFORM_FLIPPED_270: + *bx = sy; + *by = sx; + break; + } +} + +WL_EXPORT pixman_box32_t +weston_transformed_rect(int width, int height, + enum wl_output_transform transform, + pixman_box32_t rect) +{ + float x1, x2, y1, y2; + + pixman_box32_t ret; + + weston_transformed_coord(width, height, transform, + rect.x1, rect.y1, &x1, &y1); + weston_transformed_coord(width, height, transform, + rect.x2, rect.y2, &x2, &y2); + + if (x1 <= x2) { + ret.x1 = x1; + ret.x2 = x2; + } else { + ret.x1 = x2; + ret.x2 = x1; + } + + if (y1 <= y2) { + ret.y1 = y1; + ret.y2 = y2; + } else { + ret.y1 = y2; + ret.y2 = y1; + } + + return ret; +}