Arachnoid GLESv1.1 plugin. Compile and run (a bit glitchy and no frameskip) on the...
[mupen64plus-pandora.git] / source / mupen64plus-video-arachnoid / src / Combiner / AdvancedTexEnvCombiner.cpp
CommitLineData
22726e4d 1/******************************************************************************
2 * Arachnoid Graphics Plugin for Mupen64Plus
3 * http://bitbucket.org/wahrhaft/mupen64plus-video-arachnoid/
4 *
5 * Copyright (C) 2007 Kristofer Karlsson, Rickard Niklasson
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *****************************************************************************/
21
22#include <algorithm>
23using std::max;
24#include "AdvancedTexEnvCombiner.h"
25#include "CombinerStructs.h"
26#include "MultiTexturingExt.h" //glActiveTextureARB
27#include "ExtensionChecker.h"
28
29#ifndef GL_ATI_texture_env_combine3
30#define GL_ATI_texture_env_combine3
31 #define GL_ATI_texture_env_combine3
32 #define GL_MODULATE_ADD_ATI 0x8744
33 #define GL_MODULATE_SIGNED_ADD_ATI 0x8745
34 #define GL_MODULATE_SUBTRACT_ATI 0x8746
35#endif //GL_ATI_texture_env_combine3
36
37#ifndef GL_ATIX_texture_env_route
38#define GL_ATIX_texture_env_route 1
39 #define GL_SECONDARY_COLOR_ATIX 0x8747
40 #define GL_TEXTURE_OUTPUT_RGB_ATIX 0x8748
41 #define GL_TEXTURE_OUTPUT_ALPHA_ATIX 0x8749
42#endif // GL_ATIX_texture_env_route
43
44static TexEnvCombinerArg TexEnvArgs[] =
45{
46 // CMB
47 { GL_PREVIOUS_ARB, GL_SRC_COLOR },
48 // T0
49 { GL_TEXTURE, GL_SRC_COLOR },
50 // T1
51 { GL_TEXTURE, GL_SRC_COLOR },
52 // PRIM
53 { GL_CONSTANT_ARB, GL_SRC_COLOR },
54 // SHADE
55 { GL_PRIMARY_COLOR_ARB, GL_SRC_COLOR },
56 // ENV
57 { GL_CONSTANT_ARB, GL_SRC_COLOR },
58 // CENTER
59 { GL_CONSTANT_ARB, GL_SRC_COLOR },
60 // SCALE
61 { GL_CONSTANT_ARB, GL_SRC_COLOR },
62 // CMBALPHA
63 { GL_PREVIOUS_ARB, GL_SRC_ALPHA },
64 // T0ALPHA
65 { GL_TEXTURE, GL_SRC_ALPHA },
66 // T1ALPHA
67 { GL_TEXTURE, GL_SRC_ALPHA },
68 // PRIMALPHA
69 { GL_CONSTANT_ARB, GL_SRC_ALPHA },
70 // SHADEALPHA
71 { GL_PRIMARY_COLOR_ARB, GL_SRC_ALPHA },
72 // ENVALPHA
73 { GL_CONSTANT_ARB, GL_SRC_COLOR },
74 // LODFRAC
75 { GL_CONSTANT_ARB, GL_SRC_COLOR },
76 // PRIMLODFRAC
77 { GL_CONSTANT_ARB, GL_SRC_COLOR },
78 // NOISE
79 { GL_TEXTURE, GL_SRC_COLOR },
80 // K4
81 { GL_CONSTANT_ARB, GL_SRC_COLOR },
82 // K5
83 { GL_CONSTANT_ARB, GL_SRC_COLOR },
84 // ONE
85 { GL_CONSTANT_ARB, GL_SRC_COLOR },
86 // ZERO
87 { GL_CONSTANT_ARB, GL_SRC_COLOR }
88};
89
90//-----------------------------------------------------------------------------
91//! Constructor
92//-----------------------------------------------------------------------------
93AdvancedTexEnvCombiner::AdvancedTexEnvCombiner()
94{
95}
96
97//-----------------------------------------------------------------------------
98//! Destructor
99//-----------------------------------------------------------------------------
100AdvancedTexEnvCombiner::~AdvancedTexEnvCombiner()
101{
102}
103
104//-----------------------------------------------------------------------------
105//* Initialize
106//! Checks if extensions are supported
107//-----------------------------------------------------------------------------
108void AdvancedTexEnvCombiner::initialize()
109{
110#ifdef HAVE_GLES
111 ARB_texture_env_combine = true;
112 ARB_texture_env_crossbar = true;
113#else
114 ARB_texture_env_combine = isExtensionSupported( "GL_ARB_texture_env_combine" );
115 ARB_texture_env_crossbar = isExtensionSupported( "GL_ARB_texture_env_crossbar" );
116#endif
117 ATI_texture_env_combine3 = isExtensionSupported( "GL_ATI_texture_env_combine3" );
118 ATIX_texture_env_route = isExtensionSupported( "GL_ATIX_texture_env_route" );
119 NV_texture_env_combine4 = isExtensionSupported( "GL_NV_texture_env_combine4" );;
120
121 if ( ARB_texture_env_crossbar || NV_texture_env_combine4 || ATIX_texture_env_route )
122 {
123 TexEnvArgs[TEXEL0].source = GL_TEXTURE0_ARB;
124 TexEnvArgs[TEXEL0_ALPHA].source = GL_TEXTURE0_ARB;
125 TexEnvArgs[TEXEL1].source = GL_TEXTURE1_ARB;
126 TexEnvArgs[TEXEL1_ALPHA].source = GL_TEXTURE1_ARB;
127 }
128
129 if ( ATI_texture_env_combine3 )
130 {
131 TexEnvArgs[ONE].source = GL_ONE;
132 TexEnvArgs[ZERO].source = GL_ZERO;
133 }
134}
135
136//-----------------------------------------------------------------------------
137//* Begin Texture Update
138//! Disables all textures
139//-----------------------------------------------------------------------------
140void AdvancedTexEnvCombiner::beginTextureUpdate()
141{
142 const int openGLMaxTextureUnits = 8;
143
144 //Disable all texture channels
145 for (int i = 0; i <openGLMaxTextureUnits; i++)
146 {
147 glActiveTextureARB(GL_TEXTURE0_ARB + i);
148 glDisable(GL_TEXTURE_2D );
149 }
150}
151
152
153//-----------------------------------------------------------------------------
154//* End Texture Update
155//! Enables selected textures in a texture environment
156//! @param texEnv Texture environment with textures to be enabled
157//-----------------------------------------------------------------------------
158void AdvancedTexEnvCombiner::endTextureUpdate(TexEnvCombiner* texEnv)
159{
160 //Enable texturing
161 for (int i = 0; i <texEnv->usedUnits; i++)
162 {
163 glActiveTextureARB( GL_TEXTURE0_ARB + i );
164 glEnable( GL_TEXTURE_2D );
165 }
166}
167
168//-----------------------------------------------------------------------------
169//* Set Texture Enviroment Colors
170//! Sets texture enviorment colors for all active textures
171//! @param texEnv Texture environment with textures that will be assigned colors
172//-----------------------------------------------------------------------------
173void AdvancedTexEnvCombiner::setTextureEnviromentColors(TexEnvCombiner* texEnv)
174{
175 float color[4];
176
177 int openGLMaxTextureUnits = 8;
178
179 for (int i = 0; i < openGLMaxTextureUnits; i++)
180 {
181 this->getCombinerColor( color, texEnv->color[i].constant, texEnv->alpha[i].constant );
182
183 glActiveTextureARB(GL_TEXTURE0_ARB + i);
184 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color[0]);
185 }
186}
187
188//-----------------------------------------------------------------------------
189//* Set Texture Enviroment
190//! Sets texture environment for all active textures
191//! @param texEnv Texture environment with input data which will be
192//! sent to OpenGL using function "glTexEnvi" using ARB extensions
193//-----------------------------------------------------------------------------
194void AdvancedTexEnvCombiner::setTextureEnviroment(TexEnvCombiner* texEnv)
195{
196 const int openGLMaxTextureUnits = 8;
197
198 for (int i=0; i<openGLMaxTextureUnits; ++i)
199 {
200 glActiveTextureARB(GL_TEXTURE0_ARB + i);
201
202 if ( (i < texEnv->usedUnits ) || (i < 2 && texEnv->usesT1) )
203 {
204 glEnable( GL_TEXTURE_2D );
205 glTexEnvi( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB );
206 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, texEnv->color[i].combine );
207 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, texEnv->color[i].arg0.source );
208 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, texEnv->color[i].arg0.operand );
209 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_RGB_ARB, texEnv->color[i].arg1.source );
210 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_RGB_ARB, texEnv->color[i].arg1.operand );
211 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, texEnv->color[i].arg2.source );
212 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_RGB_ARB, texEnv->color[i].arg2.operand );
213 glTexEnvi( GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, texEnv->alpha[i].combine );
214 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, texEnv->alpha[i].arg0.source );
215 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, texEnv->alpha[i].arg0.operand );
216 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, texEnv->alpha[i].arg1.source );
217 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, texEnv->alpha[i].arg1.operand );
218 glTexEnvi( GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_ARB, texEnv->alpha[i].arg2.source );
219 glTexEnvi( GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_ARB, texEnv->alpha[i].arg2.operand );
220 }
221 else
222 {
223 glDisable(GL_TEXTURE_2D);
224 }
225 }
226}
227
228//-----------------------------------------------------------------------------
229//* Create New Texture Enviornment
230//! Allocates a new texture enviroment
231//! @param[in] colorCombiner How to combine and get a color
232//! @param[in] alphaCombiner How to combine and get an alpha value
233//! @return The texture enviroment that was created
234//-----------------------------------------------------------------------------
235TexEnvCombiner* AdvancedTexEnvCombiner::createNewTextureEnviroment(Combiner* colorCombiner, Combiner *alphaCombiner)
236{
237 TexEnvCombiner* envCombiner = new TexEnvCombiner();
238
239 int curUnit;
240
241 const int openGLMaxTextureUnits = 8;
242
243 //For each texture unit
244 for (int i = 0; i < openGLMaxTextureUnits; i++)
245 {
246 envCombiner->color[i].combine = GL_REPLACE;
247 envCombiner->alpha[i].combine = GL_REPLACE;
248
249 SetColorCombinerValues( i, arg0, GL_PREVIOUS_ARB, GL_SRC_COLOR );
250 SetColorCombinerValues( i, arg1, GL_PREVIOUS_ARB, GL_SRC_COLOR );
251 SetColorCombinerValues( i, arg2, GL_PREVIOUS_ARB, GL_SRC_COLOR );
252 envCombiner->color[i].constant = COMBINED;
253 envCombiner->color[i].outputTexture = GL_TEXTURE0_ARB + i;
254
255 SetAlphaCombinerValues( i, arg0, GL_PREVIOUS_ARB, GL_SRC_ALPHA );
256 SetAlphaCombinerValues( i, arg1, GL_PREVIOUS_ARB, GL_SRC_ALPHA );
257 SetAlphaCombinerValues( i, arg2, GL_PREVIOUS_ARB, GL_SRC_ALPHA );
258 envCombiner->alpha[i].constant = COMBINED;
259 envCombiner->alpha[i].outputTexture = GL_TEXTURE0_ARB + i;
260 }
261
262 envCombiner->usesT0 = false;
263 envCombiner->usesT1 = false;
264
265 envCombiner->vertex.color = COMBINED;
266 envCombiner->vertex.secondaryColor = COMBINED;
267 envCombiner->vertex.alpha = COMBINED;
268
269 curUnit = 0;
270
271 for (int i=0; i<alphaCombiner->numStages; i++)
272 {
273 for (int j = 0; j < alphaCombiner->stage[i].numOps; j++)
274 {
275 float sb = 0.0f;
276
277 if (alphaCombiner->stage[i].op[j].param1 == PRIMITIVE_ALPHA)
278 sb = m_primColor[3];
279 else if (alphaCombiner->stage[i].op[j].param1 == ENV_ALPHA)
280 sb = m_envColor[3];
281 else if (alphaCombiner->stage[i].op[j].param1 == ONE)
282 sb = 1.0f;
283
284 if (((alphaCombiner->stage[i].numOps - j) >= 3) &&
285 (alphaCombiner->stage[i].op[j].op == SUB) &&
286 (alphaCombiner->stage[i].op[j+1].op == MUL) &&
287 (alphaCombiner->stage[i].op[j+2].op == ADD) &&
288 (sb > 0.5f) &&
289 (ARB_texture_env_combine))
290 {
291 envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA;
292 envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA;
293
294 if (alphaCombiner->stage[i].op[j].param1 == ONE)
295 {
296 SetAlphaCombinerValues( curUnit, arg0, envCombiner->alpha[curUnit].arg0.source, GL_ONE_MINUS_SRC_ALPHA );
297 }
298 else
299 {
300 envCombiner->alpha[curUnit].combine = GL_SUBTRACT_ARB;
301 SetAlphaCombinerValues( curUnit, arg1, envCombiner->alpha[curUnit].arg0.source, GL_SRC_ALPHA );
302 SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 );
303
304 curUnit++;
305 }
306
307 j++;
308
309 envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA;
310 envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA;
311
312 envCombiner->alpha[curUnit].combine = GL_MODULATE;
313 SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 );
314
315 curUnit++;
316 j++;
317
318 envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA;
319 envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA;
320
321 envCombiner->alpha[curUnit].combine = GL_SUBTRACT_ARB;
322 SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 );
323
324 curUnit++;
325 }
326 else
327 {
328 envCombiner->usesT0 |= alphaCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA;
329 envCombiner->usesT1 |= alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA;
330
331 switch (alphaCombiner->stage[i].op[j].op)
332 {
333 case LOAD:
334 if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) &&
335 (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0))
336 curUnit++;
337
338 envCombiner->alpha[curUnit].combine = GL_REPLACE;
339
340 SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 );
341 break;
342 case SUB:
343 if (!ARB_texture_env_combine)
344 break;
345
346 if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) &&
347 (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0))
348 curUnit++;
349
350 if ((j > 0) && (alphaCombiner->stage[i].op[j-1].op == LOAD) && (alphaCombiner->stage[i].op[j-1].param1 == ONE))
351 {
352 SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 );
353 envCombiner->alpha[curUnit].arg0.operand = GL_ONE_MINUS_SRC_ALPHA;
354 }
355 else if ((ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->alpha[curUnit - 1].combine == GL_MODULATE))
356 {
357 curUnit--;
358 SetAlphaCombinerValues( curUnit, arg2, envCombiner->alpha[curUnit].arg1.source, envCombiner->alpha[curUnit].arg1.operand );
359 envCombiner->alpha[curUnit].combine = GL_MODULATE_SUBTRACT_ATI;
360 SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 );
361 curUnit++;
362 }
363 else
364 {
365 envCombiner->alpha[curUnit].combine = GL_SUBTRACT_ARB;
366 SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 );
367 curUnit++;
368 }
369 break;
370 case MUL:
371 if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) &&
372 (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0))
373 curUnit++;
374
375 envCombiner->alpha[curUnit].combine = GL_MODULATE;
376
377 SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 );
378 curUnit++;
379 break;
380 case ADD:
381 if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) &&
382 (alphaCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA) && (curUnit == 0))
383 curUnit++;
384
385 if ((ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->alpha[curUnit - 1].combine == GL_MODULATE))
386 {
387 curUnit--;
388 SetAlphaCombinerValues( curUnit, arg2, envCombiner->alpha[curUnit].arg1.source, envCombiner->alpha[curUnit].arg1.operand );
389 envCombiner->alpha[curUnit].combine = GL_MODULATE_ADD_ATI;
390 SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 );
391 }
392 else
393 {
394 envCombiner->alpha[curUnit].combine = GL_ADD;
395 SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param1 );
396 }
397 curUnit++;
398 break;
399 case INTERPOLATE:
400 envCombiner->usesT0 |= (alphaCombiner->stage[i].op[j].param2 == TEXEL0_ALPHA) || (alphaCombiner->stage[i].op[j].param3 == TEXEL0_ALPHA);
401 envCombiner->usesT1 |= (alphaCombiner->stage[i].op[j].param2 == TEXEL1_ALPHA) || (alphaCombiner->stage[i].op[j].param3 == TEXEL1_ALPHA);
402
403 envCombiner->alpha[curUnit].combine = GL_INTERPOLATE_ARB;
404
405 SetAlphaCombinerArg( curUnit, arg0, alphaCombiner->stage[i].op[j].param1 );
406 SetAlphaCombinerArg( curUnit, arg1, alphaCombiner->stage[i].op[j].param2 );
407 SetAlphaCombinerArg( curUnit, arg2, alphaCombiner->stage[i].op[j].param3 );
408
409 curUnit++;
410 break;
411 }
412 }
413 }
414 }
415
416 envCombiner->usedUnits = max( curUnit, 1 );
417
418 curUnit = 0;
419 for (int i = 0; i < colorCombiner->numStages; i++)
420 {
421 for (int j = 0; j < colorCombiner->stage[i].numOps; j++)
422 {
423 float sb = 0.0f;
424
425 if (colorCombiner->stage[i].op[j].param1 == PRIMITIVE)
426 sb = (m_primColor[0] + m_primColor[2] + m_primColor[1]) / 3.0f;
427 else if (colorCombiner->stage[i].op[j].param1 == ENVIRONMENT)
428 sb = (m_envColor[0] + m_envColor[2] + m_envColor[1]) / 3.0f;
429
430 // This helps with problems caused by not using signed values between texture units
431 if (((colorCombiner->stage[i].numOps - j) >= 3) &&
432 (colorCombiner->stage[i].op[j].op == SUB) &&
433 (colorCombiner->stage[i].op[j+1].op == MUL) &&
434 (colorCombiner->stage[i].op[j+2].op == ADD) &&
435 (sb > 0.5f) &&
436 (ARB_texture_env_combine))
437 {
438 envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA));
439 envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA));
440
441 envCombiner->color[curUnit].combine = GL_SUBTRACT_ARB;
442 SetColorCombinerValues( curUnit, arg1, envCombiner->color[curUnit].arg0.source, envCombiner->color[curUnit].arg0.operand );
443 SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 );
444
445 curUnit++;
446 j++;
447
448 envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA));
449 envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA));
450
451 envCombiner->color[curUnit].combine = GL_MODULATE;
452 SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 );
453
454 curUnit++;
455 j++;
456
457 envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA));
458 envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA));
459
460 envCombiner->color[curUnit].combine = GL_SUBTRACT_ARB;
461 SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 );
462
463 curUnit++;
464 }
465 else
466 {
467 envCombiner->usesT0 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL0) || (colorCombiner->stage[i].op[j].param1 == TEXEL0_ALPHA));
468 envCombiner->usesT1 |= ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA));
469
470 switch (colorCombiner->stage[i].op[j].op)
471 {
472 case LOAD:
473 if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) &&
474 ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0))
475 curUnit++;
476
477 envCombiner->color[curUnit].combine = GL_REPLACE;
478
479 SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 );
480 break;
481 case SUB:
482 if (!ARB_texture_env_combine)
483 break;
484
485 if (!(ARB_texture_env_crossbar || NV_texture_env_combine4) &&
486 ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0))
487 curUnit++;
488
489 if ((j > 0) && (colorCombiner->stage[i].op[j-1].op == LOAD) && (colorCombiner->stage[i].op[j-1].param1 == ONE))
490 {
491 SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 );
492 envCombiner->color[curUnit].arg0.operand = GL_ONE_MINUS_SRC_COLOR;
493 }
494 else if (( ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->color[curUnit - 1].combine == GL_MODULATE))
495 {
496 curUnit--;
497 SetColorCombinerValues( curUnit, arg2, envCombiner->color[curUnit].arg1.source, envCombiner->color[curUnit].arg1.operand );
498 envCombiner->color[curUnit].combine = GL_MODULATE_SUBTRACT_ATI;
499 SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 );
500 curUnit++;
501 }
502 else
503 {
504 envCombiner->color[curUnit].combine = GL_SUBTRACT_ARB;
505 SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 );
506 curUnit++;
507 }
508 break;
509 case MUL:
510 if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) &&
511 ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0))
512 curUnit++;
513
514 envCombiner->color[curUnit].combine = GL_MODULATE;
515
516 SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 );
517 curUnit++;
518 break;
519 case ADD:
520 if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) &&
521 ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param1 == TEXEL1_ALPHA)) && (curUnit == 0))
522 curUnit++;
523
524 // ATI_texture_env_combine3 adds GL_MODULATE_ADD_ATI; saves texture units
525 if (( ATI_texture_env_combine3) && (curUnit > 0) && (envCombiner->color[curUnit - 1].combine == GL_MODULATE))
526 {
527 curUnit--;
528 SetColorCombinerValues( curUnit, arg2, envCombiner->color[curUnit].arg1.source, envCombiner->color[curUnit].arg1.operand );
529 envCombiner->color[curUnit].combine = GL_MODULATE_ADD_ATI;
530 SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 );
531 }
532 else
533 {
534 envCombiner->color[curUnit].combine = GL_ADD;
535 SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param1 );
536 }
537 curUnit++;
538 break;
539 case INTERPOLATE:
540 envCombiner->usesT0 |= (colorCombiner->stage[i].op[j].param2 == TEXEL0) || (colorCombiner->stage[i].op[j].param3 == TEXEL0) || (colorCombiner->stage[i].op[j].param3 == TEXEL0_ALPHA);
541 envCombiner->usesT1 |= (colorCombiner->stage[i].op[j].param2 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1_ALPHA);
542
543 if (!( ARB_texture_env_crossbar || NV_texture_env_combine4) &&
544 ((colorCombiner->stage[i].op[j].param1 == TEXEL1) || (colorCombiner->stage[i].op[j].param2 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1) || (colorCombiner->stage[i].op[j].param3 == TEXEL1_ALPHA)) && (curUnit == 0))
545 {
546 if (colorCombiner->stage[i].op[j].param1 == TEXEL0)
547 {
548 envCombiner->color[curUnit].combine = GL_REPLACE;
549 SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 );
550 colorCombiner->stage[i].op[j].param1 = COMBINED;
551 }
552 if (colorCombiner->stage[i].op[j].param2 == TEXEL0)
553 {
554 envCombiner->color[curUnit].combine = GL_REPLACE;
555 SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param2 )
556
557 colorCombiner->stage[i].op[j].param2 = COMBINED;
558 }
559 if (colorCombiner->stage[i].op[j].param3 == TEXEL0)
560 {
561 envCombiner->color[curUnit].combine = GL_REPLACE;
562 SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param3 );
563 colorCombiner->stage[i].op[j].param3 = COMBINED;
564 }
565 if (colorCombiner->stage[i].op[j].param3 == TEXEL0_ALPHA)
566 {
567 envCombiner->color[curUnit].combine = GL_REPLACE;
568 SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param3 );
569 colorCombiner->stage[i].op[j].param3 = COMBINED_ALPHA;
570 }
571
572 curUnit++;
573 }
574
575 envCombiner->color[curUnit].combine = GL_INTERPOLATE_ARB;
576
577 SetColorCombinerArg( curUnit, arg0, colorCombiner->stage[i].op[j].param1 );
578 SetColorCombinerArg( curUnit, arg1, colorCombiner->stage[i].op[j].param2 );
579 SetColorCombinerArg( curUnit, arg2, colorCombiner->stage[i].op[j].param3 );
580
581 curUnit++;
582 break;
583 }
584 }
585 }
586 }
587
588 envCombiner->usedUnits = max( (unsigned short)curUnit, envCombiner->usedUnits );
589 return envCombiner;
590}