mirror of https://github.com/GNOME/gimp.git
167 lines
3.6 KiB
C
167 lines
3.6 KiB
C
/* GIMP - The GNU Image Manipulation Program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* gimp-scratch.h
|
|
* Copyright (C) 2018 Ell
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 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 <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef __GIMP_SCRATCH_H__
|
|
#define __GIMP_SCRATCH_H__
|
|
|
|
|
|
#include <string.h>
|
|
|
|
|
|
#define GIMP_SCRATCH_ALIGNMENT 16
|
|
#define GIMP_SCRATCH_MAX_BLOCK_SIZE (1 << 20)
|
|
|
|
|
|
/* private types */
|
|
|
|
typedef struct
|
|
{
|
|
gsize size;
|
|
guint8 offset;
|
|
guint8 padding[GIMP_SCRATCH_ALIGNMENT - (sizeof (gsize) + 1)];
|
|
guint8 data[];
|
|
} GimpScratchBlock;
|
|
|
|
typedef struct
|
|
{
|
|
GimpScratchBlock **blocks;
|
|
gint n_blocks;
|
|
gint n_available_blocks;
|
|
} GimpScratchContext;
|
|
|
|
|
|
/* private variables */
|
|
|
|
extern GPrivate gimp_scratch_context;
|
|
|
|
|
|
/* private functions */
|
|
|
|
GimpScratchBlock * gimp_scratch_block_new (gsize size);
|
|
void gimp_scratch_block_free (GimpScratchBlock *block);
|
|
|
|
GimpScratchContext * gimp_scratch_context_new (void);
|
|
void gimp_scratch_context_free (GimpScratchContext *context);
|
|
|
|
|
|
/* public functions */
|
|
|
|
|
|
inline gpointer
|
|
gimp_scratch_alloc (gsize size)
|
|
{
|
|
GimpScratchContext *context;
|
|
GimpScratchBlock *block;
|
|
|
|
if (G_UNLIKELY (! size))
|
|
return NULL;
|
|
|
|
if (G_UNLIKELY (size > GIMP_SCRATCH_MAX_BLOCK_SIZE))
|
|
{
|
|
block = gimp_scratch_block_new (size);
|
|
block->size = 0;
|
|
|
|
return block->data;
|
|
}
|
|
|
|
context = g_private_get (&gimp_scratch_context);
|
|
|
|
if (G_UNLIKELY (! context))
|
|
{
|
|
context = gimp_scratch_context_new ();
|
|
|
|
g_private_set (&gimp_scratch_context, context);
|
|
}
|
|
|
|
if (G_LIKELY (context->n_available_blocks))
|
|
{
|
|
block = context->blocks[--context->n_available_blocks];
|
|
|
|
if (G_LIKELY (size <= block->size))
|
|
return block->data;
|
|
|
|
gimp_scratch_block_free (block);
|
|
}
|
|
|
|
block = gimp_scratch_block_new (size);
|
|
|
|
return block->data;
|
|
}
|
|
|
|
inline gpointer
|
|
gimp_scratch_alloc0 (gsize size)
|
|
{
|
|
gpointer ptr;
|
|
|
|
if (G_UNLIKELY (! size))
|
|
return NULL;
|
|
|
|
ptr = gimp_scratch_alloc (size);
|
|
|
|
memset (ptr, 0, size);
|
|
|
|
return ptr;
|
|
}
|
|
|
|
inline void
|
|
gimp_scratch_free (gpointer ptr)
|
|
{
|
|
GimpScratchContext *context;
|
|
GimpScratchBlock *block;
|
|
|
|
if (G_UNLIKELY (! ptr))
|
|
return;
|
|
|
|
block = (GimpScratchBlock *) ((guint8 *) ptr - GIMP_SCRATCH_ALIGNMENT);
|
|
|
|
if (G_UNLIKELY (! block->size))
|
|
{
|
|
gimp_scratch_block_free (block);
|
|
|
|
return;
|
|
}
|
|
|
|
context = g_private_get (&gimp_scratch_context);
|
|
|
|
if (G_UNLIKELY (context->n_available_blocks == context->n_blocks))
|
|
{
|
|
context->n_blocks = MAX (2 * context->n_blocks, 1);
|
|
context->blocks = g_renew (GimpScratchBlock *, context->blocks,
|
|
context->n_blocks);
|
|
}
|
|
|
|
context->blocks[context->n_available_blocks++] = block;
|
|
}
|
|
|
|
|
|
#define gimp_scratch_new(type, n) \
|
|
((type *) (gimp_scratch_alloc (sizeof (type) * (n))))
|
|
|
|
#define gimp_scratch_new0(type, n) \
|
|
((type *) (gimp_scratch_alloc0 (sizeof (type) * (n))))
|
|
|
|
|
|
/* stats */
|
|
|
|
guint64 gimp_scratch_get_total (void);
|
|
|
|
|
|
#endif /* __GIMP_SCRATCH_H__ */
|