forked from AuroraMiddleware/gtk
5e302ae2cc
The inspector may hold on to render nodes and textures beyond the lifetime of the widget (and thus the GL resources). To handle this situation, allow the widget to explicitly release the GL resources, and make the texture available on the clent-side as a cairo surface. This lets the recorder still show the content after the widget is gone.
824 lines
20 KiB
C
824 lines
20 KiB
C
/* gdktexture.c
|
|
*
|
|
* 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:textures
|
|
* @Title: GdkTexture
|
|
* @Short_description: Pixel data
|
|
*
|
|
* #GdkTexture is the basic element used to refer to pixel data.
|
|
* It is primarily mean for pixel data that will not change over
|
|
* multiple frames, and will be used for a long time.
|
|
*
|
|
* You cannot get your pixel data back once you've uploaded it.
|
|
*
|
|
* #GdkTexture is an immutable object: That means you cannot change
|
|
* anything about it other than increasing the reference count via
|
|
* g_object_ref().
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include "gdktextureprivate.h"
|
|
|
|
#include "gdkinternals.h"
|
|
#include "gdkcairo.h"
|
|
|
|
#include <epoxy/gl.h>
|
|
|
|
/**
|
|
* SECTION:gdktexture
|
|
* @Short_description: Image data for display
|
|
* @Title: GdkTexture
|
|
*
|
|
* A GdkTexture represents image data that can be displayed on screen.
|
|
*
|
|
* There are various ways to create GdkTexture objects from a #GdkPixbuf
|
|
* or a cairo surface, or other pixel data.
|
|
*
|
|
* An important aspect of GdkTextures is that they are immutable - once
|
|
* the image data has been wrapped in a GdkTexture, it may be uploaded
|
|
* to the GPU or used in other ways that make it impractical to allow
|
|
* modification.
|
|
*/
|
|
|
|
/**
|
|
* GdkTexture:
|
|
*
|
|
* The `GdkTexture` structure contains only private data.
|
|
*
|
|
* Since: 3.94
|
|
*/
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_WIDTH,
|
|
PROP_HEIGHT,
|
|
|
|
N_PROPS
|
|
};
|
|
|
|
static GParamSpec *properties[N_PROPS];
|
|
|
|
G_DEFINE_ABSTRACT_TYPE (GdkTexture, gdk_texture, G_TYPE_OBJECT)
|
|
|
|
#define GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD(obj,method) \
|
|
g_critical ("Texture of type '%s' does not implement GdkTexture::" # method, G_OBJECT_TYPE_NAME (obj))
|
|
|
|
static void
|
|
gdk_texture_real_download (GdkTexture *self,
|
|
guchar *data,
|
|
gsize stride)
|
|
{
|
|
GDK_TEXTURE_WARN_NOT_IMPLEMENTED_METHOD (self, download);
|
|
}
|
|
|
|
static cairo_surface_t *
|
|
gdk_texture_real_download_surface (GdkTexture *texture)
|
|
{
|
|
cairo_surface_t *surface;
|
|
|
|
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
|
texture->width, texture->height);
|
|
gdk_texture_download (texture,
|
|
cairo_image_surface_get_data (surface),
|
|
cairo_image_surface_get_stride (surface));
|
|
cairo_surface_mark_dirty (surface);
|
|
|
|
return surface;
|
|
}
|
|
|
|
static void
|
|
gdk_texture_set_property (GObject *gobject,
|
|
guint prop_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GdkTexture *self = GDK_TEXTURE (gobject);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_WIDTH:
|
|
self->width = g_value_get_int (value);
|
|
break;
|
|
|
|
case PROP_HEIGHT:
|
|
self->height = g_value_get_int (value);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdk_texture_get_property (GObject *gobject,
|
|
guint prop_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GdkTexture *self = GDK_TEXTURE (gobject);
|
|
|
|
switch (prop_id)
|
|
{
|
|
case PROP_WIDTH:
|
|
g_value_set_int (value, self->width);
|
|
break;
|
|
|
|
case PROP_HEIGHT:
|
|
g_value_set_int (value, self->height);
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gdk_texture_dispose (GObject *object)
|
|
{
|
|
GdkTexture *self = GDK_TEXTURE (object);
|
|
|
|
gdk_texture_clear_render_data (self);
|
|
|
|
G_OBJECT_CLASS (gdk_texture_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gdk_texture_class_init (GdkTextureClass *klass)
|
|
{
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
klass->download = gdk_texture_real_download;
|
|
klass->download_surface = gdk_texture_real_download_surface;
|
|
|
|
gobject_class->set_property = gdk_texture_set_property;
|
|
gobject_class->get_property = gdk_texture_get_property;
|
|
gobject_class->dispose = gdk_texture_dispose;
|
|
|
|
/**
|
|
* GdkTexture:width:
|
|
*
|
|
* The width of the texture.
|
|
*
|
|
* Since: 3.94
|
|
*/
|
|
properties[PROP_WIDTH] =
|
|
g_param_spec_int ("width",
|
|
"Width",
|
|
"The width of the texture",
|
|
1,
|
|
G_MAXINT,
|
|
1,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
G_PARAM_STATIC_STRINGS |
|
|
G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
/**
|
|
* GdkTexture:height:
|
|
*
|
|
* The height of the texture.
|
|
*
|
|
* Since: 3.94
|
|
*/
|
|
properties[PROP_HEIGHT] =
|
|
g_param_spec_int ("height",
|
|
"Height",
|
|
"The height of the texture",
|
|
1,
|
|
G_MAXINT,
|
|
1,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
G_PARAM_STATIC_STRINGS |
|
|
G_PARAM_EXPLICIT_NOTIFY);
|
|
|
|
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
|
}
|
|
|
|
static void
|
|
gdk_texture_init (GdkTexture *self)
|
|
{
|
|
}
|
|
|
|
/* GdkCairoTexture */
|
|
|
|
#define GDK_TYPE_CAIRO_TEXTURE (gdk_cairo_texture_get_type ())
|
|
|
|
G_DECLARE_FINAL_TYPE (GdkCairoTexture, gdk_cairo_texture, GDK, CAIRO_TEXTURE, GdkTexture)
|
|
|
|
struct _GdkCairoTexture {
|
|
GdkTexture parent_instance;
|
|
cairo_surface_t *surface;
|
|
};
|
|
|
|
struct _GdkCairoTextureClass {
|
|
GdkTextureClass parent_class;
|
|
};
|
|
|
|
G_DEFINE_TYPE (GdkCairoTexture, gdk_cairo_texture, GDK_TYPE_TEXTURE)
|
|
|
|
static void
|
|
gdk_cairo_texture_finalize (GObject *object)
|
|
{
|
|
GdkCairoTexture *self = GDK_CAIRO_TEXTURE (object);
|
|
|
|
cairo_surface_destroy (self->surface);
|
|
|
|
G_OBJECT_CLASS (gdk_cairo_texture_parent_class)->finalize (object);
|
|
}
|
|
|
|
static cairo_surface_t *
|
|
gdk_cairo_texture_download_surface (GdkTexture *texture)
|
|
{
|
|
GdkCairoTexture *self = GDK_CAIRO_TEXTURE (texture);
|
|
|
|
return cairo_surface_reference (self->surface);
|
|
}
|
|
|
|
static void
|
|
gdk_cairo_texture_download (GdkTexture *texture,
|
|
guchar *data,
|
|
gsize stride)
|
|
{
|
|
GdkCairoTexture *self = GDK_CAIRO_TEXTURE (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, self->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 void
|
|
gdk_cairo_texture_class_init (GdkCairoTextureClass *klass)
|
|
{
|
|
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
texture_class->download = gdk_cairo_texture_download;
|
|
texture_class->download_surface = gdk_cairo_texture_download_surface;
|
|
|
|
gobject_class->finalize = gdk_cairo_texture_finalize;
|
|
}
|
|
|
|
static void
|
|
gdk_cairo_texture_init (GdkCairoTexture *self)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* gdk_texture_new_for_data:
|
|
* @data: (array): the pixel data
|
|
* @width: the number of pixels in each row
|
|
* @height: the number of rows
|
|
* @stride: the distance from the beginning of one row to the next, in bytes
|
|
*
|
|
* Creates a new texture object holding the given data.
|
|
* The data is assumed to be in CAIRO_FORMAT_ARGB32 format.
|
|
*
|
|
* Returns: a new #GdkTexture
|
|
*
|
|
* Since: 3.94
|
|
*/
|
|
GdkTexture *
|
|
gdk_texture_new_for_data (const guchar *data,
|
|
int width,
|
|
int height,
|
|
int stride)
|
|
{
|
|
GdkTexture *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 = gdk_texture_new_for_surface (copy);
|
|
|
|
cairo_surface_destroy (copy);
|
|
cairo_surface_finish (original);
|
|
cairo_surface_destroy (original);
|
|
|
|
return texture;
|
|
}
|
|
|
|
/**
|
|
* gdk_texture_new_for_surface:
|
|
* @surface: a cairo image surface
|
|
*
|
|
* Creates a new texture object representing the surface.
|
|
* @surface must be an image surface with format CAIRO_FORMAT_ARGB32.
|
|
*
|
|
* Returns: a new #GdkTexture
|
|
*
|
|
* Since: 3.94
|
|
*/
|
|
GdkTexture *
|
|
gdk_texture_new_for_surface (cairo_surface_t *surface)
|
|
{
|
|
GdkCairoTexture *texture;
|
|
|
|
g_return_val_if_fail (cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_IMAGE, NULL);
|
|
|
|
texture = g_object_new (GDK_TYPE_CAIRO_TEXTURE,
|
|
"width", cairo_image_surface_get_width (surface),
|
|
"height", cairo_image_surface_get_height (surface),
|
|
NULL);
|
|
|
|
texture->surface = cairo_surface_reference (surface);
|
|
|
|
return (GdkTexture *) texture;
|
|
}
|
|
|
|
/* GdkPixbufTexture */
|
|
|
|
#define GDK_TYPE_PIXBUF_TEXTURE (gdk_pixbuf_texture_get_type ())
|
|
|
|
G_DECLARE_FINAL_TYPE (GdkPixbufTexture, gdk_pixbuf_texture, GDK, PIXBUF_TEXTURE, GdkTexture)
|
|
|
|
struct _GdkPixbufTexture {
|
|
GdkTexture parent_instance;
|
|
|
|
GdkPixbuf *pixbuf;
|
|
};
|
|
|
|
struct _GdkPixbufTextureClass {
|
|
GdkTextureClass parent_class;
|
|
};
|
|
|
|
G_DEFINE_TYPE (GdkPixbufTexture, gdk_pixbuf_texture, GDK_TYPE_TEXTURE)
|
|
|
|
static void
|
|
gdk_pixbuf_texture_finalize (GObject *object)
|
|
{
|
|
GdkPixbufTexture *self = GDK_PIXBUF_TEXTURE (object);
|
|
|
|
g_object_unref (self->pixbuf);
|
|
|
|
G_OBJECT_CLASS (gdk_pixbuf_texture_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gdk_pixbuf_texture_download (GdkTexture *texture,
|
|
guchar *data,
|
|
gsize stride)
|
|
{
|
|
GdkPixbufTexture *self = GDK_PIXBUF_TEXTURE (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, self->pixbuf);
|
|
cairo_surface_finish (surface);
|
|
cairo_surface_destroy (surface);
|
|
}
|
|
|
|
static cairo_surface_t *
|
|
gdk_pixbuf_texture_download_surface (GdkTexture *texture)
|
|
{
|
|
GdkPixbufTexture *self = GDK_PIXBUF_TEXTURE (texture);
|
|
|
|
return gdk_cairo_surface_create_from_pixbuf (self->pixbuf, 1, NULL);
|
|
}
|
|
|
|
static void
|
|
gdk_pixbuf_texture_class_init (GdkPixbufTextureClass *klass)
|
|
{
|
|
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
texture_class->download = gdk_pixbuf_texture_download;
|
|
texture_class->download_surface = gdk_pixbuf_texture_download_surface;
|
|
|
|
gobject_class->finalize = gdk_pixbuf_texture_finalize;
|
|
}
|
|
|
|
static void
|
|
gdk_pixbuf_texture_init (GdkPixbufTexture *self)
|
|
{
|
|
}
|
|
|
|
/* GdkGLTexture */
|
|
|
|
|
|
struct _GdkGLTexture {
|
|
GdkTexture parent_instance;
|
|
|
|
GdkGLContext *context;
|
|
int id;
|
|
|
|
cairo_surface_t *saved;
|
|
|
|
GDestroyNotify destroy;
|
|
gpointer data;
|
|
};
|
|
|
|
struct _GdkGLTextureClass {
|
|
GdkTextureClass parent_class;
|
|
};
|
|
|
|
G_DEFINE_TYPE (GdkGLTexture, gdk_gl_texture, GDK_TYPE_TEXTURE)
|
|
|
|
static void
|
|
gdk_gl_texture_dispose (GObject *object)
|
|
{
|
|
GdkGLTexture *self = GDK_GL_TEXTURE (object);
|
|
|
|
if (self->destroy)
|
|
{
|
|
self->destroy (self->data);
|
|
self->destroy = NULL;
|
|
self->data = NULL;
|
|
}
|
|
|
|
g_clear_object (&self->context);
|
|
self->id = 0;
|
|
|
|
if (self->saved)
|
|
{
|
|
cairo_surface_destroy (self->saved);
|
|
self->saved = NULL;
|
|
}
|
|
|
|
G_OBJECT_CLASS (gdk_gl_texture_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
gdk_gl_texture_download (GdkTexture *texture,
|
|
guchar *data,
|
|
gsize stride)
|
|
{
|
|
GdkGLTexture *self = GDK_GL_TEXTURE (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);
|
|
|
|
if (self->saved)
|
|
{
|
|
cairo_set_source_surface (cr, self->saved, 0, 0);
|
|
cairo_paint (cr);
|
|
}
|
|
else
|
|
{
|
|
GdkWindow *window;
|
|
|
|
window = gdk_gl_context_get_window (self->context);
|
|
gdk_cairo_draw_from_gl (cr, window, self->id, GL_TEXTURE, 1, 0, 0,
|
|
texture->width, texture->height);
|
|
}
|
|
|
|
cairo_destroy (cr);
|
|
cairo_surface_finish (surface);
|
|
cairo_surface_destroy (surface);
|
|
}
|
|
|
|
static void
|
|
gdk_gl_texture_class_init (GdkGLTextureClass *klass)
|
|
{
|
|
GdkTextureClass *texture_class = GDK_TEXTURE_CLASS (klass);
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
texture_class->download = gdk_gl_texture_download;
|
|
gobject_class->dispose = gdk_gl_texture_dispose;
|
|
}
|
|
|
|
static void
|
|
gdk_gl_texture_init (GdkGLTexture *self)
|
|
{
|
|
}
|
|
|
|
GdkGLContext *
|
|
gdk_gl_texture_get_context (GdkGLTexture *self)
|
|
{
|
|
return self->context;
|
|
}
|
|
|
|
int
|
|
gdk_gl_texture_get_id (GdkGLTexture *self)
|
|
{
|
|
return self->id;
|
|
}
|
|
|
|
void
|
|
gdk_texture_release_gl (GdkTexture *texture)
|
|
{
|
|
GdkGLTexture *self;
|
|
GdkWindow *window;
|
|
cairo_t *cr;
|
|
|
|
g_return_if_fail (GDK_IS_GL_TEXTURE (texture));
|
|
|
|
self = GDK_GL_TEXTURE (texture);
|
|
|
|
g_return_if_fail (self->saved == NULL);
|
|
|
|
self->saved = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
|
texture->width, texture->height);
|
|
|
|
cr = cairo_create (self->saved);
|
|
|
|
window = gdk_gl_context_get_window (self->context);
|
|
gdk_cairo_draw_from_gl (cr, window, self->id, GL_TEXTURE, 1, 0, 0,
|
|
texture->width, texture->height);
|
|
|
|
cairo_destroy (cr);
|
|
|
|
if (self->destroy)
|
|
{
|
|
self->destroy (self->data);
|
|
self->destroy = NULL;
|
|
self->data = NULL;
|
|
}
|
|
|
|
g_clear_object (&self->context);
|
|
self->id = 0;
|
|
}
|
|
|
|
/**
|
|
* gdk_texture_new_for_pixbuf:
|
|
* @pixbuf: a #GdkPixbuf
|
|
*
|
|
* Creates a new texture object representing the GdkPixbuf.
|
|
*
|
|
* Returns: a new #GdkTexture
|
|
*
|
|
* Since: 3.94
|
|
*/
|
|
GdkTexture *
|
|
gdk_texture_new_for_pixbuf (GdkPixbuf *pixbuf)
|
|
{
|
|
GdkPixbufTexture *self;
|
|
|
|
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
|
|
|
self = g_object_new (GDK_TYPE_PIXBUF_TEXTURE,
|
|
"width", gdk_pixbuf_get_width (pixbuf),
|
|
"height", gdk_pixbuf_get_height (pixbuf),
|
|
NULL);
|
|
|
|
self->pixbuf = g_object_ref (pixbuf);
|
|
|
|
return GDK_TEXTURE (self);
|
|
}
|
|
|
|
/**
|
|
* gdk_texture_new_from_resource:
|
|
* @resource_path: the path of the resource file
|
|
*
|
|
* Creates a new texture by loading an image from a resource.
|
|
* The file format is detected automatically.
|
|
*
|
|
* It is a fatal error if @resource_path does not specify a valid
|
|
* image resource and the program will abort if that happens.
|
|
* If you are unsure about the validity of a resource, use
|
|
* gdk_texture_new_from_file() to load it.
|
|
*
|
|
* Return value: A newly-created texture
|
|
*
|
|
* Since: 3.94
|
|
*/
|
|
GdkTexture *
|
|
gdk_texture_new_from_resource (const char *resource_path)
|
|
{
|
|
GError *error = NULL;
|
|
GdkTexture *texture;
|
|
GdkPixbuf *pixbuf;
|
|
|
|
g_return_val_if_fail (resource_path != NULL, NULL);
|
|
|
|
pixbuf = gdk_pixbuf_new_from_resource (resource_path, &error);
|
|
if (pixbuf == NULL)
|
|
g_error ("Resource path %s is not a valid image: %s", resource_path, error->message);
|
|
|
|
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
|
g_object_unref (pixbuf);
|
|
|
|
return texture;
|
|
}
|
|
|
|
/**
|
|
* gdk_texture_new_from_file:
|
|
* @file: #GFile to load
|
|
* @error: Return location for an error
|
|
*
|
|
* Creates a new texture by loading an image from a file. The file format is
|
|
* detected automatically. If %NULL is returned, then @error will be set.
|
|
*
|
|
* Return value: A newly-created #GdkTexture or %NULL if an error occured.
|
|
*
|
|
* Since: 3.94
|
|
**/
|
|
GdkTexture *
|
|
gdk_texture_new_from_file (GFile *file,
|
|
GError **error)
|
|
{
|
|
GdkTexture *texture;
|
|
GdkPixbuf *pixbuf;
|
|
GInputStream *stream;
|
|
|
|
g_return_val_if_fail (G_IS_FILE (file), NULL);
|
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
|
|
|
stream = G_INPUT_STREAM (g_file_read (file, NULL, error));
|
|
if (stream == NULL)
|
|
return NULL;
|
|
|
|
pixbuf = gdk_pixbuf_new_from_stream (stream, NULL, error);
|
|
g_object_unref (stream);
|
|
if (pixbuf == NULL)
|
|
return NULL;
|
|
|
|
texture = gdk_texture_new_for_pixbuf (pixbuf);
|
|
g_object_unref (pixbuf);
|
|
|
|
return texture;
|
|
}
|
|
|
|
GdkTexture *
|
|
gdk_texture_new_for_gl (GdkGLContext *context,
|
|
int id,
|
|
int width,
|
|
int height,
|
|
GDestroyNotify destroy,
|
|
gpointer data)
|
|
{
|
|
GdkGLTexture *self;
|
|
|
|
g_return_val_if_fail (GDK_IS_GL_CONTEXT (context), NULL);
|
|
|
|
self = g_object_new (GDK_TYPE_GL_TEXTURE,
|
|
"width", width,
|
|
"height", height,
|
|
NULL);
|
|
|
|
self->context = g_object_ref (context);
|
|
self->id = id;
|
|
self->destroy = destroy;
|
|
self->data = data;
|
|
|
|
return GDK_TEXTURE (self);
|
|
}
|
|
|
|
/**
|
|
* gdk_texture_get_width:
|
|
* @texture: a #GdkTexture
|
|
*
|
|
* Returns the width of @texture.
|
|
*
|
|
* Returns: the width of the #GdkTexture
|
|
*
|
|
* Since: 3.94
|
|
*/
|
|
int
|
|
gdk_texture_get_width (GdkTexture *texture)
|
|
{
|
|
g_return_val_if_fail (GDK_IS_TEXTURE (texture), 0);
|
|
|
|
return texture->width;
|
|
}
|
|
|
|
/**
|
|
* gdk_texture_get_height:
|
|
* @texture: a #GdkTexture
|
|
*
|
|
* Returns the height of the @texture.
|
|
*
|
|
* Returns: the height of the #GdkTexture
|
|
*
|
|
* Since: 3.94
|
|
*/
|
|
int
|
|
gdk_texture_get_height (GdkTexture *texture)
|
|
{
|
|
g_return_val_if_fail (GDK_IS_TEXTURE (texture), 0);
|
|
|
|
return texture->height;
|
|
}
|
|
|
|
cairo_surface_t *
|
|
gdk_texture_download_surface (GdkTexture *texture)
|
|
{
|
|
return GDK_TEXTURE_GET_CLASS (texture)->download_surface (texture);
|
|
}
|
|
|
|
/**
|
|
* gdk_texture_download:
|
|
* @texture: a #GdkTexture
|
|
* @data: (array): 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,
|
|
* gdk_texture_get_width (texture),
|
|
* gdk_texture_get_height (texture));
|
|
* gdk_texture_download (texture,
|
|
* cairo_image_surface_get_data (surface),
|
|
* cairo_image_surface_get_stride (surface));
|
|
* cairo_surface_mark_dirty (surface);
|
|
* ]|
|
|
*
|
|
* Since: 3.94
|
|
**/
|
|
void
|
|
gdk_texture_download (GdkTexture *texture,
|
|
guchar *data,
|
|
gsize stride)
|
|
{
|
|
g_return_if_fail (GDK_IS_TEXTURE (texture));
|
|
g_return_if_fail (data != NULL);
|
|
g_return_if_fail (stride >= gdk_texture_get_width (texture) * 4);
|
|
|
|
return GDK_TEXTURE_GET_CLASS (texture)->download (texture, data, stride);
|
|
}
|
|
|
|
gboolean
|
|
gdk_texture_set_render_data (GdkTexture *self,
|
|
gpointer key,
|
|
gpointer data,
|
|
GDestroyNotify notify)
|
|
{
|
|
g_return_val_if_fail (data != NULL, FALSE);
|
|
|
|
if (self->render_key != NULL)
|
|
return FALSE;
|
|
|
|
self->render_key = key;
|
|
self->render_data = data;
|
|
self->render_notify = notify;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
void
|
|
gdk_texture_clear_render_data (GdkTexture *self)
|
|
{
|
|
if (self->render_notify)
|
|
self->render_notify (self->render_data);
|
|
|
|
self->render_key = NULL;
|
|
self->render_data = NULL;
|
|
self->render_notify = NULL;
|
|
}
|
|
|
|
gpointer
|
|
gdk_texture_get_render_data (GdkTexture *self,
|
|
gpointer key)
|
|
{
|
|
if (self->render_key != key)
|
|
return NULL;
|
|
|
|
return self->render_data;
|
|
}
|