# $Id$
import apiutil
# A routine that can create call strings from instance names
output = ''
if index > 0:
output += ", "
return output
# We'll keep track of all the parameters that require pointers.
# They'll require special handling later.
pointers = []
pointername=''
pointerarg=''
pointertype=''
index = 0
# Watch out for the word "const" (which should be ignored)
# and for types that end in "*" (which are pointers and need
# special treatment)
index += 1
# If any argument was a pointer, we need a special pointer data
# array. The pointer data will be stored into this array, and
# references to the array will be generated as parameters.
if pointersize == 0:
pointersize = "special"
pointerarg = 'data';
pointertype = 'GLvoid *'
extendedArgstring += ", CRClientState *c"
# We'll keep track of all the parameters that require pointers.
# They'll require special handling later.
(pointers, pointername, pointerarg, pointertype, pointersize, pointercomment) = GetPointerInfo(functionName)
# Start writing the header
print 'struct instance%s {' % (functionName)
print ' DLMInstanceList *next;'
print ' DLMInstanceList *stateNext;'
print ' void (DLM_APIENTRY *execute)(DLMInstanceList *instance, SPUDispatchTable *dispatchTable);'
# Watch out for the word "const" (which should be ignored)
# and for types that end in "*" (which are pointers and need
# special treatment)
# If any argument was a pointer, we need a special pointer data
# array. The pointer data will be stored into this array, and
# references to the array will be generated as parameters.
if pointersize == None:
print " /* Oh no - pointer parameter %s found, but no pointer class specified and can't guess */" % pointername
else:
if pointersize == 'special':
else:
print '};'
# Pointers only happen with instances
print 'int crdlm_pointers_%s(struct instance%s *instance, %s);' % (functionName, functionName, extendedArgstring)
# See if the GL function must sometimes allow passthrough even
# if the display list is open
return
print 'static void execute%s(DLMInstanceList *x, SPUDispatchTable *dispatchTable)' % functionName
print '{'
print '\tif (dispatchTable->%s != NULL) {' % (functionName)
print '\t}'
print '\telse {'
print '\t\tcrWarning("DLM warning: execute%s called with NULL dispatch entry");' % (functionName)
print '\t}'
print '}'
pattern = "(VertexAttribs|VertexAttrib|Vertex)(1|2|3|4)(N?)(f|d|i|s|b|ub|us|ui)(v?)"
if m:
# only update bbox for vertex attribs if index == 0
if name == "VertexAttrib":
test = "if (index == 0) {"
elif name == "VertexAttribs":
test = "if (index == 0) {"
else:
assert name == "Vertex"
test = "{"
# find names of the X, Y, Z, W values
xName = ""
yName = ""
zName = "0.0"
wName = ""
if vector == "v":
xName = "v[0]"
if size > 1:
yName = "v[1]"
if size > 2:
zName = "v[2]"
if size > 3:
wName = "v[3]"
else:
xName = "x"
if size > 1:
yName = "y"
if size > 2:
zName = "z"
if size > 3:
wName = "w"
# start emitting code
print '\t%s' % test
if normalize == "N":
if type == "b":
denom = "128.0f"
elif type == "s":
denom = "32768.0f"
elif type == "i":
denom = "2147483647.0f"
elif type == "ub":
denom = "255.0f"
elif type == "us":
denom = "65535.0f"
elif type == "ui":
denom = "4294967295.0f"
xName = "nx"
if yName:
yName = "ny"
if zName:
zName = "nz"
if 0 and wName:
wName = "nw"
if xName:
print '\t\tif (%s < state->currentListInfo->bbox.xmin)' % xName
print '\t\t\tstate->currentListInfo->bbox.xmin = %s;' % xName
print '\t\tif (%s > state->currentListInfo->bbox.xmax)' % xName
print '\t\t\tstate->currentListInfo->bbox.xmax = %s;' % xName
if yName:
print '\t\tif (%s < state->currentListInfo->bbox.ymin)' % yName
print '\t\t\tstate->currentListInfo->bbox.ymin = %s;' % yName
print '\t\tif (%s > state->currentListInfo->bbox.ymax)' % yName
print '\t\t\tstate->currentListInfo->bbox.ymax = %s;' % yName
if zName:
print '\t\tif (%s < state->currentListInfo->bbox.zmin)' % zName
print '\t\t\tstate->currentListInfo->bbox.zmin = %s;' % zName
print '\t\tif (%s > state->currentListInfo->bbox.zmax)' % zName
print '\t\t\tstate->currentListInfo->bbox.zmax = %s;' % zName
# XXX what about divide by W if we have 4 components?
print '\t}'
else:
print ' /* bbox error for %s !!!!! */' % functionName
# These code snippets isolate the code required to add a given instance
# to the display list correctly. They are used during generation, to
# generate correct code, and also to create useful utilities.
print '%s/* Add this instance to the current display list. */' % pad
print '%sinstance->next = NULL;' % pad
print '%sinstance->stateNext = NULL;' % pad
print '%sif (!state->currentListInfo->first) {' % pad
print '%s\tstate->currentListInfo->first = (DLMInstanceList *)instance;' % pad
print '%s}' % pad
print '%selse {' % pad
print '%s\tstate->currentListInfo->last->next = (DLMInstanceList *)instance;' % pad
print '%s}' % pad
print '%sstate->currentListInfo->last = (DLMInstanceList *)instance;' % pad
print '%sstate->currentListInfo->numInstances++;' % pad
print '%s/* Instances that change state have to be added to the state list as well. */' % pad
print '%sif (!state->currentListInfo->stateFirst) {' % pad
print '%s\tstate->currentListInfo->stateFirst = (DLMInstanceList *)instance;' % pad
print '%s}' % pad
print '%selse {' % pad
print '%s\tstate->currentListInfo->stateLast->stateNext = (DLMInstanceList *)instance;' % pad
print '%s}' % pad
print '%sstate->currentListInfo->stateLast = (DLMInstanceList *)instance;' % pad
# The compile wrapper collects the parameters into a DLMInstanceList
# element, and adds that element to the end of the display list currently
# being compiled.
# Make sure the return type is void. It's nonsensical to compile
# an element with any other return type.
if return_type != 'void':
# return
# Define a structure to hold all the parameters. Note that the
# top parameters must exactly match the DLMInstanceList structure
# Start off by getting all the pointer info we could ever use
# from the parameters
(pointers, pointername, pointerarg, pointertype, pointersize, pointercomment) = GetPointerInfo(functionName)
# Finally, the compile wrapper. This one will diverge strongly
# depending on whether or not there are pointer parameters.
callstring += ", c"
argstring += ", CRClientState *c"
print '{'
print ' CRDLMContextState *state = CURRENT_STATE();'
print ' struct instance%s *instance;' % (functionName)
# The calling SPU is supposed to verify that the element is supposed to be
# compiled before it is actually compiled; typically, this is done based
# on whether a glNewList has been executed more recently than a glEndList.
# But some functions are dual-natured, sometimes being compiled, and sometimes
# being executed immediately. We can check for this here.
print '\t\tcrdlm_error(__LINE__, __FILE__, GL_INVALID_OPERATION,'
print '\t\t "this instance of function %s should not be compiled");' % functionName;
print '\t\treturn;'
print '\t}'
# Pass NULL, to just allocate space
print '\tinstance = crCalloc(sizeof(struct instance%s) + crdlm_pointers_%s(NULL, %s));' % (functionName, functionName, callstring)
else:
print '\tinstance = crCalloc(sizeof(struct instance%s));' % (functionName)
print '\tif (!instance) {'
print '\t\tcrdlm_error(__LINE__, __FILE__, GL_OUT_OF_MEMORY,'
print '\t\t\t"out of memory adding %s to display list");' % (functionName)
print '\t\treturn;'
print '\t}'
# Put in the fields that must always exist
print '\tinstance->execute = execute%s;' % functionName
# Apply all the simple (i.e. non-pointer) parameters
# If there's a pointer parameter, apply it.
print '\t}'
print '\telse {'
print '\t}'
if pointersize == 'special':
else:
print '\tcrMemcpy((void *)instance->%s, (void *) %s, %s*sizeof(%s));' % (params[pointers[0]][0], params[pointers[0]][0], pointersize, pointertype)
# this seems to work
print "#error don't know how to handle pointer parameters for %s" % (functionName)
# Add the element to the current display list
AddInstanceToList('\t')
# If the element is a state-changing element, add it to the current state list
AddInstanceToStateList('\t')
# XXX might need a better test here
print '}'
if whichfile == 'headers':
print """#ifndef _DLM_GENERATED_H
#define _DLM_GENERATED_H
/* DO NOT EDIT. This file is auto-generated by dlm_generated.py. */
"""
else:
print """#include <stdio.h>
#include "cr_spu.h"
#include "cr_dlm.h"
#include "cr_mem.h"
#include "cr_error.h"
#include "state/cr_statefuncs.h"
#include "dlm.h"
#include "dlm_pointers.h"
#include "dlm_generated.h"
/* DO NOT EDIT. This file is auto-generated by dlm_generated.py. */
"""
# Add in the "add_to_dl" utility function, which will be used by
# external (i.e. non-generated) functions. The utility ensures that
# any external functions that are written for compiling elements
# don't have to be rewritten if the conventions for adding to display
# lists are changed.
print """
void crdlm_add_to_list(
DLMInstanceList *instance,
void (*executeFunc)(DLMInstanceList *x, SPUDispatchTable *dispatchTable)"""
if (whichfile == 'headers'):
print ");"
else:
print """) {
CRDLMContextState *state = CURRENT_STATE();
instance->execute = executeFunc;"""
# Add in the common code for adding the instance to the display list
AddInstanceToList(" ")
print '}'
print ''
# Now generate the functions that won't use the crdlm_add_to_list utility.
# These all directly add their own instances to the current display list
# themselves, without using the crdlm_add_to_list() function.
print "\n/*** %s ***/" % func_name
# Auto-generate an appropriate DL function. First, functions
# that go into the display list but that rely on state will
# have to have their argument strings expanded, to take pointers
# to that appropriate state.
if whichfile == "headers":
# All others just pass through
if whichfile == 'headers':
print "#endif /* _DLM_GENERATED_H */"