This chapter looks at when a request to redraw a surface can be made
A Wayland server will render buffers. This will take some time. If an attempt is made by a client to ask for a buffer to be rendered prematurely, it won't happen: the request will be ignored. The server must be able to tell a client when it is ready to handle another surface commit request.
The client needs to register a listener for the server's
information. This is done by first getting a
wl_callback
by wl_surface_frame
and then adding a listener by
wl_callback_add_listener
as in
frame_callback = wl_surface_frame(surface);
wl_callback_add_listener(frame_callback, &frame_listener, NULL);
The wl_callback_listener
is a struct with only
one function member such as
static const struct wl_callback_listener frame_listener = {
redraw
};
The function (here redraw
) could do a variety
of things: for example it could set a flag for a thread to
later render something, or it could wake up a sleeping thread
to render. Here we just draw again into shared memory
and call to render that by committing the surface.
The drawing is deliberately simple: fill the drawing area
with a single colour, starting with black and each time
lightening it to white, at the end of which we go back to
black:
uint32_t pixel_value = 0x0; // black
static void
paint_pixels() {
int n;
uint32_t *pixel = shm_data;
for (n =0; n < WIDTH*HEIGHT; n++) {
*pixel++ = pixel_value;
}
// increase each RGB component by one
pixel_value += 0x10101;
// if it's reached 0xffffff (white) reset to zero
if (pixel_value > 0xffffff) {
pixel_value = 0x0;
}
}
The complete code is surface.c:
Content written to a surface's buffer will stay unchanged until overwritten by the client. The compositor is responsible for manipulating and displaying this content, so if, say, a portion of the client's window is obscured and then uncovered, the compositor will look after redrawing it without the client needing to do anything. This is different to the X Window model, where the client has to redraw areas 'damaged' by the windows of other clients.
On the other had, if the client redraws content in an area,
then it has to inform the compositor of which part to redraw.
The wl_surface_commit
tells the compositor
to redraw, while the wl_surface_damage
tells the compositor which areas to redraw.
In the previous example we redrew the entire window surface
and consequently damaged the entire window surface as well.
We can get an interesting effect by damaging a smaller rectangle
each time, so that the undamaged area is not redrawn by the
compositor. The result looks like