From 1c66237f9984760238abab1a584867efa7e8d2e6 Mon Sep 17 00:00:00 2001 From: Richard Grenville Date: Wed, 8 May 2013 22:44:36 +0800 Subject: [PATCH 1/4] Imp: Fix GL_TEXTURE_RECTANGLE & Enhance --glx-copy-from-front - Fix GL_TEXTURE_RECTANGLE support. Thanks to amonakov for guides. (#107) - Enhance --glx-copy-from-front to improve performance and make it work with --glx-swap-method, copied from kwin patch. Thanks to bwat47 for info. (#107) - Add texture2Doffset() support in blur GLSL shader. Thanks to amonakov for advice. No visible benefit here, though. (#107) - Only limited tests are done and I'm super sleepy. Bugs expected --- src/common.h | 16 +++- src/compton.c | 12 ++- src/opengl.c | 202 ++++++++++++++++++++++++++++++++++---------------- 3 files changed, 160 insertions(+), 70 deletions(-) diff --git a/src/common.h b/src/common.h index 9a693c6..6d7cea1 100644 --- a/src/common.h +++ b/src/common.h @@ -392,6 +392,8 @@ typedef struct { bool glx_no_rebind_pixmap; /// GLX swap method we assume OpenGL uses. int glx_swap_method; + /// Whether to use GL_EXT_gpu_shader4 to (hopefully) accelerates blurring. + bool glx_use_gpushader4; /// Whether to try to detect WM windows and mark them as focused. bool mark_wmwin_focused; /// Whether to mark override-redirect windows as focused. @@ -1234,7 +1236,7 @@ mstrncpy(const char *src, unsigned len) { /** * Allocate the space and join two strings. */ -static inline char * __attribute__((const)) +static inline char * mstrjoin(const char *src1, const char *src2) { char *str = malloc(sizeof(char) * (strlen(src1) + strlen(src2) + 1)); @@ -1247,7 +1249,7 @@ mstrjoin(const char *src1, const char *src2) { /** * Allocate the space and join two strings; */ -static inline char * __attribute__((const)) +static inline char * mstrjoin3(const char *src1, const char *src2, const char *src3) { char *str = malloc(sizeof(char) * (strlen(src1) + strlen(src2) + strlen(src3) + 1)); @@ -1259,6 +1261,16 @@ mstrjoin3(const char *src1, const char *src2, const char *src3) { return str; } +/** + * Concatenate a string on heap with another string. + */ +static inline void +mstrextend(char **psrc1, const char *src2) { + *psrc1 = realloc(*psrc1, (*psrc1 ? strlen(*psrc1): 0) + strlen(src2) + 1); + + strcat(*psrc1, src2); +} + /** * Normalize an int value to a specific range. * diff --git a/src/compton.c b/src/compton.c index 1111c19..0fb040b 100644 --- a/src/compton.c +++ b/src/compton.c @@ -4238,9 +4238,10 @@ usage(void) { " boost.\n" "--glx-copy-from-front\n" " GLX backend: Copy unmodified regions from front buffer instead of\n" - " redrawing them all. My tests with nvidia-drivers show a 10% decrease\n" - " in performance when the whole screen is modified, but a 20% increase\n" - " when only 1/4 is. My tests on nouveau show terrible slowdown.\n" + " redrawing them all. My tests with nvidia-drivers show a 5% decrease\n" + " in performance when the whole screen is modified, but a 30% increase\n" + " when only 1/4 is. My tests on nouveau show terrible slowdown. Could\n" + " work with --glx-swap-method but not --glx-use-copysubbuffermesa.\n" "--glx-use-copysubbuffermesa\n" " GLX backend: Use MESA_copy_sub_buffer to do partial screen update.\n" " My tests on nouveau shows a 200% performance boost when only 1/4 of\n" @@ -4258,6 +4259,9 @@ usage(void) { " but safer (6 is still faster than 0). -1 means auto-detect using\n" " GLX_EXT_buffer_age, supported by some drivers. Useless with\n" " --glx-use-copysubbuffermesa.\n" + "--glx-use-gpushader4\n" + " GLX backend: Use GL_EXT_gpu_shader4 for some optimization on blur\n" + " GLSL code. My tests on GTX 670 show no noticeable effect.\n" #undef WARNING #ifndef CONFIG_DBUS #define WARNING WARNING_DISABLED @@ -4879,6 +4883,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { { "fade-exclude", required_argument, NULL, 300 }, { "blur-kern", required_argument, NULL, 301 }, { "resize-damage", required_argument, NULL, 302 }, + { "glx-use-gpushader4", no_argument, NULL, 303 }, // Must terminate with a NULL entry { NULL, 0, NULL, 0 }, }; @@ -5111,6 +5116,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { // --resize-damage ps->o.resize_damage = atoi(optarg); break; + P_CASEBOOL(303, glx_use_gpushader4); default: usage(); break; diff --git a/src/opengl.c b/src/opengl.c index 71017f7..d7b4116 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -197,23 +197,41 @@ glx_init_blur(session_t *ps) { { static const char *FRAG_SHADER_BLUR_PREFIX = "#version 110\n" + "%s" "uniform float offset_x;\n" "uniform float offset_y;\n" "uniform float factor_center;\n" - "uniform sampler2D tex_scr;\n" + "uniform %s tex_scr;\n" "\n" "void main() {\n" " vec4 sum = vec4(0.0, 0.0, 0.0, 0.0);\n"; static const char *FRAG_SHADER_BLUR_ADD = - " sum += float(%.7g) * texture2D(tex_scr, vec2(gl_TexCoord[0].x + offset_x * float(%d), gl_TexCoord[0].y + offset_y * float(%d)));\n"; + " sum += float(%.7g) * %s(tex_scr, vec2(gl_TexCoord[0].x + offset_x * float(%d), gl_TexCoord[0].y + offset_y * float(%d)));\n"; + static const char *FRAG_SHADER_BLUR_ADD_GPUSHADER4 = + " sum += float(%.7g) * %sOffset(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y), ivec2(%d, %d));\n"; static const char *FRAG_SHADER_BLUR_SUFFIX = - " sum += texture2D(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y)) * factor_center;\n" + " sum += %s(tex_scr, vec2(gl_TexCoord[0].x, gl_TexCoord[0].y)) * factor_center;\n" " gl_FragColor = sum / (factor_center + float(%.7g));\n" "}\n"; - int wid = XFixedToDouble(ps->o.blur_kern[0]), hei = XFixedToDouble(ps->o.blur_kern[1]); + + const bool use_texture_rect = !ps->glx_has_texture_non_power_of_two; + const char *sampler_type = (use_texture_rect ? + "sampler2DRect": "sampler2D"); + const char *texture_func = (use_texture_rect ? + "texture2DRect": "texture2D"); + const char *shader_add = FRAG_SHADER_BLUR_ADD; + char *extension = mstrcpy(""); + if (use_texture_rect) + mstrextend(&extension, "#extension GL_ARB_texture_rectangle : require\n"); + if (ps->o.glx_use_gpushader4) { + mstrextend(&extension, "#extension GL_EXT_gpu_shader4 : require\n"); + shader_add = FRAG_SHADER_BLUR_ADD_GPUSHADER4; + } + + int wid = XFixedToDouble(ps->o.blur_kern[0]), + hei = XFixedToDouble(ps->o.blur_kern[1]); int nele = wid * hei - 1; - int len = strlen(FRAG_SHADER_BLUR_PREFIX) + (strlen(FRAG_SHADER_BLUR_ADD) + 42) * nele - + strlen(FRAG_SHADER_BLUR_SUFFIX) + 12 + 1; + int len = strlen(FRAG_SHADER_BLUR_PREFIX) + strlen(sampler_type) + strlen(extension) + (strlen(shader_add) + strlen(texture_func) + 42) * nele + strlen(FRAG_SHADER_BLUR_SUFFIX) + strlen(texture_func) + 12 + 1; char *shader_str = calloc(len, sizeof(char)); if (!shader_str) { printf_errf("(): Failed to allocate %d bytes for shader string.", len); @@ -221,8 +239,8 @@ glx_init_blur(session_t *ps) { } { char *pc = shader_str; - strcpy(pc, FRAG_SHADER_BLUR_PREFIX); - pc += strlen(FRAG_SHADER_BLUR_PREFIX); + sprintf(pc, FRAG_SHADER_BLUR_PREFIX, extension, sampler_type); + pc += strlen(pc); assert(strlen(shader_str) < len); double sum = 0.0; @@ -232,13 +250,13 @@ glx_init_blur(session_t *ps) { continue; double val = XFixedToDouble(ps->o.blur_kern[2 + i * wid + j]); sum += val; - sprintf(pc, FRAG_SHADER_BLUR_ADD, val, j - wid / 2, i - hei / 2); + sprintf(pc, shader_add, val, texture_func, j - wid / 2, i - hei / 2); pc += strlen(pc); assert(strlen(shader_str) < len); } } - sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, sum); + sprintf(pc, FRAG_SHADER_BLUR_SUFFIX, texture_func, sum); assert(strlen(shader_str) < len); #ifdef DEBUG_GLX_GLSL fputs(shader_str, stdout); @@ -246,6 +264,7 @@ glx_init_blur(session_t *ps) { #endif } ps->glx_frag_shader_blur = glx_create_shader(GL_FRAGMENT_SHADER, shader_str); + free(extension); free(shader_str); } @@ -268,8 +287,10 @@ glx_init_blur(session_t *ps) { } P_GET_UNIFM_LOC("factor_center", glx_prog_blur_unifm_factor_center); - P_GET_UNIFM_LOC("offset_x", glx_prog_blur_unifm_offset_x); - P_GET_UNIFM_LOC("offset_y", glx_prog_blur_unifm_offset_y); + if (!ps->o.glx_use_gpushader4) { + P_GET_UNIFM_LOC("offset_x", glx_prog_blur_unifm_offset_x); + P_GET_UNIFM_LOC("offset_y", glx_prog_blur_unifm_offset_y); + } #undef P_GET_UNIFM_LOC @@ -593,24 +614,8 @@ glx_paint_pre(session_t *ps, XserverRegion *preg) { // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Get buffer age - int buffer_age = ps->o.glx_swap_method; bool trace_damage = (ps->o.glx_swap_method < 0 || ps->o.glx_swap_method > 1); - // Query GLX_EXT_buffer_age for buffer age - if (SWAPM_BUFFER_AGE == buffer_age) { - unsigned val = 0; - glXQueryDrawable(ps->dpy, get_tgt_window(ps), - GLX_BACK_BUFFER_AGE_EXT, &val); - buffer_age = val; - } - - // Buffer age too high - if (buffer_age > CGLX_MAX_BUFFER_AGE + 1) - buffer_age = 0; - - // Make sure buffer age >= 0 - buffer_age = max_i(buffer_age, 0); - // Trace raw damage regions XserverRegion newdamage = None; if (trace_damage && *preg) @@ -619,37 +624,89 @@ glx_paint_pre(session_t *ps, XserverRegion *preg) { // OpenGL doesn't support partial repaint without GLX_MESA_copy_sub_buffer, // we could redraw the whole screen or copy unmodified pixels from // front buffer with --glx-copy-from-front. - if (ps->o.glx_use_copysubbuffermesa || 1 == buffer_age || !*preg) { - } - else if (buffer_age > 1) { - for (int i = 0; i < buffer_age - 1; ++i) { - XserverRegion dmg = ps->all_damage_last[i]; - if (!dmg) { - free_region(ps, preg); - break; - } - XFixesUnionRegion(ps->dpy, *preg, *preg, dmg); - } - } - else if (!ps->o.glx_copy_from_front) { - free_region(ps, preg); + if (ps->o.glx_use_copysubbuffermesa || !*preg) { } else { + int buffer_age = ps->o.glx_swap_method; + + // Getting buffer age { - XserverRegion reg_copy = XFixesCreateRegion(ps->dpy, NULL, 0); - XFixesSubtractRegion(ps->dpy, reg_copy, ps->screen_reg, *preg); - glx_set_clip(ps, reg_copy, NULL); - free_region(ps, ®_copy); + // Query GLX_EXT_buffer_age for buffer age + if (SWAPM_BUFFER_AGE == buffer_age) { + unsigned val = 0; + glXQueryDrawable(ps->dpy, get_tgt_window(ps), + GLX_BACK_BUFFER_AGE_EXT, &val); + buffer_age = val; + } + + // Buffer age too high + if (buffer_age > CGLX_MAX_BUFFER_AGE + 1) + buffer_age = 0; + + // Make sure buffer age >= 0 + buffer_age = max_i(buffer_age, 0); + + // Check if we have we have empty regions + if (buffer_age > 1) { + for (int i = 0; i < buffer_age - 1; ++i) + if (!ps->all_damage_last[i]) { buffer_age = 0; break; } + } } - { - GLfloat raster_pos[4]; - glGetFloatv(GL_CURRENT_RASTER_POSITION, raster_pos); - glReadBuffer(GL_FRONT); - glRasterPos2f(0.0, 0.0); - glCopyPixels(0, 0, ps->root_width, ps->root_height, GL_COLOR); - glReadBuffer(GL_BACK); - glRasterPos4fv(raster_pos); + // Do nothing for buffer_age 1 (copy) + if (1 != buffer_age) { + // Copy pixels + if (ps->o.glx_copy_from_front) { + // Determine copy area + XserverRegion reg_copy = XFixesCreateRegion(ps->dpy, NULL, 0); + if (!buffer_age) { + XFixesSubtractRegion(ps->dpy, reg_copy, ps->screen_reg, *preg); + } + else { + for (int i = 0; i < buffer_age - 1; ++i) + XFixesUnionRegion(ps->dpy, reg_copy, reg_copy, + ps->all_damage_last[i]); + XFixesSubtractRegion(ps->dpy, reg_copy, reg_copy, *preg); + } + + // Actually copy pixels + { + GLfloat raster_pos[4]; + GLfloat curx = 0.0f, cury = 0.0f; + glGetFloatv(GL_CURRENT_RASTER_POSITION, raster_pos); + glReadBuffer(GL_FRONT); + glRasterPos2f(0.0, 0.0); + { + int nrects = 0; + XRectangle *rects = XFixesFetchRegion(ps->dpy, reg_copy, &nrects); + for (int i = 0; i < nrects; ++i) { + const int x = rects[i].x; + const int y = ps->root_height - rects[i].y - rects[i].height; + // Kwin patch says glRasterPos2f() causes artifacts on bottom + // screen edge with some drivers + glBitmap(0, 0, 0, 0, x - curx, y - cury, NULL); + curx = x; + cury = y; + glCopyPixels(x, y, rects[i].width, rects[i].height, GL_COLOR); + } + cxfree(rects); + } + glReadBuffer(GL_BACK); + glRasterPos4fv(raster_pos); + } + + free_region(ps, ®_copy); + } + + // Determine paint area + if (ps->o.glx_copy_from_front) { } + else if (buffer_age) { + for (int i = 0; i < buffer_age - 1; ++i) + XFixesUnionRegion(ps->dpy, *preg, *preg, ps->all_damage_last[i]); + } + else { + free_region(ps, preg); + } } } @@ -819,13 +876,20 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z, glTexParameteri(tex_tgt, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(tex_tgt, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(tex_tgt, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(tex_tgt, 0, GL_RGB, mwidth, mheight, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(tex_tgt, 0, GL_RGB, mwidth, mheight, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL); glCopyTexSubImage2D(tex_tgt, 0, 0, 0, mdx, ps->root_height - mdy - mheight, mwidth, mheight); #ifdef DEBUG_GLX printf_dbgf("(): %d, %d, %d, %d\n", mdx, ps->root_height - mdy - mheight, mwidth, mheight); #endif + // Texture scaling factor + GLfloat texfac_x = 1.0f, texfac_y = 1.0f; + if (GL_TEXTURE_2D == tex_tgt) { + texfac_x /= mwidth; + texfac_y /= mheight; + } + // Paint it back // Color negation for testing... // glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); @@ -836,9 +900,9 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z, #ifdef CONFIG_VSYNC_OPENGL_GLSL glUseProgram(ps->glx_prog_blur); if (ps->glx_prog_blur_unifm_offset_x >= 0) - glUniform1f(ps->glx_prog_blur_unifm_offset_x, 1.0f / mwidth); + glUniform1f(ps->glx_prog_blur_unifm_offset_x, texfac_x); if (ps->glx_prog_blur_unifm_offset_y >= 0) - glUniform1f(ps->glx_prog_blur_unifm_offset_y, 1.0f / mheight); + glUniform1f(ps->glx_prog_blur_unifm_offset_y, texfac_y); if (ps->glx_prog_blur_unifm_factor_center >= 0) glUniform1f(ps->glx_prog_blur_unifm_factor_center, factor_center); #endif @@ -846,10 +910,10 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z, { P_PAINTREG_START(); { - const GLfloat rx = (double) (crect.x - mdx) / mwidth; - const GLfloat ry = 1.0 - (double) (crect.y - mdy) / mheight; - const GLfloat rxe = rx + (double) crect.width / mwidth; - const GLfloat rye = ry - (double) crect.height / mheight; + const GLfloat rx = (crect.x - mdx) * texfac_x; + const GLfloat ry = (mheight - (crect.y - mdy)) * texfac_y; + const GLfloat rxe = rx + crect.width * texfac_x; + const GLfloat rye = ry - crect.height * texfac_y; const GLfloat rdx = crect.x; const GLfloat rdy = ps->root_height - crect.y; const GLfloat rdxe = rdx + crect.width; @@ -1049,10 +1113,18 @@ glx_render(session_t *ps, const glx_texture_t *ptex, { P_PAINTREG_START(); { - GLfloat rx = (double) (crect.x - dx + x) / ptex->width; - GLfloat ry = (double) (crect.y - dy + y) / ptex->height; - GLfloat rxe = rx + (double) crect.width / ptex->width; - GLfloat rye = ry + (double) crect.height / ptex->height; + GLfloat rx = (double) (crect.x - dx + x); + GLfloat ry = (double) (crect.y - dy + y); + GLfloat rxe = rx + (double) crect.width; + GLfloat rye = ry + (double) crect.height; + // Rectangle textures have [0-w] [0-h] while 2D texture has [0-1] [0-1] + // Thanks to amonakov for pointing out! + if (GL_TEXTURE_2D == ptex->target) { + rx = rx / ptex->width; + ry = ry / ptex->height; + rxe = rxe / ptex->width; + rye = rye / ptex->height; + } GLint rdx = crect.x; GLint rdy = ps->root_height - crect.y; GLint rdxe = rdx + crect.width; From 48fb54dfae765124f938484db4416544d4ebc3a1 Mon Sep 17 00:00:00 2001 From: Richard Grenville Date: Thu, 9 May 2013 09:43:40 +0800 Subject: [PATCH 2/4] Misc: Add DEBUG_GLX_PAINTREG - GLX: Add DEBUG_GLX_PAINTREG, for debugging painting region issues, for p4ddy's problem. --- src/opengl.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/opengl.h | 8 +++++ 2 files changed, 95 insertions(+) diff --git a/src/opengl.c b/src/opengl.c index d7b4116..a4cb858 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -719,6 +719,10 @@ glx_paint_pre(session_t *ps, XserverRegion *preg) { glx_set_clip(ps, *preg, NULL); +#ifdef DEBUG_GLX_PAINTREG + glx_render_color(ps, 0, 0, ps->root_width, ps->root_height, 0, *preg, NULL); +#endif + #ifdef DEBUG_GLX_ERR glx_check_err(ps); #endif @@ -1003,6 +1007,11 @@ glx_render(session_t *ps, const glx_texture_t *ptex, return false; } +#ifdef DEBUG_GLX_PAINTREG + glx_render_dots(ps, dx, dy, width, height, z, reg_tgt, pcache_reg); + return true; +#endif + const bool argb = (GLX_TEXTURE_FORMAT_RGBA_EXT == ps->glx_fbconfigs[ptex->depth]->texture_fmt); bool dual_texture = false; @@ -1185,6 +1194,84 @@ glx_render(session_t *ps, const glx_texture_t *ptex, return true; } +/** + * Render a region with color. + */ +static void +glx_render_color(session_t *ps, int dx, int dy, int width, int height, int z, + XserverRegion reg_tgt, const reg_data_t *pcache_reg) { + static int color = 0; + + color = color % (3 * 3 * 3 - 1) + 1; + glColor4f(1.0 / 3.0 * (color / (3 * 3)), + 1.0 / 3.0 * (color % (3 * 3) / 3), + 1.0 / 3.0 * (color % 3), + 1.0f + ); + z -= 0.2; + + { + P_PAINTREG_START(); + { + GLint rdx = crect.x; + GLint rdy = ps->root_height - crect.y; + GLint rdxe = rdx + crect.width; + GLint rdye = rdy - crect.height; + + glVertex3i(rdx, rdy, z); + glVertex3i(rdxe, rdy, z); + glVertex3i(rdxe, rdye, z); + glVertex3i(rdx, rdye, z); + } + P_PAINTREG_END(); + } + glColor4f(0.0f, 0.0f, 0.0f, 0.0f); + +#ifdef DEBUG_GLX_ERR + glx_check_err(ps); +#endif +} + +/** + * Render a region with dots. + */ +static void +glx_render_dots(session_t *ps, int dx, int dy, int width, int height, int z, + XserverRegion reg_tgt, const reg_data_t *pcache_reg) { + glColor4f(0.0f, 0.0f, 0.0f, 1.0f); + z -= 0.1; + + { + P_PAINTREG_START(); + { + static const GLint BLK_WID = 5, BLK_HEI = 5; + + glEnd(); + glPointSize(1.0); + glBegin(GL_POINTS); + + GLint rdx = crect.x; + GLint rdy = ps->root_height - crect.y; + GLint rdxe = rdx + crect.width; + GLint rdye = rdy - crect.height; + rdx = (rdx) / BLK_WID * BLK_WID; + rdy = (rdy) / BLK_HEI * BLK_HEI; + rdxe = (rdxe) / BLK_WID * BLK_WID; + rdye = (rdye) / BLK_HEI * BLK_HEI; + + for (GLint cdx = rdx; cdx < rdxe; cdx += BLK_WID) + for (GLint cdy = rdy; cdy > rdye; cdy -= BLK_HEI) + glVertex3i(cdx + BLK_WID / 2, cdy - BLK_HEI / 2, z); + } + P_PAINTREG_END(); + } + glColor4f(0.0f, 0.0f, 0.0f, 0.0f); + +#ifdef DEBUG_GLX_ERR + glx_check_err(ps); +#endif +} + /** * Swap buffer with glXCopySubBufferMESA(). */ diff --git a/src/opengl.h b/src/opengl.h index f6ba09b..eae8bcf 100644 --- a/src/opengl.h +++ b/src/opengl.h @@ -132,3 +132,11 @@ glx_update_fbconfig(session_t *ps); static int glx_cmp_fbconfig(session_t *ps, const glx_fbconfig_t *pfbc_a, const glx_fbconfig_t *pfbc_b); + +static void +glx_render_color(session_t *ps, int dx, int dy, int width, int height, int z, + XserverRegion reg_tgt, const reg_data_t *pcache_reg); + +static void +glx_render_dots(session_t *ps, int dx, int dy, int width, int height, int z, + XserverRegion reg_tgt, const reg_data_t *pcache_reg); From 90099d371da6b4103680e6ba9c9f713cf4d50a61 Mon Sep 17 00:00:00 2001 From: Richard Grenville Date: Thu, 9 May 2013 21:47:09 +0800 Subject: [PATCH 3/4] Bug fix: Compilation failure with NO_LIBCONFIG / NO_C2 - Fix compilation failure with NO_LIBCONFIG or NO_C2. Thanks to Spaulding for reporting. --- src/compton.c | 168 +++++++++++++++++++++++++------------------------- src/compton.h | 4 +- 2 files changed, 86 insertions(+), 86 deletions(-) diff --git a/src/compton.c b/src/compton.c index 0fb040b..cffee1a 100644 --- a/src/compton.c +++ b/src/compton.c @@ -4389,90 +4389,6 @@ fork_after(session_t *ps) { return success; } -#ifdef CONFIG_LIBCONFIG -/** - * Get a file stream of the configuration file to read. - * - * Follows the XDG specification to search for the configuration file. - */ -static FILE * -open_config_file(char *cpath, char **ppath) { - const static char *config_filename = "/compton.conf"; - const static char *config_filename_legacy = "/.compton.conf"; - const static char *config_home_suffix = "/.config"; - const static char *config_system_dir = "/etc/xdg"; - - char *dir = NULL, *home = NULL; - char *path = cpath; - FILE *f = NULL; - - if (path) { - f = fopen(path, "r"); - if (f && ppath) - *ppath = path; - return f; - } - - // Check user configuration file in $XDG_CONFIG_HOME firstly - if (!((dir = getenv("XDG_CONFIG_HOME")) && strlen(dir))) { - if (!((home = getenv("HOME")) && strlen(home))) - return NULL; - - path = mstrjoin3(home, config_home_suffix, config_filename); - } - else - path = mstrjoin(dir, config_filename); - - f = fopen(path, "r"); - - if (f && ppath) - *ppath = path; - else - free(path); - if (f) - return f; - - // Then check user configuration file in $HOME - if ((home = getenv("HOME")) && strlen(home)) { - path = mstrjoin(home, config_filename_legacy); - f = fopen(path, "r"); - if (f && ppath) - *ppath = path; - else - free(path); - if (f) - return f; - } - - // Check system configuration file in $XDG_CONFIG_DIRS at last - if ((dir = getenv("XDG_CONFIG_DIRS")) && strlen(dir)) { - char *part = strtok(dir, ":"); - while (part) { - path = mstrjoin(part, config_filename); - f = fopen(path, "r"); - if (f && ppath) - *ppath = path; - else - free(path); - if (f) - return f; - part = strtok(NULL, ":"); - } - } - else { - path = mstrjoin(config_system_dir, config_filename); - f = fopen(path, "r"); - if (f && ppath) - *ppath = path; - else - free(path); - if (f) - return f; - } - - return NULL; -} - /** * Parse a floating-point number in matrix. */ @@ -4601,6 +4517,90 @@ parse_conv_kern(session_t *ps, const char *src) { return parse_matrix(ps, src); } +#ifdef CONFIG_LIBCONFIG +/** + * Get a file stream of the configuration file to read. + * + * Follows the XDG specification to search for the configuration file. + */ +static FILE * +open_config_file(char *cpath, char **ppath) { + const static char *config_filename = "/compton.conf"; + const static char *config_filename_legacy = "/.compton.conf"; + const static char *config_home_suffix = "/.config"; + const static char *config_system_dir = "/etc/xdg"; + + char *dir = NULL, *home = NULL; + char *path = cpath; + FILE *f = NULL; + + if (path) { + f = fopen(path, "r"); + if (f && ppath) + *ppath = path; + return f; + } + + // Check user configuration file in $XDG_CONFIG_HOME firstly + if (!((dir = getenv("XDG_CONFIG_HOME")) && strlen(dir))) { + if (!((home = getenv("HOME")) && strlen(home))) + return NULL; + + path = mstrjoin3(home, config_home_suffix, config_filename); + } + else + path = mstrjoin(dir, config_filename); + + f = fopen(path, "r"); + + if (f && ppath) + *ppath = path; + else + free(path); + if (f) + return f; + + // Then check user configuration file in $HOME + if ((home = getenv("HOME")) && strlen(home)) { + path = mstrjoin(home, config_filename_legacy); + f = fopen(path, "r"); + if (f && ppath) + *ppath = path; + else + free(path); + if (f) + return f; + } + + // Check system configuration file in $XDG_CONFIG_DIRS at last + if ((dir = getenv("XDG_CONFIG_DIRS")) && strlen(dir)) { + char *part = strtok(dir, ":"); + while (part) { + path = mstrjoin(part, config_filename); + f = fopen(path, "r"); + if (f && ppath) + *ppath = path; + else + free(path); + if (f) + return f; + part = strtok(NULL, ":"); + } + } + else { + path = mstrjoin(config_system_dir, config_filename); + f = fopen(path, "r"); + if (f && ppath) + *ppath = path; + else + free(path); + if (f) + return f; + } + + return NULL; +} + /** * Parse a condition list in configuration file. */ diff --git a/src/compton.h b/src/compton.h index 2e4e3d1..aba07c0 100644 --- a/src/compton.h +++ b/src/compton.h @@ -146,16 +146,16 @@ free_damage(session_t *ps, Damage *p) { } } -#ifdef CONFIG_C2 /** * Destroy a condition list. */ static inline void free_wincondlst(c2_lptr_t **pcondlst) { +#ifdef CONFIG_C2 while ((*pcondlst = c2_free_lptr(*pcondlst))) continue; -} #endif +} /** * Check whether a paint_t contains enough data. From 57d8b940e7158d325fc880b3e59e21b2450aa765 Mon Sep 17 00:00:00 2001 From: Richard Grenville Date: Sun, 12 May 2013 18:21:16 +0800 Subject: [PATCH 4/4] Misc: Add DEBUG_GLX_MARK & Misc - GLX backend: Add DEBUG_GLX_MARK, to add GL marks around functions with glStringMarkerGREMEDY(), and mark frame termination with glFrameTerminatorGREMEDY(). - Print output of `compton -h` to stdout. (#110) - GLX backend: Strip out elements with factor 0 in GLSL blur code. Thanks to jrfonseca for guides. (#107) --- src/common.h | 43 +++++++++++++++++++++++++++++++++++++++++++ src/compton.c | 18 ++++++++++++------ src/compton.h | 2 +- src/dbus.c | 20 ++++++++++++++++++++ src/opengl.c | 9 +++++++++ 5 files changed, 85 insertions(+), 7 deletions(-) diff --git a/src/common.h b/src/common.h index 6d7cea1..bf9f8ae 100644 --- a/src/common.h +++ b/src/common.h @@ -317,6 +317,11 @@ typedef void (*f_ReleaseTexImageEXT) (Display *display, GLXDrawable drawable, in typedef void (*f_CopySubBuffer) (Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); +#ifdef DEBUG_GLX_MARK +typedef void (*f_StringMarkerGREMEDY) (GLsizei len, const void *string); +typedef void (*f_FrameTerminatorGREMEDY) (void); +#endif + /// @brief Wrapper of a GLX FBConfig. typedef struct { GLXFBConfig cfg; @@ -688,6 +693,12 @@ typedef struct { f_ReleaseTexImageEXT glXReleaseTexImageProc; /// Pointer to glXCopySubBufferMESA function. f_CopySubBuffer glXCopySubBufferProc; +#ifdef DEBUG_GLX_MARK + /// Pointer to StringMarkerGREMEDY function. + f_StringMarkerGREMEDY glStringMarkerGREMEDY; + /// Pointer to FrameTerminatorGREMEDY function. + f_FrameTerminatorGREMEDY glFrameTerminatorGREMEDY; +#endif /// FBConfig-s for GLX pixmap of different depths. glx_fbconfig_t *glx_fbconfigs[OPENGL_MAX_DEPTH + 1]; #ifdef CONFIG_VSYNC_OPENGL_GLSL @@ -1803,6 +1814,38 @@ glx_create_program(const GLuint * const shaders, int nshaders); #endif #endif +/** + * Add a OpenGL debugging marker. + */ +static inline void +glx_mark_(session_t *ps, const char *func, XID xid, bool start) { +#ifdef DEBUG_GLX_MARK + if (BKEND_GLX == ps->o.backend && ps->glStringMarkerGREMEDY) { + if (!func) func = "(unknown)"; + const char *postfix = (start ? " (start)": " (end)"); + char *str = malloc((strlen(func) + 12 + 2 + + strlen(postfix) + 5) * sizeof(char)); + strcpy(str, func); + sprintf(str + strlen(str), "(%#010lx)%s", xid, postfix); + ps->glStringMarkerGREMEDY(strlen(str), str); + free(str); + } +#endif +} + +#define glx_mark(ps, xid, start) glx_mark_(ps, __func__, xid, start) + +/** + * Add a OpenGL debugging marker. + */ +static inline void +glx_mark_frame(session_t *ps) { +#ifdef DEBUG_GLX_MARK + if (BKEND_GLX == ps->o.backend && ps->glFrameTerminatorGREMEDY) + ps->glFrameTerminatorGREMEDY(); +#endif +} + static inline void free_texture(session_t *ps, glx_texture_t **pptex) { #ifdef CONFIG_VSYNC_OPENGL diff --git a/src/compton.c b/src/compton.c index cffee1a..7e005b6 100644 --- a/src/compton.c +++ b/src/compton.c @@ -1402,6 +1402,8 @@ 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) { + glx_mark(ps, w->id, true); + // Fetch Pixmap if (!w->paint.pixmap && ps->has_name_pixmap) { set_ignore_next(ps); @@ -1564,6 +1566,8 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint, #endif } } + + glx_mark(ps, w->id, false); } /** @@ -1812,6 +1816,7 @@ paint_all(session_t *ps, XserverRegion region, XserverRegion region_real, win *t default: assert(0); } + glx_mark_frame(ps); if (ps->o.vsync_aggressive) vsync_wait(ps); @@ -4050,7 +4055,7 @@ ev_handle(session_t *ps, XEvent *ev) { * Print usage text and exit. */ static void -usage(void) { +usage(int ret) { #define WARNING_DISABLED " (DISABLED AT COMPILE TIME)" #define WARNING const static char *usage_text = @@ -4277,11 +4282,12 @@ usage(void) { " Specify window ID to repaint in benchmark mode. If omitted or is 0,\n" " the whole screen is repainted.\n" ; - fputs(usage_text , stderr); + FILE *f = (ret ? stderr: stdout); + fputs(usage_text, f); #undef WARNING #undef WARNING_DISABLED - exit(1); + exit(ret); } /** @@ -4903,7 +4909,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { else if ('d' == o) ps->o.display = mstrcpy(optarg); else if ('?' == o || ':' == o) - usage(); + usage(1); } // Check for abundant positional arguments @@ -4944,7 +4950,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { #define P_CASEBOOL(idx, option) case idx: ps->o.option = true; break // Short options case 'h': - usage(); + usage(0); break; case 'd': break; @@ -5118,7 +5124,7 @@ get_cfg(session_t *ps, int argc, char *const *argv, bool first_pass) { break; P_CASEBOOL(303, glx_use_gpushader4); default: - usage(); + usage(1); break; #undef P_CASEBOOL } diff --git a/src/compton.h b/src/compton.h index aba07c0..24325ab 100644 --- a/src/compton.h +++ b/src/compton.h @@ -813,7 +813,7 @@ ev_window(session_t *ps, XEvent *ev); #endif static void __attribute__ ((noreturn)) -usage(void); +usage(int ret); static bool register_cm(session_t *ps); diff --git a/src/dbus.c b/src/dbus.c index a80c012..e48aa1a 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -605,6 +605,20 @@ cdbus_process(session_t *ps, DBusMessage *msg) { "org.freedesktop.DBus.Introspectable", "Introspect")) { success = cdbus_process_introspect(ps, msg); } + else if (dbus_message_is_method_call(msg, + "org.freedesktop.DBus.Peer", "Ping")) { + cdbus_reply(ps, msg, NULL, NULL); + success = true; + } + else if (dbus_message_is_method_call(msg, + "org.freedesktop.DBus.Peer", "GetMachineId")) { + char *uuid = dbus_get_local_machine_id(); + if (uuid) { + cdbus_reply_string(ps, msg, uuid); + dbus_free(uuid); + success = true; + } + } else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameAcquired") || dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameLost")) { success = true; @@ -1028,6 +1042,12 @@ cdbus_process_introspect(session_t *ps, DBusMessage *msg) { " \n" " \n" " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" " \n" " \n" " \n" diff --git a/src/opengl.c b/src/opengl.c index a4cb858..edd6151 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -90,6 +90,13 @@ glx_init(session_t *ps, bool need_render) { // Acquire function addresses if (need_render) { +#ifdef DEBUG_GLX_MARK + ps->glStringMarkerGREMEDY = (f_StringMarkerGREMEDY) + glXGetProcAddress((const GLubyte *) "glStringMarkerGREMEDY"); + ps->glFrameTerminatorGREMEDY = (f_FrameTerminatorGREMEDY) + glXGetProcAddress((const GLubyte *) "glFrameTerminatorGREMEDY"); +#endif + ps->glXBindTexImageProc = (f_BindTexImageEXT) glXGetProcAddress((const GLubyte *) "glXBindTexImageEXT"); ps->glXReleaseTexImageProc = (f_ReleaseTexImageEXT) @@ -249,6 +256,8 @@ glx_init_blur(session_t *ps) { if (hei / 2 == i && wid / 2 == j) continue; double val = XFixedToDouble(ps->o.blur_kern[2 + i * wid + j]); + if (0.0 == val) + continue; sum += val; sprintf(pc, shader_add, val, texture_func, j - wid / 2, i - hei / 2); pc += strlen(pc);