Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/RenderSystems/GL/src/nvparse/rc1.0_general.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 7.3 KB
Line 
1#include "rc1.0_general.h"
2#include "nvparse_errors.h"
3#include "nvparse_externs.h"
4#include <stdio.h>
5
6#include <OgreGLPrerequisites.h>
7
8void GeneralCombinersStruct::Validate(int numConsts, ConstColorStruct *pcc)
9{
10        GLint maxGCs;
11        glGetIntegerv(GL_MAX_GENERAL_COMBINERS_NV, &maxGCs);
12        if (num > maxGCs) {
13                char buffer[256];
14                sprintf(buffer, "%d general combiners specified, only %d supported", num, (int)maxGCs);
15                errors.set(buffer);
16                num = maxGCs;
17        }
18
19        if (0 == num) {
20                // Setup a "fake" general combiner 0
21                general[0].ZeroOut();
22                num = 1;
23        }
24
25        localConsts = 0;
26        int i;
27        for (i = 0; i < num; i++)
28                localConsts += general[i].numConsts;
29
30        if (localConsts > 0)
31                if (NULL == glCombinerStageParameterfvNV)
32                        errors.set("local constant(s) specified, but not supported -- ignored");
33                else
34                        for (i = 0; i < num; i++)
35                                general[i].SetUnusedLocalConsts(numConsts, pcc);
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
45void 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
61void 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
73void 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
87void 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
115void 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
127void GeneralPortionStruct::Validate(int stage)
128{
129        gf.Validate(stage, designator);
130}
131
132void GeneralPortionStruct::Invoke(int stage)
133{
134        gf.Invoke(stage, designator, bs);
135}
136
137void GeneralPortionStruct::ZeroOut()
138{
139        gf.ZeroOut();
140        bs.word = RCP_SCALE_BY_ONE;
141}
142
143void 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
173void 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
214void 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
259static 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
270void 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}
Note: See TracBrowser for help on using the repository browser.