Revert "clutter-cairo-texture: Use the new cogl_pixel_buffer API"
This reverts commit 716ec82db8
.
The Cogl pixel buffer API currently has problems if an atlas texture
is created or the format needs to be converted. The atlas problem
doesn't currently show because the atlas rejects BGR textures anyway
but we may want to change this soon. The problem with format
conversion would happen under GLES because that does not support BGR
textures at all so Cogl has to do the conversion. However it doesn't
currently show either because GLES has no support for buffer objects
anyway.
It's also questionable whether the patch would give any performance
benefit because Cairo needs read/write access which implies the buffer
can't be put in write-optimised memory.
Conflicts:
clutter/clutter-cairo-texture.c
http://bugzilla.openedhand.com/show_bug.cgi?id=1982
This commit is contained in:
parent
af37a1029f
commit
16680c74f3
@ -81,8 +81,6 @@
|
||||
#include "clutter-cairo-texture.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-private.h"
|
||||
#include "cogl/cogl-pixel-buffer.h"
|
||||
#include "cogl/cogl-buffer.h"
|
||||
|
||||
G_DEFINE_TYPE (ClutterCairoTexture,
|
||||
clutter_cairo_texture,
|
||||
@ -122,9 +120,8 @@ struct _ClutterCairoTexturePrivate
|
||||
{
|
||||
cairo_format_t format;
|
||||
|
||||
CoglHandle buffer;
|
||||
guint buffer_width;
|
||||
guint buffer_height;
|
||||
cairo_surface_t *cr_surface;
|
||||
guchar *cr_surface_data;
|
||||
|
||||
guint width;
|
||||
guint height;
|
||||
@ -146,6 +143,15 @@ typedef struct
|
||||
} ClutterCairoTextureContext;
|
||||
|
||||
static const cairo_user_data_key_t clutter_cairo_texture_surface_key;
|
||||
static const cairo_user_data_key_t clutter_cairo_texture_context_key;
|
||||
|
||||
static void
|
||||
clutter_cairo_texture_surface_destroy (void *data)
|
||||
{
|
||||
ClutterCairoTexture *cairo = data;
|
||||
|
||||
cairo->priv->cr_surface = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_cairo_texture_set_property (GObject *object,
|
||||
@ -204,10 +210,23 @@ clutter_cairo_texture_finalize (GObject *object)
|
||||
{
|
||||
ClutterCairoTexturePrivate *priv = CLUTTER_CAIRO_TEXTURE (object)->priv;
|
||||
|
||||
if (priv->buffer)
|
||||
if (priv->cr_surface)
|
||||
{
|
||||
cogl_handle_unref (priv->buffer);
|
||||
priv->buffer = NULL;
|
||||
cairo_surface_t *surface = priv->cr_surface;
|
||||
|
||||
cairo_surface_finish (priv->cr_surface);
|
||||
cairo_surface_set_user_data (priv->cr_surface,
|
||||
&clutter_cairo_texture_surface_key,
|
||||
NULL, NULL);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
priv->cr_surface = NULL;
|
||||
}
|
||||
|
||||
if (priv->cr_surface_data)
|
||||
{
|
||||
g_free (priv->cr_surface_data);
|
||||
priv->cr_surface_data = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (clutter_cairo_texture_parent_class)->finalize (object);
|
||||
@ -217,30 +236,80 @@ static inline void
|
||||
clutter_cairo_texture_surface_resize_internal (ClutterCairoTexture *cairo)
|
||||
{
|
||||
ClutterCairoTexturePrivate *priv = cairo->priv;
|
||||
CoglHandle cogl_texture;
|
||||
|
||||
if (priv->buffer)
|
||||
if (priv->cr_surface)
|
||||
{
|
||||
/* If the buffer is already the right size then don't bother
|
||||
cairo_surface_t *surface = priv->cr_surface;
|
||||
|
||||
/* If the surface is already the right size then don't bother
|
||||
doing anything */
|
||||
if (priv->buffer_width == priv->width &&
|
||||
priv->buffer_height == priv->height)
|
||||
if (priv->width == cairo_image_surface_get_width (priv->cr_surface)
|
||||
&& priv->height == cairo_image_surface_get_height (priv->cr_surface))
|
||||
return;
|
||||
|
||||
cogl_handle_unref (priv->buffer);
|
||||
priv->buffer = COGL_INVALID_HANDLE;
|
||||
cairo_surface_finish (surface);
|
||||
cairo_surface_set_user_data (surface,
|
||||
&clutter_cairo_texture_surface_key,
|
||||
NULL, NULL);
|
||||
cairo_surface_destroy (surface);
|
||||
|
||||
priv->cr_surface = NULL;
|
||||
}
|
||||
|
||||
if (priv->cr_surface_data)
|
||||
{
|
||||
g_free (priv->cr_surface_data);
|
||||
priv->cr_surface_data = NULL;
|
||||
}
|
||||
|
||||
if (priv->width == 0 || priv->height == 0)
|
||||
return;
|
||||
|
||||
priv->buffer =
|
||||
cogl_pixel_buffer_new_for_size (priv->width,
|
||||
priv->height,
|
||||
CLUTTER_CAIRO_TEXTURE_PIXEL_FORMAT,
|
||||
&priv->rowstride);
|
||||
#if CAIRO_VERSION > 106000
|
||||
priv->rowstride = cairo_format_stride_for_width (priv->format, priv->width);
|
||||
#else
|
||||
/* poor man's version of cairo_format_stride_for_width() */
|
||||
switch (priv->format)
|
||||
{
|
||||
case CAIRO_FORMAT_ARGB32:
|
||||
case CAIRO_FORMAT_RGB24:
|
||||
priv->rowstride = priv->width * 4;
|
||||
break;
|
||||
|
||||
priv->buffer_width = priv->width;
|
||||
priv->buffer_height = priv->height;
|
||||
case CAIRO_FORMAT_A8:
|
||||
case CAIRO_FORMAT_A1:
|
||||
priv->rowstride = priv->width;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
#endif /* CAIRO_VERSION > 106000 */
|
||||
|
||||
priv->cr_surface_data = g_malloc0 (priv->height * priv->rowstride);
|
||||
priv->cr_surface =
|
||||
cairo_image_surface_create_for_data (priv->cr_surface_data,
|
||||
priv->format,
|
||||
priv->width, priv->height,
|
||||
priv->rowstride);
|
||||
|
||||
cairo_surface_set_user_data (priv->cr_surface,
|
||||
&clutter_cairo_texture_surface_key,
|
||||
cairo,
|
||||
clutter_cairo_texture_surface_destroy);
|
||||
|
||||
/* Create a blank Cogl texture
|
||||
*/
|
||||
cogl_texture = cogl_texture_new_from_data (priv->width, priv->height,
|
||||
COGL_TEXTURE_NONE,
|
||||
CLUTTER_CAIRO_TEXTURE_PIXEL_FORMAT,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
priv->rowstride,
|
||||
priv->cr_surface_data);
|
||||
clutter_texture_set_cogl_texture (CLUTTER_TEXTURE (cairo), cogl_texture);
|
||||
cogl_handle_unref (cogl_texture);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -252,8 +321,8 @@ clutter_cairo_texture_notify (GObject *object,
|
||||
that if both the width and height properties are set using a
|
||||
single call to g_object_set then the surface will only be resized
|
||||
once because the notifications will be frozen in between */
|
||||
if (!strcmp ("surface-width", pspec->name) ||
|
||||
!strcmp ("surface-height", pspec->name))
|
||||
if (!strcmp ("surface-width", pspec->name)
|
||||
|| !strcmp ("surface-height", pspec->name))
|
||||
{
|
||||
ClutterCairoTexture *cairo = CLUTTER_CAIRO_TEXTURE (object);
|
||||
|
||||
@ -384,31 +453,46 @@ clutter_cairo_texture_new (guint width,
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_cairo_texture_surface_destroy (void *data)
|
||||
clutter_cairo_texture_context_destroy (void *data)
|
||||
{
|
||||
ClutterCairoTextureContext *ctxt = data;
|
||||
ClutterCairoTexture *cairo = ctxt->cairo;
|
||||
ClutterCairoTexturePrivate *priv = cairo->priv;
|
||||
guchar *cairo_data;
|
||||
gint cairo_width, cairo_height;
|
||||
gint surface_width, surface_height;
|
||||
CoglHandle cogl_texture;
|
||||
|
||||
if (!priv->buffer)
|
||||
if (!priv->cr_surface)
|
||||
return;
|
||||
|
||||
cogl_buffer_unmap (priv->buffer);
|
||||
surface_width = cairo_image_surface_get_width (priv->cr_surface);
|
||||
surface_height = cairo_image_surface_get_height (priv->cr_surface);
|
||||
|
||||
cogl_texture =
|
||||
cogl_texture_new_from_buffer (priv->buffer,
|
||||
priv->buffer_width,
|
||||
priv->buffer_height,
|
||||
COGL_TEXTURE_NONE,
|
||||
cairo_width = MIN (ctxt->rect.width, surface_width);
|
||||
cairo_height = MIN (ctxt->rect.height, surface_height);
|
||||
|
||||
cogl_texture = clutter_texture_get_cogl_texture (CLUTTER_TEXTURE (cairo));
|
||||
|
||||
if (!cairo_width || !cairo_height || cogl_texture == COGL_INVALID_HANDLE)
|
||||
{
|
||||
g_free (ctxt);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
cairo_data = (priv->cr_surface_data
|
||||
+ (ctxt->rect.y * priv->rowstride)
|
||||
+ (ctxt->rect.x * 4));
|
||||
|
||||
cogl_texture_set_region (cogl_texture,
|
||||
0, 0,
|
||||
ctxt->rect.x, ctxt->rect.y,
|
||||
cairo_width, cairo_height,
|
||||
cairo_width, cairo_height,
|
||||
CLUTTER_CAIRO_TEXTURE_PIXEL_FORMAT,
|
||||
COGL_PIXEL_FORMAT_ANY,
|
||||
priv->rowstride,
|
||||
0);
|
||||
|
||||
clutter_texture_set_cogl_texture (CLUTTER_TEXTURE (cairo), cogl_texture);
|
||||
|
||||
cogl_handle_unref (cogl_texture);
|
||||
cairo_data);
|
||||
|
||||
g_free (ctxt);
|
||||
|
||||
@ -475,8 +559,6 @@ clutter_cairo_texture_create_region (ClutterCairoTexture *self,
|
||||
ClutterCairoTextureContext *ctxt;
|
||||
ClutterCairoTextureRectangle region, area, inter;
|
||||
cairo_t *cr;
|
||||
cairo_surface_t *surface;
|
||||
CoglHandle material;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self), NULL);
|
||||
|
||||
@ -499,7 +581,7 @@ clutter_cairo_texture_create_region (ClutterCairoTexture *self,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!priv->buffer)
|
||||
if (!priv->cr_surface)
|
||||
return NULL;
|
||||
|
||||
ctxt = g_new0 (ClutterCairoTextureContext, 1);
|
||||
@ -523,30 +605,9 @@ clutter_cairo_texture_create_region (ClutterCairoTexture *self,
|
||||
ctxt->rect.width = inter.width;
|
||||
ctxt->rect.height = inter.height;
|
||||
|
||||
/* Destroy the existing texture so that the GL driver won't have to
|
||||
copy it when we map the PBO */
|
||||
if ((material = clutter_texture_get_cogl_material (CLUTTER_TEXTURE (self))))
|
||||
cogl_material_set_layer (material, 0, COGL_INVALID_HANDLE);
|
||||
|
||||
/* Create a surface to render directly to the PBO */
|
||||
surface =
|
||||
cairo_image_surface_create_for_data (cogl_buffer_map (priv->buffer,
|
||||
COGL_BUFFER_ACCESS_READ |
|
||||
COGL_BUFFER_ACCESS_WRITE),
|
||||
priv->format,
|
||||
priv->buffer_width,
|
||||
priv->buffer_height,
|
||||
priv->rowstride);
|
||||
|
||||
/* Set a key so that we can recreate the texture when the surface is
|
||||
destroyed */
|
||||
cairo_surface_set_user_data (surface, &clutter_cairo_texture_surface_key,
|
||||
ctxt, clutter_cairo_texture_surface_destroy);
|
||||
|
||||
cr = cairo_create (surface);
|
||||
/* Remove the reference we have on the surface so that it will be
|
||||
destroyed when the context is destroyed */
|
||||
cairo_surface_destroy (surface);
|
||||
cr = cairo_create (priv->cr_surface);
|
||||
cairo_set_user_data (cr, &clutter_cairo_texture_context_key,
|
||||
ctxt, clutter_cairo_texture_context_destroy);
|
||||
|
||||
return cr;
|
||||
}
|
||||
@ -690,16 +751,13 @@ void
|
||||
clutter_cairo_texture_clear (ClutterCairoTexture *self)
|
||||
{
|
||||
ClutterCairoTexturePrivate *priv;
|
||||
guint8 *data;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_CAIRO_TEXTURE (self));
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (!priv->buffer)
|
||||
if (!priv->cr_surface_data)
|
||||
return;
|
||||
|
||||
data = cogl_buffer_map (priv->buffer, COGL_BUFFER_ACCESS_WRITE);
|
||||
memset (data, 0, priv->buffer_height * priv->rowstride);
|
||||
cogl_buffer_unmap (priv->buffer);
|
||||
memset (priv->cr_surface_data, 0, priv->height * priv->rowstride);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user