Port from xrender to xcb-render

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2018-09-27 18:14:44 +02:00
parent 6d54d6b055
commit 539d62ca93
8 changed files with 147 additions and 117 deletions

View File

@ -9,7 +9,7 @@ MANDIR ?= $(PREFIX)/share/man/man1
APPDIR ?= $(PREFIX)/share/applications
ICODIR ?= $(PREFIX)/share/icons/hicolor/
PACKAGES = x11 x11-xcb xcb-renderutil xcb-render xcb-damage xcb-randr xcb-image xcomposite xfixes xrender xext
PACKAGES = x11 x11-xcb xcb-renderutil xcb-render xcb-damage xcb-randr xcb-image xcomposite xfixes xext
LIBS = -lm -lrt
INCS =

View File

@ -83,7 +83,6 @@
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/shape.h>
#include <X11/extensions/Xdbe.h>
#ifdef CONFIG_XSYNC
@ -219,6 +218,10 @@
// Window opacity / dim state changed
#define WFLAG_OPCT_CHANGE 0x0004
// xcb-render specific macros
#define XFIXED_TO_DOUBLE(value) (((double) (value)) / 65536)
#define DOUBLE_TO_XFIXED(value) ((xcb_render_fixed_t) (((double) (value)) * 65536))
// === Types ===
typedef uint32_t opacity_t;
@ -489,7 +492,7 @@ typedef struct {
typedef struct {
Pixmap pixmap;
Picture pict;
xcb_render_picture_t pict;
glx_texture_t *ptex;
} paint_t;
@ -685,7 +688,7 @@ typedef struct _options_t {
/// Background blur blacklist. A linked list of conditions.
c2_lptr_t *blur_background_blacklist;
/// Blur convolution kernel.
XFixed *blur_kerns[MAX_BLUR_PASS];
xcb_render_fixed_t *blur_kerns[MAX_BLUR_PASS];
/// How much to dim an inactive window. 0.0 - 1.0, 0 to disable.
double inactive_dim;
/// Whether to use fixed inactive dim opacity, instead of deciding
@ -811,9 +814,9 @@ typedef struct session {
XserverRegion screen_reg;
/// Picture of root window. Destination of painting in no-DBE painting
/// mode.
Picture root_picture;
xcb_render_picture_t root_picture;
/// A Picture acting as the painting target.
Picture tgt_picture;
xcb_render_picture_t tgt_picture;
/// Temporary buffer to paint to before sending to display.
paint_t tgt_buffer;
#ifdef CONFIG_XSYNC
@ -859,7 +862,7 @@ typedef struct session {
/// Whether all windows are currently redirected.
bool redirected;
/// Pre-generated alpha pictures.
Picture *alpha_picts;
xcb_render_picture_t *alpha_picts;
/// Whether all reg_ignore of windows should expire in this paint.
bool reg_ignore_expire;
/// Time of last fading. In milliseconds.
@ -870,7 +873,7 @@ typedef struct session {
/// ignore linked list.
ignore_t **ignore_tail;
// Cached blur convolution kernels.
XFixed *blur_kerns_cache[MAX_BLUR_PASS];
xcb_render_fixed_t *blur_kerns_cache[MAX_BLUR_PASS];
/// Reset program after next paint.
bool reset;
@ -897,11 +900,11 @@ typedef struct session {
// === Shadow/dimming related ===
/// 1x1 black Picture.
Picture black_picture;
xcb_render_picture_t black_picture;
/// 1x1 Picture of the shadow color.
Picture cshadow_picture;
xcb_render_picture_t cshadow_picture;
/// 1x1 white Picture.
Picture white_picture;
xcb_render_picture_t white_picture;
/// Gaussian map of shadow.
conv *gaussian_map;
// for shadow precomputation

View File

@ -25,8 +25,8 @@ static void
configure_win(session_t *ps, xcb_configure_notify_event_t *ce);
static bool
xr_blur_dst(session_t *ps, Picture tgt_buffer,
int x, int y, int wid, int hei, XFixed **blur_kerns,
xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer,
int x, int y, int wid, int hei, xcb_render_fixed_t **blur_kerns,
XserverRegion reg_clip);
static void
@ -619,7 +619,7 @@ win_build_shadow(session_t *ps, win *w, double opacity) {
xcb_image_t *shadow_image = NULL;
Pixmap shadow_pixmap = None, shadow_pixmap_argb = None;
Picture shadow_picture = None, shadow_picture_argb = None;
xcb_render_picture_t shadow_picture = None, shadow_picture_argb = None;
GC gc = None;
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
@ -653,7 +653,7 @@ win_build_shadow(session_t *ps, win *w, double opacity) {
}
xcb_image_put(c, shadow_pixmap, XGContextFromGC(gc), shadow_image, 0, 0, 0);
XRenderComposite(ps->dpy, PictOpSrc, ps->cshadow_picture, shadow_picture,
xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, ps->cshadow_picture, shadow_picture,
shadow_picture_argb, 0, 0, 0, 0, 0, 0,
shadow_image->width, shadow_image->height);
@ -668,7 +668,7 @@ win_build_shadow(session_t *ps, win *w, double opacity) {
XFreeGC(ps->dpy, gc);
xcb_image_destroy(shadow_image);
XFreePixmap(ps->dpy, shadow_pixmap);
XRenderFreePicture(ps->dpy, shadow_picture);
xcb_render_free_picture(c, shadow_picture);
return true;
@ -680,9 +680,9 @@ shadow_picture_err:
if (shadow_pixmap_argb)
XFreePixmap(ps->dpy, shadow_pixmap_argb);
if (shadow_picture)
XRenderFreePicture(ps->dpy, shadow_picture);
xcb_render_free_picture(c, shadow_picture);
if (shadow_picture_argb)
XRenderFreePicture(ps->dpy, shadow_picture_argb);
xcb_render_free_picture(c, shadow_picture_argb);
if (gc)
XFreeGC(ps->dpy, gc);
@ -692,13 +692,15 @@ shadow_picture_err:
/**
* Generate a 1x1 <code>Picture</code> of a particular color.
*/
static Picture
static xcb_render_picture_t
solid_picture(session_t *ps, bool argb, double a,
double r, double g, double b) {
Pixmap pixmap;
Picture picture;
xcb_render_picture_t picture;
xcb_render_create_picture_value_list_t pa;
XRenderColor c;
xcb_render_color_t col;
xcb_rectangle_t rect;
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
pixmap = XCreatePixmap(ps->dpy, ps->root, 1, 1, argb ? 32 : 8);
@ -707,19 +709,24 @@ solid_picture(session_t *ps, bool argb, double a,
pa.repeat = True;
picture = x_create_picture_with_standard_and_pixmap(ps,
argb ? XCB_PICT_STANDARD_ARGB_32 : XCB_PICT_STANDARD_A_8, pixmap,
CPRepeat, &pa);
XCB_RENDER_CP_REPEAT, &pa);
if (!picture) {
XFreePixmap(ps->dpy, pixmap);
return None;
}
c.alpha = a * 0xffff;
c.red = r * 0xffff;
c.green = g * 0xffff;
c.blue = b * 0xffff;
col.alpha = a * 0xffff;
col.red = r * 0xffff;
col.green = g * 0xffff;
col.blue = b * 0xffff;
XRenderFillRectangle(ps->dpy, PictOpSrc, picture, &c, 0, 0, 1, 1);
rect.x = 0;
rect.y = 0;
rect.width = 1;
rect.height = 1;
xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_SRC, picture, col, 1, &rect);
XFreePixmap(ps->dpy, pixmap);
return picture;
@ -858,6 +865,7 @@ get_root_tile(session_t *ps) {
if (ps->o.paint_on_overlay) {
return ps->root_picture;
} */
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
assert(!ps->root_tile_paint.pixmap);
ps->root_tile_fill = false;
@ -894,15 +902,20 @@ get_root_tile(session_t *ps) {
.repeat = True,
};
ps->root_tile_paint.pict = x_create_picture_with_visual_and_pixmap(
ps, ps->vis, pixmap, CPRepeat, &pa);
ps, ps->vis, pixmap, XCB_RENDER_CP_REPEAT, &pa);
// Fill pixmap if needed
if (fill) {
XRenderColor c;
xcb_render_color_t col;
xcb_rectangle_t rect;
c.red = c.green = c.blue = 0x8080;
c.alpha = 0xffff;
XRenderFillRectangle(ps->dpy, PictOpSrc, ps->root_tile_paint.pict, &c, 0, 0, 1, 1);
col.red = col.green = col.blue = 0x8080;
col.alpha = 0xffff;
rect.x = rect.y = 0;
rect.width = rect.height = 1;
xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_SRC, ps->root_tile_paint.pict, col, 1, &rect);
}
ps->root_tile_fill = fill;
@ -958,7 +971,7 @@ find_client_win(session_t *ps, Window w) {
/**
* Get alpha <code>Picture</code> for an opacity in <code>double</code>.
*/
static inline Picture
static inline xcb_render_picture_t
get_alpha_pict_d(session_t *ps, double o) {
assert((round(normalize_d(o) / ps->o.alpha_step)) <= round(1.0 / ps->o.alpha_step));
return ps->alpha_picts[(int) (round(normalize_d(o)
@ -969,7 +982,7 @@ get_alpha_pict_d(session_t *ps, double o) {
* Get alpha <code>Picture</code> for an opacity in
* <code>opacity_t</code>.
*/
static inline Picture
static inline xcb_render_picture_t
get_alpha_pict_o(session_t *ps, opacity_t o) {
return get_alpha_pict_d(ps, (double) o / OPAQUE);
}
@ -1234,14 +1247,15 @@ win_paint_shadow(session_t *ps, win *w,
* @return true if successful, false otherwise
*/
static bool
xr_blur_dst(session_t *ps, Picture tgt_buffer,
int x, int y, int wid, int hei, XFixed **blur_kerns,
xr_blur_dst(session_t *ps, xcb_render_picture_t tgt_buffer,
int x, int y, int wid, int hei, xcb_render_fixed_t **blur_kerns,
XserverRegion reg_clip) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
assert(blur_kerns[0]);
// Directly copying from tgt_buffer to it does not work, so we create a
// Picture in the middle.
Picture tmp_picture = x_create_picture(ps, wid, hei, NULL, 0, NULL);
xcb_render_picture_t tmp_picture = x_create_picture(ps, wid, hei, NULL, 0, NULL);
if (!tmp_picture) {
printf_errf("(): Failed to build intermediate Picture.");
@ -1251,20 +1265,20 @@ xr_blur_dst(session_t *ps, Picture tgt_buffer,
if (reg_clip && tmp_picture)
XFixesSetPictureClipRegion(ps->dpy, tmp_picture, reg_clip, 0, 0);
Picture src_pict = tgt_buffer, dst_pict = tmp_picture;
xcb_render_picture_t src_pict = tgt_buffer, dst_pict = tmp_picture;
for (int i = 0; blur_kerns[i]; ++i) {
assert(i < MAX_BLUR_PASS - 1);
XFixed *convolution_blur = blur_kerns[i];
int kwid = XFixedToDouble(convolution_blur[0]),
khei = XFixedToDouble(convolution_blur[1]);
xcb_render_fixed_t *convolution_blur = blur_kerns[i];
int kwid = XFIXED_TO_DOUBLE(convolution_blur[0]),
khei = XFIXED_TO_DOUBLE(convolution_blur[1]);
bool rd_from_tgt = (tgt_buffer == src_pict);
// Copy from source picture to destination. The filter must
// be applied on source picture, to get the nearby pixels outside the
// window.
XRenderSetPictureFilter(ps->dpy, src_pict, XRFILTER_CONVOLUTION,
convolution_blur, kwid * khei + 2);
XRenderComposite(ps->dpy, PictOpSrc, src_pict, None, dst_pict,
xcb_render_set_picture_filter(c, src_pict, strlen(XRFILTER_CONVOLUTION), XRFILTER_CONVOLUTION,
kwid * khei + 2, convolution_blur);
xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, src_pict, None, dst_pict,
(rd_from_tgt ? x: 0), (rd_from_tgt ? y: 0), 0, 0,
(rd_from_tgt ? 0: x), (rd_from_tgt ? 0: y), wid, hei);
xrfilter_reset(ps, src_pict);
@ -1277,7 +1291,7 @@ xr_blur_dst(session_t *ps, Picture tgt_buffer,
}
if (src_pict != tgt_buffer)
XRenderComposite(ps->dpy, PictOpSrc, src_pict, None, tgt_buffer,
xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, src_pict, None, tgt_buffer,
0, 0, 0, 0, x, y, wid, hei);
free_picture(ps, &tmp_picture);
@ -1303,7 +1317,7 @@ xr_take_screenshot(session_t *ps) {
* Blur the background of a window.
*/
static inline void
win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
win_blur_background(session_t *ps, win *w, xcb_render_picture_t tgt_buffer,
XserverRegion reg_paint, const reg_data_t *pcache_reg) {
const int x = w->g.x;
const int y = w->g.y;
@ -1324,8 +1338,8 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
{
// Normalize blur kernels
for (int i = 0; i < MAX_BLUR_PASS; ++i) {
XFixed *kern_src = ps->o.blur_kerns[i];
XFixed *kern_dst = ps->blur_kerns_cache[i];
xcb_render_fixed_t *kern_src = ps->o.blur_kerns[i];
xcb_render_fixed_t *kern_dst = ps->blur_kerns_cache[i];
assert(i < MAX_BLUR_PASS);
if (!kern_src) {
assert(!kern_dst);
@ -1338,12 +1352,12 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
// Skip for fixed factor_center if the cache exists already
if (ps->o.blur_background_fixed && kern_dst) continue;
int kwid = XFixedToDouble(kern_src[0]),
khei = XFixedToDouble(kern_src[1]);
int kwid = XFIXED_TO_DOUBLE(kern_src[0]),
khei = XFIXED_TO_DOUBLE(kern_src[1]);
// Allocate cache space if needed
if (!kern_dst) {
kern_dst = malloc((kwid * khei + 2) * sizeof(XFixed));
kern_dst = malloc((kwid * khei + 2) * sizeof(xcb_render_fixed_t));
if (!kern_dst) {
printf_errf("(): Failed to allocate memory for blur kernel.");
return;
@ -1353,10 +1367,10 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
// Modify the factor of the center pixel
kern_src[2 + (khei / 2) * kwid + kwid / 2] =
XDoubleToFixed(factor_center);
DOUBLE_TO_XFIXED(factor_center);
// Copy over
memcpy(kern_dst, kern_src, (kwid * khei + 2) * sizeof(XFixed));
memcpy(kern_dst, kern_src, (kwid * khei + 2) * sizeof(xcb_render_fixed_t));
normalize_conv_kern(kwid, khei, kern_dst + 2);
}
@ -1389,20 +1403,21 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer,
void
render_(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
double opacity, bool argb, bool neg,
Picture pict, glx_texture_t *ptex,
xcb_render_picture_t pict, glx_texture_t *ptex,
XserverRegion reg_paint, const reg_data_t *pcache_reg
#ifdef CONFIG_OPENGL
, const glx_prog_main_t *pprogram
#endif
) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
switch (ps->o.backend) {
case BKEND_XRENDER:
case BKEND_XR_GLX_HYBRID:
{
Picture alpha_pict = get_alpha_pict_d(ps, opacity);
xcb_render_picture_t alpha_pict = get_alpha_pict_d(ps, opacity);
if (alpha_pict != ps->alpha_picts[0]) {
int op = ((!argb && !alpha_pict) ? PictOpSrc: PictOpOver);
XRenderComposite(ps->dpy, op, pict, alpha_pict,
int op = ((!argb && !alpha_pict) ? XCB_RENDER_PICT_OP_SRC: XCB_RENDER_PICT_OP_OVER);
xcb_render_composite(c, op, pict, alpha_pict,
ps->tgt_buffer.pict, x, y, 0, 0, dx, dy, wid, hei);
}
break;
@ -1425,6 +1440,7 @@ render_(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
static inline void
win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
const reg_data_t *pcache_reg) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
glx_mark(ps, w->id, true);
// Fetch Pixmap
@ -1447,7 +1463,7 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
};
w->paint.pict = x_create_picture_with_pictfmt_and_pixmap(ps, w->pictfmt,
draw, CPSubwindowMode, &pa);
draw, XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
}
}
@ -1474,11 +1490,11 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
const int wid = w->widthb;
const int hei = w->heightb;
Picture pict = w->paint.pict;
xcb_render_picture_t pict = w->paint.pict;
// Invert window color, if required
if (bkend_use_xrender(ps) && w->invert_color) {
Picture newpict = x_create_picture(ps, wid, hei, w->pictfmt, 0, NULL);
xcb_render_picture_t newpict = x_create_picture(ps, wid, hei, w->pictfmt, 0, NULL);
if (newpict) {
// Apply clipping region to save some CPU
if (reg_paint) {
@ -1488,14 +1504,14 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
free_region(ps, &reg);
}
XRenderComposite(ps->dpy, PictOpSrc, pict, None,
xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, pict, None,
newpict, 0, 0, 0, 0, 0, 0, wid, hei);
XRenderComposite(ps->dpy, PictOpDifference, ps->white_picture, None,
xcb_render_composite(c, XCB_RENDER_PICT_OP_DIFFERENCE, ps->white_picture, None,
newpict, 0, 0, 0, 0, 0, 0, wid, hei);
// We use an extra PictOpInReverse operation to get correct pixel
// alpha. There could be a better solution.
if (WMODE_ARGB == w->mode)
XRenderComposite(ps->dpy, PictOpInReverse, pict, None,
xcb_render_composite(c, XCB_RENDER_PICT_OP_IN_REVERSE, pict, None,
newpict, 0, 0, 0, 0, 0, 0, wid, hei);
pict = newpict;
}
@ -1576,19 +1592,19 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint,
unsigned short cval = 0xffff * dim_opacity;
// Premultiply color
XRenderColor color = {
xcb_render_color_t color = {
.red = 0, .green = 0, .blue = 0, .alpha = cval,
};
XRectangle rect = {
xcb_rectangle_t rect = {
.x = x,
.y = y,
.width = wid,
.height = hei,
};
XRenderFillRectangles(ps->dpy, PictOpOver, ps->tgt_buffer.pict,
&color, &rect, 1);
xcb_render_fill_rectangles(c, XCB_RENDER_PICT_OP_OVER, ps->tgt_buffer.pict,
color, 1, &rect);
}
break;
#ifdef CONFIG_OPENGL
@ -1654,6 +1670,7 @@ is_region_empty(const session_t *ps, XserverRegion region,
static void
paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
if (!region_real)
region_real = region;
@ -1709,7 +1726,7 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
#ifdef MONITOR_REPAINT
switch (ps->o.backend) {
case BKEND_XRENDER:
XRenderComposite(ps->dpy, PictOpSrc, ps->black_picture, None,
xcb_render_composite(c, XCB_RENDER_PICT_OP_SRC, ps->black_picture, None,
ps->tgt_picture, 0, 0, 0, 0, 0, 0,
ps->root_width, ps->root_height);
break;
@ -1889,8 +1906,8 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t
}
// No-DBE painting mode
else if (ps->tgt_buffer.pict != ps->tgt_picture) {
XRenderComposite(
ps->dpy, PictOpSrc, ps->tgt_buffer.pict, None,
xcb_render_composite(
c, XCB_RENDER_PICT_OP_SRC, ps->tgt_buffer.pict, None,
ps->tgt_picture, 0, 0, 0, 0,
0, 0, ps->root_width, ps->root_height);
}
@ -2512,11 +2529,11 @@ xerror(Display __attribute__((unused)) *dpy, XErrorEvent *ev) {
o = ev->error_code - ps->render_error;
switch (o) {
CASESTRRET2(BadPictFormat);
CASESTRRET2(BadPicture);
CASESTRRET2(BadPictOp);
CASESTRRET2(BadGlyphSet);
CASESTRRET2(BadGlyph);
CASESTRRET2(XCB_RENDER_PICT_FORMAT);
CASESTRRET2(XCB_RENDER_PICTURE);
CASESTRRET2(XCB_RENDER_PICT_OP);
CASESTRRET2(XCB_RENDER_GLYPH_SET);
CASESTRRET2(XCB_RENDER_GLYPH);
}
#ifdef CONFIG_OPENGL
@ -4234,14 +4251,14 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) {
// Convolution filter parameter (box blur)
// gaussian or binomial filters are definitely superior, yet looks
// like they aren't supported as of xorg-server-1.13.0
static const XFixed convolution_blur[] = {
// Must convert to XFixed with XDoubleToFixed()
static const xcb_render_fixed_t convolution_blur[] = {
// Must convert to XFixed with DOUBLE_TO_XFIXED()
// Matrix size
XDoubleToFixed(3), XDoubleToFixed(3),
DOUBLE_TO_XFIXED(3), DOUBLE_TO_XFIXED(3),
// Matrix
XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1),
XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1),
XDoubleToFixed(1), XDoubleToFixed(1), XDoubleToFixed(1),
DOUBLE_TO_XFIXED(1), DOUBLE_TO_XFIXED(1), DOUBLE_TO_XFIXED(1),
DOUBLE_TO_XFIXED(1), DOUBLE_TO_XFIXED(1), DOUBLE_TO_XFIXED(1),
DOUBLE_TO_XFIXED(1), DOUBLE_TO_XFIXED(1), DOUBLE_TO_XFIXED(1),
};
ps->o.blur_kerns[0] = malloc(sizeof(convolution_blur));
if (!ps->o.blur_kerns[0]) {
@ -4639,7 +4656,7 @@ init_alpha_picts(session_t *ps) {
int i;
int num = round(1.0 / ps->o.alpha_step) + 1;
ps->alpha_picts = malloc(sizeof(Picture) * num);
ps->alpha_picts = malloc(sizeof(xcb_render_picture_t) * num);
for (i = 0; i < num; ++i) {
double o = i * ps->o.alpha_step;
@ -4709,6 +4726,7 @@ init_overlay(session_t *ps) {
*/
static bool
init_filters(session_t *ps) {
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
// Blur filter
if (ps->o.blur_background || ps->o.blur_background_frame) {
switch (ps->o.backend) {
@ -4716,15 +4734,17 @@ init_filters(session_t *ps) {
case BKEND_XR_GLX_HYBRID:
{
// Query filters
XFilters *pf = XRenderQueryFilters(ps->dpy, get_tgt_window(ps));
xcb_render_query_filters_reply_t *pf = xcb_render_query_filters_reply(c,
xcb_render_query_filters(c, get_tgt_window(ps)), NULL);
if (pf) {
for (int i = 0; i < pf->nfilter; ++i) {
xcb_str_iterator_t iter = xcb_render_query_filters_filters_iterator(pf);
for (; iter.rem; xcb_str_next(&iter)) {
// Convolution filter
if (!strcmp(pf->filter[i], XRFILTER_CONVOLUTION))
if (!strcmp(xcb_str_name(iter.data), XRFILTER_CONVOLUTION))
ps->xrfilter_convolution_exists = true;
}
free(pf);
}
cxfree(pf);
// Turn features off if any required filter is not present
if (!ps->xrfilter_convolution_exists) {
@ -5326,14 +5346,17 @@ session_init(session_t *ps_old, int argc, char **argv) {
ps->root_width = DisplayWidth(ps->dpy, ps->scr);
ps->root_height = DisplayHeight(ps->dpy, ps->scr);
xcb_prefetch_extension_data(c, &xcb_render_id);
xcb_prefetch_extension_data(c, &xcb_damage_id);
xcb_prefetch_extension_data(c, &xcb_randr_id);
if (!XRenderQueryExtension(ps->dpy,
&ps->render_event, &ps->render_error)) {
ext_info = xcb_get_extension_data(c, &xcb_render_id);
if (!ext_info || !ext_info->present) {
fprintf(stderr, "No render extension\n");
exit(1);
}
ps->render_event = ext_info->first_event;
ps->render_error = ext_info->first_error;
if (!XQueryExtension(ps->dpy, COMPOSITE_NAME, &ps->composite_opcode,
&ps->composite_event, &ps->composite_error)) {
@ -5525,10 +5548,10 @@ session_init(session_t *ps_old, int argc, char **argv) {
};
ps->root_picture = x_create_picture_with_visual_and_pixmap(ps,
ps->vis, ps->root, CPSubwindowMode, &pa);
ps->vis, ps->root, XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
if (ps->o.paint_on_overlay) {
ps->tgt_picture = x_create_picture_with_visual_and_pixmap(ps,
ps->vis, ps->overlay, CPSubwindowMode, &pa);
ps->vis, ps->overlay, XCB_RENDER_CP_SUBWINDOW_MODE, &pa);
} else
ps->tgt_picture = ps->root_picture;
}

View File

@ -52,7 +52,7 @@ void map_win(session_t *ps, Window id);
void
render_(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
double opacity, bool argb, bool neg,
Picture pict, glx_texture_t *ptex,
xcb_render_picture_t pict, glx_texture_t *ptex,
XserverRegion reg_paint, const reg_data_t *pcache_reg
#ifdef CONFIG_OPENGL
, const glx_prog_main_t *pprogram
@ -63,8 +63,11 @@ render_(session_t *ps, int x, int y, int dx, int dy, int wid, int hei,
* Reset filter on a <code>Picture</code>.
*/
static inline void
xrfilter_reset(session_t *ps, Picture p) {
XRenderSetPictureFilter(ps->dpy, p, "Nearest", NULL, 0);
xrfilter_reset(session_t *ps, xcb_render_picture_t p) {
#define FILTER "Nearest"
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
xcb_render_set_picture_filter(c, p, strlen(FILTER), FILTER, 0, NULL);
#undef FILTER
}
/**
@ -146,9 +149,10 @@ rect_to_reg(session_t *ps, const XRectangle *src) {
* Destroy a <code>Picture</code>.
*/
inline static void
free_picture(session_t *ps, Picture *p) {
free_picture(session_t *ps, xcb_render_picture_t *p) {
if (*p) {
XRenderFreePicture(ps->dpy, *p);
xcb_connection_t *c = XGetXCBConnection(ps->dpy);
xcb_render_free_picture(c, *p);
*p = None;
}
}
@ -494,7 +498,7 @@ find_win_all(session_t *ps, const Window wid) {
static inline void
win_render(session_t *ps, win *w, int x, int y, int wid, int hei,
double opacity, XserverRegion reg_paint, const reg_data_t *pcache_reg,
Picture pict) {
xcb_render_picture_t pict) {
const int dx = (w ? w->g.x: 0) + x;
const int dy = (w ? w->g.y: 0) + y;
const bool argb = (w && (WMODE_ARGB == w->mode || ps->o.force_win_blend));
@ -526,13 +530,13 @@ set_tgt_clip(session_t *ps, XserverRegion reg, const reg_data_t *pcache_reg) {
* Normalize a convolution kernel.
*/
static inline void
normalize_conv_kern(int wid, int hei, XFixed *kern) {
normalize_conv_kern(int wid, int hei, xcb_render_fixed_t *kern) {
double sum = 0.0;
for (int i = 0; i < wid * hei; ++i)
sum += XFixedToDouble(kern[i]);
sum += XFIXED_TO_DOUBLE(kern[i]);
double factor = 1.0 / sum;
for (int i = 0; i < wid * hei; ++i)
kern[i] = XDoubleToFixed(XFixedToDouble(kern[i]) * factor);
kern[i] = DOUBLE_TO_XFIXED(XFIXED_TO_DOUBLE(kern[i]) * factor);
}
/**

View File

@ -49,11 +49,11 @@ parse_matrix_readnum(const char *src, double *dest) {
/**
* Parse a matrix.
*/
XFixed *
xcb_render_fixed_t *
parse_matrix(session_t *ps, const char *src, const char **endptr) {
int wid = 0, hei = 0;
const char *pc = NULL;
XFixed *matrix = NULL;
xcb_render_fixed_t *matrix = NULL;
// Get matrix width and height
{
@ -82,7 +82,7 @@ parse_matrix(session_t *ps, const char *src, const char **endptr) {
"rendering, and/or consume lots of memory");
// Allocate memory
matrix = calloc(wid * hei + 2, sizeof(XFixed));
matrix = calloc(wid * hei + 2, sizeof(xcb_render_fixed_t));
if (!matrix) {
printf_errf("(): Failed to allocate memory for matrix.");
goto parse_matrix_err;
@ -95,7 +95,7 @@ parse_matrix(session_t *ps, const char *src, const char **endptr) {
for (int i = 0; i < wid * hei; ++i) {
// Ignore the center element
if (i == skip) {
matrix[2 + i] = XDoubleToFixed(0);
matrix[2 + i] = DOUBLE_TO_XFIXED(0);
continue;
}
double val = 0;
@ -103,7 +103,7 @@ parse_matrix(session_t *ps, const char *src, const char **endptr) {
goto parse_matrix_err;
src = pc;
if (val < 0) hasneg = true;
matrix[2 + i] = XDoubleToFixed(val);
matrix[2 + i] = DOUBLE_TO_XFIXED(val);
}
if (BKEND_XRENDER == ps->o.backend && hasneg)
printf_errf("(): A convolution kernel with negative values "
@ -134,8 +134,8 @@ parse_matrix(session_t *ps, const char *src, const char **endptr) {
}
// Fill in width and height
matrix[0] = XDoubleToFixed(wid);
matrix[1] = XDoubleToFixed(hei);
matrix[0] = DOUBLE_TO_XFIXED(wid);
matrix[1] = DOUBLE_TO_XFIXED(hei);
return matrix;
@ -147,7 +147,7 @@ parse_matrix_err:
/**
* Parse a convolution kernel.
*/
XFixed *
xcb_render_fixed_t *
parse_conv_kern(session_t *ps, const char *src, const char **endptr) {
return parse_matrix(ps, src, endptr);
}
@ -156,7 +156,7 @@ parse_conv_kern(session_t *ps, const char *src, const char **endptr) {
* Parse a list of convolution kernels.
*/
bool
parse_conv_kern_lst(session_t *ps, const char *src, XFixed **dest, int max) {
parse_conv_kern_lst(session_t *ps, const char *src, xcb_render_fixed_t **dest, int max) {
static const struct {
const char *name;
const char *kern_str;

View File

@ -10,9 +10,9 @@
bool parse_long(const char *, long *);
const char *parse_matrix_readnum(const char *, double *);
XFixed *parse_matrix(session_t *, const char *, const char **);
XFixed *parse_conv_kern(session_t *, const char *, const char **);
bool parse_conv_kern_lst(session_t *, const char *, XFixed **, int);
xcb_render_fixed_t *parse_matrix(session_t *, const char *, const char **);
xcb_render_fixed_t *parse_conv_kern(session_t *, const char *, const char **);
bool parse_conv_kern_lst(session_t *, const char *, xcb_render_fixed_t **, int);
bool parse_geometry(session_t *, const char *, geometry_t *);
bool parse_rule_opacity(session_t *, const char *);

View File

@ -434,7 +434,7 @@ glx_init_blur(session_t *ps) {
}
for (int i = 0; i < MAX_BLUR_PASS && ps->o.blur_kerns[i]; ++i) {
XFixed *kern = ps->o.blur_kerns[i];
xcb_render_fixed_t *kern = ps->o.blur_kerns[i];
if (!kern)
break;
@ -442,7 +442,7 @@ glx_init_blur(session_t *ps) {
// Build shader
{
int wid = XFixedToDouble(kern[0]), hei = XFixedToDouble(kern[1]);
int wid = XFIXED_TO_DOUBLE(kern[0]), hei = XFIXED_TO_DOUBLE(kern[1]);
int nele = wid * hei - 1;
unsigned int len = strlen(FRAG_SHADER_BLUR_PREFIX) +
strlen(sampler_type) +
@ -466,7 +466,7 @@ glx_init_blur(session_t *ps) {
for (int k = 0; k < wid; ++k) {
if (hei / 2 == j && wid / 2 == k)
continue;
double val = XFixedToDouble(kern[2 + j * wid + k]);
double val = XFIXED_TO_DOUBLE(kern[2 + j * wid + k]);
if (0.0 == val)
continue;
sum += val;
@ -1187,8 +1187,8 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z,
for (int i = 0; i < MAX_BLUR_PASS; ++i) {
XFixed *kern = ps->o.blur_kerns[i];
if (!kern) break;
inc_x += XFixedToDouble(kern[0]) / 2;
inc_y += XFixedToDouble(kern[1]) / 2;
inc_x += XFIXED_TO_DOUBLE(kern[0]) / 2;
inc_y += XFIXED_TO_DOUBLE(kern[1]) / 2;
}
inc_x = min_i(ps->o.resize_damage, inc_x);
inc_y = min_i(ps->o.resize_damage, inc_y);

View File

@ -282,7 +282,7 @@ bool wid_get_opacity_prop(session_t *ps, Window wid, opacity_t def,
void win_determine_mode(session_t *ps, win *w) {
winmode_t mode = WMODE_SOLID;
if (w->pictfmt && w->pictfmt->type == PictTypeDirect &&
if (w->pictfmt && w->pictfmt->type == XCB_RENDER_PICT_TYPE_DIRECT &&
w->pictfmt->direct.alpha_mask) {
mode = WMODE_ARGB;
} else if (w->opacity != OPAQUE) {