summaryrefslogtreecommitdiffhomepage
path: root/.rules/plan/phase-08-zero-copy.md
diff options
context:
space:
mode:
Diffstat (limited to '.rules/plan/phase-08-zero-copy.md')
-rw-r--r--.rules/plan/phase-08-zero-copy.md39
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.