backend: do partial updates
Although the functionality is not implemented by any backends yet. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
f86d6b7cbd
commit
06dba4b196
|
@ -71,6 +71,32 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
static struct timespec last_paint = {0};
|
static struct timespec last_paint = {0};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
region_t reg_paint;
|
||||||
|
assert(ps->o.blur_method != BLUR_METHOD_INVALID);
|
||||||
|
if (ps->o.blur_method != BLUR_METHOD_NONE && ps->backend_data->ops->get_blur_size) {
|
||||||
|
int blur_width, blur_height;
|
||||||
|
ps->backend_data->ops->get_blur_size(ps->backend_blur_context,
|
||||||
|
&blur_width, &blur_height);
|
||||||
|
if (t) {
|
||||||
|
// The region of screen a given window influences will be smeared
|
||||||
|
// out by blur. With more windows on top of the given window, the
|
||||||
|
// influences region will be smeared out more.
|
||||||
|
//
|
||||||
|
// Instead of accurately calculate how much bigger the damage
|
||||||
|
// region will be because of blur, we assume the worst case here.
|
||||||
|
// That is, the damaged window is at the bottom of the stack, and
|
||||||
|
// all other windows have semi-transparent background
|
||||||
|
resize_region_in_place(®_damage, blur_width * t->stacking_rank,
|
||||||
|
blur_height * t->stacking_rank);
|
||||||
|
pixman_region32_intersect(®_damage, ®_damage, &ps->screen_reg);
|
||||||
|
}
|
||||||
|
reg_paint = resize_region(®_damage, blur_width, blur_height);
|
||||||
|
pixman_region32_intersect(®_paint, ®_paint, &ps->screen_reg);
|
||||||
|
} else {
|
||||||
|
pixman_region32_init(®_paint);
|
||||||
|
pixman_region32_copy(®_paint, ®_damage);
|
||||||
|
}
|
||||||
|
|
||||||
// A hint to backend, the region that will be visible on screen
|
// A hint to backend, the region that will be visible on screen
|
||||||
// backend can optimize based on this info
|
// backend can optimize based on this info
|
||||||
region_t reg_visible;
|
region_t reg_visible;
|
||||||
|
@ -85,12 +111,12 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
// TODO Bind root pixmap
|
// TODO Bind root pixmap
|
||||||
|
|
||||||
if (ps->backend_data->ops->prepare) {
|
if (ps->backend_data->ops->prepare) {
|
||||||
ps->backend_data->ops->prepare(ps->backend_data, ®_damage);
|
ps->backend_data->ops->prepare(ps->backend_data, ®_paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ps->root_image) {
|
if (ps->root_image) {
|
||||||
ps->backend_data->ops->compose(ps->backend_data, ps->root_image, 0, 0,
|
ps->backend_data->ops->compose(ps->backend_data, ps->root_image, 0, 0,
|
||||||
®_damage, ®_visible);
|
®_paint, ®_visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Windows are sorted from bottom to top
|
// Windows are sorted from bottom to top
|
||||||
|
@ -109,9 +135,9 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
// Draw shadow on target
|
// Draw shadow on target
|
||||||
if (w->shadow) {
|
if (w->shadow) {
|
||||||
// Clip region for the shadow
|
// Clip region for the shadow
|
||||||
// reg_shadow \in reg_damage
|
// reg_shadow \in reg_paint
|
||||||
auto reg_shadow = win_extents_by_val(w);
|
auto reg_shadow = win_extents_by_val(w);
|
||||||
pixman_region32_intersect(®_shadow, ®_shadow, ®_damage);
|
pixman_region32_intersect(®_shadow, ®_shadow, ®_paint);
|
||||||
if (!ps->o.wintype_option[w->window_type].full_shadow) {
|
if (!ps->o.wintype_option[w->window_type].full_shadow) {
|
||||||
pixman_region32_subtract(®_shadow, ®_shadow, ®_bound);
|
pixman_region32_subtract(®_shadow, ®_shadow, ®_bound);
|
||||||
}
|
}
|
||||||
|
@ -156,10 +182,10 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The clip region for the current window, in global/target coordinates
|
// The clip region for the current window, in global/target coordinates
|
||||||
// reg_paint \in reg_damage
|
// reg_paint_in_bound \in reg_paint
|
||||||
region_t reg_paint;
|
region_t reg_paint_in_bound;
|
||||||
pixman_region32_init(®_paint);
|
pixman_region32_init(®_paint_in_bound);
|
||||||
pixman_region32_intersect(®_paint, ®_bound, ®_damage);
|
pixman_region32_intersect(®_paint_in_bound, ®_bound, ®_paint);
|
||||||
|
|
||||||
// Blur window background
|
// Blur window background
|
||||||
// TODO since the background might change the content of the window (e.g.
|
// TODO since the background might change the content of the window (e.g.
|
||||||
|
@ -176,10 +202,10 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
// TODO resize blur region to fix black line artifact
|
// TODO resize blur region to fix black line artifact
|
||||||
if (real_win_mode == WMODE_TRANS || ps->o.force_win_blend) {
|
if (real_win_mode == WMODE_TRANS || ps->o.force_win_blend) {
|
||||||
// We need to blur the bounding shape of the window
|
// We need to blur the bounding shape of the window
|
||||||
// (reg_paint = reg_bound \cap reg_damage)
|
// (reg_paint_in_bound = reg_bound \cap reg_paint)
|
||||||
ps->backend_data->ops->blur(ps->backend_data, w->opacity,
|
ps->backend_data->ops->blur(
|
||||||
ps->backend_blur_context,
|
ps->backend_data, w->opacity, ps->backend_blur_context,
|
||||||
®_paint, ®_visible);
|
®_paint_in_bound, ®_visible);
|
||||||
} else {
|
} else {
|
||||||
// Window itself is solid, we only need to blur the frame
|
// Window itself is solid, we only need to blur the frame
|
||||||
// region
|
// region
|
||||||
|
@ -190,8 +216,8 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
|
|
||||||
auto reg_blur = win_get_region_frame_local_by_val(w);
|
auto reg_blur = win_get_region_frame_local_by_val(w);
|
||||||
pixman_region32_translate(®_blur, w->g.x, w->g.y);
|
pixman_region32_translate(®_blur, w->g.x, w->g.y);
|
||||||
// make sure reg_blur \in reg_damage
|
// make sure reg_blur \in reg_paint
|
||||||
pixman_region32_intersect(®_blur, ®_blur, ®_damage);
|
pixman_region32_intersect(®_blur, ®_blur, ®_paint);
|
||||||
ps->backend_data->ops->blur(ps->backend_data, w->opacity,
|
ps->backend_data->ops->blur(ps->backend_data, w->opacity,
|
||||||
ps->backend_blur_context,
|
ps->backend_blur_context,
|
||||||
®_blur, ®_visible);
|
®_blur, ®_visible);
|
||||||
|
@ -200,8 +226,9 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
}
|
}
|
||||||
// Draw window on target
|
// Draw window on target
|
||||||
if (!w->invert_color && !w->dim && w->frame_opacity == 1 && w->opacity == 1) {
|
if (!w->invert_color && !w->dim && w->frame_opacity == 1 && w->opacity == 1) {
|
||||||
ps->backend_data->ops->compose(ps->backend_data, w->win_image, w->g.x,
|
ps->backend_data->ops->compose(ps->backend_data, w->win_image,
|
||||||
w->g.y, ®_paint, ®_visible);
|
w->g.x, w->g.y,
|
||||||
|
®_paint_in_bound, ®_visible);
|
||||||
} else {
|
} else {
|
||||||
// For window image processing, we don't need to limit the process
|
// For window image processing, we don't need to limit the process
|
||||||
// region to damage, since the window image data is independent
|
// region to damage, since the window image data is independent
|
||||||
|
@ -219,7 +246,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
// outside of the damage region won't be painted onto target
|
// outside of the damage region won't be painted onto target
|
||||||
region_t reg_visible_local;
|
region_t reg_visible_local;
|
||||||
pixman_region32_init(®_visible_local);
|
pixman_region32_init(®_visible_local);
|
||||||
pixman_region32_intersect(®_visible_local, ®_visible, ®_damage);
|
pixman_region32_intersect(®_visible_local, ®_visible, ®_paint);
|
||||||
pixman_region32_translate(®_visible_local, -w->g.x, -w->g.y);
|
pixman_region32_translate(®_visible_local, -w->g.x, -w->g.y);
|
||||||
// Data outside of the bounding shape won't be visible, but it is
|
// Data outside of the bounding shape won't be visible, but it is
|
||||||
// not necessary to limit the image operations to the bounding
|
// not necessary to limit the image operations to the bounding
|
||||||
|
@ -228,7 +255,6 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
pixman_region32_intersect(®_visible_local, ®_visible_local,
|
pixman_region32_intersect(®_visible_local, ®_visible_local,
|
||||||
®_bound_local);
|
®_bound_local);
|
||||||
|
|
||||||
// A region covers the entire window
|
|
||||||
auto new_img = ps->backend_data->ops->copy(
|
auto new_img = ps->backend_data->ops->copy(
|
||||||
ps->backend_data, w->win_image, ®_visible_local);
|
ps->backend_data, w->win_image, ®_visible_local);
|
||||||
if (w->invert_color) {
|
if (w->invert_color) {
|
||||||
|
@ -258,21 +284,22 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
NULL, ®_visible_local, (double[]){w->opacity});
|
NULL, ®_visible_local, (double[]){w->opacity});
|
||||||
}
|
}
|
||||||
ps->backend_data->ops->compose(ps->backend_data, new_img, w->g.x,
|
ps->backend_data->ops->compose(ps->backend_data, new_img, w->g.x,
|
||||||
w->g.y, ®_paint, ®_visible);
|
w->g.y, ®_paint_in_bound,
|
||||||
|
®_visible);
|
||||||
ps->backend_data->ops->release_image(ps->backend_data, new_img);
|
ps->backend_data->ops->release_image(ps->backend_data, new_img);
|
||||||
pixman_region32_fini(®_visible_local);
|
pixman_region32_fini(®_visible_local);
|
||||||
pixman_region32_fini(®_bound_local);
|
pixman_region32_fini(®_bound_local);
|
||||||
}
|
}
|
||||||
pixman_region32_fini(®_bound);
|
pixman_region32_fini(®_bound);
|
||||||
pixman_region32_fini(®_paint);
|
pixman_region32_fini(®_paint_in_bound);
|
||||||
}
|
}
|
||||||
pixman_region32_fini(®_damage);
|
pixman_region32_fini(®_paint);
|
||||||
|
|
||||||
if (ps->o.monitor_repaint) {
|
if (ps->o.monitor_repaint) {
|
||||||
reg_damage = get_damage(ps, false);
|
auto reg_damage_debug = get_damage(ps, false);
|
||||||
ps->backend_data->ops->fill(ps->backend_data,
|
ps->backend_data->ops->fill(
|
||||||
(struct color){0.5, 0, 0, 0.5}, ®_damage);
|
ps->backend_data, (struct color){0.5, 0, 0, 0.5}, ®_damage_debug);
|
||||||
pixman_region32_fini(®_damage);
|
pixman_region32_fini(®_damage_debug);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the head of the damage ring
|
// Move the head of the damage ring
|
||||||
|
@ -285,9 +312,11 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
|
||||||
if (ps->backend_data->ops->present) {
|
if (ps->backend_data->ops->present) {
|
||||||
// Present the rendered scene
|
// Present the rendered scene
|
||||||
// Vsync is done here
|
// Vsync is done here
|
||||||
ps->backend_data->ops->present(ps->backend_data, NULL);
|
ps->backend_data->ops->present(ps->backend_data, ®_damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pixman_region32_fini(®_damage);
|
||||||
|
|
||||||
#ifdef DEBUG_REPAINT
|
#ifdef DEBUG_REPAINT
|
||||||
struct timespec now = get_time_timespec();
|
struct timespec now = get_time_timespec();
|
||||||
struct timespec diff = {0};
|
struct timespec diff = {0};
|
||||||
|
|
|
@ -575,6 +575,11 @@ static struct managed_win *paint_preprocess(session_t *ps, bool *fade_running) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w->prev_trans = bottom;
|
w->prev_trans = bottom;
|
||||||
|
if (bottom) {
|
||||||
|
w->stacking_rank = bottom->stacking_rank + 1;
|
||||||
|
} else {
|
||||||
|
w->stacking_rank = 0;
|
||||||
|
}
|
||||||
bottom = w;
|
bottom = w;
|
||||||
|
|
||||||
// If the screen is not redirected and the window has redir_ignore set,
|
// If the screen is not redirected and the window has redir_ignore set,
|
||||||
|
|
|
@ -169,6 +169,8 @@ struct managed_win {
|
||||||
void *shadow_image;
|
void *shadow_image;
|
||||||
/// Pointer to the next higher window to paint.
|
/// Pointer to the next higher window to paint.
|
||||||
struct managed_win *prev_trans;
|
struct managed_win *prev_trans;
|
||||||
|
/// Number of windows above this window
|
||||||
|
int stacking_rank;
|
||||||
// TODO rethink reg_ignore
|
// TODO rethink reg_ignore
|
||||||
|
|
||||||
// Core members
|
// Core members
|
||||||
|
|
Loading…
Reference in New Issue