From e2b8c3fd1e5eb06c137daf03dcb6c11f93aa2cd4 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Tue, 22 Nov 2022 16:12:36 +0000 Subject: [PATCH 01/12] c2: replace pcre with pcre2 Because pcre has been deprecated.[1] There are subtle changes from pcre to pcre2, so this could be a breaking change. Closes #895 [1]: https://www.pcre.org/original/changelog.txt Signed-off-by: Yuxuan Shui --- src/c2.c | 155 ++++++++++++++++++++++++------------------------ src/meson.build | 5 +- 2 files changed, 79 insertions(+), 81 deletions(-) diff --git a/src/c2.c b/src/c2.c index 80ecb24..f8af699 100644 --- a/src/c2.c +++ b/src/c2.c @@ -17,15 +17,8 @@ // libpcre #ifdef CONFIG_REGEX_PCRE -#include - -// For compatibility with #endif @@ -89,49 +82,52 @@ struct _c2_b { /// Structure for leaf element in a window condition struct _c2_l { bool neg : 1; - enum { C2_L_OEXISTS, - C2_L_OEQ, - C2_L_OGT, - C2_L_OGTEQ, - C2_L_OLT, - C2_L_OLTEQ, + enum { + C2_L_OEXISTS, + C2_L_OEQ, + C2_L_OGT, + C2_L_OGTEQ, + C2_L_OLT, + C2_L_OLTEQ, } op : 3; - enum { C2_L_MEXACT, - C2_L_MSTART, - C2_L_MCONTAINS, - C2_L_MWILDCARD, - C2_L_MPCRE, + enum { + C2_L_MEXACT, + C2_L_MSTART, + C2_L_MCONTAINS, + C2_L_MWILDCARD, + C2_L_MPCRE, } match : 3; bool match_ignorecase : 1; char *tgt; xcb_atom_t tgtatom; bool tgt_onframe; int index; - enum { C2_L_PUNDEFINED = -1, - C2_L_PID = 0, - C2_L_PX, - C2_L_PY, - C2_L_PX2, - C2_L_PY2, - C2_L_PWIDTH, - C2_L_PHEIGHT, - C2_L_PWIDTHB, - C2_L_PHEIGHTB, - C2_L_PBDW, - C2_L_PFULLSCREEN, - C2_L_POVREDIR, - C2_L_PARGB, - C2_L_PFOCUSED, - C2_L_PWMWIN, - C2_L_PBSHAPED, - C2_L_PROUNDED, - C2_L_PCLIENT, - C2_L_PWINDOWTYPE, - C2_L_PLEADER, - C2_L_PNAME, - C2_L_PCLASSG, - C2_L_PCLASSI, - C2_L_PROLE, + enum { + C2_L_PUNDEFINED = -1, + C2_L_PID = 0, + C2_L_PX, + C2_L_PY, + C2_L_PX2, + C2_L_PY2, + C2_L_PWIDTH, + C2_L_PHEIGHT, + C2_L_PWIDTHB, + C2_L_PHEIGHTB, + C2_L_PBDW, + C2_L_PFULLSCREEN, + C2_L_POVREDIR, + C2_L_PARGB, + C2_L_PFOCUSED, + C2_L_PWMWIN, + C2_L_PBSHAPED, + C2_L_PROUNDED, + C2_L_PCLIENT, + C2_L_PWINDOWTYPE, + C2_L_PLEADER, + C2_L_PNAME, + C2_L_PCLASSG, + C2_L_PCLASSI, + C2_L_PROLE, } predef; enum c2_l_type { C2_L_TUNDEFINED, @@ -142,15 +138,16 @@ struct _c2_l { C2_L_TDRAWABLE, } type; int format; - enum { C2_L_PTUNDEFINED, - C2_L_PTSTRING, - C2_L_PTINT, + enum { + C2_L_PTUNDEFINED, + C2_L_PTSTRING, + C2_L_PTINT, } ptntype; char *ptnstr; long ptnint; #ifdef CONFIG_REGEX_PCRE - pcre *regex_pcre; - pcre_extra *regex_pcre_extra; + pcre2_code *regex_pcre; + pcre2_match_data *regex_pcre_match; #endif }; @@ -1059,32 +1056,31 @@ static bool c2_l_postprocess(session_t *ps, c2_l_t *pleaf) { // PCRE patterns if (C2_L_PTSTRING == pleaf->ptntype && C2_L_MPCRE == pleaf->match) { #ifdef CONFIG_REGEX_PCRE - const char *error = NULL; - int erroffset = 0; - int options = 0; + int errorcode = 0; + PCRE2_SIZE erroffset = 0; + unsigned int options = 0; // Ignore case flag - if (pleaf->match_ignorecase) - options |= PCRE_CASELESS; + if (pleaf->match_ignorecase) { + options |= PCRE2_CASELESS; + } // Compile PCRE expression pleaf->regex_pcre = - pcre_compile(pleaf->ptnstr, options, &error, &erroffset, NULL); - if (!pleaf->regex_pcre) { - log_error("Pattern \"%s\": PCRE regular expression parsing " + pcre2_compile((PCRE2_SPTR)pleaf->ptnstr, PCRE2_ZERO_TERMINATED, + options, &errorcode, &erroffset, NULL); + if (pleaf->regex_pcre == NULL) { + PCRE2_UCHAR buffer[256]; + pcre2_get_error_message(errorcode, buffer, sizeof(buffer)); + log_error("Pattern \"%s\": PCRE regular expression " + "parsing " "failed on " - "offset %d: %s", - pleaf->ptnstr, erroffset, error); + "offset %zu: %s", + pleaf->ptnstr, erroffset, buffer); return false; } -#ifdef CONFIG_REGEX_PCRE_JIT - pleaf->regex_pcre_extra = - pcre_study(pleaf->regex_pcre, PCRE_STUDY_JIT_COMPILE, &error); - if (!pleaf->regex_pcre_extra) { - printf("Pattern \"%s\": PCRE regular expression study failed: %s", - pleaf->ptnstr, error); - } -#endif + pleaf->regex_pcre_match = + pcre2_match_data_create_from_pattern(pleaf->regex_pcre, NULL); // Free the target string // free(pleaf->tgt); @@ -1102,16 +1098,18 @@ static bool c2_tree_postprocess(session_t *ps, c2_ptr_t node) { if (!node.isbranch) { return c2_l_postprocess(ps, node.l); } - if (!c2_tree_postprocess(ps, node.b->opr1)) + if (!c2_tree_postprocess(ps, node.b->opr1)) { return false; + } return c2_tree_postprocess(ps, node.b->opr2); } bool c2_list_postprocess(session_t *ps, c2_lptr_t *list) { c2_lptr_t *head = list; while (head) { - if (!c2_tree_postprocess(ps, head->ptr)) + if (!c2_tree_postprocess(ps, head->ptr)) { return false; + } head = head->next; } return true; @@ -1124,8 +1122,9 @@ static void c2_free(c2_ptr_t p) { if (p.isbranch) { c2_b_t *const pbranch = p.b; - if (!pbranch) + if (!pbranch) { return; + } c2_free(pbranch->opr1); c2_free(pbranch->opr2); @@ -1135,14 +1134,15 @@ static void c2_free(c2_ptr_t p) { else { c2_l_t *const pleaf = p.l; - if (!pleaf) + if (!pleaf) { return; + } free(pleaf->tgt); free(pleaf->ptnstr); #ifdef CONFIG_REGEX_PCRE - pcre_free(pleaf->regex_pcre); - LPCRE_FREE_STUDY(pleaf->regex_pcre_extra); + pcre2_code_free(pleaf->regex_pcre); + pcre2_match_data_free(pleaf->regex_pcre_match); #endif free(pleaf); } @@ -1550,9 +1550,10 @@ static inline void c2_match_once_leaf(session_t *ps, const struct managed_win *w case C2_L_MPCRE: #ifdef CONFIG_REGEX_PCRE assert(strlen(tgt) <= INT_MAX); - res = (pcre_exec(pleaf->regex_pcre, - pleaf->regex_pcre_extra, tgt, - (int)strlen(tgt), 0, 0, NULL, 0) >= 0); + assert(pleaf->regex_pcre); + res = (pcre2_match(pleaf->regex_pcre, (PCRE2_SPTR)tgt, + strlen(tgt), 0, 0, + pleaf->regex_pcre_match, NULL) > 0); #else assert(0); #endif diff --git a/src/meson.build b/src/meson.build index 60d83a8..09eb07b 100644 --- a/src/meson.build +++ b/src/meson.build @@ -44,11 +44,8 @@ if get_option('config_file') srcs += [ 'config_libconfig.c' ] endif if get_option('regex') - pcre = dependency('libpcre', required: true) + pcre = dependency('libpcre2-8', required: true) cflags += ['-DCONFIG_REGEX_PCRE'] - if pcre.version().version_compare('>=8.20') - cflags += ['-DCONFIG_REGEX_PCRE_JIT'] - endif deps += [pcre] endif From 0a2cd0f14eebc41cc4c7b7c9a3db964a2b1a5ab0 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Wed, 30 Nov 2022 04:16:15 +0000 Subject: [PATCH 02/12] backend: gl: add dither Add bayer ordered dithering when presenting to screen. Reduce banding when using a strong blur. Also use 16-bit intermediary textures to preserve precision in the rendering pipeline. Related: #602 Signed-off-by: Yuxuan Shui --- src/backend/gl/blur.c | 2 +- src/backend/gl/gl_common.c | 6 ++++-- src/backend/gl/gl_common.h | 5 +++-- src/backend/gl/shaders.c | 30 ++++++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/backend/gl/blur.c b/src/backend/gl/blur.c index b73aeee..aad1e5f 100644 --- a/src/backend/gl/blur.c +++ b/src/backend/gl/blur.c @@ -284,7 +284,7 @@ bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, void *mask, } glBindTexture(GL_TEXTURE_2D, bctx->blur_textures[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_size->width, + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, tex_size->width, tex_size->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); if (bctx->method == BLUR_METHOD_DUAL_KAWASE) { diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index a7d2aab..cfa98d1 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -627,7 +627,7 @@ void gl_resize(struct gl_data *gd, int width, int height) { assert(viewport_dimensions[1] >= gd->height); glBindTexture(GL_TEXTURE_2D, gd->back_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, width, height, 0, GL_BGR, + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL); gl_check_err(); @@ -873,7 +873,9 @@ bool gl_init(struct gl_data *gd, session_t *ps) { glUniformMatrix4fv(pml, 1, false, projection_matrix[0]); glUseProgram(0); - gd->present_prog = gl_create_program_from_str(present_vertex_shader, dummy_frag); + gd->present_prog = + gl_create_program_from_strv((const char *[]){present_vertex_shader, NULL}, + (const char *[]){present_frag, dither_glsl, NULL}); if (!gd->present_prog) { log_error("Failed to create the present shader"); return false; diff --git a/src/backend/gl/gl_common.h b/src/backend/gl/gl_common.h index 3a78865..bad75ed 100644 --- a/src/backend/gl/gl_common.h +++ b/src/backend/gl/gl_common.h @@ -288,5 +288,6 @@ static const GLuint vert_in_texcoord_loc = 1; #define QUOTE(...) #__VA_ARGS__ extern const char vertex_shader[], copy_with_mask_frag[], masking_glsl[], dummy_frag[], - fill_frag[], fill_vert[], interpolating_frag[], interpolating_vert[], win_shader_glsl[], - win_shader_default[], present_vertex_shader[], shadow_colorization_frag[]; + present_frag[], fill_frag[], fill_vert[], interpolating_frag[], interpolating_vert[], + win_shader_glsl[], win_shader_default[], present_vertex_shader[], dither_glsl[], + shadow_colorization_frag[]; diff --git a/src/backend/gl/shaders.c b/src/backend/gl/shaders.c index 4a18e62..bd620fe 100644 --- a/src/backend/gl/shaders.c +++ b/src/backend/gl/shaders.c @@ -9,6 +9,15 @@ const char dummy_frag[] = GLSL(330, } ); +const char present_frag[] = GLSL(330, + uniform sampler2D tex; + in vec2 texcoord; + vec4 dither(vec4, vec2); + void main() { + gl_FragColor = dither(texelFetch(tex, ivec2(texcoord.xy), 0), texcoord); + } +); + const char copy_with_mask_frag[] = GLSL(330, uniform sampler2D tex; in vec2 texcoord; @@ -174,6 +183,27 @@ const char vertex_shader[] = GLSL(330, texcoord = in_texcoord + texorig; } ); +const char dither_glsl[] = GLSL(330, + // Stolen from: https://www.shadertoy.com/view/7sfXDn + float bayer2(vec2 a) { + a = floor(a); + return fract(a.x / 2. + a.y * a.y * .75); + } + // 16 * 16 is 2^8, so in total we have equivalent of 16-bit + // color depth, should be enough? + float bayer(vec2 a16) { + vec2 a8 = a16 * .5; + vec2 a4 = a8 * .5; + vec2 a2 = a4 * .5; + float bayer32 = ((bayer2(a2) * .25 + bayer2( a4)) + * .25 + bayer2( a8)) + * .25 + bayer2(a16); + return bayer32; + } + vec4 dither(vec4 c, vec2 coord) { + return vec4(c + bayer(coord) / 255.0); + } +); const char shadow_colorization_frag[] = GLSL(330, uniform vec4 color; uniform sampler2D tex; From 1271839bafbbbea3545cbcf1b936d1ac41135531 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Wed, 30 Nov 2022 05:28:57 +0000 Subject: [PATCH 03/12] options: add dithered-present option See also 0a2cd0f14eebc41cc4c7b7c9a3db964a2b1a5ab0 Related: #602 Signed-off-by: Yuxuan Shui --- man/picom.1.asciidoc | 3 +++ picom.sample.conf | 5 +++++ src/backend/gl/blur.c | 16 ++++++++++------ src/backend/gl/gl_common.c | 22 ++++++++++++++++------ src/backend/gl/gl_common.h | 10 ++++++---- src/backend/xrender/xrender.c | 4 ++++ src/config.h | 2 ++ src/config_libconfig.c | 2 ++ src/options.c | 8 ++++++++ 9 files changed, 56 insertions(+), 16 deletions(-) diff --git a/man/picom.1.asciidoc b/man/picom.1.asciidoc index 61af5a2..5b2182f 100644 --- a/man/picom.1.asciidoc +++ b/man/picom.1.asciidoc @@ -268,6 +268,9 @@ May also be one of the predefined kernels: `3x3box` (default), `5x5box`, `7x7box *--window-shader-fg-rule* 'SHADER':'CONDITION':: Specify GLSL fragment shader path for rendering window contents using patterns. Similar to *--opacity-rule*, arguments should be in the format of 'SHADER:CONDITION', e.g. "shader.frag:name = \'window\'". Leading and trailing whitespaces in 'SHADER' will be trimmed. If 'SHADER' is "default", then the default shader will be used for the matching windows. (This also unfortunately means you can't use a shader file named "default"). Does not work when *--legacy-backends* is enabled. +*--dithered-present* + Use higher precision during rendering, and apply dither when presenting the rendered screen. Reduces banding artifacts, but might cause performance degradation. Only works with OpenGL. + FORMAT OF CONDITIONS -------------------- Some options accept a condition string to match certain windows. A condition string is formed by one or more conditions, joined by logical operators. diff --git a/picom.sample.conf b/picom.sample.conf index 7c74eb8..f0c7a79 100644 --- a/picom.sample.conf +++ b/picom.sample.conf @@ -215,6 +215,11 @@ blur-background-exclude = [ # backend = "glx" backend = "xrender"; +# Use higher precision during rendering, and apply dither when presenting the +# rendered screen. Reduces banding artifacts, but might cause performance +# degradation. Only works with OpenGL. +dithered-present = false; + # Enable/disable VSync. # vsync = false vsync = true; diff --git a/src/backend/gl/blur.c b/src/backend/gl/blur.c index aad1e5f..9297038 100644 --- a/src/backend/gl/blur.c +++ b/src/backend/gl/blur.c @@ -259,10 +259,10 @@ bool gl_dual_kawase_blur(double opacity, struct gl_blur_context *bctx, const rec return true; } -bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, void *mask, - coord_t mask_dst, const region_t *reg_blur, - const region_t *reg_visible attr_unused, GLuint source_texture, - geometry_t source_size, GLuint target_fbo, GLuint default_mask) { +bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, void *mask, coord_t mask_dst, + const region_t *reg_blur, const region_t *reg_visible attr_unused, + GLuint source_texture, geometry_t source_size, GLuint target_fbo, + GLuint default_mask, bool high_precision) { bool ret = false; if (source_size.width != bctx->fb_width || source_size.height != bctx->fb_height) { @@ -284,7 +284,11 @@ bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, void *mask, } glBindTexture(GL_TEXTURE_2D, bctx->blur_textures[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, tex_size->width, + GLint format = GL_RGBA8; + if (high_precision) { + format = GL_RGBA16; + } + glTexImage2D(GL_TEXTURE_2D, 0, format, tex_size->width, tex_size->height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); if (bctx->method == BLUR_METHOD_DUAL_KAWASE) { @@ -406,7 +410,7 @@ bool gl_blur(backend_t *base, double opacity, void *ctx, void *mask, coord_t mas return gl_blur_impl(opacity, bctx, mask, mask_dst, reg_blur, reg_visible, gd->back_texture, (geometry_t){.width = gd->width, .height = gd->height}, - gd->back_fbo, gd->default_mask_texture); + gd->back_fbo, gd->default_mask_texture, gd->dithered_present); } static inline void gl_free_blur_shader(gl_blur_shader_t *shader) { diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index cfa98d1..67b7e64 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -622,13 +622,16 @@ void gl_resize(struct gl_data *gd, int width, int height) { gd->height = height; gd->width = width; + GLint format = GL_RGB8; + if (gd->dithered_present) { + format = GL_RGB16; + } assert(viewport_dimensions[0] >= gd->width); assert(viewport_dimensions[1] >= gd->height); glBindTexture(GL_TEXTURE_2D, gd->back_texture); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16, width, height, 0, GL_BGR, - GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL); gl_check_err(); } @@ -873,9 +876,16 @@ bool gl_init(struct gl_data *gd, session_t *ps) { glUniformMatrix4fv(pml, 1, false, projection_matrix[0]); glUseProgram(0); - gd->present_prog = - gl_create_program_from_strv((const char *[]){present_vertex_shader, NULL}, - (const char *[]){present_frag, dither_glsl, NULL}); + gd->dithered_present = ps->o.dithered_present; + if (gd->dithered_present) { + gd->present_prog = gl_create_program_from_strv( + (const char *[]){present_vertex_shader, NULL}, + (const char *[]){present_frag, dither_glsl, NULL}); + } else { + gd->present_prog = gl_create_program_from_strv( + (const char *[]){present_vertex_shader, NULL}, + (const char *[]){dummy_frag, NULL}); + } if (!gd->present_prog) { log_error("Failed to create the present shader"); return false; @@ -1281,7 +1291,7 @@ void *gl_shadow_from_mask(backend_t *base, void *mask, 1.0, gsctx->blur_context, NULL, (coord_t){0}, ®_blur, NULL, source_texture, (geometry_t){.width = new_inner->width, .height = new_inner->height}, - fbo, gd->default_mask_texture); + fbo, gd->default_mask_texture, gd->dithered_present); pixman_region32_fini(®_blur); } diff --git a/src/backend/gl/gl_common.h b/src/backend/gl/gl_common.h index bad75ed..b7ef2b4 100644 --- a/src/backend/gl/gl_common.h +++ b/src/backend/gl/gl_common.h @@ -109,6 +109,8 @@ struct gl_data { GLuint back_texture, back_fbo; GLuint present_prog; + bool dithered_present; + GLuint default_mask_texture; /// Called when an gl_texture is decoupled from the texture it refers. Returns @@ -163,10 +165,10 @@ void *gl_clone(backend_t *base, const void *image_data, const region_t *reg_visi bool gl_blur(backend_t *base, double opacity, void *ctx, void *mask, coord_t mask_dst, const region_t *reg_blur, const region_t *reg_visible); -bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, void *mask, - coord_t mask_dst, const region_t *reg_blur, - const region_t *reg_visible attr_unused, GLuint source_texture, - geometry_t source_size, GLuint target_fbo, GLuint default_mask); +bool gl_blur_impl(double opacity, struct gl_blur_context *bctx, void *mask, coord_t mask_dst, + const region_t *reg_blur, const region_t *reg_visible attr_unused, + GLuint source_texture, geometry_t source_size, GLuint target_fbo, + GLuint default_mask, bool high_precision); void *gl_create_blur_context(backend_t *base, enum blur_method, void *args); void gl_destroy_blur_context(backend_t *base, void *ctx); struct backend_shadow_context *gl_create_shadow_context(backend_t *base, double radius); diff --git a/src/backend/xrender/xrender.c b/src/backend/xrender/xrender.c index 2b7f8e1..e85a85f 100644 --- a/src/backend/xrender/xrender.c +++ b/src/backend/xrender/xrender.c @@ -858,6 +858,10 @@ static void get_blur_size(void *blur_context, int *width, int *height) { } static backend_t *backend_xrender_init(session_t *ps) { + if (ps->o.dithered_present) { + log_warn("\"dithered-present\" is not supported by the xrender backend."); + } + auto xd = ccalloc(1, struct _xrender_data); init_backend_base(&xd->base, ps); diff --git a/src/config.h b/src/config.h index 7259dc1..3f11e1e 100644 --- a/src/config.h +++ b/src/config.h @@ -256,6 +256,8 @@ typedef struct options { /// A list of conditions of windows to which transparent clipping /// should not apply c2_lptr_t *transparent_clipping_blacklist; + + bool dithered_present; } options_t; extern const char *const BACKEND_STRS[NUM_BKEND + 1]; diff --git a/src/config_libconfig.c b/src/config_libconfig.c index 461fff3..ba987a8 100644 --- a/src/config_libconfig.c +++ b/src/config_libconfig.c @@ -452,6 +452,8 @@ char *parse_config_libconfig(options_t *opt, const char *config_file, bool *shad lcfg_lookup_bool(&cfg, "no-ewmh-fullscreen", &opt->no_ewmh_fullscreen); // --transparent-clipping lcfg_lookup_bool(&cfg, "transparent-clipping", &opt->transparent_clipping); + // --dithered_present + lcfg_lookup_bool(&cfg, "dithered-present", &opt->dithered_present); // --transparent-clipping-exclude parse_cfg_condlst(&cfg, &opt->transparent_clipping_blacklist, "transparent-clipping-exclude"); diff --git a/src/options.c b/src/options.c index 0226714..d6138b9 100644 --- a/src/options.c +++ b/src/options.c @@ -168,6 +168,10 @@ static const struct picom_option picom_options[] = { "similar to --opacity-rule. SHADER_PATH can be \"default\", in which case " "the default shader will be used. Does not work when --legacy-backends is " "enabled. See man page for more details"}, + // 338 is transparent-clipping-exclude + {"dithered-present" , no_argument , 339, NULL , "Use higher precision during rendering, and apply dither when presenting the " + "rendered screen. Reduces banding artifacts, but might cause performance " + "degradation. Only works with OpenGL."}, {"legacy-backends" , no_argument , 733, NULL , "Use deprecated version of the backends."}, {"monitor-repaint" , no_argument , 800, NULL , "Highlight the updated area of the screen. For debugging."}, {"diagnostics" , no_argument , 801, NULL , "Print diagnostic information"}, @@ -716,6 +720,10 @@ bool get_cfg(options_t *opt, int argc, char *const *argv, bool shadow_enable, // --clip-shadow-above condlst_add(&opt->shadow_clip_list, optarg); break; + case 339: + // --dithered-present + opt->dithered_present = true; + break; P_CASEBOOL(733, legacy_backends); P_CASEBOOL(800, monitor_repaint); case 801: From 1a82b8180a596594797f880a836b78e18b95c773 Mon Sep 17 00:00:00 2001 From: Jake Date: Tue, 29 Nov 2022 22:20:22 -0800 Subject: [PATCH 04/12] Change dreaw -> draw --- src/options.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options.c b/src/options.c index 0226714..631f540 100644 --- a/src/options.c +++ b/src/options.c @@ -46,7 +46,7 @@ static const struct picom_option picom_options[] = { {"fade-delta" , required_argument, 'D', NULL , "The time between steps in a fade in milliseconds. (default 10)"}, {"menu-opacity" , required_argument, 'm', NULL , "The opacity for menus. (default 1.0)"}, {"shadow" , no_argument , 'c', NULL , "Enabled client-side shadows on windows."}, - {"clear-shadow" , no_argument , 'z', NULL , "Don't dreaw shadow behind the window."}, + {"clear-shadow" , no_argument , 'z', NULL , "Don't draw shadow behind the window."}, {"fading" , no_argument , 'f', NULL , "Fade windows in/out when opening/closing and when opacity changes, " "unless --no-fading-openclose is used."}, {"inactive-opacity" , required_argument, 'i', NULL , "Opacity of inactive windows. (0.1 - 1.0)"}, From d704e0f80e1df1198cc229b8abbc88eb3caec862 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Wed, 30 Nov 2022 12:13:09 +0000 Subject: [PATCH 05/12] backend: gl: don't add dither where it's not needed If a pixel is perfectly representable as an 8-bit number, don't add dither. Reduce artifacts where dither is unnecessary. Signed-off-by: Yuxuan Shui --- src/backend/gl/shaders.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/backend/gl/shaders.c b/src/backend/gl/shaders.c index bd620fe..90f636b 100644 --- a/src/backend/gl/shaders.c +++ b/src/backend/gl/shaders.c @@ -201,7 +201,9 @@ const char dither_glsl[] = GLSL(330, return bayer32; } vec4 dither(vec4 c, vec2 coord) { - return vec4(c + bayer(coord) / 255.0); + vec4 residual = mod(c, 1.0 / 255.0); + vec4 dithered = vec4(greaterThan(residual, vec4(1e-4))); + return vec4(c + dithered * bayer(coord) / 255.0); } ); const char shadow_colorization_frag[] = GLSL(330, From de3e1a80eb93f11cc0ad27cb46db35fcb6a4a5ac Mon Sep 17 00:00:00 2001 From: Evgeniy Baskov Date: Wed, 30 Nov 2022 20:00:46 +0300 Subject: [PATCH 06/12] win: consider border when creating the mask image With rounded corners, X11 native border and blur enabled, left and bottom 2*border_width pixels were not blurred, since mask did not include border_width, only content width and height. Create mask image with dimensions that include border width. Signed-off-by: Evgeniy Baskov --- src/win.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win.c b/src/win.c index fb61191..502bb82 100644 --- a/src/win.c +++ b/src/win.c @@ -350,7 +350,7 @@ bool win_bind_mask(struct backend_base *b, struct managed_win *w) { auto reg_bound_local = win_get_bounding_shape_global_by_val(w); pixman_region32_translate(®_bound_local, -w->g.x, -w->g.y); w->mask_image = b->ops->make_mask( - b, (geometry_t){.width = w->g.width, .height = w->g.height}, ®_bound_local); + b, (geometry_t){.width = w->widthb, .height = w->heightb}, ®_bound_local); pixman_region32_fini(®_bound_local); if (!w->mask_image) { From 8b4160123ed9b3a4780c682727322d7cc5de0ab4 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Wed, 30 Nov 2022 19:23:47 +0000 Subject: [PATCH 07/12] README: update pcre requirements Signed-off-by: Yuxuan Shui --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ccf0338..49ffedf 100644 --- a/README.md +++ b/README.md @@ -37,20 +37,20 @@ Assuming you already have all the usual building tools installed (e.g. gcc, pyth * libdbus (optional, disable with the `-Ddbus=false` meson configure flag) * libconfig (optional, disable with the `-Dconfig_file=false` meson configure flag) * libGL, libEGL (optional, disable with the `-Dopengl=false` meson configure flag) -* libpcre (optional, disable with the `-Dregex=false` meson configure flag) +* libpcre2 (optional, disable with the `-Dregex=false` meson configure flag) * libev * uthash On Debian based distributions (e.g. Ubuntu), the needed packages are ``` -libxext-dev libxcb1-dev libxcb-damage0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-composite0-dev libxcb-image0-dev libxcb-present-dev libxcb-xinerama0-dev libxcb-glx0-dev libpixman-1-dev libdbus-1-dev libconfig-dev libgl-dev libegl-dev libpcre2-dev libpcre3-dev libevdev-dev uthash-dev libev-dev libx11-xcb-dev meson +libxext-dev libxcb1-dev libxcb-damage0-dev libxcb-xfixes0-dev libxcb-shape0-dev libxcb-render-util0-dev libxcb-render0-dev libxcb-randr0-dev libxcb-composite0-dev libxcb-image0-dev libxcb-present-dev libxcb-xinerama0-dev libxcb-glx0-dev libpixman-1-dev libdbus-1-dev libconfig-dev libgl-dev libegl-dev libpcre2-dev libevdev-dev uthash-dev libev-dev libx11-xcb-dev meson ``` On Fedora, the needed packages are ``` -dbus-devel gcc git libconfig-devel libdrm-devel libev-devel libX11-devel libX11-xcb libXext-devel libxcb-devel libGL-devel libEGL-devel meson pcre-devel pixman-devel uthash-devel xcb-util-image-devel xcb-util-renderutil-devel xorg-x11-proto-devel +dbus-devel gcc git libconfig-devel libdrm-devel libev-devel libX11-devel libX11-xcb libXext-devel libxcb-devel libGL-devel libEGL-devel meson pcre2-devel pixman-devel uthash-devel xcb-util-image-devel xcb-util-renderutil-devel xorg-x11-proto-devel ``` To build the documents, you need `asciidoc` From 756757ee76269962dbbcddf5fcb746929571697c Mon Sep 17 00:00:00 2001 From: Maxim Solovyov Date: Thu, 1 Dec 2022 20:55:57 +0300 Subject: [PATCH 08/12] README: fix meson's warnings about setup commands this fixes `WARNING: Running the setup command as `meson [options]` instead of `meson setup [options]` is ambiguous and deprecated.` warning while setting up the project --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 49ffedf..b1711eb 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ To build the documents, you need `asciidoc` ```bash $ git submodule update --init --recursive -$ meson --buildtype=release . build +$ meson setup --buildtype=release . build $ ninja -C build ``` @@ -70,13 +70,12 @@ If you have libraries and/or headers installed at non-default location (e.g. und You can do that by setting the `CPPFLAGS` and `LDFLAGS` environment variables when running `meson`. Like this: ```bash -$ LDFLAGS="-L/path/to/libraries" CPPFLAGS="-I/path/to/headers" meson --buildtype=release . build - +$ LDFLAGS="-L/path/to/libraries" CPPFLAGS="-I/path/to/headers" meson setup --buildtype=release . build ``` As an example, on FreeBSD, you might have to run meson with: ```bash -$ LDFLAGS="-L/usr/local/lib" CPPFLAGS="-I/usr/local/include" meson --buildtype=release . build +$ LDFLAGS="-L/usr/local/lib" CPPFLAGS="-I/usr/local/include" meson setup --buildtype=release . build $ ninja -C build ``` From d38b0ead7d516d7db0782261ea8c46e7477f1331 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Thu, 1 Dec 2022 18:54:22 +0000 Subject: [PATCH 09/12] backend: gl: try different back buffer formats Prefer RGB formats first, because they use less memory; but fallback to RGBA formats, as they are formats required by OpenGL. Signed-off-by: Yuxuan Shui --- src/backend/gl/gl_common.c | 30 +++++++++++++++++++----------- src/backend/gl/gl_common.h | 1 + 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index 67b7e64..44522b0 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -622,16 +622,13 @@ void gl_resize(struct gl_data *gd, int width, int height) { gd->height = height; gd->width = width; - GLint format = GL_RGB8; - if (gd->dithered_present) { - format = GL_RGB16; - } assert(viewport_dimensions[0] >= gd->width); assert(viewport_dimensions[1] >= gd->height); glBindTexture(GL_TEXTURE_2D, gd->back_texture); - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, gd->back_format, width, height, 0, GL_BGR, + GL_UNSIGNED_BYTE, NULL); gl_check_err(); } @@ -919,14 +916,25 @@ bool gl_init(struct gl_data *gd, session_t *ps) { glUniformMatrix4fv(pml, 1, false, projection_matrix[0]); glUseProgram(0); - // Set up the size of the back texture - gl_resize(gd, ps->root_width, ps->root_height); - + // Set up the size and format of the back texture glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gd->back_fbo); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - gd->back_texture, 0); glDrawBuffer(GL_COLOR_ATTACHMENT0); - if (!gl_check_fb_complete(GL_FRAMEBUFFER)) { + const GLint *format = (const GLint[]){GL_RGB8, GL_RGBA8}; + if (gd->dithered_present) { + format = (const GLint[]){GL_RGB16, GL_RGBA16}; + } + for (int i = 0; i < 2; i++) { + gd->back_format = format[i]; + gl_resize(gd, ps->root_width, ps->root_height); + + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, gd->back_texture, 0); + if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE) { + log_info("Using back buffer format %#x", gd->back_format); + break; + } + } + if (!gl_check_fb_complete(GL_DRAW_FRAMEBUFFER)) { return false; } glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); diff --git a/src/backend/gl/gl_common.h b/src/backend/gl/gl_common.h index b7ef2b4..4aad9c0 100644 --- a/src/backend/gl/gl_common.h +++ b/src/backend/gl/gl_common.h @@ -107,6 +107,7 @@ struct gl_data { gl_fill_shader_t fill_shader; gl_shadow_shader_t shadow_shader; GLuint back_texture, back_fbo; + GLint back_format; GLuint present_prog; bool dithered_present; From 8143c07de62371e3e1580addf8214b7d8cf61972 Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Thu, 1 Dec 2022 21:21:19 +0000 Subject: [PATCH 10/12] Update README.md Signed-off-by: Yuxuan Shui --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b1711eb..f6bdfe1 100644 --- a/README.md +++ b/README.md @@ -89,15 +89,21 @@ Default install prefix is `/usr/local`, you can change it with `meson configure ## How to Contribute -### Code +All contributions are welcome! -You can look at the [Projects](https://github.com/yshui/picom/projects) page, and see if there is anything that interests you. Or you can take a look at the [Issues](https://github.com/yshui/picom/issues). +New features you think should be included in picom, a fix for a bug you found - please open a PR! -### Non-code +You can take a look at the [Issues](https://github.com/yshui/picom/issues). -Even if you don't want to contribute code, you can still contribute by compiling and running this branch, and report any issue you can find. +Contributions to the documents and wiki are also appreciated. -Contributions to the documents and wiki will also be appreciated. +Even if you don't want to add anything to picom, you are still helping by compiling and running this branch, and report any issue you can find. + +### Become a Collaborator + +Becoming a collaborator of picom requires significant time commitment. You are expected to reply to issue reports, reviewing PRs, and sometimes fix bugs or implement new feature. You won't be able to push to the main branch directly, and all you code still has to go through code review. + +If this sounds good to you, feel free to contact me. ## Contributors From 236c8228b8459e40067822006797d6b5c45dc9ba Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Fri, 2 Dec 2022 02:57:28 +0000 Subject: [PATCH 11/12] backend: gl: fix use-after-scope 'format' was pointing to an array with a shorter lifetime suggested by @tryone144 Co-authored-by: Bernd Busse --- src/backend/gl/gl_common.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/backend/gl/gl_common.c b/src/backend/gl/gl_common.c index 44522b0..9789eb5 100644 --- a/src/backend/gl/gl_common.c +++ b/src/backend/gl/gl_common.c @@ -919,10 +919,8 @@ bool gl_init(struct gl_data *gd, session_t *ps) { // Set up the size and format of the back texture glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gd->back_fbo); glDrawBuffer(GL_COLOR_ATTACHMENT0); - const GLint *format = (const GLint[]){GL_RGB8, GL_RGBA8}; - if (gd->dithered_present) { - format = (const GLint[]){GL_RGB16, GL_RGBA16}; - } + const GLint *format = gd->dithered_present ? (const GLint[]){GL_RGB16, GL_RGBA16} + : (const GLint[]){GL_RGB8, GL_RGBA8}; for (int i = 0; i < 2; i++) { gd->back_format = format[i]; gl_resize(gd, ps->root_width, ps->root_height); From 0d2b14d0c3435c72ce8b3f75c627a0fa937809fa Mon Sep 17 00:00:00 2001 From: Yuxuan Shui Date: Fri, 2 Dec 2022 17:51:30 +0000 Subject: [PATCH 12/12] man: fix typo Signed-off-by: Yuxuan Shui --- man/picom.1.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/picom.1.asciidoc b/man/picom.1.asciidoc index 61af5a2..e8c4cec 100644 --- a/man/picom.1.asciidoc +++ b/man/picom.1.asciidoc @@ -481,7 +481,7 @@ Available options of the 'blur' section are: :: An integer in the range 0-20. The strength of the 'dual_kawase' blur method. Corresponds to the *--blur-strength* command line option. If set to zero, the value requested by *--blur-size* is approximated (default: 5). *kernel*::: - A string. The kernel to use for the 'kernel' blur method, specified in the same format as the *--blur-kerns* option. Corresponds to the *--blur-kerns* command line option. + A string. The kernel to use for the 'kernel' blur method, specified in the same format as the *--blur-kern* option. Corresponds to the *--blur-kern* command line option. SIGNALS -------