# Copyright (c) 2001, Stanford University
# All rights reserved.
#
# See the file LICENSE.txt for information on redistributing this software.

import sys

sys.path.append( '../packer' )
sys.path.append( '../glapi_parser' )
from pack_currenttypes import *
import apiutil

apiutil.CopyrightC()

print '''
#include "state/cr_currentpointers.h"
#include "state.h"

#include <stdio.h>

#ifdef WINDOWS
#pragma warning( disable : 4127 )
#endif

typedef void (*convert_func) (GLfloat *, const unsigned char *);
'''

import convert

for k in current_fns.keys():
	name = k
	name = '%s%s' % (k[:1].lower(),k[1:])
	ucname = k.upper()
	num_members = len(current_fns[k]['default']) + 1

	print '#define VPINCH_CONVERT_%s(op,data,dst) \\' % ucname
	print '{\\'
	print '\tGLfloat vdata[%d] = {' % num_members,

## Copy dst data into vdata
	i = 0;
	for defaultvar in current_fns[k]['default']:
		print '%d' % defaultvar,
		if i != num_members:
			print ',',
		i += 1
	print '};\\'

	print '\tswitch (op) { \\'
	for type in current_fns[k]['types']:
		if type[0:1] == "N":
			normalize = 1
			type = type[1:]
		else:
			normalize = 0
		for size in current_fns[k]['sizes']:
			uctype = type.upper()
			if ucname == 'EDGEFLAG':
				print '\tcase CR_%s_OPCODE: \\' % ucname
			else:
				print '\tcase CR_%s%d%s_OPCODE: \\' % (ucname,size,uctype)
			
			if (ucname == 'COLOR' or ucname == 'NORMAL' or ucname == 'SECONDARYCOLOR' or normalize) and type != 'f' and type != 'd':
				print '\t\t__convert_rescale_%s%d (vdata, (%s *) (data)); \\' % (type,size,gltypes[type]['type'])
			else:
				print '\t\t__convert_%s%d (vdata, (%s *) (data)); \\' % (type,size,gltypes[type]['type'])
			print '\t\tbreak; \\'

	print '\tdefault: \\'
	print '\t\tcrSimpleError ( "Unknown opcode in VPINCH_CONVERT_%s" ); \\' % ucname
	print '\t}\\'

	i = 0
	for member in current_fns[k]['members']:
		print '\t(dst).%s = vdata[%d];\\' % (member,i)
		i += 1

	print '}\n'

print '''

void crStateCurrentRecover( void )
{
	const unsigned char *v;
	convert_func convert=NULL;
	CRContext *g = GetCurrentContext();
	CRCurrentState *c = &(g->current);
	CRStateBits *sb = GetCurrentBits();
	CRCurrentBits *cb = &(sb->current);
	static const GLfloat color_default[4]			= {0.0f, 0.0f, 0.0f, 1.0f};
	static const GLfloat secondaryColor_default[4] = {0.0f, 0.0f, 0.0f, 0.0f};
	static const GLfloat texCoord_default[4]	= {0.0f, 0.0f, 0.0f, 1.0f};
	static const GLfloat normal_default[4]		= {0.0f, 0.0f, 0.0f, 1.0f};
	static const GLfloat index_default			= 0.0f;
	static const GLboolean edgeFlag_default		= GL_TRUE;
	static const GLfloat vertexAttrib_default[4] = {0.0f, 0.0f, 0.0f, 1.0f};
	static const GLfloat fogCoord_default = 0.0f;
	GLnormal_p		*normal		= &(c->current->c.normal);
	GLcolor_p		*color		= &(c->current->c.color);
	GLsecondarycolor_p *secondaryColor = &(c->current->c.secondaryColor);
	GLtexcoord_p	*texCoord	= &(c->current->c.texCoord);
	GLindex_p		*index		= &(c->current->c.index);
	GLedgeflag_p	*edgeFlag	= &(c->current->c.edgeFlag);
	GLvertexattrib_p *vertexAttrib = &(c->current->c.vertexAttrib);
	GLfogcoord_p *fogCoord = &(c->current->c.fogCoord);
	unsigned int i;
	CRbitvalue nbitID[CR_MAX_BITARRAY];

	/* 
	 * If the calling SPU hasn't called crStateSetCurrentPointers()
	 * we can't recover anything, so abort now. (i.e. we don't have
	 * a pincher, oh, and just emit the message once).
	 */
	if (!c->current) {
		static int donewarning = 0;
		if (!donewarning)
			crWarning("No pincher, please call crStateSetCurrentPointers() in your SPU");
		donewarning = 1;
		return; /* never get here */
	}

	c->attribsUsedMask = c->current->attribsUsedMask;
	
	/* silence warnings */
	(void) __convert_b1;
	(void) __convert_b2;
	(void) __convert_b3;
	(void) __convert_b4;
	(void) __convert_ui1;
	(void) __convert_ui2;
	(void) __convert_ui3;
	(void) __convert_ui4;
	(void) __convert_l1;
	(void) __convert_l2;
	(void) __convert_l3;
	(void) __convert_l4;
	(void) __convert_us1;
	(void) __convert_us2;
	(void) __convert_us3;
	(void) __convert_us4;
	(void) __convert_ub1;
	(void) __convert_ub2;
	(void) __convert_ub3;
	(void) __convert_ub4;
	(void) __convert_rescale_s1;
	(void) __convert_rescale_s2;
	(void) __convert_rescale_b1;
	(void) __convert_rescale_b2;
	(void) __convert_rescale_ui1;
	(void) __convert_rescale_ui2;
	(void) __convert_rescale_i1;
	(void) __convert_rescale_i2;
	(void) __convert_rescale_us1;
	(void) __convert_rescale_us2;
	(void) __convert_rescale_ub1;
	(void) __convert_rescale_ub2;
	(void) __convert_Ni1;
	(void) __convert_Ni2;
	(void) __convert_Ni3;
	(void) __convert_Ni4;