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
51const GLenum c_eMagTable[] =
52{
53	GL_NEAREST,
54	GL_LINEAR,
55};
56
57const 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****************************************************************************/
70enum eFunction
71{
72	eFunc_DelProg,
73	eFunc_DelShader,
74	eFunc_DelTex
75};
76
77/****************************************************************************
78** Auxiliary functions
79****************************************************************************/
80static 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****************************************************************************/
98struct 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
118		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
131		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
162	SPVRTPrint3DAPI() : m_pInstanceData(NULL) {}
163	~SPVRTPrint3DAPI()
164	{
165		if(m_pInstanceData)
166		{
167			delete m_pInstanceData;
168			m_pInstanceData = NULL;
169		}
170	}
171};
172
173int SPVRTPrint3DAPI::s_iRefCount = 0;
174SPVRTPrint3DAPI::SInstanceData SPVRTPrint3DAPI::s_InstanceData;
175
176/****************************************************************************
177** Class: CPVRTPrint3D
178****************************************************************************/
179
180/*!***************************************************************************
181 @Function			ReleaseTextures
182 @Description		Deallocate the memory allocated in SetTextures(...)
183*****************************************************************************/
184void 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*****************************************************************************/
232int 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*****************************************************************************/
354bool 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*****************************************************************************/
430void 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*****************************************************************************/
441bool 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*****************************************************************************/
465bool 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*****************************************************************************/
478void 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*****************************************************************************/
541void 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