Home | History | Annotate | Download | only in OGLES2
      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 ****************************************************************************/
     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 
    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 
    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 *****************************************************************************/
    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 *****************************************************************************/
    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 *****************************************************************************/
    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 *****************************************************************************/
    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 *****************************************************************************/
    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 *****************************************************************************/
    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 *****************************************************************************/
    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 *****************************************************************************/
    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