/****************************************************************************
 * RAGE128 Chapter 6 Sample Code                                            *
 *                                                                          *
 * rendstat.c - Function for setting miscellaneous 3D render states.        *
 *                                                                          *
 * Copyright (c) 1999 ATI Technologies Inc.  All rights reserved.           *
 ****************************************************************************/

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include "..\..\util\regdef.h"
#include "..\..\util\defines.h"
#include "..\..\util\main.h"
#include "..\..\util\cce.h"
#include "rendstat.h"
#include "cntx3d.h"

extern CONTEXT3D gContext3D;
extern DWORD gCommandBuf[];


/****************************************************************************
 * R128_SetRenderState										                *
 *  Function: set an enumerated render state.                               *
 *    Inputs: eRenderState - ERENDERSTATE enum of state to be set.			*
 *			  data - state-sepcific data to be set.							*
 *   Outputs: TRUE - successful.                                            *
 *			  FALSE - unsuccessful.											*
 ****************************************************************************/

BOOL R128_SetRenderState (ERENDERSTATE eRenderState, DWORD data)
{
	int i = 0;

	switch (eRenderState)
	{

	// Set shading mode.

	case RENDERSTATE_SHADEMODE:

		switch ((ESHADEMODE)data)
		{
		case SHADE_SOLIDCOLOR:
        case SHADE_FLAT:
		case SHADE_GOURAUD:
			break;

		default:
			return FALSE;
		}

        // Set PM4_VC_FPU_SETUP:PM4_COLOR_FCN field.

        gContext3D.regPM4_VC_FPU_SETUP &= ~(0x00000003 << 5);
        gContext3D.regPM4_VC_FPU_SETUP |= (data << 5);
        gCommandBuf[i++] = CCE_PACKET0 | (PM4_VC_FPU_SETUP >> 2);
        gCommandBuf[i++] = gContext3D.regPM4_VC_FPU_SETUP;
		R128_CCESubmitPackets (gCommandBuf, i);

		break;

    // Set flat shade vertex.

    case RENDERSTATE_FLATSHADEVERTEX:

        switch ((EFLATSHADEVERTEX)data)
        {
        case FLATSHADEVERTEX_D3D:
        case FLATSHADEVERTEX_OPENGL:
            break;

        default:
            return FALSE;
        }

        // Set PM4_VC_FPU_SETUP:FLAT_SHADE_VERTEX field.

        gContext3D.regPM4_VC_FPU_SETUP &= ~(0x00000001 << 14);
        gContext3D.regPM4_VC_FPU_SETUP |= (data << 14);
        gCommandBuf[i++] = CCE_PACKET0 | (PM4_VC_FPU_SETUP >> 2);
        gCommandBuf[i++] = gContext3D.regPM4_VC_FPU_SETUP;
		R128_CCESubmitPackets (gCommandBuf, i);

        break;

	// Set the constant color.

	case RENDERSTATE_SOLIDCOLOR:

		gCommandBuf[i++] = CCE_PACKET0 | (CONSTANT_COLOR_C >> 2);
		gCommandBuf[i++] = gContext3D.regCONSTANT_COLOR_C = data;
		R128_CCESubmitPackets (gCommandBuf, i);

		break;

	// Set the dither mode.

	case RENDERSTATE_DITHERMODE:

		// For now, true/false.

		gContext3D.regTEX_CNTL_C &= ~(0x00000001 << 8);
		gContext3D.regTEX_CNTL_C |= ((data & 0x00000001) << 8);

		// Set TEX_CNTL_C:DITHER_EN field.

	    gCommandBuf[i++] = CCE_PACKET0 | (TEX_CNTL_C >> 2);
		gCommandBuf[i++] = gContext3D.regTEX_CNTL_C;
		R128_CCESubmitPackets (gCommandBuf, i);

		break;

	// Set the front face direction.

	case RENDERSTATE_FRONTDIR:

		switch ((EFRONTDIR)data)
		{
        case FRONTDIR_CW:
        case FRONTDIR_CCW:
			break;

		default:
			return FALSE;
		}

		// Set PM4_VC_FPU_SETUP:FRONT_DIR field.

		gContext3D.regPM4_VC_FPU_SETUP &= ~(0x00000001);
		gContext3D.regPM4_VC_FPU_SETUP |= (data);
	    gCommandBuf[i++] = CCE_PACKET0 | (PM4_VC_FPU_SETUP >> 2);
	    gCommandBuf[i++] = gContext3D.regPM4_VC_FPU_SETUP;
		R128_CCESubmitPackets (gCommandBuf, i);

		break;

	// Set the front facing culling function.

	case RENDERSTATE_FRONTFACE_CULL_FCN:

		switch ((ECULLFCN)data)
		{
		case CULLFCN_CULL:
		case CULLFCN_DRAW_POINT:
		case CULLFCN_DRAW_LINE:
		case CULLFCN_DRAW_REV_SOLID:
			break;

		default:
			return FALSE;
		}
		// Set PM4_VC_FPU_SETUP:FRONT_CULLING_FN field.

		gContext3D.regPM4_VC_FPU_SETUP &= ~(0x00000003 << 3);
		gContext3D.regPM4_VC_FPU_SETUP |= (data << 3);
	    gCommandBuf[i++] = CCE_PACKET0 | (PM4_VC_FPU_SETUP >> 2);
	    gCommandBuf[i++] = gContext3D.regPM4_VC_FPU_SETUP;
		R128_CCESubmitPackets (gCommandBuf, i);

		break;

	// Set the back facing culling function.

	case RENDERSTATE_BACKFACE_CULL_FCN:
		switch ((ECULLFCN)data)
		{
		case CULLFCN_CULL:
		case CULLFCN_DRAW_POINT:
		case CULLFCN_DRAW_LINE:
		case CULLFCN_DRAW_REV_SOLID:
			break;

		default:
			return FALSE;
		}
		// Set PM4_VC_FPU_SETUP:BACK_CULLING_FN field.

		gContext3D.regPM4_VC_FPU_SETUP &= ~(0x00000003 << 1);
		gContext3D.regPM4_VC_FPU_SETUP |= (data << 1);
	    gCommandBuf[i++] = CCE_PACKET0 | (PM4_VC_FPU_SETUP >> 2);
	    gCommandBuf[i++] = gContext3D.regPM4_VC_FPU_SETUP;
		R128_CCESubmitPackets (gCommandBuf, i);

		break;

	case RENDERSTATE_DSTOFFSET:

		// Set DST_PITCH_OFFSET_C:DST_OFFSET field.

		gContext3D.regDST_PITCH_OFFSET_C &= 0xffe00000;
		gContext3D.regDST_PITCH_OFFSET_C |= (data & 0x001fffff);
	    gCommandBuf[i++] = CCE_PACKET0 | (DST_PITCH_OFFSET_C >> 2);
	    gCommandBuf[i++] = gContext3D.regDST_PITCH_OFFSET_C;
		R128_CCESubmitPackets (gCommandBuf, i);

		// wait for idle and/or flush ring buf?

		break;

	default:
		return FALSE;
	} // swith

	return TRUE;
}
