/*
 * Copyright (C) 1997-2009, R3vis Corporation.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA, or visit http://www.gnu.org/copyleft/lgpl.html.
 *
 * Original Contributor:
 *   Wes Bethel, R3vis Corporation, Marin County, California
 *   http://www.r3vis.com/
 * Additional Contributor(s):
 *
 * The OpenRM project is located at http://openrm.sourceforge.net/.
 */
/*
 * $Id: rmcmpmgr.h,v 1.5 2005/02/19 16:47:24 wes Exp $
 * Version: $Name: v180-alpha-02 $
 * $Revision: 1.5 $
 * $Log: rmcmpmgr.h,v $
 * Revision 1.5  2005/02/19 16:47:24  wes
 * Distro sync and consolidation.
 *
 * Revision 1.4  2005/01/23 17:17:02  wes
 * Copyright update to 2005.
 *
 * Revision 1.3  2004/01/17 04:05:41  wes
 * Updated copyright line for 2004.
 *
 * Revision 1.2  2003/02/02 02:07:14  wes
 * Updated copyright to 2003.
 *
 * Revision 1.1.1.1  2003/01/28 02:15:23  wes
 * Manual rebuild of rm150 repository.
 *
 * Revision 1.6  2002/08/29 22:21:13  wes
 * Massive upgrade to accommodate dynamic object reallocation within
 * the component manager, and within the context cache. Use the
 * debug #define DEBUG_LEVEL DEBUG_REALLOC_TRACE to get a printf
 * whenever a realloc occurs. With this upgrade, there are no
 * OpenRM limits on the size of the scene graph. There will be external
 * limits, such as the amount of RAM and the amount of space available
 * to your OpenGL implementation.
 *
 * Revision 1.5  2002/08/19 00:54:26  wes
 * Added API entries for new experiemental routines to get and set
 * the size of the OpenRM component manager object pool.
 *
 * Revision 1.4  2002/08/17 15:17:54  wes
 * Removed #define RM_COMPONENT_POOL_SIZE. This is now a global variable
 * defined in rm/rmglobal.c. The new #define is called DEFAULT_COMPONENT_POOL_SIZE.
 *
 * Revision 1.3  2002/06/17 01:10:09  wes
 * Changed RM_COMPONENT_POOL_SIZE from 1024 to 2048.
 *
 * Revision 1.2  2002/04/30 19:42:33  wes
 * Updated copyright dates.
 *
 * Revision 1.1  2000/12/03 23:20:11  wes
 * Initial entry.
 *
 */

#ifndef __rmcmpmgr_h_
#define __rmcmpmgr_h_

#ifdef __cplusplus
extern "C" {
#endif

/*
 * RM_COMPONENT_POOL_SIZE defines the number of objects created
 * by the component manager. Increasing this value increases the
 * number of such objects created by at rmInit time.
 */
/*
 * 8/11/02 wes. RM_COMPONENT_POOL_SIZE is now a global variable located
 * in rm/rmglobal.c. It's default value is defined in include/rm/rmdflts.h.
 * Its initial value can be set with the new routine
 * rmInitComponentPoolSize(value), which MUST be called prior to rmInit().
 * The default value at this time is 2048.
 */
/* #define RM_COMPONENT_POOL_SIZE 2048 */

/*
 * In a future release, the component mgr will auto-realloc when
 * the objects in the free list have been depleted. When that day
 * comes, the following #define will be used to indicate the
 * number of additional objects that will be reallocated.
 */
/* #define RM_COMPONENT_POOL_REALLOC_SIZE 1024 */

/*
 * 8/23/02 - the "objIndx" in the compList now uses a combination
 * of a "page number" and an "offset", both of which are encoded
 * into an unsigned int, which we assume is a 32-bit quanity on
 * all platforms. the following macros are used to set/get these
 * fields.
 *
 * the values for PAGE_SIZE and NUM_PAGES the number of bits allocated
 * from a 32-bit int for total items per page, and number of pages.
 */

/*
 * 12 bits for PAGE_SIZE means 4096 items per page;
 * 20 bits for NUM_PAGES means 1M pages.
 * these are encoded into a 32 bit int as:
 *
 * PAGE_INDEX (NUM_PAGES worth of bits) | OFFSET (PAGE_SIZE worth of bits)
 *
 * so that the index on a page occupies the low order bits, and the
 * page index occupies the high order bits.
 */
#define PAGE_SIZE_BITS    12	/* 2^12 = 4096 */
#define NUM_PAGES_BITS    (32-PAGE_SIZE_BITS)

#define NUM_ITEMS_PER_PAGE (1 << PAGE_SIZE_BITS)
#define OFFSET_MASK       (NUM_ITEMS_PER_PAGE - 1)
    
#define NUM_PAGES          (1 << NUM_PAGES_BITS)
#define PAGE_INDEX_MASK    (NUM_PAGES - 1)
    
/*
 * extract the page index field from the unsigned int "a"
 */
#define rmCompManagerGetPage(a) ( ((a) >> PAGE_SIZE_BITS) & PAGE_INDEX_MASK )
/*
 * extract the offset field from the unsigned int "a"
 */
#define rmCompManagerGetOffset(a) ( ((a) & OFFSET_MASK) )

/*
 * set the page field of the unsigned int "a" to the value of "b"
 */
#define rmCompManagerSetPage(a, b) ( (a)  | (((b) & PAGE_INDEX_MASK) << PAGE_SIZE_BITS) )

/*
 * set the offset field of the unsigned int "a" to the value of "b"
 */
#define rmCompManagerSetOffset(a, b) ( ((a) & (OFFSET_MASK)) | ( (b) & OFFSET_MASK) )

typedef struct RMcompList
{
    unsigned int objIndx;	/* index into object pool */
    int nextIndx;	/* index to next item in list */
    int prevIndx;	/* index to prev item in list */
    int myIndx;		/* index of this entry in metalist */
} RMcompList;

typedef struct
{
    int currentPoolSize;	/* current size of Pool (alloc & free) */
    
    int numFree;		/* number in free list */
    int numAlloc;		/* number in alloc list */
    
    RMcompList *metaListHead;	/* pointer to list */

    int startFree;		/* index to first free */
    int startAlloc;		/* index to first alloc */

    int componentSize;		/* sizeof(eachComponent) */

    int numPages;
    void **objectPool;
    
    RMmutex *guard;		/* to serialize new/delete amongst
				 multiple writers */
} RMcompMgrHdr;

/* set/get component pool size, rmcmpmgr.c [2] */
RM_EXPORT_API  void rmComponentPoolSetSize (int newSize);
RM_EXPORT_API  int  rmComponentPoolGetSize (void);


#ifdef __cplusplus
}
#endif

#endif /* __rmcmpmgr_h */
/* EOF */

