#ifndef	PAL_DATAMAN_H
#define	PAL_DATAMAN_H

#include <../source/TAL/objbase.h>

/*	======================================================================
 *	TSD & global data structures.
 */

#ifdef	MALLOC_DEBUG

/*
 *	Memory hash node
 */
typedef struct mem_list_entry_s
{
	struct mem_list_entry_s *next; /* for hash routines */
    size_t				size;
    unsigned			opaque;
    void				*data;
	u32_p				sentinel_ptr;
}	mem_list_entry_t, *mem_list_entry_p;

/*
 *	Note: HASH_LIMIT must be (power of 2)-1.
 */
#define			MEMORY_HASH_LIMIT	65535
#define			OBJECT_HASH_LIMIT	4095

/*
 *	Macros used by memory management functions.
 */
#define	MEMORY_HASHPROC(ptr) \
		(((u32_t)(ptr) + ((u32_t)(ptr) >> 4) + \
          ((u32_t)(ptr) >> 8)) & MEMORY_HASH_LIMIT)

#define	OBJECT_HASHPROC(ptr) \
		(((u32_t)(ptr) + ((u32_t)(ptr) >> 4) + \
          ((u32_t)(ptr) >> 8)) & OBJECT_HASH_LIMIT)

#define LIBV_INVALID_MAGIC	0xDEADDEAD

#endif	/* MALLOC_DEBUG */

/*
 * LibV internal data, shared between all threads.
 * Note: any changes _must_ be reflected in initializer (dataman.c).
 */

/*
 * BIG_FIXME: get rid of it, such a complexity is _not_ needed; all
 * we need to do is to aquire big_global_lock and access data stored
 * directly in C source file near to routine which uses them !
 */

#define			LIBV_GLOBAL_MAGIC		0x4C564744		/* LVGD */
typedef struct	global_data_s
{
	u32_t		magic;				/* LIBV_GLOBAL_MAGIC */
	u32_t		thread_count;		/* number of user-created threads */
	/* v_log.c */
	vhandle_t	log_file;
	u32_t		log_upper_level;
#ifdef	MALLOC_DEBUG
	/* Total number of pointers and handles */
	s32_t			hash_ref_count;
	/* Pointer hash table */
	mem_list_entry_p	memory_hash;
	/* Handle hash table */
	mem_list_entry_p	object_hash;
#endif	/* MALLOC_DEBUG */
#ifdef			CONFIG_NT_CONSOLE
	void		*inhandle, *outhandle;
	vboolean	own_console; /* == true if console was AllocConsole()d */
#endif			/* CONFIG_NT_CONSOLE */
	/* all callbacks are thread-safe, so caller can accumulate
	 * pointers to them, unlock global data and than call callbacks
	 * secuentially. TODO: debug console logs: disallow to set cb twice ? */
	vp_stack_t	log_callbacks;
#ifdef	__WIN32__
	/* vidwgl.c: counter for unical class names */
	u32_t		context_count;
	/* TODO: workaround NT 4.0 OpenGL ICD bug - implement some method to 
	 * disallow context creation from non-main thread after destruction of
	 * the first such context (GPF raised from NtWaitForMultipleObjectsEx) */
#endif	/* __WIN32__ */
	/* v_reg.c */
	ntree_p		reg_root;		/* registry root node */
	ntree_p		current_key;	/* registry current key */
}	global_data_t, *global_data_p;

/*
 *	LibV internal TSD.
 */
#define			LIBV_TSD_MAGIC		0x4C565444			/* LVTD */
typedef struct	thread_data_s
{
	u32_t		magic;
	/* vidgl/bitmap.c */
	u8_t		constant_alpha;
	/* input/incodes.c */
	input_state_t	input_state;
	/* v_wmf.c */
	u32_t		meta_x_extent,meta_y_extent;
	/* vfs/fswrap.c */
	/* PAL/vidglx.c | PAL/vidwgl.c */
	vhandle_t	gl_context;
#ifdef	__UNIX__
	/* used to determine status of the owner thread;
     * see v_sched.c :: PosixThreadEntry */
	void		*this_thread;
#endif	/* __UNIX__ */
	/* used to determine exit code of last threadJoin()'ed child;
     * see v_sched.c :: threadDestroy() */
	u32_t		child_exit_code;
#ifdef	MALLOC_DEBUG
	/* used for eliminating memory leaks */
	unsigned	mem_opaque;
#endif	/* MALLOC_DEBUG */
}	thread_data_t, *thread_data_p;

/*
 *	Internally used types and macros.
 */

#define GetThreadData() \
		((thread_data_t*)(libvGetSpecific()))

/*	Vertex drawing function */
typedef	void (*vertex_draw_proc_t)(vec_t *v,vec_t *c,vec_t *n,vec_t *t);
/*	Triangle drawing function */
typedef	void (*tri_draw_proc_t)(tlist_face_t *tri);
/*	Draw flags */
#define	NORMAL_DRAW_BIT			1
#define	TEXTURE_DRAW_BIT		2
#define	COLOR_DRAW_BIT			4

/*
 *	Internally used functions.
 */
/*
**	Returns contents of guarded section. After use, section
**	MUST be unlocked by libvUnlockGlobal().
**	Implemented in PAL/sched.c
*/
extern global_data_p	(*libvLockGlobal)(void);
/*
**	Unlocks global data, makes it possible to use by another threads.
**	Implemented in PAL/sched.c
*/
extern void				(*libvUnlockGlobal)(void);

/*
 * Returns global data, assuming thread-safe environment (or prior lock).
 */
global_data_p	libvLockedGlobal(void);

#ifdef	__cplusplus
extern "C" {
#endif	/* __cplusplus */
	/*
	**	Prints error message in case when conlPrintf() can't be used.
	**	Implemented in PAL/dataman.c
	*/
	void	V_CALL	libvError(char *msg);
	/*
	**	For changing contents of private TSD.
    **	Used for internal TSD managing, LibV clients SHOULDN'T
    **	call these functions !
	**
	**	Implemented in PAL/sched.c
	*/
	void		V_CALL		libvSetSpecific(void_p specific);
	void_p		V_CALL		libvGetSpecific(void);
	/*
	**	GL draw procs: returns functions for vertex/triangle drawing
	**	via OpenGL, depending on current OpenGL state.
    **	Implemented in vidgl/gldraw.c
	*/
	u32_t	/* returns "draw mask", which reflects current GL state */
			V_CALL	vglGetDrawBits(void);
	vertex_draw_proc_t	/* returns proc for vertex drawing */
			V_CALL	vglGetVertexDrawProc(int draw_bits);
	tri_draw_proc_t	/* same as above, for triangles */
			V_CALL	vglGetTriangleDrawProc(int draw_bits);
#ifdef	__cplusplus
}
#endif	/* __cplusplus */

/*
 *	Platform - dependent functions, used internally.
 */
#ifdef	__cplusplus
extern "C" {
#endif	/* __cplusplus */
#ifdef	__WIN32__
	/*
	**	Returns:
	**		-1 - we are under MustDie9x/ME;
	**		>= 3 - we are under NT.
	*/
	int	V_CALL	ntGetVersion(void);
#endif	/* __WIN32__ */
#ifdef	__cplusplus
}
#endif	/* __cplusplus */

#endif	/* V_MT_H */
