| 1 | /* |
| 2 | Copyright (C) 2003 Rice1964 |
| 3 | |
| 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. |
| 8 | |
| 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. |
| 13 | |
| 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. |
| 17 | */ |
| 18 | |
| 19 | #include "OGLExtensions.h" |
| 20 | #include "OGLDebug.h" |
| 21 | #include "OGLFragmentShaders.h" |
| 22 | #include "OGLRender.h" |
| 23 | #include "OGLGraphicsContext.h" |
| 24 | |
| 25 | COGLFragmentShaderCombiner::COGLFragmentShaderCombiner(CRender *pRender) |
| 26 | : COGLColorCombiner(pRender) |
| 27 | { |
| 28 | m_bShaderIsSupported = false; |
| 29 | } |
| 30 | COGLFragmentShaderCombiner::~COGLFragmentShaderCombiner() |
| 31 | { |
| 32 | } |
| 33 | |
| 34 | bool COGLFragmentShaderCombiner::Initialize(void) |
| 35 | { |
| 36 | if( !COGLColorCombiner::Initialize() ) |
| 37 | return false; |
| 38 | |
| 39 | COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext); |
| 40 | if( pcontext->IsExtensionSupported("GL_ARB_fragment_shader") ) |
| 41 | { |
| 42 | m_bShaderIsSupported = true; |
| 43 | } |
| 44 | |
| 45 | return true; |
| 46 | } |
| 47 | |
| 48 | void COGLFragmentShaderCombiner::InitCombinerCycle12(void) |
| 49 | { |
| 50 | } |
| 51 | void COGLFragmentShaderCombiner::DisableCombiner(void) |
| 52 | { |
| 53 | COGLColorCombiner::DisableCombiner(); |
| 54 | } |
| 55 | |
| 56 | void COGLFragmentShaderCombiner::InitCombinerCycleCopy(void) |
| 57 | { |
| 58 | COGLColorCombiner::InitCombinerCycleCopy(); |
| 59 | } |
| 60 | |
| 61 | void COGLFragmentShaderCombiner::InitCombinerCycleFill(void) |
| 62 | { |
| 63 | COGLColorCombiner::InitCombinerCycleFill(); |
| 64 | } |
| 65 | void COGLFragmentShaderCombiner::InitCombinerBlenderForSimpleTextureDraw(uint32 tile) |
| 66 | { |
| 67 | COGLColorCombiner::InitCombinerBlenderForSimpleTextureDraw(tile); |
| 68 | } |
| 69 | |
| 70 | #ifdef DEBUGGER |
| 71 | void COGLFragmentShaderCombiner::DisplaySimpleMuxString(void) |
| 72 | { |
| 73 | COGLColorCombiner::DisplaySimpleMuxString(); |
| 74 | } |
| 75 | #endif |
| 76 | |
| 77 | |
| 78 | |
| 79 | COGL_FragmentProgramCombiner::COGL_FragmentProgramCombiner(CRender *pRender) |
| 80 | : COGLColorCombiner4(pRender) |
| 81 | { |
| 82 | delete m_pDecodedMux; |
| 83 | m_pDecodedMux = new DecodedMuxForPixelShader; |
| 84 | m_bFragmentProgramIsSupported = false; |
| 85 | } |
| 86 | COGL_FragmentProgramCombiner::~COGL_FragmentProgramCombiner() |
| 87 | { |
| 88 | int size = m_vCompiledShaders.size(); |
| 89 | for (int i=0; i<size; i++) |
| 90 | { |
| 91 | GLuint ID = m_vCompiledShaders[i].programID; |
| 92 | pglDeleteProgramsARB(1, &ID); |
| 93 | OPENGL_CHECK_ERRORS; |
| 94 | m_vCompiledShaders[i].programID = 0; |
| 95 | } |
| 96 | |
| 97 | m_vCompiledShaders.clear(); |
| 98 | } |
| 99 | |
| 100 | bool COGL_FragmentProgramCombiner::Initialize(void) |
| 101 | { |
| 102 | if( !COGLColorCombiner4::Initialize() ) |
| 103 | return false; |
| 104 | |
| 105 | COGLGraphicsContext *pcontext = (COGLGraphicsContext *)(CGraphicsContext::g_pGraphicsContext); |
| 106 | if( pcontext->IsExtensionSupported("GL_ARB_fragment_program") ) |
| 107 | { |
| 108 | m_bFragmentProgramIsSupported = true; |
| 109 | } |
| 110 | |
| 111 | return true; |
| 112 | } |
| 113 | |
| 114 | |
| 115 | |
| 116 | void COGL_FragmentProgramCombiner::DisableCombiner(void) |
| 117 | { |
| 118 | glDisable(GL_FRAGMENT_PROGRAM_ARB); |
| 119 | OPENGL_CHECK_ERRORS; |
| 120 | COGLColorCombiner4::DisableCombiner(); |
| 121 | } |
| 122 | |
| 123 | void COGL_FragmentProgramCombiner::InitCombinerCycleCopy(void) |
| 124 | { |
| 125 | glDisable(GL_FRAGMENT_PROGRAM_ARB); |
| 126 | OPENGL_CHECK_ERRORS; |
| 127 | COGLColorCombiner4::InitCombinerCycleCopy(); |
| 128 | } |
| 129 | |
| 130 | void COGL_FragmentProgramCombiner::InitCombinerCycleFill(void) |
| 131 | { |
| 132 | glDisable(GL_FRAGMENT_PROGRAM_ARB); |
| 133 | OPENGL_CHECK_ERRORS; |
| 134 | COGLColorCombiner4::InitCombinerCycleFill(); |
| 135 | } |
| 136 | |
| 137 | const char *muxToFP_Maps[][2] = { |
| 138 | //color -- alpha |
| 139 | {"0", "0"}, //MUX_0 = 0, |
| 140 | {"1", "1"}, //MUX_1, |
| 141 | {"comb", "comb.a"}, //MUX_COMBINED, |
| 142 | {"t0", "t0.a"}, //MUX_TEXEL0, |
| 143 | {"t1", "t1.a"}, //MUX_TEXEL1, |
| 144 | {"program.env[2]", "program.env[2].a"}, //MUX_PRIM, |
| 145 | {"fragment.color", "fragment.color.a"}, //MUX_SHADE, |
| 146 | {"program.env[1]", "program.env[1].a"}, //MUX_ENV, |
| 147 | {"comb.a", "comb.a"}, //MUX_COMBALPHA, |
| 148 | {"t0.a", "t0.a"}, //MUX_T0_ALPHA, |
| 149 | {"t1.a", "t1.a"}, //MUX_T1_ALPHA, |
| 150 | {"primcolor.a", "primcolor.a"}, //MUX_PRIM_ALPHA, |
| 151 | {"fragment.color.a", "fragment.color.a"}, //MUX_SHADE_ALPHA, |
| 152 | {"envcolor.a", "envcolor.a"}, //MUX_ENV_ALPHA, |
| 153 | {"program.env[3]", "program.env[3]"}, //MUX_LODFRAC, |
| 154 | {"program.env[4]", "program.env[4]"}, //MUX_PRIMLODFRAC, |
| 155 | {"1", "1"}, //MUX_K5, |
| 156 | {"1", "1"}, //MUX_UNK, // Should not be used |
| 157 | }; |
| 158 | |
| 159 | |
| 160 | const char *oglFPTest = |
| 161 | "!!ARBfp1.0\n" |
| 162 | "#Declarations\n" |
| 163 | "TEMP t0;\n" |
| 164 | "TEMP t1;\n" |
| 165 | "TEMP comb;\n" |
| 166 | "TEMP comb2;\n" |
| 167 | "\n" |
| 168 | "ATTRIB coord0 = fragment.texcoord[0];\n" |
| 169 | "ATTRIB coord1 = fragment.texcoord[1];\n" |
| 170 | "ATTRIB shade = fragment.color;\n" |
| 171 | "ATTRIB fogfactor = fragment.fogcoord;\n" |
| 172 | "\n" |
| 173 | "OUTPUT out = result.color;\n" |
| 174 | "\n" |
| 175 | "#Instructions\n" |
| 176 | "TEX t0, coord0, texture[0], 2D;\n" |
| 177 | "TEX t1, coord1, texture[1], 2D;\n" |
| 178 | "\n" |
| 179 | "MAD_SAT out, t0, program.env[1],program.env[0];\n" |
| 180 | //"SUB comb.rgb, t0, 0;\n" |
| 181 | //"MAD_SAT out.rgb, comb, program.env[1], 0;\n" |
| 182 | //"SUB comb.a, t0, 0;\n" |
| 183 | //"MAD_SAT out.a, comb, program.env[1], 0;\n" |
| 184 | "END\n"; |
| 185 | |
| 186 | char oglNewFP[4092]; |
| 187 | |
| 188 | char* MuxToOC(uint8 val) |
| 189 | { |
| 190 | // For color channel |
| 191 | if( val&MUX_ALPHAREPLICATE ) |
| 192 | return (char*)muxToFP_Maps[val&0x1F][1]; |
| 193 | else |
| 194 | return (char*)muxToFP_Maps[val&0x1F][0]; |
| 195 | } |
| 196 | |
| 197 | char* MuxToOA(uint8 val) |
| 198 | { |
| 199 | // For alpha channel |
| 200 | return (char*)muxToFP_Maps[val&0x1F][0]; |
| 201 | } |
| 202 | |
| 203 | static void CheckFpVars(uint8 MuxVar, bool &bNeedT0, bool &bNeedT1) |
| 204 | { |
| 205 | MuxVar &= 0x1f; |
| 206 | if (MuxVar == MUX_TEXEL0 || MuxVar == MUX_T0_ALPHA) |
| 207 | bNeedT0 = true; |
| 208 | if (MuxVar == MUX_TEXEL1 || MuxVar == MUX_T1_ALPHA) |
| 209 | bNeedT1 = true; |
| 210 | } |
| 211 | |
| 212 | void COGL_FragmentProgramCombiner::GenerateProgramStr() |
| 213 | { |
| 214 | DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux; |
| 215 | |
| 216 | mux.splitType[0] = mux.splitType[1] = mux.splitType[2] = mux.splitType[3] = CM_FMT_TYPE_NOT_CHECKED; |
| 217 | m_pDecodedMux->Reformat(false); |
| 218 | |
| 219 | char tempstr[500], newFPBody[4092]; |
| 220 | bool bNeedT0 = false, bNeedT1 = false, bNeedComb2 = false; |
| 221 | newFPBody[0] = 0; |
| 222 | |
| 223 | for( int cycle=0; cycle<2; cycle++ ) |
| 224 | { |
| 225 | for( int channel=0; channel<2; channel++) |
| 226 | { |
| 227 | char* (*func)(uint8) = channel==0?MuxToOC:MuxToOA; |
| 228 | char *dst = channel==0?(char*)"rgb":(char*)"a"; |
| 229 | N64CombinerType &m = mux.m_n64Combiners[cycle*2+channel]; |
| 230 | switch( mux.splitType[cycle*2+channel] ) |
| 231 | { |
| 232 | case CM_FMT_TYPE_NOT_USED: |
| 233 | tempstr[0] = 0; |
| 234 | break; |
| 235 | case CM_FMT_TYPE_D: |
| 236 | sprintf(tempstr, "MOV comb.%s, %s;\n", dst, func(m.d)); |
| 237 | CheckFpVars(m.d, bNeedT0, bNeedT1); |
| 238 | break; |
| 239 | case CM_FMT_TYPE_A_MOD_C: |
| 240 | sprintf(tempstr, "MUL comb.%s, %s, %s;\n", dst, func(m.a), func(m.c)); |
| 241 | CheckFpVars(m.a, bNeedT0, bNeedT1); |
| 242 | CheckFpVars(m.c, bNeedT0, bNeedT1); |
| 243 | break; |
| 244 | case CM_FMT_TYPE_A_ADD_D: |
| 245 | sprintf(tempstr, "ADD_SAT comb.%s, %s, %s;\n", dst, func(m.a), func(m.d)); |
| 246 | CheckFpVars(m.a, bNeedT0, bNeedT1); |
| 247 | CheckFpVars(m.d, bNeedT0, bNeedT1); |
| 248 | break; |
| 249 | case CM_FMT_TYPE_A_SUB_B: |
| 250 | sprintf(tempstr, "SUB comb.%s, %s, %s;\n", dst, func(m.a), func(m.b)); |
| 251 | CheckFpVars(m.a, bNeedT0, bNeedT1); |
| 252 | CheckFpVars(m.b, bNeedT0, bNeedT1); |
| 253 | break; |
| 254 | case CM_FMT_TYPE_A_MOD_C_ADD_D: |
| 255 | sprintf(tempstr, "MAD_SAT comb.%s, %s, %s, %s;\n", dst, func(m.a), func(m.c), func(m.d)); |
| 256 | CheckFpVars(m.a, bNeedT0, bNeedT1); |
| 257 | CheckFpVars(m.c, bNeedT0, bNeedT1); |
| 258 | CheckFpVars(m.d, bNeedT0, bNeedT1); |
| 259 | break; |
| 260 | case CM_FMT_TYPE_A_LERP_B_C: |
| 261 | sprintf(tempstr, "LRP_SAT comb.%s, %s, %s, %s;\n", dst, func(m.c), func(m.a), func(m.b)); |
| 262 | CheckFpVars(m.a, bNeedT0, bNeedT1); |
| 263 | CheckFpVars(m.b, bNeedT0, bNeedT1); |
| 264 | CheckFpVars(m.c, bNeedT0, bNeedT1); |
| 265 | //sprintf(tempstr, "SUB comb.%s, %s, %s;\nMAD_SAT comb.%s, comb, %s, %s;\n", dst, func(m.a), func(m.b), dst, func(m.c), func(m.b)); |
| 266 | break; |
| 267 | default: |
| 268 | sprintf(tempstr, "SUB comb2.%s, %s, %s;\nMAD_SAT comb.%s, comb2, %s, %s;\n", dst, func(m.a), func(m.b), dst, func(m.c), func(m.d)); |
| 269 | CheckFpVars(m.a, bNeedT0, bNeedT1); |
| 270 | CheckFpVars(m.b, bNeedT0, bNeedT1); |
| 271 | CheckFpVars(m.c, bNeedT0, bNeedT1); |
| 272 | CheckFpVars(m.d, bNeedT0, bNeedT1); |
| 273 | bNeedComb2 = true; |
| 274 | break; |
| 275 | } |
| 276 | strcat(newFPBody, tempstr); |
| 277 | } |
| 278 | } |
| 279 | |
| 280 | strcpy(oglNewFP, "!!ARBfp1.0\n"); |
| 281 | strcat(oglNewFP, "#Declarations\n"); |
| 282 | if (gRDP.bFogEnableInBlender && gRSP.bFogEnabled) |
| 283 | strcat(oglNewFP, "OPTION ARB_fog_linear;\n"); |
| 284 | if (bNeedT0) |
| 285 | strcat(oglNewFP, "TEMP t0;\n"); |
| 286 | if (bNeedT1) |
| 287 | strcat(oglNewFP, "TEMP t1;\n"); |
| 288 | strcat(oglNewFP, "TEMP comb;\n"); |
| 289 | if (bNeedComb2) |
| 290 | strcat(oglNewFP, "TEMP comb2;\n"); |
| 291 | strcat(oglNewFP, "#Instructions\n"); |
| 292 | if (bNeedT0) |
| 293 | strcat(oglNewFP, "TEX t0, fragment.texcoord[0], texture[0], 2D;\n"); |
| 294 | if (bNeedT1) |
| 295 | strcat(oglNewFP, "TEX t1, fragment.texcoord[1], texture[1], 2D;\n"); |
| 296 | strcat(oglNewFP, "# N64 cycle 1, result is in comb\n"); |
| 297 | |
| 298 | strcat(oglNewFP, newFPBody); |
| 299 | |
| 300 | strcat(oglNewFP, "MOV result.color, comb;\n"); |
| 301 | strcat(oglNewFP, "END\n\n"); |
| 302 | } |
| 303 | |
| 304 | int COGL_FragmentProgramCombiner::ParseDecodedMux() |
| 305 | { |
| 306 | if( !m_bFragmentProgramIsSupported ) |
| 307 | return COGLColorCombiner4::ParseDecodedMux(); |
| 308 | |
| 309 | OGLShaderCombinerSaveType res; |
| 310 | |
| 311 | pglGenProgramsARB( 1, &res.programID); |
| 312 | OPENGL_CHECK_ERRORS; |
| 313 | pglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, res.programID); |
| 314 | OPENGL_CHECK_ERRORS; |
| 315 | GenerateProgramStr(); |
| 316 | |
| 317 | pglProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(oglNewFP), oglNewFP); |
| 318 | OPENGL_CHECK_ERRORS; |
| 319 | //pglProgramStringARB( GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(oglFPTest), oglFPTest); |
| 320 | |
| 321 | if (glGetError() != 0) |
| 322 | { |
| 323 | GLint position; |
| 324 | #ifdef DEBUGGER |
| 325 | char *str = (char*)glGetString(GL_PROGRAM_ERROR_STRING_ARB); |
| 326 | #endif |
| 327 | glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &position); |
| 328 | if( position >= 0 ) |
| 329 | { |
| 330 | #ifdef DEBUGGER |
| 331 | if( m_lastIndex >= 0 ) COGLColorCombiner4::DisplaySimpleMuxString(); |
| 332 | DebugMessage(M64MSG_ERROR, "%s - %s", str, oglNewFP+position); |
| 333 | #endif |
| 334 | glDisable(GL_FRAGMENT_PROGRAM_ARB); |
| 335 | return COGLColorCombiner4::ParseDecodedMux(); |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | glEnable(GL_FRAGMENT_PROGRAM_ARB); |
| 340 | OPENGL_CHECK_ERRORS; |
| 341 | res.dwMux0 = m_pDecodedMux->m_dwMux0; |
| 342 | res.dwMux1 = m_pDecodedMux->m_dwMux1; |
| 343 | res.fogIsUsed = gRDP.bFogEnableInBlender && gRSP.bFogEnabled; |
| 344 | |
| 345 | m_vCompiledShaders.push_back(res); |
| 346 | m_lastIndex = m_vCompiledShaders.size()-1; |
| 347 | |
| 348 | return m_lastIndex; |
| 349 | } |
| 350 | |
| 351 | void COGL_FragmentProgramCombiner::GenerateCombinerSetting(int index) |
| 352 | { |
| 353 | GLuint ID = m_vCompiledShaders[index].programID; |
| 354 | pglBindProgramARB( GL_FRAGMENT_PROGRAM_ARB, ID ); |
| 355 | OPENGL_CHECK_ERRORS; |
| 356 | glEnable(GL_FRAGMENT_PROGRAM_ARB); |
| 357 | OPENGL_CHECK_ERRORS; |
| 358 | } |
| 359 | |
| 360 | void COGL_FragmentProgramCombiner::GenerateCombinerSettingConstants(int index) |
| 361 | { |
| 362 | float *pf; |
| 363 | pf = GetEnvColorfv(); |
| 364 | pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 1, pf); |
| 365 | OPENGL_CHECK_ERRORS; |
| 366 | pf = GetPrimitiveColorfv(); |
| 367 | pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 2, pf); |
| 368 | OPENGL_CHECK_ERRORS; |
| 369 | |
| 370 | float frac = gRDP.LODFrac / 255.0f; |
| 371 | float tempf[4] = {frac,frac,frac,frac}; |
| 372 | pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 3, tempf); |
| 373 | OPENGL_CHECK_ERRORS; |
| 374 | |
| 375 | float frac2 = gRDP.primLODFrac / 255.0f; |
| 376 | float tempf2[4] = {frac2,frac2,frac2,frac2}; |
| 377 | pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 4, tempf2); |
| 378 | OPENGL_CHECK_ERRORS; |
| 379 | |
| 380 | float tempf3[4] = {0,0,0,0}; |
| 381 | pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, tempf3); |
| 382 | OPENGL_CHECK_ERRORS; |
| 383 | pglProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 6, tempf3); |
| 384 | OPENGL_CHECK_ERRORS; |
| 385 | } |
| 386 | |
| 387 | int COGL_FragmentProgramCombiner::FindCompiledMux() |
| 388 | { |
| 389 | #ifdef DEBUGGER |
| 390 | if( debuggerDropCombiners ) |
| 391 | { |
| 392 | m_vCompiledShaders.clear(); |
| 393 | //m_dwLastMux0 = m_dwLastMux1 = 0; |
| 394 | debuggerDropCombiners = false; |
| 395 | } |
| 396 | #endif |
| 397 | for( uint32 i=0; i<m_vCompiledShaders.size(); i++ ) |
| 398 | { |
| 399 | if( m_vCompiledShaders[i].dwMux0 == m_pDecodedMux->m_dwMux0 |
| 400 | && m_vCompiledShaders[i].dwMux1 == m_pDecodedMux->m_dwMux1 |
| 401 | && m_vCompiledShaders[i].fogIsUsed == (gRDP.bFogEnableInBlender && gRSP.bFogEnabled) ) |
| 402 | return (int)i; |
| 403 | } |
| 404 | |
| 405 | return -1; |
| 406 | } |
| 407 | |
| 408 | ////////////////////////////////////////////////////////////////////////// |
| 409 | void COGL_FragmentProgramCombiner::InitCombinerCycle12(void) |
| 410 | { |
| 411 | if( !m_bFragmentProgramIsSupported ) |
| 412 | { |
| 413 | COGLColorCombiner4::InitCombinerCycle12(); |
| 414 | return; |
| 415 | } |
| 416 | |
| 417 | #ifdef DEBUGGER |
| 418 | if( debuggerDropCombiners ) |
| 419 | { |
| 420 | UpdateCombiner(m_pDecodedMux->m_dwMux0,m_pDecodedMux->m_dwMux1); |
| 421 | m_vCompiledShaders.clear(); |
| 422 | m_dwLastMux0 = m_dwLastMux1 = 0; |
| 423 | debuggerDropCombiners = false; |
| 424 | } |
| 425 | #endif |
| 426 | |
| 427 | m_pOGLRender->EnableMultiTexture(); |
| 428 | |
| 429 | bool combinerIsChanged = false; |
| 430 | |
| 431 | if( m_pDecodedMux->m_dwMux0 != m_dwLastMux0 || m_pDecodedMux->m_dwMux1 != m_dwLastMux1 || m_lastIndex < 0 ) |
| 432 | { |
| 433 | combinerIsChanged = true; |
| 434 | m_lastIndex = FindCompiledMux(); |
| 435 | if( m_lastIndex < 0 ) // Can not found |
| 436 | { |
| 437 | m_lastIndex = ParseDecodedMux(); |
| 438 | } |
| 439 | |
| 440 | m_dwLastMux0 = m_pDecodedMux->m_dwMux0; |
| 441 | m_dwLastMux1 = m_pDecodedMux->m_dwMux1; |
| 442 | } |
| 443 | |
| 444 | |
| 445 | GenerateCombinerSettingConstants(m_lastIndex); |
| 446 | if( m_bCycleChanged || combinerIsChanged || gRDP.texturesAreReloaded || gRDP.colorsAreReloaded ) |
| 447 | { |
| 448 | if( m_bCycleChanged || combinerIsChanged ) |
| 449 | { |
| 450 | GenerateCombinerSettingConstants(m_lastIndex); |
| 451 | GenerateCombinerSetting(m_lastIndex); |
| 452 | } |
| 453 | else if( gRDP.colorsAreReloaded ) |
| 454 | { |
| 455 | GenerateCombinerSettingConstants(m_lastIndex); |
| 456 | } |
| 457 | |
| 458 | m_pOGLRender->SetAllTexelRepeatFlag(); |
| 459 | |
| 460 | gRDP.colorsAreReloaded = false; |
| 461 | gRDP.texturesAreReloaded = false; |
| 462 | } |
| 463 | else |
| 464 | { |
| 465 | m_pOGLRender->SetAllTexelRepeatFlag(); |
| 466 | } |
| 467 | } |
| 468 | |
| 469 | #ifdef DEBUGGER |
| 470 | void COGL_FragmentProgramCombiner::DisplaySimpleMuxString(void) |
| 471 | { |
| 472 | COGLColorCombiner::DisplaySimpleMuxString(); |
| 473 | DecodedMuxForPixelShader &mux = *(DecodedMuxForPixelShader*)m_pDecodedMux; |
| 474 | mux.Reformat(false); |
| 475 | GenerateProgramStr(); |
| 476 | //sprintf(oglNewFP, oglFP, |
| 477 | // MuxToOC(mux.aRGB0), MuxToOC(mux.bRGB0), MuxToOC(mux.cRGB0), MuxToOC(mux.dRGB0), |
| 478 | // MuxToOA(mux.aA0), MuxToOA(mux.bA0), MuxToOA(mux.cA0), MuxToOA(mux.dA0), |
| 479 | // MuxToOC(mux.aRGB1), MuxToOC(mux.bRGB1), MuxToOC(mux.cRGB1), MuxToOC(mux.dRGB1), |
| 480 | // MuxToOA(mux.aA1), MuxToOA(mux.bA1), MuxToOA(mux.cA1), MuxToOA(mux.dA1) |
| 481 | // ); |
| 482 | |
| 483 | TRACE0("OGL Fragment Program:"); |
| 484 | TRACE0(oglNewFP); |
| 485 | } |
| 486 | #endif |
| 487 | |