Cairo+glitz/Setup glitz with glx
Note: The glitz backend for cairo has been dropped in favor of GL surface. |
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[edit]
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[edit]
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.