[gtk/wip/chergert/glproto: 138/493] add texture pool
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/chergert/glproto: 138/493] add texture pool
- Date: Fri, 19 Feb 2021 02:25:07 +0000 (UTC)
commit 3e12ca22694d60888ff29e9ab182795565dd2318
Author: Christian Hergert <chergert redhat com>
Date: Thu Jan 7 20:29:13 2021 -0800
add texture pool
the goal here is to keep the pooling code out of the driver just so that
it is a bit easier to reason about going forward.
also, pool is a much less overloaded term here compared to cache when
dealing with textures.
gsk/meson.build | 1 +
gsk/next/gskgltexturepool.c | 185 +++++++++++++++++++++++++++++++++++++
gsk/next/gskgltexturepoolprivate.h | 69 ++++++++++++++
3 files changed, 255 insertions(+)
---
diff --git a/gsk/meson.build b/gsk/meson.build
index 8b63ccbb65..6c1f4c7566 100644
--- a/gsk/meson.build
+++ b/gsk/meson.build
@@ -62,6 +62,7 @@ gsk_private_sources = files([
'next/gskgltextureatlas.c',
'next/gskgltexturelibrary.c',
'next/gskgluniformstate.c',
+ 'next/gskgltexturepool.c',
])
gsk_public_headers = files([
diff --git a/gsk/next/gskgltexturepool.c b/gsk/next/gskgltexturepool.c
new file mode 100644
index 0000000000..219539219e
--- /dev/null
+++ b/gsk/next/gskgltexturepool.c
@@ -0,0 +1,185 @@
+/* gskgltexturepool.c
+ *
+ * Copyright 2020 Christian Hergert <chergert redhat com>
+ *
+ * This file 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.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This file 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 General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "gskgltexturepoolprivate.h"
+
+static void
+gsk_gl_texture_free (GskGLTexture *texture)
+{
+ if (texture->texture_id != 0)
+ {
+ glDeleteTextures (1, &texture->texture_id);
+ texture->texture_id = 0;
+ }
+
+ g_slice_free (GskGLTexture, texture);
+}
+
+void
+gsk_gl_texture_pool_init (GskGLTexturePool *self)
+{
+ memset (self, 0, sizeof *self);
+}
+
+void
+gsk_gl_texture_pool_clear (GskGLTexturePool *self)
+{
+ while (self->by_width.length > 0)
+ {
+ GskGLTexture *head = g_queue_peek_head (&self->by_width);
+
+ g_queue_unlink (&self->by_width, &head->width_link);
+ g_queue_unlink (&self->by_height, &head->height_link);
+
+ gsk_gl_texture_free (head);
+ }
+
+ g_assert (self->by_width.length == 0);
+ g_assert (self->by_height.length == 0);
+}
+
+void
+gsk_gl_texture_pool_put (GskGLTexturePool *self,
+ GskGLTexture *texture)
+{
+ GList *sibling = NULL;
+
+ g_return_if_fail (self != NULL);
+ g_return_if_fail (texture != NULL);
+
+ for (GList *iter = self->by_width.head;
+ iter != NULL;
+ iter = iter->next)
+ {
+ GskGLTexture *other = iter->data;
+
+ if (other->width > texture->width ||
+ (other->width == texture->width &&
+ other->height > texture->height))
+ break;
+
+ sibling = iter;
+ }
+
+ g_queue_insert_after_link (&self->by_width, sibling, &texture->width_link);
+
+ for (GList *iter = self->by_width.head;
+ iter != NULL;
+ iter = iter->next)
+ {
+ GskGLTexture *other = iter->data;
+
+ if (other->height > texture->height ||
+ (other->height == texture->height &&
+ other->width > texture->width))
+ break;
+
+ sibling = iter;
+ }
+
+ g_queue_insert_after_link (&self->by_width, sibling, &texture->width_link);
+}
+
+GskGLTexture *
+gsk_gl_texture_pool_get (GskGLTexturePool *self,
+ float width,
+ float height,
+ int min_filter,
+ int mag_filter,
+ gboolean always_create)
+{
+ GskGLTexture *texture;
+
+ g_return_val_if_fail (self != NULL, NULL);
+
+ if (always_create)
+ goto create_texture;
+
+ if (width >= height)
+ {
+ for (GList *iter = self->by_width.head;
+ iter != NULL;
+ iter = iter->next)
+ {
+ texture = iter->data;
+
+ if (texture->width >= width &&
+ texture->height >= height &&
+ texture->min_filter == min_filter &&
+ texture->mag_filter == mag_filter)
+ {
+ g_queue_unlink (&self->by_width, &texture->width_link);
+ g_queue_unlink (&self->by_height, &texture->height_link);
+
+ return texture;
+ }
+ }
+ }
+ else
+ {
+ for (GList *iter = self->by_height.head;
+ iter != NULL;
+ iter = iter->next)
+ {
+ texture = iter->data;
+
+ if (texture->width >= width &&
+ texture->height >= height &&
+ texture->min_filter == min_filter &&
+ texture->mag_filter == mag_filter)
+ {
+ g_queue_unlink (&self->by_width, &texture->width_link);
+ g_queue_unlink (&self->by_height, &texture->height_link);
+
+ return texture;
+ }
+ }
+ }
+
+create_texture:
+
+ texture = g_slice_new0 (GskGLTexture);
+ texture->width_link.data = texture;
+ texture->height_link.data = texture;
+ texture->min_filter = min_filter;
+ texture->mag_filter = mag_filter;
+
+ glGenTextures (1, &texture->texture_id);
+
+ glActiveTexture (GL_TEXTURE0);
+ glBindTexture (GL_TEXTURE_2D, texture->texture_id);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, min_filter);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, mag_filter);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ if (gdk_gl_context_get_use_es (gdk_gl_context_get_current ()))
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ else
+ glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+
+ glBindTexture (GL_TEXTURE_2D, 0);
+
+ return texture;
+}
diff --git a/gsk/next/gskgltexturepoolprivate.h b/gsk/next/gskgltexturepoolprivate.h
new file mode 100644
index 0000000000..ebedd6563d
--- /dev/null
+++ b/gsk/next/gskgltexturepoolprivate.h
@@ -0,0 +1,69 @@
+/* gskgltexturepoolprivate.h
+ *
+ * Copyright 2020 Christian Hergert <chergert redhat com>
+ *
+ * This file 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.1 of the License, or (at your option)
+ * any later version.
+ *
+ * This file 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 General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef _GSK_GL_TEXTURE_POOL_PRIVATE_H__
+#define _GSK_GL_TEXTURE_POOL_PRIVATE_H__
+
+#include "gskgltypes.h"
+
+G_BEGIN_DECLS
+
+typedef struct _GskGLTexture GskGLTexture;
+typedef struct _GskGLTexturePool GskGLTexturePool;
+
+struct _GskGLTexturePool
+{
+ GQueue by_width;
+ GQueue by_height;
+};
+
+struct _GskGLTexture
+{
+ GList width_link; /* Used to sort textures by width */
+ GList height_link; /* Used to sort textures by height */
+
+ gint64 last_used_in_frame;
+
+ GdkTexture *user;
+
+ guint texture_id;
+
+ float width;
+ float height;
+ int min_filter;
+ int mag_filter;
+
+ guint permanent : 1;
+};
+
+void gsk_gl_texture_pool_init (GskGLTexturePool *self);
+void gsk_gl_texture_pool_clear (GskGLTexturePool *self);
+GskGLTexture *gsk_gl_texture_pool_get (GskGLTexturePool *self,
+ float width,
+ float height,
+ int min_filter,
+ int mag_filter,
+ gboolean always_create);
+void gsk_gl_texture_pool_put (GskGLTexturePool *self,
+ GskGLTexture *texture);
+
+G_END_DECLS
+
+#endif /* _GSK_GL_TEXTURE_POOL_PRIVATE_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]