static void
clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *texture)
{
  ClutterGLXTexturePixmapPrivate *priv = texture->priv;
  GLXPixmap                       glx_pixmap = None;
  int                             attribs[7], i = 0, mipmap = 0;
  GLXFBConfig                    *fbconfig;
  Display                        *dpy;
  guint                           depth;
  Pixmap                          pixmap;
  guint				  pixmap_width, pixmap_height;
  ClutterBackendGLX              *backend_glx;
  ClutterTextureQuality           quality;

  CLUTTER_NOTE (TEXTURE, "Creating GLXPixmap");

  backend_glx = CLUTTER_BACKEND_GLX(clutter_get_default_backend ());

  dpy = clutter_x11_get_default_display ();

  if (priv->use_fallback == TRUE
      || !clutter_glx_texture_pixmap_using_extension (texture))
    goto cleanup;

  priv->use_fallback = FALSE;

  g_object_get (texture,
                "pixmap-width",  &pixmap_width,
                "pixmap-height", &pixmap_height,
                "pixmap-depth",  &depth,
                "pixmap",        &pixmap,
                NULL);

  if (!pixmap)
    {
      goto cleanup;
    }

  fbconfig = get_fbconfig_for_depth (depth);

  if (!fbconfig)
    {
      g_warning ("Could not find an FBConfig for selected pixmap");
      goto cleanup;
    }

  attribs[i++] = GLX_TEXTURE_FORMAT_EXT;

  if (depth == 24)
    {
      attribs[i++] = GLX_TEXTURE_FORMAT_RGB_EXT;
    }
  else if (depth == 32)
    {
      attribs[i++] = GLX_TEXTURE_FORMAT_RGBA_EXT;
    }
  else
    {
      g_warning ("Pixmap with depth bellow 24 are not supported");
      goto cleanup;
    }

  quality = clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture));

  if (quality == CLUTTER_TEXTURE_QUALITY_HIGH)
    mipmap = 1;

  attribs[i++] = GLX_MIPMAP_TEXTURE_EXT;
  attribs[i++] = mipmap;

  attribs[i++] = GLX_TEXTURE_TARGET_EXT;

  attribs[i++] = GLX_TEXTURE_2D_EXT;

  attribs[i++] = None;

  clutter_x11_trap_x_errors ();
  glx_pixmap = glXCreatePixmap (dpy,
                                *fbconfig,
                                pixmap,
                                attribs);
  XSync (dpy, FALSE);
  if (clutter_x11_untrap_x_errors ())
    {
      CLUTTER_NOTE (TEXTURE, "Failed to create GLXPixmap");

      /* Make sure we don't think the call actually succeeded */
      glx_pixmap = None;
    }

  g_free (fbconfig);

 cleanup:

  if (priv->glx_pixmap)
    clutter_glx_texture_pixmap_free_glx_pixmap (texture);

  if (glx_pixmap != None)
    {
      priv->glx_pixmap = glx_pixmap;

      create_cogl_texture (CLUTTER_TEXTURE (texture), pixmap_width, pixmap_height);

      CLUTTER_NOTE (TEXTURE, "Created GLXPixmap");

      return;
    }
  else
    {
      priv->use_fallback = TRUE;
      priv->glx_pixmap   = None;

      /* Some fucky logic here - we've fallen back and need to make sure
       * we realize here..
      */
      clutter_actor_realize (CLUTTER_ACTOR (texture));
    }
}
Ejemplo n.º 2
0
static void
try_create_glx_pixmap (CoglTexturePixmapX11 *tex_pixmap,
                       gboolean mipmap)
{
  Display *dpy;
  /* We have to initialize this *opaque* variable because gcc tries to
   * be too smart for its own good and warns that the variable may be
   * used uninitialized otherwise. */
  GLXFBConfig fb_config = (GLXFBConfig)0;
  int attribs[7];
  int i = 0;
  GLenum target;
  CoglXlibTrapState trap_state;

  _COGL_GET_CONTEXT (ctxt, NO_RETVAL);

  tex_pixmap->pixmap_bound = FALSE;
  tex_pixmap->glx_pixmap = None;

  if ((ctxt->winsys.feature_flags &
       COGL_WINSYS_FEATURE_TEXTURE_FROM_PIXMAP) == 0)
    return;

  dpy = _cogl_xlib_get_display ();

  if (!get_fbconfig_for_depth (tex_pixmap->depth, &fb_config,
                               &tex_pixmap->glx_can_mipmap))
    {
      COGL_NOTE (TEXTURE_PIXMAP, "No suitable FBConfig found for depth %i",
                 tex_pixmap->depth);
      return;
    }

  if (should_use_rectangle ())
    {
      target = GLX_TEXTURE_RECTANGLE_EXT;
      tex_pixmap->glx_can_mipmap = FALSE;
    }
  else
    target = GLX_TEXTURE_2D_EXT;

  if (!tex_pixmap->glx_can_mipmap)
    mipmap = FALSE;

  attribs[i++] = GLX_TEXTURE_FORMAT_EXT;

  if (tex_pixmap->depth == 24)
    attribs[i++] = GLX_TEXTURE_FORMAT_RGB_EXT;
  else if (tex_pixmap->depth == 32)
    attribs[i++] = GLX_TEXTURE_FORMAT_RGBA_EXT;
  else
    return;

  attribs[i++] = GLX_MIPMAP_TEXTURE_EXT;
  attribs[i++] = mipmap;

  attribs[i++] = GLX_TEXTURE_TARGET_EXT;
  attribs[i++] = target;

  attribs[i++] = None;

  /* We need to trap errors from glXCreatePixmap because it can
     sometimes fail during normal usage. For example on NVidia it gets
     upset if you try to create two GLXPixmaps for the same
     drawable. */

  _cogl_xlib_trap_errors (&trap_state);

  tex_pixmap->glx_pixmap = glXCreatePixmap (dpy,
                                            fb_config,
                                            tex_pixmap->pixmap,
                                            attribs);
  tex_pixmap->glx_pixmap_has_mipmap = mipmap;

  XSync (dpy, False);

  if (_cogl_xlib_untrap_errors (&trap_state))
    {
      COGL_NOTE (TEXTURE_PIXMAP, "Failed to create pixmap for %p", tex_pixmap);
      _cogl_xlib_trap_errors (&trap_state);
      glXDestroyPixmap (dpy, tex_pixmap->glx_pixmap);
      XSync (dpy, False);
      _cogl_xlib_untrap_errors (&trap_state);

      tex_pixmap->glx_pixmap = None;
    }
}