new_backend: New interface
Move more logic out of the backend. The backends are now more agnostic to what happens in compton. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
@ -8,18 +8,19 @@
|
||||
#include "config.h"
|
||||
#include "region.h"
|
||||
#include "win.h"
|
||||
#include "log.h"
|
||||
|
||||
backend_info_t *backend_list[NUM_BKEND] = {
|
||||
[BKEND_XRENDER] = &xrender_backend,
|
||||
backend_init_fn backend_list[NUM_BKEND] = {
|
||||
[BKEND_XRENDER] = backend_xrender_init,
|
||||
#ifdef CONFIG_OPENGL
|
||||
[BKEND_GLX] = &glx_backend,
|
||||
[BKEND_GLX] = backend_glx_init,
|
||||
#endif
|
||||
};
|
||||
|
||||
region_t get_damage(session_t *ps) {
|
||||
region_t region;
|
||||
auto buffer_age_fn = backend_list[ps->o.backend]->buffer_age;
|
||||
int buffer_age = buffer_age_fn ? buffer_age_fn(ps->backend_data, ps) : -1;
|
||||
auto buffer_age_fn = ps->backend_data->ops->buffer_age;
|
||||
int buffer_age = buffer_age_fn ? buffer_age_fn(ps->backend_data) : -1;
|
||||
|
||||
pixman_region32_init(®ion);
|
||||
if (buffer_age == -1 || buffer_age > ps->ndamage) {
|
||||
@ -48,8 +49,6 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
|
||||
pixman_region32_fini(®ion);
|
||||
return;
|
||||
}
|
||||
auto bi = backend_list[ps->o.backend];
|
||||
assert(bi);
|
||||
|
||||
#ifdef DEBUG_REPAINT
|
||||
static struct timespec last_paint = {0};
|
||||
@ -67,8 +66,16 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
|
||||
reg_paint = ®ion;
|
||||
}
|
||||
|
||||
if (bi->prepare)
|
||||
bi->prepare(ps->backend_data, ps, reg_paint);
|
||||
// TODO Bind root pixmap
|
||||
|
||||
if (ps->backend_data->ops->prepare) {
|
||||
ps->backend_data->ops->prepare(ps->backend_data, reg_paint);
|
||||
}
|
||||
|
||||
if (ps->root_image) {
|
||||
ps->backend_data->ops->compose(ps->backend_data, ps->root_image, 0, 0,
|
||||
reg_paint);
|
||||
}
|
||||
|
||||
// Windows are sorted from bottom to top
|
||||
// Each window has a reg_ignore, which is the region obscured by all the windows
|
||||
@ -81,52 +88,124 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
|
||||
// XXX XXX
|
||||
pixman_region32_subtract(®_tmp, ®ion, w->reg_ignore);
|
||||
|
||||
if (pixman_region32_not_empty(®_tmp)) {
|
||||
// Render window content
|
||||
// XXX do this in preprocess?
|
||||
bi->render_win(ps->backend_data, ps, w, w->win_data, ®_tmp);
|
||||
if (!pixman_region32_not_empty(®_tmp)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Blur window background
|
||||
bool win_transparent =
|
||||
bi->is_win_transparent(ps->backend_data, w, w->win_data);
|
||||
bool frame_transparent =
|
||||
bi->is_frame_transparent(ps->backend_data, w, w->win_data);
|
||||
if (w->blur_background &&
|
||||
(win_transparent ||
|
||||
(ps->o.blur_background_frame && frame_transparent))) {
|
||||
// Minimize the region we try to blur, if the window
|
||||
// itself is not opaque, only the frame is.
|
||||
region_t reg_blur = win_get_bounding_shape_global_by_val(w);
|
||||
if (win_is_solid(ps, w)) {
|
||||
region_t reg_noframe;
|
||||
pixman_region32_init(®_noframe);
|
||||
win_get_region_noframe_local(w, ®_noframe);
|
||||
pixman_region32_translate(®_noframe, w->g.x,
|
||||
w->g.y);
|
||||
pixman_region32_subtract(®_blur, ®_blur,
|
||||
®_noframe);
|
||||
pixman_region32_fini(®_noframe);
|
||||
}
|
||||
bi->blur(ps->backend_data, ps, w->opacity, ®_blur);
|
||||
pixman_region32_fini(®_blur);
|
||||
auto reg_bound = win_get_bounding_shape_global_by_val(w);
|
||||
// Draw shadow on target
|
||||
if (w->shadow) {
|
||||
auto reg_shadow = win_extents_by_val(w);
|
||||
pixman_region32_intersect(®_shadow, ®_shadow, ®_tmp);
|
||||
|
||||
if (!ps->o.wintype_option[w->window_type].full_shadow) {
|
||||
pixman_region32_subtract(®_shadow, ®_shadow, ®_bound);
|
||||
}
|
||||
|
||||
// Draw window on target
|
||||
bi->compose(ps->backend_data, ps, w, w->win_data, w->g.x, w->g.y,
|
||||
®_tmp);
|
||||
// Mask out the region we don't want shadow on
|
||||
if (pixman_region32_not_empty(&ps->shadow_exclude_reg)) {
|
||||
pixman_region32_subtract(®_tmp, ®_tmp,
|
||||
&ps->shadow_exclude_reg);
|
||||
}
|
||||
|
||||
if (bi->finish_render_win)
|
||||
bi->finish_render_win(ps->backend_data, ps, w, w->win_data);
|
||||
if (ps->o.xinerama_shadow_crop && w->xinerama_scr >= 0 &&
|
||||
w->xinerama_scr < ps->xinerama_nscrs) {
|
||||
// There can be a window where number of screens is
|
||||
// updated, but the screen number attached to the windows
|
||||
// have not.
|
||||
//
|
||||
// Window screen number will be updated eventually, so
|
||||
// here we just check to make sure we don't access out of
|
||||
// bounds.
|
||||
pixman_region32_intersect(
|
||||
®_shadow, ®_shadow,
|
||||
&ps->xinerama_scr_regs[w->xinerama_scr]);
|
||||
}
|
||||
|
||||
assert(w->shadow_image);
|
||||
ps->backend_data->ops->compose(ps->backend_data, w->shadow_image,
|
||||
w->g.x + w->shadow_dx,
|
||||
w->g.y + w->shadow_dy, ®_shadow);
|
||||
pixman_region32_fini(®_shadow);
|
||||
}
|
||||
|
||||
pixman_region32_intersect(®_tmp, ®_tmp, ®_bound);
|
||||
pixman_region32_fini(®_bound);
|
||||
if (!pixman_region32_not_empty(®_tmp)) {
|
||||
continue;
|
||||
}
|
||||
// Blur window background
|
||||
bool win_transparent = ps->backend_data->ops->is_image_transparent(
|
||||
ps->backend_data, w->win_image);
|
||||
bool frame_transparent = w->frame_opacity != 1;
|
||||
if (w->blur_background &&
|
||||
(win_transparent || (ps->o.blur_background_frame && frame_transparent))) {
|
||||
// Minimize the region we try to blur, if the window
|
||||
// itself is not opaque, only the frame is.
|
||||
if (win_is_solid(ps, w)) {
|
||||
region_t reg_blur;
|
||||
pixman_region32_init(®_blur);
|
||||
win_get_region_noframe_local(w, ®_blur);
|
||||
pixman_region32_translate(®_blur, w->g.x, w->g.y);
|
||||
pixman_region32_subtract(®_blur, ®_tmp, ®_blur);
|
||||
ps->backend_data->ops->blur(ps->backend_data, w->opacity,
|
||||
®_blur);
|
||||
pixman_region32_fini(®_blur);
|
||||
} else {
|
||||
ps->backend_data->ops->blur(ps->backend_data, w->opacity,
|
||||
®_tmp);
|
||||
}
|
||||
}
|
||||
// Draw window on target
|
||||
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, w->g.y, ®_tmp);
|
||||
} else {
|
||||
region_t reg_local;
|
||||
pixman_region32_init(®_local);
|
||||
pixman_region32_copy(®_local, ®_tmp);
|
||||
pixman_region32_translate(®_local, -w->g.x, -w->g.y);
|
||||
auto new_img = ps->backend_data->ops->copy(
|
||||
ps->backend_data, w->win_image, ®_local);
|
||||
if (w->invert_color) {
|
||||
ps->backend_data->ops->image_op(ps->backend_data,
|
||||
IMAGE_OP_INVERT_COLOR,
|
||||
new_img, ®_local, NULL);
|
||||
}
|
||||
if (w->dim) {
|
||||
double dim_opacity = ps->o.inactive_dim;
|
||||
if (!ps->o.inactive_dim_fixed) {
|
||||
dim_opacity *= w->opacity;
|
||||
}
|
||||
ps->backend_data->ops->image_op(
|
||||
ps->backend_data, IMAGE_OP_DIM, new_img, ®_local,
|
||||
(double[]){dim_opacity});
|
||||
}
|
||||
if (w->frame_opacity != 1) {
|
||||
auto reg_frame = win_get_region_noframe_local_by_val(w);
|
||||
pixman_region32_subtract(®_frame, ®_local, ®_frame);
|
||||
ps->backend_data->ops->image_op(
|
||||
ps->backend_data, IMAGE_OP_APPLY_ALPHA, new_img,
|
||||
®_frame, (double[]){w->frame_opacity});
|
||||
}
|
||||
if (w->opacity != 1) {
|
||||
ps->backend_data->ops->image_op(
|
||||
ps->backend_data, IMAGE_OP_APPLY_ALPHA, new_img, NULL,
|
||||
(double[]){w->opacity});
|
||||
}
|
||||
ps->backend_data->ops->compose(ps->backend_data, new_img, w->g.x,
|
||||
w->g.y, ®_tmp);
|
||||
ps->backend_data->ops->release_image(ps->backend_data, new_img);
|
||||
}
|
||||
}
|
||||
|
||||
// Free up all temporary regions
|
||||
pixman_region32_fini(®_tmp);
|
||||
|
||||
if (bi->present) {
|
||||
if (ps->backend_data->ops->present) {
|
||||
// Present the rendered scene
|
||||
// Vsync is done here
|
||||
bi->present(ps->backend_data, ps);
|
||||
ps->backend_data->ops->present(ps->backend_data);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_REPAINT
|
||||
|
Reference in New Issue
Block a user