summaryrefslogtreecommitdiff
path: root/gsk
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2016-11-16 04:14:32 +0100
committerBenjamin Otte <otte@redhat.com>2016-11-16 17:36:33 +0100
commit40565fb0308ba2e8a91a853af024bff49bd84a38 (patch)
tree828edcad15753dc51fd9e02b32eb91c07959eae7 /gsk
parent455ce80ff7a98f3ef7591ac789ea2ea4e6a42053 (diff)
downloadgtk+-40565fb0308ba2e8a91a853af024bff49bd84a38.tar.gz
gsk: Rework GskTexture
We do no longer bind textures to a renderer, instead they are a way for applications to provide texture data. For now, that's it. We've reverted to uploading it from scratch every frame.
Diffstat (limited to 'gsk')
-rw-r--r--gsk/gskcairorenderer.c87
-rw-r--r--gsk/gskglrenderer.c112
-rw-r--r--gsk/gskrenderer.c41
-rw-r--r--gsk/gskrendererprivate.h9
-rw-r--r--gsk/gsktexture.c159
-rw-r--r--gsk/gsktexture.h8
-rw-r--r--gsk/gsktextureprivate.h24
7 files changed, 159 insertions, 281 deletions
diff --git a/gsk/gskcairorenderer.c b/gsk/gskcairorenderer.c
index 360a25020d..501b5407e9 100644
--- a/gsk/gskcairorenderer.c
+++ b/gsk/gskcairorenderer.c
@@ -20,12 +20,6 @@ struct _GskCairoRendererClass
GskRendererClass parent_class;
};
-typedef struct _GskCairoTexture GskCairoTexture;
-struct _GskCairoTexture {
- GskTexture texture;
- cairo_surface_t *surface;
-};
-
G_DEFINE_TYPE (GskCairoRenderer, gsk_cairo_renderer, GSK_TYPE_RENDERER)
static gboolean
@@ -99,10 +93,12 @@ gsk_cairo_renderer_render_node (GskCairoRenderer *self,
frame.origin.x, frame.origin.y));
if (gsk_render_node_has_texture (node))
{
- GskCairoTexture *cairo_texture = (GskCairoTexture *) gsk_render_node_get_texture (node);
+ GskTexture *texture = gsk_render_node_get_texture (node);
+ cairo_surface_t *surface = gsk_texture_download (texture);
- cairo_set_source_surface (cr, cairo_texture->surface, frame.origin.x, frame.origin.y);
+ cairo_set_source_surface (cr, surface, frame.origin.x, frame.origin.y);
cairo_paint (cr);
+ cairo_surface_destroy (surface);
}
else
{
@@ -186,77 +182,6 @@ gsk_cairo_renderer_render (GskRenderer *renderer,
gsk_cairo_renderer_render_node (self, root, cr);
}
-static GskTexture *
-gsk_cairo_texture_new_for_surface (GskRenderer *renderer,
- cairo_surface_t *surface,
- int width,
- int height)
-{
- GskCairoTexture *texture;
-
- texture = gsk_texture_new (GskCairoTexture, renderer, width, height);
-
- texture->surface = cairo_surface_reference (surface);
-
- return (GskTexture *) texture;
-}
-
-static GskTexture *
-gsk_cairo_renderer_texture_new_for_data (GskRenderer *renderer,
- const guchar *data,
- int width,
- int height,
- int stride)
-{
- GskTexture *texture;
- cairo_surface_t *original, *copy;
- cairo_t *cr;
-
- original = cairo_image_surface_create_for_data ((guchar *) data, CAIRO_FORMAT_ARGB32, width, height, stride);
- copy = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
-
- cr = cairo_create (copy);
- cairo_set_source_surface (cr, original, 0, 0);
- cairo_paint (cr);
- cairo_destroy (cr);
-
- texture = gsk_cairo_texture_new_for_surface (renderer,
- copy,
- width, height);
-
- cairo_surface_destroy (copy);
- cairo_surface_destroy (original);
-
- return texture;
-}
-
-static GskTexture *
-gsk_cairo_renderer_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_cairo_texture_new_for_surface (renderer,
- surface,
- gdk_pixbuf_get_width (pixbuf),
- gdk_pixbuf_get_height (pixbuf));
-
- cairo_surface_destroy (surface);
-
- return texture;
-}
-
-static void
-gsk_cairo_renderer_texture_destroy (GskTexture *texture)
-{
- GskCairoTexture *cairo_texture = (GskCairoTexture *) texture;
-
- cairo_surface_destroy (cairo_texture->surface);
-}
-
static void
gsk_cairo_renderer_class_init (GskCairoRendererClass *klass)
{
@@ -265,10 +190,6 @@ gsk_cairo_renderer_class_init (GskCairoRendererClass *klass)
renderer_class->realize = gsk_cairo_renderer_realize;
renderer_class->unrealize = gsk_cairo_renderer_unrealize;
renderer_class->render = gsk_cairo_renderer_render;
-
- renderer_class->texture_new_for_data = gsk_cairo_renderer_texture_new_for_data;
- renderer_class->texture_new_for_pixbuf = gsk_cairo_renderer_texture_new_for_pixbuf;
- renderer_class->texture_destroy = gsk_cairo_renderer_texture_destroy;
}
static void
diff --git a/gsk/gskglrenderer.c b/gsk/gskglrenderer.c
index be9479944b..c6824acac9 100644
--- a/gsk/gskglrenderer.c
+++ b/gsk/gskglrenderer.c
@@ -90,13 +90,6 @@ typedef struct {
} ProfileTimers;
#endif
-typedef struct _GskGLTexture GskGLTexture;
-struct _GskGLTexture {
- GskTexture texture;
-
- int texture_id;
-};
-
struct _GskGLRenderer
{
GskRenderer parent_instance;
@@ -136,86 +129,6 @@ 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)
{
@@ -798,13 +711,22 @@ gsk_gl_renderer_add_render_item (GskGLRenderer *self,
if (gsk_render_node_has_texture (node))
{
GskTexture *texture = gsk_render_node_get_texture (node);
+ cairo_surface_t *surface = gsk_texture_download (texture);
+ int gl_min_filter = GL_NEAREST, gl_mag_filter = GL_NEAREST;
- 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;
+ get_gl_scaling_filters (node, &gl_min_filter, &gl_mag_filter);
+
+ /* 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);
+ gsk_gl_driver_init_texture_with_surface (self->gl_driver,
+ item.render_data.texture_id,
+ surface,
+ gl_min_filter,
+ gl_mag_filter);
}
else if (gsk_render_node_has_surface (node))
{
@@ -1062,10 +984,6 @@ 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 de2867fea5..edf4633e58 100644
--- a/gsk/gskrenderer.c
+++ b/gsk/gskrenderer.c
@@ -134,44 +134,6 @@ 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)
{
@@ -278,9 +240,6 @@ 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 5fdc130e4c..57f7e861f3 100644
--- a/gsk/gskrendererprivate.h
+++ b/gsk/gskrendererprivate.h
@@ -47,15 +47,6 @@ 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/gsktexture.c b/gsk/gsktexture.c
index 956625b787..8ccfcbac1a 100644
--- a/gsk/gsktexture.c
+++ b/gsk/gsktexture.c
@@ -23,9 +23,6 @@
*
* #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
@@ -38,7 +35,6 @@
#include "gsktextureprivate.h"
#include "gskdebugprivate.h"
-#include "gskrendererprivate.h"
/**
* GskTexture: (ref-func gsk_texture_ref) (unref-func gsk_texture_unref)
@@ -53,9 +49,7 @@ 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);
+ self->klass->finalize (self);
g_free (self);
}
@@ -100,63 +94,146 @@ gsk_texture_unref (GskTexture *texture)
gsk_texture_finalize (texture);
}
-GskTexture *
-gsk_texture_alloc (gsize size,
- GskRenderer *renderer,
- int width,
- int height)
+gpointer
+gsk_texture_new (const GskTextureClass *klass,
+ int width,
+ int height)
{
GskTexture *self;
- g_assert (size >= sizeof (GskTexture));
+ g_assert (klass->size >= sizeof (GskTexture));
- self = g_malloc0 (size);
+ self = g_malloc0 (klass->size);
+ self->klass = klass;
self->ref_count = 1;
- self->renderer = g_object_ref (renderer);
self->width = width;
self->height = height;
return self;
}
+/* GskCairoTexture */
+
+typedef struct _GskCairoTexture GskCairoTexture;
+
+struct _GskCairoTexture {
+ GskTexture texture;
+ cairo_surface_t *surface;
+};
+
+static void
+gsk_texture_cairo_finalize (GskTexture *texture)
+{
+ GskCairoTexture *cairo = (GskCairoTexture *) texture;
+
+ cairo_surface_destroy (cairo->surface);
+}
+
+static cairo_surface_t *
+gsk_texture_cairo_download (GskTexture *texture)
+{
+ GskCairoTexture *cairo = (GskCairoTexture *) texture;
+
+ return cairo_surface_reference (cairo->surface);
+}
+
+static const GskTextureClass GSK_TEXTURE_CLASS_CAIRO = {
+ "cairo",
+ sizeof (GskCairoTexture),
+ gsk_texture_cairo_finalize,
+ gsk_texture_cairo_download
+};
+
+GskTexture *
+gsk_texture_new_for_surface (cairo_surface_t *surface)
+{
+ GskCairoTexture *texture;
+
+ g_return_val_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE, NULL);
+
+ texture = gsk_texture_new (&GSK_TEXTURE_CLASS_CAIRO,
+ cairo_image_surface_get_width (surface),
+ cairo_image_surface_get_height (surface));
+
+ texture->surface = cairo_surface_reference (surface);
+
+ return (GskTexture *) texture;
+}
+
GskTexture *
-gsk_texture_new_for_data (GskRenderer *renderer,
- const guchar *data,
+gsk_texture_new_for_data (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 *texture;
+ cairo_surface_t *original, *copy;
+ cairo_t *cr;
+
+ original = cairo_image_surface_create_for_data ((guchar *) data, CAIRO_FORMAT_ARGB32, width, height, stride);
+ copy = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
+
+ cr = cairo_create (copy);
+ cairo_set_source_surface (cr, original, 0, 0);
+ cairo_paint (cr);
+ cairo_destroy (cr);
+
+ texture = gsk_texture_new_for_surface (copy);
+
+ cairo_surface_destroy (copy);
+ cairo_surface_destroy (original);
+
+ return texture;
}
-GskTexture *
-gsk_texture_new_for_pixbuf (GskRenderer *renderer,
- GdkPixbuf *pixbuf)
+/* GskPixbufTexture */
+
+typedef struct _GskPixbufTexture GskPixbufTexture;
+
+struct _GskPixbufTexture {
+ GskTexture texture;
+ GdkPixbuf *pixbuf;
+};
+
+static void
+gsk_texture_pixbuf_finalize (GskTexture *texture)
{
- g_return_val_if_fail (GSK_IS_RENDERER (renderer), NULL);
- g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
+ GskPixbufTexture *pixbuf = (GskPixbufTexture *) texture;
- return GSK_RENDERER_GET_CLASS (renderer)->texture_new_for_pixbuf (renderer, pixbuf);
+ g_object_unref (pixbuf->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)
+static cairo_surface_t *
+gsk_texture_pixbuf_download (GskTexture *texture)
{
- g_return_val_if_fail (GSK_IS_TEXTURE (texture), NULL);
+ GskPixbufTexture *pixbuf = (GskPixbufTexture *) texture;
+
+ return gdk_cairo_surface_create_from_pixbuf (pixbuf->pixbuf, 1, NULL);
+}
+
+static const GskTextureClass GSK_TEXTURE_CLASS_PIXBUF = {
+ "pixbuf",
+ sizeof (GskPixbufTexture),
+ gsk_texture_pixbuf_finalize,
+ gsk_texture_pixbuf_download
+};
+
+GskTexture *
+gsk_texture_new_for_pixbuf (GdkPixbuf *pixbuf)
+{
+ GskPixbufTexture *texture;
- return texture->renderer;
+ g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
+
+ texture = gsk_texture_new (&GSK_TEXTURE_CLASS_PIXBUF,
+ gdk_pixbuf_get_width (pixbuf),
+ gdk_pixbuf_get_height (pixbuf));
+
+ texture->pixbuf = g_object_ref (pixbuf);
+
+ return &texture->texture;
}
/**
@@ -195,3 +272,9 @@ gsk_texture_get_height (GskTexture *texture)
return texture->height;
}
+cairo_surface_t *
+gsk_texture_download (GskTexture *texture)
+{
+ return texture->klass->download (texture);
+}
+
diff --git a/gsk/gsktexture.h b/gsk/gsktexture.h
index 1d1c81e472..317cb3c34c 100644
--- a/gsk/gsktexture.h
+++ b/gsk/gsktexture.h
@@ -40,18 +40,14 @@ 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,
+GskTexture * gsk_texture_new_for_data (const guchar *data,
int width,
int height,
int stride);
GDK_AVAILABLE_IN_3_90
-GskTexture * gsk_texture_new_for_pixbuf (GskRenderer *renderer,
- GdkPixbuf *pixbuf);
+GskTexture * gsk_texture_new_for_pixbuf (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);
diff --git a/gsk/gsktextureprivate.h b/gsk/gsktextureprivate.h
index 887a03adcc..78d96de611 100644
--- a/gsk/gsktextureprivate.h
+++ b/gsk/gsktextureprivate.h
@@ -9,21 +9,31 @@ G_BEGIN_DECLS
#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))
+typedef struct _GskTextureClass GskTextureClass;
+
struct _GskTexture
{
+ const GskTextureClass *klass;
+
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);
+struct _GskTextureClass {
+ const char *name;
+ gsize size;
+
+ void (* finalize) (GskTexture *texture);
+ cairo_surface_t * (* download) (GskTexture *texture);
+};
+
+gpointer gsk_texture_new (const GskTextureClass *klass,
+ int width,
+ int height);
+GskTexture * gsk_texture_new_for_surface (cairo_surface_t *surface);
+cairo_surface_t * gsk_texture_download (GskTexture *texture);
G_END_DECLS