• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2 
3  @File         OGLES2/PVRTPrint3DAPI.cpp
4 
5  @Title        OGLES2/PVRTPrint3DAPI
6 
7  @Version
8 
9  @Copyright    Copyright (c) Imagination Technologies Limited.
10 
11  @Platform     ANSI compatible
12 
13  @Description  Displays a text string using 3D polygons. Can be done in two ways:
14                using a window defined by the user or writing straight on the
15                screen.
16 
17 ******************************************************************************/
18 
19 /****************************************************************************
20 ** Includes
21 ****************************************************************************/
22 #include <stdarg.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 
27 #include "PVRTContext.h"
28 #include "PVRTFixedPoint.h"
29 #include "PVRTMatrix.h"
30 #include "PVRTTexture.h"
31 #include "PVRTTextureAPI.h"
32 #include "PVRTPrint3D.h"
33 #include "PVRTString.h"
34 #include "PVRTShader.h"
35 #include "PVRTMap.h"
36 
37 #include "PVRTPrint3DShaders.h"
38 
39 /****************************************************************************
40 ** Defines
41 ****************************************************************************/
42 #define VERTEX_ARRAY			0
43 #define UV_ARRAY				1
44 #define COLOR_ARRAY				2
45 
46 #define INIT_PRINT3D_STATE		0
47 #define DEINIT_PRINT3D_STATE	1
48 
49 #define UNDEFINED_HANDLE 0xFAFAFAFA
50 
51 const GLenum c_eMagTable[] =
52 {
53 	GL_NEAREST,
54 	GL_LINEAR,
55 };
56 
57 const GLenum c_eMinTable[] =
58 {
59 	GL_NEAREST_MIPMAP_NEAREST,
60 	GL_LINEAR_MIPMAP_NEAREST,
61 	GL_NEAREST_MIPMAP_LINEAR,
62 	GL_LINEAR_MIPMAP_LINEAR,
63 	GL_NEAREST,
64 	GL_LINEAR,
65 };
66 
67 /****************************************************************************
68 ** Enums
69 ****************************************************************************/
70 enum eFunction
71 {
72 	eFunc_DelProg,
73 	eFunc_DelShader,
74 	eFunc_DelTex
75 };
76 
77 /****************************************************************************
78 ** Auxiliary functions
79 ****************************************************************************/
DeleteResource(eFunction eType,GLuint & handle)80 static void DeleteResource(eFunction eType, GLuint& handle)
81 {
82 	if(handle == UNDEFINED_HANDLE)
83 		return;
84 
85 	switch(eType)
86 	{
87 	case eFunc_DelProg:		glDeleteProgram(handle);		break;
88 	case eFunc_DelShader:	glDeleteShader(handle);			break;
89 	case eFunc_DelTex:		glDeleteTextures(1, &handle);	break;
90 	}
91 
92 	handle = UNDEFINED_HANDLE;
93 }
94 
95 /****************************************************************************
96 ** Structures
97 ****************************************************************************/
98 struct SPVRTPrint3DAPI
99 {
100 	GLuint						m_uTextureFont;
101 	static int					s_iRefCount;
102 
103 	struct SInstanceData
104 	{
105 		GLuint				uTextureIMGLogo;
106 		GLuint				uTexturePowerVRLogo;
107 
108 		GLuint				uVertexShaderLogo;
109 		GLuint				uFragmentShaderLogo;
110 		GLuint				uProgramLogo;
111 		GLint				mvpLocationLogo;
112 
113 		GLuint				uVertexShaderFont;
114 		GLuint				uFragmentShaderFont;
115 		GLuint				uProgramFont;
116 		GLint				mvpLocationFont;
117 
SInstanceDataSPVRTPrint3DAPI::SInstanceData118 		SInstanceData() : uTextureIMGLogo(UNDEFINED_HANDLE),
119 						  uTexturePowerVRLogo(UNDEFINED_HANDLE),
120 						uVertexShaderLogo(UNDEFINED_HANDLE),
121 						uFragmentShaderLogo(UNDEFINED_HANDLE),
122 						uProgramLogo(UNDEFINED_HANDLE),
123 						mvpLocationLogo(-1),
124 						uVertexShaderFont(UNDEFINED_HANDLE),
125 						uFragmentShaderFont(UNDEFINED_HANDLE),
126 						uProgramFont(UNDEFINED_HANDLE),
127 						mvpLocationFont(-1)
128 		{
129 		}
130 
ReleaseSPVRTPrint3DAPI::SInstanceData131 		void Release()
132 		{
133 			DeleteResource(eFunc_DelProg, uProgramLogo);
134 			DeleteResource(eFunc_DelShader, uFragmentShaderLogo);
135 			DeleteResource(eFunc_DelShader, uVertexShaderLogo);
136 
137 			DeleteResource(eFunc_DelProg, uProgramLogo);
138 			DeleteResource(eFunc_DelShader, uFragmentShaderLogo);
139 			DeleteResource(eFunc_DelShader, uVertexShaderLogo);
140 
141 			DeleteResource(eFunc_DelTex, uTextureIMGLogo);
142 			DeleteResource(eFunc_DelTex, uTexturePowerVRLogo);
143 		}
144 	};
145 
146 	// Optional per-instance data
147 	SInstanceData*				m_pInstanceData;
148 
149 	// Shared data across all Print3D instances
150 	static SInstanceData		s_InstanceData;
151 
152 	// Used to save the OpenGL state to restore them after drawing */
153 	GLboolean					isCullFaceEnabled;
154 	GLboolean					isBlendEnabled;
155 	GLboolean					isDepthTestEnabled;
156 	GLint						nArrayBufferBinding;
157 	GLint						nCurrentProgram;
158 	GLint						nTextureBinding2D;
159 	GLint						eFrontFace;
160 	GLint						eCullFaceMode;
161 
SPVRTPrint3DAPISPVRTPrint3DAPI162 	SPVRTPrint3DAPI() : m_pInstanceData(NULL) {}
~SPVRTPrint3DAPISPVRTPrint3DAPI163 	~SPVRTPrint3DAPI()
164 	{
165 		if(m_pInstanceData)
166 		{
167 			delete m_pInstanceData;
168 			m_pInstanceData = NULL;
169 		}
170 	}
171 };
172 
173 int SPVRTPrint3DAPI::s_iRefCount = 0;
174 SPVRTPrint3DAPI::SInstanceData SPVRTPrint3DAPI::s_InstanceData;
175 
176 /****************************************************************************
177 ** Class: CPVRTPrint3D
178 ****************************************************************************/
179 
180 /*!***************************************************************************
181  @Function			ReleaseTextures
182  @Description		Deallocate the memory allocated in SetTextures(...)
183 *****************************************************************************/
ReleaseTextures()184 void CPVRTPrint3D::ReleaseTextures()
185 {
186 #if !defined (DISABLE_PRINT3D)
187 
188 	if(m_pAPI)
189 	{
190 		// Has local copy
191 		if(m_pAPI->m_pInstanceData)
192 		{
193 			m_pAPI->m_pInstanceData->Release();
194 		}
195 		else
196 		{
197 			if(SPVRTPrint3DAPI::s_iRefCount != 0)
198 			{
199 				// Just decrease the reference count
200 				--SPVRTPrint3DAPI::s_iRefCount;
201 			}
202 			else
203 			{
204 				m_pAPI->s_InstanceData.Release();
205 			}
206 		}
207 	}
208 
209 	// Only release textures if they've been allocated
210 	if (!m_bTexturesSet) return;
211 
212 	// Release IndexBuffer
213 	FREE(m_pwFacesFont);
214 	FREE(m_pPrint3dVtx);
215 
216 	// Delete textures
217 	glDeleteTextures(1, &m_pAPI->m_uTextureFont);
218 
219 	m_bTexturesSet = false;
220 
221 	FREE(m_pVtxCache);
222 
223 	APIRelease();
224 
225 #endif
226 }
227 
228 /*!***************************************************************************
229  @Function			Flush
230  @Description		Flushes all the print text commands
231 *****************************************************************************/
Flush()232 int CPVRTPrint3D::Flush()
233 {
234 #if !defined (DISABLE_PRINT3D)
235 
236 	int		nTris, nVtx, nVtxBase, nTrisTot = 0;
237 
238 	_ASSERT((m_nVtxCache % 4) == 0);
239 	_ASSERT(m_nVtxCache <= m_nVtxCacheMax);
240 
241 	// Save render states
242 	APIRenderStates(INIT_PRINT3D_STATE);
243 
244 	// Draw font
245 	if(m_nVtxCache)
246 	{
247 		SPVRTPrint3DAPI::SInstanceData& Data = (m_pAPI->m_pInstanceData ? *m_pAPI->m_pInstanceData : SPVRTPrint3DAPI::s_InstanceData);
248 
249 		float fW = m_fScreenScale[0] * 640.0f;
250 		float fH = m_fScreenScale[1] * 480.0f;
251 
252 		PVRTMat4 mxOrtho = PVRTMat4::Ortho(0.0f, 0.0f, fW, -fH, -1.0f, 1.0f, PVRTMat4::OGL, m_bRotate);
253 		if(m_bRotate)
254 		{
255 			PVRTMat4 mxTrans = PVRTMat4::Translation(-fH,fW,0.0f);
256 			mxOrtho = mxOrtho * mxTrans;
257 		}
258 
259 		// Use the shader
260 		_ASSERT(Data.uProgramFont != UNDEFINED_HANDLE);
261 		glUseProgram(Data.uProgramFont);
262 
263 		// Bind the projection and modelview matrices to the shader
264 		PVRTMat4& mProj = (m_bUsingProjection ? m_mProj : mxOrtho);
265 		PVRTMat4 mMVP = mProj * m_mModelView;
266 		glUniformMatrix4fv(Data.mvpLocationFont, 1, GL_FALSE, mMVP.f);
267 
268 		// Reset
269 		m_bUsingProjection = false;
270 		PVRTMatrixIdentity(m_mModelView);
271 
272 		// Set client states
273 		glEnableVertexAttribArray(VERTEX_ARRAY);
274 		glEnableVertexAttribArray(COLOR_ARRAY);
275 		glEnableVertexAttribArray(UV_ARRAY);
276 
277 		// texture
278 		glBindTexture(GL_TEXTURE_2D, m_pAPI->m_uTextureFont);
279 
280 		unsigned int uiIndex = m_eFilterMethod[eFilterProc_Min] + (m_eFilterMethod[eFilterProc_Mip]*2);
281 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, c_eMagTable[m_eFilterMethod[eFilterProc_Mag]]);
282 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_eMinTable[uiIndex]);
283 
284 		nTrisTot = m_nVtxCache >> 1;
285 
286 		// Render the text then. Might need several submissions.
287 		nVtxBase = 0;
288 		while(m_nVtxCache)
289 		{
290 			nVtx	= PVRT_MIN(m_nVtxCache, 0xFFFC);
291 			nTris	= nVtx >> 1;
292 
293 			_ASSERT(nTris <= (PVRTPRINT3D_MAX_RENDERABLE_LETTERS*2));
294 			_ASSERT((nVtx % 4) == 0);
295 
296 			// Draw triangles
297 			glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, sizeof(SPVRTPrint3DAPIVertex), (const void*)&m_pVtxCache[nVtxBase].sx);
298 			glVertexAttribPointer(COLOR_ARRAY, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SPVRTPrint3DAPIVertex), (const void*)&m_pVtxCache[nVtxBase].color);
299 			glVertexAttribPointer(UV_ARRAY, 2, GL_FLOAT, GL_FALSE, sizeof(SPVRTPrint3DAPIVertex), (const void*)&m_pVtxCache[nVtxBase].tu);
300 
301 			glDrawElements(GL_TRIANGLES, nTris * 3, GL_UNSIGNED_SHORT, m_pwFacesFont);
302 
303 			if(glGetError())
304 			{
305 				PVRTERROR_OUTPUT_DEBUG("glDrawElements(GL_TRIANGLES, (VertexCount/2)*3, GL_UNSIGNED_SHORT, m_pFacesFont); failed\n");
306 			}
307 
308 			nVtxBase	+= nVtx;
309 			m_nVtxCache	-= nVtx;
310 		}
311 
312 		// Restore render states
313 		glDisableVertexAttribArray(VERTEX_ARRAY);
314 		glDisableVertexAttribArray(COLOR_ARRAY);
315 		glDisableVertexAttribArray(UV_ARRAY);
316 	}
317 	// Draw a logo if requested
318 #if !defined(FORCE_NO_LOGO)
319 	// User selected logos
320 	if(m_uLogoToDisplay & ePVRTPrint3DLogoPowerVR && m_uLogoToDisplay & ePVRTPrint3DLogoIMG)
321 	{
322 		APIDrawLogo(ePVRTPrint3DLogoIMG, eBottom | eRight);	// IMG to the right
323 		APIDrawLogo(ePVRTPrint3DLogoPowerVR, eBottom | eLeft);	// PVR to the left
324 	}
325 	else if(m_uLogoToDisplay & ePVRTPrint3DLogoPowerVR)
326 	{
327 		APIDrawLogo(ePVRTPrint3DLogoPowerVR, eBottom | eRight);	// logo to the right
328 	}
329 	else if(m_uLogoToDisplay & ePVRTPrint3DLogoIMG)
330 	{
331 		APIDrawLogo(ePVRTPrint3DLogoIMG, eBottom | eRight);	// logo to the right
332 	}
333 #endif
334 
335 	// Restore render states
336 	APIRenderStates(DEINIT_PRINT3D_STATE);
337 
338 	return nTrisTot;
339 
340 #else
341 	return 0;
342 #endif
343 }
344 
345 /*************************************************************
346 *					 PRIVATE FUNCTIONS						 *
347 **************************************************************/
348 
349 /*!***************************************************************************
350  @Function			APIInit
351  @Description		Initialisation and texture upload. Should be called only once
352 					for a given context.
353 *****************************************************************************/
APIInit(const SPVRTContext * const pContext,bool bMakeCopy)354 bool CPVRTPrint3D::APIInit(const SPVRTContext	* const pContext, bool bMakeCopy)
355 {
356 	PVRT_UNREFERENCED_PARAMETER(pContext);
357 
358 	m_pAPI = new SPVRTPrint3DAPI;
359 	if(!m_pAPI)
360 		return false;
361 
362 	if(bMakeCopy)
363 		m_pAPI->m_pInstanceData = new SPVRTPrint3DAPI::SInstanceData();
364 
365 	SPVRTPrint3DAPI::SInstanceData& Data = (m_pAPI->m_pInstanceData ? *m_pAPI->m_pInstanceData : SPVRTPrint3DAPI::s_InstanceData);
366 
367 	// Check to see if these shaders have already been loaded previously. Optimisation as we don't want to load many copies of the same shader!
368 	if(	Data.uFragmentShaderLogo != UNDEFINED_HANDLE && Data.uVertexShaderLogo != UNDEFINED_HANDLE && Data.uProgramLogo != UNDEFINED_HANDLE &&
369 		Data.uFragmentShaderFont != UNDEFINED_HANDLE && Data.uVertexShaderFont != UNDEFINED_HANDLE && Data.uProgramFont != UNDEFINED_HANDLE
370 	)
371 	{
372 		++SPVRTPrint3DAPI::s_iRefCount;
373 		return true;
374 	}
375 
376 	// Compiles the shaders. For a more detailed explanation, see IntroducingPVRTools
377 	CPVRTString error;
378 	GLint Linked;
379 	bool bRes = true;
380 
381 	bRes &= (PVRTShaderLoadSourceFromMemory(_Print3DFragShaderLogo_fsh, GL_FRAGMENT_SHADER, &Data.uFragmentShaderLogo, &error) == PVR_SUCCESS);
382 	bRes &= (PVRTShaderLoadSourceFromMemory(_Print3DVertShaderLogo_vsh, GL_VERTEX_SHADER, &Data.uVertexShaderLogo, &error)  == PVR_SUCCESS);
383 
384 	_ASSERT(bRes);
385 
386 	// Create the 'text' program
387 	Data.uProgramLogo = glCreateProgram();
388 	glAttachShader(Data.uProgramLogo, Data.uVertexShaderLogo);
389 	glAttachShader(Data.uProgramLogo, Data.uFragmentShaderLogo);
390 	glBindAttribLocation(Data.uProgramLogo, VERTEX_ARRAY, "myVertex");
391 	glBindAttribLocation(Data.uProgramLogo, UV_ARRAY, "myUV");
392 
393 	glLinkProgram(Data.uProgramLogo);
394 	glGetProgramiv(Data.uProgramLogo, GL_LINK_STATUS, &Linked);
395 
396 	if (!Linked)
397 		bRes = false;
398 
399 	bRes &= (PVRTShaderLoadSourceFromMemory(_Print3DFragShader_fsh, GL_FRAGMENT_SHADER, &Data.uFragmentShaderFont, &error) == PVR_SUCCESS);
400 	bRes &= (PVRTShaderLoadSourceFromMemory(_Print3DVertShader_vsh, GL_VERTEX_SHADER, &Data.uVertexShaderFont, &error)  == PVR_SUCCESS);
401 
402 	_ASSERT(bRes);
403 
404 	// Create the 'text' program
405 	Data.uProgramFont = glCreateProgram();
406 	glAttachShader(Data.uProgramFont, Data.uVertexShaderFont);
407 	glAttachShader(Data.uProgramFont, Data.uFragmentShaderFont);
408 	glBindAttribLocation(Data.uProgramFont, VERTEX_ARRAY, "myVertex");
409 	glBindAttribLocation(Data.uProgramFont, UV_ARRAY, "myUV");
410 	glBindAttribLocation(Data.uProgramFont, COLOR_ARRAY, "myColour");
411 
412 	glLinkProgram(Data.uProgramFont);
413 	glGetProgramiv(Data.uProgramFont, GL_LINK_STATUS, &Linked);
414 
415 	if (!Linked)
416 		bRes = false;
417 
418 	Data.mvpLocationLogo = glGetUniformLocation(Data.uProgramFont, "myMVPMatrix");
419 	Data.mvpLocationFont = glGetUniformLocation(Data.uProgramLogo, "myMVPMatrix");
420 
421 	_ASSERT(bRes && Data.mvpLocationLogo != -1 && Data.mvpLocationFont != -1);
422 
423 	return bRes;
424 }
425 
426 /*!***************************************************************************
427  @Function			APIRelease
428  @Description		Deinitialisation.
429 *****************************************************************************/
APIRelease()430 void CPVRTPrint3D::APIRelease()
431 {
432 	delete m_pAPI;
433 	m_pAPI = 0;
434 }
435 
436 /*!***************************************************************************
437  @Function			APIUpLoadIcons
438  @Description		Initialisation and texture upload. Should be called only once
439 					for a given context.
440 *****************************************************************************/
APIUpLoadIcons(const PVRTuint8 * const pIMG,const PVRTuint8 * const pPowerVR)441 bool CPVRTPrint3D::APIUpLoadIcons(const PVRTuint8 * const pIMG, const PVRTuint8 * const pPowerVR)
442 {
443 	SPVRTPrint3DAPI::SInstanceData& Data = (m_pAPI->m_pInstanceData ? *m_pAPI->m_pInstanceData : SPVRTPrint3DAPI::s_InstanceData);
444 
445 	// Load Icon texture
446 	if(Data.uTextureIMGLogo == UNDEFINED_HANDLE)		// Static, so might already be initialized.
447 		if(PVRTTextureLoadFromPointer((unsigned char*)pIMG, &Data.uTextureIMGLogo) != PVR_SUCCESS)
448 			return false;
449 
450 	if(Data.uTexturePowerVRLogo == UNDEFINED_HANDLE)		// Static, so might already be initialized.
451 		if(PVRTTextureLoadFromPointer((unsigned char*)pPowerVR, &Data.uTexturePowerVRLogo) != PVR_SUCCESS)
452 			return false;
453 
454 	glBindTexture(GL_TEXTURE_2D, 0);
455 	return true;
456 }
457 
458 /*!***************************************************************************
459 @Function		APIUpLoadTexture
460 @Input			pSource
461 @Output			header
462 @Return			bool	true if successful.
463 @Description	Loads and uploads the font texture from a PVR file.
464 *****************************************************************************/
APIUpLoadTexture(const PVRTuint8 * pSource,const PVRTextureHeaderV3 * header,CPVRTMap<PVRTuint32,CPVRTMap<PVRTuint32,MetaDataBlock>> & MetaDataMap)465 bool CPVRTPrint3D::APIUpLoadTexture(const PVRTuint8* pSource, const PVRTextureHeaderV3* header, CPVRTMap<PVRTuint32, CPVRTMap<PVRTuint32, MetaDataBlock> >& MetaDataMap)
466 {
467 	if(PVRTTextureLoadFromPointer(pSource, &m_pAPI->m_uTextureFont, header, true, 0U, NULL, &MetaDataMap) != PVR_SUCCESS)
468 		return false;
469 
470 	glBindTexture(GL_TEXTURE_2D, 0);
471 	return true;
472 }
473 
474 /*!***************************************************************************
475  @Function			APIRenderStates
476  @Description		Stores, writes and restores Render States
477 *****************************************************************************/
APIRenderStates(int nAction)478 void CPVRTPrint3D::APIRenderStates(int nAction)
479 {
480 	// Saving or restoring states ?
481 	switch (nAction)
482 	{
483 	case INIT_PRINT3D_STATE:
484 	{
485 		// Get previous render states
486 		m_pAPI->isCullFaceEnabled = glIsEnabled(GL_CULL_FACE);
487 		m_pAPI->isBlendEnabled = glIsEnabled(GL_BLEND);
488 		m_pAPI->isDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST);
489 
490 		glGetIntegerv(GL_FRONT_FACE, &m_pAPI->eFrontFace);
491 		glGetIntegerv(GL_CULL_FACE_MODE, &m_pAPI->eCullFaceMode);
492 		glGetIntegerv(GL_ARRAY_BUFFER_BINDING,&m_pAPI->nArrayBufferBinding);
493 		glGetIntegerv(GL_CURRENT_PROGRAM, &m_pAPI->nCurrentProgram);
494 		glGetIntegerv(GL_TEXTURE_BINDING_2D, &m_pAPI->nTextureBinding2D);
495 
496 		/******************************
497 		** SET PRINT3D RENDER STATES **
498 		******************************/
499 
500 		// Culling
501 		glFrontFace(GL_CCW);
502 		glCullFace(GL_BACK);
503 		glEnable(GL_CULL_FACE);
504 
505 		// Set blending mode
506 		glEnable(GL_BLEND);
507 		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
508 
509 		// Set Z compare properties
510 		glDisable(GL_DEPTH_TEST);
511 
512 		// Set the default GL_ARRAY_BUFFER
513 		glBindBuffer(GL_ARRAY_BUFFER, 0);
514 
515 		// texture
516 		glActiveTexture(GL_TEXTURE0);
517 		break;
518 	}
519 	case DEINIT_PRINT3D_STATE:
520 		// Restore some values
521 		if (!m_pAPI->isCullFaceEnabled) glDisable(GL_CULL_FACE);
522 		if (!m_pAPI->isBlendEnabled) glDisable(GL_BLEND);
523 		if (m_pAPI->isDepthTestEnabled) glEnable(GL_DEPTH_TEST);
524 		glCullFace((GLenum)m_pAPI->eCullFaceMode);
525 		glFrontFace((GLenum)m_pAPI->eFrontFace);
526 		glBindBuffer(GL_ARRAY_BUFFER,m_pAPI->nArrayBufferBinding);
527 		glBindTexture(GL_TEXTURE_2D, m_pAPI->nTextureBinding2D);
528 		glUseProgram(m_pAPI->nCurrentProgram); // Unset print3ds program
529 		break;
530 	}
531 }
532 
533 /****************************************************************************
534 ** Local code
535 ****************************************************************************/
536 
537 /*!***************************************************************************
538  @Function			APIDrawLogo
539  @Description
540 *****************************************************************************/
APIDrawLogo(const EPVRTPrint3DLogo uLogoToDisplay,const int ePos)541 void CPVRTPrint3D::APIDrawLogo(const EPVRTPrint3DLogo uLogoToDisplay, const int ePos)
542 {
543 	GLuint	tex = 0;
544 	float fScale = 1.0f;
545 	if(m_ui32ScreenDim[1] >= 720)
546 		fScale = 2.0f;
547 
548 	SPVRTPrint3DAPI::SInstanceData& Data = (m_pAPI->m_pInstanceData ? *m_pAPI->m_pInstanceData : SPVRTPrint3DAPI::s_InstanceData);
549 
550 	switch(uLogoToDisplay)
551 	{
552 		case ePVRTPrint3DLogoIMG:
553 			tex = Data.uTextureIMGLogo;
554 			break;
555 		case ePVRTPrint3DLogoPowerVR:
556 			tex = Data.uTexturePowerVRLogo;
557 			break;
558 		default:
559 			return; // Logo not recognised
560 	}
561 
562 	const float fLogoXSizeHalf = (128.0f / m_ui32ScreenDim[0]);
563 	const float fLogoYSizeHalf = (64.0f / m_ui32ScreenDim[1]);
564 
565 	const float fLogoXShift = 0.035f / fScale;
566 	const float fLogoYShift = 0.035f / fScale;
567 
568 	const float fLogoSizeXHalfShifted = fLogoXSizeHalf + fLogoXShift;
569 	const float fLogoSizeYHalfShifted = fLogoYSizeHalf + fLogoYShift;
570 
571 	static float Vertices[] =
572 		{
573 			-fLogoXSizeHalf, fLogoYSizeHalf , 0.5f,
574 			-fLogoXSizeHalf, -fLogoYSizeHalf, 0.5f,
575 			fLogoXSizeHalf , fLogoYSizeHalf , 0.5f,
576 	 		fLogoXSizeHalf , -fLogoYSizeHalf, 0.5f
577 		};
578 
579 	static float UVs[] = {
580 			0.0f, 0.0f,
581 			0.0f, 1.0f,
582 			1.0f, 0.0f,
583 	 		1.0f, 1.0f
584 		};
585 
586 	float *pVertices = ( (float*)&Vertices );
587 	float *pUV       = ( (float*)&UVs );
588 
589 	// Matrices
590 	PVRTMATRIX matModelView;
591 	PVRTMATRIX matTransform;
592 	PVRTMatrixIdentity(matModelView);
593 
594 	PVRTMatrixScaling(matTransform, f2vt(fScale), f2vt(fScale), f2vt(1.0f));
595 	PVRTMatrixMultiply(matModelView, matModelView, matTransform);
596 
597 	int nXPos = (ePos & eLeft) ? -1 : 1;
598 	int nYPos = (ePos & eTop) ? 1 : -1;
599 	PVRTMatrixTranslation(matTransform, nXPos - (fLogoSizeXHalfShifted * fScale * nXPos), nYPos - (fLogoSizeYHalfShifted * fScale * nYPos), 0.0f);
600 	PVRTMatrixMultiply(matModelView, matModelView, matTransform);
601 
602 	if(m_bRotate)
603 	{
604 		PVRTMatrixRotationZ(matTransform, -90.0f*PVRT_PI/180.0f);
605 		PVRTMatrixMultiply(matModelView, matModelView, matTransform);
606 	}
607 
608 	_ASSERT(Data.uProgramLogo != UNDEFINED_HANDLE);
609 	glUseProgram(Data.uProgramLogo);
610 
611 	// Bind the model-view-projection to the shader
612 	glUniformMatrix4fv(Data.mvpLocationLogo, 1, GL_FALSE, matModelView.f);
613 
614 	// Render states
615 	glActiveTexture(GL_TEXTURE0);
616 
617 	_ASSERT(tex != UNDEFINED_HANDLE);
618 	glBindTexture(GL_TEXTURE_2D, tex);
619 
620 	// Vertices
621 	glEnableVertexAttribArray(VERTEX_ARRAY);
622 	glEnableVertexAttribArray(UV_ARRAY);
623 
624 	glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, 0, (const void*)pVertices);
625 	glVertexAttribPointer(UV_ARRAY, 2, GL_FLOAT, GL_FALSE, 0, (const void*)pUV);
626 
627 	glDrawArrays(GL_TRIANGLE_STRIP,0,4);
628 
629 	glDisableVertexAttribArray(VERTEX_ARRAY);
630 	glDisableVertexAttribArray(UV_ARRAY);
631 }
632 
633 /*****************************************************************************
634  End of file (PVRTPrint3DAPI.cpp)
635 *****************************************************************************/
636 
637