mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-25 13:11:13 +00:00
gpu: Add a texture cache
... and use it when drawing textures. We'll need it in other places later, but for now that's what we have.
This commit is contained in:
parent
57c1c95e75
commit
373a6ab9f1
@ -3,16 +3,131 @@
|
||||
#include "gskgpudeviceprivate.h"
|
||||
|
||||
#include "gdk/gdkdisplayprivate.h"
|
||||
#include "gdk/gdktextureprivate.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GSK_GPU_CACHE_TEXTURE
|
||||
} GskGpuCacheType;
|
||||
|
||||
typedef struct _GskGpuCachedTexture GskGpuCachedTexture;
|
||||
typedef struct _GskGpuCacheEntry GskGpuCacheEntry;
|
||||
|
||||
struct _GskGpuCacheEntry
|
||||
{
|
||||
GskGpuCacheType type;
|
||||
guint64 last_use_timestamp;
|
||||
};
|
||||
|
||||
struct _GskGpuCachedTexture
|
||||
{
|
||||
GskGpuCacheEntry entry;
|
||||
/* atomic */ GdkTexture *texture;
|
||||
GskGpuImage *image;
|
||||
};
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_gpu_cache_entries
|
||||
#define GDK_ARRAY_TYPE_NAME GskGpuCacheEntries
|
||||
#define GDK_ARRAY_ELEMENT_TYPE GskGpuCacheEntry *
|
||||
#define GDK_ARRAY_PREALLOC 32
|
||||
#define GDK_ARRAY_NO_MEMSET 1
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
typedef struct _GskGpuDevicePrivate GskGpuDevicePrivate;
|
||||
|
||||
struct _GskGpuDevicePrivate
|
||||
{
|
||||
GdkDisplay *display;
|
||||
|
||||
GskGpuCacheEntries cache;
|
||||
guint cache_gc_source;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE_WITH_PRIVATE (GskGpuDevice, gsk_gpu_device, G_TYPE_OBJECT)
|
||||
|
||||
void
|
||||
gsk_gpu_device_gc (GskGpuDevice *self,
|
||||
gint64 timestamp)
|
||||
{
|
||||
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < gsk_gpu_cache_entries_get_size (&priv->cache); i++)
|
||||
{
|
||||
GskGpuCacheEntry *entry = gsk_gpu_cache_entries_get (&priv->cache, i);
|
||||
|
||||
switch (entry->type)
|
||||
{
|
||||
case GSK_GPU_CACHE_TEXTURE:
|
||||
{
|
||||
GskGpuCachedTexture *texture = (GskGpuCachedTexture *) entry;
|
||||
if (texture->texture != NULL)
|
||||
continue;
|
||||
|
||||
gdk_texture_clear_render_data (texture->texture);
|
||||
g_object_unref (texture->image);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
if (i + 1 != gsk_gpu_cache_entries_get_size (&priv->cache))
|
||||
{
|
||||
*gsk_gpu_cache_entries_index (&priv->cache, i) = *gsk_gpu_cache_entries_index (&priv->cache, gsk_gpu_cache_entries_get_size (&priv->cache) - 1);
|
||||
gsk_gpu_cache_entries_set_size (&priv->cache, gsk_gpu_cache_entries_get_size (&priv->cache) - 1);
|
||||
}
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_device_clear_cache (GskGpuDevice *self)
|
||||
{
|
||||
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
||||
gsize i;
|
||||
|
||||
for (i = 0; i < gsk_gpu_cache_entries_get_size (&priv->cache); i++)
|
||||
{
|
||||
GskGpuCacheEntry *entry = gsk_gpu_cache_entries_get (&priv->cache, i);
|
||||
|
||||
switch (entry->type)
|
||||
{
|
||||
case GSK_GPU_CACHE_TEXTURE:
|
||||
{
|
||||
GskGpuCachedTexture *texture = (GskGpuCachedTexture *) entry;
|
||||
|
||||
if (texture->texture)
|
||||
gdk_texture_clear_render_data (texture->texture);
|
||||
g_object_unref (texture->image);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
break;
|
||||
}
|
||||
|
||||
g_free (entry);
|
||||
}
|
||||
|
||||
gsk_gpu_cache_entries_set_size (&priv->cache, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_device_dispose (GObject *object)
|
||||
{
|
||||
GskGpuDevice *self = GSK_GPU_DEVICE (object);
|
||||
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
||||
|
||||
gsk_gpu_device_clear_cache (self);
|
||||
gsk_gpu_cache_entries_clear (&priv->cache);
|
||||
|
||||
G_OBJECT_CLASS (gsk_gpu_device_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_device_finalize (GObject *object)
|
||||
{
|
||||
@ -29,12 +144,16 @@ gsk_gpu_device_class_init (GskGpuDeviceClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->dispose = gsk_gpu_device_dispose;
|
||||
object_class->finalize = gsk_gpu_device_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_device_init (GskGpuDevice *self)
|
||||
{
|
||||
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
||||
|
||||
gsk_gpu_cache_entries_init (&priv->cache);
|
||||
}
|
||||
|
||||
void
|
||||
@ -71,3 +190,54 @@ gsk_gpu_device_create_upload_image (GskGpuDevice *self,
|
||||
{
|
||||
return GSK_GPU_DEVICE_GET_CLASS (self)->create_upload_image (self, format, width, height);
|
||||
}
|
||||
|
||||
GskGpuImage *
|
||||
gsk_gpu_device_lookup_texture_image (GskGpuDevice *self,
|
||||
GdkTexture *texture,
|
||||
gint64 timestamp)
|
||||
{
|
||||
GskGpuCachedTexture *cache;
|
||||
|
||||
cache = gdk_texture_get_render_data (texture, self);
|
||||
if (cache)
|
||||
{
|
||||
cache->entry.last_use_timestamp = timestamp;
|
||||
return g_object_ref (cache->image);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_device_cache_texture_destroy_cb (gpointer data)
|
||||
{
|
||||
GskGpuCachedTexture *cache = data;
|
||||
|
||||
g_atomic_pointer_set (&cache->texture, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
gsk_gpu_device_cache_texture_image (GskGpuDevice *self,
|
||||
GdkTexture *texture,
|
||||
gint64 timestamp,
|
||||
GskGpuImage *image)
|
||||
{
|
||||
GskGpuDevicePrivate *priv = gsk_gpu_device_get_instance_private (self);
|
||||
GskGpuCachedTexture *cache;
|
||||
|
||||
cache = g_new (GskGpuCachedTexture, 1);
|
||||
|
||||
*cache = (GskGpuCachedTexture) {
|
||||
.entry = {
|
||||
.type = GSK_GPU_CACHE_TEXTURE,
|
||||
.last_use_timestamp = timestamp,
|
||||
},
|
||||
.texture = texture,
|
||||
.image = g_object_ref (image)
|
||||
};
|
||||
|
||||
if (gdk_texture_get_render_data (texture, self))
|
||||
gdk_texture_clear_render_data (texture);
|
||||
gdk_texture_set_render_data (texture, self, cache, gsk_gpu_device_cache_texture_destroy_cb);
|
||||
gsk_gpu_cache_entries_append (&priv->cache, (GskGpuCacheEntry *) cache);
|
||||
}
|
||||
|
@ -36,6 +36,8 @@ GType gsk_gpu_device_get_type (void) G
|
||||
|
||||
void gsk_gpu_device_setup (GskGpuDevice *self,
|
||||
GdkDisplay *display);
|
||||
void gsk_gpu_device_gc (GskGpuDevice *self,
|
||||
gint64 timestamp);
|
||||
|
||||
GdkDisplay * gsk_gpu_device_get_display (GskGpuDevice *self);
|
||||
|
||||
@ -48,6 +50,14 @@ GskGpuImage * gsk_gpu_device_create_upload_image (GskGpuD
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
GskGpuImage * gsk_gpu_device_lookup_texture_image (GskGpuDevice *self,
|
||||
GdkTexture *texture,
|
||||
gint64 timestamp);
|
||||
void gsk_gpu_device_cache_texture_image (GskGpuDevice *self,
|
||||
GdkTexture *texture,
|
||||
gint64 timestamp,
|
||||
GskGpuImage *image);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskGpuDevice, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -3,10 +3,12 @@
|
||||
#include "gskgpunodeprocessorprivate.h"
|
||||
|
||||
#include "gskgpuclipprivate.h"
|
||||
#include "gskgpudeviceprivate.h"
|
||||
#include "gskgpuframeprivate.h"
|
||||
#include "gskgpuglobalsopprivate.h"
|
||||
#include "gskgpuimageprivate.h"
|
||||
#include "gskgpupatternprivate.h"
|
||||
#include "gskgpurenderpassopprivate.h"
|
||||
#include "gskgpuscissoropprivate.h"
|
||||
#include "gskgputextureopprivate.h"
|
||||
#include "gskgpuuberopprivate.h"
|
||||
@ -601,6 +603,38 @@ gsk_gpu_node_processor_add_color_node (GskGpuNodeProcessor *self,
|
||||
pattern_id);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_node_processor_add_texture_node (GskGpuNodeProcessor *self,
|
||||
GskRenderNode *node)
|
||||
{
|
||||
GskGpuDevice *device;
|
||||
GskGpuImage *image;
|
||||
GdkTexture *texture;
|
||||
gint64 timestamp;
|
||||
|
||||
device = gsk_gpu_frame_get_device (self->frame);
|
||||
texture = gsk_texture_node_get_texture (node);
|
||||
timestamp = gsk_gpu_frame_get_timestamp (self->frame);
|
||||
|
||||
image = gsk_gpu_device_lookup_texture_image (device, texture, timestamp);
|
||||
if (image == NULL)
|
||||
{
|
||||
image = gsk_gpu_upload_texture_op (self->frame, texture);
|
||||
gsk_gpu_device_cache_texture_image (device, texture, timestamp, image);
|
||||
image = g_object_ref (image);
|
||||
}
|
||||
|
||||
gsk_gpu_texture_op (self->frame,
|
||||
gsk_gpu_clip_get_shader_clip (&self->clip, &self->offset, &node->bounds),
|
||||
image,
|
||||
GSK_GPU_SAMPLER_DEFAULT,
|
||||
&node->bounds,
|
||||
&self->offset,
|
||||
&node->bounds);
|
||||
|
||||
g_object_unref (image);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_node_processor_add_opacity_node (GskGpuNodeProcessor *self,
|
||||
GskRenderNode *node)
|
||||
@ -683,7 +717,7 @@ static const struct
|
||||
},
|
||||
[GSK_TEXTURE_NODE] = {
|
||||
0,
|
||||
NULL,
|
||||
gsk_gpu_node_processor_add_texture_node,
|
||||
},
|
||||
[GSK_INSET_SHADOW_NODE] = {
|
||||
0,
|
||||
|
@ -203,6 +203,114 @@ gsk_gpu_upload_op_vk_command (GskGpuOp *op,
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef struct _GskGpuUploadTextureOp GskGpuUploadTextureOp;
|
||||
|
||||
struct _GskGpuUploadTextureOp
|
||||
{
|
||||
GskGpuOp op;
|
||||
|
||||
GskGpuImage *image;
|
||||
GskGpuBuffer *buffer;
|
||||
GdkTexture *texture;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_gpu_upload_texture_op_finish (GskGpuOp *op)
|
||||
{
|
||||
GskGpuUploadTextureOp *self = (GskGpuUploadTextureOp *) op;
|
||||
|
||||
g_object_unref (self->image);
|
||||
g_clear_object (&self->buffer);
|
||||
g_object_unref (self->texture);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_upload_texture_op_print (GskGpuOp *op,
|
||||
GskGpuFrame *frame,
|
||||
GString *string,
|
||||
guint indent)
|
||||
{
|
||||
GskGpuUploadTextureOp *self = (GskGpuUploadTextureOp *) op;
|
||||
|
||||
gsk_gpu_print_op (string, indent, "upload-texture");
|
||||
gsk_gpu_print_image (string, self->image);
|
||||
gsk_gpu_print_newline (string);
|
||||
}
|
||||
|
||||
static void
|
||||
gsk_gpu_upload_texture_op_draw (GskGpuOp *op,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GskGpuUploadTextureOp *self = (GskGpuUploadTextureOp *) op;
|
||||
GdkTextureDownloader *downloader;
|
||||
|
||||
downloader = gdk_texture_downloader_new (self->texture);
|
||||
gdk_texture_downloader_set_format (downloader, gsk_gpu_image_get_format (self->image));
|
||||
gdk_texture_downloader_download_into (downloader, data, stride);
|
||||
gdk_texture_downloader_free (downloader);
|
||||
}
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
static GskGpuOp *
|
||||
gsk_gpu_upload_texture_op_vk_command (GskGpuOp *op,
|
||||
GskGpuFrame *frame,
|
||||
VkRenderPass render_pass,
|
||||
VkFormat format,
|
||||
VkCommandBuffer command_buffer)
|
||||
{
|
||||
GskGpuUploadTextureOp *self = (GskGpuUploadTextureOp *) op;
|
||||
|
||||
return gsk_gpu_upload_op_vk_command (op,
|
||||
frame,
|
||||
command_buffer,
|
||||
GSK_VULKAN_IMAGE (self->image),
|
||||
gsk_gpu_upload_texture_op_draw,
|
||||
&self->buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
static GskGpuOp *
|
||||
gsk_gpu_upload_texture_op_gl_command (GskGpuOp *op,
|
||||
GskGpuFrame *frame,
|
||||
gsize flip_y)
|
||||
{
|
||||
GskGpuUploadTextureOp *self = (GskGpuUploadTextureOp *) op;
|
||||
|
||||
return gsk_gpu_upload_op_gl_command (op,
|
||||
frame,
|
||||
self->image,
|
||||
gsk_gpu_upload_texture_op_draw);
|
||||
}
|
||||
|
||||
static const GskGpuOpClass GSK_GPU_UPLOAD_TEXTURE_OP_CLASS = {
|
||||
GSK_GPU_OP_SIZE (GskGpuUploadTextureOp),
|
||||
GSK_GPU_STAGE_UPLOAD,
|
||||
gsk_gpu_upload_texture_op_finish,
|
||||
gsk_gpu_upload_texture_op_print,
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
gsk_gpu_upload_texture_op_vk_command,
|
||||
#endif
|
||||
gsk_gpu_upload_texture_op_gl_command
|
||||
};
|
||||
|
||||
GskGpuImage *
|
||||
gsk_gpu_upload_texture_op (GskGpuFrame *frame,
|
||||
GdkTexture *texture)
|
||||
{
|
||||
GskGpuUploadTextureOp *self;
|
||||
|
||||
self = (GskGpuUploadTextureOp *) gsk_gpu_op_alloc (frame, &GSK_GPU_UPLOAD_TEXTURE_OP_CLASS);
|
||||
|
||||
self->texture = g_object_ref (texture);
|
||||
self->image = gsk_gpu_device_create_upload_image (gsk_gpu_frame_get_device (frame),
|
||||
gdk_texture_get_format (texture),
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
|
||||
return self->image;
|
||||
}
|
||||
|
||||
typedef struct _GskGpuUploadCairoOp GskGpuUploadCairoOp;
|
||||
|
||||
struct _GskGpuUploadCairoOp
|
||||
|
Loading…
Reference in New Issue
Block a user