/*
 * $Id$
 *
 * $Date$
 * $Revision$
 *
 * (C) 1999 by Hyperion
 * All rights reserved
 *
 * This file is part of the MiniGL library project
 * See the file Licence.txt for more details
 *
 */


#include "sysinc.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static char rcsid[] UNUSED = "$Id$";

extern void SetBlendStageState(GLcontext context, uint32 stage);
extern void RebindTextures(GLcontext context);
extern void DisableBlendStage(GLcontext context, uint32 stage);
extern void EstablishCullState(GLcontext context);
extern void light_Recalculate(GLcontext context, GLuint light);
extern void tex_EstablishEnvCombine(GLcontext context);

extern uint32 client_texture_state[];

#define ED (flag == GL_TRUE?W3D_ENABLE:W3D_DISABLE)

void cgl_SetState(struct GLContextIFace *Self, GLenum cap, GLboolean flag)
{
	GLcontext context = GET_INSTANCE(Self);

	int i;

	switch(cap)
	{
		case GL_POLYGON_OFFSET_FILL:
			context->enable.PolygonOffsetFill = flag;
			break;
			
		case GL_STENCIL_TEST:
			IWarp3D->W3D_SetState(context->w3dContext, W3D_STENCILBUFFER, ED);
			context->enable.StencilTest = flag;
			break;
			
		case GL_ALPHA_TEST:
			context->enable.AlphaTest = flag;
			IWarp3D->W3D_SetState(context->w3dContext, W3D_ALPHATEST, ED);
			break;
			
		case GL_BLEND:
			context->enable.Blend = flag;
			IWarp3D->W3D_SetState(context->w3dContext, W3D_BLENDING, ED);
			break;
			
		case GL_TEXTURE_2D:
			context->enable.Texture2D[context->texture.ActiveTexture] = flag;
			if (flag == GL_TRUE)
			{			
				/* Check if the texture unit just enabled is the highest one */
				if (context->texture.ActiveTexture > context->texture.MaxTextureUnit)
					context->texture.MaxTextureUnit = context->texture.ActiveTexture;

				SetBlendStageState(context, context->texture.ActiveTexture);
				IWarp3D->W3D_SetState(context->w3dContext, W3D_TEXMAPPING, 
							W3D_ENABLE);
				RebindTextures(context);
			}
			else
			{
				/* Check if the texture unit we just disabled was the highers one */
				if (context->texture.ActiveTexture == context->texture.MaxTextureUnit)
					context->texture.MaxTextureUnit--;
				
				/* Disable the unit */
				DisableBlendStage(context, context->texture.ActiveTexture);
				
				/* Check if we still have one */
				if (context->texture.MaxTextureUnit == -1)
					IWarp3D->W3D_SetState(context->w3dContext, W3D_TEXMAPPING, 
							W3D_DISABLE);
			}
			break;
			
		case GL_TEXTURE_GEN_S:
			context->enable.TexGenS[context->texture.ActiveTexture] = flag;
			
			/* Determine if any TEXTURE_GEN state is set */
			context->enable.TexGen = GL_FALSE;
			for (i = 0; i <= context->texture.MaxTextureUnit; i++)
			{
				if (context->enable.TexGenS[i] || context->enable.TexGenT[i])
				{
					context->enable.TexGen = GL_TRUE;
					break;
				}
			}
		
			break;
			
		case GL_TEXTURE_GEN_T:
			context->enable.TexGenT[context->texture.ActiveTexture] = flag;

			/* Determine if any TEXTURE_GEN state is set */
			context->enable.TexGen = GL_FALSE;
			for (i = 0; i <= context->texture.MaxTextureUnit; i++)
			{
				if (context->enable.TexGenS[i] || context->enable.TexGenT[i])
				{
					context->enable.TexGen = GL_TRUE;
					break;
				}
			}
			
			break;
			
		case GL_FOG:
			context->FogDirty = GL_TRUE;
			context->enable.Fog = flag;
			IWarp3D->W3D_SetState(context->w3dContext, W3D_FOGGING, ED);
			break;
			
		case GL_SCISSOR_TEST:
			context->enable.ScissorTest = flag;
			if (flag == GL_TRUE)
				IWarp3D->W3D_SetScissor(context->w3dContext, &(context->w3dScissor));
			IWarp3D->W3D_SetState(context->w3dContext, W3D_SCISSOR, ED);
			break;
			
		case GL_CULL_FACE:
			context->enable.CullFace = flag;
			EstablishCullState(context);
			break;
			
		case GL_DEPTH_WRITEMASK:
			context->depth_buffer.DepthWriteMask = flag ;
			IWarp3D->W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, ED);

			break ;
			
		case GL_DEPTH_TEST:
			context->enable.DepthTest = flag;
			IWarp3D->W3D_SetState(context->w3dContext, W3D_ZBUFFER, ED);
			
			if (flag == GL_TRUE)
			{
				if (context->depth_buffer.DepthWriteMask)
					IWarp3D->W3D_SetState(context->w3dContext, 
						W3D_ZBUFFERUPDATE, W3D_ENABLE);
			}
			else
			{
				IWarp3D->W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, 
					W3D_DISABLE);
			}
			break;
			
		case GL_DITHER:
			context->enable.Dither = flag;
			IWarp3D->W3D_SetState(context->w3dContext, W3D_DITHERING, ED);
			break;
			
		case GL_POINT_SMOOTH:
			context->enable.PointSmooth = flag;
			IWarp3D->W3D_SetState(context->w3dContext, W3D_ANTI_POINT, ED);
			break;
			
		case GL_LINE_SMOOTH:
			IWarp3D->W3D_SetState(context->w3dContext, W3D_ANTI_LINE, ED);
			context->enable.LineSmooth = flag;
			break;
		
		case GL_POLYGON_SMOOTH:
			IWarp3D->W3D_SetState(context->w3dContext, W3D_ANTI_POLYGON, ED);
			context->enable.PolygonSmooth = flag;
			break;

		case GL_LINE_STIPPLE:
			IWarp3D->W3D_SetState(context->w3dContext, W3D_LINE_STIPPLE, ED);
			context->enable.LineStipple = flag;
			break;

		case GL_POLYGON_STIPPLE:
			IWarp3D->W3D_SetState(context->w3dContext, W3D_POLYGON_STIPPLE, ED);
			context->enable.PolygonStipple = flag;
			break;
			
		case MGL_PERSPECTIVE_MAPPING:
			IWarp3D->W3D_SetState(context->w3dContext, W3D_PERSPECTIVE, ED);
			break;
			
		case MGL_Z_OFFSET:
			context->enable.ZOffset = flag;
			break;
			
		case GL_CLIP_PLANE0:
		case GL_CLIP_PLANE1:
		case GL_CLIP_PLANE2:
		case GL_CLIP_PLANE3:
		case GL_CLIP_PLANE4:
		case GL_CLIP_PLANE5:
		{
			GLint plane = cap - GL_CLIP_PLANE0;
			GLFlagError(context, plane >= MAX_CLIPPLANES, GL_INVALID_ENUM);
			
			context->enable.ClipPlane[plane] = flag;
			
			/* Adjust the max clipplane setting */
			if (flag == GL_TRUE)
			{
				if (plane > context->transform.MaxClipPlane)
					context->transform.MaxClipPlane = plane;
			}
			else
			{
				if (plane == context->transform.MaxClipPlane)
				{
					int i;
					context->transform.MaxClipPlane = -1;
					
					for (i = 0; i < plane; i++)
						if (context->enable.ClipPlane[i])
							context->transform.MaxClipPlane = i;
				}
			}
		}
		break;
				
 
#ifdef MGL_USE_LIGHTING
		case GL_LIGHTING:
			context->enable.Lighting = flag;
			break;
		case GL_LIGHT0:
		case GL_LIGHT1:
		case GL_LIGHT2:
		case GL_LIGHT3:
		case GL_LIGHT4:
		case GL_LIGHT5:
		case GL_LIGHT6:
		case GL_LIGHT7:
		{
			GLint light = cap - GL_LIGHT0;
			
			GLFlagError(context, light >= MAX_LIGHTS, GL_INVALID_ENUM);
			
			context->enable.Light[light] = flag;
			
			/* Adjust MaxLight */
			if (flag == GL_TRUE)
			{
				if (light > context->lighting.MaxLight)
					context->lighting.MaxLight = light;
				light_Recalculate(context, light);
				
			}
			else
			{
				if (light == context->lighting.MaxLight)
				{
					int i;
					context->lighting.MaxLight = -1;
			
					/* Search for the highest active light */		
					for (i = 0; i < light; i++)
					{
						if (context->enable.Light[i])
							context->lighting.MaxLight = i;
					}
				}
			}
		}
		break;
		
	case GL_COLOR_MATERIAL:
		context->enable.ColorMaterial = flag;
		break;
#endif
		default:
			break;
	}
}
#undef ED

/* -- Implement glGetIntegerv -- */

#define GET_TYPE		GLint
#define GET_FUNCNAME()	cgl_GLGetIntegerv
#define FROM_BOOL(x)	(GLint)((x) ? 1 : 0)
#define FROM_COLOR(x)	(GLint)((0xffffffff * (x) - 1)/2)
#define FROM_FLOAT(x)	(GLint)(x)
#define FROM_INT(x)		(x)
#include "inc.get.c"
#undef GET_TYPE
#undef GET_FUNCNAME
#undef FROM_BOOL
#undef FROM_COLOR
#undef FROM_FLOAT
#undef FROM_INT

/* -- Implement glGetBooleanv -- */

#define GET_TYPE		GLboolean
#define GET_FUNCNAME()	cgl_GLGetBooleanv
#define FROM_BOOL(x)	(x)
#define FROM_COLOR(x)	(x == 0.0)
#define FROM_FLOAT(x)	(x == 0.0)
#define FROM_INT(x)		(x == 0)
#include "inc.get.c"
#undef GET_TYPE
#undef GET_FUNCNAME
#undef FROM_BOOL
#undef FROM_COLOR
#undef FROM_FLOAT
#undef FROM_INT

/* -- Implement glGetFloatv -- */

#define GET_TYPE		GLfloat
#define GET_FUNCNAME()	cgl_GLGetFloatv
#define FROM_BOOL(x)	(GLfloat)((x) ? 1.0f : 0.0f)
#define FROM_COLOR(x)	(GLfloat)(x)
#define FROM_FLOAT(x)	(x)
#define FROM_INT(x)		(GLfloat)(x)
#include "inc.get.c"
#undef GET_TYPE
#undef GET_FUNCNAME
#undef FROM_BOOL
#undef FROM_COLOR
#undef FROM_FLOAT
#undef FROM_INT

/* -- Implement glGetDoublev -- */

#define GET_TYPE		GLdouble
#define GET_FUNCNAME()	cgl_GLGetDoublev
#define FROM_BOOL(x)	(GLdouble)((x) ? 1.0 : 0.0)
#define FROM_COLOR(x)	(GLdouble)(x)
#define FROM_FLOAT(x)	(GLdouble)(x)
#define FROM_INT(x)		(GLdouble)(x)
#include "inc.get.c"
#undef GET_TYPE
#undef GET_FUNCNAME
#undef FROM_BOOL
#undef FROM_COLOR
#undef FROM_FLOAT
#undef FROM_INT

/* -- Implement glIsEnabled -- */
#define _IS_ENABLED_ONLY
#define GET_TYPE		GLboolean
#define GET_FUNCNAME()	cgl_GLIsEnabled
#define FROM_BOOL(x)	(x)
#define FROM_COLOR(x)	(x == 0.0)
#define FROM_FLOAT(x)	(x == 0.0)
#define FROM_INT(x)		(x == 0)
#include "inc.get.c"
#undef GET_TYPE
#undef GET_FUNCNAME
#undef FROM_BOOL
#undef FROM_COLOR
#undef FROM_FLOAT
#undef FROM_INT
#undef _IS_ENABLED_ONLY



void cgl_GLPushAttrib(struct GLContextIFace *Self, GLbitfield mask)
{
	GLcontext context = GET_INSTANCE(Self);
	GLuint stackp = context->AttribStackPointer;
	
	GLFlagError(context, context->AttribStackPointer >= ATTRIB_STACK_SIZE, 
			GL_STACK_OVERFLOW);
	
	context->AttribStackPointer ++;
	
	context->AttribStackBits[stackp] = mask;
	
	/* Push all required state.
	 * Note: Enable bits are always pushed, but only those affected by mask
	 * are actually restored on pop
	 */	
	if (mask & GL_COLOR_BUFFER_BIT)
		context->color_buffer_stack[stackp] = context->color_buffer;
	
	if (mask & GL_CURRENT_BIT)
		context->current_stack[stackp] = context->current;
		
	if (mask & GL_DEPTH_BUFFER_BIT)
		context->depth_buffer_stack[stackp] = context->depth_buffer;
		
	context->enable_stack[stackp] = context->enable;
	
	if (mask & GL_FOG_BIT)
		context->fog_stack[stackp] = context->fog;
	
	if (mask & GL_HINT_BIT)
		context->hint_stack[stackp] = context->hint;
		
	if (mask & GL_LIGHTING_BIT)
		context->lighting_stack[stackp] = context->lighting;
	
	if (mask & GL_LINE_BIT)
		context->line_stack[stackp] = context->line;
		
	if (mask & GL_POINT_BIT)
		context->point_stack[stackp] = context->point;
		
	if (mask & GL_POLYGON_BIT)
		context->polygon_stack[stackp] = context->polygon;
		
	if (mask & GL_POLYGON_STIPPLE_BIT)
		context->polygon_stipple_stack[stackp] = context->polygon_stipple;
		
	if (mask & GL_SCISSOR_BIT)
		context->scissor_stack[stackp] = context->scissor;
		
	if (mask & GL_STENCIL_BUFFER_BIT)
		context->stencil_buffer_stack[stackp] = context->stencil_buffer;

	if (mask & GL_TEXTURE_BIT)
		context->texture_stack[stackp] = context->texture;
		
	if (mask & GL_TRANSFORM_BIT)
		context->transform_stack[stackp] = context->transform;
	
	if (mask & GL_VIEWPORT_BIT)
		context->viewport_stack[stackp] = context->viewport;
}

void cgl_GLPopAttrib(struct GLContextIFace *Self)
{
	GLcontext context = GET_INSTANCE(Self);
	GLuint stackp;
	GLuint mask;
	
	GLFlagError(context, context->AttribStackPointer == 0, 
			GL_STACK_UNDERFLOW);
	
	stackp = --context->AttribStackPointer;
	
	mask = context->AttribStackBits[stackp];

	if (mask & GL_COLOR_BUFFER_BIT)
	{
		context->color_buffer = context->color_buffer_stack[stackp];
		
		IWarp3D->W3D_SetBlendMode(context->w3dContext, 
					context->color_buffer.BlendSrc,
					context->color_buffer.BlendDst);

		IWarp3D->W3D_SetColorMask(context->w3dContext,
					context->color_buffer.WriteMaskRed,
					context->color_buffer.WriteMaskGreen,
					context->color_buffer.WriteMaskBlue,
					context->color_buffer.WriteMaskAlpha);
	}
	
	if (mask & GL_CURRENT_BIT)
	{
		context->current = context->current_stack[stackp];
		
		/* No further hardware state restore required */
	}
	
	if (mask & GL_DEPTH_BUFFER_BIT)
	{
		uint32 wFunc = 0;
		
		context->depth_buffer = context->depth_buffer_stack[stackp];

		IWarp3D->W3D_SetState(context->w3dContext, W3D_ZBUFFERUPDATE, 
			context->depth_buffer.DepthWriteMask ? W3D_ENABLE : W3D_DISABLE);
			
		switch(context->depth_buffer.DepthFunc)
		{
				case GL_NEVER:		wFunc = W3D_Z_NEVER; 	break;
				case GL_LESS:		wFunc = W3D_Z_LESS;		break;
				case GL_EQUAL:		wFunc = W3D_Z_EQUAL;	break;
				case GL_LEQUAL:		wFunc = W3D_Z_LEQUAL;	break;
				case GL_GREATER:	wFunc = W3D_Z_GREATER;	break;
				case GL_NOTEQUAL:	wFunc = W3D_Z_NOTEQUAL;	break;
				case GL_GEQUAL:		wFunc = W3D_Z_GEQUAL;	break;
				case GL_ALWAYS:		wFunc = W3D_Z_ALWAYS;	break;
        }
        
		IWarp3D->W3D_SetZCompareMode(context->w3dContext, wFunc);
	}
	
	if (mask & GL_FOG_BIT)
	{
		context->fog = context->fog_stack[stackp];
		
		context->FogDirty = GL_TRUE;
		
		context->w3dFog.fog_density = context->fog.FogDensity;
		context->w3dFog.fog_color.r = context->fog.FogColor.r;
		context->w3dFog.fog_color.g = context->fog.FogColor.g;
		context->w3dFog.fog_color.b = context->fog.FogColor.b;
		
		switch (context->fog.FogMode)
		{
			case GL_LINEAR:
				context->w3dFogMode = W3D_FOG_LINEAR;
				break;
			case GL_EXP:
				context->w3dFogMode = W3D_FOG_EXP;
				break;
			case GL_EXP2:
				context->w3dFogMode = W3D_FOG_EXP_2;
				break;
		}
	}
	
	if (mask & GL_HINT_BIT)
	{
		context->hint = context->hint_stack[stackp];
		
		/* No further hardware state */
	}
	
	if (mask & GL_LIGHTING_BIT)
	{
		context->lighting = context->lighting_stack[stackp];
		
		/* No further hardware state */
	}
	
	if (mask & GL_LINE_BIT)
	{
		context->line = context->line_stack[stackp];
		
#ifdef MGL_NEW_WARP3D
		IWarp3D->W3D_SetParameter(context->w3dContext, W3D_LINE_WIDTH, 
					&context->line.LineWidth);
#endif
	}
	
	if (mask & GL_POINT_BIT)
	{
		context->point = context->point_stack[stackp];
		
#ifdef MGL_NEW_WARP3D
		IWarp3D->W3D_SetParameter(context->w3dContext, W3D_POINT_SIZE,
					&context->point.PointSize);
#endif	
	}
	
	if (mask & GL_POLYGON_BIT)
	{
		context->polygon = context->polygon_stack[stackp];
		
		EstablishCullState(context);
	}
	
	if (mask & GL_POLYGON_STIPPLE_BIT)
	{
		context->polygon_stipple = context->polygon_stipple_stack[stackp];
		
#ifdef MGL_NEW_WARP3D
		IWarp3D->W3D_SetParameter(context->w3dContext, W3D_STIPPLE_POLYGON,
				&context->polygon_stipple.pattern);
#endif
	}

	if (mask & GL_SCISSOR_BIT)
	{
		context->scissor = context->scissor_stack[stackp];
		
		Self->GLScissor(context->scissor.x, context->scissor.y,
						context->scissor.w, context->scissor.h);
	}
	
	if (mask & GL_STENCIL_BUFFER_BIT)
	{
		context->stencil_buffer = context->stencil_buffer_stack[stackp];
		
		/* No further hardware state */
	}
	
	if (mask & GL_TEXTURE_BIT || mask & GL_ENABLE_BIT)
	{
		int i;
		uint32 enable = W3D_DISABLE;
		
		if (mask & GL_TEXTURE_BIT)
			context->texture = context->texture_stack[stackp];

		memcpy(context->enable.Texture2D, context->enable_stack[stackp].Texture2D,
				sizeof(context->enable.Texture2D));
		memcpy(context->enable.TexGenS, context->enable_stack[stackp].TexGenS,
				sizeof(context->enable.TexGenS));
		memcpy(context->enable.TexGenT, context->enable_stack[stackp].TexGenT,
				sizeof(context->enable.TexGenT));
		context->enable.TexGen = context->enable_stack[stackp].TexGen;

		for (i = 0; i < context->texture.MaxTextureUnit; i++)
		{
			if (context->enable.Texture2D[i])
			{
				enable = W3D_ENABLE;
				break;
			}
		}
		
		IWarp3D->W3D_SetState(context->w3dContext, W3D_TEXMAPPING, enable);

		if (mask & GL_TEXTURE_BIT)
		{
			RebindTextures(context);
			tex_EstablishEnvCombine(context);
		}
	}
	
	if (mask & GL_TRANSFORM_BIT)
	{
		context->transform = context->transform_stack[stackp];
		
		/* No further hardware state */
	}
	
	if (mask & GL_VIEWPORT_BIT)
	{
		context->viewport = context->viewport_stack[stackp];
		
		Self->GLViewport(context->viewport.x, context->viewport.x,
						 context->viewport.w, context->viewport.h);
	}
	
	/* Handle enables. To reduce the code and avoid unnecessary copies, we don't
	 * copy the whole structure, but only those necessary (which might be all of
	 * them)
	 */
#define TEST(en) (context->enable.en ? W3D_ENABLE : W3D_DISABLE)

	if (mask & GL_COLOR_BUFFER_BIT || mask & GL_ENABLE_BIT)
	{
		context->enable.AlphaTest = context->enable_stack[stackp].AlphaTest;
		context->enable.Blend = context->enable_stack[stackp].Blend;
		context->enable.Dither = context->enable_stack[stackp].Dither;
		
		IWarp3D->W3D_SetState(context->w3dContext, W3D_ALPHATEST, TEST(AlphaTest));
		IWarp3D->W3D_SetState(context->w3dContext, W3D_BLENDING, TEST(Blend));
		IWarp3D->W3D_SetState(context->w3dContext, W3D_DITHERING, TEST(Dither));
	}
	
	if (mask & GL_FOG_BIT || mask & GL_ENABLE_BIT)
	{
		context->enable.Fog = context->enable_stack[stackp].Fog;
		
		IWarp3D->W3D_SetState(context->w3dContext, W3D_FOGGING, TEST(Fog));
	}
	
	if (mask & GL_SCISSOR_BIT || mask & GL_ENABLE_BIT)
	{
		context->enable.ScissorTest = context->enable_stack[stackp].ScissorTest;
		
		IWarp3D->W3D_SetState(context->w3dContext, W3D_SCISSOR, TEST(ScissorTest));
	}
	
	if (mask & GL_POLYGON_BIT || mask & GL_ENABLE_BIT)
	{
		context->enable.CullFace = context->enable_stack[stackp].CullFace;
		context->enable.PolygonSmooth = context->enable_stack[stackp].PolygonSmooth;
		context->enable.PolygonStipple = context->enable_stack[stackp].PolygonStipple;
		context->enable.PolygonOffsetFill = context->enable_stack[stackp].PolygonOffsetFill;

		IWarp3D->W3D_SetState(context->w3dContext, W3D_ANTI_POLYGON, TEST(PolygonSmooth));
	}
	
	if (mask & GL_DEPTH_BUFFER_BIT || mask & GL_ENABLE_BIT)
	{
		context->enable.DepthTest = context->enable_stack[stackp].DepthTest;
		context->enable.ZOffset = context->enable_stack[stackp].ZOffset;
		
		IWarp3D->W3D_SetState(context->w3dContext, W3D_ZBUFFER, TEST(DepthTest));
	}
	
	if (mask & GL_POINT_BIT || mask & GL_ENABLE_BIT)
	{
		context->enable.PointSmooth = context->enable_stack[stackp].PointSmooth;
		
		IWarp3D->W3D_SetState(context->w3dContext, W3D_ANTI_POINT, TEST(PointSmooth));
	}
	
	if (mask & GL_LINE_BIT || mask & GL_ENABLE_BIT)
	{
		context->enable.LineSmooth = context->enable_stack[stackp].LineSmooth;
		context->enable.LineStipple = context->enable_stack[stackp].LineStipple;
		
		IWarp3D->W3D_SetState(context->w3dContext, W3D_ANTI_LINE, TEST(LineSmooth));
		IWarp3D->W3D_SetState(context->w3dContext, W3D_LINE_STIPPLE, TEST(LineStipple));
	}
	
	/* Texture enables handled above */
	
	if (mask & GL_LIGHTING_BIT || mask & GL_ENABLE_BIT)
	{
		context->enable.Lighting = context->enable_stack[stackp].Lighting;
		context->enable.ColorMaterial = context->enable_stack[stackp].ColorMaterial;
		memcpy(context->enable.Light, context->enable_stack[stackp].Light,
			sizeof(context->enable.Light));
	}
	
	if (mask & GL_TRANSFORM_BIT || mask & GL_ENABLE_BIT)
	{
		memcpy(context->enable.ClipPlane, context->enable_stack[stackp].ClipPlane,
			sizeof(context->enable.ClipPlane));
	}
	
	if (mask & GL_STENCIL_BUFFER_BIT || mask & GL_ENABLE_BIT)
	{
		context->enable.StencilTest = context->enable_stack[stackp].StencilTest;
		
		IWarp3D->W3D_SetState(context->w3dContext, W3D_STENCILBUFFER, TEST(StencilTest));
	}
}
