picom upto date sync with yshui, full anim support

This commit is contained in:
Arda Atci
2022-10-04 00:24:05 +03:00
parent 7107241519
commit f6b0b04f5b
16 changed files with 1108 additions and 196 deletions

View File

@@ -55,6 +55,58 @@ region_t get_damage(session_t *ps, bool all_damage) {
return region;
}
static void process_window_for_painting(session_t *ps, struct managed_win *w,
void *win_image, double additional_alpha,
region_t *reg_bound, region_t *reg_visible,
region_t *reg_paint, region_t *reg_paint_in_bound) {
// For window image processing, we don't have to limit the process
// region to damage for correctness. (see <damager-note> for
// details)
// The visible region, in window local coordinates Although we
// don't limit process region to damage, we provide that info in
// reg_visible as a hint. Since window image data outside of the
// damage region won't be painted onto target
coord_t window_coord = {.x = w->g.x, .y = w->g.y};
coord_t dest_coord = {.x = w->g.x + w->widthb, .y = w->g.y + w->heightb};
region_t reg_visible_local;
{
// The bounding shape, in window local coordinates
region_t reg_bound_local;
pixman_region32_init(&reg_bound_local);
pixman_region32_copy(&reg_bound_local, reg_bound);
pixman_region32_translate(&reg_bound_local, -w->g.x, -w->g.y);
pixman_region32_init(&reg_visible_local);
pixman_region32_intersect(&reg_visible_local, reg_visible, reg_paint);
pixman_region32_translate(&reg_visible_local, -w->g.x, -w->g.y);
// Data outside of the bounding shape won't be visible,
// but it is not necessary to limit the image operations
// to the bounding shape yet. So pass that as the visible
// region, not the clip region.
pixman_region32_intersect(&reg_visible_local, &reg_visible_local,
&reg_bound_local);
pixman_region32_fini(&reg_bound_local);
}
auto new_img = ps->backend_data->ops->clone_image(ps->backend_data, win_image,
&reg_visible_local);
auto reg_frame = win_get_region_frame_local_by_val(w);
double alpha = additional_alpha * w->opacity;
ps->backend_data->ops->set_image_property(
ps->backend_data, IMAGE_PROPERTY_OPACITY, new_img, &alpha);
ps->backend_data->ops->image_op(ps->backend_data, IMAGE_OP_APPLY_ALPHA, new_img,
&reg_frame, &reg_visible_local,
(double[]){w->frame_opacity});
pixman_region32_fini(&reg_frame);
ps->backend_data->ops->compose(ps->backend_data, new_img,
window_coord, NULL, dest_coord,
reg_paint_in_bound, reg_visible);
ps->backend_data->ops->release_image(ps->backend_data, new_img);
pixman_region32_fini(&reg_visible_local);
}
void handle_device_reset(session_t *ps) {
log_error("Device reset detected");
// Wait for reset to complete
@@ -185,7 +237,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
if (ps->root_image) {
ps->backend_data->ops->compose(ps->backend_data, ps->root_image,
(coord_t){0}, NULL, (coord_t){0},
(coord_t){0}, NULL, (coord_t){.x = ps->root_width, .y = ps->root_height},
&reg_paint, &reg_visible);
} else {
ps->backend_data->ops->fill(ps->backend_data, (struct color){0, 0, 0, 1},
@@ -237,6 +289,7 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
* option */
auto real_win_mode = w->mode;
coord_t window_coord = {.x = w->g.x, .y = w->g.y};
coord_t dest_coord = {.x = w->g.x + w->widthb, .y = w->g.y + w->heightb};
if (w->blur_background &&
(ps->o.force_win_blend || real_win_mode == WMODE_TRANS ||
@@ -409,6 +462,17 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
ps->backend_data->ops->set_image_property(
ps->backend_data, IMAGE_PROPERTY_BORDER_WIDTH,
w->win_image, &border_width);
if (w->old_win_image) {
// TODO(dccsillag): explain why the following is
// "necessary"
double zero = 0.0;
ps->backend_data->ops->set_image_property(
ps->backend_data, IMAGE_PROPERTY_BORDER_WIDTH,
w->old_win_image, &zero);
ps->backend_data->ops->set_image_property(
ps->backend_data, IMAGE_PROPERTY_CORNER_RADIUS,
w->old_win_image, &zero);
}
}
ps->backend_data->ops->set_image_property(
@@ -431,53 +495,43 @@ void paint_all_new(session_t *ps, struct managed_win *t, bool ignore_damage) {
}
// Draw window on target
if (w->frame_opacity == 1) {
bool is_animating = 0 <= w->animation_progress && w->animation_progress < 1.0;
if (w->frame_opacity == 1 && !is_animating) {
ps->backend_data->ops->compose(ps->backend_data, w->win_image,
window_coord, NULL, window_coord,
window_coord, NULL, dest_coord,
&reg_paint_in_bound, &reg_visible);
} else {
// For window image processing, we don't have to limit the process
// region to damage for correctness. (see <damager-note> for
// details)
if (is_animating && w->old_win_image) {
bool is_focused = win_is_focused_raw(ps, w);
if (!is_focused && w->focused && w->opacity_is_set)
is_focused = true;
assert(w->old_win_image);
// The visible region, in window local coordinates Although we
// don't limit process region to damage, we provide that info in
// reg_visible as a hint. Since window image data outside of the
// damage region won't be painted onto target
region_t reg_visible_local;
region_t reg_bound_local;
{
// The bounding shape, in window local coordinates
pixman_region32_init(&reg_bound_local);
pixman_region32_copy(&reg_bound_local, &reg_bound);
pixman_region32_translate(&reg_bound_local, -w->g.x, -w->g.y);
bool resizing =
w->g.width != w->pending_g.width ||
w->g.height != w->pending_g.height;
pixman_region32_init(&reg_visible_local);
pixman_region32_intersect(&reg_visible_local,
&reg_visible, &reg_paint);
pixman_region32_translate(&reg_visible_local, -w->g.x,
-w->g.y);
// Data outside of the bounding shape won't be visible,
// but it is not necessary to limit the image operations
// to the bounding shape yet. So pass that as the visible
// region, not the clip region.
pixman_region32_intersect(
&reg_visible_local, &reg_visible_local, &reg_bound_local);
// Only animate opacity here if we are resizing
// a transparent window
process_window_for_painting(ps, w, w->win_image,
is_focused ? 1.0 : w->opacity >= 1 ? 1.0 : w->animation_progress,
&reg_bound, &reg_visible,
&reg_paint, &reg_paint_in_bound);
// Only do this if size changes as otherwise moving
// transparent windows will flicker and if you just
// move so slightly they will keep flickering
if (resizing && (!is_focused || !w->opacity_is_set)) {
process_window_for_painting(ps, w, w->old_win_image,
1.0 - w->animation_progress,
&reg_bound, &reg_visible,
&reg_paint, &reg_paint_in_bound);
}
} else {
process_window_for_painting(
ps, w, w->win_image, 1.0, &reg_bound, &reg_visible,
&reg_paint, &reg_paint_in_bound);
}
auto new_img = ps->backend_data->ops->clone_image(
ps->backend_data, w->win_image, &reg_visible_local);
auto reg_frame = win_get_region_frame_local_by_val(w);
ps->backend_data->ops->image_op(
ps->backend_data, IMAGE_OP_APPLY_ALPHA, new_img, &reg_frame,
&reg_visible_local, (double[]){w->frame_opacity});
pixman_region32_fini(&reg_frame);
ps->backend_data->ops->compose(ps->backend_data, new_img,
window_coord, NULL, window_coord,
&reg_paint_in_bound, &reg_visible);
ps->backend_data->ops->release_image(ps->backend_data, new_img);
pixman_region32_fini(&reg_visible_local);
pixman_region32_fini(&reg_bound_local);
}
skip:
pixman_region32_fini(&reg_bound);

View File

@@ -183,6 +183,11 @@ struct backend_operations {
void *mask, coord_t mask_dst, const region_t *reg_paint,
const region_t *reg_visible);
void (*_compose)(backend_t *backend_data, void *image_data,
int dst_x1, int dst_y1, int dst_x2, int dst_y2,
const region_t *reg_paint, const region_t *reg_visible);
/// Fill rectangle of the rendering buffer, mostly for debug purposes, optional.
void (*fill)(backend_t *backend_data, struct color, const region_t *clip);

View File

@@ -412,7 +412,7 @@ static void _gl_compose(backend_t *base, struct backend_image *img, GLuint targe
}
glUniform1i(win_shader->uniform_mask_tex, 2);
glUniform2f(win_shader->uniform_mask_offset, (float)mask_offset.x,
glUniform2f(win_shader->uniform_mask_offset, (float)mask_offset.x ,
(float)mask_offset.y);
if (mask != NULL) {
glUniform1i(win_shader->uniform_mask_inverted, mask->color_inverted);
@@ -494,7 +494,8 @@ void x_rect_to_coords(int nrects, const rect_t *rects, coord_t image_dst,
int extent_height, int texture_height, int root_height,
bool y_inverted, GLint *coord, GLuint *indices) {
image_dst.y = root_height - image_dst.y;
image_dst.y -= extent_height;
image_dst.y -= extent_height;
for (int i = 0; i < nrects; i++) {
// Y-flip. Note after this, crect.y1 > crect.y2
@@ -573,6 +574,11 @@ void gl_compose(backend_t *base, void *image_data, coord_t image_dst, void *mask
coord_t mask_offset = {.x = mask_dst.x - image_dst.x, .y = mask_dst.y - image_dst.y};
x_rect_to_coords(nrects, rects, image_dst, inner->height, inner->height,
gd->height, inner->y_inverted, coord, indices);
for (unsigned int i = 2; i < 16; i+=4) {
coord[i+0] = lerp_range(0, mask_offset.x, 0, inner->width, coord[i+0]);
coord[i+1] = lerp_range(0, mask_offset.y, 0, inner->height, coord[i+1]);
}
_gl_compose(base, img, gd->back_fbo, mask, mask_offset, coord, indices, nrects);
free(indices);