Implement monitor repaint in new xrender
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
c387a266dc
commit
eed5ea719e
|
@ -2,7 +2,7 @@
|
||||||
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
#include "backend.h"
|
#include "backend/backend.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -17,11 +17,18 @@ backend_init_fn backend_list[NUM_BKEND] = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
region_t get_damage(session_t *ps) {
|
/**
|
||||||
|
* @param all_damage if true ignore damage and repaint the whole screen
|
||||||
|
*/
|
||||||
|
region_t get_damage(session_t *ps, bool all_damage) {
|
||||||
region_t region;
|
region_t region;
|
||||||
auto buffer_age_fn = ps->backend_data->ops->buffer_age;
|
auto buffer_age_fn = ps->backend_data->ops->buffer_age;
|
||||||
int buffer_age = buffer_age_fn ? buffer_age_fn(ps->backend_data) : -1;
|
int buffer_age = buffer_age_fn ? buffer_age_fn(ps->backend_data) : -1;
|
||||||
|
|
||||||
|
if (all_damage) {
|
||||||
|
buffer_age = -1;
|
||||||
|
}
|
||||||
|
|
||||||
pixman_region32_init(®ion);
|
pixman_region32_init(®ion);
|
||||||
if (buffer_age == -1 || buffer_age > ps->ndamage) {
|
if (buffer_age == -1 || buffer_age > ps->ndamage) {
|
||||||
pixman_region32_copy(®ion, &ps->screen_reg);
|
pixman_region32_copy(®ion, &ps->screen_reg);
|
||||||
|
@ -42,7 +49,7 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
// part of the image we want to reuse
|
// part of the image we want to reuse
|
||||||
region_t reg_damage;
|
region_t reg_damage;
|
||||||
if (!ignore_damage) {
|
if (!ignore_damage) {
|
||||||
reg_damage = get_damage(ps);
|
reg_damage = get_damage(ps, ps->o.monitor_repaint);
|
||||||
} else {
|
} else {
|
||||||
pixman_region32_init(®_damage);
|
pixman_region32_init(®_damage);
|
||||||
pixman_region32_copy(®_damage, &ps->screen_reg);
|
pixman_region32_copy(®_damage, &ps->screen_reg);
|
||||||
|
@ -149,7 +156,8 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
ps->backend_data->ops->blur(ps->backend_data, w->opacity,
|
ps->backend_data->ops->blur(ps->backend_data, w->opacity,
|
||||||
®_paint, ®_visible);
|
®_paint, ®_visible);
|
||||||
} else if (frame_transparent && ps->o.blur_background_frame) {
|
} else if (frame_transparent && ps->o.blur_background_frame) {
|
||||||
// Window itself is solid, we only need to blur the frame region
|
// Window itself is solid, we only need to blur the frame
|
||||||
|
// region
|
||||||
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_damage
|
||||||
|
@ -165,8 +173,8 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
w->g.y, ®_paint, ®_visible);
|
w->g.y, ®_paint, ®_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 from
|
// region to damage, since the window image data is independent
|
||||||
// the target image data, which we want to protect.
|
// from the target image data, which we want to protect.
|
||||||
|
|
||||||
// The bounding shape, in window local coordinates
|
// The bounding shape, in window local coordinates
|
||||||
region_t reg_bound_local;
|
region_t reg_bound_local;
|
||||||
|
@ -183,8 +191,9 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
pixman_region32_intersect(®_visible_local, ®_visible, ®_damage);
|
pixman_region32_intersect(®_visible_local, ®_visible, ®_damage);
|
||||||
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 shape
|
// not necessary to limit the image operations to the bounding
|
||||||
// yet. So pass that as the visible region, not the clip region.
|
// shape yet. So pass that as the visible region, not the clip
|
||||||
|
// region.
|
||||||
pixman_region32_intersect(®_visible_local, ®_visible_local,
|
pixman_region32_intersect(®_visible_local, ®_visible_local,
|
||||||
®_bound_local);
|
®_bound_local);
|
||||||
|
|
||||||
|
@ -231,6 +240,15 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
}
|
}
|
||||||
pixman_region32_fini(®_damage);
|
pixman_region32_fini(®_damage);
|
||||||
|
|
||||||
|
if (ps->o.monitor_repaint) {
|
||||||
|
reg_damage = get_damage(ps, false);
|
||||||
|
auto extent = pixman_region32_extents(®_damage);
|
||||||
|
ps->backend_data->ops->fill_rectangle(
|
||||||
|
ps->backend_data, 0.5, 0, 0, 0.5, extent->x1, extent->y1,
|
||||||
|
extent->x2 - extent->x1, extent->y2 - extent->y1, ®_damage);
|
||||||
|
pixman_region32_fini(®_damage);
|
||||||
|
}
|
||||||
|
|
||||||
// Move the head of the damage ring
|
// Move the head of the damage ring
|
||||||
ps->damage = ps->damage - 1;
|
ps->damage = ps->damage - 1;
|
||||||
if (ps->damage < ps->damage_ring) {
|
if (ps->damage < ps->damage_ring) {
|
||||||
|
|
|
@ -83,6 +83,10 @@ struct backend_operations {
|
||||||
void (*compose)(backend_t *backend_data, void *image_data, int dst_x, int dst_y,
|
void (*compose)(backend_t *backend_data, void *image_data, int dst_x, int dst_y,
|
||||||
const region_t *reg_paint, const region_t *reg_visible);
|
const region_t *reg_paint, const region_t *reg_visible);
|
||||||
|
|
||||||
|
/// Fill rectangle of target, mostly for debug purposes, optional.
|
||||||
|
void (*fill_rectangle)(backend_t *backend_data, double r, double g, double b, double a,
|
||||||
|
int x, int y, int width, int height, const region_t *clip);
|
||||||
|
|
||||||
/// Blur a given region on of the target.
|
/// Blur a given region on of the target.
|
||||||
bool (*blur)(backend_t *backend_data, double opacity, const region_t *reg_blur,
|
bool (*blur)(backend_t *backend_data, double opacity, const region_t *reg_blur,
|
||||||
const region_t *reg_visible) attr_nonnull(1, 3, 4);
|
const region_t *reg_visible) attr_nonnull(1, 3, 4);
|
||||||
|
|
|
@ -267,7 +267,8 @@ void *default_backend_render_shadow(backend_t *backend_data, int width, int heig
|
||||||
shadow_pixel, &shadow, &pict);
|
shadow_pixel, &shadow, &pict);
|
||||||
|
|
||||||
auto visual = x_get_visual_for_standard(backend_data->c, XCB_PICT_STANDARD_ARGB_32);
|
auto visual = x_get_visual_for_standard(backend_data->c, XCB_PICT_STANDARD_ARGB_32);
|
||||||
void *ret = backend_data->ops->bind_pixmap(backend_data, shadow, x_get_visual_info(backend_data->c, visual), true);
|
void *ret = backend_data->ops->bind_pixmap(
|
||||||
|
backend_data, shadow, x_get_visual_info(backend_data->c, visual), true);
|
||||||
xcb_render_free_picture(backend_data->c, pict);
|
xcb_render_free_picture(backend_data->c, pict);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,6 +103,18 @@ static void compose(backend_t *base, void *img_data, int dst_x, int dst_y,
|
||||||
pixman_region32_fini(®);
|
pixman_region32_fini(®);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void fill_rectangle(backend_t *base, double r, double g, double b, double a, int x,
|
||||||
|
int y, int width, int height, const region_t *clip) {
|
||||||
|
struct _xrender_data *xd = (void *)base;
|
||||||
|
x_set_picture_clip_region(base->c, xd->back[xd->curr_back], 0, 0, clip);
|
||||||
|
// color is in X fixed point representation
|
||||||
|
xcb_render_fill_rectangles(
|
||||||
|
base->c, XCB_RENDER_PICT_OP_OVER, xd->back[xd->curr_back],
|
||||||
|
(xcb_render_color_t){
|
||||||
|
.red = r * 0xffff, .green = g * 0xffff, .blue = b * 0xffff, .alpha = a * 0xffff},
|
||||||
|
1, (xcb_rectangle_t[]){{.x = x, .y = y, .width = width, .height = height}});
|
||||||
|
}
|
||||||
|
|
||||||
static bool blur(backend_t *backend_data, double opacity, const region_t *reg_blur,
|
static bool blur(backend_t *backend_data, double opacity, const region_t *reg_blur,
|
||||||
const region_t *reg_visible) {
|
const region_t *reg_visible) {
|
||||||
struct _xrender_data *xd = (void *)backend_data;
|
struct _xrender_data *xd = (void *)backend_data;
|
||||||
|
@ -192,8 +204,8 @@ static bool blur(backend_t *backend_data, double opacity, const region_t *reg_bl
|
||||||
// There is only 1 pass
|
// There is only 1 pass
|
||||||
if (i == 1) {
|
if (i == 1) {
|
||||||
xcb_render_composite(c, XCB_RENDER_PICT_OP_OVER, src_pict, alpha_pict,
|
xcb_render_composite(c, XCB_RENDER_PICT_OP_OVER, src_pict, alpha_pict,
|
||||||
xd->back[xd->curr_back], 0, 0, 0, 0, extent->x1, extent->y1,
|
xd->back[xd->curr_back], 0, 0, 0, 0, extent->x1,
|
||||||
width, height);
|
extent->y1, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_render_free_picture(c, tmp_picture[0]);
|
xcb_render_free_picture(c, tmp_picture[0]);
|
||||||
|
@ -446,6 +458,7 @@ static struct backend_operations xrender_ops = {
|
||||||
.blur = blur,
|
.blur = blur,
|
||||||
.present = present,
|
.present = present,
|
||||||
.compose = compose,
|
.compose = compose,
|
||||||
|
.fill_rectangle = fill_rectangle,
|
||||||
.bind_pixmap = bind_pixmap,
|
.bind_pixmap = bind_pixmap,
|
||||||
.release_image = release_image,
|
.release_image = release_image,
|
||||||
.render_shadow = default_backend_render_shadow,
|
.render_shadow = default_backend_render_shadow,
|
||||||
|
|
Loading…
Reference in New Issue