Cairo+glitz/Setup glitz with glx

From Sidvind
Jump to: navigation, search
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.

Code:

  1.  Display* display = XOpenDisplay(NULL);
  2.  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.

Code:

  1.  // A template format is specified.
  2.  glitz_drawable_format_t templ;
  3.  templ.samples = 1;
  4.  templ.depth_size = 24;
  5.  templ.doublebuffer = 1;
  6.  
  7.  // Only the fields specified by this mask will be matched.
  8.  unsigned long format_mask = GLITZ_FORMAT_SAMPLES_MASK | GLITZ_FORMAT_DOUBLEBUFFER_MASK | GLITZ_FORMAT_DEPTH_SIZE_MASK;
  9.  
  10.  // glitz_glx_find_window_format searches the available formats for one matching the template. The zero in the end specifies
  11.  // which format to use, zero means the first matching. It is possible to iterate over the available formats by increasing
  12.  // this value until NULL is returned.
  13.  glitz_drawable_format_t* dformat = glitz_glx_find_window_format (display, screen, format_mask, &templ, 0);
  14.  if (!dformat) {
  15.         fprintf (stderr, "Error: couldn't find window format\n");
  16.         return 1;
  17.  }
  18.  
  19.  // As the name implies glitz_glx_get_visual_info_from_format extracts a XVisualInfo from a glitz_drawable_format_t.
  20.  XVisualInfo* vinfo = glitz_glx_get_visual_info_from_format (display, screen, dformat);
  21.  if (!vinfo) {
  22.         fprintf (stderr, "Error: no visual info from format\n");
  23.         return 1;
  24.  }

Next up is actually creating the window.

Code:

  1.  // Reference to the root-window.
  2.  Window root = DefaultRootWindow(display);
  3.  
  4.  // Creates the colormap
  5.  Colormap cmap = XCreateColormap(display, root, vinfo->visual, AllocNone);
  6.  
  7.  // Window attributes
  8.  XSetWindowAttributes swa;
  9.  swa.colormap = cmap;
  10.  swa.event_mask = ExposureMask;
  11.  unsigned long mask = CWColormap | CWEventMask;
  12.  
  13.  // Create a window using the earlier found XVisualInfo.
  14.  Window window = XCreateWindow(display, root, 0, 0, 800, 600, 0, vinfo->depth, InputOutput, vinfo->visual, mask, &swa);
  15.  XMapWindow(display, window);
  16.  
  17.  // Make it possible to "correctly" close the window.
  18.  Atom wm_delete_window = XInternAtom(display, "WM_DELETE_WINDOW", 0);
  19.  XSetWMProtocols(display, window, &wm_delete_window, 1);
  20.  
  21.  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.

Code:

  1.  // Create the glitz drawable. If this is the first time it is called it will create the opengl context and make it the current.
  2.  glitz_drawable_t* drawable = glitz_glx_create_drawable_for_window (display, screen, dformat, window, 800, 600);
  3.  
  4.  // 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.
  5.  // Similar to before a template is created and a matching format is searched for.
  6.  glitz_format_t *format, templ;
  7.  glitz_drawable_buffer_t buffer;
  8.  
  9.  templ.color = dformat->color;
  10.  format = glitz_find_format (drawable,
  11.         GLITZ_FORMAT_FOURCC_MASK     |
  12.         GLITZ_FORMAT_RED_SIZE_MASK   |
  13.         GLITZ_FORMAT_GREEN_SIZE_MASK |
  14.         GLITZ_FORMAT_BLUE_SIZE_MASK  |
  15.         GLITZ_FORMAT_ALPHA_SIZE_MASK,
  16.         &templ,
  17.         0
  18.  );
  19.  
  20.  if (!format) {
  21.         fprintf (stderr, "Error: couldn't find surface format\n");
  22.         return NULL;
  23.  }
  24.  
  25.  // Create a surface with above format.
  26.  glitz_surface_t* surface = glitz_surface_create (drawable, format, 800, 600, 0, NULL);
  27.  if (!surface) {
  28.         fprintf (stderr, "Error: couldn't create glitz surface\n");
  29.         return NULL;
  30.  }
  31.  
  32.  // The surface buffer must be bound to the drawable. The surface buffer is the buffer which rendering
  33.  // calls is made to. If a doublebuffered surface is selected the backbuffer will used.
  34.  if (dformat->doublebuffer) {
  35.         buffer = GLITZ_DRAWABLE_BUFFER_BACK_COLOR;
  36.  } else {
  37.         buffer = GLITZ_DRAWABLE_BUFFER_FRONT_COLOR;
  38.  }
  39.  
  40.  // Bind the surface buffer to the drawable.
  41.  glitz_surface_attach (surface, drawable, buffer);

Next part: cairo+glitz/Setup cairo.