38 |
|
|
39 |
def matchop(str,i): |
def matchop(str,i): |
40 |
def opchar(str, i): |
def opchar(str, i): |
41 |
return i < len(str) and str[i] in [ "*", "/", "+", "-", ".", "|" ] |
return i < len(str) and str[i] in [ "*", "/", "+", "-", ".", "|", "%" ] |
42 |
if opchar(str, i): return i + 1 |
if opchar(str, i): return i + 1 |
43 |
return 0 |
return 0 |
44 |
|
|
144 |
tree[i:i+1] = [("reg", regmap[node[1]], "RGB")] |
tree[i:i+1] = [("reg", regmap[node[1]], "RGB")] |
145 |
i += 1 |
i += 1 |
146 |
|
|
|
def removeparen(tree): |
|
|
# Remove extra parentheses |
|
|
if len(tree) == 1 and tree[0][0] == "sub": |
|
|
tree[:] = tree[0][1] |
|
|
return tree |
|
|
|
|
147 |
def parsekey(tree): |
def parsekey(tree): |
148 |
# Return list of node types |
# Return list of node types |
149 |
return map(lambda x: x[0], tree) |
return tuple(map(lambda x: x[0], tree)) |
|
|
|
150 |
|
|
151 |
def findregs(tree, type = "reg"): |
def findregs(tree, type = "reg"): |
152 |
def func(x, type=type): return x[0] == type |
def func(x, type=type): return x[0] == type |
182 |
("-", .5): "HALF_BIAS_NORMAL_NV", |
("-", .5): "HALF_BIAS_NORMAL_NV", |
183 |
} |
} |
184 |
|
|
185 |
key = tuple(parsekey(tree)) |
for i in range(0,len(tree)): |
186 |
|
if tree[i][0] == "sub": |
187 |
if inputmap.has_key(key): |
key = parsekey(tree[i][1]) |
188 |
reg = (findregs(tree) + [("reg", "ZERO", "ALPHA")])[0] |
if inputmap.has_key(key): |
189 |
tree[:] = [("in", reg[1], inputmap[key], reg[2])] |
reg = (findregs(tree[i][1]) + [("reg", "ZERO", "ALPHA")])[0] |
190 |
else: |
tree[i] = ("in", reg[1], inputmap[key], reg[2]) |
|
for i in range(0,len(tree)): |
|
|
if tree[i][0] == "sub": |
|
|
parseinput(tree[i][1], final) |
|
|
if len(tree[i][1]) == 1: |
|
|
tree[i] = tree[i][1][0] |
|
191 |
else: |
else: |
192 |
# Search for substring matches, too, for single-node keys |
parseinput(tree[i][1], final) |
193 |
key = (tree[i][0],) |
elif tree[i][0] == "reg": |
194 |
if inputmap.has_key(key): |
# Convert identity-mapped regs |
195 |
reg = ("reg", "ZERO", "ALPHA") |
tree[i] = ("in", tree[i][1], inputmap["reg",], tree[i][2]) |
|
if key == ("reg",): reg = tree[i] |
|
|
tree[i] = ("in", reg[1], inputmap[key], reg[2]) |
|
196 |
|
|
197 |
|
return tree |
198 |
|
|
199 |
def parseGeneralCombiner(outreg, tree): |
def parseGeneralCombiner(outreg, tree): |
200 |
out = { |
out = { |
214 |
("-", 0): "NONE", |
("-", 0): "NONE", |
215 |
} |
} |
216 |
|
|
217 |
key = tuple(parsekey(tree)) |
key = parsekey(tree) |
218 |
if outputscale.has_key(key): |
if outputscale.has_key(key): |
219 |
out["scale"] = outputscale[key] |
out["scale"] = outputscale[key] |
220 |
tree[:] = tree[:-2] |
tree = tree[0][1] |
|
removeparen(tree) |
|
221 |
|
|
222 |
key = tuple(parsekey(tree)[-2:]) |
key = parsekey(tree[-2:]) |
223 |
if outputbias.has_key(key): |
if outputbias.has_key(key): |
224 |
out["bias"] = outputbias[key] |
out["bias"] = outputbias[key] |
225 |
tree[:] = tree[:-2] |
tree = tree[:-2] |
226 |
|
|
|
removeparen(tree) |
|
227 |
parseinput(tree) |
parseinput(tree) |
228 |
|
|
229 |
funcmap = { |
funcmap = { |
230 |
("in", ".", "in"): ("AB", "TRUE"), |
("in", ".", "in"): ("AB", "TRUE"), |
|
("in",): ("A", "FALSE"), |
|
231 |
("in", "*", "in"): ("AB", "FALSE"), |
("in", "*", "in"): ("AB", "FALSE"), |
232 |
|
("in",): ("A", "FALSE"), |
233 |
|
("-", "in"): ("A", "FALSE", 1), |
234 |
|
|
235 |
("in", "+", "in"): ("AC", "FALSE"), |
("in", "+", "in"): ("AC", "FALSE"), |
236 |
("in", "+", "in", "*", "in"): ("ACD", "FALSE"), |
("in", "+", "in", "*", "in"): ("ACD", "FALSE"), |
237 |
("in", "*", "in", "+", "in"): ("ABC", "FALSE"), |
("in", "*", "in", "+", "in"): ("ABC", "FALSE"), |
238 |
("in", "*", "in", "+", "in", "*", "in"): ("ABCD", "FALSE"), |
("in", "*", "in", "+", "in", "*", "in"): ("ABCD", "FALSE"), |
239 |
|
("-", "in", "+", "in"): ("AC", "FALSE", 1), |
240 |
|
("-", "in", "+", "in", "*", "in"): ("ACD", "FALSE", 1), |
241 |
|
("in", "-", "in"): ("AC", "FALSE", 2), |
242 |
|
("in", "*", "in", "-", "in"): ("ABC", "FALSE", 1), |
243 |
|
("-", "in", "-", "in"): ("AC", "FALSE", 3), |
244 |
("in", "|", "in"): ("AC", "TRUE"), |
("in", "|", "in"): ("AC", "TRUE"), |
245 |
("in", "|", "in", "*", "in"): ("ACD", "TRUE"), |
("in", "|", "in", "*", "in"): ("ACD", "TRUE"), |
246 |
("in", "*", "in", "|", "in"): ("ABC", "TRUE"), |
("in", "*", "in", "|", "in"): ("ABC", "TRUE"), |
247 |
("in", "*", "in", "|", "in", "*", "in"): ("ABCD", "TRUE"), |
("in", "*", "in", "|", "in", "*", "in"): ("ABCD", "TRUE"), |
248 |
} |
} |
249 |
|
|
250 |
key = tuple(parsekey(tree)) |
key = parsekey(tree) |
251 |
if funcmap.has_key(key): |
if funcmap.has_key(key): |
252 |
func = funcmap[key] |
func = funcmap[key] |
253 |
regs = findregs(tree, "in") |
regs = findregs(tree, "in") |
254 |
|
neg = len(func) > 2 and func[2] |
255 |
|
|
256 |
if "C" in func[0]: |
if "C" in func[0]: |
257 |
regset = "ABCD" |
regset = "ABCD" |
267 |
|
|
268 |
for reg in regset: |
for reg in regset: |
269 |
if reg not in func[0]: |
if reg not in func[0]: |
270 |
out[reg] = "ZERO UNSIGNED_IDENTITY_NV ALPHA" |
if neg & 1: out[reg] = "ZERO EXPAND_NORMAL_NV ALPHA" |
271 |
|
else: out[reg] = "ZERO UNSIGNED_INVERT_NV ALPHA" |
272 |
|
neg >>= 1 |
273 |
else: |
else: |
274 |
print "ERROR: General combiner function", key, "not recognized" |
print "ERROR: General combiner function", key, "not recognized" |
275 |
return None |
return None |
339 |
|
|
340 |
|
|
341 |
def parseFinalCombiner(outreg, tree): |
def parseFinalCombiner(outreg, tree): |
342 |
parseinput(tree, final = 1) |
tree = parseinput([("sub",tree)], final = 1) |
343 |
|
if tree[0][0] == "sub": tree = tree[0][1] |
344 |
|
|
345 |
key = tuple(parsekey(tree)) |
key = parsekey(tree) |
346 |
|
|
347 |
if outreg == "EF": |
if outreg == "EF": |
348 |
if key != ("in", "*", "in"): |
if key != ("in", "*", "in"): |
349 |
print "ERROR: EF must be a product, got", key |
print "ERROR: EF must be a product, got", key |
350 |
return "" |
return "" |
351 |
return ("FinalCombinerInput VARIABLE_E_NV " + |
return ("FinalCombinerInputNV VARIABLE_E_NV " + |
352 |
" ".join(tree[0][1:]) + "\n" + |
" ".join(tree[0][1:]) + "\n" + |
353 |
"FinalCombinerInput VARIABLE_F_NV " + |
"FinalCombinerInputNV VARIABLE_F_NV " + |
354 |
" ".join(tree[2][1:]) + "\n") |
" ".join(tree[2][1:]) + "\n") |
355 |
elif outreg == "ALPHA": |
elif outreg == "ALPHA": |
356 |
if key != ("in",): |
if key != ("in",): |
357 |
print "ERROR: alpha must be an input mapped register, got", key |
print "ERROR: alpha must be an input mapped register, got", key |
358 |
return "" |
return "" |
359 |
return ("FinalCombinerInput VARIABLE_G_NV " + |
return ("FinalCombinerInputNV VARIABLE_G_NV " + |
360 |
" ".join(tree[0][1:]) + "\n") |
" ".join(tree[0][1:]) + "\n") |
361 |
else: |
else: |
362 |
funcmap = { |
funcmap = { |
381 |
regs[0], regs[i]) |
regs[0], regs[i]) |
382 |
return "" |
return "" |
383 |
else: |
else: |
384 |
code += ("FinalCombinerInput VARIABLE_%s_NV %s\n" |
code += ("FinalCombinerInputNV VARIABLE_%s_NV %s\n" |
385 |
% (func[i], " ".join(regs[i][1:]))) |
% (func[i], " ".join(regs[i][1:]))) |
386 |
|
|
387 |
for reg in "ABCD": |
for reg in "ABCD": |
388 |
if reg not in func: |
if reg not in func: |
389 |
code += ("FinalCombinerInput VARIABLE_%s_NV " |
code += ("FinalCombinerInputNV VARIABLE_%s_NV " |
390 |
"ZERO UNSIGNED_IDENTITY_NV ALPHA\n" % reg) |
"ZERO UNSIGNED_IDENTITY_NV ALPHA\n" % reg) |
391 |
|
|
392 |
return code |
return code |
413 |
| REGNAME . RGB_COMP |
| REGNAME . RGB_COMP |
414 |
|
|
415 |
IN = REG |
IN = REG |
416 |
|
| (REG) |
417 |
| (1 - REG) |
| (1 - REG) |
418 |
| (+REG) |
| (+REG) |
419 |
| (-REG) |
| (-REG) |
421 |
| (1 - 2 * REG) |
| (1 - 2 * REG) |
422 |
| (REG - .5) |
| (REG - .5) |
423 |
| (.5 - REG) |
| (.5 - REG) |
424 |
| 0 | .5 | 1 | (-1) | (-.5) | (-0) | (+0) | (+.5) | (+1) |
| (0) | (.5) | (1) | (-1) | (-.5) | (-0) | (+0) | (+.5) | (+1) |
|
| (IN) |
|
425 |
|
|
426 |
EXP = IN . IN |
EXP = IN . IN |
427 |
| IN |
| IN |
435 |
| IN * IN '|' IN |
| IN * IN '|' IN |
436 |
| IN * IN '|' IN * IN |
| IN * IN '|' IN * IN |
437 |
|
|
438 |
PAREN_EXP = EXP |
BIASED_EXP = EXP |
439 |
| (EXP) |
| EXP - .5 |
440 |
|
| EXP - 0 |
|
BIASED_EXP = PAREN_EXP |
|
|
| PAREN_EXP - .5 |
|
|
| PAREN_EXP - 0 |
|
441 |
|
|
442 |
OUT = BIASED_EXP |
OUT = BIASED_EXP |
443 |
| (BIASED_EXP) / 2 |
| (BIASED_EXP) / 2 |
446 |
| (BIASED_EXP) * 2 |
| (BIASED_EXP) * 2 |
447 |
| (BIASED_EXP) * 4 |
| (BIASED_EXP) * 4 |
448 |
|
|
|
|
|
449 |
FINAL_IN = REG |
FINAL_IN = REG |
450 |
| (1 - REG) |
| (1 - REG) |
451 |
| 0 | 1 |
| (0) | (1) |
452 |
| (FINAL_IN) |
|
453 |
|
FINAL_IN1 = FINAL_IN |
454 |
|
| 1 - REG |
455 |
|
| 0 | 1 |
456 |
|
|
457 |
FINAL_OUT = FINAL_IN * FINAL_IN + FINAL_IN * FINAL_IN + FINAL_IN |
FINAL_OUT = FINAL_IN * FINAL_IN + FINAL_IN * FINAL_IN + FINAL_IN |
458 |
| FINAL_IN * FINAL_IN + FINAL_IN * FINAL_IN |
| FINAL_IN * FINAL_IN + FINAL_IN * FINAL_IN |
459 |
| FINAL_IN * FINAL_IN + FINAL_IN |
| FINAL_IN * FINAL_IN + FINAL_IN |
460 |
| FINAL_IN + FINAL_IN |
| FINAL_IN + FINAL_IN |
461 |
| FINAL_IN * FINAL_IN |
| FINAL_IN * FINAL_IN |
462 |
| FINAL_IN |
| FINAL_IN1 |
463 |
|
|
464 |
FUNC = REG '=' OUT |
FUNC = REG '=' OUT |
465 |
| RGB_COMP '=' FINAL_OUT |
| RGB_COMP '=' FINAL_OUT |
466 |
| ALPHA_COMP '=' FINAL_IN |
| ALPHA_COMP '=' FINAL_IN1 |
467 |
| EF '=' FINAL_IN * FINAL_IN |
| EF '=' FINAL_IN * FINAL_IN |
468 |
| CONST0 '=' vector |
| CONST0 '=' vector |
469 |
| CONST1 '=' vector |
| CONST1 '=' vector |
472 |
# The syntax is given by FUNC above. |
# The syntax is given by FUNC above. |
473 |
# Code from lines not containing a '=' is passed through. |
# Code from lines not containing a '=' is passed through. |
474 |
# |
# |
475 |
# str The code lines separated by '\n' or ';'. '#'-comments are removed. |
# str The code lines separated by '\n' or ';'. '#'-comments are ignored |
476 |
# returns The generated code |
# returns The generated code |
477 |
# |
# |
478 |
# NUM_GENERAL_COMBINERS_NV and PER_STAGE_CONSTANTS_NV are automatically set. |
# NUM_GENERAL_COMBINERS_NV and PER_STAGE_CONSTANTS_NV are automatically set. |
479 |
# |
# |
480 |
# Semantics: |
# Semantics: |
481 |
# - A new combiner stage is started for all combiner code lines except for |
# - A new combiner stage is started (unless empty) for all lines except for |
482 |
# those adjacent "REG = OUT" assignments that can fit in the current stage. |
# those adjacent "REG = OUT" assignments that can fit in the current stage. |
483 |
# - Per stage constants are enabled unless all constant assignments are |
# - Per stage constants are enabled unless all constant assignments are |
484 |
# either before or after all general combiner register assignments |
# either before or after all general combiner register assignments |
495 |
# color = EF * FOG + (1-EF) * SPARE1 |
# color = EF * FOG + (1-EF) * SPARE1 |
496 |
# |
# |
497 |
def parseCombiner(str): |
def parseCombiner(str): |
498 |
def removeComment(line): |
def splitLine(line): |
499 |
pos = line.find("#") |
pos = line.find("#") |
500 |
if pos >= 0: return line[:pos] |
if pos >= 0: |
501 |
return line |
if line[:pos].strip(): |
502 |
|
return line[:pos].split(";") + [ line[pos:] ] |
503 |
lines = ";".join(map(removeComment,str.splitlines())).split(";") |
return [ line ] |
504 |
|
return line.split(";") |
505 |
|
|
506 |
|
lines = reduce(lambda x,y: x+y, map(splitLine, str.splitlines())) |
507 |
|
|
508 |
code = "" |
code = "" |
509 |
|
|
510 |
stage = { |
stage = { |
514 |
} |
} |
515 |
|
|
516 |
for line in lines: |
for line in lines: |
517 |
line = line.strip() |
if line.lstrip().startswith("#"): |
518 |
if not line: continue |
code += line + "\n" |
519 |
|
continue |
520 |
|
|
521 |
pos = line.find("=") |
pos = line.find("=") |
522 |
if pos == -1: |
if pos == -1: |
523 |
|
code += outputGeneralCombiner(stage) |
524 |
code += line + "\n" |
code += line + "\n" |
525 |
continue |
continue |
526 |
|
|
559 |
out = parseGeneralCombiner(outreg, right) |
out = parseGeneralCombiner(outreg, right) |
560 |
if not out: return "" |
if not out: return "" |
561 |
|
|
562 |
|
if outcomp == "BLUE": |
563 |
|
print "ERROR: cannot write only BLUE in", line |
564 |
|
return "" |
565 |
|
|
566 |
if not addStageComp(stage[outcomp], out): |
if not addStageComp(stage[outcomp], out): |
567 |
code += outputGeneralCombiner(stage) |
code += outputGeneralCombiner(stage) |
568 |
stage[outcomp] = out |
stage[outcomp] = out |