mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-04-13 08:22:16 -04:00
Merge branch 'fractional-scene-wip' into 'master'
scene: use position independent scaling Closes #3793, #3705, #3792, and #3139 See merge request wlroots/wlroots!5071
This commit is contained in:
commit
8eabe2eeea
11 changed files with 465 additions and 223 deletions
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node);
|
struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node);
|
||||||
|
|
||||||
void scene_node_get_size(struct wlr_scene_node *node, int *width, int *height);
|
void scene_node_get_size(struct wlr_scene_node *node, double *width, double *height);
|
||||||
|
|
||||||
void scene_surface_set_clip(struct wlr_scene_surface *surface, struct wlr_box *clip);
|
void scene_surface_set_clip(struct wlr_scene_surface *surface, struct wlr_box *clip);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ typedef bool (*wlr_scene_buffer_point_accepts_input_func_t)(
|
||||||
struct wlr_scene_buffer *buffer, double *sx, double *sy);
|
struct wlr_scene_buffer *buffer, double *sx, double *sy);
|
||||||
|
|
||||||
typedef void (*wlr_scene_buffer_iterator_func_t)(
|
typedef void (*wlr_scene_buffer_iterator_func_t)(
|
||||||
struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data);
|
struct wlr_scene_buffer *buffer, double sx, double sy, void *user_data);
|
||||||
|
|
||||||
enum wlr_scene_node_type {
|
enum wlr_scene_node_type {
|
||||||
WLR_SCENE_NODE_TREE,
|
WLR_SCENE_NODE_TREE,
|
||||||
|
|
@ -66,18 +66,19 @@ struct wlr_scene_node {
|
||||||
struct wl_list link; // wlr_scene_tree.children
|
struct wl_list link; // wlr_scene_tree.children
|
||||||
|
|
||||||
bool enabled;
|
bool enabled;
|
||||||
int x, y; // relative to parent
|
double x, y; // relative to parent
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
} events;
|
} events;
|
||||||
|
|
||||||
|
bool scaling_group;
|
||||||
void *data;
|
void *data;
|
||||||
|
|
||||||
struct wlr_addon_set addons;
|
struct wlr_addon_set addons;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
pixman_region32_t visible;
|
pixman_region64f_t visible;
|
||||||
} WLR_PRIVATE;
|
} WLR_PRIVATE;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -141,7 +142,7 @@ struct wlr_scene_surface {
|
||||||
/** A scene-graph node displaying a solid-colored rectangle */
|
/** A scene-graph node displaying a solid-colored rectangle */
|
||||||
struct wlr_scene_rect {
|
struct wlr_scene_rect {
|
||||||
struct wlr_scene_node node;
|
struct wlr_scene_node node;
|
||||||
int width, height;
|
double width, height;
|
||||||
float color[4];
|
float color[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -188,9 +189,9 @@ struct wlr_scene_buffer {
|
||||||
float opacity;
|
float opacity;
|
||||||
enum wlr_scale_filter_mode filter_mode;
|
enum wlr_scale_filter_mode filter_mode;
|
||||||
struct wlr_fbox src_box;
|
struct wlr_fbox src_box;
|
||||||
int dst_width, dst_height;
|
double dst_width, dst_height;
|
||||||
enum wl_output_transform transform;
|
enum wl_output_transform transform;
|
||||||
pixman_region32_t opaque_region;
|
pixman_region64f_t opaque_region;
|
||||||
enum wlr_color_transfer_function transfer_function;
|
enum wlr_color_transfer_function transfer_function;
|
||||||
enum wlr_color_named_primaries primaries;
|
enum wlr_color_named_primaries primaries;
|
||||||
enum wlr_color_encoding color_encoding;
|
enum wlr_color_encoding color_encoding;
|
||||||
|
|
@ -228,7 +229,7 @@ struct wlr_scene_output {
|
||||||
|
|
||||||
struct wlr_damage_ring damage_ring;
|
struct wlr_damage_ring damage_ring;
|
||||||
|
|
||||||
int x, y;
|
double x, y;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
struct wl_signal destroy;
|
struct wl_signal destroy;
|
||||||
|
|
@ -301,7 +302,7 @@ void wlr_scene_node_set_enabled(struct wlr_scene_node *node, bool enabled);
|
||||||
/**
|
/**
|
||||||
* Set the position of the node relative to its parent.
|
* Set the position of the node relative to its parent.
|
||||||
*/
|
*/
|
||||||
void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y);
|
void wlr_scene_node_set_position(struct wlr_scene_node *node, double x, double y);
|
||||||
/**
|
/**
|
||||||
* Move the node right above the specified sibling.
|
* Move the node right above the specified sibling.
|
||||||
* Asserts that node and sibling are distinct and share the same parent.
|
* Asserts that node and sibling are distinct and share the same parent.
|
||||||
|
|
@ -332,7 +333,7 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node,
|
||||||
*
|
*
|
||||||
* True is returned if the node and all of its ancestors are enabled.
|
* True is returned if the node and all of its ancestors are enabled.
|
||||||
*/
|
*/
|
||||||
bool wlr_scene_node_coords(struct wlr_scene_node *node, int *lx, int *ly);
|
bool wlr_scene_node_coords(struct wlr_scene_node *node, double *lx, double *ly);
|
||||||
/**
|
/**
|
||||||
* Call `iterator` on each buffer in the scene-graph, with the buffer's
|
* Call `iterator` on each buffer in the scene-graph, with the buffer's
|
||||||
* position in layout coordinates. The function is called from root to leaves
|
* position in layout coordinates. The function is called from root to leaves
|
||||||
|
|
@ -453,12 +454,12 @@ void wlr_scene_surface_send_frame_done(struct wlr_scene_surface *scene_surface,
|
||||||
* The color argument must be a premultiplied color value.
|
* The color argument must be a premultiplied color value.
|
||||||
*/
|
*/
|
||||||
struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent,
|
struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent,
|
||||||
int width, int height, const float color[static 4]);
|
double width, double height, const float color[static 4]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the width and height of an existing rectangle node.
|
* Change the width and height of an existing rectangle node.
|
||||||
*/
|
*/
|
||||||
void wlr_scene_rect_set_size(struct wlr_scene_rect *rect, int width, int height);
|
void wlr_scene_rect_set_size(struct wlr_scene_rect *rect, double width, double height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the color of an existing rectangle node.
|
* Change the color of an existing rectangle node.
|
||||||
|
|
@ -519,7 +520,7 @@ void wlr_scene_buffer_set_buffer_with_options(struct wlr_scene_buffer *scene_buf
|
||||||
* determine if buffers which reside under this one need to be rendered or not.
|
* determine if buffers which reside under this one need to be rendered or not.
|
||||||
*/
|
*/
|
||||||
void wlr_scene_buffer_set_opaque_region(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_buffer_set_opaque_region(struct wlr_scene_buffer *scene_buffer,
|
||||||
const pixman_region32_t *region);
|
const pixman_region64f_t *region);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the source rectangle describing the region of the buffer which will be
|
* Set the source rectangle describing the region of the buffer which will be
|
||||||
|
|
@ -538,7 +539,7 @@ void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer,
|
||||||
* destination size is zero.
|
* destination size is zero.
|
||||||
*/
|
*/
|
||||||
void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer,
|
||||||
int width, int height);
|
double width, double height);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a transform which will be applied to the buffer.
|
* Set a transform which will be applied to the buffer.
|
||||||
|
|
@ -591,7 +592,7 @@ void wlr_scene_output_destroy(struct wlr_scene_output *scene_output);
|
||||||
* Set the output's position in the scene-graph.
|
* Set the output's position in the scene-graph.
|
||||||
*/
|
*/
|
||||||
void wlr_scene_output_set_position(struct wlr_scene_output *scene_output,
|
void wlr_scene_output_set_position(struct wlr_scene_output *scene_output,
|
||||||
int lx, int ly);
|
double lx, double ly);
|
||||||
|
|
||||||
struct wlr_scene_output_state_options {
|
struct wlr_scene_output_state_options {
|
||||||
struct wlr_scene_timer *timer;
|
struct wlr_scene_timer *timer;
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,14 @@ void wlr_box_closest_point(const struct wlr_box *box, double x, double y,
|
||||||
bool wlr_box_intersection(struct wlr_box *dest, const struct wlr_box *box_a,
|
bool wlr_box_intersection(struct wlr_box *dest, const struct wlr_box *box_a,
|
||||||
const struct wlr_box *box_b);
|
const struct wlr_box *box_b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gives the intersecting box between two struct wlr_fbox.
|
||||||
|
*
|
||||||
|
* Returns an empty box if the provided boxes don't intersect.
|
||||||
|
*/
|
||||||
|
bool wlr_fbox_intersection(struct wlr_fbox *dest, const struct wlr_fbox *box_a,
|
||||||
|
const struct wlr_fbox *box_b);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies if a point is contained within the bounds of a given struct wlr_box.
|
* Verifies if a point is contained within the bounds of a given struct wlr_box.
|
||||||
*
|
*
|
||||||
|
|
@ -79,6 +87,14 @@ bool wlr_box_contains_point(const struct wlr_box *box, double x, double y);
|
||||||
*/
|
*/
|
||||||
bool wlr_box_contains_box(const struct wlr_box *bigger, const struct wlr_box *smaller);
|
bool wlr_box_contains_box(const struct wlr_box *bigger, const struct wlr_box *smaller);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that a box is fully contained within another box.
|
||||||
|
*
|
||||||
|
* Returns true if the "smaller" box is fully contained within the "bigger" box.
|
||||||
|
* If either of the boxes are empty, false is returned.
|
||||||
|
*/
|
||||||
|
bool wlr_fbox_contains_box(const struct wlr_fbox *bigger, const struct wlr_fbox *smaller);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether a box is empty or not.
|
* Checks whether a box is empty or not.
|
||||||
*
|
*
|
||||||
|
|
@ -114,6 +130,13 @@ void wlr_fbox_transform(struct wlr_fbox *dest, const struct wlr_fbox *box,
|
||||||
*/
|
*/
|
||||||
bool wlr_box_intersects(const struct wlr_box *a, const struct wlr_box *b);
|
bool wlr_box_intersects(const struct wlr_box *a, const struct wlr_box *b);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether two boxes intersect.
|
||||||
|
*
|
||||||
|
* Returns false if either box is empty.
|
||||||
|
*/
|
||||||
|
bool wlr_fbox_intersects(const struct wlr_fbox *a, const struct wlr_fbox *b);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the two boxes are equal, false otherwise.
|
* Returns true if the two boxes are equal, false otherwise.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,31 @@ void wlr_region_scale(pixman_region32_t *dst, const pixman_region32_t *src,
|
||||||
void wlr_region_scale_xy(pixman_region32_t *dst, const pixman_region32_t *src,
|
void wlr_region_scale_xy(pixman_region32_t *dst, const pixman_region32_t *src,
|
||||||
float scale_x, float scale_y);
|
float scale_x, float scale_y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale a fractional region by the specified factor.
|
||||||
|
*
|
||||||
|
* The resulting coordinates are rounded to nearest integer.
|
||||||
|
*
|
||||||
|
* Also see wlr_region_scalef_xy().
|
||||||
|
*/
|
||||||
|
void wlr_region_scalef(pixman_region32_t *dst, const pixman_region64f_t *src,
|
||||||
|
float scale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scale a region by the specified factors.
|
||||||
|
*
|
||||||
|
* The X and Y coordinates are scaled separately by scale_x and scale_y.
|
||||||
|
*
|
||||||
|
* The resulting coordinates are rounded to nearest integer.
|
||||||
|
*/
|
||||||
|
void wlr_region_scalef_xy(pixman_region32_t *dst, const pixman_region64f_t *src,
|
||||||
|
float scale_x, float scale_y);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy an integer region into a fractional region.
|
||||||
|
*/
|
||||||
|
void wlr_region64f_copy_from_region32(pixman_region64f_t *dst, const pixman_region32_t *src);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a transform to a region inside a box of size `width` x `height`.
|
* Applies a transform to a region inside a box of size `width` x `height`.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ xkbcommon = dependency('xkbcommon',
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
pixman = dependency('pixman-1',
|
pixman = dependency('pixman-1',
|
||||||
version: '>=0.43.0',
|
version: '>=0.46.2',
|
||||||
fallback: 'pixman',
|
fallback: 'pixman',
|
||||||
default_options: ['werror=false'],
|
default_options: ['werror=false'],
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ static void bench_scene_node_at(struct wlr_scene *scene, struct tree_spec *spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void noop_iterator(struct wlr_scene_buffer *buffer,
|
static void noop_iterator(struct wlr_scene_buffer *buffer,
|
||||||
int sx, int sy, void *user_data) {
|
double sx, double sy, void *user_data) {
|
||||||
(void)buffer;
|
(void)buffer;
|
||||||
(void)sx;
|
(void)sx;
|
||||||
(void)sy;
|
(void)sy;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ struct scene_node_source_frame_event {
|
||||||
|
|
||||||
static size_t last_output_num = 0;
|
static size_t last_output_num = 0;
|
||||||
|
|
||||||
static void _get_scene_node_extents(struct wlr_scene_node *node, struct wlr_box *box, int lx, int ly) {
|
static void _get_scene_node_extents(struct wlr_scene_node *node, struct wlr_fbox *box, double lx, double ly) {
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
case WLR_SCENE_NODE_TREE:;
|
case WLR_SCENE_NODE_TREE:;
|
||||||
struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node);
|
struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node);
|
||||||
|
|
@ -45,7 +45,7 @@ static void _get_scene_node_extents(struct wlr_scene_node *node, struct wlr_box
|
||||||
break;
|
break;
|
||||||
case WLR_SCENE_NODE_RECT:
|
case WLR_SCENE_NODE_RECT:
|
||||||
case WLR_SCENE_NODE_BUFFER:;
|
case WLR_SCENE_NODE_BUFFER:;
|
||||||
struct wlr_box node_box = { .x = lx, .y = ly };
|
struct wlr_fbox node_box = { .x = lx, .y = ly };
|
||||||
scene_node_get_size(node, &node_box.width, &node_box.height);
|
scene_node_get_size(node, &node_box.width, &node_box.height);
|
||||||
|
|
||||||
if (node_box.x < box->x) {
|
if (node_box.x < box->x) {
|
||||||
|
|
@ -64,9 +64,9 @@ static void _get_scene_node_extents(struct wlr_scene_node *node, struct wlr_box
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void get_scene_node_extents(struct wlr_scene_node *node, struct wlr_box *box) {
|
static void get_scene_node_extents(struct wlr_scene_node *node, struct wlr_fbox *box) {
|
||||||
*box = (struct wlr_box){ .x = INT_MAX, .y = INT_MAX };
|
*box = (struct wlr_fbox){ .x = INT_MAX, .y = INT_MAX };
|
||||||
int lx = 0, ly = 0;
|
double lx = 0, ly = 0;
|
||||||
wlr_scene_node_coords(node, &lx, &ly);
|
wlr_scene_node_coords(node, &lx, &ly);
|
||||||
_get_scene_node_extents(node, box, lx, ly);
|
_get_scene_node_extents(node, box, lx, ly);
|
||||||
}
|
}
|
||||||
|
|
@ -74,7 +74,7 @@ static void get_scene_node_extents(struct wlr_scene_node *node, struct wlr_box *
|
||||||
static void source_render(struct scene_node_source *source) {
|
static void source_render(struct scene_node_source *source) {
|
||||||
struct wlr_scene_output *scene_output = source->scene_output;
|
struct wlr_scene_output *scene_output = source->scene_output;
|
||||||
|
|
||||||
struct wlr_box extents;
|
struct wlr_fbox extents;
|
||||||
get_scene_node_extents(source->node, &extents);
|
get_scene_node_extents(source->node, &extents);
|
||||||
|
|
||||||
if (extents.width == 0 || extents.height == 0) {
|
if (extents.width == 0 || extents.height == 0) {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <wlr/types/wlr_presentation_time.h>
|
#include <wlr/types/wlr_presentation_time.h>
|
||||||
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
|
#include <wlr/types/wlr_single_pixel_buffer_v1.h>
|
||||||
#include <wlr/util/transform.h>
|
#include <wlr/util/transform.h>
|
||||||
|
#include <wlr/util/region.h>
|
||||||
#include "types/wlr_scene.h"
|
#include "types/wlr_scene.h"
|
||||||
|
|
||||||
static double get_surface_preferred_buffer_scale(struct wlr_surface *surface) {
|
static double get_surface_preferred_buffer_scale(struct wlr_surface *surface) {
|
||||||
|
|
@ -182,7 +183,7 @@ static void handle_scene_buffer_frame_done(
|
||||||
|
|
||||||
void wlr_scene_surface_send_frame_done(struct wlr_scene_surface *scene_surface,
|
void wlr_scene_surface_send_frame_done(struct wlr_scene_surface *scene_surface,
|
||||||
const struct timespec *when) {
|
const struct timespec *when) {
|
||||||
if (!pixman_region32_empty(&scene_surface->buffer->node.visible)) {
|
if (!pixman_region64f_empty(&scene_surface->buffer->node.visible)) {
|
||||||
wlr_surface_send_frame_done(scene_surface->surface, when);
|
wlr_surface_send_frame_done(scene_surface->surface, when);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -298,7 +299,11 @@ static void surface_reconfigure(struct wlr_scene_surface *scene_surface) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_scene_buffer_set_opaque_region(scene_buffer, &opaque);
|
pixman_region64f_t opaquef;
|
||||||
|
pixman_region64f_init(&opaquef);
|
||||||
|
wlr_region64f_copy_from_region32(&opaquef, &opaque);
|
||||||
|
|
||||||
|
wlr_scene_buffer_set_opaque_region(scene_buffer, &opaquef);
|
||||||
wlr_scene_buffer_set_source_box(scene_buffer, &src_box);
|
wlr_scene_buffer_set_source_box(scene_buffer, &src_box);
|
||||||
wlr_scene_buffer_set_dest_size(scene_buffer, width, height);
|
wlr_scene_buffer_set_dest_size(scene_buffer, width, height);
|
||||||
wlr_scene_buffer_set_transform(scene_buffer, state->transform);
|
wlr_scene_buffer_set_transform(scene_buffer, state->transform);
|
||||||
|
|
@ -343,6 +348,7 @@ static void surface_reconfigure(struct wlr_scene_surface *scene_surface) {
|
||||||
wlr_scene_buffer_set_buffer(scene_buffer, NULL);
|
wlr_scene_buffer_set_buffer(scene_buffer, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pixman_region64f_fini(&opaquef);
|
||||||
pixman_region32_fini(&opaque);
|
pixman_region32_fini(&opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -359,7 +365,7 @@ static void handle_scene_surface_surface_commit(
|
||||||
// schedule the frame however if the node is enabled and there is an
|
// schedule the frame however if the node is enabled and there is an
|
||||||
// output intersecting, otherwise the frame done events would never reach
|
// output intersecting, otherwise the frame done events would never reach
|
||||||
// the surface anyway.
|
// the surface anyway.
|
||||||
int lx, ly;
|
double lx, ly;
|
||||||
bool enabled = wlr_scene_node_coords(&scene_buffer->node, &lx, &ly);
|
bool enabled = wlr_scene_node_coords(&scene_buffer->node, &lx, &ly);
|
||||||
|
|
||||||
if (!wl_list_empty(&surface->surface->current.frame_callback_list) &&
|
if (!wl_list_empty(&surface->surface->current.frame_callback_list) &&
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ static void scene_node_init(struct wlr_scene_node *node,
|
||||||
wl_list_init(&node->link);
|
wl_list_init(&node->link);
|
||||||
|
|
||||||
wl_signal_init(&node->events.destroy);
|
wl_signal_init(&node->events.destroy);
|
||||||
pixman_region32_init(&node->visible);
|
pixman_region64f_init(&node->visible);
|
||||||
|
|
||||||
if (parent != NULL) {
|
if (parent != NULL) {
|
||||||
wl_list_insert(parent->children.prev, &node->link);
|
wl_list_insert(parent->children.prev, &node->link);
|
||||||
|
|
@ -115,7 +115,7 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) {
|
||||||
|
|
||||||
scene_buffer_set_buffer(scene_buffer, NULL);
|
scene_buffer_set_buffer(scene_buffer, NULL);
|
||||||
scene_buffer_set_texture(scene_buffer, NULL);
|
scene_buffer_set_texture(scene_buffer, NULL);
|
||||||
pixman_region32_fini(&scene_buffer->opaque_region);
|
pixman_region64f_fini(&scene_buffer->opaque_region);
|
||||||
wlr_drm_syncobj_timeline_unref(scene_buffer->wait_timeline);
|
wlr_drm_syncobj_timeline_unref(scene_buffer->wait_timeline);
|
||||||
|
|
||||||
assert(wl_list_empty(&scene_buffer->events.outputs_update.listener_list));
|
assert(wl_list_empty(&scene_buffer->events.outputs_update.listener_list));
|
||||||
|
|
@ -148,7 +148,7 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) {
|
||||||
assert(wl_list_empty(&node->events.destroy.listener_list));
|
assert(wl_list_empty(&node->events.destroy.listener_list));
|
||||||
|
|
||||||
wl_list_remove(&node->link);
|
wl_list_remove(&node->link);
|
||||||
pixman_region32_fini(&node->visible);
|
pixman_region64f_fini(&node->visible);
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,10 +202,10 @@ struct wlr_scene_tree *wlr_scene_tree_create(struct wlr_scene_tree *parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*scene_node_box_iterator_func_t)(struct wlr_scene_node *node,
|
typedef bool (*scene_node_box_iterator_func_t)(struct wlr_scene_node *node,
|
||||||
int sx, int sy, void *data);
|
double sx, double sy, void *data);
|
||||||
|
|
||||||
static bool _scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box,
|
static bool _scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_fbox *box,
|
||||||
scene_node_box_iterator_func_t iterator, void *user_data, int lx, int ly) {
|
scene_node_box_iterator_func_t iterator, void *user_data, double lx, double ly) {
|
||||||
if (!node->enabled) {
|
if (!node->enabled) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -222,10 +222,10 @@ static bool _scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box
|
||||||
break;
|
break;
|
||||||
case WLR_SCENE_NODE_RECT:
|
case WLR_SCENE_NODE_RECT:
|
||||||
case WLR_SCENE_NODE_BUFFER:;
|
case WLR_SCENE_NODE_BUFFER:;
|
||||||
struct wlr_box node_box = { .x = lx, .y = ly };
|
struct wlr_fbox node_box = { .x = lx, .y = ly };
|
||||||
scene_node_get_size(node, &node_box.width, &node_box.height);
|
scene_node_get_size(node, &node_box.width, &node_box.height);
|
||||||
|
|
||||||
if (wlr_box_intersects(&node_box, box) &&
|
if (wlr_fbox_intersects(&node_box, box) &&
|
||||||
iterator(node, lx, ly, user_data)) {
|
iterator(node, lx, ly, user_data)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -235,17 +235,17 @@ static bool _scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box,
|
static bool scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_fbox *box,
|
||||||
scene_node_box_iterator_func_t iterator, void *user_data) {
|
scene_node_box_iterator_func_t iterator, void *user_data) {
|
||||||
int x, y;
|
double x, y;
|
||||||
wlr_scene_node_coords(node, &x, &y);
|
wlr_scene_node_coords(node, &x, &y);
|
||||||
|
|
||||||
return _scene_nodes_in_box(node, box, iterator, user_data, x, y);
|
return _scene_nodes_in_box(node, box, iterator, user_data, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_node_opaque_region(struct wlr_scene_node *node, int x, int y,
|
static void scene_node_opaque_region(struct wlr_scene_node *node, double x, double y,
|
||||||
pixman_region32_t *opaque) {
|
pixman_region64f_t *opaque) {
|
||||||
int width, height;
|
double width, height;
|
||||||
scene_node_get_size(node, &width, &height);
|
scene_node_get_size(node, &width, &height);
|
||||||
|
|
||||||
if (node->type == WLR_SCENE_NODE_RECT) {
|
if (node->type == WLR_SCENE_NODE_RECT) {
|
||||||
|
|
@ -265,21 +265,21 @@ static void scene_node_opaque_region(struct wlr_scene_node *node, int x, int y,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scene_buffer->buffer_is_opaque) {
|
if (!scene_buffer->buffer_is_opaque) {
|
||||||
pixman_region32_copy(opaque, &scene_buffer->opaque_region);
|
pixman_region64f_copy(opaque, &scene_buffer->opaque_region);
|
||||||
pixman_region32_intersect_rect(opaque, opaque, 0, 0, width, height);
|
pixman_region64f_intersect_rectf(opaque, opaque, 0, 0, width, height);
|
||||||
pixman_region32_translate(opaque, x, y);
|
pixman_region64f_translatef(opaque, x, y);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_fini(opaque);
|
pixman_region64f_fini(opaque);
|
||||||
pixman_region32_init_rect(opaque, x, y, width, height);
|
pixman_region64f_init_rectf(opaque, x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct scene_update_data {
|
struct scene_update_data {
|
||||||
pixman_region32_t *visible;
|
pixman_region64f_t *visible;
|
||||||
const pixman_region32_t *update_region;
|
const pixman_region64f_t *update_region;
|
||||||
struct wlr_box update_box;
|
struct wlr_fbox update_box;
|
||||||
struct wl_list *outputs;
|
struct wl_list *outputs;
|
||||||
bool calculate_visibility;
|
bool calculate_visibility;
|
||||||
bool restack_xwayland_surfaces;
|
bool restack_xwayland_surfaces;
|
||||||
|
|
@ -289,11 +289,11 @@ struct scene_update_data {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t region_area(const pixman_region32_t *region) {
|
static double region_area(const pixman_region64f_t *region) {
|
||||||
uint32_t area = 0;
|
double area = 0;
|
||||||
|
|
||||||
int nrects;
|
int nrects;
|
||||||
pixman_box32_t *rects = pixman_region32_rectangles(region, &nrects);
|
pixman_box64f_t *rects = pixman_region64f_rectangles(region, &nrects);
|
||||||
for (int i = 0; i < nrects; ++i) {
|
for (int i = 0; i < nrects; ++i) {
|
||||||
area += (rects[i].x2 - rects[i].x1) * (rects[i].y2 - rects[i].y1);
|
area += (rects[i].x2 - rects[i].x1) * (rects[i].y2 - rects[i].y1);
|
||||||
}
|
}
|
||||||
|
|
@ -301,8 +301,8 @@ static uint32_t region_area(const pixman_region32_t *region) {
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scale_region(pixman_region32_t *region, float scale, bool round_up) {
|
static void scale_region(pixman_region32_t *region, pixman_region64f_t *src, float scale, bool round_up) {
|
||||||
wlr_region_scale(region, region, scale);
|
wlr_region_scalef(region, src, scale);
|
||||||
|
|
||||||
if (round_up && floor(scale) != scale) {
|
if (round_up && floor(scale) != scale) {
|
||||||
wlr_region_expand(region, region, 1);
|
wlr_region_expand(region, region, 1);
|
||||||
|
|
@ -312,7 +312,7 @@ static void scale_region(pixman_region32_t *region, float scale, bool round_up)
|
||||||
struct render_data {
|
struct render_data {
|
||||||
enum wl_output_transform transform;
|
enum wl_output_transform transform;
|
||||||
float scale;
|
float scale;
|
||||||
struct wlr_box logical;
|
struct wlr_fbox logical;
|
||||||
int trans_width, trans_height;
|
int trans_width, trans_height;
|
||||||
|
|
||||||
struct wlr_scene_output *output;
|
struct wlr_scene_output *output;
|
||||||
|
|
@ -321,10 +321,10 @@ struct render_data {
|
||||||
pixman_region32_t damage;
|
pixman_region32_t damage;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void logical_to_buffer_coords(pixman_region32_t *region, const struct render_data *data,
|
static void logical_to_buffer_coords(pixman_region32_t *region, pixman_region64f_t *src,
|
||||||
bool round_up) {
|
const struct render_data *data, bool round_up) {
|
||||||
enum wl_output_transform transform = wlr_output_transform_invert(data->transform);
|
enum wl_output_transform transform = wlr_output_transform_invert(data->transform);
|
||||||
scale_region(region, data->scale, round_up);
|
scale_region(region, src, data->scale, round_up);
|
||||||
wlr_region_transform(region, region, transform, data->trans_width, data->trans_height);
|
wlr_region_transform(region, region, transform, data->trans_width, data->trans_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -336,20 +336,22 @@ static void output_to_buffer_coords(pixman_region32_t *damage, struct wlr_output
|
||||||
wlr_output_transform_invert(output->transform), width, height);
|
wlr_output_transform_invert(output->transform), width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int scale_length(int length, int offset, float scale) {
|
static int scale_length(double length, double offset, float scale) {
|
||||||
return round((offset + length) * scale) - round(offset * scale);
|
return round((offset + length) * scale) - round(offset * scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scale_box(struct wlr_box *box, float scale) {
|
static void transform_output_box(struct wlr_box *box, struct wlr_fbox *src,
|
||||||
box->width = scale_length(box->width, box->x, scale);
|
const struct render_data *data, bool scale_stretch) {
|
||||||
box->height = scale_length(box->height, box->y, scale);
|
|
||||||
box->x = round(box->x * scale);
|
|
||||||
box->y = round(box->y * scale);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void transform_output_box(struct wlr_box *box, const struct render_data *data) {
|
|
||||||
enum wl_output_transform transform = wlr_output_transform_invert(data->transform);
|
enum wl_output_transform transform = wlr_output_transform_invert(data->transform);
|
||||||
scale_box(box, data->scale);
|
if (scale_stretch) {
|
||||||
|
box->width = scale_length(src->width, src->x, data->scale);
|
||||||
|
box->height = scale_length(src->height, src->y, data->scale);
|
||||||
|
} else {
|
||||||
|
box->width = round(src->width * data->scale);
|
||||||
|
box->height = round(src->height * data->scale);
|
||||||
|
}
|
||||||
|
box->x = round(src->x * data->scale);
|
||||||
|
box->y = round(src->y * data->scale);
|
||||||
wlr_box_transform(box, box, transform, data->trans_width, data->trans_height);
|
wlr_box_transform(box, box, transform, data->trans_width, data->trans_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -381,25 +383,77 @@ static void scene_output_damage_whole(struct wlr_scene_output *scene_output) {
|
||||||
pixman_region32_fini(&damage);
|
pixman_region32_fini(&damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_damage_outputs(struct wlr_scene *scene, const pixman_region32_t *damage) {
|
static void scene_damage_outputs(struct wlr_scene *scene, const pixman_region64f_t *damage) {
|
||||||
if (pixman_region32_empty(damage)) {
|
if (pixman_region64f_empty(damage)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene_output *scene_output;
|
struct wlr_scene_output *scene_output;
|
||||||
wl_list_for_each(scene_output, &scene->outputs, link) {
|
wl_list_for_each(scene_output, &scene->outputs, link) {
|
||||||
|
pixman_region64f_t logical_output_damage;
|
||||||
|
pixman_region64f_init(&logical_output_damage);
|
||||||
|
pixman_region64f_copy(&logical_output_damage, damage);
|
||||||
|
pixman_region64f_translatef(&logical_output_damage,
|
||||||
|
-scene_output->x, -scene_output->y);
|
||||||
pixman_region32_t output_damage;
|
pixman_region32_t output_damage;
|
||||||
pixman_region32_init(&output_damage);
|
pixman_region32_init(&output_damage);
|
||||||
pixman_region32_copy(&output_damage, damage);
|
scale_region(&output_damage, &logical_output_damage, scene_output->output->scale, true);
|
||||||
pixman_region32_translate(&output_damage,
|
pixman_region64f_fini(&logical_output_damage);
|
||||||
-scene_output->x, -scene_output->y);
|
|
||||||
scale_region(&output_damage, scene_output->output->scale, true);
|
|
||||||
output_to_buffer_coords(&output_damage, scene_output->output);
|
output_to_buffer_coords(&output_damage, scene_output->output);
|
||||||
scene_output_damage(scene_output, &output_damage);
|
scene_output_damage(scene_output, &output_damage);
|
||||||
pixman_region32_fini(&output_damage);
|
pixman_region32_fini(&output_damage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void visible_region_active_outputs(struct wl_list *outputs, struct wlr_scene_output *ignore, pixman_region64f_t *visible,
|
||||||
|
uint64_t *active_outputs, size_t *count, struct wlr_scene_output **primary_output) {
|
||||||
|
double largest_overlap = 0;
|
||||||
|
|
||||||
|
if (!pixman_region64f_empty(visible)) {
|
||||||
|
double visible_area = region_area(visible);
|
||||||
|
|
||||||
|
struct wlr_scene_output *scene_output;
|
||||||
|
wl_list_for_each(scene_output, outputs, link) {
|
||||||
|
if (scene_output == ignore) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scene_output->output->enabled) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_fbox output_box = {
|
||||||
|
.x = scene_output->x,
|
||||||
|
.y = scene_output->y,
|
||||||
|
};
|
||||||
|
int output_width, output_height;
|
||||||
|
wlr_output_effective_resolution(scene_output->output,
|
||||||
|
&output_width, &output_height);
|
||||||
|
output_box.width = output_width;
|
||||||
|
output_box.height = output_height;
|
||||||
|
|
||||||
|
pixman_region64f_t intersection;
|
||||||
|
pixman_region64f_init(&intersection);
|
||||||
|
pixman_region64f_intersect_rectf(&intersection, visible,
|
||||||
|
output_box.x, output_box.y, output_box.width, output_box.height);
|
||||||
|
uint32_t overlap = region_area(&intersection);
|
||||||
|
pixman_region64f_fini(&intersection);
|
||||||
|
|
||||||
|
// If the overlap accounts for less than 10% of the visible node area,
|
||||||
|
// ignore this output
|
||||||
|
if (overlap >= 0.1 * visible_area) {
|
||||||
|
if (overlap >= largest_overlap) {
|
||||||
|
largest_overlap = overlap;
|
||||||
|
*primary_output = scene_output;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*active_outputs) |= 1ull << scene_output->index;
|
||||||
|
(*count)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void update_node_update_outputs(struct wlr_scene_node *node,
|
static void update_node_update_outputs(struct wlr_scene_node *node,
|
||||||
struct wl_list *outputs, struct wlr_scene_output *ignore,
|
struct wl_list *outputs, struct wlr_scene_output *ignore,
|
||||||
struct wlr_scene_output *force) {
|
struct wlr_scene_output *force) {
|
||||||
|
|
@ -408,61 +462,22 @@ static void update_node_update_outputs(struct wlr_scene_node *node,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
|
struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node);
|
||||||
|
|
||||||
uint32_t largest_overlap = 0;
|
|
||||||
struct wlr_scene_output *old_primary_output = scene_buffer->primary_output;
|
struct wlr_scene_output *old_primary_output = scene_buffer->primary_output;
|
||||||
scene_buffer->primary_output = NULL;
|
scene_buffer->primary_output = NULL;
|
||||||
|
|
||||||
|
// let's update the outputs in two steps:
|
||||||
|
// - the primary outputs
|
||||||
|
// - the enter/leave signals
|
||||||
|
// This ensures that the enter/leave signals can rely on the primary output
|
||||||
|
// to have a reasonable value. Otherwise, they may get a value that's in
|
||||||
|
// the middle of a calculation.
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
uint64_t active_outputs = 0;
|
uint64_t active_outputs = 0;
|
||||||
|
struct wlr_scene_output *primary_output = NULL;
|
||||||
|
visible_region_active_outputs(outputs, ignore, &node->visible,
|
||||||
|
&active_outputs, &count, &primary_output);
|
||||||
|
|
||||||
if (!pixman_region32_empty(&node->visible)) {
|
scene_buffer->primary_output = primary_output;
|
||||||
uint32_t visible_area = region_area(&node->visible);
|
|
||||||
|
|
||||||
// let's update the outputs in two steps:
|
|
||||||
// - the primary outputs
|
|
||||||
// - the enter/leave signals
|
|
||||||
// This ensures that the enter/leave signals can rely on the primary output
|
|
||||||
// to have a reasonable value. Otherwise, they may get a value that's in
|
|
||||||
// the middle of a calculation.
|
|
||||||
struct wlr_scene_output *scene_output;
|
|
||||||
wl_list_for_each(scene_output, outputs, link) {
|
|
||||||
if (scene_output == ignore) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!scene_output->output->enabled) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct wlr_box output_box = {
|
|
||||||
.x = scene_output->x,
|
|
||||||
.y = scene_output->y,
|
|
||||||
};
|
|
||||||
wlr_output_effective_resolution(scene_output->output,
|
|
||||||
&output_box.width, &output_box.height);
|
|
||||||
|
|
||||||
pixman_region32_t intersection;
|
|
||||||
pixman_region32_init(&intersection);
|
|
||||||
pixman_region32_intersect_rect(&intersection, &node->visible,
|
|
||||||
output_box.x, output_box.y, output_box.width, output_box.height);
|
|
||||||
uint32_t overlap = region_area(&intersection);
|
|
||||||
pixman_region32_fini(&intersection);
|
|
||||||
|
|
||||||
// If the overlap accounts for less than 10% of the visible node area,
|
|
||||||
// ignore this output
|
|
||||||
if (overlap >= 0.1 * visible_area) {
|
|
||||||
if (overlap >= largest_overlap) {
|
|
||||||
largest_overlap = overlap;
|
|
||||||
scene_buffer->primary_output = scene_output;
|
|
||||||
}
|
|
||||||
|
|
||||||
active_outputs |= 1ull << scene_output->index;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (old_primary_output != scene_buffer->primary_output) {
|
if (old_primary_output != scene_buffer->primary_output) {
|
||||||
scene_buffer->prev_feedback_options =
|
scene_buffer->prev_feedback_options =
|
||||||
(struct wlr_linux_dmabuf_feedback_v1_init_options){0};
|
(struct wlr_linux_dmabuf_feedback_v1_init_options){0};
|
||||||
|
|
@ -523,7 +538,7 @@ static struct wlr_xwayland_surface *scene_node_try_get_managed_xwayland_surface(
|
||||||
}
|
}
|
||||||
|
|
||||||
static void restack_xwayland_surface(struct wlr_scene_node *node,
|
static void restack_xwayland_surface(struct wlr_scene_node *node,
|
||||||
struct wlr_box *box, struct scene_update_data *data) {
|
struct wlr_fbox *box, struct scene_update_data *data) {
|
||||||
struct wlr_xwayland_surface *xwayland_surface =
|
struct wlr_xwayland_surface *xwayland_surface =
|
||||||
scene_node_try_get_managed_xwayland_surface(node);
|
scene_node_try_get_managed_xwayland_surface(node);
|
||||||
if (!xwayland_surface) {
|
if (!xwayland_surface) {
|
||||||
|
|
@ -532,7 +547,7 @@ static void restack_xwayland_surface(struct wlr_scene_node *node,
|
||||||
|
|
||||||
// ensure this node is entirely inside the update region. If not, we can't
|
// ensure this node is entirely inside the update region. If not, we can't
|
||||||
// restack this node since we're not considering the whole thing.
|
// restack this node since we're not considering the whole thing.
|
||||||
if (wlr_box_contains_box(&data->update_box, box)) {
|
if (wlr_fbox_contains_box(&data->update_box, box)) {
|
||||||
if (data->restack_above) {
|
if (data->restack_above) {
|
||||||
wlr_xwayland_surface_restack(xwayland_surface, data->restack_above, XCB_STACK_MODE_BELOW);
|
wlr_xwayland_surface_restack(xwayland_surface, data->restack_above, XCB_STACK_MODE_BELOW);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -545,23 +560,23 @@ static void restack_xwayland_surface(struct wlr_scene_node *node,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool scene_node_update_iterator(struct wlr_scene_node *node,
|
static bool scene_node_update_iterator(struct wlr_scene_node *node,
|
||||||
int lx, int ly, void *_data) {
|
double lx, double ly, void *_data) {
|
||||||
struct scene_update_data *data = _data;
|
struct scene_update_data *data = _data;
|
||||||
|
|
||||||
struct wlr_box box = { .x = lx, .y = ly };
|
struct wlr_fbox box = { .x = lx, .y = ly };
|
||||||
scene_node_get_size(node, &box.width, &box.height);
|
scene_node_get_size(node, &box.width, &box.height);
|
||||||
|
|
||||||
pixman_region32_subtract(&node->visible, &node->visible, data->update_region);
|
pixman_region64f_subtract(&node->visible, &node->visible, data->update_region);
|
||||||
pixman_region32_union(&node->visible, &node->visible, data->visible);
|
pixman_region64f_union(&node->visible, &node->visible, data->visible);
|
||||||
pixman_region32_intersect_rect(&node->visible, &node->visible,
|
pixman_region64f_intersect_rectf(&node->visible, &node->visible,
|
||||||
lx, ly, box.width, box.height);
|
lx, ly, box.width, box.height);
|
||||||
|
|
||||||
if (data->calculate_visibility) {
|
if (data->calculate_visibility) {
|
||||||
pixman_region32_t opaque;
|
pixman_region64f_t opaque;
|
||||||
pixman_region32_init(&opaque);
|
pixman_region64f_init(&opaque);
|
||||||
scene_node_opaque_region(node, lx, ly, &opaque);
|
scene_node_opaque_region(node, lx, ly, &opaque);
|
||||||
pixman_region32_subtract(data->visible, data->visible, &opaque);
|
pixman_region64f_subtract(data->visible, data->visible, &opaque);
|
||||||
pixman_region32_fini(&opaque);
|
pixman_region64f_fini(&opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
update_node_update_outputs(node, data->outputs, NULL, NULL);
|
update_node_update_outputs(node, data->outputs, NULL, NULL);
|
||||||
|
|
@ -575,7 +590,7 @@ static bool scene_node_update_iterator(struct wlr_scene_node *node,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_node_visibility(struct wlr_scene_node *node,
|
static void scene_node_visibility(struct wlr_scene_node *node,
|
||||||
pixman_region32_t *visible) {
|
pixman_region64f_t *visible) {
|
||||||
if (!node->enabled) {
|
if (!node->enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -589,11 +604,11 @@ static void scene_node_visibility(struct wlr_scene_node *node,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_union(visible, visible, &node->visible);
|
pixman_region64f_union(visible, visible, &node->visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_node_bounds(struct wlr_scene_node *node,
|
static void scene_node_bounds(struct wlr_scene_node *node,
|
||||||
int x, int y, pixman_region32_t *visible) {
|
double x, double y, pixman_region64f_t *visible) {
|
||||||
if (!node->enabled) {
|
if (!node->enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -607,18 +622,18 @@ static void scene_node_bounds(struct wlr_scene_node *node,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int width, height;
|
double width, height;
|
||||||
scene_node_get_size(node, &width, &height);
|
scene_node_get_size(node, &width, &height);
|
||||||
pixman_region32_union_rect(visible, visible, x, y, width, height);
|
pixman_region64f_union_rectf(visible, visible, x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_update_region(struct wlr_scene *scene,
|
static void scene_update_region(struct wlr_scene *scene,
|
||||||
const pixman_region32_t *update_region) {
|
const pixman_region64f_t *update_region) {
|
||||||
pixman_region32_t visible;
|
pixman_region64f_t visible;
|
||||||
pixman_region32_init(&visible);
|
pixman_region64f_init(&visible);
|
||||||
pixman_region32_copy(&visible, update_region);
|
pixman_region64f_copy(&visible, update_region);
|
||||||
|
|
||||||
struct pixman_box32 *region_box = pixman_region32_extents(update_region);
|
struct pixman_box64f *region_box = pixman_region64f_extents(update_region);
|
||||||
struct scene_update_data data = {
|
struct scene_update_data data = {
|
||||||
.visible = &visible,
|
.visible = &visible,
|
||||||
.update_region = update_region,
|
.update_region = update_region,
|
||||||
|
|
@ -636,7 +651,7 @@ static void scene_update_region(struct wlr_scene *scene,
|
||||||
// update node visibility and output enter/leave events
|
// update node visibility and output enter/leave events
|
||||||
scene_nodes_in_box(&scene->tree.node, &data.update_box, scene_node_update_iterator, &data);
|
scene_nodes_in_box(&scene->tree.node, &data.update_box, scene_node_update_iterator, &data);
|
||||||
|
|
||||||
pixman_region32_fini(&visible);
|
pixman_region64f_fini(&visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_node_cleanup_when_disabled(struct wlr_scene_node *node,
|
static void scene_node_cleanup_when_disabled(struct wlr_scene_node *node,
|
||||||
|
|
@ -654,7 +669,7 @@ static void scene_node_cleanup_when_disabled(struct wlr_scene_node *node,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_clear(&node->visible);
|
pixman_region64f_clear(&node->visible);
|
||||||
update_node_update_outputs(node, outputs, NULL, NULL);
|
update_node_update_outputs(node, outputs, NULL, NULL);
|
||||||
|
|
||||||
#if WLR_HAS_XWAYLAND
|
#if WLR_HAS_XWAYLAND
|
||||||
|
|
@ -685,10 +700,10 @@ static void scene_node_cleanup_when_disabled(struct wlr_scene_node *node,
|
||||||
* being reparented to a disabled super tree.
|
* being reparented to a disabled super tree.
|
||||||
*/
|
*/
|
||||||
static void scene_node_update(struct wlr_scene_node *node,
|
static void scene_node_update(struct wlr_scene_node *node,
|
||||||
pixman_region32_t *damage) {
|
pixman_region64f_t *damage) {
|
||||||
struct wlr_scene *scene = scene_node_get_root(node);
|
struct wlr_scene *scene = scene_node_get_root(node);
|
||||||
|
|
||||||
int x, y;
|
double x, y;
|
||||||
if (!wlr_scene_node_coords(node, &x, &y)) {
|
if (!wlr_scene_node_coords(node, &x, &y)) {
|
||||||
// We assume explicit damage on a disabled tree means the node was just
|
// We assume explicit damage on a disabled tree means the node was just
|
||||||
// disabled.
|
// disabled.
|
||||||
|
|
@ -697,34 +712,34 @@ static void scene_node_update(struct wlr_scene_node *node,
|
||||||
|
|
||||||
scene_update_region(scene, damage);
|
scene_update_region(scene, damage);
|
||||||
scene_damage_outputs(scene, damage);
|
scene_damage_outputs(scene, damage);
|
||||||
pixman_region32_fini(damage);
|
pixman_region64f_fini(damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_t visible;
|
pixman_region64f_t visible;
|
||||||
if (!damage) {
|
if (!damage) {
|
||||||
pixman_region32_init(&visible);
|
pixman_region64f_init(&visible);
|
||||||
scene_node_visibility(node, &visible);
|
scene_node_visibility(node, &visible);
|
||||||
damage = &visible;
|
damage = &visible;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_t update_region;
|
pixman_region64f_t update_region;
|
||||||
pixman_region32_init(&update_region);
|
pixman_region64f_init(&update_region);
|
||||||
pixman_region32_copy(&update_region, damage);
|
pixman_region64f_copy(&update_region, damage);
|
||||||
scene_node_bounds(node, x, y, &update_region);
|
scene_node_bounds(node, x, y, &update_region);
|
||||||
|
|
||||||
scene_update_region(scene, &update_region);
|
scene_update_region(scene, &update_region);
|
||||||
pixman_region32_fini(&update_region);
|
pixman_region64f_fini(&update_region);
|
||||||
|
|
||||||
scene_node_visibility(node, damage);
|
scene_node_visibility(node, damage);
|
||||||
scene_damage_outputs(scene, damage);
|
scene_damage_outputs(scene, damage);
|
||||||
pixman_region32_fini(damage);
|
pixman_region64f_fini(damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent,
|
struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent,
|
||||||
int width, int height, const float color[static 4]) {
|
double width, double height, const float color[static 4]) {
|
||||||
assert(parent);
|
assert(parent);
|
||||||
assert(width >= 0 && height >= 0);
|
assert(width >= 0 && height >= 0);
|
||||||
|
|
||||||
|
|
@ -743,7 +758,7 @@ struct wlr_scene_rect *wlr_scene_rect_create(struct wlr_scene_tree *parent,
|
||||||
return scene_rect;
|
return scene_rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_rect_set_size(struct wlr_scene_rect *rect, int width, int height) {
|
void wlr_scene_rect_set_size(struct wlr_scene_rect *rect, double width, double height) {
|
||||||
if (rect->width == width && rect->height == height) {
|
if (rect->width == width && rect->height == height) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -845,7 +860,7 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent,
|
||||||
wl_signal_init(&scene_buffer->events.output_sample);
|
wl_signal_init(&scene_buffer->events.output_sample);
|
||||||
wl_signal_init(&scene_buffer->events.frame_done);
|
wl_signal_init(&scene_buffer->events.frame_done);
|
||||||
|
|
||||||
pixman_region32_init(&scene_buffer->opaque_region);
|
pixman_region64f_init(&scene_buffer->opaque_region);
|
||||||
wl_list_init(&scene_buffer->buffer_release.link);
|
wl_list_init(&scene_buffer->buffer_release.link);
|
||||||
wl_list_init(&scene_buffer->renderer_destroy.link);
|
wl_list_init(&scene_buffer->renderer_destroy.link);
|
||||||
scene_buffer->opacity = 1;
|
scene_buffer->opacity = 1;
|
||||||
|
|
@ -919,7 +934,7 @@ void wlr_scene_buffer_set_buffer_with_options(struct wlr_scene_buffer *scene_buf
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lx, ly;
|
double lx, ly;
|
||||||
if (!wlr_scene_node_coords(&scene_buffer->node, &lx, &ly)) {
|
if (!wlr_scene_node_coords(&scene_buffer->node, &lx, &ly)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -989,10 +1004,13 @@ void wlr_scene_buffer_set_buffer_with_options(struct wlr_scene_buffer *scene_buf
|
||||||
wlr_region_expand(&output_damage, &output_damage,
|
wlr_region_expand(&output_damage, &output_damage,
|
||||||
dist_x >= dist_y ? dist_x : dist_y);
|
dist_x >= dist_y ? dist_x : dist_y);
|
||||||
|
|
||||||
|
pixman_region64f_t logical_cull_region;
|
||||||
|
pixman_region64f_init(&logical_cull_region);
|
||||||
|
pixman_region64f_copy(&logical_cull_region, &scene_buffer->node.visible);
|
||||||
pixman_region32_t cull_region;
|
pixman_region32_t cull_region;
|
||||||
pixman_region32_init(&cull_region);
|
pixman_region32_init(&cull_region);
|
||||||
pixman_region32_copy(&cull_region, &scene_buffer->node.visible);
|
scale_region(&cull_region, &logical_cull_region, output_scale, true);
|
||||||
scale_region(&cull_region, output_scale, true);
|
pixman_region64f_fini(&logical_cull_region);
|
||||||
pixman_region32_translate(&cull_region, -lx * output_scale, -ly * output_scale);
|
pixman_region32_translate(&cull_region, -lx * output_scale, -ly * output_scale);
|
||||||
pixman_region32_intersect(&output_damage, &output_damage, &cull_region);
|
pixman_region32_intersect(&output_damage, &output_damage, &cull_region);
|
||||||
pixman_region32_fini(&cull_region);
|
pixman_region32_fini(&cull_region);
|
||||||
|
|
@ -1023,23 +1041,23 @@ void wlr_scene_buffer_set_buffer(struct wlr_scene_buffer *scene_buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_buffer_set_opaque_region(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_buffer_set_opaque_region(struct wlr_scene_buffer *scene_buffer,
|
||||||
const pixman_region32_t *region) {
|
const pixman_region64f_t *region) {
|
||||||
if (pixman_region32_equal(&scene_buffer->opaque_region, region)) {
|
if (pixman_region64f_equal(&scene_buffer->opaque_region, region)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_copy(&scene_buffer->opaque_region, region);
|
pixman_region64f_copy(&scene_buffer->opaque_region, region);
|
||||||
|
|
||||||
int x, y;
|
double x, y;
|
||||||
if (!wlr_scene_node_coords(&scene_buffer->node, &x, &y)) {
|
if (!wlr_scene_node_coords(&scene_buffer->node, &x, &y)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_t update_region;
|
pixman_region64f_t update_region;
|
||||||
pixman_region32_init(&update_region);
|
pixman_region64f_init(&update_region);
|
||||||
scene_node_bounds(&scene_buffer->node, x, y, &update_region);
|
scene_node_bounds(&scene_buffer->node, x, y, &update_region);
|
||||||
scene_update_region(scene_node_get_root(&scene_buffer->node), &update_region);
|
scene_update_region(scene_node_get_root(&scene_buffer->node), &update_region);
|
||||||
pixman_region32_fini(&update_region);
|
pixman_region64f_fini(&update_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer,
|
||||||
|
|
@ -1059,7 +1077,7 @@ void wlr_scene_buffer_set_source_box(struct wlr_scene_buffer *scene_buffer,
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_buffer_set_dest_size(struct wlr_scene_buffer *scene_buffer,
|
||||||
int width, int height) {
|
double width, double height) {
|
||||||
if (scene_buffer->dst_width == width && scene_buffer->dst_height == height) {
|
if (scene_buffer->dst_width == width && scene_buffer->dst_height == height) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1082,7 +1100,7 @@ void wlr_scene_buffer_set_transform(struct wlr_scene_buffer *scene_buffer,
|
||||||
|
|
||||||
void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer,
|
void wlr_scene_buffer_send_frame_done(struct wlr_scene_buffer *scene_buffer,
|
||||||
struct wlr_scene_frame_done_event *event) {
|
struct wlr_scene_frame_done_event *event) {
|
||||||
if (!pixman_region32_empty(&scene_buffer->node.visible)) {
|
if (!pixman_region64f_empty(&scene_buffer->node.visible)) {
|
||||||
wl_signal_emit_mutable(&scene_buffer->events.frame_done, event);
|
wl_signal_emit_mutable(&scene_buffer->events.frame_done, event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1170,7 +1188,7 @@ static struct wlr_texture *scene_buffer_get_texture(
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scene_node_get_size(struct wlr_scene_node *node, int *width, int *height) {
|
void scene_node_get_size(struct wlr_scene_node *node, double *width, double *height) {
|
||||||
*width = 0;
|
*width = 0;
|
||||||
*height = 0;
|
*height = 0;
|
||||||
|
|
||||||
|
|
@ -1188,9 +1206,10 @@ void scene_node_get_size(struct wlr_scene_node *node, int *width, int *height) {
|
||||||
*width = scene_buffer->dst_width;
|
*width = scene_buffer->dst_width;
|
||||||
*height = scene_buffer->dst_height;
|
*height = scene_buffer->dst_height;
|
||||||
} else {
|
} else {
|
||||||
*width = scene_buffer->buffer_width;
|
int w = scene_buffer->buffer_width, h = scene_buffer->buffer_height;
|
||||||
*height = scene_buffer->buffer_height;
|
wlr_output_transform_coords(scene_buffer->transform, &w, &h);
|
||||||
wlr_output_transform_coords(scene_buffer->transform, width, height);
|
*width = w;
|
||||||
|
*height = h;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -1201,9 +1220,9 @@ void wlr_scene_node_set_enabled(struct wlr_scene_node *node, bool enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x, y;
|
double x, y;
|
||||||
pixman_region32_t visible;
|
pixman_region64f_t visible;
|
||||||
pixman_region32_init(&visible);
|
pixman_region64f_init(&visible);
|
||||||
if (wlr_scene_node_coords(node, &x, &y)) {
|
if (wlr_scene_node_coords(node, &x, &y)) {
|
||||||
scene_node_visibility(node, &visible);
|
scene_node_visibility(node, &visible);
|
||||||
}
|
}
|
||||||
|
|
@ -1213,7 +1232,7 @@ void wlr_scene_node_set_enabled(struct wlr_scene_node *node, bool enabled) {
|
||||||
scene_node_update(node, &visible);
|
scene_node_update(node, &visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_node_set_position(struct wlr_scene_node *node, int x, int y) {
|
void wlr_scene_node_set_position(struct wlr_scene_node *node, double x, double y) {
|
||||||
if (node->x == x && node->y == y) {
|
if (node->x == x && node->y == y) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1283,9 +1302,9 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node,
|
||||||
assert(&ancestor->node != node);
|
assert(&ancestor->node != node);
|
||||||
}
|
}
|
||||||
|
|
||||||
int x, y;
|
double x, y;
|
||||||
pixman_region32_t visible;
|
pixman_region64f_t visible;
|
||||||
pixman_region32_init(&visible);
|
pixman_region64f_init(&visible);
|
||||||
if (wlr_scene_node_coords(node, &x, &y)) {
|
if (wlr_scene_node_coords(node, &x, &y)) {
|
||||||
scene_node_visibility(node, &visible);
|
scene_node_visibility(node, &visible);
|
||||||
}
|
}
|
||||||
|
|
@ -1297,10 +1316,10 @@ void wlr_scene_node_reparent(struct wlr_scene_node *node,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_scene_node_coords(struct wlr_scene_node *node,
|
bool wlr_scene_node_coords(struct wlr_scene_node *node,
|
||||||
int *lx_ptr, int *ly_ptr) {
|
double *lx_ptr, double *ly_ptr) {
|
||||||
assert(node);
|
assert(node);
|
||||||
|
|
||||||
int lx = 0, ly = 0;
|
double lx = 0, ly = 0;
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
while (true) {
|
while (true) {
|
||||||
lx += node->x;
|
lx += node->x;
|
||||||
|
|
@ -1319,7 +1338,7 @@ bool wlr_scene_node_coords(struct wlr_scene_node *node,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_node_for_each_scene_buffer(struct wlr_scene_node *node,
|
static void scene_node_for_each_scene_buffer(struct wlr_scene_node *node,
|
||||||
int lx, int ly, wlr_scene_buffer_iterator_func_t user_iterator,
|
double lx, double ly, wlr_scene_buffer_iterator_func_t user_iterator,
|
||||||
void *user_data) {
|
void *user_data) {
|
||||||
if (!node->enabled) {
|
if (!node->enabled) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -1352,7 +1371,7 @@ struct node_at_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool scene_node_at_iterator(struct wlr_scene_node *node,
|
static bool scene_node_at_iterator(struct wlr_scene_node *node,
|
||||||
int lx, int ly, void *data) {
|
double lx, double ly, void *data) {
|
||||||
struct node_at_data *at_data = data;
|
struct node_at_data *at_data = data;
|
||||||
|
|
||||||
double rx = at_data->lx - lx;
|
double rx = at_data->lx - lx;
|
||||||
|
|
@ -1375,9 +1394,9 @@ static bool scene_node_at_iterator(struct wlr_scene_node *node,
|
||||||
|
|
||||||
struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node,
|
struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node,
|
||||||
double lx, double ly, double *nx, double *ny) {
|
double lx, double ly, double *nx, double *ny) {
|
||||||
struct wlr_box box = {
|
struct wlr_fbox box = {
|
||||||
.x = floor(lx),
|
.x = lx,
|
||||||
.y = floor(ly),
|
.y = ly,
|
||||||
.width = 1,
|
.width = 1,
|
||||||
.height = 1
|
.height = 1
|
||||||
};
|
};
|
||||||
|
|
@ -1402,8 +1421,9 @@ struct wlr_scene_node *wlr_scene_node_at(struct wlr_scene_node *node,
|
||||||
|
|
||||||
struct render_list_entry {
|
struct render_list_entry {
|
||||||
struct wlr_scene_node *node;
|
struct wlr_scene_node *node;
|
||||||
|
bool scale_stretch;
|
||||||
bool highlight_transparent_region;
|
bool highlight_transparent_region;
|
||||||
int x, y;
|
double x, y;
|
||||||
};
|
};
|
||||||
|
|
||||||
static float get_luminance_multiplier(const struct wlr_color_luminances *src_lum,
|
static float get_luminance_multiplier(const struct wlr_color_luminances *src_lum,
|
||||||
|
|
@ -1414,31 +1434,41 @@ static float get_luminance_multiplier(const struct wlr_color_luminances *src_lum
|
||||||
static void scene_entry_render(struct render_list_entry *entry, const struct render_data *data) {
|
static void scene_entry_render(struct render_list_entry *entry, const struct render_data *data) {
|
||||||
struct wlr_scene_node *node = entry->node;
|
struct wlr_scene_node *node = entry->node;
|
||||||
|
|
||||||
|
pixman_region64f_t logical_render_region;
|
||||||
|
pixman_region64f_init(&logical_render_region);
|
||||||
|
pixman_region64f_copy(&logical_render_region, &node->visible);
|
||||||
|
pixman_region64f_translatef(&logical_render_region, -data->logical.x, -data->logical.y);
|
||||||
|
|
||||||
pixman_region32_t render_region;
|
pixman_region32_t render_region;
|
||||||
pixman_region32_init(&render_region);
|
pixman_region32_init(&render_region);
|
||||||
pixman_region32_copy(&render_region, &node->visible);
|
logical_to_buffer_coords(&render_region, &logical_render_region, data, true);
|
||||||
pixman_region32_translate(&render_region, -data->logical.x, -data->logical.y);
|
pixman_region64f_fini(&logical_render_region);
|
||||||
logical_to_buffer_coords(&render_region, data, true);
|
|
||||||
pixman_region32_intersect(&render_region, &render_region, &data->damage);
|
pixman_region32_intersect(&render_region, &render_region, &data->damage);
|
||||||
if (pixman_region32_empty(&render_region)) {
|
if (pixman_region32_empty(&render_region)) {
|
||||||
pixman_region32_fini(&render_region);
|
pixman_region32_fini(&render_region);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = entry->x - data->logical.x;
|
double x = entry->x - data->logical.x;
|
||||||
int y = entry->y - data->logical.y;
|
double y = entry->y - data->logical.y;
|
||||||
|
|
||||||
struct wlr_box dst_box = {
|
struct wlr_fbox node_box = {
|
||||||
.x = x,
|
.x = x,
|
||||||
.y = y,
|
.y = y,
|
||||||
};
|
};
|
||||||
scene_node_get_size(node, &dst_box.width, &dst_box.height);
|
scene_node_get_size(node, &node_box.width, &node_box.height);
|
||||||
transform_output_box(&dst_box, data);
|
struct wlr_box dst_box = {0};
|
||||||
|
transform_output_box(&dst_box, &node_box, data, entry->scale_stretch);
|
||||||
|
|
||||||
|
pixman_region64f_t logical_opaque;
|
||||||
|
pixman_region64f_init(&logical_opaque);
|
||||||
|
scene_node_opaque_region(node, x, y, &logical_opaque);
|
||||||
|
|
||||||
pixman_region32_t opaque;
|
pixman_region32_t opaque;
|
||||||
pixman_region32_init(&opaque);
|
pixman_region32_init(&opaque);
|
||||||
scene_node_opaque_region(node, x, y, &opaque);
|
logical_to_buffer_coords(&opaque, &logical_opaque, data, false);
|
||||||
logical_to_buffer_coords(&opaque, data, false);
|
pixman_region64f_fini(&logical_opaque);
|
||||||
pixman_region32_subtract(&opaque, &render_region, &opaque);
|
pixman_region32_subtract(&opaque, &render_region, &opaque);
|
||||||
|
|
||||||
switch (node->type) {
|
switch (node->type) {
|
||||||
|
|
@ -1845,7 +1875,7 @@ struct wlr_scene_output *wlr_scene_get_scene_output(struct wlr_scene *scene,
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_scene_output_set_position(struct wlr_scene_output *scene_output,
|
void wlr_scene_output_set_position(struct wlr_scene_output *scene_output,
|
||||||
int lx, int ly) {
|
double lx, double ly) {
|
||||||
if (scene_output->x == lx && scene_output->y == ly) {
|
if (scene_output->x == lx && scene_output->y == ly) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1873,8 +1903,9 @@ static bool scene_node_invisible(struct wlr_scene_node *node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct render_list_constructor_data {
|
struct render_list_constructor_data {
|
||||||
struct wlr_box box;
|
struct wlr_fbox box;
|
||||||
struct wl_array *render_list;
|
struct wl_array *render_list;
|
||||||
|
struct wlr_scene_output *scene_output;
|
||||||
bool calculate_visibility;
|
bool calculate_visibility;
|
||||||
bool highlight_transparent_region;
|
bool highlight_transparent_region;
|
||||||
bool fractional_scale;
|
bool fractional_scale;
|
||||||
|
|
@ -1889,8 +1920,23 @@ static bool scene_buffer_is_black_opaque(struct wlr_scene_buffer *scene_buffer)
|
||||||
scene_buffer->opacity == 1.0;
|
scene_buffer->opacity == 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct wlr_scene_node *scene_node_scaling_group(struct wlr_scene_node *node) {
|
||||||
|
struct wlr_scene_node *scaling_group = node;
|
||||||
|
while (true) {
|
||||||
|
if (node->scaling_group) {
|
||||||
|
scaling_group = node;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (node->parent == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
node = &node->parent->node;
|
||||||
|
}
|
||||||
|
return scaling_group;
|
||||||
|
}
|
||||||
|
|
||||||
static bool construct_render_list_iterator(struct wlr_scene_node *node,
|
static bool construct_render_list_iterator(struct wlr_scene_node *node,
|
||||||
int lx, int ly, void *_data) {
|
double lx, double ly, void *_data) {
|
||||||
struct render_list_constructor_data *data = _data;
|
struct render_list_constructor_data *data = _data;
|
||||||
|
|
||||||
if (scene_node_invisible(node)) {
|
if (scene_node_invisible(node)) {
|
||||||
|
|
@ -1921,17 +1967,40 @@ static bool construct_render_list_iterator(struct wlr_scene_node *node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_t intersection;
|
pixman_region64f_t intersection;
|
||||||
pixman_region32_init(&intersection);
|
pixman_region64f_init(&intersection);
|
||||||
pixman_region32_intersect_rect(&intersection, &node->visible,
|
pixman_region64f_intersect_rectf(&intersection, &node->visible,
|
||||||
data->box.x, data->box.y,
|
data->box.x, data->box.y,
|
||||||
data->box.width, data->box.height);
|
data->box.width, data->box.height);
|
||||||
if (pixman_region32_empty(&intersection)) {
|
if (pixman_region64f_empty(&intersection)) {
|
||||||
pixman_region32_fini(&intersection);
|
pixman_region64f_fini(&intersection);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pixman_region32_fini(&intersection);
|
pixman_region64f_fini(&intersection);
|
||||||
|
|
||||||
|
bool scale_stretch = false;
|
||||||
|
if (data->scene_output != NULL) {
|
||||||
|
struct wlr_scene_node *scaling_group = scene_node_scaling_group(node);
|
||||||
|
|
||||||
|
double x, y;
|
||||||
|
wlr_scene_node_coords(scaling_group, &x, &y);
|
||||||
|
|
||||||
|
pixman_region64f_t visible;
|
||||||
|
pixman_region64f_init(&visible);
|
||||||
|
scene_node_bounds(scaling_group, x, y, &visible);
|
||||||
|
|
||||||
|
uint64_t active_outputs;
|
||||||
|
size_t count;
|
||||||
|
struct wlr_scene_output *primary_output = NULL;
|
||||||
|
visible_region_active_outputs(&data->scene_output->scene->outputs, NULL, &visible,
|
||||||
|
&active_outputs, &count, &primary_output);
|
||||||
|
pixman_region64f_fini(&visible);
|
||||||
|
|
||||||
|
scale_stretch = primary_output != NULL &&
|
||||||
|
data->scene_output != primary_output &&
|
||||||
|
data->scene_output->output->scale != primary_output->output->scale;
|
||||||
|
}
|
||||||
|
|
||||||
struct render_list_entry *entry = wl_array_add(data->render_list, sizeof(*entry));
|
struct render_list_entry *entry = wl_array_add(data->render_list, sizeof(*entry));
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
|
|
@ -1942,6 +2011,7 @@ static bool construct_render_list_iterator(struct wlr_scene_node *node,
|
||||||
.node = node,
|
.node = node,
|
||||||
.x = lx,
|
.x = lx,
|
||||||
.y = ly,
|
.y = ly,
|
||||||
|
.scale_stretch = scale_stretch,
|
||||||
.highlight_transparent_region = data->highlight_transparent_region,
|
.highlight_transparent_region = data->highlight_transparent_region,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -2094,11 +2164,12 @@ static enum scene_direct_scanout_result scene_entry_try_direct_scanout(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translate the position from scene coordinates to output coordinates
|
// Translate the position from scene coordinates to output coordinates
|
||||||
pending.buffer_dst_box.x = entry->x - scene_output->x;
|
struct wlr_fbox node_box = {
|
||||||
pending.buffer_dst_box.y = entry->y - scene_output->y;
|
.x = entry->x - scene_output->x,
|
||||||
|
.y = entry->y - scene_output->y
|
||||||
scene_node_get_size(node, &pending.buffer_dst_box.width, &pending.buffer_dst_box.height);
|
};
|
||||||
transform_output_box(&pending.buffer_dst_box, data);
|
scene_node_get_size(node, &node_box.width, &node_box.height);
|
||||||
|
transform_output_box(&pending.buffer_dst_box, &node_box, data, false);
|
||||||
|
|
||||||
struct wlr_buffer *wlr_buffer = buffer->buffer;
|
struct wlr_buffer *wlr_buffer = buffer->buffer;
|
||||||
struct wlr_client_buffer *client_buffer = wlr_client_buffer_get(wlr_buffer);
|
struct wlr_client_buffer *client_buffer = wlr_client_buffer_get(wlr_buffer);
|
||||||
|
|
@ -2275,6 +2346,16 @@ cleanup_transforms:
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool scene_outputs_have_multiple_scale_factors(struct wlr_scene *scene, float scale) {
|
||||||
|
struct wlr_scene_output *scene_output;
|
||||||
|
wl_list_for_each(scene_output, &scene->outputs, link) {
|
||||||
|
if (scene_output->output->enabled && scene_output->output->scale != scale) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
||||||
struct wlr_output_state *state, const struct wlr_scene_output_state_options *options) {
|
struct wlr_output_state *state, const struct wlr_scene_output_state_options *options) {
|
||||||
struct wlr_scene_output_state_options default_options = {0};
|
struct wlr_scene_output_state_options default_options = {0};
|
||||||
|
|
@ -2343,9 +2424,13 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
||||||
render_data.logical.width = render_data.trans_width / render_data.scale;
|
render_data.logical.width = render_data.trans_width / render_data.scale;
|
||||||
render_data.logical.height = render_data.trans_height / render_data.scale;
|
render_data.logical.height = render_data.trans_height / render_data.scale;
|
||||||
|
|
||||||
|
bool multiple_output_scales =
|
||||||
|
scene_outputs_have_multiple_scale_factors(scene_output->scene, render_data.scale);
|
||||||
|
|
||||||
struct render_list_constructor_data list_con = {
|
struct render_list_constructor_data list_con = {
|
||||||
.box = render_data.logical,
|
.box = render_data.logical,
|
||||||
.render_list = &scene_output->render_list,
|
.render_list = &scene_output->render_list,
|
||||||
|
.scene_output = multiple_output_scales ? scene_output : NULL,
|
||||||
.calculate_visibility = scene_output->scene->calculate_visibility,
|
.calculate_visibility = scene_output->scene->calculate_visibility,
|
||||||
.highlight_transparent_region = scene_output->scene->highlight_transparent_region,
|
.highlight_transparent_region = scene_output->scene->highlight_transparent_region,
|
||||||
.fractional_scale = floor(render_data.scale) != render_data.scale,
|
.fractional_scale = floor(render_data.scale) != render_data.scale,
|
||||||
|
|
@ -2516,13 +2601,17 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
||||||
// that may have been omitted from the render list via the black
|
// that may have been omitted from the render list via the black
|
||||||
// rect optimization. In order to ensure we don't cull background
|
// rect optimization. In order to ensure we don't cull background
|
||||||
// rendering in that black rect region, consider the node's visibility.
|
// rendering in that black rect region, consider the node's visibility.
|
||||||
|
pixman_region64f_t logical_opaque;
|
||||||
|
pixman_region64f_init(&logical_opaque);
|
||||||
|
scene_node_opaque_region(entry->node, entry->x, entry->y, &logical_opaque);
|
||||||
|
pixman_region64f_intersect(&logical_opaque, &logical_opaque, &entry->node->visible);
|
||||||
|
pixman_region64f_translatef(&logical_opaque, -scene_output->x, -scene_output->y);
|
||||||
|
|
||||||
pixman_region32_t opaque;
|
pixman_region32_t opaque;
|
||||||
pixman_region32_init(&opaque);
|
pixman_region32_init(&opaque);
|
||||||
scene_node_opaque_region(entry->node, entry->x, entry->y, &opaque);
|
logical_to_buffer_coords(&opaque, &logical_opaque, &render_data, false);
|
||||||
pixman_region32_intersect(&opaque, &opaque, &entry->node->visible);
|
pixman_region64f_fini(&logical_opaque);
|
||||||
|
|
||||||
pixman_region32_translate(&opaque, -scene_output->x, -scene_output->y);
|
|
||||||
logical_to_buffer_coords(&opaque, &render_data, false);
|
|
||||||
pixman_region32_subtract(&background, &background, &opaque);
|
pixman_region32_subtract(&background, &background, &opaque);
|
||||||
pixman_region32_fini(&opaque);
|
pixman_region32_fini(&opaque);
|
||||||
}
|
}
|
||||||
|
|
@ -2655,8 +2744,8 @@ void wlr_scene_output_send_frame_done(struct wlr_scene_output *scene_output,
|
||||||
scene_output, now);
|
scene_output, now);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box,
|
static void scene_output_for_each_scene_buffer(const struct wlr_fbox *output_box,
|
||||||
struct wlr_scene_node *node, int lx, int ly,
|
struct wlr_scene_node *node, double lx, double ly,
|
||||||
wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) {
|
wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) {
|
||||||
if (!node->enabled) {
|
if (!node->enabled) {
|
||||||
return;
|
return;
|
||||||
|
|
@ -2666,10 +2755,10 @@ static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box,
|
||||||
ly += node->y;
|
ly += node->y;
|
||||||
|
|
||||||
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
if (node->type == WLR_SCENE_NODE_BUFFER) {
|
||||||
struct wlr_box node_box = { .x = lx, .y = ly };
|
struct wlr_fbox node_box = { .x = lx, .y = ly };
|
||||||
scene_node_get_size(node, &node_box.width, &node_box.height);
|
scene_node_get_size(node, &node_box.width, &node_box.height);
|
||||||
|
|
||||||
if (wlr_box_intersects(output_box, &node_box)) {
|
if (wlr_fbox_intersects(output_box, &node_box)) {
|
||||||
struct wlr_scene_buffer *scene_buffer =
|
struct wlr_scene_buffer *scene_buffer =
|
||||||
wlr_scene_buffer_from_node(node);
|
wlr_scene_buffer_from_node(node);
|
||||||
user_iterator(scene_buffer, lx, ly, user_data);
|
user_iterator(scene_buffer, lx, ly, user_data);
|
||||||
|
|
@ -2686,9 +2775,11 @@ static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box,
|
||||||
|
|
||||||
void wlr_scene_output_for_each_buffer(struct wlr_scene_output *scene_output,
|
void wlr_scene_output_for_each_buffer(struct wlr_scene_output *scene_output,
|
||||||
wlr_scene_buffer_iterator_func_t iterator, void *user_data) {
|
wlr_scene_buffer_iterator_func_t iterator, void *user_data) {
|
||||||
struct wlr_box box = { .x = scene_output->x, .y = scene_output->y };
|
struct wlr_fbox box = { .x = scene_output->x, .y = scene_output->y };
|
||||||
wlr_output_effective_resolution(scene_output->output,
|
int width, height;
|
||||||
&box.width, &box.height);
|
wlr_output_effective_resolution(scene_output->output, &width, &height);
|
||||||
|
box.width = width;
|
||||||
|
box.height = height;
|
||||||
scene_output_for_each_scene_buffer(&box, &scene_output->scene->tree.node, 0, 0,
|
scene_output_for_each_scene_buffer(&box, &scene_output->scene->tree.node, 0, 0,
|
||||||
iterator, user_data);
|
iterator, user_data);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
48
util/box.c
48
util/box.c
|
|
@ -82,6 +82,34 @@ bool wlr_box_intersection(struct wlr_box *dest, const struct wlr_box *box_a,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wlr_fbox_intersection(struct wlr_fbox *dest, const struct wlr_fbox *box_a,
|
||||||
|
const struct wlr_fbox *box_b) {
|
||||||
|
bool a_empty = wlr_fbox_empty(box_a);
|
||||||
|
bool b_empty = wlr_fbox_empty(box_b);
|
||||||
|
|
||||||
|
if (a_empty || b_empty) {
|
||||||
|
*dest = (struct wlr_fbox){0};
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double x1 = fmax(box_a->x, box_b->x);
|
||||||
|
double y1 = fmax(box_a->y, box_b->y);
|
||||||
|
double x2 = fmin(box_a->x + box_a->width, box_b->x + box_b->width);
|
||||||
|
double y2 = fmin(box_a->y + box_a->height, box_b->y + box_b->height);
|
||||||
|
|
||||||
|
dest->x = x1;
|
||||||
|
dest->y = y1;
|
||||||
|
dest->width = x2 - x1;
|
||||||
|
dest->height = y2 - y1;
|
||||||
|
|
||||||
|
if (wlr_fbox_empty(dest)) {
|
||||||
|
*dest = (struct wlr_fbox){0};
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool wlr_box_contains_point(const struct wlr_box *box, double x, double y) {
|
bool wlr_box_contains_point(const struct wlr_box *box, double x, double y) {
|
||||||
if (wlr_box_empty(box)) {
|
if (wlr_box_empty(box)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -102,6 +130,17 @@ bool wlr_box_contains_box(const struct wlr_box *bigger, const struct wlr_box *sm
|
||||||
smaller->y + smaller->height <= bigger->y + bigger->height;
|
smaller->y + smaller->height <= bigger->y + bigger->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wlr_fbox_contains_box(const struct wlr_fbox *bigger, const struct wlr_fbox *smaller) {
|
||||||
|
if (wlr_fbox_empty(bigger) || wlr_fbox_empty(smaller)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return smaller->x >= bigger->x &&
|
||||||
|
smaller->x + smaller->width <= bigger->x + bigger->width &&
|
||||||
|
smaller->y >= bigger->y &&
|
||||||
|
smaller->y + smaller->height <= bigger->y + bigger->height;
|
||||||
|
}
|
||||||
|
|
||||||
bool wlr_box_intersects(const struct wlr_box *a, const struct wlr_box *b) {
|
bool wlr_box_intersects(const struct wlr_box *a, const struct wlr_box *b) {
|
||||||
if (wlr_box_empty(a) || wlr_box_empty(b)) {
|
if (wlr_box_empty(a) || wlr_box_empty(b)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -111,6 +150,15 @@ bool wlr_box_intersects(const struct wlr_box *a, const struct wlr_box *b) {
|
||||||
a->y < b->y + b->height && b->y < a->y + a->height;
|
a->y < b->y + b->height && b->y < a->y + a->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool wlr_fbox_intersects(const struct wlr_fbox *a, const struct wlr_fbox *b) {
|
||||||
|
if (wlr_fbox_empty(a) || wlr_fbox_empty(b)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return a->x < b->x + b->width && b->x < a->x + a->width &&
|
||||||
|
a->y < b->y + b->height && b->y < a->y + a->height;
|
||||||
|
}
|
||||||
|
|
||||||
void wlr_box_transform(struct wlr_box *dest, const struct wlr_box *box,
|
void wlr_box_transform(struct wlr_box *dest, const struct wlr_box *box,
|
||||||
enum wl_output_transform transform, int width, int height) {
|
enum wl_output_transform transform, int width, int height) {
|
||||||
struct wlr_box src = {0};
|
struct wlr_box src = {0};
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,54 @@ void wlr_region_scale_xy(pixman_region32_t *dst, const pixman_region32_t *src,
|
||||||
free(dst_rects);
|
free(dst_rects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wlr_region_scalef(pixman_region32_t *dst, const pixman_region64f_t *src,
|
||||||
|
float scale) {
|
||||||
|
wlr_region_scalef_xy(dst, src, scale, scale);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_region_scalef_xy(pixman_region32_t *dst, const pixman_region64f_t *src,
|
||||||
|
float scale_x, float scale_y) {
|
||||||
|
int nrects;
|
||||||
|
const pixman_box64f_t *src_rects = pixman_region64f_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) {
|
||||||
|
dst_rects[i].x1 = round(src_rects[i].x1 * scale_x);
|
||||||
|
dst_rects[i].x2 = round(src_rects[i].x2 * scale_x);
|
||||||
|
dst_rects[i].y1 = round(src_rects[i].y1 * scale_y);
|
||||||
|
dst_rects[i].y2 = round(src_rects[i].y2 * scale_y);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_region32_fini(dst);
|
||||||
|
pixman_region32_init_rects(dst, dst_rects, nrects);
|
||||||
|
free(dst_rects);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wlr_region64f_copy_from_region32(pixman_region64f_t *dst, const pixman_region32_t *src) {
|
||||||
|
int nrects;
|
||||||
|
const pixman_box32_t *src_rects = pixman_region32_rectangles(src, &nrects);
|
||||||
|
|
||||||
|
pixman_box64f_t *dst_rects = malloc(nrects * sizeof(pixman_box64f_t));
|
||||||
|
if (dst_rects == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < nrects; ++i) {
|
||||||
|
dst_rects[i].x1 = src_rects[i].x1;
|
||||||
|
dst_rects[i].x2 = src_rects[i].x2;
|
||||||
|
dst_rects[i].y1 = src_rects[i].y1;
|
||||||
|
dst_rects[i].y2 = src_rects[i].y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_region64f_fini(dst);
|
||||||
|
pixman_region64f_init_rects(dst, dst_rects, nrects);
|
||||||
|
free(dst_rects);
|
||||||
|
}
|
||||||
|
|
||||||
void wlr_region_transform(pixman_region32_t *dst, const pixman_region32_t *src,
|
void wlr_region_transform(pixman_region32_t *dst, const pixman_region32_t *src,
|
||||||
enum wl_output_transform transform, int width, int height) {
|
enum wl_output_transform transform, int width, int height) {
|
||||||
if (transform == WL_OUTPUT_TRANSFORM_NORMAL) {
|
if (transform == WL_OUTPUT_TRANSFORM_NORMAL) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue