2 Copyright (C) 2003 Rice1964
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #include "OGLExtensions.h"
21 #include "OGLCombinerNV.h"
22 #include "OGLRender.h"
23 #include "OGLGraphicsContext.h"
25 //========================================================================
26 #define MUX_E_F (MUX_PRIMLODFRAC+1)
27 #define MUX_SPARE1 (MUX_E_F+1)
28 #define MUX_SECONDARY_COLOR (MUX_SPARE1+1)
29 #define MUX_NOT_USED MUX_ERR
30 #define MUX_COMBINED_SIGNED (MUX_SECONDARY_COLOR+1) //Use only by Nvidia register combiner
36 GLenum componentUsage;
39 RGBMapType RGBmap1[] =
41 {GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_0 = 0,
42 {GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_RGB}, //MUX_1, = ZERO NEG
43 {GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_COMBINED,
44 {GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_TEXEL0,
45 {GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_TEXEL1,
46 {GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_PRIM,
47 {GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_SHADE,
48 {GL_CONSTANT_COLOR1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_ENV,
49 {GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA}, //MUX_COMBALPHA,
50 {GL_TEXTURE0_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA}, //MUX_T0_ALPHA,
51 {GL_TEXTURE1_ARB, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA}, //MUX_T1_ALPHA,
52 {GL_CONSTANT_COLOR0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA}, //MUX_PRIM_ALPHA,
53 {GL_PRIMARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA}, //MUX_SHADE_ALPHA,
54 {GL_CONSTANT_COLOR1_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA}, //MUX_ENV_ALPHA,
55 {GL_CONSTANT_COLOR1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_LODFRAC,
56 {GL_CONSTANT_COLOR1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_PRIMLODFRAC,
57 {GL_E_TIMES_F_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_E_F,
58 {GL_SPARE1_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_SPARE1,
59 {GL_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB}, //MUX_SECONDARY_COLOR,
60 {GL_SPARE0_NV, GL_SIGNED_IDENTITY_NV, GL_RGB}, //MUX_COMBINED_SIGNED,
64 //========================================================================
65 COGLColorCombinerNvidia::COGLColorCombinerNvidia(CRender *pRender) :
66 COGLColorCombiner4(pRender)
68 m_bNVSupported = false;
70 m_pDecodedMux = new COGLDecodedMux;
71 m_pDecodedMux->m_maxConstants=2;
74 COGLColorCombinerNvidia::~COGLColorCombinerNvidia()
76 m_vCompiledSettings.clear();
80 bool COGLColorCombinerNvidia::Initialize(void)
82 m_bNVSupported = false;
84 if( COGLColorCombiner4::Initialize() )
86 m_bSupportMultiTexture = true;
88 COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext);
89 if( pcontext->IsExtensionSupported("GL_NV_texture_env_combine4") || pcontext->IsExtensionSupported("GL_NV_register_combiners") )
91 m_bNVSupported = true;
92 glEnable(GL_REGISTER_COMBINERS_NV);
97 DebugMessage(M64MSG_ERROR, "Your video card does not support Nvidia OpenGL extension combiner");
98 glDisable(GL_REGISTER_COMBINERS_NV);
103 glDisable(GL_REGISTER_COMBINERS_NV);
107 void COGLColorCombinerNvidia::InitCombinerCycle12(void)
109 if( !m_bNVSupported ) {COGLColorCombiner4::InitCombinerCycle12(); return;}
111 glEnable(GL_REGISTER_COMBINERS_NV);
114 if( debuggerDropCombiners )
116 m_vCompiledSettings.clear();
117 m_dwLastMux0 = m_dwLastMux1 = 0;
118 debuggerDropCombiners = false;
122 m_pOGLRender->EnableMultiTexture();
123 bool combinerIsChanged = false;
125 if( m_pDecodedMux->m_dwMux0 != m_dwLastMux0 || m_pDecodedMux->m_dwMux1 != m_dwLastMux1 || m_lastIndex < 0 )
127 combinerIsChanged = true;
128 m_lastIndex = FindCompiledMux();
129 if( m_lastIndex < 0 ) // Can not found
131 NVRegisterCombinerParserType result;
132 ParseDecodedMux(result);
133 m_lastIndex= SaveParserResult(result);
136 m_dwLastMux0 = m_pDecodedMux->m_dwMux0;
137 m_dwLastMux1 = m_pDecodedMux->m_dwMux1;
138 GenerateNVRegisterCombinerSetting(m_lastIndex);
141 m_pOGLRender->SetAllTexelRepeatFlag();
143 if( m_bCycleChanged || combinerIsChanged || gRDP.texturesAreReloaded || gRDP.colorsAreReloaded )
145 gRDP.texturesAreReloaded = false;
146 if( m_bCycleChanged || combinerIsChanged )
148 GenerateNVRegisterCombinerSettingConstants(m_lastIndex);
149 GenerateNVRegisterCombinerSetting(m_lastIndex);
150 ApplyFogAtFinalStage();
152 else if( gRDP.colorsAreReloaded )
154 GenerateNVRegisterCombinerSettingConstants(m_lastIndex);
157 gRDP.colorsAreReloaded = false;
161 void COGLColorCombinerNvidia::ParseDecodedMux(NVRegisterCombinerParserType &result) // Compile the decodedMux into NV register combiner setting
163 //int stagesForRGB=0;
164 //int stagesForAlpha=0;
167 COGLDecodedMux &mux = *(COGLDecodedMux*)m_pDecodedMux;
168 mux.To_AB_Add_CD_Format();
172 if( StagesNeedToUse(mux, N64Cycle0RGB) == 0 )
174 // Nothing to be done for RGB
175 ByPassGeneralStage(result.s1rgb);
176 ByPassGeneralStage(result.s2rgb);
177 ByPassFinalStage(result.finalrgb);
179 else if( StagesNeedToUse(mux, N64Cycle0RGB) == 1 )
181 result.stagesUsed = 1;
182 Parse1Mux(mux, N64Cycle0RGB, result.s1rgb);
183 if( StagesNeedToUse(mux, N64Cycle1RGB) == 0 )
185 ByPassGeneralStage(result.s2rgb);
186 ByPassFinalStage(result.finalrgb);
190 result.stagesUsed = 2;
191 Parse1MuxForStage2AndFinalStage(mux, N64Cycle1RGB, result.s2rgb, result.finalrgb);
196 result.stagesUsed = 2;
197 Parse1Mux2Stages(mux, N64Cycle0RGB, result.s1rgb, result.s2rgb);
198 Parse1MuxForFinalStage(mux, N64Cycle1RGB, result.finalrgb);
203 if( m_pDecodedMux->m_bTexel0IsUsed && m_pDecodedMux->m_bTexel1IsUsed )
205 result.finalrgb.a = MUX_TEXEL0;
206 result.finalrgb.b = MUX_TEXEL1;
207 result.finalrgb.c = MUX_0;
208 result.finalrgb.d = MUX_0;
212 if( StagesNeedToUse(mux, N64Cycle0Alpha) == 0 )
214 // Nothing to be done for Alpha
215 ByPassGeneralStage(result.s1alpha);
216 ByPassGeneralStage(result.s2alpha);
217 ByPassFinalStage(result.finalalpha);
219 else if( Parse1Mux2Stages(mux, N64Cycle0Alpha, result.s1alpha, result.s2alpha) == 1 )
221 // Only 1 NV stage is used
222 if( result.stagesUsed == 0 ) result.stagesUsed = 1;
223 if( StagesNeedToUse(mux, N64Cycle1Alpha) == 0 )
225 ByPassGeneralStage(result.s2alpha);
229 Parse1Mux(mux, N64Cycle1Alpha, result.s2alpha);
230 result.stagesUsed = 2;
235 // The 1st is used 2 stages, skip the 2nd N64 alpha setting
236 result.stagesUsed = 2;
237 result.s2alpha.a=MUX_COMBINED;
238 result.s2alpha.b=MUX_1;
239 result.s2alpha.c=m_pDecodedMux->m_n64Combiners[N64Cycle0Alpha].d;
240 result.s2alpha.d=MUX_1;
243 // Parse Alpha setting, alpha does not have a final stage
244 ByPassFinalStage(result.finalalpha);
245 ParseDecodedMuxForConstant(result);
248 void COGLColorCombinerNvidia::ParseDecodedMuxForConstant(NVRegisterCombinerParserType &result)
250 result.constant0 = MUX_0;
251 result.constant1 = MUX_0;
252 bool const0Used=false;
253 bool const1Used=false;
254 if( m_pDecodedMux->isUsed(MUX_PRIM) )
256 result.constant0 = MUX_PRIM;
259 if( m_pDecodedMux->isUsed(MUX_ENV) )
263 result.constant1 = MUX_ENV;
268 result.constant0 = MUX_ENV;
272 if( m_pDecodedMux->isUsed(MUX_LODFRAC) && !const1Used )
276 result.constant1 = MUX_LODFRAC;
279 else if( !const0Used )
281 result.constant0 = MUX_LODFRAC;
286 if( m_pDecodedMux->isUsed(MUX_PRIMLODFRAC) && !const1Used )
290 result.constant1 = MUX_PRIMLODFRAC;
293 else if( !const0Used )
295 result.constant0 = MUX_PRIMLODFRAC;
301 int COGLColorCombinerNvidia::StagesNeedToUse(COGLDecodedMux &mux, N64StageNumberType stage)
303 N64CombinerType &m = mux.m_n64Combiners[stage];
305 switch(mux.splitType[stage])
307 case CM_FMT_TYPE_NOT_USED:
309 case CM_FMT_TYPE_D: // = A ==> can be done in 1 NV stage
310 case CM_FMT_TYPE_A_ADD_D: // = A+D ==> can be done in 1 NV stage
311 case CM_FMT_TYPE_A_MOD_C: // = A*C ==> can be done in 1 NV stage
312 case CM_FMT_TYPE_A_SUB_B: // = A-B ==> can be done in 1 NV stage
313 case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D ==> can be done in 1 NV stage
314 case CM_FMT_TYPE_A_LERP_B_C: // = (A-B)*C+B ==> can be done in 1 NV stage
315 case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C ==> can be done in 1 NV stage
316 case CM_FMT_TYPE_AB_ADD_CD: // = AB+CD
317 case CM_FMT_TYPE_AB_SUB_CD: // = AB-CD
319 case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+D ==> can not be done in 1 stage
320 if( m.a == m.d ) // = 2A-B, simply it to A-B, in fact,we can do 2A-B with NV register combiner
322 else // Need two NV stages for this N64 combiner
324 case CM_FMT_TYPE_A_B_C_D: // = (A-B)*C+D ==> can not be done in 1 stage
326 //if( m.a == m.d ) // = (A-B)*C+A = A(C+1)-B*C = A-B*C
329 if( m.d == m.c ) // = (A-B)*C+C = A*C+(1-B)*C
331 else // = (A-B)*C+D, need two NV stages
336 bool isTex(uint8 val)
338 if( (val&MUX_MASK) == MUX_TEXEL0 || (val&MUX_MASK) == MUX_TEXEL1 )
343 int COGLColorCombinerNvidia::Parse1Mux(COGLDecodedMux &mux, N64StageNumberType stage, NVGeneralCombinerType &res) // Compile the decodedMux into NV register combiner setting
345 // Parse 1 N64 combiner, generate result and return how many NV stage is needed.
346 // result will be put into only 1 NV stage, not the 2nd one even if 2nd one is needed.
347 // The caller of this function will handle the 2nd NV stage if it is needed
350 // Up to here, the m_pDecodedMux is already simplied, N64 stage 1 and stage 2 have been
351 // adjusted so stage1 is almost always complicated than stage 2
353 // The stage type in decodedMux is still in (A-B)*C+D format
354 // we need to parser and translate it to A*B+C*D format for NV register general combiner
355 // and to A*D+(1-A)*C+D format for the NV final combiner
357 // Remember that N64 has two stages, NV has two general combiner stages and 1 final combiner stage
358 // NV should be able to simulate exactly all possible N64 combiner settings
360 CM_FMT_TYPE1_D, // = A ==> can be done in 1 NV stage
361 CM_FMT_TYPE2_A_ADD_D, // = A+D ==> can be done in 1 NV stage
362 CM_FMT_TYPE3_A_MOD_C, // = A*C ==> can be done in 1 NV stage
363 CM_FMT_TYPE4_A_SUB_B, // = A-B ==> can be done in 1 NV stage
364 CM_FMT_TYPE5_A_MOD_C_ADD_D, // = A*C+D ==> can be done in 1 NV stage
365 CM_FMT_TYPE6_A_LERP_B_C, // = (A-B)*C+B ==> can be done in 1 NV stage
366 CM_FMT_TYPE8_A_SUB_B_MOD_C, // = (A-B)*C ==> can be done in 1 NV stage
368 CM_FMT_TYPE7_A_SUB_B_ADD_D, // = A-B+C ==> can not be done in 1 stage
369 CM_FMT_TYPE9_A_B_C_D, // = (A-B)*C+D ==> can not be done in 1 stage
371 the last two ones, since we can neither do it in the final stage, if the 1st N64 stage
372 happen to be one of the two types and have used the two NV general combiners, and if the 2nd N64
373 combiner happens to be one of the two types as well, then we have to simplify the N64 combiner so
374 to implement it. In such as case, the N64 combiners are too complicated, we just do what either as
375 we can to implement it.
377 Use UNSIGNED_INVERT of ZERO ==> ONE
379 // If the 1st N64 stage can not be done in 1 NV stage, then we will do 1st N64 stage
380 // by using 2 NV general combiner stages, and the 2nd N64 stage by using the NV final
383 // RGB channel and alpha channel is the same in the general combiner, but different in
384 // the final combiner. In fact, final combiner does not do anything for alpha channel
385 // so alpha channel setting of both N64 combiner must be implemented by the two NV general
388 If we can not implement the two alpha setting in 2 NV combiner stages, we will do what either
392 N64CombinerType &m = mux.m_n64Combiners[stage];
394 switch(mux.splitType[stage])
396 case CM_FMT_TYPE_NOT_USED:
403 case CM_FMT_TYPE_D: // = A ==> can be done in 1 NV stage
410 case CM_FMT_TYPE_A_ADD_D: // = A+D ==> can be done in 1 NV stage
417 case CM_FMT_TYPE_A_MOD_C: // = A*C ==> can be done in 1 NV stage
424 case CM_FMT_TYPE_A_SUB_B: // = A-B ==> can be done in 1 NV stage
431 case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D ==> can be done in 1 NV stage
438 case CM_FMT_TYPE_A_LERP_B_C: // = (A-B)*C+B ==> can be done in 1 NV stage
442 res.c=m.c^MUX_COMPLEMENT;
446 case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C ==> can be done in 1 NV stage
453 case CM_FMT_TYPE_AB_ADD_CD: // = AB+CD
460 case CM_FMT_TYPE_AB_SUB_CD: // = AB-CD
467 case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+D ==> can not be done in 1 stage
468 if( m.a == m.d ) // = 2A-B, simply it to A-B, in fact,we can do 2A-B with NV register combiner
476 else // Need two NV stages for this N64 combiner
482 if( isTex(res.b) || !isTex(res.d) )
495 case CM_FMT_TYPE_A_B_C_D: // = (A-B)*C+D ==> can not be done in 1 stage
497 if( m.a == m.d ) // = (A-B)*C+A = A(C+1)-B*C = A-B*C
505 else if( m.d == m.c ) // = (A-B)*C+C = A*C+(1-B)*C
509 res.c=m.b^MUX_COMPLEMENT;
513 else // = (A-B)*C+D, need two NV stages
515 // Stage 1: R1=(A-B)*C = AC-BC
526 // = (A-B)*C = A*C - B*C
538 int COGLColorCombinerNvidia::Parse1Mux2Stages(COGLDecodedMux &mux, N64StageNumberType stage, NVGeneralCombinerType &res, NVGeneralCombinerType &res2)
540 N64CombinerType &m = mux.m_n64Combiners[stage];
541 switch(mux.splitType[stage])
543 case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+D ==> can not be done in 1 stage
544 if( m.a != m.d ) // = 2A-B, simply it to A-B, in fact,we can do 2A-B with NV register combiner
552 res2.a=MUX_COMBINED_SIGNED;
560 case CM_FMT_TYPE_A_B_C_D: // = (A-B)*C+D ==> can not be done in 1 stage
561 case CM_FMT_TYPE_A_B_C_A: // = (A-B)*C+D ==> can not be done in 1 stage
562 //if( m.a != m.d && m.d != m.c )
564 // Stage 1: R1=(A-B)*C = AC-BC
570 res2.a=MUX_COMBINED_SIGNED;
581 return Parse1Mux(mux, stage, res);
585 void COGLColorCombinerNvidia::Parse1MuxForFinalStage(COGLDecodedMux &mux, N64StageNumberType stage, NVFinalCombinerType &res)
587 N64CombinerType &m = mux.m_n64Combiners[stage];
589 // Final stage equation is: AB+(1-A)C+D
590 switch(mux.splitType[stage])
592 case CM_FMT_TYPE_NOT_USED:
598 case CM_FMT_TYPE_D: // = A ==> can be done in 1 NV stage
604 case CM_FMT_TYPE_A_ADD_D: // = A+D ==> can be done in 1 NV stage
610 case CM_FMT_TYPE_A_MOD_C: // = A*C ==> can be done in 1 NV stage
616 case CM_FMT_TYPE_A_SUB_B: // = A-B ==> can be done in 1 NV stage
622 case CM_FMT_TYPE_A_MOD_C_ADD_D: // = A*C+D ==> can be done in 1 NV stage
628 case CM_FMT_TYPE_A_LERP_B_C: // = (A-B)*C+B ==> can be done in 1 NV stage
637 case CM_FMT_TYPE_A_SUB_B_MOD_C: // = (A-B)*C ==> can be done in 1 NV stage
643 case CM_FMT_TYPE_AB_ADD_CD: // = AB+CD
651 case CM_FMT_TYPE_AB_SUB_CD: // = AB-CD
659 case CM_FMT_TYPE_A_SUB_B_ADD_D: // = A-B+D ==> can not be done in 1 stage
660 if( m.a == m.d ) // = 2A-B, simply it to A-B, in fact,we can do 2A-B with NV register combiner
667 else // Need two NV stages for this N64 combiner
669 TRACE0("NV Combiner parse, check me, not fully support this combiner");
670 // final combiner can not fully support this combiner setting
678 case CM_FMT_TYPE_A_B_C_D: // = (A-B)*C+D ==> can not be done in 1 stage
680 if( m.a == m.d ) // = (A-B)*C+A = A(C+1)-B*C = A-B*C
693 else if( m.d == m.c ) // = (A-B)*C+C = A*C+(1-B)*C
702 else // = (A-B)*C+D, need two NV stages
704 TRACE0("NV Combiner parse, check me, not fully support this combiner");
705 // final combiner can not fully support this combiner setting
706 // Stage 1: R1=(A-B)*C = AC-BC
717 int COGLColorCombinerNvidia::Parse1MuxForStage2AndFinalStage(COGLDecodedMux &mux, N64StageNumberType stage, NVGeneralCombinerType &res, NVFinalCombinerType &fres)
719 if( Parse1Mux(mux, stage, res) == 1 )
721 ByPassFinalStage(fres);
726 ByPassFinalStage(fres);
729 fres.d = mux.m_n64Combiners[stage].d;
735 void COGLColorCombinerNvidia::ByPassFinalStage(NVFinalCombinerType &fres)
746 void COGLColorCombinerNvidia::ByPassGeneralStage(NVGeneralCombinerType &res)
754 int COGLColorCombinerNvidia::FindCompiledMux(void)
756 for( uint32 i=0; i<m_vCompiledSettings.size(); i++ )
758 if( m_vCompiledSettings[i].dwMux0 == m_pDecodedMux->m_dwMux0 && m_vCompiledSettings[i].dwMux1 == m_pDecodedMux->m_dwMux1 )
764 void COGLColorCombinerNvidia::GenerateNVRegisterCombinerSettingConstants(int index)
766 NVRegisterCombinerSettingType &info = m_vCompiledSettings[index];
767 uint8 consts[2] = {info.constant0,info.constant1};
771 for( int i=0; i<2; i++ )
776 pf = GetPrimitiveColorfv();
777 pglCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV+i,pf);
780 pf = GetEnvColorfv();
781 pglCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV+i,pf);
784 case MUX_PRIMLODFRAC:
786 float frac = gRDP.primLODFrac / 255.0f;
787 float tempf[4] = {frac,frac,frac,frac};
788 pglCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV+i,tempf);
795 void COGLColorCombinerNvidia::GenerateNVRegisterCombinerSetting(int index)
797 if( index < 0 || index >= (int)m_vCompiledSettings.size() )
799 TRACE0("NV Register combiner, vector index out of range");
803 NVRegisterCombinerSettingType &info = m_vCompiledSettings[index];
805 pglCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV,info.numOfStages);
809 if( info.numOfStages > 0 )
813 pglCombinerInputNV(GL_COMBINER0_NV, GL_RGB, info.stage1RGB[i].variable, info.stage1RGB[i].input,
814 info.stage1RGB[i].mapping, info.stage1RGB[i].componentUsage );
819 pglCombinerInputNV(GL_COMBINER0_NV, GL_ALPHA, info.stage1Alpha[i].variable, info.stage1Alpha[i].input,
820 info.stage1Alpha[i].mapping, info.stage1Alpha[i].componentUsage );
823 pglCombinerOutputNV(GL_COMBINER0_NV, GL_RGB, info.stage1outputRGB.abOutput, info.stage1outputRGB.cdOutput,
824 info.stage1outputRGB.sumOutput, info.stage1outputRGB.scale, info.stage1outputRGB.bias, info.stage1outputRGB.abDotProduct,
825 info.stage1outputRGB.cdDotProduct, info.stage1outputRGB.muxSum);
827 pglCombinerOutputNV(GL_COMBINER0_NV, GL_ALPHA, info.stage2outputAlpha.abOutput, info.stage2outputAlpha.cdOutput,
828 info.stage2outputAlpha.sumOutput, info.stage2outputAlpha.scale, info.stage2outputAlpha.bias, info.stage2outputAlpha.abDotProduct,
829 info.stage2outputAlpha.cdDotProduct, info.stage2outputAlpha.muxSum);
831 if( info.numOfStages > 1 )
835 pglCombinerInputNV(GL_COMBINER1_NV, GL_RGB, info.stage2RGB[i].variable,
836 info.stage2RGB[i].input, info.stage2RGB[i].mapping, info.stage2RGB[i].componentUsage );
841 pglCombinerInputNV(GL_COMBINER1_NV, GL_ALPHA, info.stage2Alpha[i].variable, info.stage2Alpha[i].input,
842 info.stage2Alpha[i].mapping, info.stage2Alpha[i].componentUsage );
845 pglCombinerOutputNV(GL_COMBINER1_NV, GL_RGB, info.stage2outputRGB.abOutput, info.stage2outputRGB.cdOutput,
846 info.stage2outputRGB.sumOutput, info.stage2outputRGB.scale, info.stage2outputRGB.bias, info.stage2outputRGB.abDotProduct,
847 info.stage2outputRGB.cdDotProduct, info.stage2outputRGB.muxSum);
849 pglCombinerOutputNV(GL_COMBINER1_NV, GL_ALPHA, info.stage2outputAlpha.abOutput, info.stage2outputAlpha.cdOutput,
850 info.stage2outputAlpha.sumOutput, info.stage2outputAlpha.scale, info.stage2outputAlpha.bias, info.stage2outputAlpha.abDotProduct,
851 info.stage2outputAlpha.cdDotProduct, info.stage2outputAlpha.muxSum);
857 pglFinalCombinerInputNV(info.finalStage[i].variable, info.finalStage[i].input,
858 info.finalStage[i].mapping, info.finalStage[i].componentUsage );
862 GLenum COGLColorCombinerNvidia::ConstMap(uint8 c)
880 case MUX_SHADE_ALPHA:
883 case MUX_PRIMLODFRAC:
890 void Set1Variable(GLenum variable, uint8 val, NVCombinerInputType &record, const NVRegisterCombinerParserType &result, bool forRGB=true)
892 record.variable = variable;
893 record.componentUsage = RGBmap1[val&MUX_MASK].componentUsage;
894 record.input = RGBmap1[val&MUX_MASK].input;
895 record.mapping = RGBmap1[val&MUX_MASK].mapping;
897 switch( val&MUX_MASK )
901 case MUX_PRIMLODFRAC:
903 if( (val&MUX_MASK) == result.constant0 )
905 record.input = GL_CONSTANT_COLOR0_NV;
907 else if( (val&MUX_MASK) == result.constant1 )
909 record.input = GL_CONSTANT_COLOR1_NV;
913 record.input = GL_ZERO;
920 record.mapping = GL_SIGNED_NEGATE_NV;
922 else if( val == MUX_1 )
924 record.mapping = GL_UNSIGNED_INVERT_NV;
926 else if( val & MUX_COMPLEMENT )
928 record.mapping = GL_UNSIGNED_INVERT_NV;
931 if( val & MUX_ALPHAREPLICATE || !forRGB )
933 record.componentUsage = GL_ALPHA;
937 int COGLColorCombinerNvidia::SaveParserResult(const NVRegisterCombinerParserType &result)
939 NVRegisterCombinerSettingType save;
942 Set1Variable(GL_VARIABLE_A_NV, result.s1rgb.a, save.stage1RGB[0], result);
943 Set1Variable(GL_VARIABLE_B_NV, result.s1rgb.b, save.stage1RGB[1], result);
944 Set1Variable(GL_VARIABLE_C_NV, result.s1rgb.c, save.stage1RGB[2], result);
945 Set1Variable(GL_VARIABLE_D_NV, result.s1rgb.d, save.stage1RGB[3], result);
948 Set1Variable(GL_VARIABLE_A_NV, result.s1alpha.a, save.stage1Alpha[0], result, false);
949 Set1Variable(GL_VARIABLE_B_NV, result.s1alpha.b, save.stage1Alpha[1], result, false);
950 Set1Variable(GL_VARIABLE_C_NV, result.s1alpha.c, save.stage1Alpha[2], result, false);
951 Set1Variable(GL_VARIABLE_D_NV, result.s1alpha.d, save.stage1Alpha[3], result, false);
954 Set1Variable(GL_VARIABLE_A_NV, result.s2rgb.a, save.stage2RGB[0], result);
955 Set1Variable(GL_VARIABLE_B_NV, result.s2rgb.b, save.stage2RGB[1], result);
956 Set1Variable(GL_VARIABLE_C_NV, result.s2rgb.c, save.stage2RGB[2], result);
957 Set1Variable(GL_VARIABLE_D_NV, result.s2rgb.d, save.stage2RGB[3], result);
960 Set1Variable(GL_VARIABLE_A_NV, result.s2alpha.a, save.stage2Alpha[0], result, false);
961 Set1Variable(GL_VARIABLE_B_NV, result.s2alpha.b, save.stage2Alpha[1], result, false);
962 Set1Variable(GL_VARIABLE_C_NV, result.s2alpha.c, save.stage2Alpha[2], result, false);
963 Set1Variable(GL_VARIABLE_D_NV, result.s2alpha.d, save.stage2Alpha[3], result, false);
966 Set1Variable(GL_VARIABLE_A_NV, result.finalrgb.a, save.finalStage[0], result);
967 Set1Variable(GL_VARIABLE_B_NV, result.finalrgb.b, save.finalStage[1], result);
968 Set1Variable(GL_VARIABLE_C_NV, result.finalrgb.c, save.finalStage[2], result);
969 Set1Variable(GL_VARIABLE_D_NV, result.finalrgb.d, save.finalStage[3], result);
970 Set1Variable(GL_VARIABLE_E_NV, result.finalrgb.e, save.finalStage[4], result);
971 //save.finalStage[4].componentUsage = GL_ALPHA;
972 Set1Variable(GL_VARIABLE_F_NV, result.finalrgb.f, save.finalStage[5], result);
973 //save.finalStage[5].componentUsage = GL_ALPHA;
974 Set1Variable(GL_VARIABLE_G_NV, result.finalrgb.g, save.finalStage[6], result);
975 save.finalStage[6].componentUsage = GL_ALPHA;
977 save.numOfStages = result.stagesUsed;
978 save.dwMux0 = m_pDecodedMux->m_dwMux0;
979 save.dwMux1 = m_pDecodedMux->m_dwMux1;
981 save.stage1outputRGB.scale = GL_NONE;
982 save.stage1outputRGB.sumOutput = GL_SPARE0_NV;
983 save.stage1outputRGB.abDotProduct = GL_FALSE;
984 save.stage1outputRGB.cdDotProduct = GL_FALSE;
985 save.stage1outputRGB.abOutput = GL_SPARE1_NV;
986 save.stage1outputRGB.cdOutput = GL_SECONDARY_COLOR_NV;
987 save.stage1outputRGB.bias = GL_NONE;
988 save.stage1outputRGB.muxSum = GL_FALSE;
990 save.stage1outputAlpha.scale = GL_NONE;
991 save.stage1outputAlpha.sumOutput = GL_SPARE0_NV;
992 save.stage1outputAlpha.abDotProduct = GL_FALSE;
993 save.stage1outputAlpha.cdDotProduct = GL_FALSE;
994 save.stage1outputAlpha.abOutput = GL_SPARE1_NV;
995 save.stage1outputAlpha.cdOutput = GL_SECONDARY_COLOR_NV;
996 save.stage1outputAlpha.bias = GL_NONE;
997 save.stage1outputAlpha.muxSum = GL_FALSE;
999 save.stage2outputRGB.scale = GL_NONE;
1000 save.stage2outputRGB.sumOutput = GL_SPARE0_NV;
1001 save.stage2outputRGB.abDotProduct = GL_FALSE;
1002 save.stage2outputRGB.cdDotProduct = GL_FALSE;
1003 save.stage2outputRGB.abOutput = GL_SPARE1_NV;
1004 save.stage2outputRGB.cdOutput = GL_SECONDARY_COLOR_NV;
1005 save.stage2outputRGB.bias = GL_NONE;
1006 save.stage2outputRGB.muxSum = GL_FALSE;
1008 save.stage2outputAlpha.scale = GL_NONE;
1009 save.stage2outputAlpha.sumOutput = GL_SPARE0_NV;
1010 save.stage2outputAlpha.abDotProduct = GL_FALSE;
1011 save.stage2outputAlpha.cdDotProduct = GL_FALSE;
1012 save.stage2outputAlpha.abOutput = GL_SPARE1_NV;
1013 save.stage2outputAlpha.cdOutput = GL_SECONDARY_COLOR_NV;
1014 save.stage2outputAlpha.bias = GL_NONE;
1015 save.stage2outputAlpha.muxSum = GL_FALSE;
1017 save.constant0 = result.constant0;
1018 save.constant1 = result.constant1;
1021 memcpy(&(save.parseResult),&result, sizeof(result));
1024 TRACE0("\nNew Mux:\n");
1026 COGLColorCombiner::DisplaySimpleMuxString();
1027 DisplayNVCombinerString(save);
1031 m_vCompiledSettings.push_back(save);
1033 return m_vCompiledSettings.size()-1; // Return the index of the last element
1037 void COGLColorCombinerNvidia::DisableCombiner(void)
1039 glDisable(GL_REGISTER_COMBINERS_NV);
1040 COGLColorCombiner4::DisableCombiner();
1043 void COGLColorCombinerNvidia::InitCombinerCycleCopy(void)
1045 glDisable(GL_REGISTER_COMBINERS_NV);
1046 COGLColorCombiner4::InitCombinerCycleCopy();
1049 void COGLColorCombinerNvidia::InitCombinerCycleFill(void)
1051 glDisable(GL_REGISTER_COMBINERS_NV);
1052 COGLColorCombiner4::InitCombinerCycleFill();
1055 void COGLColorCombinerNvidia::InitCombinerBlenderForSimpleTextureDraw(uint32 tile)
1057 glDisable(GL_REGISTER_COMBINERS_NV);
1058 COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(tile);
1061 void COGLColorCombinerNvidia::ApplyFogAtFinalStage()
1063 // If we need to enable fog at final stage, the current flag stage setting
1064 // will be affect, which means correct combiner setting at final stage is lost
1065 // in order to use fog
1066 if( glIsEnabled(GL_FOG) )
1068 // Use final stage as: cmb*fogfactor+fog*(1-fogfactor)
1069 pglFinalCombinerInputNV(GL_VARIABLE_A_NV, GL_FOG, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA );
1070 pglFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
1071 pglFinalCombinerInputNV(GL_VARIABLE_C_NV, GL_FOG, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
1072 pglFinalCombinerInputNV(GL_VARIABLE_D_NV, GL_ZERO, GL_UNSIGNED_IDENTITY_NV, GL_RGB );
1077 extern const char *translatedCombTypes[];
1078 void COGLColorCombinerNvidia::DisplaySimpleMuxString(void)
1080 COGLColorCombiner::DisplaySimpleMuxString();
1081 TRACE0("\nNV Combiner setting\n");
1082 uint32 index = FindCompiledMux();
1085 NVRegisterCombinerSettingType &record = m_vCompiledSettings[index];
1086 DisplayNVCombinerString(record);
1090 char* FormatStrForFinalStage(uint8 val, char* buf)
1092 if( (val&MUX_MASK) == MUX_E_F )
1098 return DecodedMux::FormatStr(val, buf);
1101 void COGLColorCombinerNvidia::DisplayNVCombinerString(NVRegisterCombinerSettingType &record)
1103 NVRegisterCombinerParserType &result = record.parseResult;
1116 TRACE0("\nNvidia combiner stages:\n");
1118 DebuggerAppendMsg("//aRGB0:\t%s * %s + %s * %s\n", DecodedMux::FormatStr(result.s1rgb.a, buf0),
1119 DecodedMux::FormatStr(result.s1rgb.b, buf1), DecodedMux::FormatStr(result.s1rgb.c, buf2),DecodedMux::FormatStr(result.s1rgb.d, buf3));
1120 DebuggerAppendMsg("//aA0:\t%s * %s + %s * %s\n", DecodedMux::FormatStr(result.s1alpha.a, buf0),
1121 DecodedMux::FormatStr(result.s1alpha.b, buf1), DecodedMux::FormatStr(result.s1alpha.c, buf2),DecodedMux::FormatStr(result.s1alpha.d, buf3));
1122 if( record.numOfStages == 2 )
1124 DebuggerAppendMsg("//aRGB1:\t%s * %s + %s * %s\n", DecodedMux::FormatStr(result.s2rgb.a, buf0),
1125 DecodedMux::FormatStr(result.s2rgb.b, buf1), DecodedMux::FormatStr(result.s2rgb.c, buf2),DecodedMux::FormatStr(result.s2rgb.d, buf3));
1126 DebuggerAppendMsg("//aA1:\t%s * %s + %s * %s\n", DecodedMux::FormatStr(result.s2alpha.a, buf0),
1127 DecodedMux::FormatStr(result.s2alpha.b, buf1), DecodedMux::FormatStr(result.s2alpha.c, buf2),DecodedMux::FormatStr(result.s2alpha.d, buf3));
1129 DebuggerAppendMsg("//Final:\t%s * %s + (1 - %s) * %s + %s\n\tE=%s, F=%s\n", FormatStrForFinalStage(result.finalrgb.a, buf0),
1130 FormatStrForFinalStage(result.finalrgb.b, buf1), FormatStrForFinalStage(result.finalrgb.a, buf2),
1131 FormatStrForFinalStage(result.finalrgb.c, buf3), FormatStrForFinalStage(result.finalrgb.d, buf4),
1132 FormatStrForFinalStage(result.finalrgb.e, buf5), FormatStrForFinalStage(result.finalrgb.f, buf6));
1134 if( result.constant0 != MUX_0 )
1136 DebuggerAppendMsg("//Constant 0:\t%s\n", DecodedMux::FormatStr(result.constant0, buf0));
1138 if( result.constant1 != MUX_0 )
1140 DebuggerAppendMsg("//Constant 1:\t%s\n", DecodedMux::FormatStr(result.constant1, buf0));