diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2022-08-25 01:47:00 +0200 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2022-08-25 02:16:36 +0200 |
commit | b196ef4f089be8ef20810b6687487c1e58aeae35 (patch) | |
tree | fcb20e9274832e8167a9b93690dcc194f538a992 | |
parent | d82be078076c040a513fa9fd495e3c36a3fd4828 (diff) | |
download | nncmpp-b196ef4f089be8ef20810b6687487c1e58aeae35.tar.gz nncmpp-b196ef4f089be8ef20810b6687487c1e58aeae35.tar.xz nncmpp-b196ef4f089be8ef20810b6687487c1e58aeae35.zip |
X11: mildly optimize drawing
There is no real performance impact on modern systems.
-rw-r--r-- | nncmpp.c | 45 |
1 files changed, 33 insertions, 12 deletions
@@ -1357,6 +1357,7 @@ static struct app_context int xkb_base_event_code; ///< Xkb base event code Window x11_window; ///< Application window Pixmap x11_pixmap; ///< Off-screen bitmap + Region x11_clip; ///< Invalidated region Picture x11_pixmap_picture; ///< XRender wrap for x11_pixmap XftDraw *xft_draw; ///< Xft rendering context XftFont *xft_regular; ///< Regular font @@ -5673,19 +5674,27 @@ x11_render_spectrum (struct widget *self) x11_render_padding (self); #ifdef WITH_FFTW - int step = self->width / g.spectrum.bars; + XRectangle rectangles[g.spectrum.bars]; + int step = self->width / N_ELEMENTS (rectangles); for (int i = 0; i < g.spectrum.bars; i++) { - float value = g.spectrum.spectrum[i]; - int height = round ((self->height - 2) * value); - XRenderFillRectangle (g.dpy, PictOpSrc, - g.x11_pixmap_picture, x11_fg (self), + int height = round ((self->height - 2) * g.spectrum.spectrum[i]); + rectangles[i] = (XRectangle) + { self->x + i * step, self->y + self->height - 1 - height, step, - height); + height, + }; } -#endif // WITH_FFTW + + XRenderFillRectangles (g.dpy, PictOpSrc, g.x11_pixmap_picture, + x11_fg (self), rectangles, N_ELEMENTS (rectangles)); +#endif // WITH_FFTW + + // Enable the spectrum_redraw() hack. + XRectangle r = { self->x, self->y, self->width, self->height }; + XUnionRectWithRegion (&r, g.x11_clip, g.x11_clip); } static struct widget * @@ -5812,20 +5821,26 @@ x11_render (void) { XRenderFillRectangle (g.dpy, PictOpSrc, g.x11_pixmap_picture, &x11_default_bg, 0, 0, g.ui_width, g.ui_height); - - // TODO: Consider setting clip rectangles (not particularly needed). LIST_FOR_EACH (struct widget, w, g.widgets.head) if (w->width && w->height) w->on_render (w); + + XRectangle r = { 0, 0, g.ui_width, g.ui_height }; + XUnionRectWithRegion (&r, g.x11_clip, g.x11_clip); poller_idle_set (&g.xpending_event); } static void x11_flip (void) { + // This exercise in futility doesn't seem to affect CPU usage much. + XRectangle r = {}; + XClipBox (g.x11_clip, &r); XCopyArea (g.dpy, g.x11_pixmap, g.x11_window, DefaultGC (g.dpy, DefaultScreen (g.dpy)), - 0, 0, g.ui_width, g.ui_height, 0, 0); + r.x, r.y, r.width, r.height, r.x, r.y); + + XSubtractRegion (g.x11_clip, g.x11_clip, g.x11_clip); poller_idle_set (&g.xpending_event); } @@ -5834,6 +5849,7 @@ x11_destroy (void) { XDestroyIC (g.x11_ic); XCloseIM (g.x11_im); + XDestroyRegion (g.x11_clip); XDestroyWindow (g.dpy, g.x11_window); XRenderFreePicture (g.dpy, g.x11_pixmap_picture); XFreePixmap (g.dpy, g.x11_pixmap); @@ -6072,9 +6088,13 @@ on_x11_event (XEvent *ev) switch (ev->type) { case Expose: - if (!ev->xexpose.count) - poller_idle_set (&g.flip_event); + { + XRectangle r = { ev->xexpose.x, ev->xexpose.y, + ev->xexpose.width, ev->xexpose.height }; + XUnionRectWithRegion (&r, g.x11_clip, g.x11_clip); + poller_idle_set (&g.flip_event); break; + } case ConfigureNotify: if (g.ui_width == ev->xconfigure.width && g.ui_height == ev->xconfigure.height) @@ -6308,6 +6328,7 @@ x11_init (void) g.x11_window = XCreateWindow (g.dpy, RootWindow (g.dpy, screen), 100, 100, g.ui_width, g.ui_height, 0, CopyFromParent, InputOutput, visual, CWEventMask | CWBackPixel | CWBitGravity, &attrs); + g.x11_clip = XCreateRegion (); XTextProperty prop = {}; char *name = PROGRAM_NAME; |