Cairo+glitz/Setup glitz with glx

glitz is an OpenGL image compositing library partially designed to act as a cairo backend. Getting glitz to work can be a bit tricky especially due to the lack of documentation. Lack of good documentation and samples for Xlib/glx makes it even worse, but I find that common with anything related to Xlib. This will be a simple tutorial on how to get glitz to work. I assume you have a basic understanding of Xlib and glx before reading this.

Creating a window
First we open a X display as usual. Display* display = XOpenDisplay(NULL); unsigned int screen = DefaultScreen(display);

When creating the X window a XVisualInfo is needed. glitz requires a glitz_drawable_format_t which is related to the XVisualInfo. These two should match but I have seen cases where non matching similar formats has been used. I found it simpler to search for a suitable drawable format and extract the visual info from it than the other way around. // A template format is specified. glitz_drawable_format_t templ; templ.samples = 1; templ.depth_size = 24; templ.doublebuffer = 1; // Only the fields specified by this mask will be matched. unsigned long format_mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_DOUBLEBUFFER_MASK | GLITZ_FORMAT_DEPTH_SIZE_MASK; // glitz_glx_find_window_format searches the available formats for one matching the template. The zero in the end specifies // which format to use, zero means the first matching. It is possible to iterate over the available formats by increasing // this value until NULL is returned. glitz_drawable_format_t* dformat = glitz_glx_find_window_format (display, screen, format_mask, &templ, 0); if (!dformat) { fprintf (stderr, "Error: couldn't find window format\n"); return 1; } // As the name implies glitz_glx_get_visual_info_from_format extracts a XVisualInfo from a glitz_drawable_format_t. XVisualInfo* vinfo = glitz_glx_get_visual_info_from_format (display, screen, dformat); if (!vinfo) { fprintf (stderr, "Error: no visual info from format\n"); return 1; }

Next up is actually creating the window.

// Reference to the root-window. Window root = DefaultRootWindow(display); // Creates the colormap Colormap cmap = XCreateColormap(display, root, vinfo->visual, AllocNone); // Window attributes XSetWindowAttributes swa; swa.colormap = cmap; swa.event_mask = ExposureMask; unsigned long mask = CWColormap | CWEventMask; // Create a window using the earlier found XVisualInfo. Window window = XCreateWindow(display, root, 0, 0, 800, 600, 0, vinfo->depth, InputOutput, vinfo->visual, mask, &swa); XMapWindow(display, window); // Make it possible to "correctly" close the window. Atom wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", 0); XSetWMProtocols(display, window, &wm_delete_window, 1); XSync(display, false);

Creating a drawable surface
After the window is created we create a glitz drawable which is used to create glitz surfaces. Behind the scenes this is kind of the OpenGL context and drawable usually created when using Xlib and OpenGL. // Create the glitz drawable. If this is the first time it is called it will create the opengl context and make it the current. glitz_drawable_t* drawable = glitz_glx_create_drawable_for_window (display, screen, dformat, window, 800, 600); // A glitz_format_t must be used when creating a surface. Not that this is not the same format as glitz_drawable_format_t used earlier. // Similar to before a template is created and a matching format is searched for. glitz_format_t *format, templ; glitz_drawable_buffer_t buffer; templ.color = dformat->color; format = glitz_find_format (drawable, 	GLITZ_FORMAT_FOURCC_MASK    | 	GLITZ_FORMAT_RED_SIZE_MASK   | 	GLITZ_FORMAT_GREEN_SIZE_MASK | 	GLITZ_FORMAT_BLUE_SIZE_MASK  | 	GLITZ_FORMAT_ALPHA_SIZE_MASK, 	&templ, 	0 ); if (!format) { fprintf (stderr, "Error: couldn't find surface format\n"); return NULL; } // Create a surface with above format. glitz_surface_t* surface = glitz_surface_create (drawable, format, 800, 600, 0, NULL); if (!surface) { fprintf (stderr, "Error: couldn't create glitz surface\n"); return NULL; } // The surface buffer must be bound to the drawable. The surface buffer is the buffer which rendering // calls is made to. If a doublebuffered surface is selected the backbuffer will used. if (dformat->doublebuffer) { buffer = GLITZ_DRAWABLE_BUFFER_BACK_COLOR; } else { buffer = GLITZ_DRAWABLE_BUFFER_FRONT_COLOR; } // Bind the surface buffer to the drawable. glitz_surface_attach (surface, drawable, buffer);

Next part: cairo+glitz/Setup cairo.