Damage tracking for transformed outputs
This commit is contained in:
parent
a98ece68d3
commit
ece2c1e4e2
|
@ -581,15 +581,14 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_box hotspot = {
|
struct wlr_box hotspot = {
|
||||||
.width = plane->surf.width,
|
|
||||||
.height = plane->surf.height,
|
|
||||||
.x = hotspot_x,
|
.x = hotspot_x,
|
||||||
.y = hotspot_y,
|
.y = hotspot_y,
|
||||||
};
|
};
|
||||||
enum wl_output_transform transform =
|
enum wl_output_transform transform =
|
||||||
wlr_output_transform_invert(output->transform);
|
wlr_output_transform_invert(output->transform);
|
||||||
struct wlr_box transformed_hotspot;
|
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_x = transformed_hotspot.x;
|
||||||
plane->cursor_hotspot_y = transformed_hotspot.y;
|
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_drm_plane *plane = conn->crtc->cursor;
|
||||||
|
|
||||||
struct wlr_box box;
|
struct wlr_box box = { .x = x, .y = y };
|
||||||
box.x = x;
|
|
||||||
box.y = y;
|
int width, height;
|
||||||
wlr_output_effective_resolution(output, &box.width, &box.height);
|
wlr_output_effective_resolution(output, &width, &height);
|
||||||
|
|
||||||
enum wl_output_transform transform =
|
enum wl_output_transform transform =
|
||||||
wlr_output_transform_invert(output->transform);
|
wlr_output_transform_invert(output->transform);
|
||||||
struct wlr_box transformed_box;
|
struct wlr_box transformed_box;
|
||||||
wlr_box_transform(&box, transform, &transformed_box);
|
wlr_box_transform(&box, transform, width, height, &transformed_box);
|
||||||
|
|
||||||
if (plane != NULL) {
|
if (plane != NULL) {
|
||||||
transformed_box.x -= plane->cursor_hotspot_x;
|
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_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,
|
wl_egl_window_get_attached_size(wlr_wl_pointer->current_output->egl_window,
|
||||||
&box.width, &box.height);
|
&width, &height);
|
||||||
box.x = wl_fixed_to_int(surface_x);
|
|
||||||
box.y = wl_fixed_to_int(surface_y);
|
|
||||||
|
|
||||||
|
struct wlr_box box = {
|
||||||
|
.x = wl_fixed_to_int(surface_x),
|
||||||
|
.y = wl_fixed_to_int(surface_y),
|
||||||
|
};
|
||||||
struct wlr_box transformed;
|
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.x /= wlr_output->scale;
|
||||||
transformed.y /= 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 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.
|
* required.
|
||||||
*/
|
*/
|
||||||
#define ROOTS_OUTPUT_PREVIOUS_DAMAGE_LEN 2
|
#define ROOTS_OUTPUT_PREVIOUS_DAMAGE_LEN 2
|
||||||
|
@ -22,7 +22,7 @@ struct roots_output {
|
||||||
struct roots_view *fullscreen_view;
|
struct roots_view *fullscreen_view;
|
||||||
|
|
||||||
struct timespec last_frame;
|
struct timespec last_frame;
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage; // in ouput-local coordinates
|
||||||
bool frame_pending;
|
bool frame_pending;
|
||||||
|
|
||||||
// circular queue for previous damage
|
// circular queue for previous damage
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define WLR_TYPES_WLR_BOX_H
|
#define WLR_TYPES_WLR_BOX_H
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <wayland-server.h>
|
||||||
|
|
||||||
struct wlr_box {
|
struct wlr_box {
|
||||||
int x, y;
|
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);
|
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,
|
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
|
#endif
|
||||||
|
|
|
@ -61,7 +61,8 @@ struct wlr_output {
|
||||||
enum wl_output_transform transform;
|
enum wl_output_transform transform;
|
||||||
|
|
||||||
bool needs_swap;
|
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];
|
float transform_matrix[16];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define WLR_UTIL_REGION_H
|
#define WLR_UTIL_REGION_H
|
||||||
|
|
||||||
#include <pixman.h>
|
#include <pixman.h>
|
||||||
|
#include <wayland-server.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scales a region, ie. multiplies all its coordinates by `scale`.
|
* 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,
|
void wlr_region_scale(pixman_region32_t *dst, pixman_region32_t *src,
|
||||||
float scale);
|
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
|
#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);
|
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,
|
static void render_surface(struct wlr_surface *surface, double lx, double ly,
|
||||||
float rotation, void *_data) {
|
float rotation, void *_data) {
|
||||||
struct render_data *data = _data;
|
struct render_data *data = _data;
|
||||||
|
@ -187,7 +220,6 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: output transform support
|
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
pixman_region32_init(&damage);
|
pixman_region32_init(&damage);
|
||||||
pixman_region32_union_rect(&damage, &damage, box.x, box.y,
|
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);
|
&output->wlr_output->transform_matrix);
|
||||||
|
|
||||||
int nrects;
|
int nrects;
|
||||||
pixman_box32_t *rects =
|
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
|
||||||
pixman_region32_rectangles(&damage, &nrects);
|
|
||||||
for (int i = 0; i < nrects; ++i) {
|
for (int i = 0; i < nrects; ++i) {
|
||||||
struct wlr_box scissor = {
|
scissor_output(output, &rects[i]);
|
||||||
.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);
|
|
||||||
wlr_render_with_matrix(output->desktop->server->renderer,
|
wlr_render_with_matrix(output->desktop->server->renderer,
|
||||||
surface->texture, &matrix);
|
surface->texture, &matrix);
|
||||||
}
|
}
|
||||||
|
@ -258,7 +283,6 @@ static void render_decorations(struct roots_view *view,
|
||||||
struct wlr_box box;
|
struct wlr_box box;
|
||||||
get_decoration_box(view, output, &box);
|
get_decoration_box(view, output, &box);
|
||||||
|
|
||||||
// TODO: output transform support
|
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
pixman_region32_init(&damage);
|
pixman_region32_init(&damage);
|
||||||
pixman_region32_union_rect(&damage, &damage, box.x, box.y,
|
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_box32_t *rects =
|
||||||
pixman_region32_rectangles(&damage, &nrects);
|
pixman_region32_rectangles(&damage, &nrects);
|
||||||
for (int i = 0; i < nrects; ++i) {
|
for (int i = 0; i < nrects; ++i) {
|
||||||
struct wlr_box scissor = {
|
scissor_output(output, &rects[i]);
|
||||||
.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);
|
|
||||||
wlr_render_colored_quad(output->desktop->server->renderer, &color,
|
wlr_render_colored_quad(output->desktop->server->renderer, &color,
|
||||||
&matrix);
|
&matrix);
|
||||||
}
|
}
|
||||||
|
@ -359,13 +377,15 @@ static void render_output(struct roots_output *output) {
|
||||||
int buffer_age = -1;
|
int buffer_age = -1;
|
||||||
wlr_output_make_current(wlr_output, &buffer_age);
|
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
|
// Check if we can use damage tracking
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
pixman_region32_init(&damage);
|
pixman_region32_init(&damage);
|
||||||
if (buffer_age <= 0 || buffer_age - 1 > ROOTS_OUTPUT_PREVIOUS_DAMAGE_LEN) {
|
if (buffer_age <= 0 || buffer_age - 1 > ROOTS_OUTPUT_PREVIOUS_DAMAGE_LEN) {
|
||||||
// Buffer new or too old, damage the whole output
|
// Buffer new or too old, damage the whole output
|
||||||
pixman_region32_union_rect(&damage, &damage, 0, 0,
|
pixman_region32_union_rect(&damage, &damage, 0, 0, width, height);
|
||||||
wlr_output->width, wlr_output->height);
|
|
||||||
} else {
|
} else {
|
||||||
pixman_region32_copy(&damage, &output->damage);
|
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_union(&damage, &damage, &output->previous_damage[j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pixman_region32_intersect_rect(&damage, &damage, 0, 0,
|
pixman_region32_intersect_rect(&damage, &damage, 0, 0, width, height);
|
||||||
wlr_output->width, wlr_output->height);
|
|
||||||
|
|
||||||
if (!pixman_region32_not_empty(&damage) && !wlr_output->needs_swap) {
|
if (!pixman_region32_not_empty(&damage) && !wlr_output->needs_swap) {
|
||||||
// Output doesn't need swap and isn't damaged, skip rendering completely
|
// 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;
|
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) {
|
for (int i = 0; i < nrects; ++i) {
|
||||||
struct wlr_box scissor = {
|
scissor_output(output, &rects[i]);
|
||||||
.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);
|
|
||||||
wlr_renderer_clear(output->desktop->server->renderer,
|
wlr_renderer_clear(output->desktop->server->renderer,
|
||||||
clear_color[0], clear_color[1], clear_color[2], 1);
|
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) {
|
static void output_damage_whole(struct roots_output *output) {
|
||||||
pixman_region32_union_rect(&output->damage, &output->damage,
|
int width, height;
|
||||||
0, 0, output->wlr_output->width, output->wlr_output->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);
|
schedule_render(output);
|
||||||
}
|
}
|
||||||
|
@ -584,7 +600,6 @@ static void damage_from_surface(struct wlr_surface *surface,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: output transform support
|
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
pixman_region32_init(&damage);
|
pixman_region32_init(&damage);
|
||||||
pixman_region32_copy(&damage, &surface->current->surface_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,
|
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) {
|
if (transform % 2 == 0) {
|
||||||
dest->width = box->width;
|
dest->width = src.width;
|
||||||
dest->height = box->height;
|
dest->height = src.height;
|
||||||
} else {
|
} else {
|
||||||
dest->width = box->height;
|
dest->width = src.height;
|
||||||
dest->height = box->width;
|
dest->height = src.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (transform) {
|
switch (transform) {
|
||||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||||
dest->x = box->x;
|
dest->x = src.x;
|
||||||
dest->y = box->y;
|
dest->y = src.y;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_90:
|
case WL_OUTPUT_TRANSFORM_90:
|
||||||
dest->x = box->y;
|
dest->x = src.y;
|
||||||
dest->y = box->width - box->x;
|
dest->y = width - src.x - src.width;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_180:
|
case WL_OUTPUT_TRANSFORM_180:
|
||||||
dest->x = box->width - box->x;
|
dest->x = width - src.x - src.width;
|
||||||
dest->y = box->height - box->y;
|
dest->y = height - src.y - src.height;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_270:
|
case WL_OUTPUT_TRANSFORM_270:
|
||||||
dest->x = box->height - box->y;
|
dest->x = height - src.y - src.height;
|
||||||
dest->y = box->x;
|
dest->y = src.x;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
case WL_OUTPUT_TRANSFORM_FLIPPED:
|
||||||
dest->x = box->width - box->x;
|
dest->x = width - src.x - src.width;
|
||||||
dest->y = box->y;
|
dest->y = src.y;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
|
||||||
dest->x = box->height - box->y;
|
dest->x = height - src.y - src.height;
|
||||||
dest->y = box->width - box->x;
|
dest->y = width - src.x - src.width;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
case WL_OUTPUT_TRANSFORM_FLIPPED_180:
|
||||||
dest->x = box->x;
|
dest->x = src.x;
|
||||||
dest->y = box->height - box->y;
|
dest->y = height - src.y - src.height;
|
||||||
break;
|
break;
|
||||||
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
case WL_OUTPUT_TRANSFORM_FLIPPED_270:
|
||||||
dest->x = box->y;
|
dest->x = src.y;
|
||||||
dest->y = box->x;
|
dest->y = src.x;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <wlr/render/matrix.h>
|
#include <wlr/render/matrix.h>
|
||||||
#include <wlr/render/gles2.h>
|
#include <wlr/render/gles2.h>
|
||||||
#include <wlr/render.h>
|
#include <wlr/render.h>
|
||||||
|
#include <wlr/util/region.h>
|
||||||
|
|
||||||
static void wl_output_send_to_resource(struct wl_resource *resource) {
|
static void wl_output_send_to_resource(struct wl_resource *resource) {
|
||||||
assert(resource);
|
assert(resource);
|
||||||
|
@ -554,6 +555,7 @@ static void output_fullscreen_surface_handle_commit(
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
pixman_region32_init(&damage);
|
pixman_region32_init(&damage);
|
||||||
pixman_region32_copy(&damage, &surface->current->surface_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_translate(&damage, box.x, box.y);
|
||||||
pixman_region32_union(&output->damage, &output->damage, &damage);
|
pixman_region32_union(&output->damage, &output->damage, &damage);
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <wayland-server.h>
|
#include <wayland-server.h>
|
||||||
#include <wlr/util/log.h>
|
#include <wlr/util/log.h>
|
||||||
|
#include <wlr/util/region.h>
|
||||||
#include <wlr/render/interface.h>
|
#include <wlr/render/interface.h>
|
||||||
#include <wlr/types/wlr_surface.h>
|
#include <wlr/types/wlr_surface.h>
|
||||||
#include <wlr/render/egl.h>
|
#include <wlr/render/egl.h>
|
||||||
|
@ -185,85 +186,6 @@ static bool wlr_surface_update_size(struct wlr_surface *surface,
|
||||||
return update_damage;
|
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.
|
* 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) {
|
if (update_damage) {
|
||||||
pixman_region32_t buffer_damage;
|
pixman_region32_t buffer_damage;
|
||||||
pixman_region32_init(&buffer_damage);
|
pixman_region32_init(&buffer_damage);
|
||||||
wlr_surface_to_buffer_region(state->scale, state->transform,
|
pixman_region32_copy(&buffer_damage, &state->surface_damage);
|
||||||
&state->surface_damage, &buffer_damage, state->width,
|
wlr_region_transform(&buffer_damage, &buffer_damage,
|
||||||
state->height);
|
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,
|
pixman_region32_union(&state->buffer_damage,
|
||||||
&state->buffer_damage, &buffer_damage);
|
&state->buffer_damage, &buffer_damage);
|
||||||
pixman_region32_fini(&buffer_damage);
|
pixman_region32_fini(&buffer_damage);
|
||||||
|
|
|
@ -6,5 +6,5 @@ lib_wlr_util = static_library(
|
||||||
'region.c',
|
'region.c',
|
||||||
),
|
),
|
||||||
include_directories: wlr_inc,
|
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_fini(dst);
|
||||||
pixman_region32_init_rects(dst, dst_rects, nrects);
|
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 New Issue