/* -*- mode: C; tab-width:8; c-basic-offset:2 -*- */

/*
 * Mesa 3-D graphics library
 * Version:  3.3
 *
 * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 *
 * Original Mesa / 3Dfx device driver (C) 1999 David Bucciarelli, by the
 * terms stated above.
 *
 * Thank you for your contribution, David!
 *
 * Please make note of the above copyright/license statement.  If you
 * contributed code or bug fixes to this code under the previous (GNU
 * Library) license and object to the new license, your code will be
 * removed at your request.  Please see the Mesa docs/COPYRIGHT file
 * for more information.
 *
 * Additional Mesa/3Dfx driver developers:
 *   Daryll Strauss <daryll@precisioninsight.com>
 *   Keith Whitwell <keith@precisioninsight.com>
 *
 * See fxapi.h for more revision/author details.
 */


#ifndef __FX_GLIDE_WARPER__
#define __FX_GLIDE_WARPER__

#include <glide.h>

/* 
 * General context: 
 */
#if !defined(FX_GLIDE3)
     typedef FxU32 	 FX_GrContext_t;	/* Not used in Glide2 */
#else
     typedef GrContext_t FX_GrContext_t;
#endif

/* 
 * Glide3 emulation on Glide2: 
 */
#if !defined(FX_GLIDE3)
	/* Constanst for FX_grGetInteger( ) */
	#define FX_FOG_TABLE_ENTRIES            0x0004    /* The number of entries in the hardware fog table. */
	#define FX_GLIDE_STATE_SIZE             0x0006	  /* Size of buffer, in bytes, needed to save Glide state. */
	#define FX_LFB_PIXEL_PIPE               0x0009	  /* 1 if LFB writes can go through the 3D pixel pipe. */		
	#define FX_PENDING_BUFFERSWAPS          0x0014    /* The number of buffer swaps pending. */
	#define FX_TEXTURE_ALIGN		0x0024    /* The required alignment for textures */
#else
	#define FX_FOG_TABLE_ENTRIES            GR_FOG_TABLE_ENTRIES
	#define FX_GLIDE_STATE_SIZE             GR_GLIDE_STATE_SIZE
	#define FX_LFB_PIXEL_PIPE               GR_LFB_PIXEL_PIPE
	#define FX_PENDING_BUFFERSWAPS          GR_PENDING_BUFFERSWAPS
	#define FX_TEXTURE_ALIGN		GR_TEXTURE_ALIGN
#endif

/*
 * Genral warper functions for Glide2/Glide3:
 */ 
extern FxI32 FX_grGetInteger(FxU32 pname);
extern FxI32 FX_grGetInteger_NoLock(FxU32 pname);

/*
 * Glide2 emulation on Glide3:
 */
#if defined(FX_GLIDE3)

#define GR_ASPECT_1x1 GR_ASPECT_LOG2_1x1
#define GR_ASPECT_2x1 GR_ASPECT_LOG2_2x1
#define GR_ASPECT_4x1 GR_ASPECT_LOG2_4x1
#define GR_ASPECT_8x1 GR_ASPECT_LOG2_8x1
#define GR_ASPECT_1x2 GR_ASPECT_LOG2_1x2
#define GR_ASPECT_1x4 GR_ASPECT_LOG2_1x4
#define GR_ASPECT_1x8 GR_ASPECT_LOG2_1x8

#define GR_LOD_256	GR_LOD_LOG2_256
#define GR_LOD_128	GR_LOD_LOG2_128
#define GR_LOD_64	GR_LOD_LOG2_64
#define GR_LOD_32	GR_LOD_LOG2_32	
#define GR_LOD_16	GR_LOD_LOG2_16
#define GR_LOD_8	GR_LOD_LOG2_8
#define GR_LOD_4	GR_LOD_LOG2_4
#define GR_LOD_2	GR_LOD_LOG2_2
#define GR_LOD_1	GR_LOD_LOG2_1

#define GR_FOG_WITH_TABLE GR_FOG_WITH_TABLE_ON_Q

typedef int GrSstType;

#define MAX_NUM_SST            4

#define GR_SSTTYPE_VOODOO    0
#define GR_SSTTYPE_SST96     1
#define GR_SSTTYPE_AT3D      2
#define GR_SSTTYPE_Voodoo2   3

typedef struct GrTMUConfig_St {
  int    tmuRev;                /* Rev of Texelfx chip */
  int    tmuRam;                /* 1, 2, or 4 MB */
} GrTMUConfig_t;

typedef struct GrVoodooConfig_St {
  int    fbRam;                         /* 1, 2, or 4 MB */
  int    fbiRev;                        /* Rev of Pixelfx chip */
  int    nTexelfx;                      /* How many texelFX chips are there? */
  FxBool sliDetect;                     /* Is it a scan-line interleaved board? */
  GrTMUConfig_t tmuConfig[GLIDE_NUM_TMU];   /* Configuration of the Texelfx chips */
} GrVoodooConfig_t;

typedef struct GrSst96Config_St {
  int   fbRam;                  /* How much? */
  int   nTexelfx;
  GrTMUConfig_t tmuConfig;
} GrSst96Config_t;

typedef GrVoodooConfig_t GrVoodoo2Config_t;

typedef struct GrAT3DConfig_St {
  int   rev;
} GrAT3DConfig_t;

typedef struct {
  int num_sst;                  /* # of HW units in the system */
  struct {
    GrSstType type;             /* Which hardware is it? */
    union SstBoard_u {
      GrVoodooConfig_t  VoodooConfig;
      GrSst96Config_t   SST96Config;
      GrAT3DConfig_t    AT3DConfig;
      GrVoodoo2Config_t Voodoo2Config;
    } sstBoard;
  } SSTs[MAX_NUM_SST];          /* configuration for each board */
} GrHwConfiguration;

typedef FxU32 GrHint_t;
#define GR_HINTTYPE_MIN                 0
#define GR_HINT_STWHINT                 0

typedef FxU32 GrSTWHint_t;
#define GR_STWHINT_W_DIFF_FBI   FXBIT(0)
#define GR_STWHINT_W_DIFF_TMU0  FXBIT(1)
#define GR_STWHINT_ST_DIFF_TMU0 FXBIT(2)
#define GR_STWHINT_W_DIFF_TMU1  FXBIT(3)
#define GR_STWHINT_ST_DIFF_TMU1 FXBIT(4)
#define GR_STWHINT_W_DIFF_TMU2  FXBIT(5)
#define GR_STWHINT_ST_DIFF_TMU2 FXBIT(6)

#define GR_CONTROL_ACTIVATE 		1
#define GR_CONTROL_DEACTIVATE		0

#define GrState				void

/*
** move the vertex layout defintion to application
*/
typedef struct {
  float  sow;                   /* s texture ordinate (s over w) */
  float  tow;                   /* t texture ordinate (t over w) */  
  float  oow;                   /* 1/w (used mipmapping - really 0xfff/w) */
}  GrTmuVertex;


#if FX_USE_PARGB

typedef struct
{
  float x, y;         /* X and Y in screen space */
  float ooz;          /* 65535/Z (used for Z-buffering) */
  float oow;          /* 1/W (used for W-buffering, texturing) */
  FxU32 argb;         /* R, G, B, A [0..255.0] */
  GrTmuVertex         tmuvtx[GLIDE_NUM_TMU];
  float z;            /* Z is ignored */
} GrVertex;

#define GR_VERTEX_X_OFFSET              0
#define GR_VERTEX_Y_OFFSET              1
#define GR_VERTEX_OOZ_OFFSET            2
#define GR_VERTEX_OOW_OFFSET            3
#define GR_VERTEX_PARGB_OFFSET          4
#define GR_VERTEX_SOW_TMU0_OFFSET       5
#define GR_VERTEX_TOW_TMU0_OFFSET       6
#define GR_VERTEX_OOW_TMU0_OFFSET       7
#define GR_VERTEX_SOW_TMU1_OFFSET       8
#define GR_VERTEX_TOW_TMU1_OFFSET       9
#define GR_VERTEX_OOW_TMU1_OFFSET       10
#define GR_VERTEX_Z_OFFSET		11

#define GET_PARGB(v)	((FxU32*)(v))[GR_VERTEX_PARGB_OFFSET]
/* GET_PA: returns the alpha component */
#if GLIDE_ENDIAN == GLIDE_ENDIAN_BIG
   #define GET_PA(v)		((FxU8*)(v))[GR_VERTEX_PARGB_OFFSET*4]
#else 
   #define GET_PA(v)		((FxU8*)(v))[GR_VERTEX_PARGB_OFFSET*4+3]
#endif 
#define MESACOLOR2PARGB(c)	(c[ACOMP] << 24 | c[GCOMP] << 16 | c[GCOMP] << 8 | c[BCOMP])
#define PACK_4F_ARGB(dest,a,r,g,b) { 								\
    					     const GLuint cr = (int)r;				\
    					     const GLuint cg = (int)g;				\
    					     const GLuint ca = (int)a;				\
    					     const GLuint cb = (int)b;				\
    					     dest = ca << 24 | cr << 16 | cg << 8 | cb;		\
    				        }

#else /* FX_USE_PARGB */

typedef struct
{
  float x, y, z;                /* X, Y, and Z of scrn space -- Z is ignored */
  float r, g, b;                /* R, G, B, ([0..255.0]) */
  float ooz;                    /* 65535/Z (used for Z-buffering) */
  float a;                      /* Alpha [0..255.0] */
  float oow;                    /* 1/W (used for W-buffering, texturing) */
  GrTmuVertex  tmuvtx[GLIDE_NUM_TMU];
} GrVertex;

#define GR_VERTEX_X_OFFSET              0
#define GR_VERTEX_Y_OFFSET              1
#define GR_VERTEX_Z_OFFSET              2
#define GR_VERTEX_R_OFFSET              3
#define GR_VERTEX_G_OFFSET              4
#define GR_VERTEX_B_OFFSET              5
#define GR_VERTEX_OOZ_OFFSET            6
#define GR_VERTEX_A_OFFSET              7
#define GR_VERTEX_OOW_OFFSET            8
#define GR_VERTEX_SOW_TMU0_OFFSET       9
#define GR_VERTEX_TOW_TMU0_OFFSET       10
#define GR_VERTEX_OOW_TMU0_OFFSET       11
#define GR_VERTEX_SOW_TMU1_OFFSET       12
#define GR_VERTEX_TOW_TMU1_OFFSET       13
#define GR_VERTEX_OOW_TMU1_OFFSET       14
#endif /* FX_USE_PARGB */

#endif


/*
 * Glide2 functions for Glide3
 */
#if defined(FX_GLIDE3)
#define FX_grTexDownloadTable(TMU,type,data)	\
  do { 						\
    BEGIN_BOARD_LOCK(); 			\
    grTexDownloadTable(type,data); 		\
    END_BOARD_LOCK(); 				\
  } while (0);
#define FX_grTexDownloadTable_NoLock(TMU,type,data) \
  grTexDownloadTable(type, data)
#else
#define FX_grTexDownloadTable(TMU,type,data) 	\
  do {						\
    BEGIN_BOARD_LOCK();				\
    grTexDownloadTable(TMU,type,data);		\
    END_BOARD_LOCK();				\
  } while (0);
#define FX_grTexDownloadTable_NoLock grTexDownloadTable
#endif

/*
 * Flush
 */
#if defined(FX_GLIDE3)
#define FX_grFlush()	\
  do {			\
    BEGIN_BOARD_LOCK(); \
    grFlush();		\
    END_BOARD_LOCK();	\
  } while (0)
#else
#define FX_grFlush()	\
  do {			\
    BEGIN_BOARD_LOCK(); \
    grSstIdle();	\
    END_BOARD_LOCK();	\
  } while (0)
#endif	

#define FX_grFinish()	\
  do {			\
    BEGIN_BOARD_LOCK(); \
    grFinish();		\
    END_BOARD_LOCK();	\
  } while (0)

/*
 * Write region: ToDo possible exploit the PixelPipe parameter.
 */
#if defined(FX_GLIDE3)
#define FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)		\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,FXFALSE,src_stride,src_data);	\
    END_BOARD_LOCK();		\
  } while(0)
#else
#define FX_grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data)		\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grLfbWriteRegion(dst_buffer,dst_x,dst_y,src_format,src_width,src_height,src_stride,src_data);		\
    END_BOARD_LOCK();		\
  } while (0)
#endif

/*
 * Read region
 */
#define FX_grLfbReadRegion(src_buffer,src_x,src_y,src_width,src_height,dst_stride,dst_data)			\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grLfbReadRegion(src_buffer,src_x,src_y,src_width,src_height,dst_stride,dst_data);				\
    END_BOARD_LOCK();		\
  } while (0);

/*
 * Draw triangle
 */
#define FX_grDrawTriangle(a,b,c)	\
  do {					\
    BEGIN_CLIP_LOOP();			\
    grDrawTriangle(a,b,c);		\
    END_CLIP_LOOP();			\
  } while (0)

/*
 * For Lod/LodLog2 conversion.
 */
#if defined(FX_GLIDE3)
	#define FX_largeLodLog2(info)		(info).largeLodLog2
#else
	#define FX_largeLodLog2(info)		(info).largeLod	
#endif

#if defined(FX_GLIDE3)
	#define FX_aspectRatioLog2(info)		(info).aspectRatioLog2
#else
	#define FX_aspectRatioLog2(info)		(info).aspectRatio
#endif

#if defined(FX_GLIDE3)
	#define FX_smallLodLog2(info)		(info).smallLodLog2
#else
	#define FX_smallLodLog2(info)		(info).smallLod
#endif

#if defined(FX_GLIDE3)
	#define FX_lodToValue(val)		((int)(GR_LOD_256-val))
#else
	#define FX_lodToValue(val)		((int)(val))
#endif

#if defined(FX_GLIDE3)
	#define FX_largeLodValue(info)		((int)(GR_LOD_256-(info).largeLodLog2))
#else
	#define FX_largeLodValue(info)		((int)(info).largeLod)
#endif
#define FX_largeLodValue_NoLock FX_largeLodValue

#if defined(FX_GLIDE3)
	#define FX_smallLodValue(info)		((int)(GR_LOD_256-(info).smallLodLog2))
#else
	#define FX_smallLodValue(info)		((int)(info).smallLod)
#endif
#define FX_smallLodValue_NoLock FX_smallLodValue

#if defined(FX_GLIDE3)
	#define FX_valueToLod(val)		((GrLOD_t)(GR_LOD_256-val))
#else
	#define FX_valueToLod(val)		((GrLOD_t)(val))
#endif

/*
 * ScreenWidth/Height stuff.
 */
	extern int FX_grSstScreenWidth(void);
	extern int FX_grSstScreenHeight(void);



/*
 * Version string.
 */
#if defined(FX_GLIDE3)
	extern void FX_grGlideGetVersion(char *buf);
#else
	#define FX_grGlideGetVersion(b)	\
	do {				\
	  BEGIN_BOARD_LOCK();		\
	  grGlideGetVersion(b);		\
	  END_BOARD_LOCK();		\
	} while (0)
#endif
/*
 * Performance statistics
 */
#if defined(FX_GLIDE3)
        extern void FX_grSstPerfStats(GrSstPerfStats_t *st);
#else
	#define FX_grSstPerfStats(s)	\
	do {				\
	  BEGIN_BOARD_LOCK();		\
	  grSstPerfStats(s);		\
	  END_BOARD_LOCK();		\
	} while (0)
#endif

/*
 * Hardware Query
 */
       extern int FX_grSstQueryHardware(GrHwConfiguration *config);

/*
 * GrHints
 */
#if defined(FX_GLIDE3)
        extern void FX_grHints_NoLock(GrHint_t hintType, FxU32 hintMask);
	extern void FX_grHints(GrHint_t hintType, FxU32 hintMask);
#else
	#define FX_grHints(t,m)		\
	do {				\
	  BEGIN_BOARD_LOCK();		\
	  grHints(t, m);		\
	  END_BOARD_LOCK();		\
	} while(0)
        #define FX_grHints_NoLock grHints
#endif
/*
 * Antialiashed line+point drawing.
 */
#if defined(FX_GLIDE3)
	extern void FX_grAADrawLine(GrVertex *a,GrVertex *b);
#else
	#define FX_grAADrawLine(a,b)	\
	do {				\
	  BEGIN_CLIP_LOOP();		\
	  grAADrawLine(a,b);		\
	  END_CLIP_LOOP();		\
	} while (0)
#endif

#if defined(FX_GLIDE3)
	extern void FX_grAADrawPoint(GrVertex *a);
#else
	#define FX_grAADrawPoint(a)	\
	do {				\
	  BEGIN_CLIP_LOOP();		\
	  grAADrawPoint(a);		\
	  END_CLIP_LOOP();		\
	} while (0)
#endif

/*
 * Needed for Glide3 only, to set up Glide2 compatible vertex layout.
 */
#if defined(FX_GLIDE3)
	extern void FX_setupGrVertexLayout(void);
#else
	#define FX_setupGrVertexLayout()		do {} while (0)
#endif
/*
 * grSstControl stuff
 */
extern FxBool FX_grSstControl(FxU32 code);

/*
 * grGammaCorrectionValue
 */
#if defined(FX_GLIDE3)
      extern void FX_grGammaCorrectionValue(float val);
#else
      #define FX_grGammaCorrectionValue(v)	\
      do {					\
        BEGIN_BOARD_LOCK();			\
	grGammaCorrectionValue(v)		\
        END_BOARD_LOCK();			\
      } while (0)
#endif

#if defined(FX_GLIDE3)
#define FX_grSstWinClose(w)	\
  do { 				\
    BEGIN_BOARD_LOCK();		\
    grSstWinClose(w);		\
    END_BOARD_LOCK();		\
  } while (0)
#else
#define FX_grSstWinClose(w)	\
  do { 				\
    BEGIN_BOARD_LOCK();		\
    grSstWinClose();		\
    END_BOARD_LOCK();		\
  } while (0)
#endif


extern FX_GrContext_t FX_grSstWinOpen( FxU32                hWnd,
                                       GrScreenResolution_t screen_resolution,
                                       GrScreenRefresh_t    refresh_rate,
                                       GrColorFormat_t      color_format,
                                       GrOriginLocation_t   origin_location,
                                       int                  nColBuffers,
                                       int                  nAuxBuffers);


#define FX_grDrawLine(v1, v2)	\
  do {				\
    BEGIN_CLIP_LOOP();		\
    grDrawLine(v1, v2);		\
    END_CLIP_LOOP();		\
  } while (0)

#define FX_grDrawPoint(p)	\
  do {				\
    BEGIN_CLIP_LOOP();		\
    grDrawPoint(p);		\
    END_CLIP_LOOP();		\
  } while (0)

#if defined(FX_GLIDE3)
extern void FX_grDrawPolygonVertexList(int n, GrVertex *v);
#else
#define FX_grDrawPolygonVertexList(n, v)	\
  do {						\
    BEGIN_CLIP_LOOP();				\
    grDrawPolygonVertexList(n, v);		\
    END_CLIP_LOOP();				\
  } while (0)
#endif

#define FX_grDitherMode(m)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grDitherMode(m);		\
    END_BOARD_LOCK();		\
  } while (0)

#define FX_grRenderBuffer(b)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grRenderBuffer(b);		\
    END_BOARD_LOCK();		\
  } while (0)

#define FX_grBufferClear(c, a, d)	\
  do {					\
    BEGIN_CLIP_LOOP();			\
    grBufferClear(c, a, d);		\
    END_CLIP_LOOP();			\
  } while (0)

#define FX_grDepthMask(m)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grDepthMask(m);		\
    END_BOARD_LOCK();		\
  } while (0)

#define FX_grColorMask(c, a)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grColorMask(c, a);		\
    END_BOARD_LOCK();		\
  } while (0)

extern FxBool FX_grLfbLock(GrLock_t type, GrBuffer_t buffer, 
			   GrLfbWriteMode_t writeMode, 
			   GrOriginLocation_t origin, FxBool pixelPipeline, 
			   GrLfbInfo_t *info );

#define FX_grLfbUnlock(t, b)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grLfbUnlock(t, b);		\
    END_BOARD_LOCK();		\
  } while (0)

#define FX_grConstantColorValue(v)	\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grConstantColorValue(v);		\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grConstantColorValue_NoLock grConstantColorValue

#define FX_grAADrawTriangle(a, b, c, ab, bc, ca)	\
  do {							\
    BEGIN_CLIP_LOOP();					\
    grAADrawTriangle(a, b, c, ab, bc, ca);		\
    END_CLIP_LOOP();					\
  } while (0)

#define FX_grAlphaBlendFunction(rs, rd, as, ad)	\
  do {						\
    BEGIN_BOARD_LOCK();				\
    grAlphaBlendFunction(rs, rd, as, ad);	\
    END_BOARD_LOCK();				\
  } while (0)

#define FX_grAlphaCombine(func, fact, loc, oth, inv)	\
  do {							\
    BEGIN_BOARD_LOCK();					\
    grAlphaCombine(func, fact, loc, oth, inv);		\
    END_BOARD_LOCK();					\
  } while (0)

#define FX_grAlphaCombine_NoLock grAlphaCombine

#define FX_grAlphaTestFunction(f)	\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grAlphaTestFunction(f);		\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grAlphaTestReferenceValue(v)	\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grAlphaTestReferenceValue(v);	\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grClipWindow(minx, miny, maxx, maxy)	\
  do {						\
    BEGIN_BOARD_LOCK();				\
    grClipWindow(minx, miny, maxx, maxy);	\
    END_BOARD_LOCK();				\
  } while (0)

#define FX_grClipWindow_NoLock grClipWindow

#define FX_grColorCombine(func, fact, loc, oth, inv)	\
  do {							\
    BEGIN_BOARD_LOCK();					\
    grColorCombine(func, fact, loc, oth, inv);		\
    END_BOARD_LOCK();					\
  } while (0)

#define FX_grColorCombine_NoLock grColorCombine

#define FX_grCullMode(m)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grCullMode(m);		\
    END_BOARD_LOCK();		\
  } while (0)

#define FX_grDepthBiasLevel(lev)	\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grDepthBiasLevel(lev);		\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grDepthBufferFunction(func)	\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grDepthBufferFunction(func);	\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grFogColorValue(c)		\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grFogColorValue(c);			\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grFogMode(m)	\
  do {			\
    BEGIN_BOARD_LOCK(); \
    grFogMode(m);	\
    END_BOARD_LOCK();	\
  } while (0)

#define FX_grFogTable(t)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grFogTable(t);		\
    END_BOARD_LOCK();		\
  } while (0)

#define FX_grTexClampMode(t, sc, tc)	\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grTexClampMode(t, sc, tc);		\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grTexClampMode_NoLock grTexClampMode

#define FX_grTexCombine(t, rfunc, rfact, afunc, afact, rinv, ainv)	\
  do {									\
    BEGIN_BOARD_LOCK();							\
    grTexCombine(t, rfunc, rfact, afunc, afact, rinv, ainv);		\
    END_BOARD_LOCK();							\
  } while (0)

#define FX_grTexCombine_NoLock grTexCombine

#define FX_grTexDownloadMipMapLevel(t, sa, tlod, llod, ar, f, eo, d)	\
  do {									\
    BEGIN_BOARD_LOCK();							\
    grTexDownloadMipMapLevel(t, sa, tlod, llod, ar, f, eo, d);		\
    END_BOARD_LOCK();							\
  } while (0)

#define FX_grTexDownloadMipMapLevel_NoLock grTexDownloadMipMapLevel

#define FX_grTexDownloadMipMapLevelPartial(t, sa, tlod, llod, ar, f, eo, d, s, e);	\
  do {									    \
    BEGIN_BOARD_LOCK();							    \
    grTexDownloadMipMapLevelPartial(t, sa, tlod, llod, ar, f, eo, d, s, e); \
    END_BOARD_LOCK();							    \
  } while (0)

#define FX_grTexFilterMode(t, minf, magf)	\
  do {						\
    BEGIN_BOARD_LOCK();				\
    grTexFilterMode(t, minf, magf);		\
    END_BOARD_LOCK();				\
  } while (0)

#define FX_grTexFilterMode_NoLock grTexFilterMode

extern FxU32 FX_grTexMinAddress(GrChipID_t tmu);
extern FxU32 FX_grTexMaxAddress(GrChipID_t tmu);

#define FX_grTexMipMapMode(t, m, lod)	\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grTexMipMapMode(t, m, lod);		\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grTexMipMapMode_NoLock grTexMipMapMode

#define FX_grTexSource(t, sa, eo, i)	\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grTexSource(t, sa, eo, i);		\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grTexSource_NoLock grTexSource

extern FxU32 FX_grTexTextureMemRequired(FxU32 evenOdd, GrTexInfo *info);
#define FX_grTexTextureMemRequired_NoLock grTexTextureMemRequired

#define FX_grGlideGetState(s)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grGlideGetState(s);		\
    END_BOARD_LOCK();		\
  } while (0)
#define FX_grGlideGetState_NoLock(s) grGlideGetState(s);

#define FX_grDRIBufferSwap(i)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grDRIBufferSwap(i);		\
    END_BOARD_LOCK();		\
  } while (0)

#define FX_grSstSelect(b)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grSstSelect(b);		\
    END_BOARD_LOCK();		\
  } while (0)

#define FX_grSstSelect_NoLock grSstSelect

#define FX_grGlideSetState(s)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grGlideSetState(s);		\
    END_BOARD_LOCK();		\
  } while (0)
#define FX_grGlideSetState_NoLock(s) grGlideSetState(s);

#define FX_grDepthBufferMode(m)	\
  do {				\
    BEGIN_BOARD_LOCK();		\
    grDepthBufferMode(m);	\
    END_BOARD_LOCK();		\
  } while (0)

#define FX_grLfbWriteColorFormat(f)	\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grLfbWriteColorFormat(f);		\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grDrawVertexArray(m, c, p)	\
  do {					\
    BEGIN_CLIP_LOOP();			\
    grDrawVertexArray(m, c, p);		\
    END_CLIP_LOOP();			\
  } while (0)

#define FX_grGlideShutdown()		\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grGlideShutdown();			\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grTexLodBiasValue_NoLock(t, v) grTexLodBiasValue(t, v)

#define FX_grTexLodBiasValue(t, v)	\
  do {					\
    BEGIN_BOARD_LOCK();			\
    grTexLodBiasValue(t, v);	\
    END_BOARD_LOCK();			\
  } while (0)

#define FX_grGlideInit_NoLock grGlideInit
#define FX_grSstWinOpen_NoLock grSstWinOpen

extern int FX_getFogTableSize(void);
extern int FX_getGrStateSize(void);

#endif /* __FX_GLIDE_WARPER__ */

