clutter-{glx,x11}-texture-pixmap: Use CoglTexturePixmapX11
The pixmap handling of both of the texture pixmap actors in Clutter is now removed and instead it just creates a CoglTexturePixmapX11. Both actors are now equivalent so there is no need to choose between the two.
This commit is contained in:
parent
a197baa533
commit
5d860a9978
@ -6,8 +6,10 @@
|
|||||||
* Authored By Johan Bilien <johan.bilien@nokia.com>
|
* Authored By Johan Bilien <johan.bilien@nokia.com>
|
||||||
* Matthew Allum <mallum@o-hand.com>
|
* Matthew Allum <mallum@o-hand.com>
|
||||||
* Robert Bragg <bob@o-hand.com>
|
* Robert Bragg <bob@o-hand.com>
|
||||||
|
* Neil Roberts <neil@linux.intel.com>
|
||||||
*
|
*
|
||||||
* Copyright (C) 2007 OpenedHand
|
* Copyright (C) 2007 OpenedHand
|
||||||
|
* Copyright (C) 2010 Intel Corporation.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -25,11 +27,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* TODO:
|
|
||||||
* - Automagically handle named pixmaps, and window resizes (i.e
|
|
||||||
* essentially handle window id's being passed in) ?
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:clutter-glx-texture-pixmap
|
* SECTION:clutter-glx-texture-pixmap
|
||||||
* @short_description: A texture which displays the content of an X Pixmap.
|
* @short_description: A texture which displays the content of an X Pixmap.
|
||||||
@ -38,15 +35,12 @@
|
|||||||
* X Pixmap as a ClutterActor. Used together with the X Composite extension,
|
* X Pixmap as a ClutterActor. Used together with the X Composite extension,
|
||||||
* it allows to display the content of X Windows inside Clutter.
|
* it allows to display the content of X Windows inside Clutter.
|
||||||
*
|
*
|
||||||
* The class requires the GLX_EXT_texture_from_pixmap OpenGL extension
|
* This class used to be necessary to use the
|
||||||
* (http://people.freedesktop.org/~davidr/GLX_EXT_texture_from_pixmap.txt)
|
* GLX_EXT_texture_from_pixmap extension to get fast texture
|
||||||
*
|
* updates. However since Clutter 1.4 the handling of this extension
|
||||||
* The GL_ARB_texture_non_power_of_two extension will be used if it is
|
* has moved down to Cogl. ClutterX11TexturePixmap and
|
||||||
* available. Otherwise it will try to use the
|
* ClutterGLXTexturePixmap are now equivalent and either one of them
|
||||||
* GL_ARB_texture_rectangle extension. If both are available you can
|
* may use the extension if it is possible.
|
||||||
* force it to prefer the rectangle extension by setting the
|
|
||||||
* CLUTTER_PIXMAP_TEXTURE_RECTANGLE to 'force'. To prevent it ever
|
|
||||||
* using the rectangle extension you can set it to 'disable'.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@ -59,802 +53,21 @@
|
|||||||
|
|
||||||
#include "../x11/clutter-x11-texture-pixmap.h"
|
#include "../x11/clutter-x11-texture-pixmap.h"
|
||||||
#include "clutter-glx-texture-pixmap.h"
|
#include "clutter-glx-texture-pixmap.h"
|
||||||
#include "clutter-glx.h"
|
#include "cogl/winsys/cogl-texture-pixmap-x11.h"
|
||||||
#include "clutter-backend-glx.h"
|
|
||||||
|
|
||||||
#include "../clutter-util.h"
|
|
||||||
#include "../clutter-debug.h"
|
|
||||||
#include "../clutter-private.h"
|
|
||||||
|
|
||||||
#include "cogl/cogl.h"
|
|
||||||
#include "cogl/cogl-material-private.h"
|
|
||||||
|
|
||||||
typedef void (*BindTexImage) (Display *display,
|
|
||||||
GLXDrawable drawable,
|
|
||||||
int buffer,
|
|
||||||
int *attribList);
|
|
||||||
typedef void (*ReleaseTexImage) (Display *display,
|
|
||||||
GLXDrawable drawable,
|
|
||||||
int buffer);
|
|
||||||
|
|
||||||
typedef void (*GenerateMipmap) (GLenum target);
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
CLUTTER_GLX_RECTANGLE_DISALLOW,
|
|
||||||
CLUTTER_GLX_RECTANGLE_ALLOW,
|
|
||||||
CLUTTER_GLX_RECTANGLE_FORCE
|
|
||||||
} RectangleState;
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
PROP_0,
|
|
||||||
PROP_AUTO_REDRAW,
|
|
||||||
};
|
|
||||||
|
|
||||||
static BindTexImage _gl_bind_tex_image = NULL;
|
|
||||||
static ReleaseTexImage _gl_release_tex_image = NULL;
|
|
||||||
static GenerateMipmap _gl_generate_mipmap = NULL;
|
|
||||||
static gboolean _have_tex_from_pixmap_ext = FALSE;
|
|
||||||
static gboolean _ext_check_done = FALSE;
|
|
||||||
static gboolean _have_tex_rectangle = FALSE;
|
|
||||||
static RectangleState _rectangle_state = CLUTTER_GLX_RECTANGLE_ALLOW;
|
|
||||||
|
|
||||||
struct _ClutterGLXTexturePixmapPrivate
|
|
||||||
{
|
|
||||||
GLXPixmap glx_pixmap;
|
|
||||||
|
|
||||||
gboolean use_fallback;
|
|
||||||
|
|
||||||
gboolean bound;
|
|
||||||
gint can_mipmap;
|
|
||||||
gboolean mipmap_generate_queued;
|
|
||||||
|
|
||||||
gboolean bind_tex_image_queued;
|
|
||||||
|
|
||||||
gboolean using_rectangle;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_glx_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
|
|
||||||
gint x,
|
|
||||||
gint y,
|
|
||||||
gint width,
|
|
||||||
gint height);
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_glx_texture_pixmap_create_glx_pixmap (ClutterGLXTexturePixmap *tex);
|
|
||||||
|
|
||||||
static ClutterX11TexturePixmapClass *parent_class = NULL;
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (ClutterGLXTexturePixmap, \
|
G_DEFINE_TYPE (ClutterGLXTexturePixmap, \
|
||||||
clutter_glx_texture_pixmap, \
|
clutter_glx_texture_pixmap, \
|
||||||
CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
|
CLUTTER_X11_TYPE_TEXTURE_PIXMAP);
|
||||||
|
|
||||||
static void
|
|
||||||
bind_texture (ClutterGLXTexturePixmap *tex)
|
|
||||||
{
|
|
||||||
GLuint handle = 0;
|
|
||||||
GLenum target = 0;
|
|
||||||
CoglHandle cogl_tex =
|
|
||||||
clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (tex));
|
|
||||||
|
|
||||||
if (!cogl_texture_get_gl_texture (cogl_tex, &handle, &target))
|
|
||||||
g_warning ("Failed to pluck out GL handle from cogl texture to bind");
|
|
||||||
|
|
||||||
if (tex->priv->using_rectangle)
|
|
||||||
_cogl_bind_gl_texture_transient (target, handle, TRUE);
|
|
||||||
else
|
|
||||||
_cogl_bind_gl_texture_transient (target, handle, FALSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
release_tex_image (ClutterGLXTexturePixmap *texture)
|
|
||||||
{
|
|
||||||
ClutterGLXTexturePixmapPrivate *priv = texture->priv;
|
|
||||||
Display *dpy;
|
|
||||||
|
|
||||||
if (!priv->glx_pixmap || !priv->bound)
|
|
||||||
return;
|
|
||||||
|
|
||||||
dpy = clutter_x11_get_default_display ();
|
|
||||||
|
|
||||||
bind_texture (texture);
|
|
||||||
|
|
||||||
clutter_x11_trap_x_errors ();
|
|
||||||
|
|
||||||
(_gl_release_tex_image) (dpy,
|
|
||||||
priv->glx_pixmap,
|
|
||||||
GLX_FRONT_LEFT_EXT);
|
|
||||||
|
|
||||||
XSync (dpy, FALSE);
|
|
||||||
|
|
||||||
if (clutter_x11_untrap_x_errors ())
|
|
||||||
CLUTTER_NOTE (TEXTURE, "Failed to release?");
|
|
||||||
|
|
||||||
CLUTTER_NOTE (TEXTURE, "Destroyed pxm: %li", priv->glx_pixmap);
|
|
||||||
|
|
||||||
priv->bound = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
on_glx_texture_pixmap_pre_paint (ClutterGLXTexturePixmap *texture,
|
|
||||||
gpointer user_data)
|
|
||||||
{
|
|
||||||
ClutterGLXTexturePixmapPrivate *priv = texture->priv;
|
|
||||||
gboolean tex_bound = FALSE;
|
|
||||||
Display *dpy = clutter_x11_get_default_display();
|
|
||||||
|
|
||||||
if (priv->bind_tex_image_queued)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (TEXTURE, "Really updating via GLX");
|
|
||||||
|
|
||||||
bind_texture (CLUTTER_GLX_TEXTURE_PIXMAP (texture));
|
|
||||||
tex_bound = TRUE;
|
|
||||||
|
|
||||||
clutter_x11_trap_x_errors ();
|
|
||||||
|
|
||||||
(_gl_bind_tex_image) (dpy,
|
|
||||||
priv->glx_pixmap,
|
|
||||||
GLX_FRONT_LEFT_EXT,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
XSync (dpy, FALSE);
|
|
||||||
|
|
||||||
/* Note above fires X error for non name pixmaps - but
|
|
||||||
* things still seem to work - i.e pixmap updated
|
|
||||||
*/
|
|
||||||
if (clutter_x11_untrap_x_errors ())
|
|
||||||
CLUTTER_NOTE (TEXTURE, "Update bind_tex_image failed");
|
|
||||||
|
|
||||||
priv->bound = TRUE;
|
|
||||||
|
|
||||||
if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture))
|
|
||||||
== CLUTTER_TEXTURE_QUALITY_HIGH)
|
|
||||||
{
|
|
||||||
priv->mipmap_generate_queued++;
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->bind_tex_image_queued = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_gl_generate_mipmap &&
|
|
||||||
priv->can_mipmap &&
|
|
||||||
priv->mipmap_generate_queued)
|
|
||||||
{
|
|
||||||
GLuint handle = 0;
|
|
||||||
GLenum target = 0;
|
|
||||||
CoglHandle cogl_tex;
|
|
||||||
cogl_tex = clutter_texture_get_cogl_texture
|
|
||||||
(CLUTTER_TEXTURE(texture));
|
|
||||||
|
|
||||||
bind_texture (texture);
|
|
||||||
tex_bound = TRUE;
|
|
||||||
|
|
||||||
cogl_texture_get_gl_texture (cogl_tex, &handle, &target);
|
|
||||||
|
|
||||||
_gl_generate_mipmap (target);
|
|
||||||
}
|
|
||||||
priv->mipmap_generate_queued = FALSE;
|
|
||||||
|
|
||||||
/* Disable mipmaps if we can't support them */
|
|
||||||
if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture))
|
|
||||||
== CLUTTER_TEXTURE_QUALITY_HIGH
|
|
||||||
&& !priv->can_mipmap)
|
|
||||||
{
|
|
||||||
CoglHandle material
|
|
||||||
= clutter_texture_get_cogl_material (CLUTTER_TEXTURE (texture));
|
|
||||||
|
|
||||||
cogl_material_set_layer_filters (material, 0,
|
|
||||||
COGL_MATERIAL_FILTER_LINEAR,
|
|
||||||
COGL_MATERIAL_FILTER_LINEAR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_glx_texture_pixmap_init (ClutterGLXTexturePixmap *self)
|
clutter_glx_texture_pixmap_init (ClutterGLXTexturePixmap *self)
|
||||||
{
|
{
|
||||||
ClutterGLXTexturePixmapPrivate *priv;
|
|
||||||
|
|
||||||
priv = self->priv =
|
|
||||||
G_TYPE_INSTANCE_GET_PRIVATE (self,
|
|
||||||
CLUTTER_GLX_TYPE_TEXTURE_PIXMAP,
|
|
||||||
ClutterGLXTexturePixmapPrivate);
|
|
||||||
|
|
||||||
g_signal_connect (CLUTTER_ACTOR(self),
|
|
||||||
"paint", G_CALLBACK (on_glx_texture_pixmap_pre_paint),
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (_ext_check_done == FALSE)
|
|
||||||
{
|
|
||||||
const char *gl_extensions = NULL;
|
|
||||||
const gchar *glx_extensions = NULL;
|
|
||||||
const char *rect_env;
|
|
||||||
|
|
||||||
glx_extensions =
|
|
||||||
glXQueryExtensionsString (clutter_x11_get_default_display (),
|
|
||||||
clutter_x11_get_default_screen ());
|
|
||||||
|
|
||||||
/* Check for the texture from pixmap extension */
|
|
||||||
if (_cogl_check_extension ("GLX_EXT_texture_from_pixmap",
|
|
||||||
glx_extensions))
|
|
||||||
{
|
|
||||||
_gl_bind_tex_image =
|
|
||||||
(BindTexImage)cogl_get_proc_address ("glXBindTexImageEXT");
|
|
||||||
_gl_release_tex_image =
|
|
||||||
(ReleaseTexImage)cogl_get_proc_address ("glXReleaseTexImageEXT");
|
|
||||||
|
|
||||||
if (_gl_bind_tex_image && _gl_release_tex_image)
|
|
||||||
_have_tex_from_pixmap_ext = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_gl_generate_mipmap =
|
|
||||||
(GenerateMipmap)cogl_get_proc_address ("glGenerateMipmapEXT");
|
|
||||||
|
|
||||||
gl_extensions = (char *) glGetString (GL_EXTENSIONS);
|
|
||||||
_have_tex_rectangle = _cogl_check_extension ("GL_ARB_texture_rectangle",
|
|
||||||
gl_extensions);
|
|
||||||
|
|
||||||
if ((rect_env = g_getenv ("CLUTTER_PIXMAP_TEXTURE_RECTANGLE")))
|
|
||||||
{
|
|
||||||
if (g_ascii_strcasecmp (rect_env, "force") == 0)
|
|
||||||
_rectangle_state = CLUTTER_GLX_RECTANGLE_FORCE;
|
|
||||||
else if (g_ascii_strcasecmp (rect_env, "disable") == 0)
|
|
||||||
_rectangle_state = CLUTTER_GLX_RECTANGLE_DISALLOW;
|
|
||||||
else if (rect_env[0])
|
|
||||||
g_warning ("Unknown value for CLUTTER_PIXMAP_TEXTURE_RECTANGLE, "
|
|
||||||
"should be 'force' or 'disable'");
|
|
||||||
}
|
|
||||||
|
|
||||||
_ext_check_done = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_glx_texture_pixmap_free_rectangle (ClutterGLXTexturePixmap *texture)
|
|
||||||
{
|
|
||||||
ClutterGLXTexturePixmapPrivate *priv = texture->priv;
|
|
||||||
CoglHandle cogl_tex;
|
|
||||||
|
|
||||||
/* Cogl won't free the GL texture resource if it was created with
|
|
||||||
new_from_foreign so we need to free it manually */
|
|
||||||
if (priv->using_rectangle)
|
|
||||||
{
|
|
||||||
cogl_tex = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (texture));
|
|
||||||
|
|
||||||
if (cogl_tex != COGL_INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
GLuint gl_handle;
|
|
||||||
GLenum gl_target;
|
|
||||||
|
|
||||||
cogl_texture_get_gl_texture (cogl_tex, &gl_handle, &gl_target);
|
|
||||||
|
|
||||||
if (gl_target == GL_TEXTURE_RECTANGLE_ARB)
|
|
||||||
glDeleteTextures (1, &gl_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
priv->using_rectangle = FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_glx_texture_pixmap_dispose (GObject *object)
|
|
||||||
{
|
|
||||||
ClutterGLXTexturePixmap *texture = CLUTTER_GLX_TEXTURE_PIXMAP (object);
|
|
||||||
ClutterGLXTexturePixmapPrivate *priv = texture->priv;
|
|
||||||
|
|
||||||
clutter_glx_texture_pixmap_free_rectangle (texture);
|
|
||||||
|
|
||||||
if (priv->glx_pixmap != None)
|
|
||||||
{
|
|
||||||
clutter_x11_trap_x_errors ();
|
|
||||||
|
|
||||||
glXDestroyPixmap (clutter_x11_get_default_display(),
|
|
||||||
priv->glx_pixmap);
|
|
||||||
XSync (clutter_x11_get_default_display(), FALSE);
|
|
||||||
|
|
||||||
clutter_x11_untrap_x_errors ();
|
|
||||||
|
|
||||||
priv->glx_pixmap = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_glx_texture_pixmap_parent_class)->dispose (object);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_glx_texture_pixmap_notify (GObject *object, GParamSpec *pspec)
|
|
||||||
{
|
|
||||||
if (g_str_equal (pspec->name, "pixmap"))
|
|
||||||
{
|
|
||||||
ClutterGLXTexturePixmap *texture = CLUTTER_GLX_TEXTURE_PIXMAP (object);
|
|
||||||
if (CLUTTER_ACTOR_IS_REALIZED (texture))
|
|
||||||
clutter_glx_texture_pixmap_create_glx_pixmap (texture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
should_use_rectangle (void)
|
|
||||||
{
|
|
||||||
/* Use the rectangle only if it is available and either:
|
|
||||||
|
|
||||||
the CLUTTER_PIXMAP_TEXTURE_RECTANGLE environment variable is
|
|
||||||
set to 'force'
|
|
||||||
|
|
||||||
*or*
|
|
||||||
|
|
||||||
the env var is set to 'allow' (which is the default) and NPOTs
|
|
||||||
textures are not available */
|
|
||||||
return _have_tex_rectangle
|
|
||||||
&& ((_rectangle_state == CLUTTER_GLX_RECTANGLE_ALLOW
|
|
||||||
&& !clutter_feature_available (CLUTTER_FEATURE_TEXTURE_NPOT))
|
|
||||||
|| _rectangle_state == CLUTTER_GLX_RECTANGLE_FORCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
create_cogl_texture (ClutterTexture *texture,
|
|
||||||
guint width,
|
|
||||||
guint height)
|
|
||||||
{
|
|
||||||
ClutterGLXTexturePixmap *texture_glx = CLUTTER_GLX_TEXTURE_PIXMAP (texture);
|
|
||||||
ClutterGLXTexturePixmapPrivate *priv = texture_glx->priv;
|
|
||||||
CoglHandle handle;
|
|
||||||
gboolean using_rectangle;
|
|
||||||
GLint gl_format;
|
|
||||||
CoglPixelFormat cogl_format = COGL_PIXEL_FORMAT_RGBA_8888;
|
|
||||||
guint depth;
|
|
||||||
|
|
||||||
g_object_get (G_OBJECT (texture_glx), "pixmap-depth", &depth, NULL);
|
|
||||||
if (depth == 32)
|
|
||||||
{
|
|
||||||
gl_format = GL_RGBA;
|
|
||||||
cogl_format = COGL_PIXEL_FORMAT_RGBA_8888;
|
|
||||||
}
|
|
||||||
else if (depth == 24)
|
|
||||||
{
|
|
||||||
gl_format = GL_RGB;
|
|
||||||
cogl_format = COGL_PIXEL_FORMAT_RGB_888;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_critical ("Can't create a TFP cogl texture for pixmap with depth < 24");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We want to use the GL_ARB_texture_rectangle extension on some
|
|
||||||
chipsets because GL_ARB_texture_non_power_of_two is not always
|
|
||||||
supported or might be buggy */
|
|
||||||
if (should_use_rectangle ())
|
|
||||||
{
|
|
||||||
GLuint tex = 0;
|
|
||||||
|
|
||||||
using_rectangle = TRUE;
|
|
||||||
|
|
||||||
glGenTextures (1, &tex);
|
|
||||||
_cogl_bind_gl_texture_transient (GL_TEXTURE_RECTANGLE_ARB, tex, TRUE);
|
|
||||||
glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0,
|
|
||||||
gl_format, width, height,
|
|
||||||
0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
|
|
||||||
handle = cogl_texture_new_from_foreign (tex, GL_TEXTURE_RECTANGLE_ARB,
|
|
||||||
width, height,
|
|
||||||
0, 0,
|
|
||||||
cogl_format | COGL_BGR_BIT |
|
|
||||||
COGL_PREMULT_BIT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
handle
|
|
||||||
= cogl_texture_new_with_size (width, height,
|
|
||||||
COGL_TEXTURE_NO_SLICING,
|
|
||||||
cogl_format | COGL_BGR_BIT |
|
|
||||||
COGL_PREMULT_BIT);
|
|
||||||
|
|
||||||
using_rectangle = FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (handle)
|
|
||||||
{
|
|
||||||
clutter_glx_texture_pixmap_free_rectangle (texture_glx);
|
|
||||||
priv->using_rectangle = using_rectangle;
|
|
||||||
|
|
||||||
clutter_texture_set_cogl_texture (texture, handle);
|
|
||||||
cogl_handle_unref(handle);
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_glx_texture_pixmap_realize (ClutterActor *actor)
|
|
||||||
{
|
|
||||||
ClutterGLXTexturePixmap *texture;
|
|
||||||
ClutterGLXTexturePixmapPrivate *priv;
|
|
||||||
|
|
||||||
texture = CLUTTER_GLX_TEXTURE_PIXMAP (actor);
|
|
||||||
priv = texture->priv;
|
|
||||||
|
|
||||||
clutter_glx_texture_pixmap_create_glx_pixmap (texture);
|
|
||||||
|
|
||||||
if (priv->use_fallback)
|
|
||||||
{
|
|
||||||
CLUTTER_ACTOR_CLASS (clutter_glx_texture_pixmap_parent_class)->
|
|
||||||
realize (actor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (TEXTURE, "texture pixmap realised");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_glx_texture_pixmap_unrealize (ClutterActor *actor)
|
|
||||||
{
|
|
||||||
ClutterGLXTexturePixmap *texture = CLUTTER_GLX_TEXTURE_PIXMAP (actor);
|
|
||||||
Display *dpy;
|
|
||||||
|
|
||||||
dpy = clutter_x11_get_default_display();
|
|
||||||
|
|
||||||
clutter_glx_texture_pixmap_free_rectangle (texture);
|
|
||||||
|
|
||||||
if (!_have_tex_from_pixmap_ext)
|
|
||||||
{
|
|
||||||
CLUTTER_ACTOR_CLASS (clutter_glx_texture_pixmap_parent_class)->
|
|
||||||
unrealize (actor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CLUTTER_ACTOR_IS_REALIZED (actor))
|
|
||||||
return;
|
|
||||||
|
|
||||||
release_tex_image (texture);
|
|
||||||
|
|
||||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GLXFBConfig *
|
|
||||||
get_fbconfig_for_depth (ClutterGLXTexturePixmap *texture, guint depth)
|
|
||||||
{
|
|
||||||
GLXFBConfig *fbconfigs, *ret = NULL;
|
|
||||||
int n_elements, i, found;
|
|
||||||
Display *dpy;
|
|
||||||
int db, stencil, alpha, mipmap, rgba, value;
|
|
||||||
|
|
||||||
static GLXFBConfig *cached_config = NULL;
|
|
||||||
static gboolean have_cached_config = FALSE;
|
|
||||||
static int cached_mipmap = 0;
|
|
||||||
|
|
||||||
if (have_cached_config)
|
|
||||||
{
|
|
||||||
texture->priv->can_mipmap = cached_mipmap;
|
|
||||||
return cached_config;
|
|
||||||
}
|
|
||||||
|
|
||||||
dpy = clutter_x11_get_default_display ();
|
|
||||||
|
|
||||||
fbconfigs = glXGetFBConfigs (dpy,
|
|
||||||
clutter_x11_get_default_screen (),
|
|
||||||
&n_elements);
|
|
||||||
|
|
||||||
db = G_MAXSHORT;
|
|
||||||
stencil = G_MAXSHORT;
|
|
||||||
mipmap = 0;
|
|
||||||
rgba = 0;
|
|
||||||
|
|
||||||
found = n_elements;
|
|
||||||
|
|
||||||
for (i = 0; i < n_elements; i++)
|
|
||||||
{
|
|
||||||
XVisualInfo *vi;
|
|
||||||
int visual_depth;
|
|
||||||
|
|
||||||
vi = glXGetVisualFromFBConfig (dpy,
|
|
||||||
fbconfigs[i]);
|
|
||||||
if (vi == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
visual_depth = vi->depth;
|
|
||||||
|
|
||||||
XFree (vi);
|
|
||||||
|
|
||||||
if (visual_depth != depth)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
glXGetFBConfigAttrib (dpy,
|
|
||||||
fbconfigs[i],
|
|
||||||
GLX_ALPHA_SIZE,
|
|
||||||
&alpha);
|
|
||||||
glXGetFBConfigAttrib (dpy,
|
|
||||||
fbconfigs[i],
|
|
||||||
GLX_BUFFER_SIZE,
|
|
||||||
&value);
|
|
||||||
if (value != depth && (value - alpha) != depth)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
value = 0;
|
|
||||||
if (depth == 32)
|
|
||||||
{
|
|
||||||
glXGetFBConfigAttrib (dpy,
|
|
||||||
fbconfigs[i],
|
|
||||||
GLX_BIND_TO_TEXTURE_RGBA_EXT,
|
|
||||||
&value);
|
|
||||||
if (value)
|
|
||||||
rgba = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!value)
|
|
||||||
{
|
|
||||||
if (rgba)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
glXGetFBConfigAttrib (dpy,
|
|
||||||
fbconfigs[i],
|
|
||||||
GLX_BIND_TO_TEXTURE_RGB_EXT,
|
|
||||||
&value);
|
|
||||||
if (!value)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
glXGetFBConfigAttrib (dpy,
|
|
||||||
fbconfigs[i],
|
|
||||||
GLX_DOUBLEBUFFER,
|
|
||||||
&value);
|
|
||||||
if (value > db)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
db = value;
|
|
||||||
|
|
||||||
glXGetFBConfigAttrib (dpy,
|
|
||||||
fbconfigs[i],
|
|
||||||
GLX_STENCIL_SIZE,
|
|
||||||
&value);
|
|
||||||
if (value > stencil)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
stencil = value;
|
|
||||||
|
|
||||||
if (_gl_generate_mipmap)
|
|
||||||
{
|
|
||||||
glXGetFBConfigAttrib (dpy,
|
|
||||||
fbconfigs[i],
|
|
||||||
GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
|
|
||||||
&value);
|
|
||||||
|
|
||||||
if (value < mipmap)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
mipmap = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
found = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (found != n_elements)
|
|
||||||
{
|
|
||||||
ret = g_malloc (sizeof (GLXFBConfig));
|
|
||||||
*ret = fbconfigs[found];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (n_elements)
|
|
||||||
XFree (fbconfigs);
|
|
||||||
|
|
||||||
have_cached_config = TRUE;
|
|
||||||
cached_config = ret;
|
|
||||||
texture->priv->can_mipmap = cached_mipmap = mipmap;
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_glx_texture_pixmap_free_glx_pixmap (ClutterGLXTexturePixmap *texture)
|
|
||||||
{
|
|
||||||
ClutterGLXTexturePixmapPrivate *priv = texture->priv;
|
|
||||||
Display *dpy;
|
|
||||||
|
|
||||||
dpy = clutter_x11_get_default_display ();
|
|
||||||
|
|
||||||
release_tex_image (texture);
|
|
||||||
|
|
||||||
clutter_x11_trap_x_errors ();
|
|
||||||
if (priv->glx_pixmap)
|
|
||||||
glXDestroyPixmap (dpy, priv->glx_pixmap);
|
|
||||||
XSync (dpy, FALSE);
|
|
||||||
clutter_x11_untrap_x_errors ();
|
|
||||||
priv->glx_pixmap = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 = None;
|
|
||||||
guint pixmap_width = 0, pixmap_height = 0;
|
|
||||||
ClutterBackendGLX *backend_glx;
|
|
||||||
ClutterTextureQuality quality;
|
|
||||||
|
|
||||||
backend_glx = CLUTTER_BACKEND_GLX(clutter_get_default_backend ());
|
|
||||||
|
|
||||||
dpy = clutter_x11_get_default_display ();
|
|
||||||
|
|
||||||
if (!_have_tex_from_pixmap_ext)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
g_object_get (texture,
|
|
||||||
"pixmap-width", &pixmap_width,
|
|
||||||
"pixmap-height", &pixmap_height,
|
|
||||||
"pixmap-depth", &depth,
|
|
||||||
"pixmap", &pixmap,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!pixmap)
|
|
||||||
{
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLUTTER_NOTE (TEXTURE, "Creating GLXPixmap");
|
|
||||||
|
|
||||||
fbconfig = get_fbconfig_for_depth (texture, 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 below 24 are not supported");
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
quality = clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture));
|
|
||||||
|
|
||||||
if (quality == CLUTTER_TEXTURE_QUALITY_HIGH && priv->can_mipmap)
|
|
||||||
mipmap = priv->can_mipmap;
|
|
||||||
|
|
||||||
attribs[i++] = GLX_MIPMAP_TEXTURE_EXT;
|
|
||||||
attribs[i++] = mipmap;
|
|
||||||
|
|
||||||
attribs[i++] = GLX_TEXTURE_TARGET_EXT;
|
|
||||||
|
|
||||||
attribs[i++] = (should_use_rectangle ()
|
|
||||||
? GLX_TEXTURE_RECTANGLE_EXT : GLX_TEXTURE_2D_EXT);
|
|
||||||
|
|
||||||
attribs[i++] = None;
|
|
||||||
|
|
||||||
/* Note: some drivers (e.g. Nvidia) get upset if you effectivly create a glx
|
|
||||||
* pixmap for the same server side object, even though you might have unique
|
|
||||||
* client side names, we currently avoid hitting this problem by destroying
|
|
||||||
* the current glx pixmap first */
|
|
||||||
if (priv->glx_pixmap)
|
|
||||||
clutter_glx_texture_pixmap_free_glx_pixmap (texture);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!create_cogl_texture (CLUTTER_TEXTURE (texture),
|
|
||||||
pixmap_width, pixmap_height))
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (TEXTURE, "Unable to create texture for pixmap");
|
|
||||||
|
|
||||||
glXDestroyPixmap (dpy, glx_pixmap);
|
|
||||||
glx_pixmap = None;
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
|
|
||||||
if (priv->glx_pixmap)
|
|
||||||
clutter_glx_texture_pixmap_free_glx_pixmap (texture);
|
|
||||||
|
|
||||||
if (glx_pixmap != None)
|
|
||||||
{
|
|
||||||
priv->use_fallback = FALSE;
|
|
||||||
priv->glx_pixmap = glx_pixmap;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (TEXTURE, "Created GLXPixmap");
|
|
||||||
|
|
||||||
clutter_glx_texture_pixmap_update_area (CLUTTER_X11_TEXTURE_PIXMAP (texture),
|
|
||||||
0, 0,
|
|
||||||
pixmap_width, pixmap_height);
|
|
||||||
|
|
||||||
/* Get ready to queue initial mipmap generation */
|
|
||||||
if (clutter_texture_get_filter_quality (CLUTTER_TEXTURE (texture))
|
|
||||||
== CLUTTER_TEXTURE_QUALITY_HIGH)
|
|
||||||
{
|
|
||||||
priv->mipmap_generate_queued = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (pixmap)
|
|
||||||
CLUTTER_NOTE (TEXTURE, "Falling back to X11 manual mechansim");
|
|
||||||
|
|
||||||
priv->use_fallback = TRUE;
|
|
||||||
priv->glx_pixmap = None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_glx_texture_pixmap_update_area (ClutterX11TexturePixmap *texture,
|
|
||||||
gint x,
|
|
||||||
gint y,
|
|
||||||
gint width,
|
|
||||||
gint height)
|
|
||||||
{
|
|
||||||
ClutterGLXTexturePixmap *texture_glx = CLUTTER_GLX_TEXTURE_PIXMAP (texture);
|
|
||||||
ClutterGLXTexturePixmapPrivate *priv = texture_glx->priv;
|
|
||||||
|
|
||||||
CLUTTER_NOTE (TEXTURE, "Updating texture pixmap");
|
|
||||||
|
|
||||||
if (!CLUTTER_ACTOR_IS_REALIZED (texture))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (priv->use_fallback)
|
|
||||||
{
|
|
||||||
CLUTTER_NOTE (TEXTURE, "Falling back to X11");
|
|
||||||
|
|
||||||
clutter_glx_texture_pixmap_free_rectangle (texture_glx);
|
|
||||||
|
|
||||||
parent_class->update_area (texture,
|
|
||||||
x, y,
|
|
||||||
width, height);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->glx_pixmap == None)
|
|
||||||
return;
|
|
||||||
|
|
||||||
priv->bind_tex_image_queued = TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_glx_texture_pixmap_class_init (ClutterGLXTexturePixmapClass *klass)
|
clutter_glx_texture_pixmap_class_init (ClutterGLXTexturePixmapClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
||||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
|
||||||
ClutterX11TexturePixmapClass *x11_texture_class =
|
|
||||||
CLUTTER_X11_TEXTURE_PIXMAP_CLASS (klass);
|
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (ClutterGLXTexturePixmapPrivate));
|
|
||||||
|
|
||||||
parent_class = g_type_class_peek_parent(klass);
|
|
||||||
|
|
||||||
object_class->dispose = clutter_glx_texture_pixmap_dispose;
|
|
||||||
object_class->notify = clutter_glx_texture_pixmap_notify;
|
|
||||||
|
|
||||||
actor_class->realize = clutter_glx_texture_pixmap_realize;
|
|
||||||
actor_class->unrealize = clutter_glx_texture_pixmap_unrealize;
|
|
||||||
|
|
||||||
x11_texture_class->update_area = clutter_glx_texture_pixmap_update_area;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -875,15 +88,14 @@ clutter_glx_texture_pixmap_class_init (ClutterGLXTexturePixmapClass *klass)
|
|||||||
gboolean
|
gboolean
|
||||||
clutter_glx_texture_pixmap_using_extension (ClutterGLXTexturePixmap *texture)
|
clutter_glx_texture_pixmap_using_extension (ClutterGLXTexturePixmap *texture)
|
||||||
{
|
{
|
||||||
ClutterGLXTexturePixmapPrivate *priv;
|
CoglHandle cogl_texture;
|
||||||
|
|
||||||
priv = CLUTTER_GLX_TEXTURE_PIXMAP (texture)->priv;
|
g_return_val_if_fail (CLUTTER_GLX_IS_TEXTURE_PIXMAP (texture), FALSE);
|
||||||
|
|
||||||
return (_have_tex_from_pixmap_ext && !priv->use_fallback);
|
cogl_texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (texture));
|
||||||
/* Assume NPOT TFP's are supported even if regular NPOT isn't advertised
|
|
||||||
* but tfp is. Seemingly some Intel drivers do this ?
|
return (cogl_is_texture_pixmap_x11 (cogl_texture) &&
|
||||||
*/
|
cogl_texture_pixmap_x11_is_using_tfp_extension (cogl_texture));
|
||||||
/* && clutter_feature_available (COGL_FEATURE_TEXTURE_NPOT)); */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
*
|
*
|
||||||
* An OpenGL based 'interactive canvas' library.
|
* An OpenGL based 'interactive canvas' library.
|
||||||
*
|
*
|
||||||
* Authored By Johan Bilien <johan.bilien@nokia.com>
|
|
||||||
*
|
|
||||||
* Copyright (C) 2007 OpenedHand
|
* Copyright (C) 2007 OpenedHand
|
||||||
|
* Copyright (C) 2010 Intel Corporation.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -20,7 +19,9 @@
|
|||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*
|
* Authors:
|
||||||
|
* Johan Bilien <johan.bilien@nokia.com>
|
||||||
|
* Neil Roberts <neil@linux.intel.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -47,15 +48,11 @@
|
|||||||
#include "clutter-private.h"
|
#include "clutter-private.h"
|
||||||
|
|
||||||
#include "cogl/cogl.h"
|
#include "cogl/cogl.h"
|
||||||
|
#include "cogl/winsys/cogl-texture-pixmap-x11.h"
|
||||||
|
|
||||||
#include <X11/extensions/Xdamage.h>
|
#include <X11/extensions/Xdamage.h>
|
||||||
#include <X11/extensions/Xcomposite.h>
|
#include <X11/extensions/Xcomposite.h>
|
||||||
|
|
||||||
#include <sys/ipc.h>
|
|
||||||
#include <sys/shm.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <X11/extensions/XShm.h>
|
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
PROP_PIXMAP = 1,
|
PROP_PIXMAP = 1,
|
||||||
@ -103,15 +100,10 @@ struct _ClutterX11TexturePixmapPrivate
|
|||||||
guint pixmap_width, pixmap_height;
|
guint pixmap_width, pixmap_height;
|
||||||
guint depth;
|
guint depth;
|
||||||
|
|
||||||
XImage *image;
|
|
||||||
XShmSegmentInfo shminfo;
|
|
||||||
|
|
||||||
gboolean automatic_updates;
|
gboolean automatic_updates;
|
||||||
Damage damage;
|
Damage damage;
|
||||||
Drawable damage_drawable;
|
|
||||||
|
|
||||||
/* FIXME: lots of gbooleans. coalesce into bitfields */
|
/* FIXME: lots of gbooleans. coalesce into bitfields */
|
||||||
gboolean have_shm;
|
|
||||||
gboolean window_redirect_automatic;
|
gboolean window_redirect_automatic;
|
||||||
gboolean window_mapped;
|
gboolean window_mapped;
|
||||||
gboolean destroyed;
|
gboolean destroyed;
|
||||||
@ -152,150 +144,21 @@ check_extensions (ClutterX11TexturePixmap *texture)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_shm_resources (ClutterX11TexturePixmap *texture)
|
process_damage_event (ClutterX11TexturePixmap *texture,
|
||||||
|
XDamageNotifyEvent *damage_event)
|
||||||
{
|
{
|
||||||
ClutterX11TexturePixmapPrivate *priv;
|
|
||||||
|
|
||||||
priv = texture->priv;
|
|
||||||
|
|
||||||
if (priv->shminfo.shmid != -1)
|
|
||||||
{
|
|
||||||
XShmDetach(clutter_x11_get_default_display(),
|
|
||||||
&priv->shminfo);
|
|
||||||
shmdt(priv->shminfo.shmaddr);
|
|
||||||
shmctl(priv->shminfo.shmid, IPC_RMID, NULL);
|
|
||||||
priv->shminfo.shmid = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Tries to allocate enough shared mem to handle a full size
|
|
||||||
* update size of the X Pixmap. */
|
|
||||||
static gboolean
|
|
||||||
try_alloc_shm (ClutterX11TexturePixmap *texture)
|
|
||||||
{
|
|
||||||
ClutterX11TexturePixmapPrivate *priv;
|
|
||||||
XImage *dummy_image;
|
|
||||||
Display *dpy;
|
|
||||||
|
|
||||||
priv = texture->priv;
|
|
||||||
dpy = clutter_x11_get_default_display();
|
|
||||||
|
|
||||||
g_return_val_if_fail (priv->pixmap, FALSE);
|
|
||||||
|
|
||||||
if (!XShmQueryExtension(dpy) || g_getenv("CLUTTER_X11_NO_SHM"))
|
|
||||||
{
|
|
||||||
priv->have_shm = FALSE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
clutter_x11_trap_x_errors ();
|
|
||||||
|
|
||||||
/* We are creating a dummy_image so we can have Xlib calculate
|
|
||||||
* image->bytes_per_line - including any magic padding it may
|
|
||||||
* want - for the largest possible ximage we might need to use
|
|
||||||
* when handling updates to the texture.
|
|
||||||
*
|
|
||||||
* Note: we pass a NULL shminfo here, but that has no bearing
|
|
||||||
* on the setup of the XImage, except that ximage->obdata will
|
|
||||||
* == NULL.
|
|
||||||
*/
|
|
||||||
dummy_image =
|
|
||||||
XShmCreateImage(dpy,
|
|
||||||
DefaultVisual(dpy,
|
|
||||||
clutter_x11_get_default_screen()),
|
|
||||||
priv->depth,
|
|
||||||
ZPixmap,
|
|
||||||
NULL,
|
|
||||||
NULL, /* shminfo, */
|
|
||||||
priv->pixmap_width,
|
|
||||||
priv->pixmap_height);
|
|
||||||
if (!dummy_image)
|
|
||||||
goto failed_image_create;
|
|
||||||
|
|
||||||
priv->shminfo.shmid = shmget (IPC_PRIVATE,
|
|
||||||
dummy_image->bytes_per_line
|
|
||||||
* dummy_image->height,
|
|
||||||
IPC_CREAT | 0777);
|
|
||||||
if (priv->shminfo.shmid == -1)
|
|
||||||
goto failed_shmget;
|
|
||||||
|
|
||||||
priv->shminfo.shmaddr = shmat (priv->shminfo.shmid, NULL, 0);
|
|
||||||
if (priv->shminfo.shmaddr == (void *) -1)
|
|
||||||
goto failed_shmat;
|
|
||||||
|
|
||||||
priv->shminfo.readOnly = False;
|
|
||||||
|
|
||||||
if (XShmAttach (dpy, &priv->shminfo) == 0)
|
|
||||||
goto failed_xshmattach;
|
|
||||||
|
|
||||||
if (clutter_x11_untrap_x_errors ())
|
|
||||||
g_warning ("X Error: Failed to setup XShm");
|
|
||||||
|
|
||||||
XDestroyImage (dummy_image);
|
|
||||||
|
|
||||||
priv->have_shm = TRUE;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
failed_xshmattach:
|
|
||||||
g_warning ("XShmAttach failed");
|
|
||||||
shmdt (priv->shminfo.shmaddr);
|
|
||||||
|
|
||||||
failed_shmat:
|
|
||||||
g_warning ("shmat failed");
|
|
||||||
shmctl (priv->shminfo.shmid, IPC_RMID, NULL);
|
|
||||||
|
|
||||||
failed_shmget:
|
|
||||||
g_warning ("shmget failed");
|
|
||||||
XDestroyImage (dummy_image);
|
|
||||||
|
|
||||||
failed_image_create:
|
|
||||||
if (clutter_x11_untrap_x_errors ())
|
|
||||||
g_warning ("X Error: Failed to setup XShm");
|
|
||||||
|
|
||||||
priv->have_shm = FALSE;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
check_for_pixmap_damage (ClutterX11TexturePixmap *texture)
|
|
||||||
{
|
|
||||||
ClutterX11TexturePixmapPrivate *priv = texture->priv;
|
|
||||||
Display *dpy;
|
Display *dpy;
|
||||||
XserverRegion parts;
|
|
||||||
int i, r_count;
|
|
||||||
XRectangle *r_damage;
|
|
||||||
XRectangle r_bounds;
|
|
||||||
|
|
||||||
clutter_x11_trap_x_errors ();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Retrieve the damaged region and break it down into individual
|
|
||||||
* rectangles so we do not have to update the whole shebang.
|
|
||||||
*/
|
|
||||||
dpy = clutter_x11_get_default_display();
|
dpy = clutter_x11_get_default_display();
|
||||||
parts = XFixesCreateRegion (dpy, NULL, 0);
|
|
||||||
XDamageSubtract (dpy, priv->damage, None, parts);
|
|
||||||
|
|
||||||
r_damage = XFixesFetchRegionAndBounds (dpy,
|
/* Cogl will deal with updating the texture and subtracting from the
|
||||||
parts,
|
damage region so we only need to queue a redraw */
|
||||||
&r_count,
|
g_signal_emit (texture, signals[QUEUE_DAMAGE_REDRAW],
|
||||||
&r_bounds);
|
0,
|
||||||
|
damage_event->area.x,
|
||||||
clutter_x11_untrap_x_errors ();
|
damage_event->area.y,
|
||||||
|
damage_event->area.width,
|
||||||
if (r_damage)
|
damage_event->area.height);
|
||||||
{
|
|
||||||
for (i = 0; i < r_count; ++i)
|
|
||||||
clutter_x11_texture_pixmap_update_area (texture,
|
|
||||||
r_damage[i].x,
|
|
||||||
r_damage[i].y,
|
|
||||||
r_damage[i].width,
|
|
||||||
r_damage[i].height);
|
|
||||||
XFree (r_damage);
|
|
||||||
}
|
|
||||||
|
|
||||||
XFixesDestroyRegion (dpy, parts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ClutterX11FilterReturn
|
static ClutterX11FilterReturn
|
||||||
@ -315,10 +178,10 @@ on_x_event_filter (XEvent *xev, ClutterEvent *cev, gpointer data)
|
|||||||
{
|
{
|
||||||
XDamageNotifyEvent *dev = (XDamageNotifyEvent*)xev;
|
XDamageNotifyEvent *dev = (XDamageNotifyEvent*)xev;
|
||||||
|
|
||||||
if (dev->drawable != priv->damage_drawable)
|
if (dev->damage != priv->damage)
|
||||||
return CLUTTER_X11_FILTER_CONTINUE;
|
return CLUTTER_X11_FILTER_CONTINUE;
|
||||||
|
|
||||||
check_for_pixmap_damage (texture);
|
process_damage_event (texture, dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
return CLUTTER_X11_FILTER_CONTINUE;
|
return CLUTTER_X11_FILTER_CONTINUE;
|
||||||
@ -358,6 +221,32 @@ on_x_event_filter_too (XEvent *xev, ClutterEvent *cev, gpointer data)
|
|||||||
return CLUTTER_X11_FILTER_CONTINUE;
|
return CLUTTER_X11_FILTER_CONTINUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_pixmap_damage_object (ClutterX11TexturePixmap *texture)
|
||||||
|
{
|
||||||
|
ClutterX11TexturePixmapPrivate *priv = texture->priv;
|
||||||
|
CoglHandle cogl_texture;
|
||||||
|
|
||||||
|
/* If we already have a CoglTexturePixmapX11 then update its
|
||||||
|
damage object */
|
||||||
|
cogl_texture =
|
||||||
|
clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (texture));
|
||||||
|
|
||||||
|
if (cogl_texture && cogl_is_texture_pixmap_x11 (cogl_texture))
|
||||||
|
{
|
||||||
|
if (priv->damage)
|
||||||
|
{
|
||||||
|
const CoglTexturePixmapX11ReportLevel report_level =
|
||||||
|
COGL_TEXTURE_PIXMAP_X11_DAMAGE_BOUNDING_BOX;
|
||||||
|
cogl_texture_pixmap_x11_set_damage_object (cogl_texture,
|
||||||
|
priv->damage,
|
||||||
|
report_level);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
cogl_texture_pixmap_x11_set_damage_object (cogl_texture, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
create_damage_resources (ClutterX11TexturePixmap *texture)
|
create_damage_resources (ClutterX11TexturePixmap *texture)
|
||||||
{
|
{
|
||||||
@ -367,19 +256,14 @@ create_damage_resources (ClutterX11TexturePixmap *texture)
|
|||||||
priv = texture->priv;
|
priv = texture->priv;
|
||||||
dpy = clutter_x11_get_default_display();
|
dpy = clutter_x11_get_default_display();
|
||||||
|
|
||||||
if (!priv->window && !priv->pixmap)
|
if (!priv->pixmap)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
clutter_x11_trap_x_errors ();
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
if (priv->window)
|
|
||||||
priv->damage_drawable = priv->window;
|
|
||||||
else
|
|
||||||
priv->damage_drawable = priv->pixmap;
|
|
||||||
|
|
||||||
priv->damage = XDamageCreate (dpy,
|
priv->damage = XDamageCreate (dpy,
|
||||||
priv->damage_drawable,
|
priv->pixmap,
|
||||||
XDamageReportNonEmpty);
|
XDamageReportBoundingBox);
|
||||||
|
|
||||||
/* Errors here might occur if the window is already destroyed, we
|
/* Errors here might occur if the window is already destroyed, we
|
||||||
* simply skip processing damage and assume that the texture pixmap
|
* simply skip processing damage and assume that the texture pixmap
|
||||||
@ -389,7 +273,11 @@ create_damage_resources (ClutterX11TexturePixmap *texture)
|
|||||||
clutter_x11_untrap_x_errors ();
|
clutter_x11_untrap_x_errors ();
|
||||||
|
|
||||||
if (priv->damage)
|
if (priv->damage)
|
||||||
clutter_x11_add_filter (on_x_event_filter, (gpointer)texture);
|
{
|
||||||
|
clutter_x11_add_filter (on_x_event_filter, (gpointer)texture);
|
||||||
|
|
||||||
|
update_pixmap_damage_object (texture);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -408,9 +296,10 @@ free_damage_resources (ClutterX11TexturePixmap *texture)
|
|||||||
XSync (dpy, FALSE);
|
XSync (dpy, FALSE);
|
||||||
clutter_x11_untrap_x_errors ();
|
clutter_x11_untrap_x_errors ();
|
||||||
priv->damage = None;
|
priv->damage = None;
|
||||||
priv->damage_drawable = None;
|
|
||||||
|
|
||||||
clutter_x11_remove_filter (on_x_event_filter, (gpointer)texture);
|
clutter_x11_remove_filter (on_x_event_filter, (gpointer)texture);
|
||||||
|
|
||||||
|
update_pixmap_damage_object (texture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,15 +371,12 @@ clutter_x11_texture_pixmap_init (ClutterX11TexturePixmap *self)
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
self->priv->image = NULL;
|
|
||||||
self->priv->automatic_updates = FALSE;
|
self->priv->automatic_updates = FALSE;
|
||||||
self->priv->damage = None;
|
self->priv->damage = None;
|
||||||
self->priv->damage_drawable = None;
|
|
||||||
self->priv->window = None;
|
self->priv->window = None;
|
||||||
self->priv->pixmap = None;
|
self->priv->pixmap = None;
|
||||||
self->priv->pixmap_height = 0;
|
self->priv->pixmap_height = 0;
|
||||||
self->priv->pixmap_width = 0;
|
self->priv->pixmap_width = 0;
|
||||||
self->priv->shminfo.shmid = -1;
|
|
||||||
self->priv->window_redirect_automatic = TRUE;
|
self->priv->window_redirect_automatic = TRUE;
|
||||||
self->priv->window_mapped = FALSE;
|
self->priv->window_mapped = FALSE;
|
||||||
self->priv->destroyed = FALSE;
|
self->priv->destroyed = FALSE;
|
||||||
@ -515,14 +401,6 @@ clutter_x11_texture_pixmap_dispose (GObject *object)
|
|||||||
priv->pixmap = None;
|
priv->pixmap = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->image)
|
|
||||||
{
|
|
||||||
XDestroyImage (priv->image);
|
|
||||||
priv->image = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
free_shm_resources (texture);
|
|
||||||
|
|
||||||
G_OBJECT_CLASS (clutter_x11_texture_pixmap_parent_class)->dispose (object);
|
G_OBJECT_CLASS (clutter_x11_texture_pixmap_parent_class)->dispose (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,26 +499,10 @@ clutter_x11_texture_pixmap_get_property (GObject *object,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
clutter_x11_texture_pixmap_realize (ClutterActor *actor)
|
|
||||||
{
|
|
||||||
ClutterX11TexturePixmap *texture = CLUTTER_X11_TEXTURE_PIXMAP (actor);
|
|
||||||
ClutterX11TexturePixmapPrivate *priv = texture->priv;
|
|
||||||
|
|
||||||
CLUTTER_ACTOR_CLASS (clutter_x11_texture_pixmap_parent_class)->
|
|
||||||
realize (actor);
|
|
||||||
|
|
||||||
clutter_x11_texture_pixmap_update_area_real (texture,
|
|
||||||
0, 0,
|
|
||||||
priv->pixmap_width,
|
|
||||||
priv->pixmap_height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
clutter_x11_texture_pixmap_class_init (ClutterX11TexturePixmapClass *klass)
|
clutter_x11_texture_pixmap_class_init (ClutterX11TexturePixmapClass *klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
|
||||||
GParamSpec *pspec;
|
GParamSpec *pspec;
|
||||||
ClutterBackend *default_backend;
|
ClutterBackend *default_backend;
|
||||||
|
|
||||||
@ -650,8 +512,6 @@ clutter_x11_texture_pixmap_class_init (ClutterX11TexturePixmapClass *klass)
|
|||||||
object_class->set_property = clutter_x11_texture_pixmap_set_property;
|
object_class->set_property = clutter_x11_texture_pixmap_set_property;
|
||||||
object_class->get_property = clutter_x11_texture_pixmap_get_property;
|
object_class->get_property = clutter_x11_texture_pixmap_get_property;
|
||||||
|
|
||||||
actor_class->realize = clutter_x11_texture_pixmap_realize;
|
|
||||||
|
|
||||||
klass->update_area = clutter_x11_texture_pixmap_update_area_real;
|
klass->update_area = clutter_x11_texture_pixmap_update_area_real;
|
||||||
|
|
||||||
pspec = g_param_spec_ulong ("pixmap",
|
pspec = g_param_spec_ulong ("pixmap",
|
||||||
@ -799,9 +659,11 @@ clutter_x11_texture_pixmap_class_init (ClutterX11TexturePixmapClass *klass)
|
|||||||
* @width: The width of the damage region
|
* @width: The width of the damage region
|
||||||
* @height: The height of the damage region
|
* @height: The height of the damage region
|
||||||
*
|
*
|
||||||
* ::queue-damage-redraw is emitted to notify that some sub-region of the
|
* ::queue-damage-redraw is emitted to notify that some sub-region
|
||||||
* underlying pixmap has changed and you need to queue a
|
* of the texture has been changed (either by an automatic damage
|
||||||
* corresponding redraw for the actor.
|
* update or by an explicit call to
|
||||||
|
* clutter_x11_texture_pixmap_update_area). This usually means a
|
||||||
|
* redraw needs to be queued for the actor.
|
||||||
*
|
*
|
||||||
* The default handler will queue a clipped redraw in response to
|
* The default handler will queue a clipped redraw in response to
|
||||||
* the damage, using the assumption that the pixmap is being painted
|
* the damage, using the assumption that the pixmap is being painted
|
||||||
@ -846,196 +708,12 @@ clutter_x11_texture_pixmap_update_area_real (ClutterX11TexturePixmap *texture,
|
|||||||
gint width,
|
gint width,
|
||||||
gint height)
|
gint height)
|
||||||
{
|
{
|
||||||
ClutterX11TexturePixmapPrivate *priv;
|
CoglHandle cogl_texture;
|
||||||
Display *dpy;
|
|
||||||
XImage *image;
|
|
||||||
char *first_pixel;
|
|
||||||
GError *error = NULL;
|
|
||||||
guint bytes_per_line;
|
|
||||||
char *data;
|
|
||||||
gboolean data_allocated = FALSE;
|
|
||||||
int err_code;
|
|
||||||
|
|
||||||
if (!CLUTTER_ACTOR_IS_REALIZED (texture))
|
cogl_texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (texture));
|
||||||
return;
|
|
||||||
|
|
||||||
priv = texture->priv;
|
if (cogl_texture)
|
||||||
dpy = clutter_x11_get_default_display();
|
cogl_texture_pixmap_x11_update_area (cogl_texture, x, y, width, height);
|
||||||
|
|
||||||
if (!priv->pixmap)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (priv->shminfo.shmid == -1)
|
|
||||||
try_alloc_shm (texture);
|
|
||||||
|
|
||||||
clutter_x11_trap_x_errors ();
|
|
||||||
|
|
||||||
if (priv->have_shm)
|
|
||||||
{
|
|
||||||
image =
|
|
||||||
XShmCreateImage(dpy,
|
|
||||||
DefaultVisual(dpy,
|
|
||||||
clutter_x11_get_default_screen()),
|
|
||||||
priv->depth,
|
|
||||||
ZPixmap,
|
|
||||||
NULL,
|
|
||||||
&priv->shminfo,
|
|
||||||
width,
|
|
||||||
height);
|
|
||||||
image->data = priv->shminfo.shmaddr;
|
|
||||||
|
|
||||||
XShmGetImage (dpy, priv->pixmap, image, x, y, AllPlanes);
|
|
||||||
first_pixel = image->data;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!priv->image)
|
|
||||||
{
|
|
||||||
priv->image = XGetImage (dpy,
|
|
||||||
priv->pixmap,
|
|
||||||
0, 0,
|
|
||||||
priv->pixmap_width, priv->pixmap_height,
|
|
||||||
AllPlanes,
|
|
||||||
ZPixmap);
|
|
||||||
first_pixel = priv->image->data + priv->image->bytes_per_line * y
|
|
||||||
+ x * priv->image->bits_per_pixel/8;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
XGetSubImage (dpy,
|
|
||||||
priv->pixmap,
|
|
||||||
x, y,
|
|
||||||
width, height,
|
|
||||||
AllPlanes,
|
|
||||||
ZPixmap,
|
|
||||||
priv->image,
|
|
||||||
x, y);
|
|
||||||
first_pixel = priv->image->data + priv->image->bytes_per_line * y
|
|
||||||
+ x * priv->image->bits_per_pixel/8;
|
|
||||||
}
|
|
||||||
image = priv->image;
|
|
||||||
}
|
|
||||||
|
|
||||||
XSync (dpy, FALSE);
|
|
||||||
|
|
||||||
if ((err_code = clutter_x11_untrap_x_errors ()))
|
|
||||||
{
|
|
||||||
g_warning ("Failed to get XImage of pixmap: %lx, removing",
|
|
||||||
priv->pixmap);
|
|
||||||
/* safe to assume pixmap has gone away? - therefor reset */
|
|
||||||
clutter_x11_texture_pixmap_set_pixmap (texture, None);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->depth == 24)
|
|
||||||
{
|
|
||||||
guint xpos, ypos;
|
|
||||||
|
|
||||||
for (ypos=0; ypos<height; ypos++)
|
|
||||||
for (xpos=0; xpos<width; xpos++)
|
|
||||||
{
|
|
||||||
char *p = first_pixel + image->bytes_per_line*ypos
|
|
||||||
+ xpos * 4;
|
|
||||||
p[3] = 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
data = first_pixel;
|
|
||||||
bytes_per_line = image->bytes_per_line;
|
|
||||||
}
|
|
||||||
else if (priv->depth == 16)
|
|
||||||
{
|
|
||||||
guint xpos, ypos;
|
|
||||||
data = g_malloc (height * width * 4);
|
|
||||||
data_allocated = TRUE;
|
|
||||||
bytes_per_line = width * 4;
|
|
||||||
|
|
||||||
for (ypos=0; ypos<height; ypos++)
|
|
||||||
for (xpos=0; xpos<width; xpos++)
|
|
||||||
{
|
|
||||||
char *src_p = first_pixel + image->bytes_per_line * ypos
|
|
||||||
+ xpos * 2;
|
|
||||||
guint16 *src_pixel = (guint16 *)src_p;
|
|
||||||
char *dst_p = data + bytes_per_line * ypos + xpos * 4;
|
|
||||||
guint32 *dst_pixel = (guint32 *)dst_p;
|
|
||||||
|
|
||||||
*dst_pixel =
|
|
||||||
((((*src_pixel << 3) & 0xf8) | ((*src_pixel >> 2) & 0x7)) | \
|
|
||||||
(((*src_pixel << 5) & 0xfc00) | ((*src_pixel >> 1) & 0x300)) | \
|
|
||||||
(((*src_pixel << 8) & 0xf80000) | ((*src_pixel << 3) & 0x70000)))
|
|
||||||
| 0xff000000;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (priv->depth == 32)
|
|
||||||
{
|
|
||||||
bytes_per_line = image->bytes_per_line;
|
|
||||||
data = first_pixel;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return;
|
|
||||||
|
|
||||||
/* For debugging purposes, un comment to simply generate dummy
|
|
||||||
* pixmap data. (A Green background and Blue cross) */
|
|
||||||
#if 0
|
|
||||||
{
|
|
||||||
guint xpos, ypos;
|
|
||||||
|
|
||||||
if (data_allocated)
|
|
||||||
g_free (data);
|
|
||||||
data_allocated = TRUE;
|
|
||||||
data = g_malloc (width*height*4);
|
|
||||||
bytes_per_line = width *4;
|
|
||||||
|
|
||||||
for (ypos=0; ypos<height; ypos++)
|
|
||||||
for (xpos=0; xpos<width; xpos++)
|
|
||||||
{
|
|
||||||
char *p = data + width*4*ypos + xpos * 4;
|
|
||||||
guint32 *pixel = (guint32 *)p;
|
|
||||||
if ((xpos > width/2 && xpos <= (width/2) + width/4)
|
|
||||||
|| (ypos > height/2 && ypos <= (height/2) + height/4))
|
|
||||||
*pixel=0xff0000ff;
|
|
||||||
else
|
|
||||||
*pixel=0xff00ff00;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (x != 0 || y != 0 ||
|
|
||||||
width != priv->pixmap_width || height != priv->pixmap_height)
|
|
||||||
clutter_texture_set_area_from_rgb_data (CLUTTER_TEXTURE (texture),
|
|
||||||
(guint8 *)data,
|
|
||||||
TRUE,
|
|
||||||
x, y,
|
|
||||||
width, height,
|
|
||||||
bytes_per_line,
|
|
||||||
4,
|
|
||||||
CLUTTER_TEXTURE_RGB_FLAG_BGR |
|
|
||||||
CLUTTER_TEXTURE_RGB_FLAG_PREMULT,
|
|
||||||
&error);
|
|
||||||
else
|
|
||||||
clutter_texture_set_from_rgb_data (CLUTTER_TEXTURE (texture),
|
|
||||||
(guint8 *)data,
|
|
||||||
TRUE,
|
|
||||||
width, height,
|
|
||||||
bytes_per_line,
|
|
||||||
4,
|
|
||||||
CLUTTER_TEXTURE_RGB_FLAG_BGR |
|
|
||||||
CLUTTER_TEXTURE_RGB_FLAG_PREMULT,
|
|
||||||
&error);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
g_warning ("Error when uploading from pixbuf: %s",
|
|
||||||
error->message);
|
|
||||||
g_error_free (error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data_allocated)
|
|
||||||
g_free (data);
|
|
||||||
|
|
||||||
if (priv->have_shm)
|
|
||||||
XFree (image);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1121,6 +799,8 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
|
|||||||
Status status = 0;
|
Status status = 0;
|
||||||
gboolean new_pixmap = FALSE, new_pixmap_width = FALSE;
|
gboolean new_pixmap = FALSE, new_pixmap_width = FALSE;
|
||||||
gboolean new_pixmap_height = FALSE, new_pixmap_depth = FALSE;
|
gboolean new_pixmap_height = FALSE, new_pixmap_depth = FALSE;
|
||||||
|
CoglHandle material;
|
||||||
|
CoglHandle cogl_texture;
|
||||||
|
|
||||||
ClutterX11TexturePixmapPrivate *priv;
|
ClutterX11TexturePixmapPrivate *priv;
|
||||||
|
|
||||||
@ -1130,6 +810,12 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
|
|||||||
|
|
||||||
clutter_x11_trap_x_errors ();
|
clutter_x11_trap_x_errors ();
|
||||||
|
|
||||||
|
/* Get rid of the existing Cogl texture early because it may try to
|
||||||
|
use the pixmap which we might destroy */
|
||||||
|
material = clutter_texture_get_cogl_material (CLUTTER_TEXTURE (texture));
|
||||||
|
if (material)
|
||||||
|
cogl_material_set_layer (material, 0, COGL_INVALID_HANDLE);
|
||||||
|
|
||||||
status = XGetGeometry (clutter_x11_get_default_display(),
|
status = XGetGeometry (clutter_x11_get_default_display(),
|
||||||
(Drawable)pixmap,
|
(Drawable)pixmap,
|
||||||
&root,
|
&root,
|
||||||
@ -1148,12 +834,6 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
|
|||||||
width = height = depth = 0;
|
width = height = depth = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->image)
|
|
||||||
{
|
|
||||||
XDestroyImage (priv->image);
|
|
||||||
priv->image = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (priv->pixmap != pixmap)
|
if (priv->pixmap != pixmap)
|
||||||
{
|
{
|
||||||
if (priv->pixmap && priv->owns_pixmap)
|
if (priv->pixmap && priv->owns_pixmap)
|
||||||
@ -1162,12 +842,10 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
|
|||||||
priv->pixmap = pixmap;
|
priv->pixmap = pixmap;
|
||||||
new_pixmap = TRUE;
|
new_pixmap = TRUE;
|
||||||
|
|
||||||
/* The damage object is created on the window if there is any
|
/* The damage object is created on the pixmap, so it needs to be
|
||||||
* but if there is no window, then we create it directly on
|
* recreated with a change in pixmap.
|
||||||
* the pixmap, so it needs to be recreated with a change in
|
|
||||||
* pixmap.
|
|
||||||
*/
|
*/
|
||||||
if (priv->automatic_updates && new_pixmap && !priv->window)
|
if (priv->automatic_updates && new_pixmap)
|
||||||
{
|
{
|
||||||
free_damage_resources (texture);
|
free_damage_resources (texture);
|
||||||
create_damage_resources (texture);
|
create_damage_resources (texture);
|
||||||
@ -1205,19 +883,13 @@ clutter_x11_texture_pixmap_set_pixmap (ClutterX11TexturePixmap *texture,
|
|||||||
if (new_pixmap_depth)
|
if (new_pixmap_depth)
|
||||||
g_object_notify (G_OBJECT (texture), "pixmap-depth");
|
g_object_notify (G_OBJECT (texture), "pixmap-depth");
|
||||||
|
|
||||||
free_shm_resources (texture);
|
if (pixmap)
|
||||||
|
|
||||||
if (priv->depth != 0 &&
|
|
||||||
priv->pixmap != None &&
|
|
||||||
priv->pixmap_width != 0 &&
|
|
||||||
priv->pixmap_height != 0)
|
|
||||||
{
|
{
|
||||||
if (CLUTTER_ACTOR_IS_REALIZED (texture))
|
cogl_texture = cogl_texture_pixmap_x11_new (pixmap, FALSE);
|
||||||
clutter_x11_texture_pixmap_update_area (texture,
|
clutter_texture_set_cogl_texture (CLUTTER_TEXTURE (texture),
|
||||||
0, 0,
|
cogl_texture);
|
||||||
priv->pixmap_width,
|
cogl_handle_unref (cogl_texture);
|
||||||
priv->pixmap_height);
|
update_pixmap_damage_object (texture);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1310,12 +982,6 @@ clutter_x11_texture_pixmap_set_window (ClutterX11TexturePixmap *texture,
|
|||||||
clutter_x11_add_filter (on_x_event_filter_too, (gpointer)texture);
|
clutter_x11_add_filter (on_x_event_filter_too, (gpointer)texture);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (priv->automatic_updates)
|
|
||||||
{
|
|
||||||
free_damage_resources (texture);
|
|
||||||
create_damage_resources (texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_object_ref (texture);
|
g_object_ref (texture);
|
||||||
g_object_notify (G_OBJECT (texture), "window");
|
g_object_notify (G_OBJECT (texture), "window");
|
||||||
|
|
||||||
@ -1509,6 +1175,5 @@ clutter_x11_texture_pixmap_set_automatic (ClutterX11TexturePixmap *texture,
|
|||||||
free_damage_resources (texture);
|
free_damage_resources (texture);
|
||||||
|
|
||||||
priv->automatic_updates = setting;
|
priv->automatic_updates = setting;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user