X11: mildly optimize drawing

There is no real performance impact on modern systems.
This commit is contained in:
Přemysl Eric Janouch 2022-08-25 01:47:00 +02:00
parent d82be07807
commit b196ef4f08
Signed by: p
GPG Key ID: A0420B94F92B9493
1 changed files with 33 additions and 12 deletions

View File

@ -1357,6 +1357,7 @@ static struct app_context
int xkb_base_event_code; ///< Xkb base event code int xkb_base_event_code; ///< Xkb base event code
Window x11_window; ///< Application window Window x11_window; ///< Application window
Pixmap x11_pixmap; ///< Off-screen bitmap Pixmap x11_pixmap; ///< Off-screen bitmap
Region x11_clip; ///< Invalidated region
Picture x11_pixmap_picture; ///< XRender wrap for x11_pixmap Picture x11_pixmap_picture; ///< XRender wrap for x11_pixmap
XftDraw *xft_draw; ///< Xft rendering context XftDraw *xft_draw; ///< Xft rendering context
XftFont *xft_regular; ///< Regular font XftFont *xft_regular; ///< Regular font
@ -5673,19 +5674,27 @@ x11_render_spectrum (struct widget *self)
x11_render_padding (self); x11_render_padding (self);
#ifdef WITH_FFTW #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++) for (int i = 0; i < g.spectrum.bars; i++)
{ {
float value = g.spectrum.spectrum[i]; int height = round ((self->height - 2) * g.spectrum.spectrum[i]);
int height = round ((self->height - 2) * value); rectangles[i] = (XRectangle)
XRenderFillRectangle (g.dpy, PictOpSrc, {
g.x11_pixmap_picture, x11_fg (self),
self->x + i * step, self->x + i * step,
self->y + self->height - 1 - height, self->y + self->height - 1 - height,
step, step,
height); height,
};
} }
XRenderFillRectangles (g.dpy, PictOpSrc, g.x11_pixmap_picture,
x11_fg (self), rectangles, N_ELEMENTS (rectangles));
#endif // WITH_FFTW #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 * static struct widget *
@ -5812,20 +5821,26 @@ x11_render (void)
{ {
XRenderFillRectangle (g.dpy, PictOpSrc, g.x11_pixmap_picture, XRenderFillRectangle (g.dpy, PictOpSrc, g.x11_pixmap_picture,
&x11_default_bg, 0, 0, g.ui_width, g.ui_height); &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) LIST_FOR_EACH (struct widget, w, g.widgets.head)
if (w->width && w->height) if (w->width && w->height)
w->on_render (w); 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); poller_idle_set (&g.xpending_event);
} }
static void static void
x11_flip (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, XCopyArea (g.dpy, g.x11_pixmap, g.x11_window,
DefaultGC (g.dpy, DefaultScreen (g.dpy)), 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); poller_idle_set (&g.xpending_event);
} }
@ -5834,6 +5849,7 @@ x11_destroy (void)
{ {
XDestroyIC (g.x11_ic); XDestroyIC (g.x11_ic);
XCloseIM (g.x11_im); XCloseIM (g.x11_im);
XDestroyRegion (g.x11_clip);
XDestroyWindow (g.dpy, g.x11_window); XDestroyWindow (g.dpy, g.x11_window);
XRenderFreePicture (g.dpy, g.x11_pixmap_picture); XRenderFreePicture (g.dpy, g.x11_pixmap_picture);
XFreePixmap (g.dpy, g.x11_pixmap); XFreePixmap (g.dpy, g.x11_pixmap);
@ -6072,9 +6088,13 @@ on_x11_event (XEvent *ev)
switch (ev->type) switch (ev->type)
{ {
case Expose: case Expose:
if (!ev->xexpose.count) {
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); poller_idle_set (&g.flip_event);
break; break;
}
case ConfigureNotify: case ConfigureNotify:
if (g.ui_width == ev->xconfigure.width if (g.ui_width == ev->xconfigure.width
&& g.ui_height == ev->xconfigure.height) && 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.x11_window = XCreateWindow (g.dpy, RootWindow (g.dpy, screen), 100, 100,
g.ui_width, g.ui_height, 0, CopyFromParent, InputOutput, visual, g.ui_width, g.ui_height, 0, CopyFromParent, InputOutput, visual,
CWEventMask | CWBackPixel | CWBitGravity, &attrs); CWEventMask | CWBackPixel | CWBitGravity, &attrs);
g.x11_clip = XCreateRegion ();
XTextProperty prop = {}; XTextProperty prop = {};
char *name = PROGRAM_NAME; char *name = PROGRAM_NAME;