1 #include "rc1.0_general.h"
2 #include "nvparse_errors.h"
3 #include "nvparse_externs.h"
4 #include <stdio.h>
5
Validate(int numConsts,ConstColorStruct * pcc)6 void GeneralCombinersStruct::Validate(int numConsts, ConstColorStruct *pcc)
7 {
8 GLint maxGCs;
9 glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &maxGCs);
10 if (num > maxGCs) {
11 char buffer[256];
12 sprintf(buffer, "%d general combiners specified, only %d supported", num, (int)maxGCs);
13 errors.set(buffer);
14 num = maxGCs;
15 }
16
17 if (0 == num) {
18 // Setup a "fake" general combiner 0
19 general[0].ZeroOut();
20 num = 1;
21 }
22
23 localConsts = 0;
24 int i;
25 for (i = 0; i < num; i++)
26 localConsts += general[i].numConsts;
27
28 if (localConsts > 0)
29 {
30 if (NULL == glCombinerStageParameterfvNV)
31 errors.set("local constant(s) specified, but not supported -- ignored");
32 else
33 for (i = 0; i < num; i++)
34 general[i].SetUnusedLocalConsts(numConsts, pcc);
35 }
36
37 for (i = 0; i < num; i++)
38 general[i].Validate(i);
39
40
41 for (; i < maxGCs; i++)
42 general[i].ZeroOut();
43 }
44
Invoke()45 void GeneralCombinersStruct::Invoke()
46 {
47 glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, num);
48 int i;
49 for (i = 0; i < num; i++)
50 general[i].Invoke(i);
51
52 if (NULL != glCombinerStageParameterfvNV) {
53 if (localConsts > 0)
54 glEnable(GL_PER_STAGE_CONSTANTS_NV);
55 else
56 glDisable(GL_PER_STAGE_CONSTANTS_NV);
57 }
58
59 }
60
ZeroOut()61 void GeneralCombinerStruct::ZeroOut()
62 {
63 numPortions = 2;
64 numConsts = 0;
65
66 portion[0].ZeroOut();
67 portion[0].designator = RCP_RGB;
68 portion[1].ZeroOut();
69 portion[1].designator = RCP_ALPHA;
70 }
71
72
SetUnusedLocalConsts(int numGlobalConsts,ConstColorStruct * globalCCs)73 void GeneralCombinerStruct::SetUnusedLocalConsts(int numGlobalConsts, ConstColorStruct *globalCCs)
74 {
75 int i;
76 for (i = 0; i < numGlobalConsts; i++) {
77 bool constUsed = false;
78 int j;
79 for (j = 0; j < numConsts; j++)
80 constUsed |= (cc[j].reg.bits.name == globalCCs[i].reg.bits.name);
81 if (!constUsed)
82 cc[numConsts++] = globalCCs[i];
83 }
84 }
85
86
Validate(int stage)87 void GeneralCombinerStruct::Validate(int stage)
88 {
89 if (2 == numConsts &&
90 cc[0].reg.bits.name == cc[1].reg.bits.name)
91 errors.set("local constant set twice");
92
93 switch (numPortions)
94 {
95 case 0:
96 portion[0].designator = RCP_RGB;
97 // Fallthru
98 case 1:
99 portion[1].designator = ((RCP_RGB == portion[0].designator) ? RCP_ALPHA : RCP_RGB);
100 // Fallthru
101 case 2:
102 if (portion[0].designator == portion[1].designator)
103 errors.set("portion declared twice");
104 break;
105 }
106 int i;
107 for (i = 0; i < numPortions; i++)
108 portion[i].Validate(stage);
109
110 for (; i < 2; i++)
111 portion[i].ZeroOut();
112
113 }
114
Invoke(int stage)115 void GeneralCombinerStruct::Invoke(int stage)
116 {
117 int i;
118
119 if (NULL != glCombinerStageParameterfvNV)
120 for (i = 0; i < numConsts; i++)
121 glCombinerStageParameterfvNV(GL_COMBINER0_NV + stage, cc[i].reg.bits.name, &(cc[i].v[0]));
122
123 for (i = 0; i < 2; i++)
124 portion[i].Invoke(stage);
125 }
126
Validate(int stage)127 void GeneralPortionStruct::Validate(int stage)
128 {
129 gf.Validate(stage, designator);
130 }
131
Invoke(int stage)132 void GeneralPortionStruct::Invoke(int stage)
133 {
134 gf.Invoke(stage, designator, bs);
135 }
136
ZeroOut()137 void GeneralPortionStruct::ZeroOut()
138 {
139 gf.ZeroOut();
140 bs.word = RCP_SCALE_BY_ONE;
141 }
142
ZeroOut()143 void GeneralFunctionStruct::ZeroOut()
144 {
145 // Create mapped registers for zero and discard
146 MappedRegisterStruct unsignedZero;
147 RegisterEnum zero;
148 zero.word = RCP_ZERO;
149 unsignedZero.Init(zero);
150
151 MappedRegisterStruct unsignedDiscard;
152 RegisterEnum discard;
153 discard.word = RCP_DISCARD;
154 unsignedDiscard.Init(discard);
155
156 numOps = 3;
157
158 op[0].op = RCP_MUL;
159 op[0].reg[0] = unsignedDiscard;
160 op[0].reg[1] = unsignedZero;
161 op[0].reg[2] = unsignedZero;
162
163 op[1].op = RCP_MUL;
164 op[1].reg[0] = unsignedDiscard;
165 op[1].reg[1] = unsignedZero;
166 op[1].reg[2] = unsignedZero;
167
168 op[2].op = RCP_SUM;
169 op[2].reg[0] = unsignedDiscard;
170
171 }
172
Validate(int stage,int portion)173 void GeneralFunctionStruct::Validate(int stage, int portion)
174 {
175 int i;
176 for (i = 0; i < numOps; i++)
177 op[i].Validate(stage, portion);
178 // Check if multiple ops are writing to same register (and it's not DISCARD)
179 if (numOps > 1 &&
180 op[0].reg[0].reg.bits.name == op[1].reg[0].reg.bits.name &&
181 GL_DISCARD_NV != op[0].reg[0].reg.bits.name)
182 errors.set("writing to same register twice");
183 if (numOps > 2 &&
184 (op[0].reg[0].reg.bits.name == op[2].reg[0].reg.bits.name ||
185 op[1].reg[0].reg.bits.name == op[2].reg[0].reg.bits.name) &&
186 GL_DISCARD_NV != op[2].reg[0].reg.bits.name)
187 errors.set("writing to same register twice");
188
189 // Set unused outputs to discard, unused inputs to zero/unsigned_identity
190 if (numOps < 2) {
191 // Set C input to zero
192 op[1].reg[1].reg.bits.name = GL_ZERO;
193 op[1].reg[1].map = GL_UNSIGNED_IDENTITY_NV;
194 op[1].reg[1].reg.bits.channel = portion;
195
196 // Set D input to zero
197 op[1].reg[2].reg.bits.name = GL_ZERO;
198 op[1].reg[2].map = GL_UNSIGNED_IDENTITY_NV;
199 op[1].reg[2].reg.bits.channel = portion;
200
201 // Discard CD output
202 op[1].op = false;
203 op[1].reg[0].reg.bits.name = GL_DISCARD_NV;
204 }
205
206 if (numOps < 3) {
207 // Discard muxSum output
208 op[2].reg[0].reg.bits.name = GL_DISCARD_NV;
209 op[2].op = RCP_SUM;
210 }
211 }
212
213
Invoke(int stage,int portion,BiasScaleEnum bs)214 void GeneralFunctionStruct::Invoke(int stage, int portion, BiasScaleEnum bs)
215 {
216 GLenum portionEnum = (RCP_RGB == portion) ? GL_RGB : GL_ALPHA;
217
218 glCombinerInputNV(GL_COMBINER0_NV + stage,
219 portionEnum,
220 GL_VARIABLE_A_NV,
221 op[0].reg[1].reg.bits.name,
222 op[0].reg[1].map,
223 MAP_CHANNEL(op[0].reg[1].reg.bits.channel));
224
225 glCombinerInputNV(GL_COMBINER0_NV + stage,
226 portionEnum,
227 GL_VARIABLE_B_NV,
228 op[0].reg[2].reg.bits.name,
229 op[0].reg[2].map,
230 MAP_CHANNEL(op[0].reg[2].reg.bits.channel));
231
232 glCombinerInputNV(GL_COMBINER0_NV + stage,
233 portionEnum,
234 GL_VARIABLE_C_NV,
235 op[1].reg[1].reg.bits.name,
236 op[1].reg[1].map,
237 MAP_CHANNEL(op[1].reg[1].reg.bits.channel));
238
239 glCombinerInputNV(GL_COMBINER0_NV + stage,
240 portionEnum,
241 GL_VARIABLE_D_NV,
242 op[1].reg[2].reg.bits.name,
243 op[1].reg[2].map,
244 MAP_CHANNEL(op[1].reg[2].reg.bits.channel));
245
246 glCombinerOutputNV(GL_COMBINER0_NV + stage,
247 portionEnum,
248 op[0].reg[0].reg.bits.name,
249 op[1].reg[0].reg.bits.name,
250 op[2].reg[0].reg.bits.name,
251 bs.bits.scale,
252 bs.bits.bias,
253 op[0].op,
254 op[1].op,
255 (op[2].op == RCP_MUX) ? true : false);
256 }
257
258 // This helper function assigns a channel to an undesignated input register
ConvertRegister(RegisterEnum & reg,int portion)259 static void ConvertRegister(RegisterEnum& reg, int portion)
260 {
261 if (RCP_NONE == reg.bits.channel) {
262 reg.bits.channel = portion;
263 if (GL_FOG == reg.bits.name && RCP_ALPHA == portion)
264 // Special case where fog alpha is final only, but RGB is not
265 reg.bits.finalOnly = true;
266 }
267 }
268
269
Validate(int stage,int portion)270 void OpStruct::Validate(int stage, int portion)
271 {
272 int args = 1;
273
274 if (RCP_DOT == op || RCP_MUL == op)
275 args = 3;
276 else
277 args = 1;
278
279 if (reg[0].reg.bits.readOnly)
280 errors.set("writing to a read-only register");
281
282 if (RCP_ALPHA == portion &&
283 RCP_DOT == op)
284 errors.set("dot used in alpha portion");
285 int i;
286 for (i = 0; i < args; i++) {
287 ConvertRegister(reg[i].reg, portion);
288 if (reg[i].reg.bits.finalOnly)
289 errors.set("final register used in general combiner");
290 if (RCP_RGB == portion &&
291 RCP_BLUE == reg[i].reg.bits.channel)
292 errors.set("blue register used in rgb portion");
293 if (RCP_ALPHA == portion &&
294 RCP_RGB == reg[i].reg.bits.channel)
295 errors.set("rgb register used in alpha portion");
296 if (i > 0 &&
297 GL_DISCARD_NV == reg[i].reg.bits.name)
298 errors.set("reading from discard");
299 }
300 }
301