diff options
author | Benjamin Otte <otte@redhat.com> | 2016-12-21 22:11:52 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2016-12-23 08:11:01 +0100 |
commit | 6c5679314742f33076c46398583baff5ed4a1902 (patch) | |
tree | 74d9a4802e5128e4d67aaec12a6475462bbe0201 /gsk | |
parent | d58799ff7aa11266efcfd9bc4c3a780c2a5d6879 (diff) | |
download | gtk+-6c5679314742f33076c46398583baff5ed4a1902.tar.gz |
gsk: Add gsk_texture_download() API
Now users can download pixels and make everything slooooooow.
Diffstat (limited to 'gsk')
-rw-r--r-- | gsk/gskrenderer.c | 1 | ||||
-rw-r--r-- | gsk/gsktexture.c | 99 | ||||
-rw-r--r-- | gsk/gsktexture.h | 5 | ||||
-rw-r--r-- | gsk/gsktextureprivate.h | 3 |
4 files changed, 105 insertions, 3 deletions
diff --git a/gsk/gskrenderer.c b/gsk/gskrenderer.c index 87a4074735..623e395bc4 100644 --- a/gsk/gskrenderer.c +++ b/gsk/gskrenderer.c @@ -650,7 +650,6 @@ gsk_renderer_render_texture (GskRenderer *renderer, g_return_val_if_fail (priv->root_node == NULL, NULL); priv->root_node = gsk_render_node_ref (root); - gsk_render_node_make_immutable (priv->root_node); if (viewport == NULL) { diff --git a/gsk/gsktexture.c b/gsk/gsktexture.c index aabc805f0d..cc8cdedfce 100644 --- a/gsk/gsktexture.c +++ b/gsk/gsktexture.c @@ -37,6 +37,8 @@ #include "gskdebugprivate.h" #include "gskrenderer.h" +#include "gdk/gdkinternals.h" + /** * GskTexture: (ref-func gsk_texture_ref) (unref-func gsk_texture_unref) * @@ -142,10 +144,35 @@ gsk_texture_cairo_download_surface (GskTexture *texture) return cairo_surface_reference (cairo->surface); } +static void +gsk_texture_cairo_download (GskTexture *texture, + guchar *data, + gsize stride) +{ + GskCairoTexture *cairo = (GskCairoTexture *) texture; + cairo_surface_t *surface; + cairo_t *cr; + + surface = cairo_image_surface_create_for_data (data, + CAIRO_FORMAT_ARGB32, + texture->width, texture->height, + stride); + cr = cairo_create (surface); + + cairo_set_source_surface (cr, cairo->surface, 0, 0); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + + cairo_destroy (cr); + cairo_surface_finish (surface); + cairo_surface_destroy (surface); +} + static const GskTextureClass GSK_TEXTURE_CLASS_CAIRO = { "cairo", sizeof (GskCairoTexture), gsk_texture_cairo_finalize, + gsk_texture_cairo_download, gsk_texture_cairo_download_surface }; @@ -208,6 +235,23 @@ gsk_texture_pixbuf_finalize (GskTexture *texture) g_object_unref (pixbuf->pixbuf); } +static void +gsk_texture_pixbuf_download (GskTexture *texture, + guchar *data, + gsize stride) +{ + GskPixbufTexture *pixbuf = (GskPixbufTexture *) texture; + cairo_surface_t *surface; + + surface = cairo_image_surface_create_for_data (data, + CAIRO_FORMAT_ARGB32, + texture->width, texture->height, + stride); + gdk_cairo_surface_paint_pixbuf (surface, pixbuf->pixbuf); + cairo_surface_finish (surface); + cairo_surface_destroy (surface); +} + static cairo_surface_t * gsk_texture_pixbuf_download_surface (GskTexture *texture) { @@ -220,7 +264,8 @@ static const GskTextureClass GSK_TEXTURE_CLASS_PIXBUF = { "pixbuf", sizeof (GskPixbufTexture), gsk_texture_pixbuf_finalize, - gsk_texture_pixbuf_download_surface, + gsk_texture_pixbuf_download, + gsk_texture_pixbuf_download_surface }; GskTexture * @@ -278,7 +323,57 @@ gsk_texture_get_height (GskTexture *texture) cairo_surface_t * gsk_texture_download_surface (GskTexture *texture) { - return texture->klass->download_surface (texture); + cairo_surface_t *surface; + + if (texture->klass->download_surface) + return texture->klass->download_surface (texture); + + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + texture->width, texture->height); + gsk_texture_download (texture, + cairo_image_surface_get_data (surface), + cairo_image_surface_get_stride (surface)); + cairo_surface_mark_dirty (surface); + + return surface; +} + +/** + * gsk_texture_download: + * @texture: a #GskTexture + * @data: pointer to enough memory to be filled with the + * downloaded data of @texture + * @stride: rowstride in bytes + * + * Downloads the @texture into local memory. This may be + * an expensive operation, as the actual texture data may + * reside on a GPU or on a remote display server. + * + * The data format of the downloaded data is equivalent to + * %CAIRO_FORMAT_ARGB32, so every downloaded pixel requires + * 4 bytes of memory. + * + * Downloading a texture into a Cairo image surface: + * |[<!-- language="C" --> + * surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + * gsk_texture_get_width (texture), + * gsk_texture_get_height (texture)); + * gsk_texture_download (texture, + * cairo_image_surface_get_data (surface), + * cairo_image_surface_get_stride (surface)); + * cairo_surface_mark_dirty (surface); + * ]| + **/ +void +gsk_texture_download (GskTexture *texture, + guchar *data, + gsize stride) +{ + g_return_if_fail (GSK_IS_TEXTURE (texture)); + g_return_if_fail (data != NULL); + g_return_if_fail (stride >= gsk_texture_get_width (texture) * 4); + + return texture->klass->download (texture, data, stride); } gboolean diff --git a/gsk/gsktexture.h b/gsk/gsktexture.h index 317cb3c34c..67cbe718c4 100644 --- a/gsk/gsktexture.h +++ b/gsk/gsktexture.h @@ -52,6 +52,11 @@ int gsk_texture_get_width (GskTexture GDK_AVAILABLE_IN_3_90 int gsk_texture_get_height (GskTexture *texture); +GDK_AVAILABLE_IN_3_90 +void gsk_texture_download (GskTexture *texture, + guchar *data, + gsize stride); + G_END_DECLS #endif /* __GSK_TEXTURE_H__ */ diff --git a/gsk/gsktextureprivate.h b/gsk/gsktextureprivate.h index 13eba48eae..637bc74343 100644 --- a/gsk/gsktextureprivate.h +++ b/gsk/gsktextureprivate.h @@ -30,6 +30,9 @@ struct _GskTextureClass { gsize size; void (* finalize) (GskTexture *texture); + void (* download) (GskTexture *texture, + guchar *data, + gsize stride); cairo_surface_t * (* download_surface) (GskTexture *texture); }; |