Surface Basics

June 30, 2026

Today's the day! We finally get to render an actual client buffer using our compositor. Is that an exciting process? No, not really. But the results must surely be mindboggling then..?! ...ehh. But we're starting to cross that threshold of being able to do more visual demos and experiments now, so that's exciting.

Interfaces

There are a few key interfaces we need to make use out of in order to get our client's buffer of pixels to the server. We make use of wl_shm to create a wl_shm_pool, which is a pool of shared memory. Then from that, we create some wl_buffer resources, allowing us to share our data with the compositor.

To actually send our data to the compositor, we create a wl_surface from the wl_compositor global, attach our buffer to it, and send it off. As part of this process, we also assign our surface the xdg_toplevel role, which comes from xdg_surface and xdg_wm_base. Roles are how our compositor can tell the difference between a top level application window and, say, our mouse cursor.

Textures

Once all the above resources are in place, you still need to get the buffer of pixel data rendered onto the screen. That's where OpenGL and textures come into play. The compositor saves the pixel buffer to a texture, which it then wraps around a "unit quad" - a 1x1 rectangle we've created inside OpenGL. This unit quad then gets transformed by a surface-level projection matrix to make the application window the correct size and shape inside OpenGL's canvas, and also an output-level projection matrix to map OpenGL's canvas to the physical screen.

Related Links

Here's the PR for these changes: Github PR #5

There are also protocol reference pages for the interfaces discussed in this video: