Common code in Core
-------------------

NOTE: Some of the interfaces described here (most notably the allocator) are
      semi-internal interfaces and as such API is not considered stable.

Common Macros and Inline Functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[source,c]
-------------------------------------------------------------------------------
#include <core/gp_common.h>
/* or */
#include <gfxprim.h>

GP_MIN(a, b);

GP_MAX(a, b);

GP_MAX3(a, b, c);

GP_ABS(a);

GP_SWAP(a, b);

GP_SIGN(a);

GP_ARRAY_SIZE(arr);

GP_CONTAINER_OF(ptr, structure, member);

-------------------------------------------------------------------------------

These common macros implements basic functions such as minimum, maximum,
absolute value, swap and sign.

All macros use 'typeof()' in order to evaluate their arguments exactly once.

The 'GP_ARRAY_SIZE()' macro computes size of statically defined array (i.e.
returns +sizeof(array) / sizeof(elem)+).

The 'GP_CONTAINER_OF()' macro computes pointer to a structure given pointer to
its member.

[source,c]
-------------------------------------------------------------------------------
#include <core/GP_Clamp.h>

/*
 * Clamps integer value to 8 bit unsigned value.
 */
GP_CLAMP_INT_0_255(val);

/*
 * Clamps integer value.
 */
GP_CLAMP(val, min, max);

-------------------------------------------------------------------------------

Value clamping macros.

NOTE: this header is not included by including the 'gfxprim.h' header.

Temporary Buffer Allocator
~~~~~~~~~~~~~~~~~~~~~~~~~~

Temporary buffer allocator is used to allocate temporary buffer needed for
certain operations (mostly used in image filters).

The intended usage of temporary buffers is:

* Count sum of the size needed for all buffers
* Allocate temporary buffer of this size
* Partition the buffer into smaller blocks
* Use the blocks as needed
* Once operation is done, free the buffer

The allocator code greatly simplifies these steps. Moreover it avoids memory
fragmentation by creating small buffers on the process stack (current theshold
is set to 2kB) and by grouping the temporary buffers into one continuous
region.

NOTE: The allocator itself does not align the resulting blocks. It's your
      responsibility to allocate the buffers in a way that the result is
      adequately aligned (hint: the start of the block is aligned, so
      get blocks that needs to be aligned first).

[source,c]
-------------------------------------------------------------------------------
#include <core/gp_temp_alloc.h>

/*
 * A macro that creates block allocator.
 *
 * The name must be unique among variable and functions names.
 *
 * The bsize is actual size of the block allocated.
 */
gp_temp_alloc_create(name, bsize);

/*
 * A macro that returns pointer to the start of a block of a bsize
 * partioned from the block allocator passed as self argument.
 */
gp_temp_alloc_get(self, bsize);

/*
 * Free the allocator memory.
 */
gp_temp_alloc_free(self);
-------------------------------------------------------------------------------

Example usage of the allocator:

[source,c]
-------------------------------------------------------------------------------
#include <core/gp_temp_alloc.h>

int foo(...)
{
	gp_temp_alloc_create(tmp, 3 * img->width);

	uint8_t *R = gp_temp_alloc_get(tmp, img->width);
	uint8_t *G = gp_temp_alloc_get(tmp, img->width);
	uint8_t *B = gp_temp_alloc_get(tmp, img->width);

	/* start of the code that uses the buffers */

	...

	if (error) {
		gp_temp_alloc_free(tmp);
		return -1;
	}

	...

	/* end of the code that uses the buffers */

	gp_temp_alloc_free(tmp);

	return 0;
}
-------------------------------------------------------------------------------

