# 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.