/[gzz]/gzz/gfx/libutil/nvcode.py
ViewVC logotype

Diff of /gzz/gfx/libutil/nvcode.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.3 by jvk, Tue Oct 29 16:34:04 2002 UTC revision 1.4 by jvk, Fri Nov 22 08:41:27 2002 UTC
# Line 34  def combinerscale(x): Line 34  def combinerscale(x):
34      elif x < 1.5: return "NONE"      elif x < 1.5: return "NONE"
35      elif x < 3: return "SCALE_BY_TWO_NV"      elif x < 3: return "SCALE_BY_TWO_NV"
36      return "SCALE_BY_FOUR_NV"      return "SCALE_BY_FOUR_NV"
37    
38    
39    def matchop(str,i):
40        def opchar(str, i):
41            return i < len(str) and str[i] in [ "*", "/", "+", "-", ".", "|" ]
42        if opchar(str, i): return i + 1
43        return 0
44    
45    def matchid(str, i):
46        def idchar(str, i):
47            return i < len(str) and ("0" <= str[i] <= "9" or
48                                     "A" <= str[i] <= "Z" or
49                                     "a" <= str[i] <= "z" or
50                                     str[i] == "_")
51        if not idchar(str, i): return 0
52        while idchar(str, i): i += 1
53        return i
54    
55    def matchnum(str, i):
56        if (i < len(str) and "0" <= str[i] <= "9") or (
57            i + 1 < len(str) and str[i] == "." and  "0" <= str[i + 1] <= "9"):
58            while i < len(str) and (str[i] == "." or "0" <= str[i] <= "9"): i += 1
59            return i
60        return 0
61    
62    def exptree(exp, i):
63        if i == len(exp): return ([], i)
64    
65        if exp[i] in [" ", "\t"]:
66            return exptree(exp, i + 1)
67        elif exp[i] == "(":
68            (subtree, pos) = exptree(exp, i + 1)
69            car = ("sub", subtree)
70            if pos == len(exp):
71                print "WARNING: Missing closing parenthesis"
72            else:
73                pos += 1
74        elif exp[i] == ")":
75            return ([], i)
76        else:
77            pos = matchnum(exp, i)
78            if pos:
79                car = (float(exp[i:pos]),)
80            else:
81                pos = matchid(exp, i)
82                if pos:
83                    car = ("id", exp[i:pos])
84                else:
85                    pos = matchop(exp, i)
86    
87                    if pos:
88                        car = (exp[i:pos],)
89                    else:
90                        return ([], i)
91            
92        (cdr,i) = exptree(exp, pos)
93    
94        return ([car] + cdr,i)
95    
96    
97    def printtree(tree, pre = ""):
98        for node in tree:
99            if node[0] == "sub":
100                printtree(node[1], pre + "> ")
101            else:
102                if len(node) == 1: node = node[0]
103                print pre + str(node)
104    
105    def parsecomp(name):
106        if name in ["a", "alpha"]: return "ALPHA"
107        if name in ["b", "blue"]: return "BLUE"
108        if name in ["rgb", "color", "col"]: return "RGB"
109        return None
110    
111    def parseregs(tree):
112        regmap = {
113            "COL0": "PRIMARY_COLOR_NV",
114            "COL1": "SECONDARY_COLOR_NV",
115            "TEX0": "TEXTURE0",
116            "TEX1": "TEXTURE1",
117            "TEX2": "TEXTURE2",
118            "TEX3": "TEXTURE3",
119            "SPARE0": "SPARE0_NV",
120            "SPARE1": "SPARE1_NV",
121            "FOG": "FOG",
122            "CONST0": "CONSTANT_COLOR0_NV",
123            "CONST1": "CONSTANT_COLOR1_NV",
124            "ZERO": "ZERO",
125            "EF": "E_TIMES_F_NV",
126            "SPARE0_PLUS_COL1" : "SPARE0_PLUS_SECONDARY_COLOR_NV",
127            }
128    
129        i = 0
130        while i < len(tree):
131            node = tree[i]
132            if node[0] == "sub":
133                parseregs(node[1])
134            else:
135                if node[0] == "id" and regmap.has_key(node[1]):
136                    if (i + 2 < len(tree) and
137                        tree[i+1] == (".",) and
138                        tree[i+2][0] == "id" and
139                        parsecomp(tree[i+2][1])):
140                        tree[i:i+3] = [("reg", regmap[node[1]],
141                                        parsecomp(tree[i+2][1]))]
142                    else:
143                        tree[i:i+1] = [("reg", regmap[node[1]], "RGB")]
144            i += 1
145            
146    def findregs(list, type = "reg"):
147        indlist = []
148        for i in range(0,len(list)):
149            if list[i] == type: indlist.append(i)
150        return indlist
151    
152    def parseinput(tree):
153        inputmap = {
154            ("+", "reg"): "SIGNED_IDENTITY_NV",
155            ("reg",): "UNSIGNED_IDENTITY_NV",
156            (2, "reg", "-", 1): "EXPAND_NORMAL_NV",
157            (2, "*", "reg", "-", 1): "EXPAND_NORMAL_NV",
158            ("reg", "-", .5): "HALF_BIAS_NORMAL_NV",
159            ("-", "reg"): "SIGNED_NEGATE_NV",
160            (1, "-", "reg"): "UNSIGNED_INVERT_NV",
161            (1, "-", 2, "reg"): "EXPAND_NEGATE_NV",
162            (1, "-", 2, "*", "reg"): "EXPAND_NEGATE_NV",
163            (.5, "-", "reg"): "HALF_BIAS_NEGATE"
164            }
165    
166        key = tuple(map(lambda node: node[0], tree))
167        
168        if inputmap.has_key(key):
169            i = findregs(key)[0]
170            tree[:] = [("in", tree[i][1], inputmap[key], tree[i][2])]
171        else:
172            for i in range(0,len(tree)):
173                if tree[i][0] == "sub":
174                    parseinput(tree[i][1])
175                    if len(tree[i][1]) == 1:
176                        tree[i] = tree[i][1][0]
177                elif tree[i][0] == "reg":
178                    tree[i] = ("in", tree[i][1], inputmap["reg",], tree[i][2])
179    
180    def setcheck(hash, name, value):
181        if hash.has_key(name):
182            if hash[name] != value:
183                print "ERROR: Incompatible <" + name + ">'s"
184                return 0
185        else:
186            hash[name] = value
187        return 1
188    
189    def parseoutput(tree, out, outreg = "OUTREG"):
190    
191        scale = "NONE"
192        bias = "NONE"
193    
194        outputscale = {
195            ("*", .5): "SCALE_BY_ONE_HALF_NV",
196            ("/", 2): "SCALE_BY_ONE_HALF_NV",
197            ("*", 1): "NONE",
198            ("*", 2): "SCALE_BY_TWO_NV",
199            ("*", 4): "SCALE_BY_FOUR_NV"
200            }
201        outputbias = {
202            ("-", .5): "BIAS_BY_NEGATIVE_ONE_HALF_NV",
203            }
204        
205        l = map(lambda node: node[0], tree)
206        if len(l) >= 2:
207            key = tuple(l[1:])
208            if outputscale.has_key(key):
209                scale = outputscale[key]
210                tree[:] = tree[:-2]
211                if len(tree) == 1 and tree[0][0] == "sub":
212                    tree[:] = tree[0][1]
213    
214        l = map(lambda node: node[0], tree)
215        if len(l) >= 2:
216            key = tuple(l[-2:])
217            if outputbias.has_key(key):
218                bias = outputbias[key]
219                tree[:] = tree[:-2]
220    
221        setcheck(out, "bias", bias)
222        setcheck(out, "scale", scale)
223    
224        funcmap1 = {
225            ("in", ".", "in"): ("AB", "TRUE"),
226            ("in",): ("A", "FALSE"),
227            ("in", "*", "in"): ("AB", "TRUE"),
228            }
229        
230        funcmap2 = {
231            ("in", "+", "in"): ("AC", "FALSE"),
232            ("in", "+", "in", "*", "in"): ("ACD", "FALSE"),
233            ("in", "*", "in", "+", "in"): ("ABC", "FALSE"),
234            ("in", "*", "in", "+", "in", "*", "in"): ("ABCD", "FALSE"),
235            ("in", "|", "in"): ("AC", "TRUE"),
236            ("in", "|", "in", "*", "in"): ("ACD", "TRUE"),
237            ("in", "*", "in", "|", "in"): ("ABC", "TRUE"),
238            ("in", "*", "in", "|", "in", "*", "in"): ("ABCD", "TRUE"),
239            }
240    
241        key = tuple(map(lambda node: node[0], tree))
242        if funcmap1.has_key(key):
243            func = funcmap1[key]
244            regs = findregs(key, "in")
245    
246            foo = [ " ".join(tree[reg][1:]) for reg in regs ]
247            if len(foo) == 1: foo += ["ZERO UNSIGNED_IDENTITY_NV ALPHA"]
248    
249            if (out.has_key("A") and out["A"] != foo[0] or
250                out.has_key("B") and out["B"] != foo[1] or
251                out.has_key("abDot") and out["abDot"] != func[1] or
252                out.has_key("abOut")):
253                setcheck(out, "C", foo[0])
254                setcheck(out, "D", foo[1])
255                setcheck(out, "cdDot", func[1])
256                setcheck(out, "cdOut", outreg)
257            else:
258                setcheck(out, "A", foo[0])
259                setcheck(out, "B", foo[1])
260                setcheck(out, "abDot", func[1])
261                setcheck(out, "abOut", outreg)
262            
263        elif funcmap2.has_key(key):
264            func = funcmap2[key]
265            regs = findregs(key, "in")
266    
267            for i in range(0,len(regs)):
268                setcheck(out, func[0][i], " ".join(tree[regs[i]][1:]))
269    
270            for name in "ABCD":
271                if name not in func[0]:
272                    setcheck(out, name, "ZERO UNSIGNED_IDENTITY_NV ALPHA")
273    
274            setcheck(out, "sumOut", outreg)
275            setcheck(out, "muxSum", func[1])
276        else:
277            print "Function not recognized"
278            printtree(tree)
279            return 0
280    
281        return 1
282    
283    # Parse general combiner stage code from lines such as
284    #   SPARE0 = (COL0 . COL1 - .5) * 2
285    #   SPARE1 = (CONST0 * (1 - COL0) - .5) * 2
286    #   SPARE0.alpha = (1 - 2 * COL0.alpha) + COL1.blue
287    def parseGeneralCombiner(lines, stage = 0):
288        out = {
289            "RGB": {},
290            "ALPHA": {}
291            }
292        
293        for line in lines:
294            mid = line.find("=")
295            if mid == -1:
296                print "ERROR: '=' not found:", line
297                return ""
298            
299            (left, lend) = exptree(line, 0)
300            (right, rend) = exptree(line, mid + 1)
301            if lend < mid:
302                print "ERROR: extra input:", line[lend:mid]
303                return ""
304            if rend < len(line):
305                print "ERROR: extra input:", line[rend:]
306                return ""
307            
308            parseregs(left)
309            parseregs(right)
310            
311            if len(left) != 1 or left[0][0] != "reg":
312                print "ERROR: left side not a register:"
313                printtree(left)
314                return ""
315    
316            outreg = left[0][1]
317            outcomp = left[0][2]
318    
319            parseinput(right)
320            if not parseoutput(right, out[outcomp], outreg):
321                return ""
322    
323        code = "".join(map(lambda x: "# " + x + "\n", lines))
324        for comp in "RGB", "ALPHA":
325            if out[comp]:
326                for var in "A", "B", "C", "D":
327                    if out[comp].has_key(var):
328                        code += (
329                            "CombinerInputNV COMBINER%s_NV %s VARIABLE_%s_NV %s\n"
330                            % (stage, comp, var, out[comp][var]))
331    
332                code += (
333                    "CombinerOutputNV COMBINER%s_NV %s %s %s %s %s %s %s %s %s\n"
334                    % (stage, comp,
335                       out[comp].get("abOut", "DISCARD_NV"),
336                       out[comp].get("cdOut", "DISCARD_NV"),
337                       out[comp].get("sumOut", "DISCARD_NV"),
338                       out[comp]["scale"],
339                       out[comp]["bias"],
340                       out[comp].get("abDot", "FALSE"),
341                       out[comp].get("cdDot", "FALSE"),
342                       out[comp].get("muxSum", "FALSE"),
343                       )
344                    )
345    
346        return code
347    
348    
349    # Parse final combiner code from lines such as
350    #   alpha = 1-SPARE0
351    #   EF = COL0 * (1 - COL1.alpha)
352    #   color = EF * FOG + (1-EF) * SPARE1
353    def parseFinalCombiner(lines):
354        code = "".join(map(lambda x: "# " + x + "\n", lines))
355        for line in lines:
356            mid = line.find("=")
357            if mid == -1:
358                print "ERROR: '=' not found:", line
359                return ""
360            
361            (left, lend) = exptree(line, 0)
362            (right, rend) = exptree(line, mid + 1)
363            if lend < mid:
364                print "ERROR: extra input:", line[lend:mid]
365                return ""
366            if rend < len(line):
367                print "ERROR: extra input:", line[rend:]
368                return ""
369    
370            outreg = None
371            if len(left) == 1 and left[0][0] == "id":
372                if left[0][1] == "EF":
373                    outreg = "EF"
374                else:
375                    outreg = parsecomp(left[0][1])
376    
377            if outreg not in ["EF", "RGB", "ALPHA"]:
378                print "ERROR: left side must be EF, color, or alpha:"
379                printtree(left)
380                return ""
381    
382            parseregs(right)
383            parseinput(right)
384    
385            key = tuple(map(lambda node: node[0], right))
386    
387            if outreg == "EF":
388                if key != ("in", "*", "in"):
389                    print "ERROR: EF must be a product"
390                    printtree(right)
391                    return ""
392                code += ("FinalCombinerInput VARIABLE_E_NV " +
393                         " ".join(right[0][1:]) + "\n" +
394                         "FinalCombinerInput VARIABLE_F_NV " +
395                         " ".join(right[2][1:]) + "\n")
396            elif outreg == "ALPHA":
397                if key != ("in",):
398                    print "ERROR: alpha must be an input mapped register"
399                    printtree(right)
400                    return ""
401                code += ("FinalCombinerInput VARIABLE_G_NV " +
402                         " ".join(right[0][1:]) + "\n")
403            else:
404                funcmap = {
405                    ("in", "*", "in", "+", "in", "*", "in", "+", "in"): "ABACD",
406                    ("in", "*", "in", "+", "in", "*", "in"): "ABAC",
407                    ("in", "*", "in"): "AB",
408                    ("in"): "D",
409                    }
410                if funcmap.has_key(key):
411                    func = funcmap[key]
412                    regs = findregs(key, "in")
413    
414                    for i in range(0,len(regs)):
415                        inreg = [foo for foo in right[regs[i]][1:]]
416                        
417                        if i > 0 and func[i] == "A":
418                            if inreg[1] == "UNSIGNED_IDENTITY_NV":
419                                inreg[1] = "UNSIGNED_INVERT_NV"
420                            if inreg[1] ==  "UNSIGNED_INVERT_NV":
421                                inreg[1] = "UNSIGNED_IDENTITY_NV"
422                            if inreg[1] != right[0][2] or inreg[0] != right[0][1]:
423                                print "ERROR: inconsistent A variables"
424                                printtree(right)
425                                return ""
426                        else:
427                            code += ("FinalCombinerInput VARIABLE_%s_NV %s\n"
428                                     % (func[i], " ".join(inreg)))
429    
430                    for reg in "ABCD":
431                        if reg not in func:
432                            code += ("FinalCombinerInput VARIABLE_%s_NV "
433                                     "ZERO UNSIGNED_IDENTITY_NV ALPHA\n" % reg)
434    
435        return code
436        

Legend:
Removed from v.1.3  
changed lines
  Added in v.1.4

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26