Skip to content

Cache solid alpha pictures at 256 discrete levels - #48

Open
jEsuSdA wants to merge 1 commit into
tycho-kirchner:masterfrom
jEsuSdA:fix/cache-alpha-pictures-double-free
Open

Cache solid alpha pictures at 256 discrete levels#48
jEsuSdA wants to merge 1 commit into
tycho-kirchner:masterfrom
jEsuSdA:fix/cache-alpha-pictures-double-free

Conversation

@jEsuSdA

@jEsuSdA jEsuSdA commented Jul 2, 2026

Copy link
Copy Markdown

Summary

Caches solid alpha pictures at 256 discrete levels to eliminate redundant X server round-trips for translucent windows. Also fixes a double-free bug that would occur if the cached pictures were freed per-window.

Problem

Creating a solid alpha picture via solid_picture() involves multiple X server round-trips: XCreatePixmap, XRenderCreatePicture, XRenderFillRectangle. Every window with opacity < OPAQUE creates its own alpha picture in paint_all(), and determine_mode() destroys it when the mode changes. For a desktop with many translucent windows, this means dozens of redundant picture creations per frame.

Solution

Global cache

  • g_alpha_pict_cache[256] — indexed by opacity >> 24 (0-255). Each level is created on first demand and reused for all windows with that opacity level.
  • g_border_alpha_pict — cached once for frame opacity (shared across all windows with frame opacity).

No per-window free

Since the pictures are now shared across windows, they must never be freed per-window:

  • determine_mode() now only nulls the pointers, never calling XRenderFreePicture()
  • finish_destroy_win() now only nulls the pointers

This fixes the double-free that would occur when two windows share the same cached picture.

Changes

  • Only fastcompmgr.c is touched
  • make clean && make produces zero warnings, zero errors

Impact

Eliminates redundant alpha picture creation/destruction, reducing server round-trips especially for desktops with many translucent windows.

…erver round-trips

Creating a solid alpha picture via solid_picture() involves multiple X server
round-trips: XCreatePixmap, XRenderCreatePicture, XRenderFillRectangle.
Currently, every window with opacity < OPAQUE creates its own alpha picture
in paint_all(), and determine_mode() destroys it when the mode changes. For a
desktop with many translucent windows, this means dozens of redundant picture
creations per frame.

Add a global cache of 256 discrete alpha levels (indexed by opacity>>24).
When a window needs an alpha picture, it reuses the cached one instead of
creating a new one. The border alpha picture (for frame opacity) is also
cached once.

Since the pictures are now shared across windows, they must never be freed
per-window. determine_mode() and finish_destroy_win() now only null the
pointers, never calling XRenderFreePicture(). This fixes the double-free
that would otherwise occur when two windows share the same cached picture.

Impact: eliminates redundant alpha picture creation/destruction, reducing
server round-trips especially for desktops with many translucent windows.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant