Merge pull request #86 from yshui/damage-ring
Make buffer age not glx specific
This commit is contained in:
commit
4bc2870ddf
|
@ -592,63 +592,6 @@ void glx_render_win(void *backend_data, session_t *ps, win *w, void *win_data, c
|
||||||
gl_check_err();
|
gl_check_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Preprocess function before start painting.
|
|
||||||
*/
|
|
||||||
static void attr_unused glx_paint_pre(session_t *ps, region_t *preg) {
|
|
||||||
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
// Get buffer age
|
|
||||||
bool trace_damage = (ps->o.glx_swap_method < 0 || ps->o.glx_swap_method > 1);
|
|
||||||
|
|
||||||
// Trace raw damage regions
|
|
||||||
region_t newdamage;
|
|
||||||
pixman_region32_init(&newdamage);
|
|
||||||
if (trace_damage)
|
|
||||||
copy_region(&newdamage, preg);
|
|
||||||
|
|
||||||
// We use GLX buffer_age extension to decide which pixels in
|
|
||||||
// the back buffer is reusable, and limit our redrawing
|
|
||||||
int buffer_age = 0;
|
|
||||||
|
|
||||||
// Query GLX_EXT_buffer_age for buffer age
|
|
||||||
if (ps->o.glx_swap_method == SWAPM_BUFFER_AGE) {
|
|
||||||
unsigned val = 0;
|
|
||||||
glXQueryDrawable(ps->dpy, get_tgt_window(ps), GLX_BACK_BUFFER_AGE_EXT, &val);
|
|
||||||
buffer_age = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buffer age too high
|
|
||||||
if (buffer_age > CGLX_MAX_BUFFER_AGE + 1)
|
|
||||||
buffer_age = 0;
|
|
||||||
|
|
||||||
assert(buffer_age >= 0);
|
|
||||||
|
|
||||||
if (buffer_age) {
|
|
||||||
// Determine paint area
|
|
||||||
for (int i = 0; i < buffer_age - 1; ++i)
|
|
||||||
pixman_region32_union(preg, preg, &ps->all_damage_last[i]);
|
|
||||||
} else
|
|
||||||
// buffer_age == 0 means buffer age is not available, paint everything
|
|
||||||
copy_region(preg, &ps->screen_reg);
|
|
||||||
|
|
||||||
if (trace_damage) {
|
|
||||||
// XXX use a circular queue instead of memmove
|
|
||||||
pixman_region32_fini(&ps->all_damage_last[CGLX_MAX_BUFFER_AGE - 1]);
|
|
||||||
memmove(ps->all_damage_last + 1, ps->all_damage_last,
|
|
||||||
(CGLX_MAX_BUFFER_AGE - 1) * sizeof(region_t *));
|
|
||||||
ps->all_damage_last[0] = newdamage;
|
|
||||||
}
|
|
||||||
|
|
||||||
// gl_set_clip(ps, preg);
|
|
||||||
|
|
||||||
#ifdef DEBUG_GLX_PAINTREG
|
|
||||||
glx_render_color(ps, 0, 0, ps->root_width, ps->root_height, 0, *preg, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
gl_check_err();
|
|
||||||
}
|
|
||||||
|
|
||||||
backend_info_t glx_backend = {
|
backend_info_t glx_backend = {
|
||||||
.init = glx_init,
|
.init = glx_init,
|
||||||
.deinit = glx_deinit,
|
.deinit = glx_deinit,
|
||||||
|
|
15
src/common.h
15
src/common.h
|
@ -427,9 +427,11 @@ typedef struct session {
|
||||||
/// Program start time.
|
/// Program start time.
|
||||||
struct timeval time_start;
|
struct timeval time_start;
|
||||||
/// The region needs to painted on next paint.
|
/// The region needs to painted on next paint.
|
||||||
region_t all_damage;
|
region_t *damage;
|
||||||
/// The region damaged on the last paint.
|
/// The region damaged on the last paint.
|
||||||
region_t all_damage_last[CGLX_MAX_BUFFER_AGE];
|
region_t *damage_ring;
|
||||||
|
/// Number of damage regions we track
|
||||||
|
int ndamage;
|
||||||
/// Whether all windows are currently redirected.
|
/// Whether all windows are currently redirected.
|
||||||
bool redirected;
|
bool redirected;
|
||||||
/// Pre-generated alpha pictures.
|
/// Pre-generated alpha pictures.
|
||||||
|
@ -897,15 +899,6 @@ find_focused(session_t *ps) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Free all regions in ps->all_damage_last .
|
|
||||||
*/
|
|
||||||
static inline void
|
|
||||||
free_all_damage_last(session_t *ps) {
|
|
||||||
for (int i = 0; i < CGLX_MAX_BUFFER_AGE; ++i)
|
|
||||||
pixman_region32_clear(&ps->all_damage_last[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a rectangle includes the whole screen.
|
* Check if a rectangle includes the whole screen.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -206,38 +206,6 @@ get_time_ms(void) {
|
||||||
return tv.tv_sec % SEC_WRAP * 1000 + tv.tv_usec / 1000;
|
return tv.tv_sec % SEC_WRAP * 1000 + tv.tv_usec / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Resize a region.
|
|
||||||
*/
|
|
||||||
static inline void
|
|
||||||
resize_region(session_t *ps, region_t *region, short mod) {
|
|
||||||
if (!mod || !region) return;
|
|
||||||
// Loop through all rectangles
|
|
||||||
int nrects;
|
|
||||||
int nnewrects = 0;
|
|
||||||
pixman_box32_t *rects = pixman_region32_rectangles(region, &nrects);
|
|
||||||
auto newrects = ccalloc(nrects, pixman_box32_t);
|
|
||||||
for (int i = 0; i < nrects; i++) {
|
|
||||||
int x1 = max_i(rects[i].x1 - mod, 0);
|
|
||||||
int y1 = max_i(rects[i].y1 - mod, 0);
|
|
||||||
int x2 = min_i(rects[i].x2 + mod, ps->root_width);
|
|
||||||
int y2 = min_i(rects[i].y2 + mod, ps->root_height);
|
|
||||||
int wid = x2 - x1;
|
|
||||||
int hei = y2 - y1;
|
|
||||||
if (wid <= 0 || hei <= 0)
|
|
||||||
continue;
|
|
||||||
newrects[nnewrects] = (pixman_box32_t) {
|
|
||||||
.x1 = x1, .x2 = x2, .y1 = y1, .y2 = y2
|
|
||||||
};
|
|
||||||
++nnewrects;
|
|
||||||
}
|
|
||||||
|
|
||||||
pixman_region32_fini(region);
|
|
||||||
pixman_region32_init_rects(region, newrects, nnewrects);
|
|
||||||
|
|
||||||
free(newrects);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the Xinerama screen a window is on.
|
* Get the Xinerama screen a window is on.
|
||||||
*
|
*
|
||||||
|
@ -345,7 +313,7 @@ void add_damage(session_t *ps, const region_t *damage) {
|
||||||
|
|
||||||
if (!damage)
|
if (!damage)
|
||||||
return;
|
return;
|
||||||
pixman_region32_union(&ps->all_damage, &ps->all_damage, (region_t *)damage);
|
pixman_region32_union(ps->damage, ps->damage, (region_t *)damage);
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Fading ===
|
// === Fading ===
|
||||||
|
@ -1082,7 +1050,10 @@ configure_win(session_t *ps, xcb_configure_notify_event_t *ce) {
|
||||||
|
|
||||||
rebuild_screen_reg(ps);
|
rebuild_screen_reg(ps);
|
||||||
rebuild_shadow_exclude_reg(ps);
|
rebuild_shadow_exclude_reg(ps);
|
||||||
free_all_damage_last(ps);
|
for (int i = 0; i < ps->ndamage; i++) {
|
||||||
|
pixman_region32_clear(&ps->damage_ring[i]);
|
||||||
|
}
|
||||||
|
ps->damage = ps->damage_ring + ps->ndamage - 1;
|
||||||
|
|
||||||
// Re-redirect screen if required
|
// Re-redirect screen if required
|
||||||
if (ps->o.reredir_on_root_change && ps->redirected) {
|
if (ps->o.reredir_on_root_change && ps->redirected) {
|
||||||
|
@ -1281,7 +1252,6 @@ ev_xcb_error(session_t attr_unused *ps, xcb_generic_error_t *err) {
|
||||||
|
|
||||||
static void
|
static void
|
||||||
expose_root(session_t *ps, const rect_t *rects, int nrects) {
|
expose_root(session_t *ps, const rect_t *rects, int nrects) {
|
||||||
free_all_damage_last(ps);
|
|
||||||
region_t region;
|
region_t region;
|
||||||
pixman_region32_init_rects(®ion, rects, nrects);
|
pixman_region32_init_rects(®ion, rects, nrects);
|
||||||
add_damage(ps, ®ion);
|
add_damage(ps, ®ion);
|
||||||
|
@ -2424,25 +2394,9 @@ _draw_callback(EV_P_ session_t *ps, int revents) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the screen is unredirected, free all_damage to stop painting
|
// If the screen is unredirected, free all_damage to stop painting
|
||||||
if (!ps->redirected || ps->o.stoppaint_force == ON)
|
if (ps->redirected && ps->o.stoppaint_force != ON) {
|
||||||
pixman_region32_clear(&ps->all_damage);
|
|
||||||
|
|
||||||
if (pixman_region32_not_empty(&ps->all_damage)) {
|
|
||||||
region_t all_damage_orig, *region_real = NULL;
|
|
||||||
pixman_region32_init(&all_damage_orig);
|
|
||||||
|
|
||||||
// keep a copy of non-resized all_damage for region_real
|
|
||||||
if (ps->o.resize_damage > 0) {
|
|
||||||
copy_region(&all_damage_orig, &ps->all_damage);
|
|
||||||
resize_region(ps, &ps->all_damage, ps->o.resize_damage);
|
|
||||||
region_real = &all_damage_orig;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int paint = 0;
|
static int paint = 0;
|
||||||
paint_all(ps, &ps->all_damage, region_real, t);
|
paint_all(ps, t, false);
|
||||||
|
|
||||||
pixman_region32_clear(&ps->all_damage);
|
|
||||||
pixman_region32_fini(&all_damage_orig);
|
|
||||||
|
|
||||||
paint++;
|
paint++;
|
||||||
if (ps->o.benchmark && paint >= ps->o.benchmark)
|
if (ps->o.benchmark && paint >= ps->o.benchmark)
|
||||||
|
@ -2714,9 +2668,6 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
||||||
*ps = s_def;
|
*ps = s_def;
|
||||||
ps->loop = EV_DEFAULT;
|
ps->loop = EV_DEFAULT;
|
||||||
pixman_region32_init(&ps->screen_reg);
|
pixman_region32_init(&ps->screen_reg);
|
||||||
pixman_region32_init(&ps->all_damage);
|
|
||||||
for (int i = 0; i < CGLX_MAX_BUFFER_AGE; i ++)
|
|
||||||
pixman_region32_init(&ps->all_damage_last[i]);
|
|
||||||
|
|
||||||
ps_g = ps;
|
ps_g = ps;
|
||||||
ps->ignore_tail = &ps->ignore_head;
|
ps->ignore_tail = &ps->ignore_head;
|
||||||
|
@ -3197,9 +3148,10 @@ session_destroy(session_t *ps) {
|
||||||
free_paint(ps, &ps->tgt_buffer);
|
free_paint(ps, &ps->tgt_buffer);
|
||||||
|
|
||||||
pixman_region32_fini(&ps->screen_reg);
|
pixman_region32_fini(&ps->screen_reg);
|
||||||
pixman_region32_fini(&ps->all_damage);
|
for (int i = 0; i < ps->ndamage; ++i)
|
||||||
for (int i = 0; i < CGLX_MAX_BUFFER_AGE; ++i)
|
pixman_region32_fini(&ps->damage_ring[i]);
|
||||||
pixman_region32_fini(&ps->all_damage_last[i]);
|
ps->ndamage = 0;
|
||||||
|
ps->damage_ring = ps->damage = NULL;
|
||||||
free(ps->expose_rects);
|
free(ps->expose_rects);
|
||||||
|
|
||||||
free(ps->o.config_file);
|
free(ps->o.config_file);
|
||||||
|
@ -3308,7 +3260,7 @@ session_run(session_t *ps) {
|
||||||
t = paint_preprocess(ps, ps->list);
|
t = paint_preprocess(ps, ps->list);
|
||||||
|
|
||||||
if (ps->redirected)
|
if (ps->redirected)
|
||||||
paint_all(ps, NULL, NULL, t);
|
paint_all(ps, t, true);
|
||||||
|
|
||||||
// In benchmark mode, we want draw_idle handler to always be active
|
// In benchmark mode, we want draw_idle handler to always be active
|
||||||
if (ps->o.benchmark)
|
if (ps->o.benchmark)
|
||||||
|
|
60
src/opengl.c
60
src/opengl.c
|
@ -857,66 +857,6 @@ glx_release_pixmap(session_t *ps, glx_texture_t *ptex) {
|
||||||
glx_check_err(ps);
|
glx_check_err(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Preprocess function before start painting.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
glx_paint_pre(session_t *ps, region_t *preg) {
|
|
||||||
ps->psglx->z = 0.0;
|
|
||||||
// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
||||||
|
|
||||||
// Get buffer age
|
|
||||||
bool trace_damage = (ps->o.glx_swap_method < 0 || ps->o.glx_swap_method > 1);
|
|
||||||
|
|
||||||
// Trace raw damage regions
|
|
||||||
region_t newdamage;
|
|
||||||
pixman_region32_init(&newdamage);
|
|
||||||
if (trace_damage)
|
|
||||||
copy_region(&newdamage, preg);
|
|
||||||
|
|
||||||
// We use GLX buffer_age extension to decide which pixels in
|
|
||||||
// the back buffer is reusable, and limit our redrawing
|
|
||||||
int buffer_age = 0;
|
|
||||||
|
|
||||||
// Query GLX_EXT_buffer_age for buffer age
|
|
||||||
if (ps->o.glx_swap_method == SWAPM_BUFFER_AGE) {
|
|
||||||
unsigned val = 0;
|
|
||||||
glXQueryDrawable(ps->dpy, get_tgt_window(ps),
|
|
||||||
GLX_BACK_BUFFER_AGE_EXT, &val);
|
|
||||||
buffer_age = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buffer age too high
|
|
||||||
if (buffer_age > CGLX_MAX_BUFFER_AGE + 1)
|
|
||||||
buffer_age = 0;
|
|
||||||
|
|
||||||
assert(buffer_age >= 0);
|
|
||||||
|
|
||||||
if (buffer_age) {
|
|
||||||
// Determine paint area
|
|
||||||
for (int i = 0; i < buffer_age - 1; ++i)
|
|
||||||
pixman_region32_union(preg, preg, &ps->all_damage_last[i]);
|
|
||||||
} else
|
|
||||||
// buffer_age == 0 means buffer age is not available, paint everything
|
|
||||||
copy_region(preg, &ps->screen_reg);
|
|
||||||
|
|
||||||
if (trace_damage) {
|
|
||||||
// XXX use a circular queue instead of memmove
|
|
||||||
pixman_region32_fini(&ps->all_damage_last[CGLX_MAX_BUFFER_AGE - 1]);
|
|
||||||
memmove(ps->all_damage_last + 1, ps->all_damage_last,
|
|
||||||
(CGLX_MAX_BUFFER_AGE - 1) * sizeof(region_t));
|
|
||||||
ps->all_damage_last[0] = newdamage;
|
|
||||||
}
|
|
||||||
|
|
||||||
glx_set_clip(ps, preg);
|
|
||||||
|
|
||||||
#ifdef DEBUG_GLX_PAINTREG
|
|
||||||
glx_render_color(ps, 0, 0, ps->root_width, ps->root_height, 0, *preg, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
glx_check_err(ps);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set clipping region on the target window.
|
* Set clipping region on the target window.
|
||||||
*/
|
*/
|
||||||
|
|
253
src/render.c
253
src/render.c
|
@ -59,6 +59,28 @@ static inline bool bkend_use_xrender(session_t *ps) {
|
||||||
return BKEND_XRENDER == ps->o.backend || BKEND_XR_GLX_HYBRID == ps->o.backend;
|
return BKEND_XRENDER == ps->o.backend || BKEND_XR_GLX_HYBRID == ps->o.backend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int maximum_buffer_age(session_t *ps) {
|
||||||
|
if (bkend_use_glx(ps) && ps->o.glx_swap_method == SWAPM_BUFFER_AGE) {
|
||||||
|
return CGLX_MAX_BUFFER_AGE;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_buffer_age(session_t *ps) {
|
||||||
|
#ifdef CONFIG_OPENGL
|
||||||
|
if (bkend_use_glx(ps)) {
|
||||||
|
if (ps->o.glx_swap_method == SWAPM_BUFFER_AGE) {
|
||||||
|
unsigned int val;
|
||||||
|
glXQueryDrawable(ps->dpy, get_tgt_window(ps), GLX_BACK_BUFFER_AGE_EXT, &val);
|
||||||
|
return (int)val ?: -1;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset filter on a <code>Picture</code>.
|
* Reset filter on a <code>Picture</code>.
|
||||||
*/
|
*/
|
||||||
|
@ -68,6 +90,7 @@ static inline void xrfilter_reset(session_t *ps, xcb_render_picture_t p) {
|
||||||
#undef FILTER
|
#undef FILTER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the input/output clip region of the target buffer (not the actual target!)
|
||||||
static inline void attr_nonnull(1, 2) set_tgt_clip(session_t *ps, region_t *reg) {
|
static inline void attr_nonnull(1, 2) set_tgt_clip(session_t *ps, region_t *reg) {
|
||||||
switch (ps->o.backend) {
|
switch (ps->o.backend) {
|
||||||
case BKEND_XRENDER:
|
case BKEND_XRENDER:
|
||||||
|
@ -113,8 +136,7 @@ void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, doubl
|
||||||
int alpha_step = opacity * MAX_ALPHA;
|
int alpha_step = opacity * MAX_ALPHA;
|
||||||
xcb_render_picture_t alpha_pict = ps->alpha_picts[alpha_step];
|
xcb_render_picture_t alpha_pict = ps->alpha_picts[alpha_step];
|
||||||
if (alpha_step != 0) {
|
if (alpha_step != 0) {
|
||||||
int op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC
|
int op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC : XCB_RENDER_PICT_OP_OVER);
|
||||||
: XCB_RENDER_PICT_OP_OVER);
|
|
||||||
xcb_render_composite(ps->c, op, pict, alpha_pict, ps->tgt_buffer.pict,
|
xcb_render_composite(ps->c, op, pict, alpha_pict, ps->tgt_buffer.pict,
|
||||||
x, y, 0, 0, dx, dy, wid, hei);
|
x, y, 0, 0, dx, dy, wid, hei);
|
||||||
}
|
}
|
||||||
|
@ -131,8 +153,7 @@ void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, doubl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void paint_region(session_t *ps, win *w, int x, int y, int wid, int hei, double opacity,
|
||||||
paint_region(session_t *ps, win *w, int x, int y, int wid, int hei, double opacity,
|
|
||||||
const region_t *reg_paint, xcb_render_picture_t pict) {
|
const region_t *reg_paint, xcb_render_picture_t pict) {
|
||||||
const int dx = (w ? w->g.x : 0) + x;
|
const int dx = (w ? w->g.x : 0) + x;
|
||||||
const int dy = (w ? w->g.y : 0) + y;
|
const int dy = (w ? w->g.y : 0) + y;
|
||||||
|
@ -200,8 +221,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
// Let glx_bind_pixmap() determine pixmap size, because if the user
|
// Let glx_bind_pixmap() determine pixmap size, because if the user
|
||||||
// is resizing windows, the width and height we get may not be up-to-date,
|
// is resizing windows, the width and height we get may not be up-to-date,
|
||||||
// causing the jittering issue M4he reported in #7.
|
// causing the jittering issue M4he reported in #7.
|
||||||
if (!paint_bind_tex(ps, &w->paint, 0, 0, 0,
|
if (!paint_bind_tex(ps, &w->paint, 0, 0, 0, (!ps->o.glx_no_rebind_pixmap && w->pixmap_damaged))) {
|
||||||
(!ps->o.glx_no_rebind_pixmap && w->pixmap_damaged))) {
|
|
||||||
log_error("Failed to bind texture for window %#010x.", w->id);
|
log_error("Failed to bind texture for window %#010x.", w->id);
|
||||||
}
|
}
|
||||||
w->pixmap_damaged = false;
|
w->pixmap_damaged = false;
|
||||||
|
@ -229,15 +249,15 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
pixman_region32_init(®);
|
pixman_region32_init(®);
|
||||||
pixman_region32_copy(®, (region_t *)reg_paint);
|
pixman_region32_copy(®, (region_t *)reg_paint);
|
||||||
pixman_region32_translate(®, -x, -y);
|
pixman_region32_translate(®, -x, -y);
|
||||||
// FIXME XFixesSetPictureClipRegion(ps->dpy, newpict, 0, 0, reg);
|
// FIXME XFixesSetPictureClipRegion(ps->dpy, newpict, 0,
|
||||||
|
// 0, reg);
|
||||||
pixman_region32_fini(®);
|
pixman_region32_fini(®);
|
||||||
}
|
}
|
||||||
|
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, pict, XCB_NONE,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, pict, XCB_NONE,
|
||||||
newpict, 0, 0, 0, 0, 0, 0, wid, hei);
|
newpict, 0, 0, 0, 0, 0, 0, wid, hei);
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_DIFFERENCE,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_DIFFERENCE, ps->white_picture,
|
||||||
ps->white_picture, XCB_NONE, newpict, 0, 0,
|
XCB_NONE, newpict, 0, 0, 0, 0, 0, 0, wid, hei);
|
||||||
0, 0, 0, 0, wid, hei);
|
|
||||||
// We use an extra PictOpInReverse operation to get correct
|
// We use an extra PictOpInReverse operation to get correct
|
||||||
// pixel alpha. There could be a better solution.
|
// pixel alpha. There could be a better solution.
|
||||||
if (win_has_alpha(w))
|
if (win_has_alpha(w))
|
||||||
|
@ -261,8 +281,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
const int r = extents.right;
|
const int r = extents.right;
|
||||||
|
|
||||||
#define COMP_BDR(cx, cy, cwid, chei) \
|
#define COMP_BDR(cx, cy, cwid, chei) \
|
||||||
paint_region(ps, w, (cx), (cy), (cwid), (chei), w->frame_opacity *dopacity, \
|
paint_region(ps, w, (cx), (cy), (cwid), (chei), w->frame_opacity *dopacity, reg_paint, pict)
|
||||||
reg_paint, pict)
|
|
||||||
|
|
||||||
// Sanitize the margins, in case some broken WM makes
|
// Sanitize the margins, in case some broken WM makes
|
||||||
// top_width + bottom_width > height in some cases.
|
// top_width + bottom_width > height in some cases.
|
||||||
|
@ -353,8 +372,7 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
} break;
|
} break;
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
case BKEND_GLX:
|
case BKEND_GLX:
|
||||||
glx_dim_dst(ps, x, y, wid, hei, ps->psglx->z - 0.7, dim_opacity,
|
glx_dim_dst(ps, x, y, wid, hei, ps->psglx->z - 0.7, dim_opacity, reg_paint);
|
||||||
reg_paint);
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
default: assert(false);
|
default: assert(false);
|
||||||
|
@ -380,9 +398,8 @@ static bool get_root_tile(session_t *ps) {
|
||||||
|
|
||||||
// Get the values of background attributes
|
// Get the values of background attributes
|
||||||
for (int p = 0; background_props_str[p]; p++) {
|
for (int p = 0; background_props_str[p]; p++) {
|
||||||
winprop_t prop =
|
winprop_t prop = wid_get_prop(
|
||||||
wid_get_prop(ps, ps->root, get_atom(ps, background_props_str[p]), 1L,
|
ps, ps->root, get_atom(ps, background_props_str[p]), 1L, XCB_ATOM_PIXMAP, 32);
|
||||||
XCB_ATOM_PIXMAP, 32);
|
|
||||||
if (prop.nitems) {
|
if (prop.nitems) {
|
||||||
pixmap = *prop.p32;
|
pixmap = *prop.p32;
|
||||||
fill = false;
|
fill = false;
|
||||||
|
@ -465,15 +482,13 @@ static bool win_build_shadow(session_t *ps, win *w, double opacity) {
|
||||||
xcb_render_picture_t shadow_picture = XCB_NONE, shadow_picture_argb = XCB_NONE;
|
xcb_render_picture_t shadow_picture = XCB_NONE, shadow_picture_argb = XCB_NONE;
|
||||||
xcb_gcontext_t gc = XCB_NONE;
|
xcb_gcontext_t gc = XCB_NONE;
|
||||||
|
|
||||||
shadow_image =
|
shadow_image = make_shadow(ps->c, ps->gaussian_map, opacity, width, height);
|
||||||
make_shadow(ps->c, ps->gaussian_map, opacity, width, height);
|
|
||||||
if (!shadow_image) {
|
if (!shadow_image) {
|
||||||
log_error("failed to make shadow");
|
log_error("failed to make shadow");
|
||||||
return XCB_NONE;
|
return XCB_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
shadow_pixmap =
|
shadow_pixmap = x_create_pixmap(ps, 8, ps->root, shadow_image->width, shadow_image->height);
|
||||||
x_create_pixmap(ps, 8, ps->root, shadow_image->width, shadow_image->height);
|
|
||||||
shadow_pixmap_argb =
|
shadow_pixmap_argb =
|
||||||
x_create_pixmap(ps, 32, ps->root, shadow_image->width, shadow_image->height);
|
x_create_pixmap(ps, 32, ps->root, shadow_image->width, shadow_image->height);
|
||||||
|
|
||||||
|
@ -570,8 +585,7 @@ static inline void normalize_conv_kern(int wid, int hei, xcb_render_fixed_t *ker
|
||||||
*
|
*
|
||||||
* @return true if successful, false otherwise
|
* @return true if successful, false otherwise
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, int y, int wid,
|
||||||
xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, int y, int wid,
|
|
||||||
int hei, xcb_render_fixed_t **blur_kerns, const region_t *reg_clip) {
|
int hei, xcb_render_fixed_t **blur_kerns, const region_t *reg_clip) {
|
||||||
assert(blur_kerns[0]);
|
assert(blur_kerns[0]);
|
||||||
|
|
||||||
|
@ -600,12 +614,10 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, int y, int wi
|
||||||
// be applied on source picture, to get the nearby pixels outside the
|
// be applied on source picture, to get the nearby pixels outside the
|
||||||
// window.
|
// window.
|
||||||
xcb_render_set_picture_filter(ps->c, src_pict, strlen(XRFILTER_CONVOLUTION),
|
xcb_render_set_picture_filter(ps->c, src_pict, strlen(XRFILTER_CONVOLUTION),
|
||||||
XRFILTER_CONVOLUTION, kwid * khei + 2,
|
XRFILTER_CONVOLUTION, kwid * khei + 2, convolution_blur);
|
||||||
convolution_blur);
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE, dst_pict,
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE,
|
(rd_from_tgt ? x : 0), (rd_from_tgt ? y : 0), 0, 0,
|
||||||
dst_pict, (rd_from_tgt ? x : 0),
|
(rd_from_tgt ? 0 : x), (rd_from_tgt ? 0 : y), wid, hei);
|
||||||
(rd_from_tgt ? y : 0), 0, 0, (rd_from_tgt ? 0 : x),
|
|
||||||
(rd_from_tgt ? 0 : y), wid, hei);
|
|
||||||
xrfilter_reset(ps, src_pict);
|
xrfilter_reset(ps, src_pict);
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -672,12 +684,10 @@ static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modify the factor of the center pixel
|
// Modify the factor of the center pixel
|
||||||
kern_src[2 + (khei / 2) * kwid + kwid / 2] =
|
kern_src[2 + (khei / 2) * kwid + kwid / 2] = DOUBLE_TO_XFIXED(factor_center);
|
||||||
DOUBLE_TO_XFIXED(factor_center);
|
|
||||||
|
|
||||||
// Copy over
|
// Copy over
|
||||||
memcpy(kern_dst, kern_src,
|
memcpy(kern_dst, kern_src, (kwid * khei + 2) * sizeof(xcb_render_fixed_t));
|
||||||
(kwid * khei + 2) * sizeof(xcb_render_fixed_t));
|
|
||||||
normalize_conv_kern(kwid, khei, kern_dst + 2);
|
normalize_conv_kern(kwid, khei, kern_dst + 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,10 +718,40 @@ static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize a region.
|
||||||
|
*/
|
||||||
|
static inline void resize_region(region_t *region, short mod) {
|
||||||
|
if (!mod || !region)
|
||||||
|
return;
|
||||||
|
// Loop through all rectangles
|
||||||
|
int nrects;
|
||||||
|
int nnewrects = 0;
|
||||||
|
pixman_box32_t *rects = pixman_region32_rectangles(region, &nrects);
|
||||||
|
auto newrects = ccalloc(nrects, pixman_box32_t);
|
||||||
|
for (int i = 0; i < nrects; i++) {
|
||||||
|
int x1 = rects[i].x1 - mod;
|
||||||
|
int y1 = rects[i].y1 - mod;
|
||||||
|
int x2 = rects[i].x2 + mod;
|
||||||
|
int y2 = rects[i].y2 + mod;
|
||||||
|
int wid = x2 - x1;
|
||||||
|
int hei = y2 - y1;
|
||||||
|
if (wid <= 0 || hei <= 0)
|
||||||
|
continue;
|
||||||
|
newrects[nnewrects] = (pixman_box32_t){.x1 = x1, .x2 = x2, .y1 = y1, .y2 = y2};
|
||||||
|
++nnewrects;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_region32_fini(region);
|
||||||
|
pixman_region32_init_rects(region, newrects, nnewrects);
|
||||||
|
|
||||||
|
free(newrects);
|
||||||
|
}
|
||||||
|
|
||||||
/// paint all windows
|
/// paint all windows
|
||||||
/// region = ??
|
/// region = ??
|
||||||
/// region_real = the damage region
|
/// region_real = the damage region
|
||||||
void paint_all(session_t *ps, region_t *region, const region_t *region_real, win *const t) {
|
void paint_all(session_t *ps, win *const t, bool ignore_damage) {
|
||||||
if (ps->o.xrender_sync_fence) {
|
if (ps->o.xrender_sync_fence) {
|
||||||
if (!x_fence_sync(ps, ps->sync_fence)) {
|
if (!x_fence_sync(ps, ps->sync_fence)) {
|
||||||
log_error("x_fence_sync failed, xrender-sync-fence will be "
|
log_error("x_fence_sync failed, xrender-sync-fence will be "
|
||||||
|
@ -722,24 +762,32 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!region_real) {
|
region_t region;
|
||||||
region_real = region;
|
pixman_region32_init(®ion);
|
||||||
|
int buffer_age = get_buffer_age(ps);
|
||||||
|
if (buffer_age == -1 || buffer_age > ps->ndamage || ignore_damage) {
|
||||||
|
pixman_region32_copy(®ion, &ps->screen_reg);
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < get_buffer_age(ps); i++) {
|
||||||
|
const int curr = ((ps->damage - ps->damage_ring) + i) % ps->ndamage;
|
||||||
|
pixman_region32_union(®ion, ®ion, &ps->damage_ring[curr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pixman_region32_not_empty(®ion)) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG_REPAINT
|
#ifdef DEBUG_REPAINT
|
||||||
static struct timespec last_paint = {0};
|
static struct timespec last_paint = {0};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!region)
|
if (ps->o.resize_damage > 0) {
|
||||||
region_real = region = &ps->screen_reg;
|
resize_region(®ion, ps->o.resize_damage);
|
||||||
else
|
}
|
||||||
// Remove the damaged area out of screen
|
|
||||||
pixman_region32_intersect(region, region, &ps->screen_reg);
|
|
||||||
|
|
||||||
#ifdef CONFIG_OPENGL
|
// Remove the damaged area out of screen
|
||||||
if (bkend_use_glx(ps))
|
pixman_region32_intersect(®ion, ®ion, &ps->screen_reg);
|
||||||
glx_paint_pre(ps, region);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!paint_isvalid(ps, &ps->tgt_buffer)) {
|
if (!paint_isvalid(ps, &ps->tgt_buffer)) {
|
||||||
if (!ps->tgt_buffer.pixmap) {
|
if (!ps->tgt_buffer.pixmap) {
|
||||||
|
@ -759,26 +807,34 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BKEND_XRENDER == ps->o.backend) {
|
if (BKEND_XRENDER == ps->o.backend) {
|
||||||
x_set_picture_clip_region(ps, ps->tgt_picture, 0, 0, region_real);
|
x_set_picture_clip_region(ps, ps->tgt_picture, 0, 0, ®ion);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_OPENGL
|
||||||
|
if (bkend_use_glx(ps)) {
|
||||||
|
ps->psglx->z = 0.0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
region_t reg_tmp, *reg_paint;
|
region_t reg_tmp, *reg_paint;
|
||||||
pixman_region32_init(®_tmp);
|
pixman_region32_init(®_tmp);
|
||||||
if (t) {
|
if (t) {
|
||||||
// Calculate the region upon which the root window is to be painted
|
// Calculate the region upon which the root window is to be
|
||||||
// based on the ignore region of the lowest window, if available
|
// painted based on the ignore region of the lowest window, if
|
||||||
pixman_region32_subtract(®_tmp, region, t->reg_ignore);
|
// available
|
||||||
|
pixman_region32_subtract(®_tmp, ®ion, t->reg_ignore);
|
||||||
reg_paint = ®_tmp;
|
reg_paint = ®_tmp;
|
||||||
} else {
|
} else {
|
||||||
reg_paint = region;
|
reg_paint = ®ion;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_tgt_clip(ps, reg_paint);
|
set_tgt_clip(ps, reg_paint);
|
||||||
paint_root(ps, reg_paint);
|
paint_root(ps, reg_paint);
|
||||||
|
|
||||||
// Windows are sorted from bottom to top
|
// Windows are sorted from bottom to top
|
||||||
// Each window has a reg_ignore, which is the region obscured by all the windows
|
// Each window has a reg_ignore, which is the region obscured by all the
|
||||||
// on top of that window. This is used to reduce the number of pixels painted.
|
// windows on top of that window. This is used to reduce the number of
|
||||||
|
// pixels painted.
|
||||||
//
|
//
|
||||||
// Whether this is beneficial is to be determined XXX
|
// Whether this is beneficial is to be determined XXX
|
||||||
for (win *w = t; w; w = w->prev_trans) {
|
for (win *w = t; w; w = w->prev_trans) {
|
||||||
|
@ -790,39 +846,39 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win
|
||||||
if (!win_build_shadow(ps, w, 1))
|
if (!win_build_shadow(ps, w, 1))
|
||||||
log_error("build shadow failed");
|
log_error("build shadow failed");
|
||||||
|
|
||||||
// Shadow doesn't need to be painted underneath the body of
|
// Shadow doesn't need to be painted underneath the body
|
||||||
// the window Because no one can see it
|
// of the windows above. Because no one can see it
|
||||||
pixman_region32_subtract(®_tmp, region, w->reg_ignore);
|
pixman_region32_subtract(®_tmp, ®ion, w->reg_ignore);
|
||||||
|
|
||||||
// Mask out the region we don't want shadow on
|
// Mask out the region we don't want shadow on
|
||||||
if (pixman_region32_not_empty(&ps->shadow_exclude_reg))
|
if (pixman_region32_not_empty(&ps->shadow_exclude_reg))
|
||||||
pixman_region32_subtract(®_tmp, ®_tmp,
|
pixman_region32_subtract(®_tmp, ®_tmp, &ps->shadow_exclude_reg);
|
||||||
&ps->shadow_exclude_reg);
|
|
||||||
|
|
||||||
// Might be worth while to crop the region to shadow border
|
// Might be worth while to crop the region to shadow
|
||||||
pixman_region32_intersect_rect(
|
// border
|
||||||
®_tmp, ®_tmp, w->g.x + w->shadow_dx,
|
pixman_region32_intersect_rect(®_tmp, ®_tmp, w->g.x + w->shadow_dx,
|
||||||
w->g.y + w->shadow_dy, w->shadow_width, w->shadow_height);
|
w->g.y + w->shadow_dy,
|
||||||
|
w->shadow_width, w->shadow_height);
|
||||||
|
|
||||||
// Mask out the body of the window from the shadow if needed
|
// Mask out the body of the window from the shadow if
|
||||||
// Doing it here instead of in make_shadow() for saving GPU
|
// needed Doing it here instead of in make_shadow() for
|
||||||
// power and handling shaped windows (XXX unconfirmed)
|
// saving GPU power and handling shaped windows (XXX
|
||||||
|
// unconfirmed)
|
||||||
if (!ps->o.wintype_option[w->window_type].full_shadow)
|
if (!ps->o.wintype_option[w->window_type].full_shadow)
|
||||||
pixman_region32_subtract(®_tmp, ®_tmp, &bshape);
|
pixman_region32_subtract(®_tmp, ®_tmp, &bshape);
|
||||||
|
|
||||||
#ifdef CONFIG_XINERAMA
|
#ifdef CONFIG_XINERAMA
|
||||||
if (ps->o.xinerama_shadow_crop && w->xinerama_scr >= 0 &&
|
if (ps->o.xinerama_shadow_crop && w->xinerama_scr >= 0 &&
|
||||||
w->xinerama_scr < ps->xinerama_nscrs)
|
w->xinerama_scr < ps->xinerama_nscrs)
|
||||||
// There can be a window where number of screens is
|
// There can be a window where number of screens
|
||||||
// updated, but the screen number attached to the
|
// is updated, but the screen number attached to
|
||||||
// windows have not.
|
// the windows have not.
|
||||||
//
|
//
|
||||||
// Window screen number will be updated eventually,
|
// Window screen number will be updated
|
||||||
// so here we just check to make sure we don't access
|
// eventually, so here we just check to make sure
|
||||||
// out of bounds.
|
// we don't access out of bounds.
|
||||||
pixman_region32_intersect(
|
pixman_region32_intersect(
|
||||||
®_tmp, ®_tmp,
|
®_tmp, ®_tmp, &ps->xinerama_scr_regs[w->xinerama_scr]);
|
||||||
&ps->xinerama_scr_regs[w->xinerama_scr]);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Detect if the region is empty before painting
|
// Detect if the region is empty before painting
|
||||||
|
@ -832,10 +888,11 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the region based on the reg_ignore of the next (higher)
|
// Calculate the paint region based on the reg_ignore of the current
|
||||||
// window and the bounding region
|
// window and its bounding region.
|
||||||
// XXX XXX
|
// Remeber, reg_ignore is the union of all windows above the current
|
||||||
pixman_region32_subtract(®_tmp, region, w->reg_ignore);
|
// window.
|
||||||
|
pixman_region32_subtract(®_tmp, ®ion, w->reg_ignore);
|
||||||
pixman_region32_intersect(®_tmp, ®_tmp, &bshape);
|
pixman_region32_intersect(®_tmp, ®_tmp, &bshape);
|
||||||
pixman_region32_fini(&bshape);
|
pixman_region32_fini(&bshape);
|
||||||
|
|
||||||
|
@ -855,6 +912,13 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win
|
||||||
// Free up all temporary regions
|
// Free up all temporary regions
|
||||||
pixman_region32_fini(®_tmp);
|
pixman_region32_fini(®_tmp);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
// Do this as early as possible
|
// Do this as early as possible
|
||||||
set_tgt_clip(ps, &ps->screen_reg);
|
set_tgt_clip(ps, &ps->screen_reg);
|
||||||
|
|
||||||
|
@ -886,14 +950,8 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win
|
||||||
// the paint region. This is not very efficient, but since
|
// the paint region. This is not very efficient, but since
|
||||||
// it's for debug only, we don't really care
|
// it's for debug only, we don't really care
|
||||||
|
|
||||||
// First, we clear tgt_buffer.pict's clip region, since we
|
// First we create a new picture, and copy content from the buffer to it
|
||||||
// want to copy everything
|
xcb_render_pictforminfo_t *pictfmt = x_get_pictform_for_visual(ps, ps->vis);
|
||||||
x_set_picture_clip_region(ps, ps->tgt_buffer.pict, 0, 0,
|
|
||||||
&ps->screen_reg);
|
|
||||||
|
|
||||||
// Then we create a new picture, and copy content to it
|
|
||||||
xcb_render_pictforminfo_t *pictfmt =
|
|
||||||
x_get_pictform_for_visual(ps, ps->vis);
|
|
||||||
xcb_render_picture_t new_pict = x_create_picture_with_pictfmt(
|
xcb_render_picture_t new_pict = x_create_picture_with_pictfmt(
|
||||||
ps, ps->root_width, ps->root_height, pictfmt, 0, NULL);
|
ps, ps->root_width, ps->root_height, pictfmt, 0, NULL);
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC,
|
||||||
|
@ -901,22 +959,22 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win
|
||||||
0, 0, 0, 0, ps->root_width, ps->root_height);
|
0, 0, 0, 0, ps->root_width, ps->root_height);
|
||||||
|
|
||||||
// Next, we set the region of paint and highlight it
|
// Next, we set the region of paint and highlight it
|
||||||
x_set_picture_clip_region(ps, new_pict, 0, 0, region_real);
|
x_set_picture_clip_region(ps, new_pict, 0, 0, ®ion);
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_OVER,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_OVER, ps->white_picture,
|
||||||
ps->white_picture,
|
|
||||||
ps->alpha_picts[MAX_ALPHA / 2], new_pict, 0, 0,
|
ps->alpha_picts[MAX_ALPHA / 2], new_pict, 0, 0,
|
||||||
0, 0, 0, 0, ps->root_width, ps->root_height);
|
0, 0, 0, 0, ps->root_width, ps->root_height);
|
||||||
|
|
||||||
// Finally, clear clip region and put the whole thing on screen
|
// Finally, clear clip regions of new_pict and the screen, and put
|
||||||
|
// the whole thing on screen
|
||||||
x_set_picture_clip_region(ps, new_pict, 0, 0, &ps->screen_reg);
|
x_set_picture_clip_region(ps, new_pict, 0, 0, &ps->screen_reg);
|
||||||
|
x_set_picture_clip_region(ps, ps->tgt_picture, 0, 0, &ps->screen_reg);
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, new_pict,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, new_pict,
|
||||||
XCB_NONE, ps->tgt_picture, 0, 0, 0, 0, 0, 0,
|
XCB_NONE, ps->tgt_picture, 0, 0, 0, 0, 0, 0,
|
||||||
ps->root_width, ps->root_height);
|
ps->root_width, ps->root_height);
|
||||||
xcb_render_free_picture(ps->c, new_pict);
|
xcb_render_free_picture(ps->c, new_pict);
|
||||||
} else
|
} else
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, ps->tgt_buffer.pict,
|
||||||
ps->tgt_buffer.pict, XCB_NONE,
|
XCB_NONE, ps->tgt_picture, 0, 0, 0, 0, 0, 0,
|
||||||
ps->tgt_picture, 0, 0, 0, 0, 0, 0,
|
|
||||||
ps->root_width, ps->root_height);
|
ps->root_width, ps->root_height);
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
|
@ -936,7 +994,7 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win
|
||||||
glFlush();
|
glFlush();
|
||||||
glXWaitX();
|
glXWaitX();
|
||||||
glx_render(ps, ps->tgt_buffer.ptex, 0, 0, 0, 0, ps->root_width,
|
glx_render(ps, ps->tgt_buffer.ptex, 0, 0, 0, 0, ps->root_width,
|
||||||
ps->root_height, 0, 1.0, false, false, region_real, NULL);
|
ps->root_height, 0, 1.0, false, false, ®ion, NULL);
|
||||||
// falls through
|
// falls through
|
||||||
case BKEND_GLX: glXSwapBuffers(ps->dpy, get_tgt_window(ps)); break;
|
case BKEND_GLX: glXSwapBuffers(ps->dpy, get_tgt_window(ps)); break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -967,6 +1025,9 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win
|
||||||
log_trace(" %#010lx", w->id);
|
log_trace(" %#010lx", w->id);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Free the paint region
|
||||||
|
pixman_region32_fini(®ion);
|
||||||
|
|
||||||
// Check if fading is finished on all painted windows
|
// Check if fading is finished on all painted windows
|
||||||
{
|
{
|
||||||
win *pprev = NULL;
|
win *pprev = NULL;
|
||||||
|
@ -1095,6 +1156,14 @@ bool init_render(session_t *ps) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ps->ndamage = maximum_buffer_age(ps);
|
||||||
|
ps->damage_ring = ccalloc(ps->ndamage, region_t);
|
||||||
|
ps->damage = ps->damage_ring + ps->ndamage - 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < ps->ndamage; i++) {
|
||||||
|
pixman_region32_init(&ps->damage_ring[i]);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ void
|
||||||
paint_one(session_t *ps, win *w, const region_t *reg_paint);
|
paint_one(session_t *ps, win *w, const region_t *reg_paint);
|
||||||
|
|
||||||
void
|
void
|
||||||
paint_all(session_t *ps, region_t *region, const region_t *region_real, win * const t);
|
paint_all(session_t *ps, win * const t, bool ignore_damage);
|
||||||
|
|
||||||
void free_picture(xcb_connection_t *c, xcb_render_picture_t *p);
|
void free_picture(xcb_connection_t *c, xcb_render_picture_t *p);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue