Speed up shadow generation for small windows
Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
3686bf7a33
commit
428c24a6fa
@ -47,7 +47,7 @@ solid_picture(session_t *ps, bool argb, double a, double r, double g, double b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
xcb_image_t *make_shadow(xcb_connection_t *c, const conv *kernel,
|
xcb_image_t *make_shadow(xcb_connection_t *c, const conv *kernel,
|
||||||
const double *shadow_sum, double opacity, int width, int height) {
|
double opacity, int width, int height) {
|
||||||
/*
|
/*
|
||||||
* We classify shadows into 4 kinds of regions
|
* We classify shadows into 4 kinds of regions
|
||||||
* r = shadow radius
|
* r = shadow radius
|
||||||
@ -62,6 +62,7 @@ xcb_image_t *make_shadow(xcb_connection_t *c, const conv *kernel,
|
|||||||
* height+r +-----+---------+-----+
|
* height+r +-----+---------+-----+
|
||||||
*/
|
*/
|
||||||
xcb_image_t *ximage;
|
xcb_image_t *ximage;
|
||||||
|
const double *shadow_sum = kernel->rsum;
|
||||||
int d = kernel->size, r = d / 2;
|
int d = kernel->size, r = d / 2;
|
||||||
int swidth = width + r * 2, sheight = height + r * 2;
|
int swidth = width + r * 2, sheight = height + r * 2;
|
||||||
|
|
||||||
@ -181,7 +182,7 @@ bool build_shadow(session_t *ps, double opacity, const int width, const int heig
|
|||||||
xcb_gcontext_t gc = None;
|
xcb_gcontext_t gc = None;
|
||||||
|
|
||||||
shadow_image =
|
shadow_image =
|
||||||
make_shadow(ps->c, ps->gaussian_map, ps->shadow_sum, 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 false;
|
return false;
|
||||||
|
@ -19,5 +19,5 @@ solid_picture(session_t *ps, bool argb, double a, double r, double g, double b);
|
|||||||
|
|
||||||
void paint_all_new(session_t *ps, region_t *region, win *const t);
|
void paint_all_new(session_t *ps, region_t *region, win *const t);
|
||||||
|
|
||||||
xcb_image_t *make_shadow(xcb_connection_t *c, const conv *kernel,
|
xcb_image_t *
|
||||||
const double *shadow_sum, double opacity, int width, int height);
|
make_shadow(xcb_connection_t *c, const conv *kernel, double opacity, int width, int height);
|
||||||
|
@ -531,8 +531,6 @@ typedef struct session {
|
|||||||
/// Gaussian map of shadow.
|
/// Gaussian map of shadow.
|
||||||
conv *gaussian_map;
|
conv *gaussian_map;
|
||||||
// for shadow precomputation
|
// for shadow precomputation
|
||||||
/// Pre-computed table for shadow.
|
|
||||||
double *shadow_sum;
|
|
||||||
/// A region in which shadow is not painted on.
|
/// A region in which shadow is not painted on.
|
||||||
region_t shadow_exclude_reg;
|
region_t shadow_exclude_reg;
|
||||||
|
|
||||||
|
@ -2640,7 +2640,6 @@ session_init(session_t *ps_old, int argc, char **argv) {
|
|||||||
.cshadow_picture = XCB_NONE,
|
.cshadow_picture = XCB_NONE,
|
||||||
.white_picture = XCB_NONE,
|
.white_picture = XCB_NONE,
|
||||||
.gaussian_map = NULL,
|
.gaussian_map = NULL,
|
||||||
.shadow_sum = NULL,
|
|
||||||
|
|
||||||
.refresh_rate = 0,
|
.refresh_rate = 0,
|
||||||
.refresh_intv = 0UL,
|
.refresh_intv = 0UL,
|
||||||
|
23
src/kernel.c
23
src/kernel.c
@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
@ -28,9 +29,20 @@ double sum_kernel(const conv *map, int x, int y, int width, int height) {
|
|||||||
if (yend > map->size)
|
if (yend > map->size)
|
||||||
yend = map->size;
|
yend = map->size;
|
||||||
|
|
||||||
|
assert(yend > 0 && xend > 0);
|
||||||
|
|
||||||
|
int d = map->size;
|
||||||
|
if (map->rsum) {
|
||||||
|
double v1 = xstart ? map->rsum[(yend - 1) * d + xstart - 1] : 0;
|
||||||
|
double v2 = ystart ? map->rsum[(ystart - 1) * d + xend - 1] : 0;
|
||||||
|
double v3 =
|
||||||
|
(xstart && ystart) ? map->rsum[(ystart - 1) * d + xstart - 1] : 0;
|
||||||
|
return map->rsum[(yend - 1) * d + xend - 1] - v1 - v2 + v3;
|
||||||
|
}
|
||||||
|
|
||||||
for (int yi = ystart; yi < yend; yi++) {
|
for (int yi = ystart; yi < yend; yi++) {
|
||||||
for (int xi = xstart; xi < xend; xi++) {
|
for (int xi = xstart; xi < xend; xi++) {
|
||||||
ret += map->data[yi * map->size + xi];
|
ret += map->data[yi * d + xi];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,6 +77,7 @@ conv *gaussian_kernel(double r) {
|
|||||||
|
|
||||||
c = cvalloc(sizeof(conv) + size * size * sizeof(double));
|
c = cvalloc(sizeof(conv) + size * size * sizeof(double));
|
||||||
c->size = size;
|
c->size = size;
|
||||||
|
c->rsum = NULL;
|
||||||
t = 0.0;
|
t = 0.0;
|
||||||
|
|
||||||
for (int y = 0; y < size; y++) {
|
for (int y = 0; y < size; y++) {
|
||||||
@ -86,13 +99,13 @@ conv *gaussian_kernel(double r) {
|
|||||||
|
|
||||||
/// preprocess kernels to make shadow generation faster
|
/// preprocess kernels to make shadow generation faster
|
||||||
/// shadow_sum[x*d+y] is the sum of the kernel from (0, 0) to (x, y), inclusive
|
/// shadow_sum[x*d+y] is the sum of the kernel from (0, 0) to (x, y), inclusive
|
||||||
void shadow_preprocess(conv *map, double **shadow_sum) {
|
void shadow_preprocess(conv *map) {
|
||||||
const int d = map->size;
|
const int d = map->size;
|
||||||
|
|
||||||
if (*shadow_sum)
|
if (map->rsum)
|
||||||
free(*shadow_sum);
|
free(map->rsum);
|
||||||
|
|
||||||
auto sum = *shadow_sum = ccalloc(d * d, double);
|
auto sum = map->rsum = ccalloc(d * d, double);
|
||||||
sum[0] = map->data[0];
|
sum[0] = map->data[0];
|
||||||
|
|
||||||
for (int x = 1; x < d; x++) {
|
for (int x = 1; x < d; x++) {
|
||||||
|
@ -2,12 +2,14 @@
|
|||||||
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
// Copyright (c) Yuxuan Shui <yshuiv7@gmail.com>
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <stdlib.h>
|
||||||
#include "compiler.h"
|
#include "compiler.h"
|
||||||
|
|
||||||
/// Code for generating convolution kernels
|
/// Code for generating convolution kernels
|
||||||
|
|
||||||
typedef struct conv {
|
typedef struct conv {
|
||||||
int size;
|
int size;
|
||||||
|
double *rsum;
|
||||||
double data[];
|
double data[];
|
||||||
} conv;
|
} conv;
|
||||||
|
|
||||||
@ -21,4 +23,9 @@ conv *gaussian_kernel(double r);
|
|||||||
|
|
||||||
/// preprocess kernels to make shadow generation faster
|
/// preprocess kernels to make shadow generation faster
|
||||||
/// shadow_sum[x*d+y] is the sum of the kernel from (0, 0) to (x, y), inclusive
|
/// shadow_sum[x*d+y] is the sum of the kernel from (0, 0) to (x, y), inclusive
|
||||||
void shadow_preprocess(conv *map, double **shadow_sum);
|
void shadow_preprocess(conv *map);
|
||||||
|
|
||||||
|
static inline void free_conv(conv *k) {
|
||||||
|
free(k->rsum);
|
||||||
|
free(k);
|
||||||
|
}
|
||||||
|
@ -451,7 +451,7 @@ static bool win_build_shadow(session_t *ps, win *w, double opacity) {
|
|||||||
xcb_gcontext_t gc = XCB_NONE;
|
xcb_gcontext_t gc = XCB_NONE;
|
||||||
|
|
||||||
shadow_image =
|
shadow_image =
|
||||||
make_shadow(ps->c, ps->gaussian_map, ps->shadow_sum, 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;
|
||||||
@ -1058,7 +1058,7 @@ bool init_render(session_t *ps) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ps->gaussian_map = gaussian_kernel(ps->o.shadow_radius);
|
ps->gaussian_map = gaussian_kernel(ps->o.shadow_radius);
|
||||||
shadow_preprocess(ps->gaussian_map, &ps->shadow_sum);
|
shadow_preprocess(ps->gaussian_map);
|
||||||
|
|
||||||
ps->black_picture = solid_picture(ps, true, 1, 0, 0, 0);
|
ps->black_picture = solid_picture(ps, true, 1, 0, 0, 0);
|
||||||
ps->white_picture = solid_picture(ps, true, 1, 1, 1, 1);
|
ps->white_picture = solid_picture(ps, true, 1, 1, 1, 1);
|
||||||
@ -1116,8 +1116,7 @@ void deinit_render(session_t *ps) {
|
|||||||
|
|
||||||
free_picture(ps->c, &ps->black_picture);
|
free_picture(ps->c, &ps->black_picture);
|
||||||
free_picture(ps->c, &ps->white_picture);
|
free_picture(ps->c, &ps->white_picture);
|
||||||
free(ps->shadow_sum);
|
free_conv(ps->gaussian_map);
|
||||||
free(ps->gaussian_map);
|
|
||||||
|
|
||||||
// Free other X resources
|
// Free other X resources
|
||||||
free_root_tile(ps);
|
free_root_tile(ps);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user