• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *****************************************************************************/
CPVRTPFXEffect()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 *****************************************************************************/
CPVRTPFXEffect(SPVRTContext & sContext)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 *****************************************************************************/
~CPVRTPFXEffect()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 *****************************************************************************/
Load(CPVRTPFXParser & src,const char * const pszEffect,const char * const pszFileName,PVRTPFXEffectDelegate * pDelegate,unsigned int & uiUnknownUniforms,CPVRTString * pReturnError)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 *****************************************************************************/
LoadTexturesForEffect(PVRTPFXEffectDelegate * pDelegate,CPVRTString * pReturnError)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 *****************************************************************************/
LoadShadersForEffect(CPVRTPFXParser & src,const char * const pszFileName,CPVRTString * pReturnError)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 *****************************************************************************/
Destroy()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 *****************************************************************************/
Activate(const int i32RenderTextureId,const unsigned int ui32ReplacementTexture)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 *****************************************************************************/
GetSemantics(CPVRTArray<SPVRTPFXUniform> & aUniforms,const CPVRTArray<SPVRTPFXParserSemantic> & aParams,const CPVRTArray<SPVRTPFXUniformSemantic> & aUniformSemantics,unsigned int * const pnUnknownUniformCount,const GLuint uiProgram,bool bIsAttribue,CPVRTString * const errorMsg)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 *****************************************************************************/
GetUniformArray() const572 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 *****************************************************************************/
RebuildUniformTable(unsigned int & uiUnknownSemantics,CPVRTString * pReturnError)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 *****************************************************************************/
RegisterUniformSemantic(const SPVRTPFXUniformSemantic * const psUniforms,unsigned int uiNumUniforms,CPVRTString * pReturnError)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 *****************************************************************************/
RemoveUniformSemantic(unsigned int uiSemanticID,CPVRTString * pReturnError)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 *****************************************************************************/
GetTextureArray() const686 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 *****************************************************************************/
SetTexture(const unsigned int nIdx,const GLuint ui,const unsigned int u32flags)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 *****************************************************************************/
SetDefaultUniformValue(const char * const pszName,const SPVRTSemanticDefaultData * psDefaultValue)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 *****************************************************************************/
SetContext(SPVRTContext * const pContext)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 *****************************************************************************/
GetProgramHandle() const914 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 *****************************************************************************/
GetEffectIndex() const924 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 *****************************************************************************/
GetSemanticArray() const935 const CPVRTArray<SPVRTPFXUniformSemantic>& CPVRTPFXEffect::GetSemanticArray() const
936 {
937 	return m_Semantics;
938 }
939 
940 /*****************************************************************************
941  End of file (PVRTPFXParserAPI.cpp)
942 *****************************************************************************/
943 
944