forked from AuroraMiddleware/gtk
gsktexture: Allow attaching render data to textures
This allows renderers (or anyone really) to attach "render data" to textures. Only the first render data sticks. You can gsk_texture_set_render_data() with the key you will use to look the data up again, and if no data has been set yet, yours will be set. You can retrieve this data via gsk_texture_get_render_data() later on. If your data has been cleared, NULL will be returned. When gsk_texture_clear_render_data() is called (which the texture will call when it is finalized), your destory notify will be called and you have to release your render data. The GL driver uses this to attach texture ids to GskTextures.
This commit is contained in:
parent
40565fb030
commit
48e7f4191f
@ -3,6 +3,7 @@
|
||||
#include "gskgldriverprivate.h"
|
||||
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gsktextureprivate.h"
|
||||
|
||||
#include <gdk/gdk.h>
|
||||
#include <epoxy/gl.h>
|
||||
@ -14,8 +15,8 @@ typedef struct {
|
||||
GLuint min_filter;
|
||||
GLuint mag_filter;
|
||||
GArray *fbos;
|
||||
GskTexture *user;
|
||||
gboolean in_use : 1;
|
||||
gboolean reserved : 1;
|
||||
} Texture;
|
||||
|
||||
typedef struct {
|
||||
@ -76,7 +77,8 @@ texture_free (gpointer data)
|
||||
{
|
||||
Texture *t = data;
|
||||
|
||||
g_warn_if_fail (!t->reserved);
|
||||
if (t->user)
|
||||
gsk_texture_clear_render_data (t->user);
|
||||
|
||||
g_clear_pointer (&t->fbos, g_array_unref);
|
||||
glDeleteTextures (1, &t->texture_id);
|
||||
@ -272,7 +274,7 @@ gsk_gl_driver_collect_textures (GskGLDriver *driver)
|
||||
{
|
||||
Texture *t = value_p;
|
||||
|
||||
if (t->reserved)
|
||||
if (t->user)
|
||||
continue;
|
||||
|
||||
if (t->in_use)
|
||||
@ -383,17 +385,14 @@ find_texture_by_size (GHashTable *textures,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
gsk_gl_driver_create_texture (GskGLDriver *driver,
|
||||
gboolean reserve,
|
||||
int width,
|
||||
int height)
|
||||
static Texture *
|
||||
create_texture (GskGLDriver *driver,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
guint texture_id;
|
||||
Texture *t;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
|
||||
|
||||
if (width >= driver->max_texture_size ||
|
||||
height >= driver->max_texture_size)
|
||||
{
|
||||
@ -406,13 +405,12 @@ gsk_gl_driver_create_texture (GskGLDriver *driver,
|
||||
}
|
||||
|
||||
t = find_texture_by_size (driver->textures, width, height);
|
||||
if (t != NULL && !t->in_use)
|
||||
if (t != NULL && !t->in_use && t->user == NULL)
|
||||
{
|
||||
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;
|
||||
return t;
|
||||
}
|
||||
|
||||
glGenTextures (1, &texture_id);
|
||||
@ -424,25 +422,67 @@ 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;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gl_driver_release_texture (gpointer data)
|
||||
{
|
||||
Texture *t = data;
|
||||
|
||||
t->user = NULL;
|
||||
}
|
||||
|
||||
int
|
||||
gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver,
|
||||
GskTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter)
|
||||
{
|
||||
Texture *t;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
|
||||
g_return_val_if_fail (GSK_IS_TEXTURE (texture), -1);
|
||||
|
||||
t = gsk_texture_get_render_data (texture, driver);
|
||||
|
||||
if (t)
|
||||
{
|
||||
if (t->min_filter == min_filter && t->mag_filter == mag_filter)
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
t = create_texture (driver, gsk_texture_get_width (texture), gsk_texture_get_height (texture));
|
||||
|
||||
if (gsk_texture_set_render_data (texture, driver, t, gsk_gl_driver_release_texture))
|
||||
t->user = texture;
|
||||
|
||||
surface = gsk_texture_download (texture);
|
||||
gsk_gl_driver_bind_source_texture (driver, t->texture_id);
|
||||
gsk_gl_driver_init_texture_with_surface (driver,
|
||||
t->texture_id,
|
||||
surface,
|
||||
min_filter,
|
||||
mag_filter);
|
||||
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gl_driver_release_texture (GskGLDriver *driver,
|
||||
int texture_id)
|
||||
int
|
||||
gsk_gl_driver_create_texture (GskGLDriver *driver,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
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;
|
||||
g_return_val_if_fail (GSK_IS_GL_DRIVER (driver), -1);
|
||||
|
||||
t = create_texture (driver, width, height);
|
||||
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
static Vao *
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <gdk/gdk.h>
|
||||
#include <graphene.h>
|
||||
|
||||
#include <gsk/gsktexture.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GSK_TYPE_GL_DRIVER (gsk_gl_driver_get_type ())
|
||||
@ -23,12 +25,13 @@ int gsk_gl_driver_get_max_texture_size (GskGLDriver *driver
|
||||
void gsk_gl_driver_begin_frame (GskGLDriver *driver);
|
||||
void gsk_gl_driver_end_frame (GskGLDriver *driver);
|
||||
|
||||
int gsk_gl_driver_get_texture_for_texture (GskGLDriver *driver,
|
||||
GskTexture *texture,
|
||||
int min_filter,
|
||||
int mag_filter);
|
||||
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,
|
||||
|
@ -153,7 +153,6 @@ 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);
|
||||
@ -695,7 +694,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, FALSE, item.size.width, item.size.height);
|
||||
gsk_gl_driver_create_texture (self->gl_driver, 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);
|
||||
|
||||
@ -711,22 +710,14 @@ 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;
|
||||
|
||||
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);
|
||||
item.render_data.texture_id = gsk_gl_driver_get_texture_for_texture (self->gl_driver,
|
||||
texture,
|
||||
gl_min_filter,
|
||||
gl_mag_filter);
|
||||
}
|
||||
else if (gsk_render_node_has_surface (node))
|
||||
{
|
||||
@ -737,7 +728,6 @@ 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);
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include "gsktextureprivate.h"
|
||||
|
||||
#include "gskdebugprivate.h"
|
||||
#include "gskrenderer.h"
|
||||
|
||||
/**
|
||||
* GskTexture: (ref-func gsk_texture_ref) (unref-func gsk_texture_unref)
|
||||
@ -49,6 +50,8 @@ G_DEFINE_BOXED_TYPE(GskTexture, gsk_texture, gsk_texture_ref, gsk_texture_unref)
|
||||
static void
|
||||
gsk_texture_finalize (GskTexture *self)
|
||||
{
|
||||
gsk_texture_clear_render_data (self);
|
||||
|
||||
self->klass->finalize (self);
|
||||
|
||||
g_free (self);
|
||||
@ -278,3 +281,41 @@ gsk_texture_download (GskTexture *texture)
|
||||
return texture->klass->download (texture);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gsk_texture_set_render_data (GskTexture *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
|
||||
gsk_texture_clear_render_data (GskTexture *self)
|
||||
{
|
||||
if (self->render_notify)
|
||||
self->render_notify (self->render_data);
|
||||
|
||||
self->render_key = NULL;
|
||||
self->render_data = NULL;
|
||||
self->render_notify = NULL;
|
||||
}
|
||||
|
||||
gpointer
|
||||
gsk_texture_get_render_data (GskTexture *self,
|
||||
gpointer key)
|
||||
{
|
||||
if (self->render_key != key)
|
||||
return NULL;
|
||||
|
||||
return self->render_data;
|
||||
}
|
||||
|
@ -19,6 +19,10 @@ struct _GskTexture
|
||||
|
||||
int width;
|
||||
int height;
|
||||
|
||||
gpointer render_key;
|
||||
gpointer render_data;
|
||||
GDestroyNotify render_notify;
|
||||
};
|
||||
|
||||
struct _GskTextureClass {
|
||||
@ -35,6 +39,14 @@ gpointer gsk_texture_new (const GskTextureClass
|
||||
GskTexture * gsk_texture_new_for_surface (cairo_surface_t *surface);
|
||||
cairo_surface_t * gsk_texture_download (GskTexture *texture);
|
||||
|
||||
gboolean gsk_texture_set_render_data (GskTexture *self,
|
||||
gpointer key,
|
||||
gpointer data,
|
||||
GDestroyNotify notify);
|
||||
void gsk_texture_clear_render_data (GskTexture *self);
|
||||
gpointer gsk_texture_get_render_data (GskTexture *self,
|
||||
gpointer key);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GSK_TEXTURE_PRIVATE_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user