diff options
Diffstat (limited to '.rules/plan/phase-08-zero-copy.md')
| -rw-r--r-- | .rules/plan/phase-08-zero-copy.md | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/.rules/plan/phase-08-zero-copy.md b/.rules/plan/phase-08-zero-copy.md new file mode 100644 index 0000000..56f99c3 --- /dev/null +++ b/.rules/plan/phase-08-zero-copy.md @@ -0,0 +1,39 @@ +# Phase 8 — GLX Texture-from-Pixmap (Zero-Copy Upgrade) + +--- + +## Step 8.1 — Replace XGetImage with GLX_EXT_texture_from_pixmap + +This is the performance upgrade. Instead of reading pixels through the +CPU, bind the X pixmap directly as an OpenGL texture: + +1. Find an FBConfig that supports `GLX_BIND_TO_TEXTURE_RGBA_EXT`. +2. Create a `GLXPixmap` from the X `Pixmap`. +3. Call `glXBindTexImageEXT()` to bind it as a GL texture. +4. Wrap the GL texture ID in a raylib `Texture2D` struct (set `.id` + directly, since raylib textures are just GL texture handles with + width/height/format metadata). + +On damage: `glXReleaseTexImageEXT` then `glXBindTexImageEXT` to refresh. +On resize: destroy and recreate the GLX pixmap. + +Handle `GLX_Y_INVERTED_EXT` — if the pixmap is Y-inverted, flip the +texture coordinates when drawing (use `DrawTexturePro` with a negative +source height, or flip in a shader). + +**Verify:** Same visual result as Step 3.4 but with dramatically less +CPU usage. Confirm with `top` or `perf` that `XGetImage` is no longer +called. `xeyes` still tracks the mouse smoothly. Resizing windows +works without artifacts. + +**Note:** This step may not work inside Xephyr (which uses software +rendering). If `GLX_EXT_texture_from_pixmap` is not available in Xephyr, +keep the CPU-copy path as a fallback and test zero-copy on a real X +session or VM with GPU passthrough. Implement runtime detection: + +```c +const char *glx_exts = glXQueryExtensionsString(dpy, screen); +bool has_tfp = strstr(glx_exts, "GLX_EXT_texture_from_pixmap") != NULL; +``` + +Use `has_tfp` to pick the code path. |
