1 /****************************************************************************** 2 3 @File OGLES2/PVRTPFXParserAPI.cpp 4 5 @Title OGLES2/PVRTPFXParserAPI 6 7 @Version 8 9 @Copyright Copyright (c) Imagination Technologies Limited. 10 11 @Platform ANSI compatible 12 13 @Description PFX file parser. 14 15 ******************************************************************************/ 16 17 /***************************************************************************** 18 ** Includes 19 *****************************************************************************/ 20 #include <stdio.h> 21 #include <string.h> 22 #include <stdlib.h> 23 24 #include "PVRTContext.h" 25 #include "PVRTMatrix.h" 26 #include "PVRTFixedPoint.h" 27 #include "PVRTString.h" 28 #include "PVRTShader.h" 29 #include "PVRTPFXParser.h" 30 #include "PVRTPFXParserAPI.h" 31 #include "PVRTPFXSemantics.h" 32 #include "PVRTTexture.h" 33 #include "PVRTTextureAPI.h" 34 35 /*!*************************************************************************** 36 @Function CPVRTPFXEffect Constructor 37 @Description Sets the context and initialises the member variables to zero. 38 *****************************************************************************/ 39 CPVRTPFXEffect::CPVRTPFXEffect(): 40 m_bLoaded(false), m_psContext(NULL), m_pParser(NULL), m_nEffect(0), m_uiProgram(0), m_Semantics(PVRTPFXSemanticsGetSemanticList(), ePVRTPFX_NumSemantics) 41 { 42 } 43 44 /*!*************************************************************************** 45 @Function CPVRTPFXEffect Constructor 46 @Description Sets the context and initialises the member variables to zero. 47 *****************************************************************************/ 48 CPVRTPFXEffect::CPVRTPFXEffect(SPVRTContext &sContext): 49 m_bLoaded(false), m_psContext(&sContext), m_pParser(NULL), m_nEffect(0), m_uiProgram(0), m_Semantics(PVRTPFXSemanticsGetSemanticList(), ePVRTPFX_NumSemantics) 50 { 51 } 52 53 /*!*************************************************************************** 54 @Function CPVRTPFXEffect Destructor 55 @Description Calls Destroy(). 56 *****************************************************************************/ 57 CPVRTPFXEffect::~CPVRTPFXEffect() 58 { 59 Destroy(); 60 61 // Free allocated strings 62 for(unsigned int uiIndex = ePVRTPFX_NumSemantics; uiIndex < m_Semantics.GetSize(); ++uiIndex) 63 { 64 delete [] m_Semantics[uiIndex].p; 65 m_Semantics[uiIndex].p = NULL; 66 } 67 } 68 69 /*!*************************************************************************** 70 @Function Load 71 @Input src PFX Parser Object 72 @Input pszEffect Effect name 73 @Input pszFileName Effect file name 74 @Output pReturnError Error string 75 @Returns EPVRTError PVR_SUCCESS if load succeeded 76 @Description Loads the specified effect from the CPVRTPFXParser object. 77 Compiles and links the shaders. Initialises texture data. 78 *****************************************************************************/ 79 EPVRTError CPVRTPFXEffect::Load(CPVRTPFXParser &src, const char * const pszEffect, const char * const pszFileName, 80 PVRTPFXEffectDelegate* pDelegate, unsigned int& uiUnknownUniforms, CPVRTString *pReturnError) 81 { 82 unsigned int i; 83 84 if(!src.GetNumberEffects()) 85 return PVR_FAIL; 86 87 // --- First find the named effect from the effect file 88 if(pszEffect) 89 { 90 int iEffect = src.FindEffectByName(CPVRTStringHash(pszEffect)); 91 if(iEffect == -1) 92 return PVR_FAIL; 93 94 m_nEffect = (unsigned int)iEffect; 95 } 96 else 97 { 98 m_nEffect = 0; 99 } 100 101 // --- Now load the effect 102 m_pParser = &src; 103 const SPVRTPFXParserEffect &ParserEffect = src.GetEffect(m_nEffect); 104 105 // Create room for per-texture data 106 const CPVRTArray<SPVRTPFXParserEffectTexture>& EffectTextures = src.GetEffect(m_nEffect).Textures; 107 unsigned int uiNumTexturesForEffect = EffectTextures.GetSize(); 108 m_Textures.SetCapacity(uiNumTexturesForEffect); 109 110 // Initialise each Texture 111 for(i = 0; i < uiNumTexturesForEffect; ++i) 112 { 113 int iTexIdx = src.FindTextureByName(EffectTextures[i].Name); 114 if(iTexIdx < 0) 115 { 116 *pReturnError += PVRTStringFromFormattedStr("ERROR: Effect '%s' requests non-existent texture: %s\n", ParserEffect.Name.c_str(), EffectTextures[i].Name.c_str()); 117 return PVR_FAIL; 118 } 119 120 unsigned int uiTexIdx = m_Textures.Append(); 121 m_Textures[uiTexIdx].Name = src.GetTexture((unsigned int)iTexIdx)->Name; 122 m_Textures[uiTexIdx].ui = 0xFFFFFFFF; 123 m_Textures[uiTexIdx].flags = 0; 124 m_Textures[uiTexIdx].unit = 0; 125 } 126 127 // Load the shaders 128 if(LoadShadersForEffect(src, pszFileName, pReturnError) != PVR_SUCCESS) 129 return PVR_FAIL; 130 131 // Build uniform table 132 if(RebuildUniformTable(uiUnknownUniforms, pReturnError) != PVR_SUCCESS) 133 return PVR_FAIL; 134 135 // Load the requested textures 136 if(pDelegate) 137 { 138 if(LoadTexturesForEffect(pDelegate, pReturnError) != PVR_SUCCESS) 139 return PVR_FAIL; 140 } 141 142 m_bLoaded = true; 143 144 return PVR_SUCCESS; 145 } 146 147 /*!*************************************************************************** 148 @Function LoadTexturesForEffect 149 @Output pReturnError 150 @Return EPVRTError 151 @Description Loads all of the textures for this effect. 152 *****************************************************************************/ 153 EPVRTError CPVRTPFXEffect::LoadTexturesForEffect(PVRTPFXEffectDelegate* pDelegate, CPVRTString *pReturnError) 154 { 155 GLuint uiHandle; 156 unsigned int uiFlags; 157 158 for(unsigned int i = 0; i < m_Textures.GetSize(); ++i) 159 { 160 int iTexID = m_pParser->FindTextureByName(m_Textures[i].Name); 161 if(iTexID == -1) 162 { 163 *pReturnError += PVRTStringFromFormattedStr("ERROR: Cannot find texture '%s' in any TEXTURE block.\n", m_Textures[i].Name.c_str()); 164 return PVR_FAIL; 165 } 166 167 const SPVRTPFXParserTexture* pTexDesc = m_pParser->GetTexture(iTexID); 168 169 170 uiHandle = 0xBADF00D; 171 uiFlags = 0; 172 173 if(pDelegate->PVRTPFXOnLoadTexture(pTexDesc->FileName, uiHandle, uiFlags) != PVR_SUCCESS) 174 { 175 *pReturnError += PVRTStringFromFormattedStr("ERROR: Failed to load texture: %s.\n", pTexDesc->FileName.c_str()); 176 return PVR_FAIL; 177 } 178 179 // Make sure uiHandle was written. 180 if(uiHandle == 0xBADF00D) 181 { 182 *pReturnError += PVRTStringFromFormattedStr("ERROR: GL handle for texture '%s' not set!\n", pTexDesc->FileName.c_str()); 183 return PVR_FAIL; 184 } 185 186 SetTexture(i, uiHandle, uiFlags); 187 } 188 189 return PVR_SUCCESS; 190 } 191 192 /*!*************************************************************************** 193 @Function LoadShadersForEffect 194 @Input pszFileName 195 @Output pReturnError 196 @Return EPVRTError 197 @Description Loads all of the GLSL shaders for an effect. 198 *****************************************************************************/ 199 EPVRTError CPVRTPFXEffect::LoadShadersForEffect(CPVRTPFXParser &src, const char * const pszFileName, CPVRTString *pReturnError) 200 { 201 // initialise attributes to default values 202 char *pszVertexShader = NULL; 203 char *pszFragmentShader = NULL; 204 bool bFreeVertexShader = false; 205 bool bFreeFragmentShader = false; 206 unsigned int uiVertIdx = 0; 207 unsigned int uiFragIdx = 0; 208 unsigned int uiVertexShader = 0; 209 unsigned int uiFragShader = 0; 210 211 const SPVRTPFXParserEffect &ParserEffect = src.GetEffect(m_nEffect); 212 213 // find shaders requested 214 for(uiVertIdx = 0; uiVertIdx < src.GetNumberVertexShaders(); ++uiVertIdx) 215 { 216 const SPVRTPFXParserShader& VertexShader = src.GetVertexShader(uiVertIdx); 217 if(ParserEffect.VertexShaderName == VertexShader.Name) 218 { 219 if(VertexShader.bUseFileName) 220 { 221 pszVertexShader = VertexShader.pszGLSLcode; 222 } 223 else 224 { 225 if(!VertexShader.pszGLSLcode) 226 continue; // No code specified. 227 #if 0 228 // offset glsl code by nFirstLineNumber 229 pszVertexShader = (char *)malloc((strlen(VertexShader.pszGLSLcode) + (VertexShader.nFirstLineNumber) + 1) * sizeof(char)); 230 pszVertexShader[0] = '\0'; 231 for(unsigned int n = 0; n < VertexShader.nFirstLineNumber; n++) 232 strcat(pszVertexShader, "\n"); 233 strcat(pszVertexShader, VertexShader.pszGLSLcode); 234 #else 235 pszVertexShader = (char *)malloc(strlen(VertexShader.pszGLSLcode) + 1); 236 pszVertexShader[0] = '\0'; 237 strcat(pszVertexShader, VertexShader.pszGLSLcode); 238 #endif 239 bFreeVertexShader = true; 240 } 241 242 break; 243 } 244 } 245 for(uiFragIdx = 0; uiFragIdx < src.GetNumberFragmentShaders(); ++uiFragIdx) 246 { 247 const SPVRTPFXParserShader& FragmentShader = src.GetFragmentShader(uiFragIdx); 248 if(ParserEffect.FragmentShaderName == FragmentShader.Name) 249 { 250 if(FragmentShader.bUseFileName) 251 { 252 pszFragmentShader = FragmentShader.pszGLSLcode; 253 } 254 else 255 { 256 if(!FragmentShader.pszGLSLcode) 257 continue; // No code specified. 258 259 #if 0 260 // offset glsl code by nFirstLineNumber 261 pszFragmentShader = (char *)malloc((strlen(FragmentShader.pszGLSLcode) + (FragmentShader.nFirstLineNumber) + 1) * sizeof(char)); 262 pszFragmentShader[0] = '\0'; 263 for(unsigned int n = 0; n < FragmentShader.nFirstLineNumber; n++) 264 strcat(pszFragmentShader, "\n"); 265 strcat(pszFragmentShader, FragmentShader.pszGLSLcode); 266 #else 267 pszFragmentShader = (char *)malloc(strlen(FragmentShader.pszGLSLcode) + 1); 268 pszFragmentShader[0] = '\0'; 269 strcat(pszFragmentShader, FragmentShader.pszGLSLcode); 270 #endif 271 bFreeFragmentShader = true; 272 } 273 274 break; 275 } 276 } 277 278 CPVRTString error; 279 bool bLoadSource = 1; 280 281 // Try first to load from the binary block 282 if (src.GetVertexShader(uiVertIdx).pbGLSLBinary!=NULL) 283 { 284 #if defined(GL_SGX_BINARY_IMG) 285 if (PVRTShaderLoadBinaryFromMemory(src.GetVertexShader(uiVertIdx).pbGLSLBinary, src.GetVertexShader(uiVertIdx).nGLSLBinarySize, 286 GL_VERTEX_SHADER, GL_SGX_BINARY_IMG, &uiVertexShader, &error) == PVR_SUCCESS) 287 { 288 // success loading the binary block so we do not need to load the source 289 bLoadSource = 0; 290 } 291 else 292 #endif 293 { 294 bLoadSource = 1; 295 } 296 } 297 298 // If it fails, load from source 299 if (bLoadSource) 300 { 301 if(pszVertexShader) 302 { 303 if (PVRTShaderLoadSourceFromMemory(pszVertexShader, GL_VERTEX_SHADER, &uiVertexShader, &error) != PVR_SUCCESS) 304 { 305 *pReturnError = CPVRTString("ERROR: Vertex Shader compile error in file '") + pszFileName + "':\n" + error; 306 if(bFreeVertexShader) FREE(pszVertexShader); 307 if(bFreeFragmentShader) FREE(pszFragmentShader); 308 return PVR_FAIL; 309 } 310 } 311 else // Shader not found or failed binary block 312 { 313 if (src.GetVertexShader(uiVertIdx).pbGLSLBinary==NULL) 314 { 315 *pReturnError = CPVRTString("ERROR: Vertex shader ") + ParserEffect.VertexShaderName.String() + " not found in " + pszFileName + ".\n"; 316 } 317 else 318 { 319 *pReturnError = CPVRTString("ERROR: Binary vertex shader ") + ParserEffect.VertexShaderName.String() + " not supported.\n"; 320 } 321 322 if(bFreeVertexShader) FREE(pszVertexShader); 323 if(bFreeFragmentShader) FREE(pszFragmentShader); 324 return PVR_FAIL; 325 } 326 } 327 328 // Try first to load from the binary block 329 if (src.GetFragmentShader(uiFragIdx).pbGLSLBinary!=NULL) 330 { 331 #if defined(GL_SGX_BINARY_IMG) 332 if (PVRTShaderLoadBinaryFromMemory(src.GetFragmentShader(uiFragIdx).pbGLSLBinary, src.GetFragmentShader(uiFragIdx).nGLSLBinarySize, 333 GL_FRAGMENT_SHADER, GL_SGX_BINARY_IMG, &uiFragShader, &error) == PVR_SUCCESS) 334 { 335 // success loading the binary block so we do not need to load the source 336 bLoadSource = 0; 337 } 338 else 339 #endif 340 { 341 bLoadSource = 1; 342 } 343 } 344 345 // If it fails, load from source 346 if (bLoadSource) 347 { 348 if(pszFragmentShader) 349 { 350 if (PVRTShaderLoadSourceFromMemory(pszFragmentShader, GL_FRAGMENT_SHADER, &uiFragShader, &error) != PVR_SUCCESS) 351 { 352 *pReturnError = CPVRTString("ERROR: Fragment Shader compile error in file '") + pszFileName + "':\n" + error; 353 if(bFreeVertexShader) FREE(pszVertexShader); 354 if(bFreeFragmentShader) FREE(pszFragmentShader); 355 return PVR_FAIL; 356 } 357 } 358 else // Shader not found or failed binary block 359 { 360 if (src.GetFragmentShader(uiFragIdx).pbGLSLBinary==NULL) 361 { 362 *pReturnError = CPVRTString("ERROR: Fragment shader ") + ParserEffect.FragmentShaderName.String() + " not found in " + pszFileName + ".\n"; 363 } 364 else 365 { 366 *pReturnError = CPVRTString("ERROR: Binary Fragment shader ") + ParserEffect.FragmentShaderName.String() + " not supported.\n"; 367 } 368 369 if(bFreeVertexShader) 370 FREE(pszVertexShader); 371 if(bFreeFragmentShader) 372 FREE(pszFragmentShader); 373 374 return PVR_FAIL; 375 } 376 } 377 378 if(bFreeVertexShader) 379 FREE(pszVertexShader); 380 381 if(bFreeFragmentShader) 382 FREE(pszFragmentShader); 383 384 // Create the shader program 385 m_uiProgram = glCreateProgram(); 386 387 388 // Attach the fragment and vertex shaders to it 389 glAttachShader(m_uiProgram, uiFragShader); 390 glAttachShader(m_uiProgram, uiVertexShader); 391 392 glDeleteShader(uiVertexShader); 393 glDeleteShader(uiFragShader); 394 395 // Bind vertex attributes 396 for(unsigned int i = 0; i < ParserEffect.Attributes.GetSize(); ++i) 397 { 398 glBindAttribLocation(m_uiProgram, i, ParserEffect.Attributes[i].pszName); 399 } 400 401 // Link the program. 402 glLinkProgram(m_uiProgram); 403 GLint Linked; 404 glGetProgramiv(m_uiProgram, GL_LINK_STATUS, &Linked); 405 if (!Linked) 406 { 407 int i32InfoLogLength, i32CharsWritten; 408 glGetProgramiv(m_uiProgram, GL_INFO_LOG_LENGTH, &i32InfoLogLength); 409 char* pszInfoLog = new char[i32InfoLogLength]; 410 glGetProgramInfoLog(m_uiProgram, i32InfoLogLength, &i32CharsWritten, pszInfoLog); 411 *pReturnError = CPVRTString("ERROR: Linking shaders in file '") + pszFileName + "':\n\n" 412 + CPVRTString("Failed to link: ") + pszInfoLog + "\n"; 413 delete [] pszInfoLog; 414 return PVR_FAIL; 415 } 416 417 return PVR_SUCCESS; 418 } 419 420 /*!*************************************************************************** 421 @Function Destroy 422 @Description Deletes the gl program object and texture data. 423 *****************************************************************************/ 424 void CPVRTPFXEffect::Destroy() 425 { 426 { 427 if(m_uiProgram != 0) 428 { 429 GLint val; 430 glGetProgramiv(m_uiProgram, GL_DELETE_STATUS, &val); 431 if(val == GL_FALSE) 432 { 433 glDeleteProgram(m_uiProgram); 434 } 435 m_uiProgram = 0; 436 } 437 } 438 439 m_bLoaded = false; 440 } 441 442 /*!*************************************************************************** 443 @Function Activate 444 @Returns PVR_SUCCESS if activate succeeded 445 @Description Selects the gl program object and binds the textures. 446 *****************************************************************************/ 447 EPVRTError CPVRTPFXEffect::Activate(const int i32RenderTextureId, const unsigned int ui32ReplacementTexture) 448 { 449 GLuint uiTextureId; 450 GLenum eTarget; 451 452 // Set the program 453 glUseProgram(m_uiProgram); 454 455 // Set the textures 456 for(unsigned int uiTex = 0; uiTex < m_Textures.GetSize(); ++uiTex) 457 { 458 uiTextureId = m_Textures[uiTex].ui; 459 if(i32RenderTextureId != -1 && (uiTextureId == (unsigned int)i32RenderTextureId)) 460 uiTextureId = ui32ReplacementTexture; 461 462 // Set active texture unit. 463 glActiveTexture(GL_TEXTURE0 + m_Textures[uiTex].unit); 464 465 // Bind texture 466 eTarget = (m_Textures[uiTex].flags & PVRTEX_CUBEMAP ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D); 467 glBindTexture(eTarget, uiTextureId); 468 } 469 470 return PVR_SUCCESS; 471 } 472 473 /*!*************************************************************************** 474 @Function GetSemantics 475 @Output aUniforms an array of uniform data 476 @Output pnUnknownUniformCount unknown uniform count 477 @Input psParams pointer to semantic data array 478 @Input nParamCount number of samantic items 479 @Input psUniformSemantics pointer to uniform semantics array 480 @Input nUniformSemantics number of uniform semantic items 481 @Input pglesExt opengl extensions object 482 @Input uiProgram program object index 483 @Input bIsAttribue true if getting attribute semantics 484 @Output errorMsg error string 485 @Returns unsigned int number of successful semantics 486 @Description Get the data array for the semantics. 487 *****************************************************************************/ 488 static unsigned int GetSemantics( 489 CPVRTArray<SPVRTPFXUniform>& aUniforms, 490 const CPVRTArray<SPVRTPFXParserSemantic>& aParams, 491 const CPVRTArray<SPVRTPFXUniformSemantic>& aUniformSemantics, 492 unsigned int* const pnUnknownUniformCount, 493 const GLuint uiProgram, 494 bool bIsAttribue, 495 CPVRTString* const errorMsg) 496 { 497 unsigned int i, j, nCount, nCountUnused; 498 int nLocation; 499 500 /* 501 Loop over the parameters searching for their semantics. If 502 found/recognised, it should be placed in the output array. 503 */ 504 nCount = 0; 505 nCountUnused = 0; 506 char szTmpUniformName[2048]; // Temporary buffer to use for building uniform names. 507 508 for(j = 0; j < aParams.GetSize(); ++j) 509 { 510 for(i = 0; i < aUniformSemantics.GetSize(); ++i) 511 { 512 if(strcmp(aParams[j].pszValue, aUniformSemantics[i].p) != 0) 513 { 514 continue; 515 } 516 517 // Semantic found for this parameter 518 if(bIsAttribue) 519 { 520 nLocation = glGetAttribLocation(uiProgram, aParams[j].pszName); 521 } 522 else 523 { 524 nLocation = glGetUniformLocation(uiProgram, aParams[j].pszName); 525 526 // Check for array. Workaround for some OpenGL:ES implementations which require array element appended to uniform name 527 // in order to return the correct location. 528 if(nLocation == -1) 529 { 530 strcpy(szTmpUniformName, aParams[j].pszName); 531 strcat(szTmpUniformName, "[0]"); 532 nLocation = glGetUniformLocation(uiProgram, szTmpUniformName); 533 } 534 } 535 536 if(nLocation != -1) 537 { 538 unsigned int uiIdx = aUniforms.Append(); 539 aUniforms[uiIdx].nSemantic = aUniformSemantics[i].n; 540 aUniforms[uiIdx].nLocation = nLocation; 541 aUniforms[uiIdx].nIdx = aParams[j].nIdx; 542 aUniforms[uiIdx].sValueName = aParams[j].pszName; 543 ++nCount; 544 } 545 else 546 { 547 *errorMsg += "WARNING: Variable not used by GLSL code: "; 548 *errorMsg += CPVRTString(aParams[j].pszName) + " "; 549 *errorMsg += CPVRTString(aParams[j].pszValue) + "\n"; 550 ++nCountUnused; 551 } 552 553 // Skip to the next parameter 554 break; 555 } 556 if(i == aUniformSemantics.GetSize()) 557 { 558 *errorMsg += "WARNING: Semantic unknown to application: "; 559 *errorMsg += CPVRTString(aParams[j].pszValue) + "\n"; 560 } 561 } 562 563 *pnUnknownUniformCount = aParams.GetSize() - nCount - nCountUnused; 564 return nCount; 565 } 566 567 /*!*************************************************************************** 568 @Function GetUniformArray 569 @Return const CPVRTArray<SPVRTPFXUniform>& 570 @Description Returns a list of known semantics. 571 *****************************************************************************/ 572 const CPVRTArray<SPVRTPFXUniform>& CPVRTPFXEffect::GetUniformArray() const 573 { 574 return m_Uniforms; 575 } 576 577 /*!*************************************************************************** 578 @Function BuildUniformTable 579 @Output uiUnknownSemantics 580 @Output pReturnError 581 @Return EPVRTError 582 @Description Builds the uniform table from a list of known semantics. 583 *****************************************************************************/ 584 EPVRTError CPVRTPFXEffect::RebuildUniformTable(unsigned int& uiUnknownSemantics, CPVRTString* pReturnError) 585 { 586 unsigned int nUnknownCount; 587 const SPVRTPFXParserEffect& ParserEffect = m_pParser->GetEffect(m_nEffect); 588 589 GetSemantics(m_Uniforms, ParserEffect.Uniforms, m_Semantics, &nUnknownCount, m_uiProgram, false, pReturnError); 590 uiUnknownSemantics = nUnknownCount; 591 592 GetSemantics(m_Uniforms, ParserEffect.Attributes, m_Semantics, &nUnknownCount, m_uiProgram, true, pReturnError); 593 uiUnknownSemantics += nUnknownCount; 594 595 return PVR_SUCCESS; 596 } 597 598 /*!*************************************************************************** 599 @Function RegisterUniformSemantic 600 @Input psUniforms 601 @Input uiNumUniforms 602 @Return EPVRTError 603 @Description Registers a user-provided uniform semantic. 604 *****************************************************************************/ 605 EPVRTError CPVRTPFXEffect::RegisterUniformSemantic(const SPVRTPFXUniformSemantic* const psUniforms, unsigned int uiNumUniforms, CPVRTString* pReturnError) 606 { 607 for(unsigned int uiIndex = 0; uiIndex < uiNumUniforms; ++uiIndex) 608 { 609 // Check that this doesn't already exist. 610 if(m_Semantics.Contains(psUniforms[uiIndex])) 611 { 612 *pReturnError += PVRTStringFromFormattedStr("ERROR: Uniform semantic with ID '%u' already exists.\n", psUniforms[uiIndex].n); 613 return PVR_FAIL; 614 } 615 616 // Make copy as we need to manage the memory. 617 char* pSemName = new char[strlen(psUniforms[uiIndex].p)+1]; 618 strcpy(pSemName, psUniforms[uiIndex].p); 619 620 unsigned int uiIdx = m_Semantics.Append(); 621 m_Semantics[uiIdx].n = psUniforms[uiIndex].n; 622 m_Semantics[uiIdx].p = pSemName; 623 } 624 625 // Check if the effect has already been loaded. If it hasn't, great. If it has, we need to rebuild the uniform table. 626 if(m_bLoaded) 627 { 628 // Clear the current list. 629 m_Uniforms.Clear(); 630 631 unsigned int uiUnknownSemantics; 632 return RebuildUniformTable(uiUnknownSemantics, pReturnError); 633 } 634 635 return PVR_SUCCESS; 636 } 637 638 /*!*************************************************************************** 639 @Function RemoveUniformSemantic 640 @Input uiSemanticID 641 @Output pReturnError 642 @Return PVR_SUCCESS on success 643 @Description Removes a given semantic ID from the 'known' semantic list and 644 re-parses the effect to update the uniform table. 645 *****************************************************************************/ 646 EPVRTError CPVRTPFXEffect::RemoveUniformSemantic(unsigned int uiSemanticID, CPVRTString* pReturnError) 647 { 648 // Make sure that the given ID isn't a PFX semantic 649 if(uiSemanticID < ePVRTPFX_NumSemantics) 650 { 651 *pReturnError += "ERROR: Cannot remove a default PFX semantic."; 652 return PVR_FAIL; 653 } 654 655 // Find the index in the array 656 unsigned int uiSemanticIndex = 0; 657 while(uiSemanticIndex < m_Semantics.GetSize() && m_Semantics[uiSemanticIndex].n != uiSemanticID) ++uiSemanticIndex; 658 659 if(uiSemanticIndex == m_Semantics.GetSize()) 660 { 661 *pReturnError += PVRTStringFromFormattedStr("ERROR: Semantic with ID %d does not exist.", uiSemanticID); 662 return PVR_FAIL; 663 } 664 665 m_Semantics.Remove(uiSemanticIndex); 666 667 // Check if the effect has already been loaded. If it hasn't, great. If it has, we need to rebuild the uniform table. 668 if(m_bLoaded) 669 { 670 // Clear the current list. 671 m_Uniforms.Clear(); 672 673 unsigned int uiUnknownSemantics; 674 return RebuildUniformTable(uiUnknownSemantics, pReturnError); 675 } 676 677 return PVR_SUCCESS; 678 } 679 680 /*!*************************************************************************** 681 @Function GetTextureArray 682 @Output nCount number of textures 683 @Returns SPVRTPFXTexture* pointer to the texture data array 684 @Description Gets the texture data array. 685 *****************************************************************************/ 686 const CPVRTArray<SPVRTPFXTexture>& CPVRTPFXEffect::GetTextureArray() const 687 { 688 return m_Textures; 689 } 690 691 /*!*************************************************************************** 692 @Function SetTexture 693 @Input nIdx texture number 694 @Input ui opengl texture handle 695 @Input u32flags texture flags 696 @Description Sets the textrue and applys the filtering. 697 *****************************************************************************/ 698 void CPVRTPFXEffect::SetTexture(const unsigned int nIdx, const GLuint ui, const unsigned int u32flags) 699 { 700 if(nIdx < (unsigned int) m_Textures.GetSize()) 701 { 702 GLenum u32Target = GL_TEXTURE_2D; 703 704 // Check if texture is a cubemap 705 if((u32flags & PVRTEX_CUBEMAP) != 0) 706 u32Target = GL_TEXTURE_CUBE_MAP; 707 708 // Get the texture details from the PFX Parser. This contains details such as mipmapping and filter modes. 709 const CPVRTStringHash& TexName = m_pParser->GetEffect(m_nEffect).Textures[nIdx].Name; 710 int iTexIdx = m_pParser->FindTextureByName(TexName); 711 if(iTexIdx == -1) 712 return; 713 714 const SPVRTPFXParserTexture* pPFXTex = m_pParser->GetTexture(iTexIdx); 715 716 // Only change parameters if ui (handle is > 0) 717 if(ui > 0) 718 { 719 glBindTexture(u32Target, ui); 720 721 // Set default filter from PFX file 722 723 // --- Mipmapping/Minification 724 switch(pPFXTex->nMIP) 725 { 726 case eFilter_None: // No mipmapping 727 switch(pPFXTex->nMin) 728 { 729 case eFilter_Nearest: 730 glTexParameteri(u32Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // Off 731 break; 732 case eFilter_Linear: 733 glTexParameteri(u32Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Bilinear - no Mipmap 734 break; 735 } 736 break; 737 case eFilter_Nearest: // Standard mipmapping 738 switch(pPFXTex->nMin) 739 { 740 case eFilter_Nearest: 741 glTexParameteri(u32Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); // Nearest - std. Mipmap 742 break; 743 case eFilter_Linear: 744 glTexParameteri(u32Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); // Bilinear - std. Mipmap 745 break; 746 } 747 break; 748 case eFilter_Linear: // Trilinear mipmapping 749 switch(pPFXTex->nMin) 750 { 751 case eFilter_Nearest: 752 glTexParameteri(u32Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR); // Nearest - Trilinear 753 break; 754 case eFilter_Linear: 755 glTexParameteri(u32Target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // Bilinear - Trilinear 756 break; 757 } 758 break; 759 } 760 761 // --- Magnification 762 switch(pPFXTex->nMag) 763 { 764 case eFilter_Nearest: 765 glTexParameteri(u32Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 766 break; 767 case eFilter_Linear: 768 glTexParameteri(u32Target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 769 break; 770 } 771 772 // --- Wrapping S 773 switch(pPFXTex->nWrapS) 774 { 775 case eWrap_Clamp: 776 glTexParameteri(u32Target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 777 break; 778 case eWrap_Repeat: 779 glTexParameteri(u32Target, GL_TEXTURE_WRAP_S, GL_REPEAT); 780 break; 781 } 782 783 // --- Wrapping T 784 switch(pPFXTex->nWrapT) 785 { 786 case eWrap_Clamp: 787 glTexParameteri(u32Target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 788 break; 789 case eWrap_Repeat: 790 glTexParameteri(u32Target, GL_TEXTURE_WRAP_T, GL_REPEAT); 791 break; 792 } 793 794 // --- Wrapping R 795 #ifdef GL_TEXTURE_WRAP_R 796 switch(pPFXTex->nWrapR) 797 { 798 case eWrap_Clamp: 799 glTexParameteri(u32Target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 800 break; 801 case eWrap_Repeat: 802 glTexParameteri(u32Target, GL_TEXTURE_WRAP_R, GL_REPEAT); 803 break; 804 } 805 #endif 806 } 807 808 // Store the texture details 809 m_Textures[nIdx].ui = ui; 810 m_Textures[nIdx].flags = u32flags; 811 812 // Find the texture unit from the parser 813 unsigned int uiIndex = m_pParser->FindTextureIndex(pPFXTex->Name, m_nEffect); 814 if(uiIndex != 0xFFFFFFFF) 815 { 816 m_Textures[nIdx].unit = m_pParser->GetEffect(m_nEffect).Textures[uiIndex].nNumber; 817 } 818 } 819 } 820 821 822 /*!*************************************************************************** 823 @Function SetDefaultSemanticValue 824 @Input pszName name of uniform 825 @Input psDefaultValue pointer to default value 826 @Description Sets the default value for the uniform semantic. 827 *****************************************************************************/ 828 void CPVRTPFXEffect::SetDefaultUniformValue(const char *const pszName, const SPVRTSemanticDefaultData *psDefaultValue) 829 { 830 831 GLint nLocation = glGetUniformLocation(m_uiProgram, pszName); 832 // Check for array. Workaround for some OpenGL:ES implementations which require array element appended to uniform name 833 // in order to return the correct location. 834 if(nLocation == -1) 835 { 836 char szTmpUniformName[2048]; 837 strcpy(szTmpUniformName, pszName); 838 strcat(szTmpUniformName, "[0]"); 839 nLocation = glGetUniformLocation(m_uiProgram, szTmpUniformName); 840 } 841 842 switch(psDefaultValue->eType) 843 { 844 case eDataTypeMat2: 845 glUniformMatrix2fv(nLocation, 1, GL_FALSE, psDefaultValue->pfData); 846 break; 847 case eDataTypeMat3: 848 glUniformMatrix3fv(nLocation, 1, GL_FALSE, psDefaultValue->pfData); 849 break; 850 case eDataTypeMat4: 851 glUniformMatrix4fv(nLocation, 1, GL_FALSE, psDefaultValue->pfData); 852 break; 853 case eDataTypeVec2: 854 glUniform2fv(nLocation, 1, psDefaultValue->pfData); 855 break; 856 case eDataTypeRGB: 857 case eDataTypeVec3: 858 glUniform3fv(nLocation, 1, psDefaultValue->pfData); 859 break; 860 case eDataTypeRGBA: 861 case eDataTypeVec4: 862 glUniform4fv(nLocation, 1, psDefaultValue->pfData); 863 break; 864 case eDataTypeIvec2: 865 glUniform2iv(nLocation, 1, psDefaultValue->pnData); 866 break; 867 case eDataTypeIvec3: 868 glUniform3iv(nLocation, 1, psDefaultValue->pnData); 869 break; 870 case eDataTypeIvec4: 871 glUniform4iv(nLocation, 1, psDefaultValue->pnData); 872 break; 873 case eDataTypeBvec2: 874 glUniform2i(nLocation, psDefaultValue->pbData[0] ? 1 : 0, psDefaultValue->pbData[1] ? 1 : 0); 875 break; 876 case eDataTypeBvec3: 877 glUniform3i(nLocation, psDefaultValue->pbData[0] ? 1 : 0, psDefaultValue->pbData[1] ? 1 : 0, psDefaultValue->pbData[2] ? 1 : 0); 878 break; 879 case eDataTypeBvec4: 880 glUniform4i(nLocation, psDefaultValue->pbData[0] ? 1 : 0, psDefaultValue->pbData[1] ? 1 : 0, psDefaultValue->pbData[2] ? 1 : 0, psDefaultValue->pbData[3] ? 1 : 0); 881 break; 882 case eDataTypeFloat: 883 glUniform1f(nLocation, psDefaultValue->pfData[0]); 884 break; 885 case eDataTypeInt: 886 glUniform1i(nLocation, psDefaultValue->pnData[0]); 887 break; 888 case eDataTypeBool: 889 glUniform1i(nLocation, psDefaultValue->pbData[0] ? 1 : 0); 890 break; 891 892 case eNumDefaultDataTypes: 893 case eDataTypeNone: 894 default: 895 break; 896 } 897 } 898 899 /*!*************************************************************************** 900 @Function SetContext 901 @Input pContext 902 @Description 903 *****************************************************************************/ 904 void CPVRTPFXEffect::SetContext(SPVRTContext *const pContext) 905 { 906 m_psContext = pContext; 907 } 908 909 /*!*************************************************************************** 910 @Function GetProgramHandle 911 @Return unsigned int 912 @Description Returns the OGL program handle. 913 *****************************************************************************/ 914 unsigned int CPVRTPFXEffect::GetProgramHandle() const 915 { 916 return m_uiProgram; 917 } 918 919 /*!*************************************************************************** 920 @Function GetEffectIndex 921 @Return unsigned int 922 @Description Gets the active effect index within the PFX file. 923 *****************************************************************************/ 924 unsigned int CPVRTPFXEffect::GetEffectIndex() const 925 { 926 return m_nEffect; 927 } 928 929 /*!*************************************************************************** 930 @Function GetSemanticArray 931 @Return const CPVRTArray<SPVRTPFXUniformSemantic>& 932 @Description Gets the array of registered semantics which will be used to 933 match PFX code. 934 *****************************************************************************/ 935 const CPVRTArray<SPVRTPFXUniformSemantic>& CPVRTPFXEffect::GetSemanticArray() const 936 { 937 return m_Semantics; 938 } 939 940 /***************************************************************************** 941 End of file (PVRTPFXParserAPI.cpp) 942 *****************************************************************************/ 943 944