1
0
Fork 0
mirror of https://github.com/yshui/picom.git synced 2025-04-21 18:03:02 -04:00

renderer/layout: use dynarr for layers

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2024-06-04 17:31:27 +01:00
parent 9579cde5bd
commit 5513992060
No known key found for this signature in database
GPG key ID: D3A4405BE6CC17F4
4 changed files with 40 additions and 48 deletions

View file

@ -1,12 +1,13 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
#include "command_builder.h"
#include "common.h"
#include "layout.h"
#include "utils/dynarr.h"
#include "wm/win.h"
#include "command_builder.h"
/// Generate commands for rendering the body of the window in `layer`.
///
/// @param[in] frame_region frame region of the window, in window local coordinates
@ -201,14 +202,14 @@ command_for_blur(struct layer *layer, struct backend_command *cmd,
static inline void
command_builder_apply_transparent_clipping(struct layout *layout, region_t *scratch_region) {
// Going from top down, apply transparent-clipping
if (layout->len == 0) {
if (dynarr_is_empty(layout->layers)) {
return;
}
pixman_region32_clear(scratch_region);
auto end = &layout->commands[layout->number_of_commands - 1];
auto begin = &layout->commands[layout->first_layer_start - 1];
auto layer = &layout->layers[layout->len - 1];
auto layer = &dynarr_last(layout->layers);
// `layer_start` is one before the first command for this layer
auto layer_start = end - layer->number_of_commands;
for (auto i = end; i != begin; i--) {
@ -364,8 +365,7 @@ void command_builder_build(struct command_builder *cb, struct layout *layout, bo
const struct win_option *wintype_options) {
unsigned ncmds = 1;
for (unsigned i = 0; i < layout->len; i++) {
auto layer = &layout->layers[i];
dynarr_foreach(layout->layers, layer) {
auto mode = win_calc_mode_raw(layer->win);
if (layer->win->blur_background && layer->blur_opacity > 0 &&
(force_blend || mode == WMODE_TRANS || layer->opacity < 1.0 ||
@ -387,8 +387,7 @@ void command_builder_build(struct command_builder *cb, struct layout *layout, bo
layout->commands = list->commands;
auto cmd = &layout->commands[ncmds - 1];
for (int i = to_int_checked(layout->len) - 1; i >= 0; i--) {
auto layer = &layout->layers[i];
dynarr_foreach_rev(layout->layers, layer) {
auto last = cmd;
auto frame_region = win_get_region_frame_local_by_val(layer->win);
pixman_region32_translate(&frame_region, layer->window.origin.x,

View file

@ -1,11 +1,13 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
#include "damage.h"
#include "layout.h"
#include "region.h"
#include "utils/dynarr.h"
#include "wm/win.h"
#include "damage.h"
static inline bool attr_unused layer_key_eq(const struct layer_key *a,
const struct layer_key *b) {
if (!a->generation || !b->generation) {
@ -160,15 +162,12 @@ void layout_manager_damage(struct layout_manager *lm, unsigned buffer_age,
for (unsigned l = 0; l <= buffer_age; l++) {
log_trace("Layout[%d]: ", -l);
auto layout = layout_manager_layout(lm, l);
for (unsigned i = 0; i < layout->len; i++) {
dynarr_foreach(layout->layers, layer) {
log_trace("\t%#010x %dx%d+%dx%d (prev %d, next %d)",
layout->layers[i].key.window,
layout->layers[i].window.size.width,
layout->layers[i].window.size.height,
layout->layers[i].window.origin.x,
layout->layers[i].window.origin.y,
layout->layers[i].prev_rank,
layout->layers[i].next_rank);
layer->key.window, layer->window.size.width,
layer->window.size.height,
layer->window.origin.x, layer->window.origin.y,
layer->prev_rank, layer->next_rank);
}
}
}
@ -206,7 +205,7 @@ void layout_manager_damage(struct layout_manager *lm, unsigned buffer_age,
// Skip layers in the past layout doesn't contain a window that has a
// match in the remaining layers of the current layout; and vice versa.
while (past_layer_rank_target < past_layout->len) {
while (past_layer_rank_target < dynarr_len(past_layout->layers)) {
past_layer_curr_rank =
layer_next_rank(lm, buffer_age, past_layer_rank_target);
if (past_layer_curr_rank >= (int)curr_layer_rank) {
@ -214,7 +213,7 @@ void layout_manager_damage(struct layout_manager *lm, unsigned buffer_age,
}
past_layer_rank_target++;
};
while (curr_layer_rank_target < curr_layout->len) {
while (curr_layer_rank_target < dynarr_len(curr_layout->layers)) {
curr_layer_past_rank =
layer_prev_rank(lm, buffer_age, curr_layer_rank_target);
if (curr_layer_past_rank >= (int)past_layer_rank) {
@ -258,10 +257,11 @@ void layout_manager_damage(struct layout_manager *lm, unsigned buffer_age,
curr_layer += 1;
}
if (past_layer_rank >= past_layout->len || curr_layer_rank >= curr_layout->len) {
if (past_layer_rank >= dynarr_len(past_layout->layers) ||
curr_layer_rank >= dynarr_len(curr_layout->layers)) {
// No more matching layers left.
assert(past_layer_rank >= past_layout->len &&
curr_layer_rank >= curr_layout->len);
assert(past_layer_rank >= dynarr_len(past_layout->layers) &&
curr_layer_rank >= dynarr_len(curr_layout->layers));
break;
}

View file

@ -9,6 +9,7 @@
#include "command_builder.h"
#include "common.h"
#include "region.h"
#include "utils/dynarr.h"
#include "utils/list.h"
#include "utils/misc.h"
#include "wm/win.h"
@ -117,11 +118,16 @@ out:
return to_paint;
}
static void layer_deinit(struct layer *layer) {
pixman_region32_fini(&layer->damaged);
}
static void layer_init(struct layer *layer) {
pixman_region32_init(&layer->damaged);
}
static void layout_deinit(struct layout *layout) {
for (unsigned i = 0; i < layout->len; i++) {
pixman_region32_fini(&layout->layers[i].damaged);
}
free(layout->layers);
dynarr_free(layout->layers, layer_deinit);
command_builder_command_list_free(layout->commands);
*layout = (struct layout){};
}
@ -136,6 +142,7 @@ struct layout_manager *layout_manager_new(unsigned max_buffer_age) {
pixman_region32_init(&planner->scratch_region);
for (unsigned i = 0; i <= max_buffer_age; i++) {
planner->layouts[i] = (struct layout){};
planner->layouts[i].layers = dynarr_new(struct layer, 5);
}
return planner;
}
@ -176,17 +183,7 @@ void layout_manager_append_layout(struct layout_manager *lm, struct wm *wm,
layout->root_image_generation = root_pixmap_generation;
unsigned nlayers = wm_stack_num_managed_windows(wm);
if (nlayers > layout->capacity) {
struct layer *new_layers =
realloc(layout->layers, nlayers * sizeof(struct layer));
BUG_ON(new_layers == NULL);
for (unsigned i = layout->capacity; i < nlayers; i++) {
pixman_region32_init(&new_layers[i].damaged);
}
layout->capacity = nlayers;
layout->layers = new_layers;
}
dynarr_resize(layout->layers, nlayers, layer_init, layer_deinit);
layout->size = size;
unsigned rank = 0;
@ -210,7 +207,7 @@ void layout_manager_append_layout(struct layout_manager *lm, struct wm *wm,
rank++;
assert(rank <= nlayers);
}
layout->len = rank;
dynarr_resize(layout->layers, rank, layer_init, layer_deinit);
// Update indices. If a layer exist in both prev_layout and current layout,
// we could update the index using next_rank; if a layer no longer exist in
@ -225,8 +222,8 @@ void layout_manager_append_layout(struct layout_manager *lm, struct wm *wm,
}
// And finally, if a layer in current layout didn't exist in prev_layout, add a
// new index for it.
for (unsigned i = 0; i < layout->len; i++) {
if (layout->layers[i].prev_rank != -1) {
dynarr_foreach(layout->layers, layer) {
if (layer->prev_rank != -1) {
continue;
}
if (!list_is_empty(&lm->free_indices)) {
@ -236,8 +233,8 @@ void layout_manager_append_layout(struct layout_manager *lm, struct wm *wm,
} else {
index = cmalloc(struct layer_index);
}
index->key = layout->layers[i].key;
index->index = i;
index->key = layer->key;
index->index = to_u32_checked(layer - layout->layers);
HASH_ADD(hh, lm->layer_indices, key, sizeof(index->key), index);
}
}

View file

@ -76,11 +76,7 @@ struct layout {
ivec2 size;
/// The root image generation, see `struct session::root_image_generation`
uint64_t root_image_generation;
/// Number of layers in `layers`
unsigned len;
/// Capacity of `layers`
unsigned capacity;
/// Layers as a flat array, from bottom to top in stack order.
/// Layers as a flat array, from bottom to top in stack order. This is a dynarr.
struct layer *layers;
/// Number of commands in `commands`
unsigned number_of_commands;