[gtk+/wip/otte/texture: 1/3] gsk: Add GskTexture



commit 329a62d11ba2688f56e5bce0eaac76250924adc6
Author: Benjamin Otte <otte redhat com>
Date:   Mon Nov 7 17:59:38 2016 +0100

    gsk: Add GskTexture

 gsk/Makefile.am            |    7 +-
 gsk/gsk.h                  |    1 +
 gsk/gskgldriver.c          |   24 ++++++
 gsk/gskgldriverprivate.h   |    3 +
 gsk/gskglrenderer.c        |  105 +++++++++++++++++++++++-
 gsk/gskrenderer.c          |   42 +++++++++
 gsk/gskrendererprivate.h   |    9 ++
 gsk/gskrendernode.c        |   24 ++++--
 gsk/gskrendernode.h        |    2 +-
 gsk/gskrendernodeprivate.h |    6 +-
 gsk/gsktexture.c           |  197 ++++++++++++++++++++++++++++++++++++++++++++
 gsk/gsktexture.h           |   61 ++++++++++++++
 gsk/gsktextureprivate.h    |   30 +++++++
 gsk/gsktypes.h             |    1 +
 14 files changed, 497 insertions(+), 15 deletions(-)
---
diff --git a/gsk/Makefile.am b/gsk/Makefile.am
index 26aced1..b4cf4f6 100644
--- a/gsk/Makefile.am
+++ b/gsk/Makefile.am
@@ -27,6 +27,7 @@ gsk_public_source_h = \
        gskrenderer.h \
        gskrendernode.h \
        gskrendernodeiter.h \
+       gsktexture.h \
        gsktypes.h
 gsk_private_source_h = \
        gskcairorendererprivate.h \
@@ -38,11 +39,13 @@ gsk_private_source_h = \
        gskprofilerprivate.h \
        gskrendererprivate.h \
        gskrendernodeprivate.h \
-       gskshaderbuilderprivate.h
+       gskshaderbuilderprivate.h \
+       gsktextureprivate.h
 gsk_public_source_c = \
        gskrenderer.c \
        gskrendernode.c \
-       gskrendernodeiter.c
+       gskrendernodeiter.c \
+       gsktexture.c
 gsk_private_source_c = \
        gskcairorenderer.c \
        gskdebug.c \
diff --git a/gsk/gsk.h b/gsk/gsk.h
index 01c4569..394895c 100644
--- a/gsk/gsk.h
+++ b/gsk/gsk.h
@@ -24,6 +24,7 @@
 #include <gsk/gskrenderer.h>
 #include <gsk/gskrendernode.h>
 #include <gsk/gskrendernodeiter.h>
+#include <gsk/gsktexture.h>
 
 #include <gsk/gsktypes.h>
 #include <gsk/gskenumtypes.h>
diff --git a/gsk/gskgldriver.c b/gsk/gskgldriver.c
index a0bd8e3..da21f6a 100644
--- a/gsk/gskgldriver.c
+++ b/gsk/gskgldriver.c
@@ -15,6 +15,7 @@ typedef struct {
   GLuint mag_filter;
   GArray *fbos;
   gboolean in_use : 1;
+  gboolean reserved : 1;
 } Texture;
 
 typedef struct {
@@ -75,6 +76,8 @@ texture_free (gpointer data)
 {
   Texture *t = data;
 
+  g_warn_if_fail (!t->reserved);
+
   g_clear_pointer (&t->fbos, g_array_unref);
   glDeleteTextures (1, &t->texture_id);
   g_slice_free (Texture, t);
@@ -269,6 +272,9 @@ gsk_gl_driver_collect_textures (GskGLDriver *driver)
     {
       Texture *t = value_p;
 
+      if (t->reserved)
+        continue;
+
       if (t->in_use)
         {
           t->in_use = FALSE;
@@ -379,6 +385,7 @@ find_texture_by_size (GHashTable *textures,
 
 int
 gsk_gl_driver_create_texture (GskGLDriver *driver,
+                              gboolean     reserve,
                               int          width,
                               int          height)
 {
@@ -404,6 +411,7 @@ gsk_gl_driver_create_texture (GskGLDriver *driver,
       GSK_NOTE (OPENGL, g_print ("Reusing Texture(%d) for size %dx%d\n",
                                  t->texture_id, t->width, t->height));
       t->in_use = TRUE;
+      t->reserved = reserve;
       return t->texture_id;
     }
 
@@ -416,11 +424,27 @@ gsk_gl_driver_create_texture (GskGLDriver *driver,
   t->min_filter = GL_NEAREST;
   t->mag_filter = GL_NEAREST;
   t->in_use = TRUE;
+  t->reserved = reserve;
   g_hash_table_insert (driver->textures, GINT_TO_POINTER (texture_id), t);
 
   return t->texture_id;
 }
 
+void
+gsk_gl_driver_release_texture (GskGLDriver *driver,
+                               int          texture_id)
+{
+  Texture *t;
+  
+  g_return_if_fail (GSK_IS_GL_DRIVER (driver));
+  
+  t = gsk_gl_driver_get_texture (driver, texture_id);
+  g_return_if_fail (t != NULL);
+  g_return_if_fail (t->reserved);
+
+  t->reserved = FALSE;
+}
+
 static Vao *
 find_vao (GHashTable    *vaos,
           int            position_id,
diff --git a/gsk/gskgldriverprivate.h b/gsk/gskgldriverprivate.h
index 6a41174..636f59c 100644
--- a/gsk/gskgldriverprivate.h
+++ b/gsk/gskgldriverprivate.h
@@ -24,8 +24,11 @@ void            gsk_gl_driver_begin_frame               (GskGLDriver     *driver
 void            gsk_gl_driver_end_frame                 (GskGLDriver     *driver);
 
 int             gsk_gl_driver_create_texture            (GskGLDriver     *driver,
+                                                         gboolean         reserved,
                                                          int              width,
                                                          int              height);
+void            gsk_gl_driver_release_texture           (GskGLDriver     *driver,
+                                                         int              texture_id);
 int             gsk_gl_driver_create_vao_for_quad       (GskGLDriver     *driver,
                                                          int              position_id,
                                                          int              uv_id,
diff --git a/gsk/gskglrenderer.c b/gsk/gskglrenderer.c
index 8f849a7..be94799 100644
--- a/gsk/gskglrenderer.c
+++ b/gsk/gskglrenderer.c
@@ -11,6 +11,7 @@
 #include "gskrendernodeprivate.h"
 #include "gskrendernodeiter.h"
 #include "gskshaderbuilderprivate.h"
+#include "gsktextureprivate.h"
 
 #include "gskprivate.h"
 
@@ -89,6 +90,13 @@ typedef struct {
 } ProfileTimers;
 #endif
 
+typedef struct _GskGLTexture GskGLTexture;
+struct _GskGLTexture {
+  GskTexture texture;
+
+  int texture_id;
+};
+
 struct _GskGLRenderer
 {
   GskRenderer parent_instance;
@@ -128,6 +136,86 @@ struct _GskGLRendererClass
 
 G_DEFINE_TYPE (GskGLRenderer, gsk_gl_renderer, GSK_TYPE_RENDERER)
 
+static GskTexture *
+gsk_gl_renderer_texture_new_for_data (GskRenderer  *renderer,
+                                      const guchar *data,
+                                      int           width,
+                                      int           height,
+                                      int           stride)
+{
+  GskGLRenderer *self = GSK_GL_RENDERER (renderer);
+  GskGLTexture *texture;
+  cairo_surface_t *surface;
+
+  gdk_gl_context_make_current (self->gl_context);
+  gsk_gl_driver_begin_frame (self->gl_driver);
+
+  /* XXX: Make this work without having to create cairo surfaces */
+  surface = cairo_image_surface_create_for_data ((guchar *) data, CAIRO_FORMAT_ARGB32, width, height, 
stride);
+
+  texture = gsk_texture_new (GskGLTexture, renderer, width, height);
+
+  texture->texture_id = gsk_gl_driver_create_texture (self->gl_driver,
+                                                      TRUE,
+                                                      width, height);
+  gsk_gl_driver_bind_source_texture (self->gl_driver, texture->texture_id);
+  gsk_gl_driver_init_texture_with_surface (self->gl_driver,
+                                           texture->texture_id,
+                                           surface,
+                                           GL_NEAREST,
+                                           GL_NEAREST);
+
+  cairo_surface_destroy (surface);
+
+  gsk_gl_driver_end_frame (self->gl_driver);
+
+  return &texture->texture;
+}
+
+static GskTexture *
+gsk_gl_renderer_texture_new_for_pixbuf (GskRenderer *renderer,
+                                        GdkPixbuf   *pixbuf)
+{
+  GskGLRenderer *self = GSK_GL_RENDERER (renderer);
+  GskGLTexture *texture;
+  cairo_surface_t *surface;
+  int width, height;
+
+  gdk_gl_context_make_current (self->gl_context);
+  gsk_gl_driver_begin_frame (self->gl_driver);
+
+  surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
+  width = gdk_pixbuf_get_width (pixbuf);
+  height = gdk_pixbuf_get_height (pixbuf);
+
+  texture = gsk_texture_new (GskGLTexture, renderer, width, height);
+
+  texture->texture_id = gsk_gl_driver_create_texture (self->gl_driver,
+                                                      TRUE,
+                                                      width, height);
+  gsk_gl_driver_bind_source_texture (self->gl_driver, texture->texture_id);
+  gsk_gl_driver_init_texture_with_surface (self->gl_driver,
+                                           texture->texture_id,
+                                           surface,
+                                           GL_NEAREST,
+                                           GL_NEAREST);
+
+  gsk_gl_driver_end_frame (self->gl_driver);
+
+  cairo_surface_destroy (surface);
+
+  return &texture->texture;
+}
+
+static void
+gsk_gl_renderer_texture_destroy (GskTexture *texture)
+{
+  GskGLTexture *gltexture = (GskGLTexture *) texture;
+  GskGLRenderer *self = GSK_GL_RENDERER (gsk_texture_get_renderer (texture));
+
+  gsk_gl_driver_release_texture (self->gl_driver, gltexture->texture_id);
+}
+
 static void
 gsk_gl_renderer_dispose (GObject *gobject)
 {
@@ -152,6 +240,7 @@ gsk_gl_renderer_create_buffers (GskGLRenderer *self,
   if (self->texture_id == 0)
     {
       self->texture_id = gsk_gl_driver_create_texture (self->gl_driver,
+                                                       FALSE,
                                                        width * scale_factor,
                                                        height * scale_factor);
       gsk_gl_driver_bind_source_texture (self->gl_driver, self->texture_id);
@@ -693,7 +782,7 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
   if (render_node_needs_render_target (node))
     {
       item.render_data.render_target_id =
-        gsk_gl_driver_create_texture (self->gl_driver, item.size.width, item.size.height);
+        gsk_gl_driver_create_texture (self->gl_driver, FALSE, item.size.width, item.size.height);
       gsk_gl_driver_init_texture_empty (self->gl_driver, item.render_data.render_target_id);
       gsk_gl_driver_create_render_target (self->gl_driver, item.render_data.render_target_id, TRUE, TRUE);
 
@@ -708,7 +797,14 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
 
   if (gsk_render_node_has_texture (node))
     {
-      item.render_data.texture_id = gsk_render_node_get_texture (node);
+      GskTexture *texture = gsk_render_node_get_texture (node);
+
+      if (gsk_texture_get_renderer (texture) != GSK_RENDERER (self))
+        {
+          g_warning ("Given Texture belongs to wrong renderer, ignoring.");
+          goto out;
+        }
+      item.render_data.texture_id = ((GskGLTexture *) texture)->texture_id;
     }
   else if (gsk_render_node_has_surface (node))
     {
@@ -719,6 +815,7 @@ gsk_gl_renderer_add_render_item (GskGLRenderer           *self,
 
       /* Upload the Cairo surface to a GL texture */
       item.render_data.texture_id = gsk_gl_driver_create_texture (self->gl_driver,
+                                                                  FALSE,
                                                                   item.size.width,
                                                                   item.size.height);
       gsk_gl_driver_bind_source_texture (self->gl_driver, item.render_data.texture_id);
@@ -965,6 +1062,10 @@ gsk_gl_renderer_class_init (GskGLRendererClass *klass)
   renderer_class->realize = gsk_gl_renderer_realize;
   renderer_class->unrealize = gsk_gl_renderer_unrealize;
   renderer_class->render = gsk_gl_renderer_render;
+
+  renderer_class->texture_new_for_data = gsk_gl_renderer_texture_new_for_data;
+  renderer_class->texture_new_for_pixbuf = gsk_gl_renderer_texture_new_for_pixbuf;
+  renderer_class->texture_destroy = gsk_gl_renderer_texture_destroy;
 }
 
 static void
diff --git a/gsk/gskrenderer.c b/gsk/gskrenderer.c
index 3bdab32..de2867f 100644
--- a/gsk/gskrenderer.c
+++ b/gsk/gskrenderer.c
@@ -42,6 +42,7 @@
 #include "gskglrendererprivate.h"
 #include "gskprofilerprivate.h"
 #include "gskrendernodeprivate.h"
+#include "gsktexture.h"
 
 #include "gskenumtypes.h"
 
@@ -133,6 +134,44 @@ gsk_renderer_real_create_cairo_surface (GskRenderer    *self,
   return res;
 }
 
+static GskTexture *
+gsk_renderer_real_texture_new_for_data (GskRenderer  *self,
+                                        const guchar *data,
+                                        int           width,
+                                        int           height,
+                                        int           stride)
+{
+  GSK_RENDERER_WARN_NOT_IMPLEMENTED_METHOD (self, texture_new_for_data);
+
+  return NULL;
+}
+
+static GskTexture *
+gsk_renderer_real_texture_new_for_pixbuf (GskRenderer *renderer,
+                                          GdkPixbuf   *pixbuf)
+{
+  GskTexture *texture;
+  cairo_surface_t *surface;
+
+  surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
+
+  texture = gsk_texture_new_for_data (renderer,
+                                      cairo_image_surface_get_data (surface),
+                                      cairo_image_surface_get_width (surface),
+                                      cairo_image_surface_get_height (surface),
+                                      cairo_image_surface_get_stride (surface));
+
+  cairo_surface_destroy (surface);
+
+  return texture;
+}
+
+static void
+gsk_renderer_real_texture_destroy (GskTexture *texture)
+{
+  GSK_RENDERER_WARN_NOT_IMPLEMENTED_METHOD (gsk_texture_get_renderer (texture), texture_destroy);
+}
+
 static void
 gsk_renderer_dispose (GObject *gobject)
 {
@@ -239,6 +278,9 @@ gsk_renderer_class_init (GskRendererClass *klass)
   klass->unrealize = gsk_renderer_real_unrealize;
   klass->render = gsk_renderer_real_render;
   klass->create_cairo_surface = gsk_renderer_real_create_cairo_surface;
+  klass->texture_new_for_data = gsk_renderer_real_texture_new_for_data;
+  klass->texture_new_for_pixbuf = gsk_renderer_real_texture_new_for_pixbuf;
+  klass->texture_destroy = gsk_renderer_real_texture_destroy;
 
   gobject_class->constructed = gsk_renderer_constructed;
   gobject_class->set_property = gsk_renderer_set_property;
diff --git a/gsk/gskrendererprivate.h b/gsk/gskrendererprivate.h
index 57f7e86..5fdc130 100644
--- a/gsk/gskrendererprivate.h
+++ b/gsk/gskrendererprivate.h
@@ -47,6 +47,15 @@ struct _GskRendererClass
                                               cairo_format_t,
                                               int width,
                                               int height);
+  /* called from gsktexture.c */
+  GskTexture * (* texture_new_for_data) (GskRenderer *renderer,
+                                         const guchar *data,
+                                         int width,
+                                         int height,
+                                         int stride);
+  GskTexture * (* texture_new_for_pixbuf) (GskRenderer *renderer,
+                                           GdkPixbuf   *pixbuf);
+  void (* texture_destroy) (GskTexture *texture);
 };
 
 gboolean gsk_renderer_is_realized (GskRenderer *renderer);
diff --git a/gsk/gskrendernode.c b/gsk/gskrendernode.c
index 2b56b10..24bb2a7 100644
--- a/gsk/gskrendernode.c
+++ b/gsk/gskrendernode.c
@@ -46,6 +46,7 @@
 #include "gskdebugprivate.h"
 #include "gskrendernodeiter.h"
 #include "gskrendererprivate.h"
+#include "gsktexture.h"
 
 #include <graphene-gobject.h>
 
@@ -1204,33 +1205,42 @@ gsk_render_node_has_texture (GskRenderNode *node)
 {
   g_return_val_if_fail (GSK_IS_RENDER_NODE (node), FALSE);
 
-  return node->texture_id != 0;
+  return node->texture != NULL;
 }
 
-int
+GskTexture *
 gsk_render_node_get_texture (GskRenderNode *node)
 {
   g_return_val_if_fail (GSK_IS_RENDER_NODE (node), 0);
 
-  return node->texture_id;
+  return node->texture;
 }
 
 /**
  * gsk_render_node_set_texture:
  * @node: a #GskRenderNode
- * @texture_id: the object id of a GL texture
+ * @texture: the #GskTexture
  *
- * Associates a @texture_id to a #GskRenderNode.
+ * Associates a #GskTexture to a #GskRenderNode.
  *
  * Since: 3.90
  */
 void
 gsk_render_node_set_texture (GskRenderNode *node,
-                             int            texture_id)
+                             GskTexture    *texture)
 {
   g_return_if_fail (GSK_IS_RENDER_NODE (node));
 
-  node->texture_id = texture_id;
+  if (node->texture == texture)
+    return;
+
+  if (node->texture)
+    gsk_texture_unref (node->texture);
+
+  node->texture = texture;
+
+  if (texture)
+    gsk_texture_ref (texture);
 }
 
 /*< private >
diff --git a/gsk/gskrendernode.h b/gsk/gskrendernode.h
index 3863423..c6f5086 100644
--- a/gsk/gskrendernode.h
+++ b/gsk/gskrendernode.h
@@ -119,7 +119,7 @@ void                    gsk_render_node_set_blend_mode          (GskRenderNode *
                                                                  GskBlendMode   blend_mode);
 GDK_AVAILABLE_IN_3_90
 void                    gsk_render_node_set_texture             (GskRenderNode *node,
-                                                                 int            texture_id);
+                                                                 GskTexture    *texture);
 GDK_AVAILABLE_IN_3_90
 void                    gsk_render_node_set_scaling_filter      (GskRenderNode *node,
                                                                  GskScalingFilter min_filter,
diff --git a/gsk/gskrendernodeprivate.h b/gsk/gskrendernodeprivate.h
index 20e6084..3447822 100644
--- a/gsk/gskrendernodeprivate.h
+++ b/gsk/gskrendernodeprivate.h
@@ -34,8 +34,8 @@ struct _GskRenderNode
   /* The contents of the node as a Cairo surface */
   cairo_surface_t *surface;
 
-  /* The contents of the node as a GL surface */
-  int texture_id;
+  /* The contents of the node as a texture */
+  GskTexture *texture;
 
   /* Paint opacity */
   double opacity;
@@ -85,7 +85,7 @@ double gsk_render_node_get_opacity (GskRenderNode *node);
 
 cairo_surface_t *gsk_render_node_get_surface (GskRenderNode *node);
 
-int gsk_render_node_get_texture (GskRenderNode *node);
+GskTexture *gsk_render_node_get_texture (GskRenderNode *node);
 
 gboolean gsk_render_node_has_surface (GskRenderNode *node);
 gboolean gsk_render_node_has_texture (GskRenderNode *node);
diff --git a/gsk/gsktexture.c b/gsk/gsktexture.c
new file mode 100644
index 0000000..956625b
--- /dev/null
+++ b/gsk/gsktexture.c
@@ -0,0 +1,197 @@
+/* GSK - The GTK Scene Kit
+ *
+ * Copyright 2016  Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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/>.
+ */
+
+/**
+ * SECTION:GskTexture
+ * @Title: GskTexture
+ * @Short_description: Pixel data uploaded to a #GskRenderer
+ *
+ * #GskTexture is the basic element used to refer to pixel data.
+ *
+ * It can only be created for an existing realized #GskRenderer and becomes
+ * invalid when the renderer gets unrealized.
+ *
+ * You cannot get your pixel data back once you've uploaded it.
+ *
+ * #GskTexture is an immutable structure: That means you cannot change
+ * anything about it other than increasing the reference count via
+ * gsk_texture_ref().
+ */
+
+#include "config.h"
+
+#include "gsktextureprivate.h"
+
+#include "gskdebugprivate.h"
+#include "gskrendererprivate.h"
+
+/**
+ * GskTexture: (ref-func gsk_texture_ref) (unref-func gsk_texture_unref)
+ *
+ * The `GskTexture` structure contains only private data.
+ *
+ * Since: 3.90
+ */
+
+G_DEFINE_BOXED_TYPE(GskTexture, gsk_texture, gsk_texture_ref, gsk_texture_unref)
+
+static void
+gsk_texture_finalize (GskTexture *self)
+{    
+  GSK_RENDERER_GET_CLASS (self->renderer)->texture_destroy (self);
+
+  g_object_unref (self->renderer);
+
+  g_free (self);
+}
+
+/**
+ * gsk_texture_ref:
+ * @texture: a #GskTexture
+ *
+ * Acquires a reference on the given #GskTexture.
+ *
+ * Returns: (transfer none): the #GskTexture with an additional reference
+ *
+ * Since: 3.90
+ */
+GskTexture *
+gsk_texture_ref (GskTexture *texture)
+{
+  g_return_val_if_fail (GSK_IS_TEXTURE (texture), NULL);
+
+  g_atomic_int_inc (&texture->ref_count);
+
+  return texture;
+}
+
+/**
+ * gsk_texture_unref:
+ * @texture: a #GskTexture
+ *
+ * Releases a reference on the given #GskTexture.
+ *
+ * If the reference was the last, the resources associated to the @texture are
+ * freed.
+ *
+ * Since: 3.90
+ */
+void
+gsk_texture_unref (GskTexture *texture)
+{
+  g_return_if_fail (GSK_IS_TEXTURE (texture));
+
+  if (g_atomic_int_dec_and_test (&texture->ref_count))
+    gsk_texture_finalize (texture);
+}
+
+GskTexture *
+gsk_texture_alloc (gsize           size,
+                   GskRenderer    *renderer,
+                   int             width,
+                   int             height)
+{
+  GskTexture *self;
+
+  g_assert (size >= sizeof (GskTexture));
+
+  self = g_malloc0 (size);
+
+  self->ref_count = 1;
+
+  self->renderer = g_object_ref (renderer);
+  self->width = width;
+  self->height = height;
+
+  return self;
+}
+
+GskTexture *
+gsk_texture_new_for_data (GskRenderer  *renderer,
+                          const guchar *data,
+                          int           width,
+                          int           height,
+                          int           stride)
+{
+  return GSK_RENDERER_GET_CLASS (renderer)->texture_new_for_data (renderer, data, width, height, stride);
+}
+
+GskTexture *
+gsk_texture_new_for_pixbuf (GskRenderer *renderer,
+                            GdkPixbuf   *pixbuf)
+{
+  g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
+  g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
+
+  return GSK_RENDERER_GET_CLASS (renderer)->texture_new_for_pixbuf (renderer, pixbuf);
+}
+
+/**
+ * gsk_texture_get_renderer:
+ * @texture: a #GskTexture
+ *
+ * Returns the renderer that @texture was created for.
+ *
+ * Returns: (transfer none): the renderer of the #GskTexture
+ *
+ * Since: 3.90
+ */
+GskRenderer *
+gsk_texture_get_renderer (GskTexture *texture)
+{
+  g_return_val_if_fail (GSK_IS_TEXTURE (texture), NULL);
+
+  return texture->renderer;
+}
+
+/**
+ * gsk_texture_get_width:
+ * @texture: a #GskTexture
+ *
+ * Returns the width of @texture.
+ *
+ * Returns: the width of the #GskTexture
+ *
+ * Since: 3.90
+ */
+int
+gsk_texture_get_width (GskTexture *texture)
+{
+  g_return_val_if_fail (GSK_IS_TEXTURE (texture), 0);
+
+  return texture->width;
+}
+
+/**
+ * gsk_texture_get_height:
+ * @texture: a #GskTexture
+ *
+ * Returns the height of the @texture.
+ *
+ * Returns: the height of the #GskTexture
+ *
+ * Since: 3.90
+ */
+int
+gsk_texture_get_height (GskTexture *texture)
+{
+  g_return_val_if_fail (GSK_IS_TEXTURE (texture), 0);
+
+  return texture->height;
+}
+
diff --git a/gsk/gsktexture.h b/gsk/gsktexture.h
new file mode 100644
index 0000000..1d1c81e
--- /dev/null
+++ b/gsk/gsktexture.h
@@ -0,0 +1,61 @@
+/* GSK - The GTK Scene Kit
+ *
+ * Copyright 2016  Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * 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/>.
+ */
+
+#ifndef __GSK_TEXTURE_H__
+#define __GSK_TEXTURE_H__
+
+#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
+#error "Only <gsk/gsk.h> can be included directly."
+#endif
+
+#include <gsk/gsktypes.h>
+
+G_BEGIN_DECLS
+
+#define GSK_TYPE_TEXTURE (gsk_texture_get_type ())
+
+#define GSK_IS_TEXTURE(texture) ((texture) != NULL)
+
+GDK_AVAILABLE_IN_3_90
+GType gsk_texture_get_type (void) G_GNUC_CONST;
+
+GDK_AVAILABLE_IN_3_90
+GskTexture *            gsk_texture_ref                        (GskTexture      *texture);
+GDK_AVAILABLE_IN_3_90
+void                    gsk_texture_unref                      (GskTexture      *texture);
+
+GDK_AVAILABLE_IN_3_90
+GskTexture *            gsk_texture_new_for_data               (GskRenderer     *renderer,
+                                                                const guchar    *data,
+                                                                int              width,
+                                                                int              height,
+                                                                int              stride);
+GDK_AVAILABLE_IN_3_90
+GskTexture *            gsk_texture_new_for_pixbuf             (GskRenderer     *renderer,
+                                                                GdkPixbuf       *pixbuf);
+
+GDK_AVAILABLE_IN_3_90
+GskRenderer *           gsk_texture_get_renderer               (GskTexture      *texture);
+GDK_AVAILABLE_IN_3_90
+int                     gsk_texture_get_width                  (GskTexture      *texture);
+GDK_AVAILABLE_IN_3_90
+int                     gsk_texture_get_height                 (GskTexture      *texture);
+
+G_END_DECLS
+
+#endif /* __GSK_TEXTURE_H__ */
diff --git a/gsk/gsktextureprivate.h b/gsk/gsktextureprivate.h
new file mode 100644
index 0000000..887a03a
--- /dev/null
+++ b/gsk/gsktextureprivate.h
@@ -0,0 +1,30 @@
+#ifndef __GSK_TEXTURE_PRIVATE_H__
+#define __GSK_TEXTURE_PRIVATE_H__
+
+#include "gsktexture.h"
+
+G_BEGIN_DECLS
+
+#define GSK_TEXTURE_CLASS(klass)            (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_TEXTURE, 
GskTextureClass))
+#define GSK_IS_TEXTURE_CLASS(klass)         (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_TEXTURE))
+#define GSK_TEXTURE_GET_CLASS(obj)          (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_TEXTURE, 
GskTextureClass))
+
+struct _GskTexture
+{
+  volatile int ref_count;
+
+  GskRenderer *renderer;
+  int width;
+  int height;
+};
+
+#define gsk_texture_new(type,renderer,width,height) \
+  (type *) gsk_texture_alloc(sizeof (type),(renderer),(width),(height))
+GskTexture *gsk_texture_alloc (gsize           size,
+                               GskRenderer    *renderer,
+                               int             width,
+                               int             height);
+
+G_END_DECLS
+
+#endif /* __GSK_TEXTURE_PRIVATE_H__ */
diff --git a/gsk/gsktypes.h b/gsk/gsktypes.h
index eae1591..32fab4c 100644
--- a/gsk/gsktypes.h
+++ b/gsk/gsktypes.h
@@ -27,5 +27,6 @@
 #include <gsk/gskenums.h>
 
 typedef struct _GskRenderer             GskRenderer;
+typedef struct _GskTexture              GskTexture;
 
 #endif /* __GSK_TYPES_H__ */


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