gtk/gsk/gpu/gskgldescriptors.c
Benjamin Otte 1b38cbd410 gpu: Handle storage buffers via descriptors
This makes the (currently single) storage buffer handled by
GskGpuDescriptors.
A side effect is that we now have support for multiple buffers in place.
We just have to use it.

Mixed into this commit is a complete rework of the pattern writer.
Instead of writing straight into the buffer (complete with repeatedly
backtracking when we have to do offscreens), write into a temporary
buffer and copy into the storage buffer on committing.
2024-01-07 07:22:52 +01:00

145 lines
3.6 KiB
C

#include "config.h"
#include "gskgldescriptorsprivate.h"
#include "gskglbufferprivate.h"
#include "gskglimageprivate.h"
struct _GskGLDescriptors
{
GskGpuDescriptors parent_instance;
GskGLDevice *device;
guint n_external;
};
G_DEFINE_TYPE (GskGLDescriptors, gsk_gl_descriptors, GSK_TYPE_GPU_DESCRIPTORS)
static void
gsk_gl_descriptors_finalize (GObject *object)
{
GskGLDescriptors *self = GSK_GL_DESCRIPTORS (object);
g_object_unref (self->device);
G_OBJECT_CLASS (gsk_gl_descriptors_parent_class)->finalize (object);
}
static gboolean
gsk_gl_descriptors_add_image (GskGpuDescriptors *desc,
GskGpuImage *image,
GskGpuSampler sampler,
guint32 *out_descriptor)
{
GskGLDescriptors *self = GSK_GL_DESCRIPTORS (desc);
gsize used_texture_units;
used_texture_units = gsk_gpu_descriptors_get_n_images (desc) + 2 * self->n_external;
if (gsk_gpu_image_get_flags (image) & GSK_GPU_IMAGE_EXTERNAL)
{
if (16 - used_texture_units < 3)
return FALSE;
*out_descriptor = (self->n_external << 1) | 1;
self->n_external++;
return TRUE;
}
else
{
if (used_texture_units >= 16)
return FALSE;
*out_descriptor = (gsk_gpu_descriptors_get_n_images (desc) - self->n_external) << 1;
return TRUE;
}
}
static gboolean
gsk_gl_descriptors_add_buffer (GskGpuDescriptors *desc,
GskGpuBuffer *buffer,
guint32 *out_descriptor)
{
gsize used_buffers;
used_buffers = gsk_gpu_descriptors_get_n_buffers (desc);
if (used_buffers >= 11)
return FALSE;
*out_descriptor = used_buffers;
return TRUE;
}
static void
gsk_gl_descriptors_class_init (GskGLDescriptorsClass *klass)
{
GskGpuDescriptorsClass *descriptors_class = GSK_GPU_DESCRIPTORS_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = gsk_gl_descriptors_finalize;
descriptors_class->add_image = gsk_gl_descriptors_add_image;
descriptors_class->add_buffer = gsk_gl_descriptors_add_buffer;
}
static void
gsk_gl_descriptors_init (GskGLDescriptors *self)
{
}
GskGpuDescriptors *
gsk_gl_descriptors_new (GskGLDevice *device)
{
GskGLDescriptors *self;
self = g_object_new (GSK_TYPE_GL_DESCRIPTORS, NULL);
self->device = g_object_ref (device);
return GSK_GPU_DESCRIPTORS (self);
}
guint
gsk_gl_descriptors_get_n_external (GskGLDescriptors *self)
{
return self->n_external;
}
void
gsk_gl_descriptors_use (GskGLDescriptors *self)
{
GskGpuDescriptors *desc = GSK_GPU_DESCRIPTORS (self);
gsize i, ext, n_textures;
n_textures = 16 - 3 * self->n_external;
ext = 0;
for (i = 0; i < gsk_gpu_descriptors_get_n_images (desc); i++)
{
GskGLImage *image = GSK_GL_IMAGE (gsk_gpu_descriptors_get_image (desc, i));
if (gsk_gpu_image_get_flags (GSK_GPU_IMAGE (image)) & GSK_GPU_IMAGE_EXTERNAL)
{
glActiveTexture (GL_TEXTURE0 + n_textures + 3 * ext);
gsk_gl_image_bind_texture (image);
ext++;
}
else
{
glActiveTexture (GL_TEXTURE0 + i - ext);
gsk_gl_image_bind_texture (image);
glBindSampler (i - ext, gsk_gl_device_get_sampler_id (self->device, gsk_gpu_descriptors_get_sampler (desc, i)));
}
}
for (i = 0; i < gsk_gpu_descriptors_get_n_buffers (desc); i++)
{
GskGLBuffer *buffer = GSK_GL_BUFFER (gsk_gpu_descriptors_get_buffer (desc, i));
/* index 0 are the globals, we start at 1 */
gsk_gl_buffer_bind_base (buffer, i + 1);
}
}