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

View file

@ -190,7 +190,7 @@ struct wlr_scene_buffer {
float opacity;
enum wlr_scale_filter_mode filter_mode;
struct wlr_fbox src_box;
int dst_width, dst_height;
double dst_width, dst_height;
enum wl_output_transform transform;
pixman_region32_t opaque_region;
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.
*/
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.

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,
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) {
if (!node->enabled) {
return false;
@ -235,10 +235,10 @@ static bool _scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box
break;
case WLR_SCENE_NODE_RECT:
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);
if (wlr_box_intersection(&node_box, &node_box, box) &&
if (wlr_fbox_intersection(&node_box, &node_box, box) &&
iterator(node, lx, ly, user_data)) {
return true;
}
@ -248,7 +248,7 @@ static bool _scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box
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) {
double 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,
pixman_region32_t *opaque) {
int width, height;
double width, height;
scene_node_get_size(node, &width, &height);
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 {
pixman_region32_t *visible;
const pixman_region32_t *update_region;
struct wlr_box update_box;
struct wlr_fbox update_box;
struct wl_list *outputs;
bool calculate_visibility;
bool restack_xwayland_surfaces;
@ -325,7 +325,7 @@ static void scale_region(pixman_region32_t *region, float scale, bool round_up)
struct render_data {
enum wl_output_transform transform;
float scale;
struct wlr_box logical;
struct wlr_fbox logical;
int trans_width, trans_height;
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);
}
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);
}
static void scale_box(struct wlr_box *box, float scale) {
box->width = scale_length(box->width, box->x, scale);
box->height = scale_length(box->height, box->y, scale);
box->x = round(box->x * scale);
box->y = round(box->y * scale);
static void scale_box(struct wlr_box *box, struct wlr_fbox *src, float scale) {
box->width = scale_length(src->width, src->x, scale);
box->height = scale_length(src->height, src->y, scale);
box->x = round(src->x * 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);
scale_box(box, data->scale);
scale_box(box, src, data->scale);
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,
struct wlr_box *box, struct scene_update_data *data) {
struct wlr_fbox *box, struct scene_update_data *data) {
struct wlr_xwayland_surface *xwayland_surface =
scene_node_try_get_managed_xwayland_surface(node);
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
// 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) {
wlr_xwayland_surface_restack(xwayland_surface, data->restack_above, XCB_STACK_MODE_BELOW);
} else {
@ -575,7 +575,7 @@ static bool scene_node_update_iterator(struct wlr_scene_node *node,
double lx, double ly, void *_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);
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;
}
int width, height;
double width, height;
scene_node_get_size(node, &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,
int width, int height) {
double width, double height) {
if (scene_buffer->dst_width == width && scene_buffer->dst_height == height) {
return;
}
@ -1199,7 +1199,7 @@ static struct wlr_texture *scene_buffer_get_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;
*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;
*height = scene_buffer->dst_height;
} else {
*width = scene_buffer->buffer_width;
*height = scene_buffer->buffer_height;
wlr_output_transform_coords(scene_buffer->transform, width, height);
int w = scene_buffer->buffer_width, h = scene_buffer->buffer_height;
wlr_output_transform_coords(scene_buffer->transform, &w, &h);
*width = w;
*height = h;
}
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,
double lx, double ly, double *nx, double *ny) {
struct wlr_box box = {
.x = floor(lx),
.y = floor(ly),
struct wlr_fbox box = {
.x = lx,
.y = ly,
.width = 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 y = entry->y - data->logical.y;
struct wlr_box dst_box = {
struct wlr_fbox node_box = {
.x = x,
.y = y,
};
scene_node_get_size(node, &dst_box.width, &dst_box.height);
transform_output_box(&dst_box, data);
scene_node_get_size(node, &node_box.width, &node_box.height);
struct wlr_box dst_box = {0};
transform_output_box(&dst_box, &node_box, data);
pixman_region32_t 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 wlr_box box;
struct wlr_fbox box;
struct wl_array *render_list;
bool calculate_visibility;
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
pending.buffer_dst_box.x = entry->x - scene_output->x;
pending.buffer_dst_box.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);
struct wlr_fbox node_box = {
.x = entry->x - scene_output->x,
.y = entry->y - scene_output->y
};
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_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);
}
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,
wlr_scene_buffer_iterator_func_t user_iterator, void *user_data) {
if (!node->enabled) {
@ -2643,11 +2646,11 @@ static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box,
ly += node->y;
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);
struct wlr_box intersection;
if (wlr_box_intersection(&intersection, output_box, &node_box)) {
struct wlr_fbox intersection;
if (wlr_fbox_intersection(&intersection, output_box, &node_box)) {
struct wlr_scene_buffer *scene_buffer =
wlr_scene_buffer_from_node(node);
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,
wlr_scene_buffer_iterator_func_t iterator, void *user_data) {
struct wlr_box box = { .x = scene_output->x, .y = scene_output->y };
wlr_output_effective_resolution(scene_output->output,
&box.width, &box.height);
struct wlr_fbox box = { .x = scene_output->x, .y = scene_output->y };
int width, 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,
iterator, user_data);
}