backend: fix rendering shadow with opacity

Shadow opacity should be multiplied with the window's opacity.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2019-03-10 19:56:55 +00:00
parent 0bd08f4ab4
commit 9296706f7b
No known key found for this signature in database
GPG Key ID: 37C999F617EA1A47
2 changed files with 25 additions and 19 deletions

View File

@ -134,9 +134,21 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
} }
assert(w->shadow_image); assert(w->shadow_image);
ps->backend_data->ops->compose( if (w->opacity == 1) {
ps->backend_data, w->shadow_image, w->g.x + w->shadow_dx, ps->backend_data->ops->compose(
w->g.y + w->shadow_dy, &reg_shadow, &reg_visible); ps->backend_data, w->shadow_image, w->g.x + w->shadow_dx,
w->g.y + w->shadow_dy, &reg_shadow, &reg_visible);
} else {
auto new_img = ps->backend_data->ops->copy(
ps->backend_data, w->shadow_image, &reg_visible);
ps->backend_data->ops->image_op(
ps->backend_data, IMAGE_OP_APPLY_ALPHA_ALL, new_img,
NULL, &reg_visible, (double[]){w->opacity});
ps->backend_data->ops->compose(
ps->backend_data, new_img, w->g.x + w->shadow_dx,
w->g.y + w->shadow_dy, &reg_shadow, &reg_visible);
ps->backend_data->ops->release_image(ps->backend_data, new_img);
}
pixman_region32_fini(&reg_shadow); pixman_region32_fini(&reg_shadow);
} }
@ -244,8 +256,7 @@ void paint_all_new(session_t *ps, win *const t, bool ignore_damage) {
if (ps->o.monitor_repaint) { if (ps->o.monitor_repaint) {
reg_damage = get_damage(ps, false); reg_damage = get_damage(ps, false);
ps->backend_data->ops->fill( ps->backend_data->ops->fill(ps->backend_data, 0.5, 0, 0, 0.5, &reg_damage);
ps->backend_data, 0.5, 0, 0, 0.5, &reg_damage);
pixman_region32_fini(&reg_damage); pixman_region32_fini(&reg_damage);
} }

View File

@ -348,12 +348,10 @@ static bool image_op(backend_t *base, enum image_operations op, void *image,
struct _xrender_data *xd = (void *)base; struct _xrender_data *xd = (void *)base;
struct _xrender_image_data *img = image; struct _xrender_image_data *img = image;
region_t reg; region_t reg;
double dim_opacity; double *dargs = arg;
double alpha_multiplier;
int *iargs = arg; int *iargs = arg;
if (op == IMAGE_OP_APPLY_ALPHA_ALL) { if (op == IMAGE_OP_APPLY_ALPHA_ALL) {
alpha_multiplier = *(double *)arg; img->opacity *= dargs[0];
img->opacity *= alpha_multiplier;
img->has_alpha = true; img->has_alpha = true;
return true; return true;
} }
@ -388,10 +386,9 @@ static bool image_op(backend_t *base, enum image_operations op, void *image,
break; break;
case IMAGE_OP_DIM_ALL: case IMAGE_OP_DIM_ALL:
x_set_picture_clip_region(base->c, img->pict, 0, 0, reg_visible); x_set_picture_clip_region(base->c, img->pict, 0, 0, reg_visible);
dim_opacity = *(double *)arg;
xcb_render_color_t color = { xcb_render_color_t color = {
.red = 0, .green = 0, .blue = 0, .alpha = 0xffff * dim_opacity}; .red = 0, .green = 0, .blue = 0, .alpha = 0xffff * dargs[0]};
// Dim the actually content of window // Dim the actually content of window
xcb_rectangle_t rect = { xcb_rectangle_t rect = {
@ -411,12 +408,11 @@ static bool image_op(backend_t *base, enum image_operations op, void *image,
break; break;
} }
alpha_multiplier = *(double *)arg; if (dargs[0] == 1) {
if (alpha_multiplier == 1) {
break; break;
} }
auto alpha_pict = xd->alpha_pict[(int)(alpha_multiplier * 255)]; auto alpha_pict = xd->alpha_pict[(int)(dargs[0] * 255)];
x_set_picture_clip_region(base->c, img->pict, 0, 0, &reg); x_set_picture_clip_region(base->c, img->pict, 0, 0, &reg);
xcb_render_composite(base->c, XCB_RENDER_PICT_OP_IN, img->pict, XCB_NONE, xcb_render_composite(base->c, XCB_RENDER_PICT_OP_IN, img->pict, XCB_NONE,
alpha_pict, 0, 0, 0, 0, 0, 0, img->width, img->height); alpha_pict, 0, 0, 0, 0, 0, 0, img->width, img->height);
@ -438,22 +434,21 @@ static void *copy(backend_t *base, const void *image, const region_t *reg) {
auto new_img = ccalloc(1, struct _xrender_image_data); auto new_img = ccalloc(1, struct _xrender_image_data);
assert(img->visual != XCB_NONE); assert(img->visual != XCB_NONE);
log_trace("xrender: copying %#010x visual %#x", img->pixmap, img->visual); log_trace("xrender: copying %#010x visual %#x", img->pixmap, img->visual);
*new_img = *img;
x_set_picture_clip_region(base->c, img->pict, 0, 0, reg); x_set_picture_clip_region(base->c, img->pict, 0, 0, reg);
new_img->has_alpha = img->has_alpha;
new_img->width = img->width;
new_img->height = img->height;
new_img->visual = img->visual;
new_img->pixmap = new_img->pixmap =
x_create_pixmap(base->c, img->depth, base->root, img->width, img->height); x_create_pixmap(base->c, img->depth, base->root, img->width, img->height);
new_img->opacity = 1; new_img->opacity = 1;
new_img->owned = true; new_img->owned = true;
if (new_img->pixmap == XCB_NONE) { if (new_img->pixmap == XCB_NONE) {
log_error("Failed to create pixmap for copy");
free(new_img); free(new_img);
return NULL; return NULL;
} }
new_img->pict = x_create_picture_with_visual_and_pixmap(base->c, img->visual, new_img->pict = x_create_picture_with_visual_and_pixmap(base->c, img->visual,
new_img->pixmap, 0, NULL); new_img->pixmap, 0, NULL);
if (new_img->pixmap == XCB_NONE) { if (new_img->pict == XCB_NONE) {
log_error("Failed to create picture for copy");
xcb_free_pixmap(base->c, new_img->pixmap); xcb_free_pixmap(base->c, new_img->pixmap);
free(new_img); free(new_img);
return NULL; return NULL;