static void
_cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
{
  _COGL_GET_CONTEXT (ctxt, NO_RETVAL);

  set_damage_object_internal (ctxt, tex_pixmap, 0, 0);

  if (tex_pixmap->image)
    XDestroyImage (tex_pixmap->image);

  if (tex_pixmap->shm_info.shmid != -1)
    {
      XShmDetach (cogl_xlib_get_display (), &tex_pixmap->shm_info);
      shmdt (tex_pixmap->shm_info.shmaddr);
      shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0);
    }

  if (tex_pixmap->tex)
    cogl_handle_unref (tex_pixmap->tex);

  if (tex_pixmap->winsys)
    {
      const CoglWinsysVtable *winsys =
        _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
      winsys->texture_pixmap_x11_free (tex_pixmap);
    }

  /* Chain up */
  _cogl_texture_free (COGL_TEXTURE (tex_pixmap));
}
static void
_cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
{
  set_damage_object_internal (tex_pixmap, 0, 0);

  if (tex_pixmap->image)
    XDestroyImage (tex_pixmap->image);

  if (tex_pixmap->shm_info.shmid != -1)
    {
      XShmDetach (_cogl_xlib_get_display (), &tex_pixmap->shm_info);
      shmdt (tex_pixmap->shm_info.shmaddr);
      shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0);
    }

  if (tex_pixmap->tex)
    cogl_handle_unref (tex_pixmap->tex);

#ifdef COGL_HAS_GLX_SUPPORT
  _cogl_texture_pixmap_x11_free_glx_pixmap (tex_pixmap);

  if (tex_pixmap->glx_tex)
    cogl_handle_unref (tex_pixmap->glx_tex);
#endif

  /* Chain up */
  _cogl_texture_free (COGL_TEXTURE (tex_pixmap));
}
void
cogl_texture_pixmap_x11_set_damage_object (CoglTexturePixmapX11 *tex_pixmap,
                                           uint32_t damage,
                                           CoglTexturePixmapX11ReportLevel
                                                                  report_level)
{
  int damage_base;

  _COGL_GET_CONTEXT (ctxt, NO_RETVAL);

  g_return_if_fail (tex_pixmap->stereo_mode != COGL_TEXTURE_PIXMAP_RIGHT);

  damage_base = _cogl_xlib_get_damage_base ();
  if (damage_base >= 0)
    set_damage_object_internal (ctxt, tex_pixmap, damage, report_level);
}
void
cogl_texture_pixmap_x11_set_damage_object (CoglHandle handle,
                                           guint32 damage,
                                           CoglTexturePixmapX11ReportLevel
                                                                  report_level)
{
  CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (handle);

  _COGL_GET_CONTEXT (ctxt, NO_RETVAL);

  if (!cogl_is_texture_pixmap_x11 (tex_pixmap))
    return;

  if (ctxt->winsys.damage_base >= 0)
    set_damage_object_internal (tex_pixmap, damage, report_level);
}
static void
_cogl_texture_pixmap_x11_free (CoglTexturePixmapX11 *tex_pixmap)
{
  Display *display;

  _COGL_GET_CONTEXT (ctxt, NO_RETVAL);

  if (tex_pixmap->stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT)
    {
      cogl_object_unref (tex_pixmap->left);

      /* Chain up */
      _cogl_texture_free (COGL_TEXTURE (tex_pixmap));

      return;
    }

  display = cogl_xlib_renderer_get_display (ctxt->display->renderer);

  set_damage_object_internal (ctxt, tex_pixmap, 0, 0);

  if (tex_pixmap->image)
    XDestroyImage (tex_pixmap->image);

  if (tex_pixmap->shm_info.shmid != -1)
    {
      XShmDetach (display, &tex_pixmap->shm_info);
      shmdt (tex_pixmap->shm_info.shmaddr);
      shmctl (tex_pixmap->shm_info.shmid, IPC_RMID, 0);
    }

  if (tex_pixmap->tex)
    cogl_object_unref (tex_pixmap->tex);

  if (tex_pixmap->winsys)
    {
      const CoglWinsysVtable *winsys =
        _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
      winsys->texture_pixmap_x11_free (tex_pixmap);
    }

  /* Chain up */
  _cogl_texture_free (COGL_TEXTURE (tex_pixmap));
}
static CoglTexturePixmapX11 *
_cogl_texture_pixmap_x11_new (CoglContext *ctxt,
                              uint32_t pixmap,
                              gboolean automatic_updates,
                              CoglTexturePixmapStereoMode stereo_mode,
                              CoglError **error)
{
  CoglTexturePixmapX11 *tex_pixmap = g_new (CoglTexturePixmapX11, 1);
  Display *display = cogl_xlib_renderer_get_display (ctxt->display->renderer);
  Window pixmap_root_window;
  int pixmap_x, pixmap_y;
  unsigned int pixmap_width, pixmap_height;
  unsigned int pixmap_border_width;
  CoglPixelFormat internal_format;
  CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
  XWindowAttributes window_attributes;
  int damage_base;
  const CoglWinsysVtable *winsys;

  if (!XGetGeometry (display, pixmap, &pixmap_root_window,
                     &pixmap_x, &pixmap_y,
                     &pixmap_width, &pixmap_height,
                     &pixmap_border_width, &tex_pixmap->depth))
    {
      g_free (tex_pixmap);
      _cogl_set_error (error,
                   COGL_TEXTURE_PIXMAP_X11_ERROR,
                   COGL_TEXTURE_PIXMAP_X11_ERROR_X11,
                   "Unable to query pixmap size");
      return NULL;
    }

  /* Note: the detailed pixel layout doesn't matter here, we are just
   * interested in RGB vs RGBA... */
  internal_format = (tex_pixmap->depth >= 32
                     ? COGL_PIXEL_FORMAT_RGBA_8888_PRE
                     : COGL_PIXEL_FORMAT_RGB_888);

  _cogl_texture_init (tex, ctxt, pixmap_width, pixmap_height,
                      internal_format,
                      NULL, /* no loader */
                      &cogl_texture_pixmap_x11_vtable);

  tex_pixmap->pixmap = pixmap;
  tex_pixmap->stereo_mode = stereo_mode;
  tex_pixmap->left = NULL;
  tex_pixmap->image = NULL;
  tex_pixmap->shm_info.shmid = -1;
  tex_pixmap->tex = NULL;
  tex_pixmap->damage_owned = FALSE;
  tex_pixmap->damage = 0;

  /* We need a visual to use for shared memory images so we'll query
     it from the pixmap's root window */
  if (!XGetWindowAttributes (display, pixmap_root_window, &window_attributes))
    {
      g_free (tex_pixmap);
      _cogl_set_error (error,
                   COGL_TEXTURE_PIXMAP_X11_ERROR,
                   COGL_TEXTURE_PIXMAP_X11_ERROR_X11,
                   "Unable to query root window attributes");
      return NULL;
    }

  tex_pixmap->visual = window_attributes.visual;

  /* If automatic updates are requested and the Xlib connection
     supports damage events then we'll register a damage object on the
     pixmap */
  damage_base = _cogl_xlib_get_damage_base ();
  if (automatic_updates && damage_base >= 0)
    {
      Damage damage = XDamageCreate (display,
                                     pixmap,
                                     XDamageReportBoundingBox);
      set_damage_object_internal (ctxt,
                                  tex_pixmap,
                                  damage,
                                  COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX);
      tex_pixmap->damage_owned = TRUE;
    }

  /* Assume the entire pixmap is damaged to begin with */
  tex_pixmap->damage_rect.x1 = 0;
  tex_pixmap->damage_rect.x2 = pixmap_width;
  tex_pixmap->damage_rect.y1 = 0;
  tex_pixmap->damage_rect.y2 = pixmap_height;

  winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
  if (winsys->texture_pixmap_x11_create)
    {
      tex_pixmap->use_winsys_texture =
        winsys->texture_pixmap_x11_create (tex_pixmap);
    }
  else
    tex_pixmap->use_winsys_texture = FALSE;

  if (!tex_pixmap->use_winsys_texture)
    tex_pixmap->winsys = NULL;

  _cogl_texture_set_allocated (tex, internal_format,
                               pixmap_width, pixmap_height);

  return _cogl_texture_pixmap_x11_object_new (tex_pixmap);
}
CoglHandle
cogl_texture_pixmap_x11_new (guint32 pixmap,
                             gboolean automatic_updates)
{
  CoglTexturePixmapX11 *tex_pixmap = g_new (CoglTexturePixmapX11, 1);
  Display *display = cogl_xlib_get_display ();
  Window pixmap_root_window;
  int pixmap_x, pixmap_y;
  unsigned int pixmap_border_width;
  CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
  XWindowAttributes window_attributes;
  int damage_base;
  const CoglWinsysVtable *winsys;

  _COGL_GET_CONTEXT (ctxt, COGL_INVALID_HANDLE);

  _cogl_texture_init (tex, &cogl_texture_pixmap_x11_vtable);

  tex_pixmap->pixmap = pixmap;
  tex_pixmap->image = NULL;
  tex_pixmap->shm_info.shmid = -1;
  tex_pixmap->tex = COGL_INVALID_HANDLE;
  tex_pixmap->damage_owned = FALSE;
  tex_pixmap->damage = 0;

  if (!XGetGeometry (display, pixmap, &pixmap_root_window,
                     &pixmap_x, &pixmap_y,
                     &tex_pixmap->width, &tex_pixmap->height,
                     &pixmap_border_width, &tex_pixmap->depth))
    {
      g_free (tex_pixmap);
      g_warning ("Unable to query pixmap size");
      return COGL_INVALID_HANDLE;
    }

  /* We need a visual to use for shared memory images so we'll query
     it from the pixmap's root window */
  if (!XGetWindowAttributes (display, pixmap_root_window, &window_attributes))
    {
      g_free (tex_pixmap);
      g_warning ("Unable to query root window attributes");
      return COGL_INVALID_HANDLE;
    }
  tex_pixmap->visual = window_attributes.visual;

  /* If automatic updates are requested and the Xlib connection
     supports damage events then we'll register a damage object on the
     pixmap */
  damage_base = _cogl_xlib_get_damage_base ();
  if (automatic_updates && damage_base >= 0)
    {
      Damage damage = XDamageCreate (display,
                                     pixmap,
                                     XDamageReportBoundingBox);
      set_damage_object_internal (ctxt,
                                  tex_pixmap,
                                  damage,
                                  COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX);
      tex_pixmap->damage_owned = TRUE;
    }

  /* Assume the entire pixmap is damaged to begin with */
  tex_pixmap->damage_rect.x1 = 0;
  tex_pixmap->damage_rect.x2 = tex_pixmap->width;
  tex_pixmap->damage_rect.y1 = 0;
  tex_pixmap->damage_rect.y2 = tex_pixmap->height;

  winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
  if (winsys->texture_pixmap_x11_create)
    {
      tex_pixmap->use_winsys_texture =
        winsys->texture_pixmap_x11_create (tex_pixmap);
    }
  else
    tex_pixmap->use_winsys_texture = FALSE;

  if (!tex_pixmap->use_winsys_texture)
    tex_pixmap->winsys = NULL;

  return _cogl_texture_pixmap_x11_handle_new (tex_pixmap);
}