mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-12-22 18:09:49 +01:00
Damage tracking for transformed outputs
This commit is contained in:
parent
a98ece68d3
commit
ece2c1e4e2
12 changed files with 185 additions and 154 deletions
|
@ -581,15 +581,14 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
|
|||
}
|
||||
|
||||
struct wlr_box hotspot = {
|
||||
.width = plane->surf.width,
|
||||
.height = plane->surf.height,
|
||||
.x = hotspot_x,
|
||||
.y = hotspot_y,
|
||||
};
|
||||
enum wl_output_transform transform =
|
||||
wlr_output_transform_invert(output->transform);
|
||||
struct wlr_box transformed_hotspot;
|
||||
wlr_box_transform(&hotspot, transform, &transformed_hotspot);
|
||||
wlr_box_transform(&hotspot, transform,
|
||||
plane->surf.width, plane->surf.height, &transformed_hotspot);
|
||||
plane->cursor_hotspot_x = transformed_hotspot.x;
|
||||
plane->cursor_hotspot_y = transformed_hotspot.y;
|
||||
|
||||
|
@ -650,15 +649,15 @@ static bool wlr_drm_connector_move_cursor(struct wlr_output *output,
|
|||
}
|
||||
struct wlr_drm_plane *plane = conn->crtc->cursor;
|
||||
|
||||
struct wlr_box box;
|
||||
box.x = x;
|
||||
box.y = y;
|
||||
wlr_output_effective_resolution(output, &box.width, &box.height);
|
||||
struct wlr_box box = { .x = x, .y = y };
|
||||
|
||||
int width, height;
|
||||
wlr_output_effective_resolution(output, &width, &height);
|
||||
|
||||
enum wl_output_transform transform =
|
||||
wlr_output_transform_invert(output->transform);
|
||||
struct wlr_box transformed_box;
|
||||
wlr_box_transform(&box, transform, &transformed_box);
|
||||
wlr_box_transform(&box, transform, width, height, &transformed_box);
|
||||
|
||||
if (plane != NULL) {
|
||||
transformed_box.x -= plane->cursor_hotspot_x;
|
||||
|
|
|
@ -54,14 +54,16 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
|
|||
|
||||
struct wlr_output *wlr_output = &wlr_wl_pointer->current_output->wlr_output;
|
||||
|
||||
struct wlr_box box;
|
||||
int width, height;
|
||||
wl_egl_window_get_attached_size(wlr_wl_pointer->current_output->egl_window,
|
||||
&box.width, &box.height);
|
||||
box.x = wl_fixed_to_int(surface_x);
|
||||
box.y = wl_fixed_to_int(surface_y);
|
||||
&width, &height);
|
||||
|
||||
struct wlr_box box = {
|
||||
.x = wl_fixed_to_int(surface_x),
|
||||
.y = wl_fixed_to_int(surface_y),
|
||||
};
|
||||
struct wlr_box transformed;
|
||||
wlr_box_transform(&box, wlr_output->transform, &transformed);
|
||||
wlr_box_transform(&box, wlr_output->transform, width, height, &transformed);
|
||||
transformed.x /= wlr_output->scale;
|
||||
transformed.y /= wlr_output->scale;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
/**
|
||||
* Damage tracking requires to keep track of previous frames' damage. To allow
|
||||
* damage tracking to work with triple buffering, an history of two frames is
|
||||
* damage tracking to work with triple buffering, a history of two frames is
|
||||
* required.
|
||||
*/
|
||||
#define ROOTS_OUTPUT_PREVIOUS_DAMAGE_LEN 2
|
||||
|
@ -22,7 +22,7 @@ struct roots_output {
|
|||
struct roots_view *fullscreen_view;
|
||||
|
||||
struct timespec last_frame;
|
||||
pixman_region32_t damage;
|
||||
pixman_region32_t damage; // in ouput-local coordinates
|
||||
bool frame_pending;
|
||||
|
||||
// circular queue for previous damage
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define WLR_TYPES_WLR_BOX_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
struct wlr_box {
|
||||
int x, y;
|
||||
|
@ -18,8 +19,11 @@ bool wlr_box_contains_point(const struct wlr_box *box, double x, double y);
|
|||
|
||||
bool wlr_box_empty(const struct wlr_box *box);
|
||||
|
||||
enum wl_output_transform;
|
||||
/**
|
||||
* Transforms a box inside a `width` x `height` box.
|
||||
*/
|
||||
void wlr_box_transform(const struct wlr_box *box,
|
||||
enum wl_output_transform transform, struct wlr_box *dest);
|
||||
enum wl_output_transform transform, int width, int height,
|
||||
struct wlr_box *dest);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -61,7 +61,8 @@ struct wlr_output {
|
|||
enum wl_output_transform transform;
|
||||
|
||||
bool needs_swap;
|
||||
pixman_region32_t damage; // damage for cursors and fullscreen surface
|
||||
// damage for cursors and fullscreen surface, in output-local coordinates
|
||||
pixman_region32_t damage;
|
||||
float transform_matrix[16];
|
||||
|
||||
struct {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define WLR_UTIL_REGION_H
|
||||
|
||||
#include <pixman.h>
|
||||
#include <wayland-server.h>
|
||||
|
||||
/**
|
||||
* Scales a region, ie. multiplies all its coordinates by `scale`.
|
||||
|
@ -12,4 +13,10 @@
|
|||
void wlr_region_scale(pixman_region32_t *dst, pixman_region32_t *src,
|
||||
float scale);
|
||||
|
||||
/**
|
||||
* Applies a transform to a region inside a box of size `width` x `height`.
|
||||
*/
|
||||
void wlr_region_transform(pixman_region32_t *dst, pixman_region32_t *src,
|
||||
enum wl_output_transform transform, int width, int height);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -170,6 +170,39 @@ static bool surface_intersect_output(struct wlr_surface *surface,
|
|||
return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box);
|
||||
}
|
||||
|
||||
static void output_get_transformed_size(struct wlr_output *wlr_output,
|
||||
int *width, int *height) {
|
||||
if (wlr_output->transform % 2 == 0) {
|
||||
*width = wlr_output->width;
|
||||
*height = wlr_output->height;
|
||||
} else {
|
||||
*width = wlr_output->height;
|
||||
*height = wlr_output->width;
|
||||
}
|
||||
}
|
||||
|
||||
static void scissor_output(struct roots_output *output, pixman_box32_t *rect) {
|
||||
struct wlr_output *wlr_output = output->wlr_output;
|
||||
|
||||
struct wlr_box box = {
|
||||
.x = rect->x1,
|
||||
.y = rect->y1,
|
||||
.width = rect->x2 - rect->x1,
|
||||
.height = rect->y2 - rect->y1,
|
||||
};
|
||||
|
||||
int ow, oh;
|
||||
output_get_transformed_size(output->wlr_output, &ow, &oh);
|
||||
|
||||
// Scissor is in renderer coordinates, ie. upside down
|
||||
enum wl_output_transform transform = wlr_output_transform_compose(
|
||||
wlr_output_transform_invert(wlr_output->transform),
|
||||
WL_OUTPUT_TRANSFORM_FLIPPED_180);
|
||||
wlr_box_transform(&box, transform, ow, oh, &box);
|
||||
|
||||
wlr_renderer_scissor(output->desktop->server->renderer, &box);
|
||||
}
|
||||
|
||||
static void render_surface(struct wlr_surface *surface, double lx, double ly,
|
||||
float rotation, void *_data) {
|
||||
struct render_data *data = _data;
|
||||
|
@ -187,7 +220,6 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly,
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: output transform support
|
||||
pixman_region32_t damage;
|
||||
pixman_region32_init(&damage);
|
||||
pixman_region32_union_rect(&damage, &damage, box.x, box.y,
|
||||
|
@ -205,16 +237,9 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly,
|
|||
&output->wlr_output->transform_matrix);
|
||||
|
||||
int nrects;
|
||||
pixman_box32_t *rects =
|
||||
pixman_region32_rectangles(&damage, &nrects);
|
||||
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
|
||||
for (int i = 0; i < nrects; ++i) {
|
||||
struct wlr_box scissor = {
|
||||
.x = rects[i].x1,
|
||||
.y = output->wlr_output->height - rects[i].y2,
|
||||
.width = rects[i].x2 - rects[i].x1,
|
||||
.height = rects[i].y2 - rects[i].y1,
|
||||
};
|
||||
wlr_renderer_scissor(output->desktop->server->renderer, &scissor);
|
||||
scissor_output(output, &rects[i]);
|
||||
wlr_render_with_matrix(output->desktop->server->renderer,
|
||||
surface->texture, &matrix);
|
||||
}
|
||||
|
@ -258,7 +283,6 @@ static void render_decorations(struct roots_view *view,
|
|||
struct wlr_box box;
|
||||
get_decoration_box(view, output, &box);
|
||||
|
||||
// TODO: output transform support
|
||||
pixman_region32_t damage;
|
||||
pixman_region32_init(&damage);
|
||||
pixman_region32_union_rect(&damage, &damage, box.x, box.y,
|
||||
|
@ -278,13 +302,7 @@ static void render_decorations(struct roots_view *view,
|
|||
pixman_box32_t *rects =
|
||||
pixman_region32_rectangles(&damage, &nrects);
|
||||
for (int i = 0; i < nrects; ++i) {
|
||||
struct wlr_box scissor = {
|
||||
.x = rects[i].x1,
|
||||
.y = output->wlr_output->height - rects[i].y2,
|
||||
.width = rects[i].x2 - rects[i].x1,
|
||||
.height = rects[i].y2 - rects[i].y1,
|
||||
};
|
||||
wlr_renderer_scissor(output->desktop->server->renderer, &scissor);
|
||||
scissor_output(output, &rects[i]);
|
||||
wlr_render_colored_quad(output->desktop->server->renderer, &color,
|
||||
&matrix);
|
||||
}
|
||||
|
@ -359,13 +377,15 @@ static void render_output(struct roots_output *output) {
|
|||
int buffer_age = -1;
|
||||
wlr_output_make_current(wlr_output, &buffer_age);
|
||||
|
||||
int width, height;
|
||||
output_get_transformed_size(output->wlr_output, &width, &height);
|
||||
|
||||
// Check if we can use damage tracking
|
||||
pixman_region32_t damage;
|
||||
pixman_region32_init(&damage);
|
||||
if (buffer_age <= 0 || buffer_age - 1 > ROOTS_OUTPUT_PREVIOUS_DAMAGE_LEN) {
|
||||
// Buffer new or too old, damage the whole output
|
||||
pixman_region32_union_rect(&damage, &damage, 0, 0,
|
||||
wlr_output->width, wlr_output->height);
|
||||
pixman_region32_union_rect(&damage, &damage, 0, 0, width, height);
|
||||
} else {
|
||||
pixman_region32_copy(&damage, &output->damage);
|
||||
|
||||
|
@ -376,8 +396,7 @@ static void render_output(struct roots_output *output) {
|
|||
pixman_region32_union(&damage, &damage, &output->previous_damage[j]);
|
||||
}
|
||||
}
|
||||
pixman_region32_intersect_rect(&damage, &damage, 0, 0,
|
||||
wlr_output->width, wlr_output->height);
|
||||
pixman_region32_intersect_rect(&damage, &damage, 0, 0, width, height);
|
||||
|
||||
if (!pixman_region32_not_empty(&damage) && !wlr_output->needs_swap) {
|
||||
// Output doesn't need swap and isn't damaged, skip rendering completely
|
||||
|
@ -401,13 +420,7 @@ static void render_output(struct roots_output *output) {
|
|||
int nrects;
|
||||
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
|
||||
for (int i = 0; i < nrects; ++i) {
|
||||
struct wlr_box scissor = {
|
||||
.x = rects[i].x1,
|
||||
.y = wlr_output->height - rects[i].y2,
|
||||
.width = rects[i].x2 - rects[i].x1,
|
||||
.height = rects[i].y2 - rects[i].y1,
|
||||
};
|
||||
wlr_renderer_scissor(output->desktop->server->renderer, &scissor);
|
||||
scissor_output(output, &rects[i]);
|
||||
wlr_renderer_clear(output->desktop->server->renderer,
|
||||
clear_color[0], clear_color[1], clear_color[2], 1);
|
||||
}
|
||||
|
@ -491,8 +504,11 @@ static void schedule_render(struct roots_output *output) {
|
|||
}
|
||||
|
||||
static void output_damage_whole(struct roots_output *output) {
|
||||
pixman_region32_union_rect(&output->damage, &output->damage,
|
||||
0, 0, output->wlr_output->width, output->wlr_output->height);
|
||||
int width, height;
|
||||
output_get_transformed_size(output->wlr_output, &width, &height);
|
||||
|
||||
pixman_region32_union_rect(&output->damage, &output->damage, 0, 0,
|
||||
width, height);
|
||||
|
||||
schedule_render(output);
|
||||
}
|
||||
|
@ -584,7 +600,6 @@ static void damage_from_surface(struct wlr_surface *surface,
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: output transform support
|
||||
pixman_region32_t damage;
|
||||
pixman_region32_init(&damage);
|
||||
pixman_region32_copy(&damage, &surface->current->surface_damage);
|
||||
|
|
|
@ -67,47 +67,50 @@ bool wlr_box_contains_point(const struct wlr_box *box, double x, double y) {
|
|||
}
|
||||
|
||||
void wlr_box_transform(const struct wlr_box *box,
|
||||
enum wl_output_transform transform, struct wlr_box *dest) {
|
||||
enum wl_output_transform transform, int width, int height,
|
||||
struct wlr_box *dest) {
|
||||
struct wlr_box src = *box;
|
||||
|
||||
if (transform % 2 == 0) {
|
||||
dest->width = box->width;
|
||||
dest->height = box->height;
|
||||
dest->width = src.width;
|
||||
dest->height = src.height;
|
||||
} else {
|
||||
dest->width = box->height;
|
||||
dest->height = box->width;
|
||||
dest->width = src.height;
|
||||
dest->height = src.width;
|
||||
}
|
||||
|
||||
switch (transform) {
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||
dest->x = box->x;
|
||||
dest->y = box->y;
|
||||
dest->x = src.x;
|
||||
dest->y = src.y;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
dest->x = box->y;
|
||||
dest->y = box->width - box->x;
|
||||
dest->x = src.y;
|
||||
dest->y = width - src.x - src.width;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
dest->x = box->width - box->x;
|
||||
dest->y = box->height - box->y;
|
||||
dest->x = width - src.x - src.width;
|
||||
dest->y = height - src.y - src.height;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
dest->x = box->height - box->y;
|
||||
dest->y = box->x;
|
||||
dest->x = height - src.y - src.height;
|
||||
dest->y = src.x;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||
dest->x = box->width - box->x;
|
||||
dest->y = box->y;
|
||||
dest->x = width - src.x - src.width;
|
||||
dest->y = src.y;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
dest->x = box->height - box->y;
|
||||
dest->y = box->width - box->x;
|
||||
dest->x = height - src.y - src.height;
|
||||
dest->y = width - src.x - src.width;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
dest->x = box->x;
|
||||
dest->y = box->height - box->y;
|
||||
dest->x = src.x;
|
||||
dest->y = height - src.y - src.height;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
dest->x = box->y;
|
||||
dest->y = box->x;
|
||||
dest->x = src.y;
|
||||
dest->y = src.x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <wlr/render/matrix.h>
|
||||
#include <wlr/render/gles2.h>
|
||||
#include <wlr/render.h>
|
||||
#include <wlr/util/region.h>
|
||||
|
||||
static void wl_output_send_to_resource(struct wl_resource *resource) {
|
||||
assert(resource);
|
||||
|
@ -554,6 +555,7 @@ static void output_fullscreen_surface_handle_commit(
|
|||
pixman_region32_t damage;
|
||||
pixman_region32_init(&damage);
|
||||
pixman_region32_copy(&damage, &surface->current->surface_damage);
|
||||
wlr_region_scale(&damage, &damage, output->scale);
|
||||
pixman_region32_translate(&damage, box.x, box.y);
|
||||
pixman_region32_union(&output->damage, &output->damage, &damage);
|
||||
pixman_region32_fini(&damage);
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <wlr/util/region.h>
|
||||
#include <wlr/render/interface.h>
|
||||
#include <wlr/types/wlr_surface.h>
|
||||
#include <wlr/render/egl.h>
|
||||
|
@ -185,85 +186,6 @@ static bool wlr_surface_update_size(struct wlr_surface *surface,
|
|||
return update_damage;
|
||||
}
|
||||
|
||||
static void wlr_surface_to_buffer_region(int scale,
|
||||
enum wl_output_transform transform, pixman_region32_t *surface_region,
|
||||
pixman_region32_t *buffer_region, int width, int height) {
|
||||
int nrects;
|
||||
pixman_box32_t *src_rects =
|
||||
pixman_region32_rectangles(surface_region, &nrects);
|
||||
pixman_box32_t *dest_rects = malloc(nrects * sizeof(*dest_rects));
|
||||
if (dest_rects == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nrects; i++) {
|
||||
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 (int 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);
|
||||
pixman_region32_init_rects(buffer_region, dest_rects, nrects);
|
||||
free(dest_rects);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append pending state to current state and clear pending state.
|
||||
*/
|
||||
|
@ -314,9 +236,11 @@ static void wlr_surface_move_state(struct wlr_surface *surface,
|
|||
if (update_damage) {
|
||||
pixman_region32_t buffer_damage;
|
||||
pixman_region32_init(&buffer_damage);
|
||||
wlr_surface_to_buffer_region(state->scale, state->transform,
|
||||
&state->surface_damage, &buffer_damage, state->width,
|
||||
state->height);
|
||||
pixman_region32_copy(&buffer_damage, &state->surface_damage);
|
||||
wlr_region_transform(&buffer_damage, &buffer_damage,
|
||||
wlr_output_transform_invert(state->transform),
|
||||
state->width, state->height);
|
||||
wlr_region_scale(&buffer_damage, &buffer_damage, state->scale);
|
||||
pixman_region32_union(&state->buffer_damage,
|
||||
&state->buffer_damage, &buffer_damage);
|
||||
pixman_region32_fini(&buffer_damage);
|
||||
|
|
|
@ -6,5 +6,5 @@ lib_wlr_util = static_library(
|
|||
'region.c',
|
||||
),
|
||||
include_directories: wlr_inc,
|
||||
dependencies: [pixman],
|
||||
dependencies: [wayland_server, pixman],
|
||||
)
|
||||
|
|
|
@ -26,4 +26,78 @@ void wlr_region_scale(pixman_region32_t *dst, pixman_region32_t *src,
|
|||
|
||||
pixman_region32_fini(dst);
|
||||
pixman_region32_init_rects(dst, dst_rects, nrects);
|
||||
free(dst_rects);
|
||||
}
|
||||
|
||||
void wlr_region_transform(pixman_region32_t *dst, pixman_region32_t *src,
|
||||
enum wl_output_transform transform, int width, int height) {
|
||||
if (transform == WL_OUTPUT_TRANSFORM_NORMAL) {
|
||||
pixman_region32_copy(dst, src);
|
||||
return;
|
||||
}
|
||||
|
||||
int nrects;
|
||||
pixman_box32_t *src_rects = pixman_region32_rectangles(src, &nrects);
|
||||
|
||||
pixman_box32_t *dst_rects = malloc(nrects * sizeof(pixman_box32_t));
|
||||
if (dst_rects == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nrects; ++i) {
|
||||
switch (transform) {
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||
dst_rects[i].x1 = src_rects[i].x1;
|
||||
dst_rects[i].y1 = src_rects[i].y1;
|
||||
dst_rects[i].x2 = src_rects[i].x2;
|
||||
dst_rects[i].y2 = src_rects[i].y2;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_90:
|
||||
dst_rects[i].x1 = src_rects[i].y1;
|
||||
dst_rects[i].y1 = width - src_rects[i].x2;
|
||||
dst_rects[i].x2 = src_rects[i].y2;
|
||||
dst_rects[i].y2 = width - src_rects[i].x1;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_180:
|
||||
dst_rects[i].x1 = width - src_rects[i].x2;
|
||||
dst_rects[i].y1 = height - src_rects[i].y2;
|
||||
dst_rects[i].x2 = width - src_rects[i].x1;
|
||||
dst_rects[i].y2 = height - src_rects[i].y1;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_270:
|
||||
dst_rects[i].x1 = height - src_rects[i].y2;
|
||||
dst_rects[i].y1 = src_rects[i].x1;
|
||||
dst_rects[i].x2 = height - src_rects[i].y1;
|
||||
dst_rects[i].y2 = src_rects[i].x2;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||
dst_rects[i].x1 = width - src_rects[i].x2;
|
||||
dst_rects[i].y1 = src_rects[i].y1;
|
||||
dst_rects[i].x2 = width - src_rects[i].x1;
|
||||
dst_rects[i].y2 = src_rects[i].y2;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||
dst_rects[i].x1 = height - src_rects[i].y2;
|
||||
dst_rects[i].y1 = width - src_rects[i].x2;
|
||||
dst_rects[i].x2 = height - src_rects[i].y1;
|
||||
dst_rects[i].y2 = width - src_rects[i].x1;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||
dst_rects[i].x1 = src_rects[i].x1;
|
||||
dst_rects[i].y1 = height - src_rects[i].y2;
|
||||
dst_rects[i].x2 = src_rects[i].x2;
|
||||
dst_rects[i].y2 = height - src_rects[i].y1;
|
||||
break;
|
||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||
dst_rects[i].x1 = src_rects[i].y1;
|
||||
dst_rects[i].y1 = src_rects[i].x1;
|
||||
dst_rects[i].x2 = src_rects[i].y2;
|
||||
dst_rects[i].y2 = src_rects[i].x2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pixman_region32_fini(dst);
|
||||
pixman_region32_init_rects(dst, dst_rects, nrects);
|
||||
free(dst_rects);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue