scene: use fractional sizes

Signed-off-by: Loukas Agorgianitis <loukas@agorgianitis.com>
This commit is contained in:
Loukas Agorgianitis 2025-04-25 20:32:52 +03:00
parent 3f5d8e1d48
commit d327cece9e
No known key found for this signature in database
GPG key ID: DDC6FA7D5BB332E6
3 changed files with 51 additions and 46 deletions

View file

@ -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);

View file

@ -190,7 +190,7 @@ 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_region32_t opaque_region;
enum wlr_color_transfer_function transfer_function; enum wlr_color_transfer_function transfer_function;
@ -538,7 +538,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.

View file

@ -217,7 +217,7 @@ 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,
double sx, double 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, double lx, double 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;
@ -235,10 +235,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_intersection(&node_box, &node_box, box) && if (wlr_fbox_intersection(&node_box, &node_box, box) &&
iterator(node, lx, ly, user_data)) { iterator(node, lx, ly, user_data)) {
return true; return true;
} }
@ -248,7 +248,7 @@ 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) {
double x, y; double x, y;
wlr_scene_node_coords(node, &x, &y); wlr_scene_node_coords(node, &x, &y);
@ -258,7 +258,7 @@ static bool scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box,
static void scene_node_opaque_region(struct wlr_scene_node *node, double x, double y, static void scene_node_opaque_region(struct wlr_scene_node *node, double x, double y,
pixman_region32_t *opaque) { pixman_region32_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) {
@ -292,7 +292,7 @@ static void scene_node_opaque_region(struct wlr_scene_node *node, double x, doub
struct scene_update_data { struct scene_update_data {
pixman_region32_t *visible; pixman_region32_t *visible;
const pixman_region32_t *update_region; const pixman_region32_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;
@ -325,7 +325,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;
@ -349,20 +349,20 @@ 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 scale_box(struct wlr_box *box, struct wlr_fbox *src, float scale) {
box->width = scale_length(box->width, box->x, scale); box->width = scale_length(src->width, src->x, scale);
box->height = scale_length(box->height, box->y, scale); box->height = scale_length(src->height, src->y, scale);
box->x = round(box->x * scale); box->x = round(src->x * scale);
box->y = round(box->y * scale); box->y = round(src->y * scale);
} }
static void transform_output_box(struct wlr_box *box, const struct render_data *data) { static void transform_output_box(struct wlr_box *box, struct wlr_fbox *src, 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); scale_box(box, src, 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);
} }
@ -550,7 +550,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) {
@ -559,7 +559,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 {
@ -575,7 +575,7 @@ static bool scene_node_update_iterator(struct wlr_scene_node *node,
double lx, double 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_region32_subtract(&node->visible, &node->visible, data->update_region);
@ -634,7 +634,7 @@ 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_region32_union_rect(visible, visible, x, y, width, height);
} }
@ -1088,7 +1088,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;
} }
@ -1199,7 +1199,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;
@ -1217,9 +1217,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;
} }
@ -1404,9 +1405,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
}; };
@ -1452,12 +1453,13 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren
double x = entry->x - data->logical.x; double x = entry->x - data->logical.x;
double 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);
pixman_region32_t opaque; pixman_region32_t opaque;
pixman_region32_init(&opaque); pixman_region32_init(&opaque);
@ -1877,7 +1879,7 @@ 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;
bool calculate_visibility; bool calculate_visibility;
bool highlight_transparent_region; bool highlight_transparent_region;
@ -2103,11 +2105,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);
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);
@ -2632,7 +2635,7 @@ 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, double lx, double 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) {
@ -2643,11 +2646,11 @@ 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);
struct wlr_box intersection; struct wlr_fbox intersection;
if (wlr_box_intersection(&intersection, output_box, &node_box)) { if (wlr_fbox_intersection(&intersection, 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);
@ -2664,9 +2667,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);
} }