forked from panda3d/panda3d
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathztriangle.py
More file actions
executable file
·271 lines (215 loc) · 9.07 KB
/
ztriangle.py
File metadata and controls
executable file
·271 lines (215 loc) · 9.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
#!/usr/bin/env python
""" This simple Python script can be run to generate
ztriangle_code_*.h, ztriangle_table.*, and ztriangle_*.cxx, which
are a poor man's form of generated code to cover the explosion of
different rendering options while scanning out triangles.
Each different combination of options is compiled to a different
inner-loop triangle scan function. The code in
tinyGraphicsStateGuardian.cxx will select the appropriate function
pointer at draw time. """
# This is the number of generated ztriangle_code_*.h and
# ztriangle_*.cxx files we will produce. You may change this freely;
# you should also change the Sources.pp file accordingly.
NumSegments = 4
# We generate an #include "ztriangle_two.h" for each combination of
# these options.
Options = [
# depth write
[ 'zon', 'zoff' ],
# color write
[ 'cstore', 'cblend', 'cgeneral', 'coff', 'csstore', 'csblend' ],
# alpha test
[ 'anone', 'aless', 'amore' ],
# depth test
[ 'znone', 'zless' ],
# texture filters
[ 'tnearest', 'tmipmap', 'tgeneral' ],
]
# The total number of different combinations of the various Options, above.
OptionsCount = reduce(lambda a, b: a * b, map(lambda o: len(o), Options))
# The various combinations of these options are explicit within
# ztriangle_two.h.
ExtraOptions = [
# shade model
[ 'white', 'flat', 'smooth' ],
# texturing
[ 'untextured', 'textured', 'perspective', 'multitex2', 'multitex3' ],
]
# The expansion of all ExtraOptions combinations into a linear list.
ExtraOptionsMat = []
for i in range(len(ExtraOptions[0])):
for j in range(len(ExtraOptions[1])):
ExtraOptionsMat.append([i, j])
FullOptions = Options + ExtraOptions
CodeTable = {
# depth write
'zon' : '#define STORE_Z(zpix, z) (zpix) = (z)',
'zoff' : '#define STORE_Z(zpix, z)',
# color write
'cstore' : '#define STORE_PIX(pix, rgb, r, g, b, a) (pix) = (rgb)',
'cblend' : '#define STORE_PIX(pix, rgb, r, g, b, a) (pix) = PIXEL_BLEND_RGB(pix, r, g, b, a)',
'cgeneral' : '#define STORE_PIX(pix, rgb, r, g, b, a) zb->store_pix_func(zb, pix, r, g, b, a)',
'coff' : '#define STORE_PIX(pix, rgb, r, g, b, a)',
# color write, sRGB
'csstore' : '#define STORE_PIX(pix, rgb, r, g, b, a) (pix) = SRGBA_TO_PIXEL(r, g, b, a)',
'csblend' : '#define STORE_PIX(pix, rgb, r, g, b, a) (pix) = PIXEL_BLEND_SRGB(pix, r, g, b, a)',
# alpha test
'anone' : '#define ACMP(zb, a) 1',
'aless' : '#define ACMP(zb, a) (((int)(a)) < (zb)->reference_alpha)',
'amore' : '#define ACMP(zb, a) (((int)(a)) > (zb)->reference_alpha)',
# depth test
'znone' : '#define ZCMP(zpix, z) 1',
'zless' : '#define ZCMP(zpix, z) ((ZPOINT)(zpix) < (ZPOINT)(z))',
# texture filters
'tnearest' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define ZB_LOOKUP_TEXTURE(texture_def, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_NEAREST(texture_def, s, t)',
'tmipmap' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx) DO_CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_def, s, t, level, level_dx) ZB_LOOKUP_TEXTURE_MIPMAP_NEAREST(texture_def, s, t, level)',
'tgeneral' : '#define CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx) DO_CALC_MIPMAP_LEVEL(mipmap_level, mipmap_dx, dsdx, dtdx)\n#define INTERP_MIPMAP\n#define ZB_LOOKUP_TEXTURE(texture_def, s, t, level, level_dx) ((level == 0) ? (texture_def)->tex_magfilter_func(texture_def, s, t, level, level_dx) : (texture_def)->tex_minfilter_func(texture_def, s, t, level, level_dx))',
}
ZTriangleStub = """
/* This file is generated code--do not edit. See ztriangle.py. */
#include <stdlib.h>
#include <stdio.h>
#include "pandabase.h"
#include "zbuffer.h"
/* Pick up all of the generated code references to ztriangle_two.h,
which ultimately calls ztriangle.h, many, many times. */
#include "ztriangle_table.h"
#include "ztriangle_code_%s.h"
"""
ops = [0] * len(Options)
class DoneException:
pass
# We write the code that actually instantiates the various
# triangle-filling functions to ztriangle_code_*.h.
code = None
codeSeg = None
fnameDict = {}
fnameList = None
def incrementOptions(ops, i = -1):
if i < -len(ops):
raise DoneException
# Increment the least-significant place if we can.
if ops[i] + 1 < len(Options[i]):
ops[i] += 1
return
# Recurse for the next-most-significant place.
ops[i] = 0
incrementOptions(ops, i - 1)
def getFname(ops):
# Returns the function name corresponding to the indicated ops
# vector.
keywordList = []
for i in range(len(ops)):
keyword = FullOptions[i][ops[i]]
keywordList.append(keyword)
if keywordList[-1].startswith('multitex'):
# We don't bother with white_multitex or flat_multitex.
keywordList[-2] = 'smooth'
fname = 'FB_triangle_%s' % ('_'.join(keywordList))
return fname
def getFref(ops):
# Returns a string that evaluates to a pointer reference to the
# indicated function.
fname = getFname(ops)
codeSeg, i = fnameDict[fname]
fref = 'ztriangle_code_%s[%s]' % (codeSeg, i)
return fref
def closeCode():
""" Close the previously-opened code file. """
if code:
print >> code, ''
print >> code, 'ZB_fillTriangleFunc ztriangle_code_%s[%s] = {' % (codeSeg, len(fnameList))
for fname in fnameList:
print >> code, ' %s,' % (fname)
print >> code, '};'
code.close()
def openCode(count):
""" Open the code file appropriate to the current segment. We
write out the generated code into a series of smaller files,
instead of one mammoth file, just to make it easier on the
compiler. """
global code, codeSeg, fnameList
seg = int(NumSegments * count / OptionsCount) + 1
if codeSeg != seg:
closeCode()
codeSeg = seg
fnameList = []
# Open a new file.
code = open('ztriangle_code_%s.h' % (codeSeg), 'wb')
print >> code, '/* This file is generated code--do not edit. See ztriangle.py. */'
print >> code, ''
# Also generate ztriangle_*.cxx, to include the above file.
zt = open('ztriangle_%s.cxx' % (codeSeg), 'wb')
print >> zt, ZTriangleStub % (codeSeg)
# First, generate the code.
count = 0
try:
while True:
openCode(count)
for i in range(len(ops)):
keyword = Options[i][ops[i]]
print >> code, CodeTable[keyword]
# This reference gets just the initial fname: omitting the
# ExtraOptions, which are implicit in ztriangle_two.h.
fname = getFname(ops)
print >> code, '#define FNAME(name) %s_ ## name' % (fname)
print >> code, '#include "ztriangle_two.h"'
print >> code, ''
# We store the full fnames generated by the above lines
# (including the ExtraOptions) in the fnameDict and fnameList
# tables.
for eops in ExtraOptionsMat:
fops = ops + eops
fname = getFname(fops)
fnameDict[fname] = (codeSeg, len(fnameList))
fnameList.append(fname)
count += 1
incrementOptions(ops)
assert count < OptionsCount
except DoneException:
pass
assert count == OptionsCount
closeCode()
# Now, generate the table of function pointers.
# The external reference for the table containing the above function
# pointers gets written here.
table_decl = open('ztriangle_table.h', 'wb')
print >> table_decl, '/* This file is generated code--do not edit. See ztriangle.py. */'
print >> table_decl, ''
# The actual table definition gets written here.
table_def = open('ztriangle_table.cxx', 'wb')
print >> table_def, '/* This file is generated code--do not edit. See ztriangle.py. */'
print >> table_def, ''
print >> table_def, '#include "pandabase.h"'
print >> table_def, '#include "zbuffer.h"'
print >> table_def, '#include "ztriangle_table.h"'
print >> table_def, ''
for i in range(NumSegments):
print >> table_def, 'extern ZB_fillTriangleFunc ztriangle_code_%s[];' % (i + 1)
print >> table_def, ''
def writeTableEntry(ops):
indent = ' ' * (len(ops) + 1)
i = len(ops)
numOps = len(FullOptions[i])
if i + 1 == len(FullOptions):
# The last level: write out the actual function names.
for j in range(numOps - 1):
print >> table_def, indent + getFref(ops + [j]) + ','
print >> table_def, indent + getFref(ops + [numOps - 1])
else:
# Intermediate levels: write out a nested reference.
for j in range(numOps - 1):
print >> table_def, indent + '{'
writeTableEntry(ops + [j])
print >> table_def, indent + '},'
print >> table_def, indent + '{'
writeTableEntry(ops + [numOps - 1])
print >> table_def, indent + '}'
arraySizeList = []
for opList in FullOptions:
arraySizeList.append('[%s]' % (len(opList)))
arraySize = ''.join(arraySizeList)
print >> table_def, 'const ZB_fillTriangleFunc fill_tri_funcs%s = {' % (arraySize)
print >> table_decl, 'extern const ZB_fillTriangleFunc fill_tri_funcs%s;' % (arraySize)
writeTableEntry([])
print >> table_def, '};'