コード例 #1
0
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));
}
コード例 #2
0
static void
_cogl_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
                                 gboolean needs_mipmap)
{
  CoglTexturePixmapStereoMode stereo_mode = tex_pixmap->stereo_mode;
  if (stereo_mode == COGL_TEXTURE_PIXMAP_RIGHT)
    tex_pixmap = tex_pixmap->left;

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

      if (winsys->texture_pixmap_x11_update (tex_pixmap, stereo_mode, needs_mipmap))
        {
          _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, TRUE);
          return;
        }
    }

  /* If it didn't work then fallback to using XGetImage. This may be
     temporary */
  _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, FALSE);

  _cogl_texture_pixmap_x11_update_image_texture (tex_pixmap);
}
コード例 #3
0
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));
}
コード例 #4
0
static CoglTexture *
_cogl_texture_pixmap_x11_get_texture (CoglTexturePixmapX11 *tex_pixmap)
{
  CoglTexturePixmapX11 *original_pixmap = tex_pixmap;
  CoglTexture *tex;
  int i;
  CoglTexturePixmapStereoMode stereo_mode = tex_pixmap->stereo_mode;

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

  /* We try getting the texture twice, once without flushing the
     updates and once with. If pre_paint has been called already then
     we should have a good idea of which texture to use so we don't
     want to mess with that by ensuring the updates. However, if we
     couldn't find a texture then we'll just make a best guess by
     flushing without expecting mipmap support and try again. This
     would happen for example if an application calls
     get_gl_texture before the first paint */

  for (i = 0; i < 2; i++)
    {
      if (tex_pixmap->use_winsys_texture)
        {
          const CoglWinsysVtable *winsys =
            _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
          tex = winsys->texture_pixmap_x11_get_texture (tex_pixmap, stereo_mode);
        }
      else
        tex = tex_pixmap->tex;

      if (tex)
        return tex;

      _cogl_texture_pixmap_x11_update (original_pixmap, FALSE);
    }

  g_assert_not_reached ();

  return NULL;
}
コード例 #5
0
static void
_cogl_texture_pixmap_x11_update (CoglTexturePixmapX11 *tex_pixmap,
                                 gboolean needs_mipmap)
{
  if (tex_pixmap->winsys)
    {
      const CoglWinsysVtable *winsys =
        _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);

      if (winsys->texture_pixmap_x11_update (tex_pixmap, needs_mipmap))
        {
          _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, TRUE);
          return;
        }
    }

  /* If it didn't work then fallback to using XGetImage. This may be
     temporary */
  _cogl_texture_pixmap_x11_set_use_winsys_texture (tex_pixmap, FALSE);

  _cogl_texture_pixmap_x11_update_image_texture (tex_pixmap);
}
コード例 #6
0
void
cogl_texture_pixmap_x11_update_area (CoglHandle handle,
                                     int x,
                                     int y,
                                     int width,
                                     int height)
{
  CoglTexturePixmapX11 *tex_pixmap = COGL_TEXTURE_PIXMAP_X11 (handle);
  const CoglWinsysVtable *winsys;

  if (!cogl_is_texture_pixmap_x11 (handle))
    return;

  /* We'll queue the update for both the GLX texture and the regular
     texture because we can't determine which will be needed until we
     actually render something */

  winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
  winsys->texture_pixmap_x11_damage_notify (tex_pixmap);

  cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
                               x, y, width, height);
}
コード例 #7
0
void
cogl_texture_pixmap_x11_update_area (CoglTexturePixmapX11 *tex_pixmap,
                                     int x,
                                     int y,
                                     int width,
                                     int height)
{
  /* We'll queue the update for both the GLX texture and the regular
     texture because we can't determine which will be needed until we
     actually render something */

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

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

  cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
                               x, y, width, height);
}
コード例 #8
0
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);
}
コード例 #9
0
static void
process_damage_event (CoglTexturePixmapX11 *tex_pixmap,
                      XDamageNotifyEvent *damage_event)
{
  CoglTexture *tex = COGL_TEXTURE (tex_pixmap);
  Display *display;
  enum
{ DO_NOTHING, NEEDS_SUBTRACT, NEED_BOUNDING_BOX } handle_mode;
  const CoglWinsysVtable *winsys;

  _COGL_GET_CONTEXT (ctxt, NO_RETVAL);

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

  COGL_NOTE (TEXTURE_PIXMAP, "Damage event received for %p", tex_pixmap);

  switch (tex_pixmap->damage_report_level)
    {
    case COGL_TEXTURE_PIXMAP_X11_DAMAGE_RAW_RECTANGLES:
      /* For raw rectangles we don't need do look at the damage region
         at all because the damage area is directly given in the event
         struct and the reporting of events is not affected by
         clearing the damage region */
      handle_mode = DO_NOTHING;
      break;

    case COGL_TEXTURE_PIXMAP_X11_DAMAGE_DELTA_RECTANGLES:
    case COGL_TEXTURE_PIXMAP_X11_DAMAGE_NON_EMPTY:
      /* For delta rectangles and non empty we'll query the damage
         region for the bounding box */
      handle_mode = NEED_BOUNDING_BOX;
      break;

    case COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX:
      /* For bounding box we need to clear the damage region but we
         don't actually care what it was because the damage event
         itself contains the bounding box of the region */
      handle_mode = NEEDS_SUBTRACT;
      break;

    default:
      g_assert_not_reached ();
    }

  /* If the damage already covers the whole rectangle then we don't
     need to request the bounding box of the region because we're
     going to update the whole texture anyway. */
  if (cogl_damage_rectangle_is_whole (&tex_pixmap->damage_rect,
                                      tex->width,
                                      tex->height))
    {
      if (handle_mode != DO_NOTHING)
        XDamageSubtract (display, tex_pixmap->damage, None, None);
    }
  else if (handle_mode == NEED_BOUNDING_BOX)
    {
      XserverRegion parts;
      int r_count;
      XRectangle r_bounds;
      XRectangle *r_damage;

      /* We need to extract the damage region so we can get the
         bounding box */

      parts = XFixesCreateRegion (display, 0, 0);
      XDamageSubtract (display, tex_pixmap->damage, None, parts);
      r_damage = XFixesFetchRegionAndBounds (display,
                                             parts,
                                             &r_count,
                                             &r_bounds);
      cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
                                   r_bounds.x,
                                   r_bounds.y,
                                   r_bounds.width,
                                   r_bounds.height);
      if (r_damage)
        XFree (r_damage);

      XFixesDestroyRegion (display, parts);
    }
  else
    {
      if (handle_mode == NEEDS_SUBTRACT)
        /* We still need to subtract from the damage region but we
           don't care what the region actually was */
        XDamageSubtract (display, tex_pixmap->damage, None, None);

      cogl_damage_rectangle_union (&tex_pixmap->damage_rect,
                                   damage_event->area.x,
                                   damage_event->area.y,
                                   damage_event->area.width,
                                   damage_event->area.height);
    }

  if (tex_pixmap->winsys)
    {
      /* If we're using the texture from pixmap extension then there's no
         point in getting the region and we can just mark that the texture
         needs updating */
      winsys = _cogl_texture_pixmap_x11_get_winsys (tex_pixmap);
      winsys->texture_pixmap_x11_damage_notify (tex_pixmap);
    }
}
コード例 #10
0
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);
}