diff --git a/common.h b/common.h index eb57250b0..d5abdfdf9 100644 --- a/common.h +++ b/common.h @@ -341,6 +341,14 @@ typedef struct _latom { struct _latom *next; } latom_t; +/// A representation of raw region data +typedef struct { + XRectangle *rects; + int nrects; +} reg_data_t; + +#define REG_DATA_INIT { NULL, 0 } + struct _timeout_t; struct _win; @@ -1532,6 +1540,20 @@ free_region(session_t *ps, XserverRegion *p) { } } +/** + * Crop a rectangle by another rectangle. + * + * psrc and pdst cannot be the same. + */ +static inline void +rect_crop(XRectangle *pdst, const XRectangle *psrc, const XRectangle *pbound) { + assert(psrc != pdst); + pdst->x = max_i(psrc->x, pbound->x); + pdst->y = max_i(psrc->y, pbound->y); + pdst->width = max_i(0, min_i(psrc->x + psrc->width, pbound->x + pbound->width) - pdst->x); + pdst->height = max_i(0, min_i(psrc->y + psrc->height, pbound->y + pbound->height) - pdst->y); +} + /** * Check if a rectangle includes the whole screen. */ @@ -1661,21 +1683,21 @@ glx_tex_binded(const glx_texture_t *ptex, Pixmap pixmap) { } void -glx_set_clip(session_t *ps, XserverRegion reg, - const XRectangle * const cache_rects, const int cache_nrects); +glx_set_clip(session_t *ps, XserverRegion reg, const reg_data_t *pcache_reg); bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z, - GLfloat factor_center); + GLfloat factor_center, XserverRegion reg_tgt, const reg_data_t *pcache_reg); bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, - GLfloat factor); + GLfloat factor, XserverRegion reg_tgt, const reg_data_t *pcache_reg); bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy, int width, int height, int z, - double opacity, bool neg, XserverRegion reg_tgt); + double opacity, bool neg, + XserverRegion reg_tgt, const reg_data_t *pcache_reg); void glx_swap_copysubbuffermesa(session_t *ps, XserverRegion reg); diff --git a/compton.c b/compton.c index e86d74951..ae4130f6a 100644 --- a/compton.c +++ b/compton.c @@ -881,7 +881,7 @@ paint_root(session_t *ps, XserverRegion reg_paint) { get_root_tile(ps); win_render(ps, NULL, 0, 0, ps->root_width, ps->root_height, 1.0, reg_paint, - ps->root_tile_paint.pict); + NULL, ps->root_tile_paint.pict); } /** @@ -1280,7 +1280,8 @@ paint_preprocess(session_t *ps, win *list) { * Paint the shadow of a window. */ static inline void -win_paint_shadow(session_t *ps, win *w, XserverRegion reg_paint) { +win_paint_shadow(session_t *ps, win *w, + XserverRegion reg_paint, const reg_data_t *pcache_reg) { if (!paint_isvalid(ps, &w->shadow_paint)) { printf_errf("(%#010lx): Missing painting data. This is a bad sign.", w->id); return; @@ -1288,7 +1289,7 @@ win_paint_shadow(session_t *ps, win *w, XserverRegion reg_paint) { render(ps, 0, 0, w->a.x + w->shadow_dx, w->a.y + w->shadow_dy, w->shadow_width, w->shadow_height, w->shadow_opacity, true, false, - w->shadow_paint.pict, w->shadow_paint.ptex, reg_paint); + w->shadow_paint.pict, w->shadow_paint.ptex, reg_paint, pcache_reg); } /** @@ -1320,7 +1321,7 @@ win_build_picture(session_t *ps, win *w, XRenderPictFormat *pictfmt) { */ static inline void win_blur_background(session_t *ps, win *w, Picture tgt_buffer, - XserverRegion reg_paint) { + XserverRegion reg_paint, const reg_data_t *pcache_reg) { const int x = w->a.x; const int y = w->a.y; const int wid = w->widthb; @@ -1385,7 +1386,8 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer, break; #ifdef CONFIG_VSYNC_OPENGL case BKEND_GLX: - glx_blur_dst(ps, x, y, wid, hei, ps->glx_z - 0.5, factor_center); + glx_blur_dst(ps, x, y, wid, hei, ps->glx_z - 0.5, factor_center, + reg_paint, pcache_reg); break; #endif default: @@ -1396,7 +1398,8 @@ win_blur_background(session_t *ps, win *w, Picture tgt_buffer, static 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, XserverRegion reg_paint) { + Picture pict, glx_texture_t *ptex, + XserverRegion reg_paint, const reg_data_t *pcache_reg) { switch (ps->o.backend) { case BKEND_XRENDER: { @@ -1411,7 +1414,7 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, #ifdef CONFIG_VSYNC_OPENGL case BKEND_GLX: glx_render(ps, ptex, x, y, dx, dy, wid, hei, - ps->glx_z, opacity, neg, reg_paint); + ps->glx_z, opacity, neg, reg_paint, pcache_reg); ps->glx_z += 1; break; #endif @@ -1424,7 +1427,8 @@ render(session_t *ps, int x, int y, int dx, int dy, int wid, int hei, * Paint a window itself and dim it if asked. */ static inline void -win_paint_win(session_t *ps, win *w, XserverRegion reg_paint) { +win_paint_win(session_t *ps, win *w, XserverRegion reg_paint, + const reg_data_t *pcache_reg) { // Fetch Pixmap if (!w->paint.pixmap && ps->has_name_pixmap) { set_ignore_next(ps); @@ -1494,7 +1498,7 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint) { double dopacity = get_opacity_percent(w);; if (!w->frame_opacity) { - win_render(ps, w, 0, 0, wid, hei, dopacity, reg_paint, pict); + win_render(ps, w, 0, 0, wid, hei, dopacity, reg_paint, pcache_reg, pict); } else { // Painting parameters @@ -1505,7 +1509,7 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint) { #define COMP_BDR(cx, cy, cwid, chei) \ win_render(ps, w, (cx), (cy), (cwid), (chei), w->frame_opacity, \ - reg_paint, pict) + reg_paint, pcache_reg, pict) // The following complicated logic is required because some broken // window managers (I'm talking about you, Openbox!) that makes @@ -1540,7 +1544,7 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint) { pwid = wid - l - pwid; if (pwid > 0) { // body - win_render(ps, w, l, t, pwid, phei, dopacity, reg_paint, pict); + win_render(ps, w, l, t, pwid, phei, dopacity, reg_paint, pcache_reg, pict); } } } @@ -1581,7 +1585,8 @@ win_paint_win(session_t *ps, win *w, XserverRegion reg_paint) { break; #ifdef CONFIG_VSYNC_OPENGL case BKEND_GLX: - glx_dim_dst(ps, x, y, wid, hei, ps->glx_z - 0.7, dim_opacity); + glx_dim_dst(ps, x, y, wid, hei, ps->glx_z - 0.7, dim_opacity, + reg_paint, pcache_reg); break; #endif } @@ -1666,7 +1671,7 @@ paint_all(session_t *ps, XserverRegion region, win *t) { reg_paint = region; } - set_tgt_clip(ps, reg_paint, NULL, 0); + set_tgt_clip(ps, reg_paint, NULL); paint_root(ps, reg_paint); // Create temporary regions for use during painting @@ -1718,15 +1723,14 @@ paint_all(session_t *ps, XserverRegion region, win *t) { // Detect if the region is empty before painting { - int nrects = 0; - XRectangle *rects = NULL; + reg_data_t cache_reg = REG_DATA_INIT; if (region == reg_paint - || !is_region_empty(ps, reg_paint, &rects, &nrects)) { - set_tgt_clip(ps, reg_paint, rects, nrects); + || !is_region_empty(ps, reg_paint, &cache_reg)) { + set_tgt_clip(ps, reg_paint, &cache_reg); - win_paint_shadow(ps, w, reg_paint); + win_paint_shadow(ps, w, reg_paint, &cache_reg); } - cxfree(rects); + free_reg_data(&cache_reg); } } @@ -1751,20 +1755,19 @@ paint_all(session_t *ps, XserverRegion region, win *t) { } { - int nrects = 0; - XRectangle *rects = NULL; - if (!is_region_empty(ps, reg_paint, &rects, &nrects)) { - set_tgt_clip(ps, reg_paint, rects, nrects); + reg_data_t cache_reg = REG_DATA_INIT; + if (!is_region_empty(ps, reg_paint, &cache_reg)) { + set_tgt_clip(ps, reg_paint, &cache_reg); // Blur window background if (w->blur_background && (WMODE_SOLID != w->mode || (ps->o.blur_background_frame && w->frame_opacity))) { - win_blur_background(ps, w, ps->tgt_buffer, reg_paint); + win_blur_background(ps, w, ps->tgt_buffer, reg_paint, &cache_reg); } // Painting the window - win_paint_win(ps, w, reg_paint); + win_paint_win(ps, w, reg_paint, &cache_reg); } - cxfree(rects); + free_reg_data(&cache_reg); } } @@ -1774,7 +1777,7 @@ paint_all(session_t *ps, XserverRegion region, win *t) { // Do this as early as possible if (!ps->o.dbe) - set_tgt_clip(ps, None, NULL, 0); + set_tgt_clip(ps, None, NULL); if (ps->o.vsync) { // Make sure all previous requests are processed to achieve best @@ -4227,8 +4230,8 @@ usage(void) { " Choose backend. Possible choices are xrender and glx" WARNING ".\n" "--glx-no-stencil\n" " GLX backend: Avoid using stencil buffer. Might cause issues\n" - " when rendering transparent content. May have a positive or\n" - " negative effect on performance. (My test shows a 10% slowdown.)\n" + " when rendering transparent content. My tests show a 15% performance\n" + " 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" @@ -6386,7 +6389,7 @@ session_run(session_t *ps) { if (!ps->redirected) free_region(ps, &ps->all_damage); - if (ps->all_damage && !is_region_empty(ps, ps->all_damage, NULL, NULL)) { + if (ps->all_damage && !is_region_empty(ps, ps->all_damage, NULL)) { static int paint = 0; paint_all(ps, ps->all_damage, t); ps->reg_ignore_expire = false; diff --git a/compton.h b/compton.h index 06bede6a2..09b1a4bfb 100644 --- a/compton.h +++ b/compton.h @@ -196,6 +196,16 @@ paint_bind_tex(session_t *ps, paint_t *ppaint, return true; } +/** + * Free data in a reg_data_t. + */ +static inline void +free_reg_data(reg_data_t *pregd) { + cxfree(pregd->rects); + pregd->rects = NULL; + pregd->nrects = 0; +} + /** * Free paint_t. */ @@ -532,29 +542,29 @@ paint_preprocess(session_t *ps, win *list); static 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, XserverRegion reg_paint); + Picture pict, glx_texture_t *ptex, + XserverRegion reg_paint, const reg_data_t *pcache_reg); static inline void -win_render(session_t *ps, win *w, int x, int y, int wid, int hei, double opacity, XserverRegion reg_paint, Picture pict) { +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) { const int dx = (w ? w->a.x: 0) + x; const int dy = (w ? w->a.y: 0) + y; const bool argb = (w && w->mode == WMODE_ARGB); const bool neg = (w && w->invert_color); render(ps, x, y, dx, dy, wid, hei, opacity, argb, neg, - pict, (w ? w->paint.ptex: ps->root_tile_paint.ptex), reg_paint); + pict, (w ? w->paint.ptex: ps->root_tile_paint.ptex), reg_paint, pcache_reg); } static inline void -set_tgt_clip(session_t *ps, XserverRegion reg, - const XRectangle * const cache_rects, const int cache_nrects) { +set_tgt_clip(session_t *ps, XserverRegion reg, const reg_data_t *pcache_reg) { switch (ps->o.backend) { case BKEND_XRENDER: XFixesSetPictureClipRegion(ps->dpy, ps->tgt_buffer, 0, 0, reg); break; #ifdef CONFIG_VSYNC_OPENGL case BKEND_GLX: - glx_set_clip(ps, reg, cache_rects, cache_nrects); + glx_set_clip(ps, reg, pcache_reg); break; #endif } @@ -870,18 +880,17 @@ dump_region(const session_t *ps, XserverRegion region) { */ static inline bool is_region_empty(const session_t *ps, XserverRegion region, - XRectangle **pcache_rects, int *pcache_nrects) { + reg_data_t *pcache_reg) { int nrects = 0; XRectangle *rects = XFixesFetchRegion(ps->dpy, region, &nrects); - if (pcache_rects) - *pcache_rects = rects; + if (pcache_reg) { + pcache_reg->rects = rects; + pcache_reg->nrects = nrects; + } else cxfree(rects); - if (pcache_nrects) - *pcache_nrects = nrects; - return !nrects; } diff --git a/opengl.c b/opengl.c index a660ab5c5..6560afe55 100644 --- a/opengl.c +++ b/opengl.c @@ -190,11 +190,6 @@ glx_on_root_change(session_t *ps) { bool glx_init_blur(session_t *ps) { #ifdef CONFIG_VSYNC_OPENGL_GLSL - if (ps->o.glx_no_stencil) { - printf_errf("(): I'm afraid blur background won't work so well without " - "stencil buffer support."); - } - // Build shader static const char *FRAG_SHADER_BLUR = "#version 110\n" @@ -562,7 +557,7 @@ glx_paint_pre(session_t *ps, XserverRegion *preg) { { XserverRegion reg_copy = XFixesCreateRegion(ps->dpy, NULL, 0); XFixesSubtractRegion(ps->dpy, reg_copy, ps->screen_reg, *preg); - glx_set_clip(ps, reg_copy, NULL, 0); + glx_set_clip(ps, reg_copy, NULL); free_region(ps, ®_copy); } @@ -577,22 +572,19 @@ glx_paint_pre(session_t *ps, XserverRegion *preg) { } } - glx_set_clip(ps, *preg, NULL, 0); + glx_set_clip(ps, *preg, NULL); } /** * Set clipping region on the target window. */ void -glx_set_clip(session_t *ps, XserverRegion reg, - const XRectangle * const cache_rects, const int cache_nrects) { +glx_set_clip(session_t *ps, XserverRegion reg, const reg_data_t *pcache_reg) { // Quit if we aren't using stencils if (ps->o.glx_no_stencil) return; - static XRectangle rect_blank = { - .x = 0, .y = 0, .width = 0, .height = 0 - }; + static XRectangle rect_blank = { .x = 0, .y = 0, .width = 0, .height = 0 }; glDisable(GL_STENCIL_TEST); glDisable(GL_SCISSOR_TEST); @@ -600,13 +592,18 @@ glx_set_clip(session_t *ps, XserverRegion reg, if (!reg) return; - int nrects = cache_nrects; + int nrects = 0; XRectangle *rects_free = NULL; - const XRectangle *rects = cache_rects; + const XRectangle *rects = NULL; + if (pcache_reg) { + rects = pcache_reg->rects; + nrects = pcache_reg->nrects; + } if (!rects) { nrects = 0; rects = rects_free = XFixesFetchRegion(ps->dpy, reg, &nrects); } + // Use one empty rectangle if the region is empty if (!nrects) { cxfree(rects_free); rects_free = NULL; @@ -657,9 +654,45 @@ glx_set_clip(session_t *ps, XserverRegion reg, cxfree(rects_free); } +#define P_PAINTREG_START() \ + XserverRegion reg_new = None; \ + XRectangle rec_all = { .x = dx, .y = dy, .width = width, .height = height }; \ + XRectangle *rects = &rec_all; \ + int nrects = 1; \ + \ + if (ps->o.glx_no_stencil && reg_tgt) { \ + if (pcache_reg) { \ + rects = pcache_reg->rects; \ + nrects = pcache_reg->nrects; \ + } \ + else { \ + reg_new = XFixesCreateRegion(ps->dpy, &rec_all, 1); \ + XFixesIntersectRegion(ps->dpy, reg_new, reg_new, reg_tgt); \ + \ + nrects = 0; \ + rects = XFixesFetchRegion(ps->dpy, reg_new, &nrects); \ + } \ + } \ + glBegin(GL_QUADS); \ + \ + for (int i = 0; i < nrects; ++i) { \ + XRectangle crect; \ + rect_crop(&crect, &rects[i], &rec_all); \ + \ + if (!crect.width || !crect.height) \ + continue; \ + +#define P_PAINTREG_END() \ + } \ + glEnd(); \ + \ + if (rects && rects != &rec_all && !(pcache_reg && pcache_reg->rects == rects)) \ + cxfree(rects); \ + free_region(ps, ®_new); \ + bool glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z, - GLfloat factor_center) { + GLfloat factor_center, XserverRegion reg_tgt, const reg_data_t *pcache_reg) { // Read destination pixels into a texture GLuint tex_scr = 0; glGenTextures(1, &tex_scr); @@ -699,37 +732,37 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z, glUniform1f(ps->glx_prog_blur_unifm_factor_center, factor_center); #endif - glBegin(GL_QUADS); - { - const GLfloat rx = 0.0; - const GLfloat ry = 1.0; - const GLfloat rxe = 1.0; - const GLfloat rye = 0.0; - const GLint rdx = dx; - const GLint rdy = ps->root_height - dy; - const GLint rdxe = rdx + width; - const GLint rdye = rdy - height; + P_PAINTREG_START(); + { + const GLfloat rx = (double) (crect.x - dx) / width; + const GLfloat ry = 1.0 - (double) (crect.y - dy) / height; + const GLfloat rxe = rx + (double) crect.width / width; + const GLfloat rye = ry - (double) crect.height / height; + const GLfloat rdx = crect.x; + const GLfloat rdy = ps->root_height - crect.y; + const GLfloat rdxe = rdx + crect.width; + const GLfloat rdye = rdy - crect.height; #ifdef DEBUG_GLX - printf_dbgf("(): %f, %f, %f, %f -> %d, %d, %d, %d\n", rx, ry, rxe, rye, rdx, rdy, rdxe, rdye); + printf_dbgf("(): %f, %f, %f, %f -> %d, %d, %d, %d\n", rx, ry, rxe, rye, rdx, rdy, rdxe, rdye); #endif - glTexCoord2f(rx, ry); - glVertex3f(rdx, rdy, z); + glTexCoord2f(rx, ry); + glVertex3f(rdx, rdy, z); - glTexCoord2f(rxe, ry); - glVertex3f(rdxe, rdy, z); + glTexCoord2f(rxe, ry); + glVertex3f(rdxe, rdy, z); - glTexCoord2f(rxe, rye); - glVertex3f(rdxe, rdye, z); + glTexCoord2f(rxe, rye); + glVertex3f(rdxe, rdye, z); - glTexCoord2f(rx, rye); - glVertex3f(rdx, rdye, z); + glTexCoord2f(rx, rye); + glVertex3f(rdx, rdye, z); + } + P_PAINTREG_END(); } - glEnd(); - #ifdef CONFIG_VSYNC_OPENGL_GLSL glUseProgram(0); #endif @@ -743,25 +776,27 @@ glx_blur_dst(session_t *ps, int dx, int dy, int width, int height, float z, bool glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, - GLfloat factor) { + GLfloat factor, XserverRegion reg_tgt, const reg_data_t *pcache_reg) { // It's possible to dim in glx_render(), but it would be over-complicated // considering all those mess in color negation and modulation glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glColor4f(0.0f, 0.0f, 0.0f, factor); - glBegin(GL_QUADS); - { - GLint rdx = dx; - GLint rdy = ps->root_height - dy; - GLint rdxe = rdx + width; - GLint rdye = rdy - height; - - glVertex3i(rdx, rdy, z); - glVertex3i(rdxe, rdy, z); - glVertex3i(rdxe, rdye, z); - glVertex3i(rdx, rdye, z); + 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(); } glEnd(); @@ -778,7 +813,8 @@ glx_dim_dst(session_t *ps, int dx, int dy, int width, int height, float z, bool glx_render(session_t *ps, const glx_texture_t *ptex, int x, int y, int dx, int dy, int width, int height, int z, - double opacity, bool neg, XserverRegion reg_tgt) { + double opacity, bool neg, + XserverRegion reg_tgt, const reg_data_t *pcache_reg) { if (!ptex || !ptex->texture) { printf_errf("(): Missing texture."); return false; @@ -878,51 +914,30 @@ glx_render(session_t *ps, const glx_texture_t *ptex, } } - { - XserverRegion reg_new = None; - - XRectangle rec_all = { - .x = dx, - .y = dy, - .width = width, - .height = height - }; - - XRectangle *rects = &rec_all; - int nrects = 1; - #ifdef DEBUG_GLX - printf_dbgf("(): Draw: %d, %d, %d, %d -> %d, %d (%d, %d) z %d\n", x, y, width, height, dx, dy, ptex->width, ptex->height, z); + printf_dbgf("(): Draw: %d, %d, %d, %d -> %d, %d (%d, %d) z %d\n", x, y, width, height, dx, dy, ptex->width, ptex->height, z); #endif - // On no-stencil mode, calculate painting region here instead of relying - // on stencil buffer - if (ps->o.glx_no_stencil && reg_tgt) { - reg_new = XFixesCreateRegion(ps->dpy, &rec_all, 1); - XFixesIntersectRegion(ps->dpy, reg_new, reg_new, reg_tgt); - - nrects = 0; - rects = XFixesFetchRegion(ps->dpy, reg_new, &nrects); - } - + // Bind texture + glBindTexture(ptex->target, ptex->texture); + if (dual_texture) { + glActiveTexture(GL_TEXTURE1); glBindTexture(ptex->target, ptex->texture); - if (dual_texture) { - glActiveTexture(GL_TEXTURE1); - glBindTexture(ptex->target, ptex->texture); - glActiveTexture(GL_TEXTURE0); - } - - glBegin(GL_QUADS); + glActiveTexture(GL_TEXTURE0); + } - for (int i = 0; i < nrects; ++i) { - GLfloat rx = (double) (rects[i].x - dx + x) / ptex->width; - GLfloat ry = (double) (rects[i].y - dy + y) / ptex->height; - GLfloat rxe = rx + (double) rects[i].width / ptex->width; - GLfloat rye = ry + (double) rects[i].height / ptex->height; - GLint rdx = rects[i].x; - GLint rdy = ps->root_height - rects[i].y; - GLint rdxe = rdx + rects[i].width; - GLint rdye = rdy - rects[i].height; + // Painting + { + 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; + GLint rdx = crect.x; + GLint rdy = ps->root_height - crect.y; + GLint rdxe = rdx + crect.width; + GLint rdye = rdy - crect.height; // Invert Y if needed, this may not work as expected, though. I don't // have such a FBConfig to test with. @@ -954,12 +969,7 @@ glx_render(session_t *ps, const glx_texture_t *ptex, P_TEXCOORD(rx, rye); glVertex3i(rdx, rdye, z); } - - glEnd(); - - if (rects && rects != &rec_all) - cxfree(rects); - free_region(ps, ®_new); + P_PAINTREG_END(); } // Cleanup @@ -993,7 +1003,7 @@ glx_swap_copysubbuffermesa(session_t *ps, XserverRegion reg) { glXSwapBuffers(ps->dpy, get_tgt_window(ps)); } else { - glx_set_clip(ps, None, NULL, 0); + glx_set_clip(ps, None, NULL); 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;