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:
parent
9579cde5bd
commit
5513992060
4 changed files with 40 additions and 48 deletions
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue