// Copyright (C) 2004-2009 Christoph Kubisch & Eike Decker
// This file is part of the "Luxinia Engine".
// For conditions of distribution and use, see copyright notice in luxiniapublicsdk.txt
//
// <Author: Christoph Kubisch>


#ifndef __LUXCORE_MEMDEFS_H__
#define __LUXCORE_MEMDEFS_H__

#include <luxplatform/luxplatform.h>
#include <luxcore/memorybase.h>
#include <luxplatform/debug.h>

// Used by the Special Allocators
//	MemoryList, MemoryPool, MemoryStack

#ifdef MEMORY_GENERIC_STATS
	#include <luxcore/memorygeneric.h>
	#define MEMORY_LOCAL_MALLOC				lxMemGenAlloc
	#define MEMORY_LOCAL_CALLOC				lxMemGenCalloc
	#define MEMORY_LOCAL_REALLOC			lxMemGenRealloc
	#define MEMORY_LOCAL_FREE				lxMemGenFree
	#define MEMORY_LOCAL_FREEALIGNED		lxMemGenFreeAligned
	#define MEMORY_LOCAL_MALLOCALIGNED		lxMemGenAllocAligned
#else
	#define MEMORY_LOCAL_MALLOC				MEMORY_GLOBAL_MALLOC
	#define MEMORY_LOCAL_CALLOC				MEMORY_GLOBAL_CALLOC
	#define MEMORY_LOCAL_REALLOC(a,b,c)		MEMORY_GLOBAL_REALLOC(a,b)
	#define MEMORY_LOCAL_FREE(a,b)			MEMORY_GLOBAL_FREE(a)
	#define MEMORY_LOCAL_FREEALIGNED(a,b)	MEMORY_GLOBAL_FREEALIGNED(a)
	#define MEMORY_LOCAL_MALLOCALIGNED		MEMORY_GLOBAL_MALLOCALIGNED
#endif

#ifdef __cplusplus
extern "C"{
#endif

//////////////////////////////////////////////////////////////////////////

typedef struct lxMemoryNode_s{
	struct lxMemoryNode_s*	next;
}lxMemoryNode_t;

typedef struct lxMemoryPage_s {
	struct lxMemoryPage_s*	next;
	uint					size;
} lxMemoryPage_t;

//////////////////////////////////////////////////////////////////////////
// MemoryList
#define MEMORY_LIST_MAXSLOTS	16

typedef struct lxMemorySizeSlot_s {
	uint			size;
	lxMemoryNode_t*	freelist;
#ifdef LUX_PROFILING
	int				cnt;
#endif
} lxMemorySizeSlot_t;

typedef struct lxMemoryList_s {
	int		cnt;
	lxMemorySizeSlot_t	slots[MEMORY_LIST_MAXSLOTS];

	byte*			chunk;
	uint			chunkpos;
	uint			chunksize;
	uint			alignSize;

	lxMemoryPage_t	*pagelist;
#ifdef LUX_PROFILING
	int				numItems;
	uint			memAllocatedPages;
	uint			memAllocatedOuter;
	uint			memWasted;
#endif
} lxMemoryList_t;

void MemoryList_initBits (lxMemoryList_t* mc, uint sizeminbit, uint sizemaxbit, uint startpagesize, uint alignSize);
void MemoryList_init (lxMemoryList_t* mc, uint numSizes, const uint *sizes, uint startpagesize, uint alignSize);
void MemoryList_deinit (lxMemoryList_t* mc);

//////////////////////////////////////////////////////////////////////////
// MemoryPool

typedef struct lxMemoryPool_s {
	uint	valueSize;
	uint	pageValues;
	uint	alignSize;
	uint	used;
	booln	multiPages;

	lxMemoryNode_t*	freelist;
	lxMemoryPage_t*	pagelist;
} lxMemoryPool_t;

void MemoryPool_init (lxMemoryPool_t* mem,uint valueSize, uint pageValues, uint alignSize, booln multiPages);
void MemoryPool_deinit (lxMemoryPool_t *mem);


//////////////////////////////////////////////////////////////////////////
// MemoryStack

typedef struct lxMemoryStack_s{
	const char		*name;
	byte			*dataorig;	// the allocated memory
	byte			*data;		// the aligned start
	size_t			inuse;		// what is used in bytes
	size_t			total;		// the total in bytes
	booln			resized;
}lxMemoryStack_t;

#ifdef __cplusplus
}
#endif

#endif
