mirror of https://github.com/yshui/picom.git
core: move damage ring related fields in session_t into a separate struct
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
0e9e0688b8
commit
d3c2e01fb0
|
@ -42,17 +42,7 @@ region_t get_damage(session_t *ps, bool all_damage) {
|
|||
}
|
||||
|
||||
pixman_region32_init(®ion);
|
||||
if (buffer_age == -1 || buffer_age > ps->ndamage) {
|
||||
pixman_region32_copy(®ion, &ps->screen_reg);
|
||||
} else {
|
||||
for (int i = 0; i < buffer_age; i++) {
|
||||
auto curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage;
|
||||
log_trace("damage index: %d, damage ring offset: %td", i, curr);
|
||||
dump_region(&ps->damage_ring[curr]);
|
||||
pixman_region32_union(®ion, ®ion, &ps->damage_ring[curr]);
|
||||
}
|
||||
pixman_region32_intersect(®ion, ®ion, &ps->screen_reg);
|
||||
}
|
||||
damage_ring_collect(&ps->damage_ring, &ps->screen_reg, ®ion, buffer_age);
|
||||
return region;
|
||||
}
|
||||
|
||||
|
@ -529,11 +519,7 @@ bool paint_all_new(session_t *ps, struct managed_win *const t) {
|
|||
}
|
||||
|
||||
// Move the head of the damage ring
|
||||
ps->damage = ps->damage - 1;
|
||||
if (ps->damage < ps->damage_ring) {
|
||||
ps->damage = ps->damage_ring + ps->ndamage - 1;
|
||||
}
|
||||
pixman_region32_clear(ps->damage);
|
||||
damage_ring_advance(&ps->damage_ring);
|
||||
|
||||
if (ps->backend_data->ops->present) {
|
||||
// Present the rendered scene
|
||||
|
|
45
src/common.h
45
src/common.h
|
@ -134,6 +134,18 @@ struct shader_info {
|
|||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
struct damage_ring {
|
||||
/// Cache a xfixes region so we don't need to allocate it every time.
|
||||
/// A workaround for yshui/picom#301
|
||||
xcb_xfixes_region_t x_region;
|
||||
/// The region needs to painted on next paint.
|
||||
int cursor;
|
||||
/// The region damaged on the last paint.
|
||||
region_t *damages;
|
||||
/// Number of damage regions we track
|
||||
int count;
|
||||
};
|
||||
|
||||
/// Structure containing all necessary data for a session.
|
||||
typedef struct session {
|
||||
// === Event handlers ===
|
||||
|
@ -250,16 +262,8 @@ typedef struct session {
|
|||
/// to the screen that's neither included in the current render, nor on the
|
||||
/// screen.
|
||||
bool render_queued;
|
||||
|
||||
/// Cache a xfixes region so we don't need to allocate it every time.
|
||||
/// A workaround for yshui/picom#301
|
||||
xcb_xfixes_region_t damaged_region;
|
||||
/// The region needs to painted on next paint.
|
||||
region_t *damage;
|
||||
/// The region damaged on the last paint.
|
||||
region_t *damage_ring;
|
||||
/// Number of damage regions we track
|
||||
int ndamage;
|
||||
/// For tracking damage regions
|
||||
struct damage_ring damage_ring;
|
||||
/// Whether all windows are currently redirected.
|
||||
bool redirected;
|
||||
/// Pre-generated alpha pictures.
|
||||
|
@ -518,3 +522,24 @@ static inline void wintype_arr_enable(bool arr[]) {
|
|||
arr[i] = true;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void damage_ring_advance(struct damage_ring *ring) {
|
||||
ring->cursor--;
|
||||
if (ring->cursor < 0) {
|
||||
ring->cursor += ring->count;
|
||||
}
|
||||
pixman_region32_clear(&ring->damages[ring->cursor]);
|
||||
}
|
||||
|
||||
static inline void damage_ring_collect(struct damage_ring *ring, region_t *all_region,
|
||||
region_t *region, int buffer_age) {
|
||||
if (buffer_age == -1 || buffer_age > ring->count) {
|
||||
pixman_region32_copy(region, all_region);
|
||||
} else {
|
||||
for (int i = 0; i < buffer_age; i++) {
|
||||
auto curr = (ring->cursor + i) % ring->count;
|
||||
pixman_region32_union(region, region, &ring->damages[curr]);
|
||||
}
|
||||
pixman_region32_intersect(region, region, all_region);
|
||||
}
|
||||
}
|
|
@ -629,12 +629,12 @@ static inline void repair_win(session_t *ps, struct managed_win *w) {
|
|||
}
|
||||
win_extents(w, &parts);
|
||||
} else {
|
||||
auto cookie =
|
||||
xcb_damage_subtract(ps->c.c, w->damage, XCB_NONE, ps->damaged_region);
|
||||
auto cookie = xcb_damage_subtract(ps->c.c, w->damage, XCB_NONE,
|
||||
ps->damage_ring.x_region);
|
||||
if (!ps->o.show_all_xerrors) {
|
||||
set_ignore_cookie(&ps->c, cookie);
|
||||
}
|
||||
x_fetch_region(&ps->c, ps->damaged_region, &parts);
|
||||
x_fetch_region(&ps->c, ps->damage_ring.x_region, &parts);
|
||||
pixman_region32_translate(&parts, w->g.x + w->g.border_width,
|
||||
w->g.y + w->g.border_width);
|
||||
}
|
||||
|
|
44
src/picom.c
44
src/picom.c
|
@ -464,7 +464,9 @@ void add_damage(session_t *ps, const region_t *damage) {
|
|||
}
|
||||
log_trace("Adding damage: ");
|
||||
dump_region(damage);
|
||||
pixman_region32_union(ps->damage, ps->damage, (region_t *)damage);
|
||||
|
||||
auto cursor = &ps->damage_ring.damages[ps->damage_ring.cursor];
|
||||
pixman_region32_union(cursor, cursor, (region_t *)damage);
|
||||
}
|
||||
|
||||
// === Fading ===
|
||||
|
@ -853,10 +855,10 @@ static void configure_root(session_t *ps) {
|
|||
}
|
||||
|
||||
if (ps->redirected) {
|
||||
for (int i = 0; i < ps->ndamage; i++) {
|
||||
pixman_region32_clear(&ps->damage_ring[i]);
|
||||
for (int i = 0; i < ps->damage_ring.count; i++) {
|
||||
pixman_region32_clear(&ps->damage_ring.damages[i]);
|
||||
}
|
||||
ps->damage = ps->damage_ring + ps->ndamage - 1;
|
||||
ps->damage_ring.cursor = ps->damage_ring.count - 1;
|
||||
#ifdef CONFIG_OPENGL
|
||||
// GLX root change callback
|
||||
if (BKEND_GLX == ps->o.backend && ps->o.legacy_backends) {
|
||||
|
@ -1531,15 +1533,15 @@ static bool redirect_start(session_t *ps) {
|
|||
|
||||
if (!ps->o.legacy_backends) {
|
||||
assert(ps->backend_data);
|
||||
ps->ndamage = ps->backend_data->ops->max_buffer_age;
|
||||
ps->damage_ring.count = ps->backend_data->ops->max_buffer_age;
|
||||
} else {
|
||||
ps->ndamage = maximum_buffer_age(ps);
|
||||
ps->damage_ring.count = maximum_buffer_age(ps);
|
||||
}
|
||||
ps->damage_ring = ccalloc(ps->ndamage, region_t);
|
||||
ps->damage = ps->damage_ring + ps->ndamage - 1;
|
||||
ps->damage_ring.damages = ccalloc(ps->damage_ring.count, region_t);
|
||||
ps->damage_ring.cursor = ps->damage_ring.count - 1;
|
||||
|
||||
for (int i = 0; i < ps->ndamage; i++) {
|
||||
pixman_region32_init(&ps->damage_ring[i]);
|
||||
for (int i = 0; i < ps->damage_ring.count; i++) {
|
||||
pixman_region32_init(&ps->damage_ring.damages[i]);
|
||||
}
|
||||
|
||||
ps->frame_pacing = !ps->o.no_frame_pacing && ps->o.vsync;
|
||||
|
@ -1613,12 +1615,13 @@ static void unredirect(session_t *ps) {
|
|||
}
|
||||
|
||||
// Free the damage ring
|
||||
for (int i = 0; i < ps->ndamage; ++i) {
|
||||
pixman_region32_fini(&ps->damage_ring[i]);
|
||||
for (int i = 0; i < ps->damage_ring.count; ++i) {
|
||||
pixman_region32_fini(&ps->damage_ring.damages[i]);
|
||||
}
|
||||
ps->ndamage = 0;
|
||||
free(ps->damage_ring);
|
||||
ps->damage_ring = ps->damage = NULL;
|
||||
ps->damage_ring.count = 0;
|
||||
free(ps->damage_ring.damages);
|
||||
ps->damage_ring.cursor = 0;
|
||||
ps->damage_ring.damages = NULL;
|
||||
|
||||
if (ps->vblank_scheduler) {
|
||||
vblank_scheduler_free(ps->vblank_scheduler);
|
||||
|
@ -2209,8 +2212,9 @@ static session_t *session_init(int argc, char **argv, Display *dpy,
|
|||
XCB_XFIXES_MINOR_VERSION)
|
||||
.sequence);
|
||||
|
||||
ps->damaged_region = x_new_id(&ps->c);
|
||||
if (!XCB_AWAIT_VOID(xcb_xfixes_create_region, ps->c.c, ps->damaged_region, 0, NULL)) {
|
||||
ps->damage_ring.x_region = x_new_id(&ps->c);
|
||||
if (!XCB_AWAIT_VOID(xcb_xfixes_create_region, ps->c.c, ps->damage_ring.x_region,
|
||||
0, NULL)) {
|
||||
log_fatal("Failed to create a XFixes region");
|
||||
goto err;
|
||||
}
|
||||
|
@ -2706,9 +2710,9 @@ static void session_destroy(session_t *ps) {
|
|||
ps->debug_window = XCB_NONE;
|
||||
}
|
||||
|
||||
if (ps->damaged_region != XCB_NONE) {
|
||||
xcb_xfixes_destroy_region(ps->c.c, ps->damaged_region);
|
||||
ps->damaged_region = XCB_NONE;
|
||||
if (ps->damage_ring.x_region != XCB_NONE) {
|
||||
xcb_xfixes_destroy_region(ps->c.c, ps->damage_ring.x_region);
|
||||
ps->damage_ring.x_region = XCB_NONE;
|
||||
}
|
||||
|
||||
if (!ps->o.legacy_backends) {
|
||||
|
|
17
src/render.c
17
src/render.c
|
@ -1009,16 +1009,7 @@ void paint_all(session_t *ps, struct managed_win *t) {
|
|||
|
||||
region_t region;
|
||||
pixman_region32_init(®ion);
|
||||
int buffer_age = get_buffer_age(ps);
|
||||
if (buffer_age == -1 || buffer_age > ps->ndamage) {
|
||||
pixman_region32_copy(®ion, &ps->screen_reg);
|
||||
} else {
|
||||
for (int i = 0; i < get_buffer_age(ps); i++) {
|
||||
auto curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage;
|
||||
pixman_region32_union(®ion, ®ion, &ps->damage_ring[curr]);
|
||||
}
|
||||
}
|
||||
|
||||
damage_ring_collect(&ps->damage_ring, &ps->screen_reg, ®ion, get_buffer_age(ps));
|
||||
if (!pixman_region32_not_empty(®ion)) {
|
||||
return;
|
||||
}
|
||||
|
@ -1219,11 +1210,7 @@ void paint_all(session_t *ps, struct managed_win *t) {
|
|||
pixman_region32_fini(®_shadow_clip);
|
||||
|
||||
// Move the head of the damage ring
|
||||
ps->damage = ps->damage - 1;
|
||||
if (ps->damage < ps->damage_ring) {
|
||||
ps->damage = ps->damage_ring + ps->ndamage - 1;
|
||||
}
|
||||
pixman_region32_clear(ps->damage);
|
||||
damage_ring_advance(&ps->damage_ring);
|
||||
|
||||
// Do this as early as possible
|
||||
set_tgt_clip(ps, &ps->screen_reg);
|
||||
|
|
Loading…
Reference in New Issue