gtk2/gsk/gl/opbuffer.c
Timm Bäder 72d4a83af8 gl renderer: Moar state tracking
Track what we really need to send for inset shadows, which are used
as a border replacement in many cases.

Fishbowl says I can draw around 200-300 more switches per frame like
this too.
2020-07-28 05:34:11 +02:00

134 lines
2.9 KiB
C

#include "opbuffer.h"
#include <string.h>
static guint op_sizes[OP_LAST] = {
0,
sizeof (OpOpacity),
sizeof (OpColor),
sizeof (OpMatrix),
sizeof (OpMatrix),
sizeof (OpProgram),
sizeof (OpRenderTarget),
sizeof (OpClip),
sizeof (OpViewport),
sizeof (OpTexture),
sizeof (OpRepeat),
sizeof (OpLinearGradient),
sizeof (OpColorMatrix),
sizeof (OpBlur),
sizeof (OpShadow),
sizeof (OpOutsetShadow),
sizeof (OpBorder),
sizeof (OpBorder),
sizeof (OpBorder),
sizeof (OpCrossFade),
sizeof (OpShadow),
0,
sizeof (OpDraw),
sizeof (OpDumpFrameBuffer),
sizeof (OpDebugGroup),
0,
sizeof (OpBlend),
};
void
op_buffer_init (OpBuffer *buffer)
{
static gsize initialized = FALSE;
if (g_once_init_enter (&initialized))
{
guint i;
for (i = 0; i < G_N_ELEMENTS (op_sizes); i++)
{
guint size = op_sizes[i];
if (size > 0)
{
/* Round all op entry sizes to the nearest 16 to ensure
* that we guarantee proper alignments for all op entries.
* This is only done once on first use.
*/
#define CHECK_SIZE(s) else if (size < (s)) { size = s; }
if (0) {}
CHECK_SIZE (16)
CHECK_SIZE (32)
CHECK_SIZE (48)
CHECK_SIZE (64)
CHECK_SIZE (80)
CHECK_SIZE (96)
CHECK_SIZE (112)
CHECK_SIZE (128)
CHECK_SIZE (144)
CHECK_SIZE (160)
CHECK_SIZE (176)
CHECK_SIZE (192)
else g_assert_not_reached ();
#undef CHECK_SIZE
op_sizes[i] = size;
}
}
g_once_init_leave (&initialized, TRUE);
}
memset (buffer, 0, sizeof *buffer);
buffer->buflen = 4096;
buffer->bufpos = 0;
buffer->buf = g_malloc (buffer->buflen);
buffer->index = g_array_new (FALSE, FALSE, sizeof (OpBufferEntry));
/* Add dummy entry to guarantee non-empty index */
op_buffer_add (buffer, OP_NONE);
}
void
op_buffer_destroy (OpBuffer *buffer)
{
g_free (buffer->buf);
g_array_unref (buffer->index);
}
void
op_buffer_clear (OpBuffer *buffer)
{
if (buffer->index->len > 1)
g_array_remove_range (buffer->index, 1, buffer->index->len - 1);
buffer->bufpos = 0;
}
static inline void
ensure_buffer_space_for (OpBuffer *buffer,
guint size)
{
if G_UNLIKELY (buffer->bufpos + size >= buffer->buflen)
{
buffer->buflen *= 2;
buffer->buf = g_realloc (buffer->buf, buffer->buflen);
}
}
gpointer
op_buffer_add (OpBuffer *buffer,
OpKind kind)
{
guint size = op_sizes[kind];
OpBufferEntry entry;
entry.pos = buffer->bufpos;
entry.kind = kind;
if (size > 0)
ensure_buffer_space_for (buffer, size);
g_array_append_val (buffer->index, entry);
buffer->bufpos += size;
return &buffer->buf[entry.pos];
}