[gtk+] gsk: Add gsk_texture_download() API



commit 6c5679314742f33076c46398583baff5ed4a1902
Author: Benjamin Otte <otte redhat com>
Date:   Wed Dec 21 22:11:52 2016 +0100

    gsk: Add gsk_texture_download() API
    
    Now users can download pixels and make everything slooooooow.

 docs/reference/gsk/gsk4-sections.txt |    1 +
 gsk/gskrenderer.c                    |    1 -
 gsk/gsktexture.c                     |   99 +++++++++++++++++++++++++++++++++-
 gsk/gsktexture.h                     |    5 ++
 gsk/gsktextureprivate.h              |    3 +
 5 files changed, 106 insertions(+), 3 deletions(-)
---
diff --git a/docs/reference/gsk/gsk4-sections.txt b/docs/reference/gsk/gsk4-sections.txt
index e27385c..eebc74d 100644
--- a/docs/reference/gsk/gsk4-sections.txt
+++ b/docs/reference/gsk/gsk4-sections.txt
@@ -79,6 +79,7 @@ gsk_texture_new_for_data
 gsk_texture_new_for_pixbuf
 gsk_texture_get_width
 gsk_texture_get_height
+gsk_texture_download
 <SUBSECTION Standard>
 GskTexture
 gsk_texture_get_type
diff --git a/gsk/gskrenderer.c b/gsk/gskrenderer.c
index 87a4074..623e395 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 aabc805..cc8cded 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 317cb3c..67cbe71 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 13eba48..637bc74 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);
 };
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]