Refactor shadow generation
Trying to make the code easier to understand. The logic is unchanged. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
edb1139507
commit
4aeffa36b8
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#include "backend.h"
|
#include "backend.h"
|
||||||
#include "backend_common.h"
|
#include "backend_common.h"
|
||||||
#include "x.h"
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#include "x.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a 1x1 <code>Picture</code> of a particular color.
|
* Generate a 1x1 <code>Picture</code> of a particular color.
|
||||||
|
@ -46,20 +46,31 @@ solid_picture(session_t *ps, bool argb, double a, double r, double g, double b)
|
||||||
return picture;
|
return picture;
|
||||||
}
|
}
|
||||||
|
|
||||||
static xcb_image_t *make_shadow(session_t *ps, double opacity, int width, int height) {
|
static xcb_image_t *
|
||||||
|
make_shadow(xcb_connection_t *c, const conv *kernel, const double *shadow_sum,
|
||||||
|
double opacity, int width, int height) {
|
||||||
|
/*
|
||||||
|
* We classify shadows into 4 kinds of regions
|
||||||
|
* r = shadow radius
|
||||||
|
* (0, 0) is the top left of the window itself
|
||||||
|
* -r r width-r width+r
|
||||||
|
* -r +-----+---------+-----+
|
||||||
|
* | 1 | 2 | 1 |
|
||||||
|
* r +-----+---------+-----+
|
||||||
|
* | 2 | 3 | 2 |
|
||||||
|
* height-r +-----+---------+-----+
|
||||||
|
* | 1 | 2 | 1 |
|
||||||
|
* height+r +-----+---------+-----+
|
||||||
|
*/
|
||||||
xcb_image_t *ximage;
|
xcb_image_t *ximage;
|
||||||
int ylimit, xlimit;
|
int d = kernel->size, r = d / 2;
|
||||||
int swidth = width + ps->cgsize;
|
int swidth = width + r * 2, sheight = height + r * 2;
|
||||||
int sheight = height + ps->cgsize;
|
|
||||||
int center = ps->cgsize / 2;
|
|
||||||
int x, y;
|
|
||||||
unsigned char d;
|
|
||||||
int x_diff;
|
|
||||||
int opacity_int = (int)(opacity * 25);
|
|
||||||
|
|
||||||
ximage = xcb_image_create_native(ps->c, swidth, sheight,
|
assert(d % 2 == 1);
|
||||||
XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 0, 0, NULL);
|
assert(d > 0);
|
||||||
|
|
||||||
|
ximage = xcb_image_create_native(c, swidth, sheight, XCB_IMAGE_FORMAT_Z_PIXMAP, 8,
|
||||||
|
0, 0, NULL);
|
||||||
if (!ximage) {
|
if (!ximage) {
|
||||||
log_error("failed to create an X image");
|
log_error("failed to create an X image");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -68,92 +79,91 @@ static xcb_image_t *make_shadow(session_t *ps, double opacity, int width, int he
|
||||||
unsigned char *data = ximage->data;
|
unsigned char *data = ximage->data;
|
||||||
uint32_t sstride = ximage->stride;
|
uint32_t sstride = ximage->stride;
|
||||||
|
|
||||||
/*
|
// If the window body is smaller than the kernel, we do convolution directly
|
||||||
* Build the gaussian in sections
|
if (width < r * 2 && height < r * 2) {
|
||||||
*/
|
for (int y = 0; y < sheight; y++) {
|
||||||
|
for (int x = 0; x < swidth; x++) {
|
||||||
/*
|
double sum = sum_kernel_normalized(
|
||||||
* center (fill the complete data array)
|
kernel, d - x - 1, d - y - 1, width, height);
|
||||||
*/
|
data[y * sstride + x] = sum * 255.0;
|
||||||
|
|
||||||
// XXX If the center part of the shadow would be entirely covered by
|
|
||||||
// the body of the window, we shouldn't need to fill the center here.
|
|
||||||
// XXX In general, we want to just fill the part that is not behind
|
|
||||||
// the window, in order to reduce CPU load and make transparent window
|
|
||||||
// look correct
|
|
||||||
if (ps->cgsize > 0) {
|
|
||||||
d = ps->shadow_top[opacity_int * (ps->cgsize + 1) + ps->cgsize];
|
|
||||||
} else {
|
|
||||||
d = (unsigned char)(sum_kernel(ps->gaussian_map, center, center, width,
|
|
||||||
height) *
|
|
||||||
opacity * 255.0);
|
|
||||||
}
|
}
|
||||||
memset(data, d, sheight * swidth);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* corners
|
|
||||||
*/
|
|
||||||
|
|
||||||
ylimit = ps->cgsize;
|
|
||||||
if (ylimit > sheight / 2)
|
|
||||||
ylimit = (sheight + 1) / 2;
|
|
||||||
|
|
||||||
xlimit = ps->cgsize;
|
|
||||||
if (xlimit > swidth / 2)
|
|
||||||
xlimit = (swidth + 1) / 2;
|
|
||||||
|
|
||||||
for (y = 0; y < ylimit; y++) {
|
|
||||||
for (x = 0; x < xlimit; x++) {
|
|
||||||
if (xlimit == ps->cgsize && ylimit == ps->cgsize) {
|
|
||||||
d = ps->shadow_corner[opacity_int * (ps->cgsize + 1) *
|
|
||||||
(ps->cgsize + 1) +
|
|
||||||
y * (ps->cgsize + 1) + x];
|
|
||||||
} else {
|
|
||||||
d = (unsigned char)(sum_kernel(ps->gaussian_map, x - center,
|
|
||||||
y - center, width, height) *
|
|
||||||
opacity * 255.0);
|
|
||||||
}
|
}
|
||||||
data[y * sstride + x] = d;
|
return ximage;
|
||||||
data[(sheight - y - 1) * sstride + x] = d;
|
}
|
||||||
data[(sheight - y - 1) * sstride + (swidth - x - 1)] = d;
|
|
||||||
data[y * sstride + (swidth - x - 1)] = d;
|
if (height < r * 2) {
|
||||||
|
// If the window height is smaller than the kernel, we divide
|
||||||
|
// the window like this:
|
||||||
|
// -r r width-r width+r
|
||||||
|
// +------+-------------+------+
|
||||||
|
// | | | |
|
||||||
|
// +------+-------------+------+
|
||||||
|
for (int y = 0; y < sheight; y++) {
|
||||||
|
for (int x = 0; x < r * 2; x++) {
|
||||||
|
double sum = sum_kernel_normalized(kernel, d - x - 1,
|
||||||
|
d - y - 1, d, height) *
|
||||||
|
255.0;
|
||||||
|
data[y * sstride + x] = sum;
|
||||||
|
data[y * sstride + swidth - x - 1] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int y = 0; y < sheight; y++) {
|
||||||
|
double sum =
|
||||||
|
sum_kernel_normalized(kernel, 0, d - y - 1, d, height) * 255.0;
|
||||||
|
memset(&data[y * sstride + r * 2], sum, width - 2 * r);
|
||||||
|
}
|
||||||
|
return ximage;
|
||||||
|
}
|
||||||
|
if (width < r * 2) {
|
||||||
|
// Similarly, for width smaller than kernel
|
||||||
|
for (int y = 0; y < r * 2; y++) {
|
||||||
|
for (int x = 0; x < swidth; x++) {
|
||||||
|
double sum = sum_kernel_normalized(kernel, d - x - 1,
|
||||||
|
d - y - 1, width, d) *
|
||||||
|
255.0;
|
||||||
|
data[y * sstride + x] = sum;
|
||||||
|
data[(sheight - y - 1) * sstride + x] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int x = 0; x < swidth; x++) {
|
||||||
|
double sum =
|
||||||
|
sum_kernel_normalized(kernel, d - x - 1, 0, width, d) * 255.0;
|
||||||
|
for (int y = r * 2; y < height; y++) {
|
||||||
|
data[y * sstride + x] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ximage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill part 3
|
||||||
|
for (int y = r; y < height + r; y++) {
|
||||||
|
memset(data + sstride * y + r, 255, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Part 1
|
||||||
|
for (int y = 0; y < r * 2; y++) {
|
||||||
|
for (int x = 0; x < r * 2; x++) {
|
||||||
|
double tmpsum = shadow_sum[y * d + x] * opacity * 255.0;
|
||||||
|
data[y * sstride + x] = tmpsum;
|
||||||
|
data[(sheight - y - 1) * sstride + x] = tmpsum;
|
||||||
|
data[(sheight - y - 1) * sstride + (swidth - x - 1)] = tmpsum;
|
||||||
|
data[y * sstride + (swidth - x - 1)] = tmpsum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Part 2, top/bottom
|
||||||
* top/bottom
|
for (int y = 0; y < r * 2; y++) {
|
||||||
*/
|
double tmpsum = shadow_sum[d * y + d - 1] * opacity * 255.0;
|
||||||
|
memset(&data[y * sstride + r * 2], tmpsum, width - r * 2);
|
||||||
x_diff = swidth - (ps->cgsize * 2);
|
memset(&data[(sheight - y - 1) * sstride + r * 2], tmpsum, width - r * 2);
|
||||||
if (x_diff > 0 && ylimit > 0) {
|
|
||||||
for (y = 0; y < ylimit; y++) {
|
|
||||||
if (ylimit == ps->cgsize) {
|
|
||||||
d = ps->shadow_top[opacity_int * (ps->cgsize + 1) + y];
|
|
||||||
} else {
|
|
||||||
d = (unsigned char)(sum_kernel(ps->gaussian_map, center,
|
|
||||||
y - center, width, height) *
|
|
||||||
opacity * 255.0);
|
|
||||||
}
|
|
||||||
memset(&data[y * sstride + ps->cgsize], d, x_diff);
|
|
||||||
memset(&data[(sheight - y - 1) * sstride + ps->cgsize], d, x_diff);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Part 2, left/right
|
||||||
* sides
|
for (int x = 0; x < r * 2; x++) {
|
||||||
*/
|
double tmpsum = shadow_sum[d * (d - 1) + x] * opacity * 255.0;
|
||||||
|
for (int y = r * 2; y < height; y++) {
|
||||||
for (x = 0; x < xlimit; x++) {
|
data[y * sstride + x] = tmpsum;
|
||||||
if (xlimit == ps->cgsize) {
|
data[y * sstride + (swidth - x - 1)] = tmpsum;
|
||||||
d = ps->shadow_top[opacity_int * (ps->cgsize + 1) + x];
|
|
||||||
} else {
|
|
||||||
d = (unsigned char)(sum_kernel(ps->gaussian_map, x - center,
|
|
||||||
center, width, height) *
|
|
||||||
opacity * 255.0);
|
|
||||||
}
|
|
||||||
for (y = ps->cgsize; y < sheight - ps->cgsize; y++) {
|
|
||||||
data[y * sstride + x] = d;
|
|
||||||
data[y * sstride + (swidth - x - 1)] = d;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,7 +181,8 @@ bool build_shadow(session_t *ps, double opacity, const int width, const int heig
|
||||||
xcb_render_picture_t shadow_picture = None, shadow_picture_argb = None;
|
xcb_render_picture_t shadow_picture = None, shadow_picture_argb = None;
|
||||||
xcb_gcontext_t gc = None;
|
xcb_gcontext_t gc = None;
|
||||||
|
|
||||||
shadow_image = make_shadow(ps, opacity, width, height);
|
shadow_image =
|
||||||
|
make_shadow(ps->c, ps->gaussian_map, ps->shadow_sum, 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;
|
||||||
|
|
|
@ -531,12 +531,8 @@ typedef struct session {
|
||||||
/// Gaussian map of shadow.
|
/// Gaussian map of shadow.
|
||||||
conv *gaussian_map;
|
conv *gaussian_map;
|
||||||
// for shadow precomputation
|
// for shadow precomputation
|
||||||
/// Shadow depth on one side.
|
/// Pre-computed table for shadow.
|
||||||
int cgsize;
|
double *shadow_sum;
|
||||||
/// Pre-computed color table for corners of shadow.
|
|
||||||
unsigned char *shadow_corner;
|
|
||||||
/// Pre-computed color table for a side of shadow.
|
|
||||||
unsigned char *shadow_top;
|
|
||||||
/// 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,9 +2640,7 @@ 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,
|
||||||
.cgsize = 0,
|
.shadow_sum = NULL,
|
||||||
.shadow_corner = NULL,
|
|
||||||
.shadow_top = NULL,
|
|
||||||
|
|
||||||
.refresh_rate = 0,
|
.refresh_rate = 0,
|
||||||
.refresh_intv = 0UL,
|
.refresh_intv = 0UL,
|
||||||
|
|
116
src/kernel.c
116
src/kernel.c
|
@ -6,75 +6,46 @@
|
||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
/// Sum a region convolution kernel. Region is defined by a width x height rectangle whose
|
||||||
|
/// top left corner is at (x, y)
|
||||||
|
double sum_kernel(const conv *map, int x, int y, int width, int height) {
|
||||||
|
double ret = 0;
|
||||||
/*
|
/*
|
||||||
* A picture will help
|
* Compute set of filter values which are "in range"
|
||||||
*
|
|
||||||
* -center 0 width width+center
|
|
||||||
* -center +-----+-------------------+-----+
|
|
||||||
* | | | |
|
|
||||||
* | | | |
|
|
||||||
* 0 +-----+-------------------+-----+
|
|
||||||
* | | | |
|
|
||||||
* | | | |
|
|
||||||
* | | | |
|
|
||||||
* height +-----+-------------------+-----+
|
|
||||||
* | | | |
|
|
||||||
* height+ | | | |
|
|
||||||
* center +-----+-------------------+-----+
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
double sum_kernel(const conv *map, int x, int y, int width,
|
int xstart = x;
|
||||||
int height) {
|
if (xstart < 0)
|
||||||
int fx, fy;
|
xstart = 0;
|
||||||
const double *g_data;
|
int xend = width + x;
|
||||||
const double *g_line = map->data;
|
if (xend > map->size)
|
||||||
int g_size = map->size;
|
xend = map->size;
|
||||||
int center = g_size / 2;
|
|
||||||
int fx_start, fx_end;
|
|
||||||
int fy_start, fy_end;
|
|
||||||
double v;
|
|
||||||
|
|
||||||
/*
|
int ystart = y;
|
||||||
* Compute set of filter values which are "in range",
|
if (ystart < 0)
|
||||||
* that's the set with:
|
ystart = 0;
|
||||||
* 0 <= x + (fx-center) && x + (fx-center) < width &&
|
int yend = height + y;
|
||||||
* 0 <= y + (fy-center) && y + (fy-center) < height
|
if (yend > map->size)
|
||||||
*
|
yend = map->size;
|
||||||
* 0 <= x + (fx - center) x + fx - center < width
|
|
||||||
* center - x <= fx fx < width + center - x
|
|
||||||
*/
|
|
||||||
|
|
||||||
fx_start = center - x;
|
for (int yi = ystart; yi < yend; yi++) {
|
||||||
if (fx_start < 0)
|
for (int xi = xstart; xi < xend; xi++) {
|
||||||
fx_start = 0;
|
ret += map->data[yi * map->size + xi];
|
||||||
fx_end = width + center - x;
|
|
||||||
if (fx_end > g_size)
|
|
||||||
fx_end = g_size;
|
|
||||||
|
|
||||||
fy_start = center - y;
|
|
||||||
if (fy_start < 0)
|
|
||||||
fy_start = 0;
|
|
||||||
fy_end = height + center - y;
|
|
||||||
if (fy_end > g_size)
|
|
||||||
fy_end = g_size;
|
|
||||||
|
|
||||||
g_line = g_line + fy_start * g_size + fx_start;
|
|
||||||
|
|
||||||
v = 0;
|
|
||||||
|
|
||||||
for (fy = fy_start; fy < fy_end; fy++) {
|
|
||||||
g_data = g_line;
|
|
||||||
g_line += g_size;
|
|
||||||
|
|
||||||
for (fx = fx_start; fx < fx_end; fx++) {
|
|
||||||
v += *g_data++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (v > 1)
|
return ret;
|
||||||
v = 1;
|
}
|
||||||
|
|
||||||
return v;
|
double sum_kernel_normalized(const conv *map, int x, int y, int width, int height) {
|
||||||
|
double ret = sum_kernel(map, x, y, width, height);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
if (ret > 1) {
|
||||||
|
ret = 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static double attr_const gaussian(double r, double x, double y) {
|
static double attr_const gaussian(double r, double x, double y) {
|
||||||
|
@ -113,4 +84,29 @@ conv *gaussian_kernel(double r) {
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
void shadow_preprocess(conv *map, double **shadow_sum) {
|
||||||
|
const int d = map->size;
|
||||||
|
|
||||||
|
if (*shadow_sum)
|
||||||
|
free(*shadow_sum);
|
||||||
|
|
||||||
|
auto sum = *shadow_sum = ccalloc(d * d, double);
|
||||||
|
sum[0] = map->data[0];
|
||||||
|
|
||||||
|
for (int x = 1; x < d; x++) {
|
||||||
|
sum[x] = sum[x - 1] + map->data[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int y = 1; y < d; y++) {
|
||||||
|
sum[y * d] = sum[(y - 1) * d] + map->data[y * d];
|
||||||
|
for (int x = 1; x < d; x++) {
|
||||||
|
double tmp = sum[(y - 1) * d + x] + sum[y * d + x - 1] -
|
||||||
|
sum[(y - 1) * d + x - 1];
|
||||||
|
sum[y * d + x] = tmp + map->data[y * d + x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// vim: set noet sw=8 ts=8 :
|
// vim: set noet sw=8 ts=8 :
|
||||||
|
|
|
@ -14,6 +14,11 @@ typedef struct conv {
|
||||||
/// Calculate the sum of a rectangle part of the convolution kernel
|
/// Calculate the sum of a rectangle part of the convolution kernel
|
||||||
/// the rectangle is defined by top left (x, y), and a size (width x height)
|
/// the rectangle is defined by top left (x, y), and a size (width x height)
|
||||||
double attr_const sum_kernel(const conv *map, int x, int y, int width, int height);
|
double attr_const sum_kernel(const conv *map, int x, int y, int width, int height);
|
||||||
|
double attr_const sum_kernel_normalized(const conv *map, int x, int y, int width, int height);
|
||||||
|
|
||||||
/// Create a kernel with gaussian distribution of radius r
|
/// Create a kernel with gaussian distribution of radius r
|
||||||
conv *gaussian_kernel(double r);
|
conv *gaussian_kernel(double r);
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
void shadow_preprocess(conv *map, double **shadow_sum);
|
||||||
|
|
306
src/render.c
306
src/render.c
|
@ -99,9 +99,8 @@ void render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, doubl
|
||||||
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,
|
xcb_render_composite(ps->c, op, pict, alpha_pict, ps->tgt_buffer.pict,
|
||||||
ps->tgt_buffer.pict, x, y, 0, 0, dx, dy, wid,
|
x, y, 0, 0, dx, dy, wid, hei);
|
||||||
hei);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -221,14 +220,14 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
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, XCB_NONE, newpict, 0, 0, 0, 0,
|
ps->white_picture, XCB_NONE, newpict, 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))
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_IN_REVERSE,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_IN_REVERSE,
|
||||||
pict, XCB_NONE, newpict, 0, 0, 0, 0, 0,
|
pict, XCB_NONE, newpict, 0, 0, 0, 0,
|
||||||
0, wid, hei);
|
0, 0, wid, hei);
|
||||||
pict = newpict;
|
pict = newpict;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -256,9 +255,8 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
// top
|
// top
|
||||||
int body_height = hei;
|
int body_height = hei;
|
||||||
// ctop = checked top
|
// ctop = checked top
|
||||||
int ctop = min_i(
|
// Make sure top margin is smaller than height
|
||||||
body_height,
|
int ctop = min_i(body_height, t);
|
||||||
t); // Make sure top margin is smaller than height
|
|
||||||
if (ctop > 0)
|
if (ctop > 0)
|
||||||
COMP_BDR(0, 0, wid, ctop);
|
COMP_BDR(0, 0, wid, ctop);
|
||||||
|
|
||||||
|
@ -268,13 +266,13 @@ void paint_one(session_t *ps, win *w, const region_t *reg_paint) {
|
||||||
|
|
||||||
// bottom
|
// bottom
|
||||||
// cbot = checked bottom
|
// cbot = checked bottom
|
||||||
int cbot =
|
// Make sure bottom margin is not too large
|
||||||
min_i(body_height,
|
int cbot = min_i(body_height, b);
|
||||||
b); // Make sure bottom margin is not too large
|
|
||||||
if (cbot > 0)
|
if (cbot > 0)
|
||||||
COMP_BDR(0, hei - cbot, wid, cbot);
|
COMP_BDR(0, hei - cbot, wid, cbot);
|
||||||
|
|
||||||
body_height -= cbot; // Height of window exclude the margin
|
// Height of window exclude the margin
|
||||||
|
body_height -= cbot;
|
||||||
if (body_height <= 0)
|
if (body_height <= 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -438,20 +436,31 @@ static void paint_root(session_t *ps, const region_t *reg_paint) {
|
||||||
ps->root_tile_paint.pict);
|
ps->root_tile_paint.pict);
|
||||||
}
|
}
|
||||||
|
|
||||||
static xcb_image_t *make_shadow(session_t *ps, double opacity, int width, int height) {
|
static xcb_image_t *
|
||||||
|
make_shadow(xcb_connection_t *c, const conv *kernel, const double *shadow_sum,
|
||||||
|
double opacity, int width, int height) {
|
||||||
|
/*
|
||||||
|
* We classify shadows into 4 kinds of regions
|
||||||
|
* r = shadow radius
|
||||||
|
* (0, 0) is the top left of the window itself
|
||||||
|
* -r r width-r width+r
|
||||||
|
* -r +-----+---------+-----+
|
||||||
|
* | 1 | 2 | 1 |
|
||||||
|
* r +-----+---------+-----+
|
||||||
|
* | 2 | 3 | 2 |
|
||||||
|
* height-r +-----+---------+-----+
|
||||||
|
* | 1 | 2 | 1 |
|
||||||
|
* height+r +-----+---------+-----+
|
||||||
|
*/
|
||||||
xcb_image_t *ximage;
|
xcb_image_t *ximage;
|
||||||
int ylimit, xlimit;
|
int d = kernel->size, r = d / 2;
|
||||||
int swidth = width + ps->cgsize;
|
int swidth = width + r * 2, sheight = height + r * 2;
|
||||||
int sheight = height + ps->cgsize;
|
|
||||||
int center = ps->cgsize / 2;
|
|
||||||
int x, y;
|
|
||||||
unsigned char d;
|
|
||||||
int x_diff;
|
|
||||||
int opacity_int = (int)(opacity * 25);
|
|
||||||
|
|
||||||
ximage = xcb_image_create_native(ps->c, swidth, sheight,
|
assert(d % 2 == 1);
|
||||||
XCB_IMAGE_FORMAT_Z_PIXMAP, 8, 0, 0, NULL);
|
assert(d > 0);
|
||||||
|
|
||||||
|
ximage = xcb_image_create_native(c, swidth, sheight, XCB_IMAGE_FORMAT_Z_PIXMAP, 8,
|
||||||
|
0, 0, NULL);
|
||||||
if (!ximage) {
|
if (!ximage) {
|
||||||
log_error("failed to create an X image");
|
log_error("failed to create an X image");
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -460,92 +469,91 @@ static xcb_image_t *make_shadow(session_t *ps, double opacity, int width, int he
|
||||||
unsigned char *data = ximage->data;
|
unsigned char *data = ximage->data;
|
||||||
uint32_t sstride = ximage->stride;
|
uint32_t sstride = ximage->stride;
|
||||||
|
|
||||||
/*
|
// If the window body is smaller than the kernel, we do convolution directly
|
||||||
* Build the gaussian in sections
|
if (width < r * 2 && height < r * 2) {
|
||||||
*/
|
for (int y = 0; y < sheight; y++) {
|
||||||
|
for (int x = 0; x < swidth; x++) {
|
||||||
/*
|
double sum = sum_kernel_normalized(
|
||||||
* center (fill the complete data array)
|
kernel, d - x - 1, d - y - 1, width, height);
|
||||||
*/
|
data[y * sstride + x] = sum * 255.0;
|
||||||
|
|
||||||
// XXX If the center part of the shadow would be entirely covered by
|
|
||||||
// the body of the window, we shouldn't need to fill the center here.
|
|
||||||
// XXX In general, we want to just fill the part that is not behind
|
|
||||||
// the window, in order to reduce CPU load and make transparent window
|
|
||||||
// look correct
|
|
||||||
if (ps->cgsize > 0) {
|
|
||||||
d = ps->shadow_top[opacity_int * (ps->cgsize + 1) + ps->cgsize];
|
|
||||||
} else {
|
|
||||||
d = (unsigned char)(sum_kernel(ps->gaussian_map, center, center, width,
|
|
||||||
height) *
|
|
||||||
opacity * 255.0);
|
|
||||||
}
|
}
|
||||||
memset(data, d, sheight * swidth);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* corners
|
|
||||||
*/
|
|
||||||
|
|
||||||
ylimit = ps->cgsize;
|
|
||||||
if (ylimit > sheight / 2)
|
|
||||||
ylimit = (sheight + 1) / 2;
|
|
||||||
|
|
||||||
xlimit = ps->cgsize;
|
|
||||||
if (xlimit > swidth / 2)
|
|
||||||
xlimit = (swidth + 1) / 2;
|
|
||||||
|
|
||||||
for (y = 0; y < ylimit; y++) {
|
|
||||||
for (x = 0; x < xlimit; x++) {
|
|
||||||
if (xlimit == ps->cgsize && ylimit == ps->cgsize) {
|
|
||||||
d = ps->shadow_corner[opacity_int * (ps->cgsize + 1) *
|
|
||||||
(ps->cgsize + 1) +
|
|
||||||
y * (ps->cgsize + 1) + x];
|
|
||||||
} else {
|
|
||||||
d = (unsigned char)(sum_kernel(ps->gaussian_map, x - center,
|
|
||||||
y - center, width, height) *
|
|
||||||
opacity * 255.0);
|
|
||||||
}
|
}
|
||||||
data[y * sstride + x] = d;
|
return ximage;
|
||||||
data[(sheight - y - 1) * sstride + x] = d;
|
}
|
||||||
data[(sheight - y - 1) * sstride + (swidth - x - 1)] = d;
|
|
||||||
data[y * sstride + (swidth - x - 1)] = d;
|
if (height < r * 2) {
|
||||||
|
// If the window height is smaller than the kernel, we divide
|
||||||
|
// the window like this:
|
||||||
|
// -r r width-r width+r
|
||||||
|
// +------+-------------+------+
|
||||||
|
// | | | |
|
||||||
|
// +------+-------------+------+
|
||||||
|
for (int y = 0; y < sheight; y++) {
|
||||||
|
for (int x = 0; x < r * 2; x++) {
|
||||||
|
double sum = sum_kernel_normalized(kernel, d - x - 1,
|
||||||
|
d - y - 1, d, height) *
|
||||||
|
255.0;
|
||||||
|
data[y * sstride + x] = sum;
|
||||||
|
data[y * sstride + swidth - x - 1] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int y = 0; y < sheight; y++) {
|
||||||
|
double sum =
|
||||||
|
sum_kernel_normalized(kernel, 0, d - y - 1, d, height) * 255.0;
|
||||||
|
memset(&data[y * sstride + r * 2], sum, width - 2 * r);
|
||||||
|
}
|
||||||
|
return ximage;
|
||||||
|
}
|
||||||
|
if (width < r * 2) {
|
||||||
|
// Similarly, for width smaller than kernel
|
||||||
|
for (int y = 0; y < r * 2; y++) {
|
||||||
|
for (int x = 0; x < swidth; x++) {
|
||||||
|
double sum = sum_kernel_normalized(kernel, d - x - 1,
|
||||||
|
d - y - 1, width, d) *
|
||||||
|
255.0;
|
||||||
|
data[y * sstride + x] = sum;
|
||||||
|
data[(sheight - y - 1) * sstride + x] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int x = 0; x < swidth; x++) {
|
||||||
|
double sum =
|
||||||
|
sum_kernel_normalized(kernel, d - x - 1, 0, width, d) * 255.0;
|
||||||
|
for (int y = r * 2; y < height; y++) {
|
||||||
|
data[y * sstride + x] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ximage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill part 3
|
||||||
|
for (int y = r; y < height + r; y++) {
|
||||||
|
memset(data + sstride * y + r, 255, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Part 1
|
||||||
|
for (int y = 0; y < r * 2; y++) {
|
||||||
|
for (int x = 0; x < r * 2; x++) {
|
||||||
|
double tmpsum = shadow_sum[y * d + x] * opacity * 255.0;
|
||||||
|
data[y * sstride + x] = tmpsum;
|
||||||
|
data[(sheight - y - 1) * sstride + x] = tmpsum;
|
||||||
|
data[(sheight - y - 1) * sstride + (swidth - x - 1)] = tmpsum;
|
||||||
|
data[y * sstride + (swidth - x - 1)] = tmpsum;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Part 2, top/bottom
|
||||||
* top/bottom
|
for (int y = 0; y < r * 2; y++) {
|
||||||
*/
|
double tmpsum = shadow_sum[d * y + d - 1] * opacity * 255.0;
|
||||||
|
memset(&data[y * sstride + r * 2], tmpsum, width - r * 2);
|
||||||
x_diff = swidth - (ps->cgsize * 2);
|
memset(&data[(sheight - y - 1) * sstride + r * 2], tmpsum, width - r * 2);
|
||||||
if (x_diff > 0 && ylimit > 0) {
|
|
||||||
for (y = 0; y < ylimit; y++) {
|
|
||||||
if (ylimit == ps->cgsize) {
|
|
||||||
d = ps->shadow_top[opacity_int * (ps->cgsize + 1) + y];
|
|
||||||
} else {
|
|
||||||
d = (unsigned char)(sum_kernel(ps->gaussian_map, center,
|
|
||||||
y - center, width, height) *
|
|
||||||
opacity * 255.0);
|
|
||||||
}
|
|
||||||
memset(&data[y * sstride + ps->cgsize], d, x_diff);
|
|
||||||
memset(&data[(sheight - y - 1) * sstride + ps->cgsize], d, x_diff);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Part 2, left/right
|
||||||
* sides
|
for (int x = 0; x < r * 2; x++) {
|
||||||
*/
|
double tmpsum = shadow_sum[d * (d - 1) + x] * opacity * 255.0;
|
||||||
|
for (int y = r * 2; y < height; y++) {
|
||||||
for (x = 0; x < xlimit; x++) {
|
data[y * sstride + x] = tmpsum;
|
||||||
if (xlimit == ps->cgsize) {
|
data[y * sstride + (swidth - x - 1)] = tmpsum;
|
||||||
d = ps->shadow_top[opacity_int * (ps->cgsize + 1) + x];
|
|
||||||
} else {
|
|
||||||
d = (unsigned char)(sum_kernel(ps->gaussian_map, x - center,
|
|
||||||
center, width, height) *
|
|
||||||
opacity * 255.0);
|
|
||||||
}
|
|
||||||
for (y = ps->cgsize; y < sheight - ps->cgsize; y++) {
|
|
||||||
data[y * sstride + x] = d;
|
|
||||||
data[y * sstride + (swidth - x - 1)] = d;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -565,7 +573,8 @@ 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 = make_shadow(ps, opacity, width, height);
|
shadow_image =
|
||||||
|
make_shadow(ps->c, ps->gaussian_map, ps->shadow_sum, 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;
|
||||||
|
@ -698,9 +707,9 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, int y, int wi
|
||||||
// Copy from source picture to destination. The filter must
|
// Copy from source picture to destination. The filter must
|
||||||
// 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(
|
xcb_render_set_picture_filter(ps->c, src_pict, strlen(XRFILTER_CONVOLUTION),
|
||||||
ps->c, src_pict, strlen(XRFILTER_CONVOLUTION), XRFILTER_CONVOLUTION,
|
XRFILTER_CONVOLUTION, kwid * khei + 2,
|
||||||
kwid * khei + 2, convolution_blur);
|
convolution_blur);
|
||||||
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE,
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_SRC, src_pict, XCB_NONE,
|
||||||
dst_pict, (rd_from_tgt ? x : 0),
|
dst_pict, (rd_from_tgt ? x : 0),
|
||||||
(rd_from_tgt ? y : 0), 0, 0, (rd_from_tgt ? 0 : x),
|
(rd_from_tgt ? y : 0), 0, 0, (rd_from_tgt ? 0 : x),
|
||||||
|
@ -726,8 +735,7 @@ xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer, int x, int y, int wi
|
||||||
/**
|
/**
|
||||||
* Blur the background of a window.
|
* Blur the background of a window.
|
||||||
*/
|
*/
|
||||||
static inline void
|
static inline void win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer,
|
||||||
win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer,
|
|
||||||
const region_t *reg_paint) {
|
const region_t *reg_paint) {
|
||||||
const int x = w->g.x;
|
const int x = w->g.x;
|
||||||
const int y = w->g.y;
|
const int y = w->g.y;
|
||||||
|
@ -794,8 +802,7 @@ win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer,
|
||||||
}
|
}
|
||||||
// Translate global coordinates to local ones
|
// Translate global coordinates to local ones
|
||||||
pixman_region32_translate(®_blur, -x, -y);
|
pixman_region32_translate(®_blur, -x, -y);
|
||||||
xr_blur_dst(ps, tgt_buffer, x, y, wid, hei, ps->blur_kerns_cache,
|
xr_blur_dst(ps, tgt_buffer, x, y, wid, hei, ps->blur_kerns_cache, ®_blur);
|
||||||
®_blur);
|
|
||||||
pixman_region32_clear(®_blur);
|
pixman_region32_clear(®_blur);
|
||||||
} break;
|
} break;
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
|
@ -815,7 +822,8 @@ win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer,
|
||||||
void paint_all(session_t *ps, region_t *region, const region_t *region_real, win *const t) {
|
void paint_all(session_t *ps, region_t *region, const region_t *region_real, win *const t) {
|
||||||
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 disabled from now on.");
|
log_error("x_fence_sync failed, xrender-sync-fence will be "
|
||||||
|
"disabled from now on.");
|
||||||
xcb_sync_destroy_fence(ps->c, ps->sync_fence);
|
xcb_sync_destroy_fence(ps->c, ps->sync_fence);
|
||||||
ps->sync_fence = XCB_NONE;
|
ps->sync_fence = XCB_NONE;
|
||||||
ps->o.xrender_sync_fence = false;
|
ps->o.xrender_sync_fence = false;
|
||||||
|
@ -997,15 +1005,15 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win
|
||||||
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,
|
||||||
ps->tgt_buffer.pict, XCB_NONE, new_pict, 0, 0, 0,
|
ps->tgt_buffer.pict, XCB_NONE, new_pict, 0, 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, region_real);
|
||||||
xcb_render_composite(
|
xcb_render_composite(ps->c, XCB_RENDER_PICT_OP_OVER,
|
||||||
ps->c, XCB_RENDER_PICT_OP_OVER, ps->white_picture,
|
ps->white_picture,
|
||||||
ps->alpha_picts[MAX_ALPHA / 2], new_pict, 0, 0, 0, 0, 0, 0,
|
ps->alpha_picts[MAX_ALPHA / 2], new_pict, 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 region 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);
|
||||||
|
@ -1015,9 +1023,9 @@ void paint_all(session_t *ps, region_t *region, const region_t *region_real, win
|
||||||
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, XCB_NONE, ps->tgt_picture,
|
ps->tgt_buffer.pict, XCB_NONE,
|
||||||
0, 0, 0, 0, 0, 0, ps->root_width,
|
ps->tgt_picture, 0, 0, 0, 0, 0, 0,
|
||||||
ps->root_height);
|
ps->root_width, ps->root_height);
|
||||||
break;
|
break;
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
case BKEND_XR_GLX_HYBRID:
|
case BKEND_XR_GLX_HYBRID:
|
||||||
|
@ -1091,8 +1099,7 @@ static bool xr_init_blur(session_t *ps) {
|
||||||
char *name = xcb_str_name(iter.data);
|
char *name = xcb_str_name(iter.data);
|
||||||
// Check for the convolution filter
|
// Check for the convolution filter
|
||||||
if (strlen(XRFILTER_CONVOLUTION) == len &&
|
if (strlen(XRFILTER_CONVOLUTION) == len &&
|
||||||
!memcmp(XRFILTER_CONVOLUTION, name,
|
!memcmp(XRFILTER_CONVOLUTION, name, strlen(XRFILTER_CONVOLUTION)))
|
||||||
strlen(XRFILTER_CONVOLUTION)))
|
|
||||||
ps->xrfilter_convolution_exists = true;
|
ps->xrfilter_convolution_exists = true;
|
||||||
}
|
}
|
||||||
free(pf);
|
free(pf);
|
||||||
|
@ -1165,49 +1172,6 @@ static bool init_alpha_picts(session_t *ps) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// precompute shadow corners and sides to save time for large windows
|
|
||||||
static void presum_gaussian(session_t *ps, conv *map) {
|
|
||||||
ps->cgsize = map->size;
|
|
||||||
|
|
||||||
const int center = map->size / 2;
|
|
||||||
const int r = ps->cgsize + 1; // radius of the kernel
|
|
||||||
const int width = ps->cgsize * 2, height = ps->cgsize * 2;
|
|
||||||
|
|
||||||
if (ps->shadow_corner)
|
|
||||||
free(ps->shadow_corner);
|
|
||||||
if (ps->shadow_top)
|
|
||||||
free(ps->shadow_top);
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
ps->shadow_corner = cvalloc(r*r*26);
|
|
||||||
ps->shadow_top = cvalloc(r*26);
|
|
||||||
|
|
||||||
for (int x = 0; x < r; x++) {
|
|
||||||
double sum = sum_kernel(map, x-center, center, width, height);
|
|
||||||
int tmp = ps->shadow_top[25*r+x] = (unsigned char)(sum*255.0);
|
|
||||||
|
|
||||||
for (int opacity = 0; opacity < 25; opacity++) {
|
|
||||||
ps->shadow_top[opacity*r+x] = tmp*opacity/25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int x = 0; x < r; x++) {
|
|
||||||
for (int y = 0; y <= x; y++) {
|
|
||||||
double sum =
|
|
||||||
sum_kernel(map, x-center, y-center, width, height);
|
|
||||||
ps->shadow_corner[25*r*r+y*r+x] = (unsigned char)(sum*255.0);
|
|
||||||
ps->shadow_corner[25*r*r+x*r+y] = ps->shadow_corner[25*r*r+y*r+x];
|
|
||||||
|
|
||||||
for (int opacity = 0; opacity < 25; opacity++) {
|
|
||||||
ps->shadow_corner[opacity*r*r+y*r+x] =
|
|
||||||
ps->shadow_corner[opacity*r*r+x*r+y] =
|
|
||||||
ps->shadow_corner[25*r*r+y*r+x]*opacity/25;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
}
|
|
||||||
|
|
||||||
bool init_render(session_t *ps) {
|
bool init_render(session_t *ps) {
|
||||||
// Initialize OpenGL as early as possible
|
// Initialize OpenGL as early as possible
|
||||||
if (bkend_use_glx(ps)) {
|
if (bkend_use_glx(ps)) {
|
||||||
|
@ -1228,8 +1192,7 @@ bool init_render(session_t *ps) {
|
||||||
// Initialize window GL shader
|
// Initialize window GL shader
|
||||||
if (BKEND_GLX == ps->o.backend && ps->o.glx_fshader_win_str) {
|
if (BKEND_GLX == ps->o.backend && ps->o.glx_fshader_win_str) {
|
||||||
#ifdef CONFIG_OPENGL
|
#ifdef CONFIG_OPENGL
|
||||||
if (!glx_load_prog_main(ps, NULL, ps->o.glx_fshader_win_str,
|
if (!glx_load_prog_main(ps, NULL, ps->o.glx_fshader_win_str, &ps->glx_prog_win))
|
||||||
&ps->glx_prog_win))
|
|
||||||
return false;
|
return false;
|
||||||
#else
|
#else
|
||||||
log_error("GLSL supported not compiled in, can't load "
|
log_error("GLSL supported not compiled in, can't load "
|
||||||
|
@ -1259,7 +1222,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);
|
||||||
presum_gaussian(ps, ps->gaussian_map);
|
shadow_preprocess(ps->gaussian_map, &ps->shadow_sum);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -1317,8 +1280,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_corner);
|
free(ps->shadow_sum);
|
||||||
free(ps->shadow_top);
|
|
||||||
free(ps->gaussian_map);
|
free(ps->gaussian_map);
|
||||||
|
|
||||||
// Free other X resources
|
// Free other X resources
|
||||||
|
|
Loading…
Reference in New Issue