sl@0: /*
sl@0: * Copyright (c) 2003 Nokia Corporation and/or its subsidiary(-ies).
sl@0: * All rights reserved.
sl@0: * This component and the accompanying materials are made available
sl@0: * under the terms of the License "Eclipse Public License v1.0"
sl@0: * which accompanies this distribution, and is available
sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: *
sl@0: * Initial Contributors:
sl@0: * Nokia Corporation - initial contribution.
sl@0: *
sl@0: * Contributors:
sl@0: *
sl@0: * Description: Global definitions
sl@0: *
sl@0: */
sl@0: 
sl@0: #ifndef __M3G_DEFS_H__
sl@0: #define __M3G_DEFS_H__
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \file
sl@0:  * \brief Global definitions for the Nokia M3G API implementation
sl@0:  */
sl@0: 
sl@0: /* Include public API */
sl@0: #include "M3G/m3g_core.h"
sl@0: 
sl@0: #if defined(__cplusplus)
sl@0: extern "C" {
sl@0: #endif
sl@0: 
sl@0: /* Try to recognize debug builds */
sl@0: #if defined(_DEBUG) || defined(DEBUG)
sl@0: #undef M3G_DEBUG
sl@0: #define M3G_DEBUG
sl@0: #endif
sl@0: 
sl@0: /*----------------------------------------------------------------------
sl@0:  * Platform dependent definitions
sl@0:  *--------------------------------------------------------------------*/
sl@0: 
sl@0: /* Define constants for use in m3g_config.h */
sl@0:     
sl@0: #define M3G_LOG_FATAL_ERRORS    0x0001
sl@0: #define M3G_LOG_USER_ERRORS     0x0002
sl@0: #define M3G_LOG_WARNINGS        0x0003
sl@0: #define M3G_LOG_PROFILE         0x0004
sl@0: #define M3G_LOG_INTERFACE       0x0010
sl@0: #define M3G_LOG_OBJECTS         0x0020
sl@0: #define M3G_LOG_STAGES          0x0040
sl@0: #define M3G_LOG_REFCOUNT        0x0080
sl@0: #define M3G_LOG_MEMORY_USAGE    0x0100
sl@0: #define M3G_LOG_MEMORY_BLOCKS   0x0200
sl@0: #define M3G_LOG_MEMORY_MAPPING  0x0400
sl@0: #define M3G_LOG_MEMORY_ALL      0x0F00
sl@0: #define M3G_LOG_RENDERING       0x1000
sl@0: #define M3G_LOG_IMAGES          0x2000
sl@0: #define M3G_LOG_ALL             0xFFFF
sl@0:     
sl@0: /* Include the platform configuration file; the possible configuration
sl@0:  * options are documented and their default values set below */
sl@0:     
sl@0: #include "m3g_config.h"
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_TARGET_GENERIC
sl@0:  * \brief Enables a generic C build
sl@0:  */   
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_TARGET_ISA
sl@0:  * \brief Enables building for ISA
sl@0:  */   
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_TARGET_SYMBIAN
sl@0:  * \brief Enables building for Symbian
sl@0:  */
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_TARGET_WIN32
sl@0:  * \brief Enables building for Win32
sl@0:  */      
sl@0: #if defined(M3G_TARGET_GENERIC)
sl@0: #elif defined(M3G_TARGET_ISA)
sl@0: #elif defined(M3G_TARGET_SYMBIAN)
sl@0: #elif defined(M3G_TARGET_WIN32)
sl@0: #elif defined(S_SPLINT_S) /* auto-recognize Splint as a special case */
sl@0: #   define M3G_TARGET_GENERIC
sl@0: #else
sl@0: #   error Build target undefined! Supply one of the M3G_TARGET_* definitions.
sl@0: #endif
sl@0:     
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_USE_NGL_API
sl@0:  * \brief Enable the legacy "NGL" OpenGL context management interface
sl@0:  */
sl@0: #if defined(M3G_USE_NGL_API)
sl@0: #   define M3G_NGL_CONTEXT_API
sl@0: #   define M3G_NGL_TEXTURE_API
sl@0: #endif
sl@0:     
sl@0: #if defined(M3G_TARGET_ISA)
sl@0: #   if !defined(M3G_NGL_CONTEXT_API)
sl@0: #       error ISA builds must define M3G_USE_NGL_API
sl@0: #   endif
sl@0: #endif   
sl@0: #if defined(M3G_TARGET_SYMBIAN)
sl@0: #   if defined(M3G_NGL_TEXTURE_API) || defined(M3G_NGL_CONTEXT_API)
sl@0: #       error Legacy NGL API not supported in Symbian builds
sl@0: #   endif
sl@0: #endif
sl@0:     
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_ALIGNMENT
sl@0:  * \brief Alignment, in bytes, mandated for internal data structures
sl@0:  *
sl@0:  * This must meet or exceed the alignment requirement of the
sl@0:  * underlying hardware. The default is 4 bytes.
sl@0:  */
sl@0: #if !defined(M3G_ALIGNMENT)
sl@0: #   define M3G_ALIGNMENT        4
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_MAX_GL_CONTEXTS
sl@0:  * \brief Maximum number of GL contexts to cache at once
sl@0:  *
sl@0:  * \note This only applies to builds using the EGL API.
sl@0:  */
sl@0: #if !defined(M3G_MAX_GL_CONTEXTS)
sl@0: #   define M3G_MAX_GL_CONTEXTS  3
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_MAX_GL_SURFACES
sl@0:  * \brief Maximum number of GL surfaces to cache at once
sl@0:  *
sl@0:  * \note This only applies to builds using the EGL API.
sl@0:  */
sl@0: #if !defined(M3G_MAX_GL_SURFACES)
sl@0: #   define M3G_MAX_GL_SURFACES  4
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_MAX_LIGHTS
sl@0:  * \brief Maximum number of lights in use simultaneously
sl@0:  *
sl@0:  * This is a rendering quality / performance trade-off; less lights
sl@0:  * will be (slightly) faster, but reduce the quality of lighting.
sl@0:  * 
sl@0:  * \note The value set here must not exceed the limits of the
sl@0:  * underlying OpenGL implementation; this is not automatically
sl@0:  * verified, but the default should be safe for all compliant OpenGL
sl@0:  * ES implementation
sl@0:  */
sl@0: #if !defined(M3G_MAX_LIGHTS)
sl@0: #   define M3G_MAX_LIGHTS       8
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_MAX_TEXTURE_DIMENSION
sl@0:  * \brief Maximum supported texture dimension
sl@0:  *
sl@0:  * \note The value set here must not exceed the limits of the
sl@0:  * underlying OpenGL implementation; this is not automatically
sl@0:  * verified, but the default should be safe for all compliant OpenGL
sl@0:  * ES implementation
sl@0:  */
sl@0: #if !defined(M3G_MAX_TEXTURE_DIMENSION)
sl@0: #   define M3G_MAX_TEXTURE_DIMENSION    256
sl@0: #endif
sl@0:     
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_MAX_VERTEX_TRANSFORMS
sl@0:  * \brief Maximum number of transforms per vertex
sl@0:  *
sl@0:  * \note The value set here must not exceed the limits of the
sl@0:  * underlying OpenGL implementation; this is not automatically
sl@0:  * verified
sl@0:  */
sl@0: #if !defined(M3G_MAX_VERTEX_TRANSFORMS)
sl@0: #   define M3G_MAX_VERTEX_TRANSFORMS    4
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_MAX_VIEWPORT_DIMENSION
sl@0:  * \brief Maximum supported viewport dimension
sl@0:  *
sl@0:  * \note The value set here must not exceed the limits of the
sl@0:  * underlying OpenGL implementation; this is not automatically
sl@0:  * verified, but the default should be safe for all compliant OpenGL
sl@0:  * ES implementation
sl@0:  */
sl@0: #if !defined(M3G_MAX_VIEWPORT_DIMENSION)
sl@0: #   define M3G_MAX_VIEWPORT_DIMENSION   1024
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_MAX_VIEWPORT_WIDTH
sl@0:  * \brief Maximum supported viewport width
sl@0:  *
sl@0:  * \note The value set here must not exceed the limits of the
sl@0:  * underlying OpenGL implementation; this is not automatically
sl@0:  * verified, but the default should be safe for all compliant OpenGL
sl@0:  * ES implementation
sl@0:  */
sl@0: #if !defined(M3G_MAX_VIEWPORT_WIDTH)
sl@0: #   define M3G_MAX_VIEWPORT_WIDTH       1024
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_MAX_VIEWPORT_HEIGHT
sl@0:  * \brief Maximum supported viewport height
sl@0:  *
sl@0:  * \note The value set here must not exceed the limits of the
sl@0:  * underlying OpenGL implementation; this is not automatically
sl@0:  * verified, but the default should be safe for all compliant OpenGL
sl@0:  * ES implementation
sl@0:  */
sl@0: #if !defined(M3G_MAX_VIEWPORT_HEIGHT)
sl@0: #   define M3G_MAX_VIEWPORT_HEIGHT      1024
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_NATIVE_LOADER
sl@0:  * \brief Include a native loader implementation
sl@0:  *
sl@0:  * This is always enabled in current builds.
sl@0:  */
sl@0: #undef M3G_NATIVE_LOADER
sl@0: #define M3G_NATIVE_LOADER
sl@0:     
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_NUM_TEXTURE_UNITS
sl@0:  * \brief Number of texture units to support
sl@0:  *
sl@0:  * \note The value set here must not exceed the limits of the
sl@0:  * underlying OpenGL implementation; this is not automatically
sl@0:  * verified, but the default should be safe for all compliant OpenGL
sl@0:  * ES implementation
sl@0:  */
sl@0: #if !defined(M3G_NUM_TEXTURE_UNITS)
sl@0: #   define M3G_NUM_TEXTURE_UNITS        2
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_SUPPORT_ANTIALIASING
sl@0:  * \brief Enable or disable support for antialiasing
sl@0:  *
sl@0:  * \note This is currently only supported for Symbian.
sl@0:  */
sl@0: #if !defined(M3G_SUPPORT_ANTIALIASING)
sl@0: #   if defined(M3G_NGL_CONTEXT_API)
sl@0: #       define M3G_SUPPORT_ANTIALIASING         M3G_FALSE
sl@0: #   else
sl@0: #       define M3G_SUPPORT_ANTIALIASING         M3G_TRUE
sl@0: #   endif
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_SUPPORT_DITHERING
sl@0:  * \brief Enable or disable support for dithering
sl@0:  */
sl@0: #if !defined(M3G_SUPPORT_DITHERING)
sl@0: #   define M3G_SUPPORT_DITHERING                M3G_FALSE
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_SUPPORT_LOCAL_CAMERA_LIGHTING
sl@0:  * \brief Enable or disable support for local camera lighting
sl@0:  */
sl@0: #if !defined(M3G_SUPPORT_LOCAL_CAMERA_LIGHTING)
sl@0: #   define M3G_SUPPORT_LOCAL_CAMERA_LIGHTING    M3G_FALSE
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_SUPPORT_MIPMAPPING
sl@0:  * \brief Enable or disable support for mipmapping
sl@0:  */
sl@0: #if !defined(M3G_SUPPORT_MIPMAPPING)
sl@0: #   define M3G_SUPPORT_MIPMAPPING               M3G_TRUE
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_SUPPORT_PERSPECTIVE_CORRECTION
sl@0:  * \brief Enable or disable support for perspective correct texturing
sl@0:  */
sl@0: #if !defined(M3G_SUPPORT_PERSPECTIVE_CORRECTION)
sl@0: #   define M3G_SUPPORT_PERSPECTIVE_CORRECTION   M3G_TRUE
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_SUPPORT_TRUE_COLOR
sl@0:  * \brief Enable or disable support for "true color" rendering
sl@0:  */
sl@0: #if !defined(M3G_SUPPORT_TRUE_COLOR)
sl@0: #   define M3G_SUPPORT_TRUE_COLOR               M3G_FALSE
sl@0: #endif
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_USE_16BIT_TEXTURES
sl@0:  * \brief Use 16-bit RGB textures internally to save memory
sl@0:  *
sl@0:  * This may reduce in some loss of performance, so it is defined
sl@0:  * M3G_FALSE by default.
sl@0:  */
sl@0: #if !defined(M3G_USE_16BIT_TEXTURES)
sl@0: #   define M3G_USE_16BIT_TEXTURES               M3G_FALSE
sl@0: #endif
sl@0:     
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_LOGLEVEL
sl@0:  * 
sl@0:  * \brief Controls the amount of log output
sl@0:  *
sl@0:  * Log output can be enabled by defining M3G_LOGLEVEL in m3g_config.h.
sl@0:  * It must be set to a bitmask indicating which categories of log
sl@0:  * messages to output.  Fatal internal errors are always output when
sl@0:  * M3G_LOGLEVEL is defined; other kinds of messages can be included by
sl@0:  * setting it to any combination of the following in m3g_config.h:
sl@0:  *
sl@0:  *  M3G_LOG_FATAL_ERRORS    fatal internal errors (equals 0)
sl@0:  *  M3G_LOG_USER_ERRORS     user errors (the same as reported
sl@0:  *                          via m3gGetError)
sl@0:  *  M3G_LOG_WARNINGS        performance warnings
sl@0:  *  M3G_LOG_PROFILE         profiling counters
sl@0:  *  M3G_LOG_INTERFACE       interface construction/destruction events
sl@0:  *  M3G_LOG_OBJECTS         object construction/destruction events
sl@0:  *  M3G_LOG_STAGES          log processing stages (animate, render, etc.)
sl@0:  *  M3G_LOG_REFCOUNT        reference count operations
sl@0:  *  M3G_LOG_MEMORY_USAGE    memory usage counters
sl@0:  *  M3G_LOG_MEMORY_BLOCKS   memory block allocs/deallocs
sl@0:  *  M3G_LOG_MEMORY_ALL      output everything memory-related
sl@0:  *  M3G_LOG_RENDERING       log rendering details
sl@0:  *  M3G_LOG_IMAGES          log image memory usage details
sl@0:  *
sl@0:  * \note The amount of log output may be limited in non-debug builds.
sl@0:  */
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \def M3G_PROFILE_LOG_INTERVAL
sl@0:  * \brief Profile logging interval
sl@0:  * 
sl@0:  * Number of frames to wait between outputting (and resetting!) the
sl@0:  * profiling counters.  Zero (default) disables profile logging.
sl@0:  */
sl@0: #if !defined(M3G_PROFILE_LOG_INTERVAL)
sl@0: #   define M3G_PROFILE_LOG_INTERVAL     0
sl@0: #endif
sl@0:     
sl@0: /*----------------------------------------------------------------------
sl@0:  * Debug build setup
sl@0:  *--------------------------------------------------------------------*/
sl@0: 
sl@0: /* General settings enabled in debug builds */
sl@0: #if defined(M3G_DEBUG)
sl@0: #   define M3G_DEBUG_ASSERTS
sl@0: #   define M3G_DEBUG_RANGE_CHECKING
sl@0: #   define M3G_DEBUG_HEAP_TRACKING
sl@0: #endif
sl@0: 
sl@0: /*----------------------------------------------------------------------
sl@0:  * Compiler dependent definitions
sl@0:  *--------------------------------------------------------------------*/
sl@0: 
sl@0: /* Try to recognize the compiler */
sl@0: #if !defined(M3G_NO_COMPILER_DETECTION)
sl@0: #   if (defined (_MSC_VER) || defined(__VC32__))&& !defined(__MWERKS__) /* Microsoft Visual C++ */
sl@0: #       undef M3G_BUILD_MSVC
sl@0: #       define M3G_BUILD_MSVC
sl@0: #   elif defined(__ARMCC_VERSION)   /* ARM Developer Suite */
sl@0: #       undef M3G_BUILD_ADS
sl@0: #       define M3G_BUILD_ADS
sl@0: #   elif defined(__BORLANDC__)      /* Borland C++ */
sl@0: #       undef M3G_BUILD_BORLAND
sl@0: #       define M3G_BUILD_BORLAND
sl@0: #   elif defined(__MWERKS__) || defined(__CW32__) /* CodeWarrior */
sl@0: #       undef M3G_BUILD_CW
sl@0: #       define M3G_BUILD_CW
sl@0: #   elif defined(__GNUC__) || defined(__GCC32__) /* GNU C */
sl@0: #       undef M3G_BUILD_GCC
sl@0: #       define M3G_BUILD_GCC
sl@0: #   elif defined(__ARMCC__)         /* RVCT */
sl@0: #       undef M3G_BUILD_RVCT
sl@0: #       define M3G_BUILD_RVCT
sl@0: #   elif defined(S_SPLINT_S)        /* Splint */
sl@0: #       undef M3G_BUILD_SPLINT
sl@0: #       define M3G_BUILD_SPLINT
sl@0: #   else
sl@0: #       error Could not identify the compiler. Please refer to m3g_defs.h for more information.
sl@0: #   endif
sl@0: #endif
sl@0: 
sl@0: /* Try to recognize thumb/arm */
sl@0: #if defined(M3G_BUILD_ADS)
sl@0: #   if defined(__thumb)
sl@0: #       define M3G_BUILD_THUMB
sl@0: #   else
sl@0: #       define M3G_BUILD_ARM
sl@0: #   endif
sl@0: #endif
sl@0: 
sl@0: /* Set up compiler-dependent definitions */
sl@0: 
sl@0: /*@-macroparams@*/
sl@0: /*@notfunction@*/
sl@0: /*!
sl@0:  * \internal \brief Macro used to denote Splint constraints */
sl@0: #define M3G_SPLINT(def)
sl@0: /*@+macroparams@*/
sl@0: 
sl@0: /*!
sl@0:  * \internal \def M3G_INLINE
sl@0:  * \brief Platform-independent inline function specifier
sl@0:  */
sl@0: 
sl@0: #if defined(M3G_BUILD_MSVC)
sl@0: #   define M3G_INLINE  __inline
sl@0: #   pragma warning (disable:4127) /* 4127: conditional expression is constant */
sl@0: #   pragma warning (disable:4514) /* 4514: unreferenced inline function has been removed */
sl@0: #   pragma warning (disable:4710) /* 4710: function not inlined */
sl@0: 
sl@0: #elif defined (M3G_BUILD_ADS)
sl@0: #   define M3G_INLINE __inline
sl@0: 
sl@0: #elif defined(M3G_BUILD_BORLAND)
sl@0: #   define M3G_INLINE  __inline
sl@0: 
sl@0: #elif defined(M3G_BUILD_CW)
sl@0: #   define M3G_INLINE
sl@0:     
sl@0: #elif defined(M3G_BUILD_GCC)
sl@0: #   define M3G_INLINE inline
sl@0: 
sl@0: #elif defined(M3G_BUILD_RVCT)
sl@0: #   define M3G_INLINE __inline
sl@0:     
sl@0: #elif defined(M3G_BUILD_SPLINT)
sl@0: #   define M3G_INLINE
sl@0: #   undef M3G_SPLINT
sl@0: /*@notfunction@*/
sl@0: #   define M3G_SPLINT(def) def
sl@0: 
sl@0: #   undef M3G_DEBUG
sl@0: /*#   define M3G_DEBUG*/
sl@0: 
sl@0: #else           /* generic fallback */
sl@0: #   define M3G_INLINE
sl@0: 
sl@0: #endif
sl@0: 
sl@0: /* Optionally cancel non-portable definitions. This is mainly to
sl@0:  * facilitate portability checking with GCC, which defines __STDC__
sl@0:  * even in non-ANSI mode) */
sl@0: 
sl@0: #if defined(M3G_STRICT_STDC)
sl@0: #   undef M3G_INLINE
sl@0: #   define M3G_INLINE
sl@0: #endif
sl@0: 
sl@0: /*----------------------------------------------------------------------
sl@0:  * Identify GL version
sl@0:  *--------------------------------------------------------------------*/
sl@0: #if defined(GL_VERSION_ES_CM_1_1) || defined(GL_OES_VERSION_1_1)
sl@0: #   define M3G_GL_ES_1_1
sl@0: #endif
sl@0: 
sl@0: /*----------------------------------------------------------------------
sl@0:  * Internal configuration and performance tuning parameters
sl@0:  *--------------------------------------------------------------------*/
sl@0: 
sl@0: #define M3G_RENDERQUEUE_BUCKET_BITS 8
sl@0: #define M3G_ENABLE_VF_CULLING
sl@0: #define M3G_GL_FORCE_PBUFFER_SIZE
sl@0:     
sl@0: /*----------------------------------------------------------------------
sl@0:  * Standard C library
sl@0:  *--------------------------------------------------------------------*/
sl@0: 
sl@0: #if defined(M3G_NO_STDLIB)
sl@0: #   define NULL 0
sl@0: typedef M3Guint M3Gsize;
sl@0: #else
sl@0: #   include <stdlib.h>
sl@0: typedef size_t M3Gsize;
sl@0: #endif
sl@0: 
sl@0: /*----------------------------------------------------------------------
sl@0:  * Run time and compile time assertions
sl@0:  *--------------------------------------------------------------------*/
sl@0: 
sl@0: /*!
sl@0:  * \internal \def M3G_ASSERT(a)
sl@0:  * \brief Run-time assertion
sl@0:  */
sl@0: #if defined(M3G_DEBUG_ASSERTS)
sl@0: 
sl@0: extern void m3gAssertFailed(const char *filename, int line);
sl@0: #define M3G_ASSERT(cond)                                        \
sl@0:     do {                                                        \
sl@0:         if (!(cond)) m3gAssertFailed(__FILE__, __LINE__);       \
sl@0:     } while (M3G_FALSE)
sl@0: 
sl@0: M3G_SPLINT(extern /*@noreturnwhenfalse@*/ void M3G_ASSERT(/*@sef@*//*@null@*/ M3Gbool /*@alt const void*@*/ cond)/*@*/;)
sl@0: 
sl@0: #else
sl@0: 
sl@0: /*@-macroparams@*/
sl@0: #   define M3G_ASSERT(cond)
sl@0: /*@+macroparams@*/
sl@0: M3G_SPLINT(extern /*@noreturnwhenfalse@*/ void M3G_ASSERT(/*@sef@*//*@null@*//*@unused@*/ M3Gbool /*@alt const void*@*/ cond)/*@*/;)
sl@0:     
sl@0: #endif /* M3G_DEBUG */
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Compile-time assertion
sl@0:  */
sl@0: /*@notfunction@*/
sl@0: #define M3G_CT_ASSERT(a)    struct __M3G_UNIQUE_NAME { unsigned bf : (a) ? 1 : -1; }
sl@0: /*@notfunction@*/
sl@0: #define __M3G_UNIQUE_NAME           __M3G_MAKE_UNIQUE_NAME(__LINE__, 0)
sl@0: /*@notfunction@*/
sl@0: #define __M3G_MAKE_UNIQUE_NAME(line, num)   __M3G_MAKE_UNIQUE_NAME2(line, num)
sl@0: /*@notfunction@*/
sl@0: #define __M3G_MAKE_UNIQUE_NAME2(line, num)  m3gCTassert ## num ## line
sl@0: 
sl@0: /*@notfunction@*/
sl@0: #define M3G_CT_ASSERT1(a)   struct __M3G_UNIQUE_NAME1 { unsigned bf : (a) ? 1 : -1; }
sl@0: /*@notfunction@*/
sl@0: #define __M3G_UNIQUE_NAME1  M3G_MAKE_UNIQUE_NAME(__LINE__, 1)
sl@0: 
sl@0: /*@notfunction@*/
sl@0: #define M3G_CT_ASSERT2(a)   struct __M3G_UNIQUE_NAME2 { unsigned bf : (a) ? 1 : -1; }
sl@0: /*@notfunction@*/
sl@0: #define __M3G_UNIQUE_NAME2  __M3G_MAKE_UNIQUE_NAME(__LINE__, 2)
sl@0: 
sl@0: #if defined(M3G_DEBUG_RANGE_CHECKING)
sl@0: #define M3G_ASSERT_RANGE(val, min, max) M3G_ASSERT(m3gInRange((val), (min), (max)))
sl@0: #else
sl@0: /*@-macroparams@*/
sl@0: #define M3G_ASSERT_RANGE(val, min, max)
sl@0: /*@+macroparams@*/
sl@0: #endif
sl@0: 
sl@0: /*----------------------------------------------------------------------
sl@0:  * Verify any global definitions, expected type sizes etc.
sl@0:  *--------------------------------------------------------------------*/
sl@0: 
sl@0: #if !defined(M3G_INLINE)
sl@0: #   error M3G_INLINE not defined in platform definitions!
sl@0: #endif
sl@0: 
sl@0: #if !defined(M3G_ALIGNMENT)
sl@0: #   error M3G_ALIGNMENT not defined in platform definitions!
sl@0: #endif
sl@0: 
sl@0: #if ((M3G_ALIGNMENT & (M3G_ALIGNMENT-1)) != 0)
sl@0: #   error M3G_ALIGNMENT is not a power of two!
sl@0: #endif
sl@0: 
sl@0: #if defined(M3G_TARGET_ISA) && !defined(M3G_USE_NGL_API)
sl@0: #   error ISA targets currently supported with M3G_USE_NGL_API only!
sl@0: #endif
sl@0: 
sl@0: #if (defined(M3G_NGL_CONTEXT_API) && !defined(M3G_NGL_TEXTURE_API)) \
sl@0:         || (defined(M3G_NGL_TEXTURE_API) && !defined(M3G_NGL_CONTEXT_API))
sl@0: #   if !defined(M3G_DEBUG)
sl@0: #       error Nonstandard NGL configurations only allowed in debug builds!
sl@0: #   endif
sl@0: #endif
sl@0: 
sl@0: /* Verify our expected type sizes */
sl@0: M3G_CT_ASSERT(sizeof(M3Gbyte)   == 1);
sl@0: M3G_CT_ASSERT(sizeof(M3Gubyte)  == 1);
sl@0: M3G_CT_ASSERT(sizeof(M3Gshort)  == 2);
sl@0: M3G_CT_ASSERT(sizeof(M3Gushort) == 2);
sl@0: M3G_CT_ASSERT(sizeof(M3Gint)    == 4);
sl@0: M3G_CT_ASSERT(sizeof(M3Guint)   == 4);
sl@0: M3G_CT_ASSERT(sizeof(M3Gfloat)   == 4);
sl@0: 
sl@0: /* Unsigned is used extensively as a wrapper for object pointers, so
sl@0:  * check that we can fit a pointer in there */
sl@0: M3G_CT_ASSERT(sizeof(M3Guint) >= sizeof(void*));
sl@0: 
sl@0: /*
sl@0:  * Globally disable some redundant Lint messages
sl@0:  */
sl@0: 
sl@0: /*lint -e701 Signed shifts left should never be a problem */
sl@0: /*lint -e702 Signed shifts right are run-time verified (m3g_interface.c) */
sl@0: 
sl@0: /*----------------------------------------------------------------------
sl@0:  * Event logging
sl@0:  *--------------------------------------------------------------------*/
sl@0: 
sl@0: #if !defined(M3G_LOGLEVEL)    
sl@0: #   define M3G_LOG(level, msg)              ((void)(level), (void)(msg))
sl@0: #   define M3G_LOG1(level, msg, a)          ((void)(level), (void)(msg), (void)(a))
sl@0: #   define M3G_LOG2(level, msg, a, b)       ((void)(level), (void)(msg), (void)(a), (void)(b))
sl@0: #   define M3G_LOG3(level, msg, a, b, c)    ((void)(level), (void)(msg), (void)(a), (void)(b), (void)(c))
sl@0: #   define M3G_LOG4(level, msg, a, b, c, d) ((void)(level), (void)(msg), (void)(a), (void)(b), (void)(c), (void)(d))
sl@0: #   define M3G_LOG5(level, msg, a, b, c, d, e) ((void)(level), (void)(msg), (void)(a), (void)(b), (void)(c), (void)(d), (void)(e))
sl@0: #else
sl@0:     void m3gBeginLog(void);
sl@0:     void m3gLogMessage(const char *format, ...);
sl@0:     void m3gEndLog(void);
sl@0: #   define M3G_LOG(level, msg) \
sl@0:     do { if ((level) & (M3G_LOGLEVEL)) m3gLogMessage((msg)); } while (M3G_FALSE)
sl@0: #   define M3G_LOG1(level, msg, a) \
sl@0:     do { if ((level) & (M3G_LOGLEVEL)) m3gLogMessage((msg), (a)); } while (M3G_FALSE)
sl@0: #   define M3G_LOG2(level, msg, a, b) \
sl@0:     do { if ((level) & (M3G_LOGLEVEL)) m3gLogMessage((msg), (a), (b)); } while (M3G_FALSE)
sl@0: #   define M3G_LOG3(level, msg, a, b, c) \
sl@0:     do { if ((level) & (M3G_LOGLEVEL)) m3gLogMessage((msg), (a), (b), (c)); } while (M3G_FALSE)
sl@0: #   define M3G_LOG4(level, msg, a, b, c, d) \
sl@0:     do { if ((level) & (M3G_LOGLEVEL)) m3gLogMessage((msg), (a), (b), (c), (d)); } while (M3G_FALSE)
sl@0: #   define M3G_LOG5(level, msg, a, b, c, d, e) \
sl@0:     do { if ((level) & (M3G_LOGLEVEL)) m3gLogMessage((msg), (a), (b), (c), (d), (e)); } while (M3G_FALSE)
sl@0: #endif
sl@0:     
sl@0: /*----------------------------------------------------------------------
sl@0:  * Useful stuff
sl@0:  *--------------------------------------------------------------------*/
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Range checking inline function
sl@0:  *
sl@0:  * \param a     Value to check
sl@0:  * \param min   Lower bound, inclusive
sl@0:  * \param max   Upper bound, inclusive
sl@0:  */
sl@0: static M3G_INLINE M3Gbool m3gInRange(M3Gint a, M3Gint min, M3Gint max)
sl@0: {
sl@0:     return ((M3Guint)(a - min) <= (M3Guint)(max - min));
sl@0: }
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Range checking for floats
sl@0:  */
sl@0: static M3G_INLINE M3Gbool m3gInRangef(M3Gfloat a, M3Gfloat min, M3Gfloat max)
sl@0: {
sl@0:     return (a >= min && a <= max);
sl@0: }
sl@0:     
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Clamping function for floats
sl@0:  *
sl@0:  * \param a     Value to clamp
sl@0:  * \param min   Minimum value
sl@0:  * \param max   Maximum value
sl@0:  */
sl@0: static M3G_INLINE M3Gfloat m3gClampFloat(M3Gfloat a, M3Gfloat min, M3Gfloat max)
sl@0: {
sl@0:     return (a <= min) ? min : (a >= max) ? max : a;
sl@0: }
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Clamping function for floats
sl@0:  *
sl@0:  * \param a     Value to clamp
sl@0:  */
sl@0: static M3G_INLINE M3Gfloat m3gClampFloatPositive(M3Gfloat a)
sl@0: {
sl@0:     return (a <= 0) ? 0 : a;
sl@0: }
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  */
sl@0: static M3G_INLINE M3Gint m3gClampInt(M3Gint a, M3Gint min, M3Gint max)
sl@0: {
sl@0:     return (a <= min) ? min : (a >= max) ? max : a;
sl@0: }
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  *
sl@0:  */
sl@0: static M3G_INLINE M3Gbool m3gIsPowerOfTwo(M3Guint a)
sl@0: {
sl@0:     return ((a & (a-1)) == 0u);
sl@0: }
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Returns the smallest power of two greater than or equal to a
sl@0:  * given integer
sl@0:  *
sl@0:  * \note Only works with positive numbers of 2^30 or less
sl@0:  */
sl@0: static M3G_INLINE M3Gint m3gNextPowerOfTwo(M3Gint x)
sl@0: {
sl@0:     M3Gint y = 1;
sl@0:     M3G_ASSERT(m3gInRange(x, 0, 1 << 30));
sl@0:     while (y < x) {
sl@0:         y <<= 1;
sl@0:     }
sl@0:     return y;
sl@0: }
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Indicate (intentionally) unreferenced parameters
sl@0:  *
sl@0:  * This is used on virtual functions, where not every implementation
sl@0:  * uses all the arguments.
sl@0:  */
sl@0: /*@notfunction@*/
sl@0: #define M3G_UNREF(a)    ((void)(a)) /*@*/
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Clamp a value to signed 8-bit range
sl@0:  */
sl@0: #define M3G_CLAMP_BYTE(a) ((M3Gbyte)  ((a) <   -128 ?   -128 : ((a) >   127 ?   127 : (a))))
sl@0: M3G_SPLINT(extern M3Gbyte M3G_CLAMP_BYTE(/*@sef@*/ int a);)
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Clamp a value to signed 16-bit range
sl@0:  */
sl@0: #define M3G_CLAMP_SHORT(a) ((M3Gshort) ((a) < -32768 ? -32768 : ((a) > 32767 ? 32767 : (a))))
sl@0: M3G_SPLINT(extern M3Gshort M3G_CLAMP_SHORT(/*@sef@*/ int a);)
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Clamp a value to unsigned 8-bit range
sl@0:  */
sl@0: #define M3G_CLAMP_UBYTE(a) ((M3Gubyte) ((a) < 0 ? 0 : ((a) >   255 ?   255 : (a))))
sl@0: M3G_SPLINT(extern M3Gubyte M3G_CLAMP_UBYTE(/*@sef@*/ int a);)
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Clamp a value to unsigned 16-bit range
sl@0:  */
sl@0: #define M3G_CLAMP_USHORT(a) ((M3Gushort)((a) < 0 ? 0 : ((a) > 65535 ? 65535 : (a))))
sl@0: M3G_SPLINT(extern M3Gushort M3G_CLAMP_USHORT(/*@sef@*/ int a);)
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Offset any pointer by a given number of bytes
sl@0:  */
sl@0: #define M3G_OFFSET_PTR(ptr, bytes) (void*)(((M3Gbyte*)(ptr)) + bytes)
sl@0: 
sl@0: /* Min & max macros and inline functions
sl@0:  *
sl@0:  * The inline function may be better optimized when one or both of the
sl@0:  * arguments are expressions */
sl@0:     
sl@0: #define M3G_MIN(a, b) ((a) <= (b) ? (a) : (b))
sl@0: #define M3G_MAX(a, b) ((a) >= (b) ? (a) : (b))
sl@0: 
sl@0: static M3G_INLINE M3Gint m3gMaxInt(M3Gint a, M3Gint b)
sl@0: {
sl@0:     return M3G_MAX(a, b);
sl@0: }
sl@0: 
sl@0: static M3G_INLINE M3Gint m3gMinInt(M3Gint a, M3Gint b)
sl@0: {
sl@0:     return M3G_MIN(a, b);
sl@0: }
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief RGB mask
sl@0:  */
sl@0: #define M3G_RGB_MASK    0x00FFFFFFu
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Alpha mask
sl@0:  */
sl@0: #define M3G_ALPHA_MASK  0xFF000000u
sl@0: 
sl@0: /*----------------------------------------------------------------------
sl@0:  * Data alignment macros
sl@0:  *--------------------------------------------------------------------*/
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Align a pointer or size value to an N-byte boundary
sl@0:  *
sl@0:  * @param value Value to align.
sl@0:  * @param size  Alignment size; must be a power of two
sl@0:  */
sl@0: #define M3G_ALIGN_TO(value, size) ((((unsigned) (value)) + ((size) - 1)) & ~((size) - 1))
sl@0: M3G_SPLINT(extern int M3G_ALIGN_TO(int /*@alt size_t@*/ value, /*@sef@*/ int size);)
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Returns a truth value for whether a pointer is aligned or not
sl@0:  */
sl@0: #define M3G_IS_ALIGNED(ptr) ((((unsigned)(ptr)) & (M3G_ALIGNMENT-1)) == 0)
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Assert proper alignment of a pointer
sl@0:  *
sl@0:  * Currently, we assume alignment to 4-byte boundaries.
sl@0:  */
sl@0: #define M3G_ASSERT_ALIGNMENT(ptr) M3G_ASSERT(M3G_IS_ALIGNED(ptr))
sl@0: 
sl@0: /*!
sl@0:  * \internal
sl@0:  * \brief Asserts that a pointer is both non-null and aligned
sl@0:  */
sl@0: #define M3G_ASSERT_PTR(ptr) M3G_ASSERT((ptr) != NULL && M3G_IS_ALIGNED(ptr))
sl@0: #define M3G_VALIDATE_PTR(ptr) M3G_ASSERT_PTR(ptr)
sl@0:     
sl@0: /*----------------------------------------------------------------------
sl@0:  * Easier names for math classes...
sl@0:  *--------------------------------------------------------------------*/
sl@0: 
sl@0: typedef M3GMatrix       Matrix;
sl@0: typedef M3GQuat         Quat;
sl@0: typedef M3GVec3         Vec3;
sl@0: typedef M3GVec4         Vec4;
sl@0: typedef M3GRectangle    Rect;
sl@0: 
sl@0: /* We rely on the layout of a Vec4 or a Quat matching an array of 4
sl@0:  * floats in a number of places, so check that */
sl@0: 
sl@0: M3G_CT_ASSERT(sizeof(M3GVec4) == 4 * sizeof(M3Gfloat));
sl@0: M3G_CT_ASSERT(sizeof(M3GQuat) == 4 * sizeof(M3Gfloat));
sl@0: 
sl@0: #if defined(__cplusplus)
sl@0: } /* extern "C" */
sl@0: #endif
sl@0: 
sl@0: #endif /*__M3G_DEFS_H__*/