1/******************************************************************************
2
3 @File         OGLES3/PVRTTextureAPI.cpp
4
5 @Title        OGLES3/PVRTTextureAPI
6
7 @Version
8
9 @Copyright    Copyright (c) Imagination Technologies Limited.
10
11 @Platform     ANSI compatible
12
13 @Description  OGLES3 texture loading.
14
15******************************************************************************/
16
17#include <string.h>
18#include <stdlib.h>
19
20#include "PVRTContext.h"
21#include "PVRTgles3Ext.h"
22#include "PVRTTexture.h"
23#include "PVRTTextureAPI.h"
24#include "PVRTDecompress.h"
25#include "PVRTFixedPoint.h"
26#include "PVRTMap.h"
27#include "PVRTMatrix.h"
28#include "PVRTMisc.h"
29#include "PVRTResourceFile.h"
30
31/*****************************************************************************
32** Functions
33****************************************************************************/
34
35/*!***********************************************************************
36	@Function:		PVRTGetOGLES3TextureFormat
37	@Input:			sTextureHeader
38	@Modified:		glInternalFormat
39	@Modified:		glFormat
40	@Modified:		glType
41	@Description:	Gets the OpenGLES equivalent values of internal format,
42					format and type for this texture header. This will return
43					any supported OpenGLES texture values, it is up to the user
44					to decide if these are valid for their current platform.
45*************************************************************************/
46static const void PVRTGetOGLES3TextureFormat(const PVRTextureHeaderV3& sTextureHeader, PVRTuint32& glInternalFormat, PVRTuint32& glFormat, PVRTuint32& glType)
47{
48	PVRTuint64 PixelFormat = sTextureHeader.u64PixelFormat;
49	EPVRTVariableType ChannelType = (EPVRTVariableType)sTextureHeader.u32ChannelType;
50	EPVRTColourSpace ColourSpace = (EPVRTColourSpace)sTextureHeader.u32ColourSpace;
51
52	//Initialisation. Any invalid formats will return 0 always.
53	glFormat = 0;
54	glType = 0;
55	glInternalFormat=0;
56
57	//Get the last 32 bits of the pixel format.
58	PVRTuint64 PixelFormatPartHigh = PixelFormat&PVRTEX_PFHIGHMASK;
59
60	//Check for a compressed format (The first 8 bytes will be 0, so the whole thing will be equal to the last 32 bits).
61	if (PixelFormatPartHigh==0)
62	{
63		//Format and type == 0 for compressed textures.
64		switch (PixelFormat)
65		{
66		case ePVRTPF_PVRTCI_2bpp_RGB:
67			{
68				if (ColourSpace == ePVRTCSpacesRGB)
69				{
70					//glInternalFormat=GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT;
71				}
72				else
73				{
74					glInternalFormat=GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
75				}
76				return;
77			}
78		case ePVRTPF_PVRTCI_2bpp_RGBA:
79			{
80				if (ColourSpace == ePVRTCSpacesRGB)
81				{
82					//glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT;
83				}
84				else
85				{
86					glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG;
87				}
88				return;
89			}
90		case ePVRTPF_PVRTCI_4bpp_RGB:
91			{
92				if (ColourSpace == ePVRTCSpacesRGB)
93				{
94					//glInternalFormat=GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT;
95				}
96				else
97				{
98					glInternalFormat=GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
99				}
100				return;
101			}
102		case ePVRTPF_PVRTCI_4bpp_RGBA:
103			{
104				if (ColourSpace == ePVRTCSpacesRGB)
105				{
106					//glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT;
107				}
108				else
109				{
110					glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG;
111				}
112				return;
113			}
114#ifndef TARGET_OS_IPHONE
115		case ePVRTPF_PVRTCII_2bpp:
116			{
117				if (ColourSpace == ePVRTCSpacesRGB)
118				{
119					//glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG;
120				}
121				else
122				{
123					glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG;
124				}
125				return;
126			}
127		case ePVRTPF_PVRTCII_4bpp:
128			{
129				if (ColourSpace == ePVRTCSpacesRGB)
130				{
131					//glInternalFormat=GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG;
132				}
133				else
134				{
135					glInternalFormat=GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG;
136				}
137				return;
138			}
139		case ePVRTPF_ETC1:
140			{
141				glInternalFormat=GL_ETC1_RGB8_OES;
142				return;
143			}
144#endif
145		case ePVRTPF_ETC2_RGB:
146			{
147				if (ColourSpace==ePVRTCSpacesRGB)
148					glInternalFormat=GL_COMPRESSED_SRGB8_ETC2;
149				else
150					glInternalFormat=GL_COMPRESSED_RGB8_ETC2;
151				return;
152			}
153		case ePVRTPF_ETC2_RGBA:
154			{
155				if (ColourSpace==ePVRTCSpacesRGB)
156					glInternalFormat=GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
157				else
158					glInternalFormat=GL_COMPRESSED_RGBA8_ETC2_EAC;
159				return;
160			}
161		case ePVRTPF_ETC2_RGB_A1:
162			{
163				if (ColourSpace==ePVRTCSpacesRGB)
164					glInternalFormat=GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
165				else
166					glInternalFormat=GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
167				return;
168			}
169		case ePVRTPF_EAC_R11:
170			{
171				if (ChannelType==ePVRTVarTypeSignedInteger || ChannelType==ePVRTVarTypeSignedIntegerNorm ||
172					ChannelType==ePVRTVarTypeSignedShort || ChannelType==ePVRTVarTypeSignedShortNorm ||
173					ChannelType==ePVRTVarTypeSignedByte || ChannelType==ePVRTVarTypeSignedByteNorm ||
174					ChannelType==ePVRTVarTypeSignedFloat)
175				{
176					glInternalFormat=GL_COMPRESSED_SIGNED_R11_EAC;
177				}
178				else
179				{
180					glInternalFormat=GL_COMPRESSED_R11_EAC;
181				}
182				return;
183			}
184		case ePVRTPF_EAC_RG11:
185			{
186				if (ChannelType==ePVRTVarTypeSignedInteger || ChannelType==ePVRTVarTypeSignedIntegerNorm ||
187					ChannelType==ePVRTVarTypeSignedShort || ChannelType==ePVRTVarTypeSignedShortNorm ||
188					ChannelType==ePVRTVarTypeSignedByte || ChannelType==ePVRTVarTypeSignedByteNorm ||
189					ChannelType==ePVRTVarTypeSignedFloat)
190				{
191					glInternalFormat=GL_COMPRESSED_SIGNED_RG11_EAC;
192				}
193				else
194				{
195					glInternalFormat=GL_COMPRESSED_RG11_EAC;
196				}
197				return;
198			}
199		}
200	}
201	else
202	{
203		switch (ChannelType)
204		{
205		case ePVRTVarTypeUnsignedFloat:
206			if (PixelFormat==PVRTGENPIXELID3('r','g','b',11,11,10) )
207			{
208				glType=GL_UNSIGNED_INT_10F_11F_11F_REV;
209				glFormat = GL_RGB;
210				glInternalFormat=GL_R11F_G11F_B10F;
211				return;
212			}
213			break;
214		case ePVRTVarTypeSignedFloat:
215			{
216				switch (PixelFormat)
217				{
218					//HALF_FLOAT
219				case PVRTGENPIXELID4('r','g','b','a',16,16,16,16):
220					{
221						glType=GL_HALF_FLOAT;
222						glFormat = GL_RGBA;
223						glInternalFormat=GL_RGBA;
224						return;
225					}
226				case PVRTGENPIXELID3('r','g','b',16,16,16):
227					{
228						glType=GL_HALF_FLOAT;
229						glFormat = GL_RGB;
230						glInternalFormat=GL_RGB16F;
231						return;
232					}
233				case PVRTGENPIXELID2('r','g',16,16):
234					{
235						glType=GL_HALF_FLOAT;
236						glFormat = GL_RG;
237						glInternalFormat=GL_RG16F;
238						return;
239					}
240				case PVRTGENPIXELID1('r',16):
241					{
242						glType=GL_HALF_FLOAT;
243						glFormat = GL_RED;
244						glInternalFormat=GL_R16F;
245						return;
246					}
247				case PVRTGENPIXELID2('l','a',16,16):
248					{
249						glType=GL_HALF_FLOAT;
250						glFormat = GL_LUMINANCE_ALPHA;
251						glInternalFormat=GL_LUMINANCE_ALPHA;
252						return;
253					}
254				case PVRTGENPIXELID1('l',16):
255					{
256						glType=GL_HALF_FLOAT;
257						glFormat = GL_LUMINANCE;
258						glInternalFormat=GL_LUMINANCE;
259						return;
260					}
261				case PVRTGENPIXELID1('a',16):
262					{
263						glType=GL_HALF_FLOAT;
264						glFormat = GL_ALPHA;
265						glInternalFormat=GL_ALPHA;
266						return;
267					}
268					//FLOAT
269				case PVRTGENPIXELID4('r','g','b','a',32,32,32,32):
270					{
271						glType=GL_FLOAT;
272						glFormat = GL_RGBA;
273						glInternalFormat=GL_RGBA32F;
274						return;
275					}
276				case PVRTGENPIXELID3('r','g','b',32,32,32):
277					{
278						glType=GL_FLOAT;
279						glFormat = GL_RGB;
280						glInternalFormat=GL_RGB32F;
281						return;
282					}
283				case PVRTGENPIXELID2('r','g',32,32):
284					{
285						glType=GL_FLOAT;
286						glFormat = GL_RG;
287						glInternalFormat=GL_RG32F;
288						return;
289					}
290				case PVRTGENPIXELID1('r',32):
291					{
292						glType=GL_FLOAT;
293						glFormat = GL_RED;
294						glInternalFormat=GL_R32F;
295						return;
296					}
297				case PVRTGENPIXELID2('l','a',32,32):
298					{
299						glType=GL_FLOAT;
300						glFormat = GL_LUMINANCE_ALPHA;
301						glInternalFormat=GL_LUMINANCE_ALPHA;
302						return;
303					}
304				case PVRTGENPIXELID1('l',32):
305					{
306						glType=GL_FLOAT;
307						glFormat = GL_LUMINANCE;
308						glInternalFormat=GL_LUMINANCE;
309						return;
310					}
311				case PVRTGENPIXELID1('a',32):
312					{
313						glType=GL_FLOAT;
314						glFormat = GL_ALPHA;
315						glInternalFormat=GL_ALPHA;
316						return;
317					}
318				}
319				break;
320			}
321		case ePVRTVarTypeUnsignedByteNorm:
322			{
323				glType = GL_UNSIGNED_BYTE;
324				switch (PixelFormat)
325				{
326				case PVRTGENPIXELID4('r','g','b','a',8,8,8,8):
327					{
328						glFormat = GL_RGBA;
329						if (ColourSpace==ePVRTCSpacesRGB)
330							glInternalFormat=GL_SRGB8_ALPHA8;
331						else
332							glInternalFormat=GL_RGBA8;
333						return;
334					}
335				case PVRTGENPIXELID3('r','g','b',8,8,8):
336					{
337						glFormat = GL_RGB;
338						if (ColourSpace==ePVRTCSpacesRGB)
339							glInternalFormat=GL_SRGB8;
340						else
341							glInternalFormat=GL_RGB8;
342						return;
343					}
344				case PVRTGENPIXELID2('r','g',8,8):
345					{
346						glFormat = GL_RG;
347						glInternalFormat=GL_RG8;
348						return;
349					}
350				case PVRTGENPIXELID1('r',8):
351					{
352						glFormat = GL_RED;
353						glInternalFormat=GL_R8;
354						return;
355					}
356				case PVRTGENPIXELID2('l','a',8,8):
357					{
358						glFormat = GL_LUMINANCE_ALPHA;
359						glInternalFormat=GL_LUMINANCE_ALPHA;
360						return;
361					}
362				case PVRTGENPIXELID1('l',8):
363					{
364						glFormat = GL_LUMINANCE;
365						glInternalFormat=GL_LUMINANCE;
366						return;
367					}
368				case PVRTGENPIXELID1('a',8):
369					{
370						glFormat = GL_ALPHA;
371						glInternalFormat=GL_ALPHA;
372						return;
373					}
374				case PVRTGENPIXELID4('b','g','r','a',8,8,8,8):
375					{
376						glFormat = GL_BGRA_EXT;
377						glInternalFormat=GL_BGRA_EXT;
378						return;
379					}
380				}
381				break;
382			}
383		case ePVRTVarTypeSignedByteNorm:
384			{
385				glType = GL_BYTE;
386				switch (PixelFormat)
387				{
388				case PVRTGENPIXELID4('r','g','b','a',8,8,8,8):
389					{
390						glFormat = GL_RGBA;
391						glInternalFormat=GL_RGBA8_SNORM;
392						return;
393					}
394				case PVRTGENPIXELID3('r','g','b',8,8,8):
395					{
396						glFormat = GL_RGB;
397						glInternalFormat=GL_RGB8_SNORM;
398						return;
399					}
400				case PVRTGENPIXELID2('r','g',8,8):
401					{
402						glFormat = GL_RG;
403						glInternalFormat=GL_RGB8_SNORM;
404						return;
405					}
406				case PVRTGENPIXELID1('r',8):
407					{
408						glFormat = GL_RED;
409						glInternalFormat=GL_R8_SNORM;
410						return;
411					}
412				}
413				break;
414			}
415		case ePVRTVarTypeUnsignedByte:
416			{
417				glType = GL_UNSIGNED_BYTE;
418				switch (PixelFormat)
419				{
420				case PVRTGENPIXELID4('r','g','b','a',8,8,8,8):
421					{
422						glFormat = GL_RGBA_INTEGER;
423						glInternalFormat=GL_RGBA8UI;
424						return;
425					}
426				case PVRTGENPIXELID3('r','g','b',8,8,8):
427					{
428						glFormat = GL_RGB_INTEGER;
429						glInternalFormat=GL_RGB8UI;
430						return;
431					}
432				case PVRTGENPIXELID2('r','g',8,8):
433					{
434						glFormat = GL_RG_INTEGER;
435						glInternalFormat=GL_RG8UI;
436						return;
437					}
438				case PVRTGENPIXELID1('r',8):
439					{
440						glFormat = GL_RED_INTEGER;
441						glInternalFormat=GL_R8UI;
442						return;
443					}
444				}
445				break;
446			}
447		case ePVRTVarTypeSignedByte:
448			{
449				glType = GL_BYTE;
450				switch (PixelFormat)
451				{
452				case PVRTGENPIXELID4('r','g','b','a',8,8,8,8):
453					{
454						glFormat = GL_RGBA_INTEGER;
455						glInternalFormat=GL_RGBA8I;
456						return;
457					}
458				case PVRTGENPIXELID3('r','g','b',8,8,8):
459					{
460						glFormat = GL_RGB_INTEGER;
461						glInternalFormat=GL_RGB8I;
462						return;
463					}
464				case PVRTGENPIXELID2('r','g',8,8):
465					{
466						glFormat = GL_RG_INTEGER;
467						glInternalFormat=GL_RG8I;
468						return;
469					}
470				case PVRTGENPIXELID1('r',8):
471					{
472						glFormat = GL_RED_INTEGER;
473						glInternalFormat=GL_R8I;
474						return;
475					}
476				}
477				break;
478			}
479		case ePVRTVarTypeUnsignedShortNorm:
480			{
481				switch (PixelFormat)
482				{
483				case PVRTGENPIXELID4('r','g','b','a',4,4,4,4):
484					{
485						glType = GL_UNSIGNED_SHORT_4_4_4_4;
486						glFormat = GL_RGBA;
487						glInternalFormat=GL_RGBA4;
488						return;
489					}
490				case PVRTGENPIXELID4('r','g','b','a',5,5,5,1):
491					{
492						glType = GL_UNSIGNED_SHORT_5_5_5_1;
493						glFormat = GL_RGBA;
494						glInternalFormat=GL_RGB5_A1;
495						return;
496					}
497				case PVRTGENPIXELID3('r','g','b',5,6,5):
498					{
499						glType = GL_UNSIGNED_SHORT_5_6_5;
500						glFormat = GL_RGB;
501						glInternalFormat=GL_RGB565;
502						return;
503					}
504				}
505				break;
506			}
507		case ePVRTVarTypeUnsignedShort:
508			{
509				glType = GL_UNSIGNED_SHORT;
510				switch (PixelFormat)
511				{
512				case PVRTGENPIXELID4('r','g','b','a',16,16,16,16):
513					{
514						glFormat = GL_RGBA_INTEGER;
515						glInternalFormat=GL_RGBA16UI;
516						return;
517					}
518				case PVRTGENPIXELID3('r','g','b',16,16,16):
519					{
520						glFormat = GL_RGB_INTEGER;
521						glInternalFormat=GL_RGB16UI;
522						return;
523					}
524				case PVRTGENPIXELID2('r','g',16,16):
525					{
526						glFormat = GL_RG_INTEGER;
527						glInternalFormat=GL_RG16UI;
528						return;
529					}
530				case PVRTGENPIXELID1('r',16):
531					{
532						glFormat = GL_RED_INTEGER;
533						glInternalFormat=GL_R16UI;
534						return;
535					}
536				}
537				break;
538			}
539		case ePVRTVarTypeSignedShort:
540			{
541				glType = GL_SHORT;
542				switch (PixelFormat)
543				{
544				case PVRTGENPIXELID4('r','g','b','a',16,16,16,16):
545					{
546						glFormat = GL_RGBA_INTEGER;
547						glInternalFormat=GL_RGBA16I;
548						return;
549					}
550				case PVRTGENPIXELID3('r','g','b',16,16,16):
551					{
552						glFormat = GL_RGB_INTEGER;
553						glInternalFormat=GL_RGB16I;
554						return;
555					}
556				case PVRTGENPIXELID2('r','g',16,16):
557					{
558						glFormat = GL_RG_INTEGER;
559						glInternalFormat=GL_RG16I;
560						return;
561					}
562				case PVRTGENPIXELID1('r',16):
563					{
564						glFormat = GL_RED_INTEGER;
565						glInternalFormat=GL_R16I;
566						return;
567					}
568				}
569				break;
570			}
571		case ePVRTVarTypeUnsignedIntegerNorm:
572			{
573				if (PixelFormat==PVRTGENPIXELID4('a','b','g','r',2,10,10,10))
574				{
575					glType = GL_UNSIGNED_INT_2_10_10_10_REV;
576					glFormat = GL_RGBA;
577					glInternalFormat=GL_RGB10_A2;
578					return;
579				}
580				break;
581			}
582		case ePVRTVarTypeUnsignedInteger:
583			{
584				glType = GL_UNSIGNED_INT;
585				switch (PixelFormat)
586				{
587				case PVRTGENPIXELID4('r','g','b','a',32,32,32,32):
588					{
589						glFormat = GL_RGBA_INTEGER;
590						glInternalFormat=GL_RGBA32UI;
591						return;
592					}
593				case PVRTGENPIXELID3('r','g','b',32,32,32):
594					{
595						glFormat = GL_RGB_INTEGER;
596						glInternalFormat=GL_RGB32UI;
597						return;
598					}
599				case PVRTGENPIXELID2('r','g',32,32):
600					{
601						glFormat = GL_RG_INTEGER;
602						glInternalFormat=GL_RG32UI;
603						return;
604					}
605				case PVRTGENPIXELID1('r',32):
606					{
607						glFormat = GL_RED_INTEGER;
608						glInternalFormat=GL_R32UI;
609						return;
610					}
611				case PVRTGENPIXELID4('a','b','g','r',2,10,10,10):
612					{
613						glType = GL_UNSIGNED_INT_2_10_10_10_REV;
614						glFormat = GL_RGBA_INTEGER;
615						glInternalFormat=GL_RGB10_A2UI;
616						return;
617					}
618				}
619				break;
620			}
621		case ePVRTVarTypeSignedInteger:
622			{
623				glType = GL_INT;
624				switch (PixelFormat)
625				{
626				case PVRTGENPIXELID4('r','g','b','a',32,32,32,32):
627					{
628						glFormat = GL_RGBA_INTEGER;
629						glInternalFormat=GL_RGBA32I;
630						return;
631					}
632				case PVRTGENPIXELID3('r','g','b',32,32,32):
633					{
634						glFormat = GL_RGB_INTEGER;
635						glInternalFormat=GL_RGB32I;
636						return;
637					}
638				case PVRTGENPIXELID2('r','g',32,32):
639					{
640						glFormat = GL_RG_INTEGER;
641						glInternalFormat=GL_RG32I;
642						return;
643					}
644				case PVRTGENPIXELID1('r',32):
645					{
646						glFormat = GL_RED_INTEGER;
647						glInternalFormat=GL_R32I;
648						return;
649					}
650				}
651				break;
652			}
653		default: { }
654		}
655	}
656
657	//Default (erroneous) return values.
658	glType = glFormat = glInternalFormat = 0;
659}
660
661
662/*!***************************************************************************
663@Function		PVRTTextureTile
664@Modified		pOut		The tiled texture in system memory
665@Input			pIn			The source texture
666@Input			nRepeatCnt	Number of times to repeat the source texture
667@Description	Allocates and fills, in system memory, a texture large enough
668				to repeat the source texture specified number of times.
669*****************************************************************************/
670void PVRTTextureTile(
671	PVRTextureHeaderV3			**pOut,
672	const PVRTextureHeaderV3	* const pIn,
673	const int					nRepeatCnt)
674{
675	unsigned int		nFormat = 0, nType = 0, nBPP, nSize, nElW = 0, nElH = 0, nElD = 0;
676	PVRTuint8		*pMmSrc, *pMmDst;
677	unsigned int		nLevel;
678	PVRTextureHeaderV3	*psTexHeaderNew;
679
680	_ASSERT(pIn->u32Width);
681	_ASSERT(pIn->u32Width == pIn->u32Height);
682	_ASSERT(nRepeatCnt > 1);
683
684	PVRTGetOGLES3TextureFormat(*pIn,nFormat,nFormat,nType);
685	PVRTGetFormatMinDims(pIn->u64PixelFormat,nElW,nElH,nElD);
686
687	nBPP = PVRTGetBitsPerPixel(pIn->u64PixelFormat);
688	nSize = pIn->u32Width * nRepeatCnt;
689
690	psTexHeaderNew	= PVRTTextureCreate(nSize, nSize, nElW, nElH, nBPP, true);
691	*psTexHeaderNew	= *pIn;
692	pMmDst	= (PVRTuint8*)psTexHeaderNew + sizeof(*psTexHeaderNew);
693	pMmSrc	= (PVRTuint8*)pIn + sizeof(*pIn);
694
695	for(nLevel = 0; ((unsigned int)1 << nLevel) < nSize; ++nLevel)
696	{
697		int nBlocksDstW = PVRT_MAX((unsigned int)1, (nSize >> nLevel) / nElW);
698		int nBlocksDstH = PVRT_MAX((unsigned int)1, (nSize >> nLevel) / nElH);
699		int nBlocksSrcW = PVRT_MAX((unsigned int)1, (pIn->u32Width >> nLevel) / nElW);
700		int nBlocksSrcH = PVRT_MAX((unsigned int)1, (pIn->u32Height >> nLevel) / nElH);
701		int nBlocksS	= nBPP * nElW * nElH / 8;
702
703		PVRTTextureLoadTiled(
704			pMmDst,
705			nBlocksDstW,
706			nBlocksDstH,
707			pMmSrc,
708			nBlocksSrcW,
709			nBlocksSrcH,
710			nBlocksS,
711			(pIn->u64PixelFormat>=ePVRTPF_PVRTCI_2bpp_RGB && pIn->u64PixelFormat<=ePVRTPF_PVRTCI_4bpp_RGBA) ? true : false);
712
713		pMmDst += nBlocksDstW * nBlocksDstH * nBlocksS;
714		pMmSrc += nBlocksSrcW * nBlocksSrcH * nBlocksS;
715	}
716
717	psTexHeaderNew->u32Width = nSize;
718	psTexHeaderNew->u32Height = nSize;
719	psTexHeaderNew->u32MIPMapCount = nLevel+1;
720	*pOut = psTexHeaderNew;
721}
722
723/*!***************************************************************************
724 @Function		PVRTTextureLoadFromPointer
725 @Input			pointer				Pointer to header-texture's structure
726 @Modified		texName				the OpenGL ES texture name as returned by glBindTexture
727 @Modified		psTextureHeader		Pointer to a PVRTextureHeaderV3 struct. Modified to
728									contain the header data of the returned texture Ignored if NULL.
729 @Input			bAllowDecompress	Allow decompression if PVRTC is not supported in hardware.
730 @Input			nLoadFromLevel		Which mip map level to start loading from (0=all)
731 @Input			texPtr				If null, texture follows header, else texture is here.
732 @Modified		pMetaData			If a valid map is supplied, this will return any and all
733									MetaDataBlocks stored in the texture, organised by DevFourCC
734									then identifier. Supplying NULL will ignore all MetaData.
735 @Return		PVR_SUCCESS on success
736 @Description	Allows textures to be stored in C header files and loaded in. Can load parts of a
737				mip mapped texture (i.e. skipping the highest detailed levels). In OpenGL Cube Map, each
738				texture's up direction is defined as next (view direction, up direction),
739				(+x,-y)(-x,-y)(+y,+z)(-y,-z)(+z,-y)(-z,-y).
740				Sets the texture MIN/MAG filter to GL_LINEAR_MIPMAP_NEAREST/GL_LINEAR
741				if mip maps are present, GL_LINEAR/GL_LINEAR otherwise.
742*****************************************************************************/
743EPVRTError PVRTTextureLoadFromPointer(	const void* pointer,
744										GLuint *const texName,
745										const void *psTextureHeader,
746										bool bAllowDecompress,
747										const unsigned int nLoadFromLevel,
748										const void * const texPtr,
749										CPVRTMap<unsigned int, CPVRTMap<unsigned int, MetaDataBlock> > *pMetaData)
750{
751	//Compression bools
752	bool bIsCompressedFormatSupported=false;
753	bool bIsCompressedFormat=false;
754	bool bIsLegacyPVR=false;
755	bool bUsesTexImage3D=false;
756
757	//Texture setup
758	PVRTextureHeaderV3 sTextureHeader;
759	PVRTuint8* pTextureData=NULL;
760
761	//Just in case header and pointer for decompression.
762	PVRTextureHeaderV3 sTextureHeaderDecomp;
763	void* pDecompressedData=NULL;
764
765	//Check if it's an old header format
766	if((*(PVRTuint32*)pointer)!=PVRTEX3_IDENT)
767	{
768		//Convert the texture header to the new format.
769		PVRTConvertOldTextureHeaderToV3((PVR_Texture_Header*)pointer,sTextureHeader,pMetaData);
770
771		//Get the texture data.
772		pTextureData = texPtr? (PVRTuint8*)texPtr:(PVRTuint8*)pointer+*(PVRTuint32*)pointer;
773
774		bIsLegacyPVR=true;
775	}
776	else
777	{
778		//Get the header from the main pointer.
779		sTextureHeader=*(PVRTextureHeaderV3*)pointer;
780
781		//Get the texture data.
782		pTextureData = texPtr? (PVRTuint8*)texPtr:(PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize;
783
784		if (pMetaData)
785		{
786			//Read in all the meta data.
787			PVRTuint32 metaDataSize=0;
788			while (metaDataSize<sTextureHeader.u32MetaDataSize)
789			{
790				//Read the DevFourCC and advance the pointer offset.
791				PVRTuint32 DevFourCC=*(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize);
792				metaDataSize+=sizeof(DevFourCC);
793
794				//Read the Key and advance the pointer offset.
795				PVRTuint32 u32Key=*(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize);
796				metaDataSize+=sizeof(u32Key);
797
798				//Read the DataSize and advance the pointer offset.
799				PVRTuint32 u32DataSize = *(PVRTuint32*)((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize);
800				metaDataSize+=sizeof(u32DataSize);
801
802				//Get the current meta data.
803				MetaDataBlock& currentMetaData = (*pMetaData)[DevFourCC][u32Key];
804
805				//Assign the values to the meta data.
806				currentMetaData.DevFOURCC=DevFourCC;
807				currentMetaData.u32Key=u32Key;
808				currentMetaData.u32DataSize=u32DataSize;
809
810				//Check for data, if there is any, read it into the meta data.
811				if(u32DataSize > 0)
812				{
813					//Allocate memory.
814					currentMetaData.Data = new PVRTuint8[u32DataSize];
815
816					//Copy the data.
817					memcpy(currentMetaData.Data, ((PVRTuint8*)pointer+PVRTEX3_HEADERSIZE+metaDataSize), u32DataSize);
818
819					//Advance the meta data size.
820					metaDataSize+=u32DataSize;
821				}
822			}
823		}
824	}
825
826	//Return the PVRTextureHeader.
827	if (psTextureHeader)
828	{
829		*(PVRTextureHeaderV3*)psTextureHeader=sTextureHeader;
830	}
831
832	//Setup GL Texture format values.
833	GLenum eTextureFormat = 0;
834	GLenum eTextureInternalFormat = 0;	// often this is the same as textureFormat, but not for BGRA8888 on iOS, for instance
835	GLenum eTextureType = 0;
836
837	//Get the OGLES format values.
838	PVRTGetOGLES3TextureFormat(sTextureHeader,eTextureInternalFormat,eTextureFormat,eTextureType);
839
840	bool bIsPVRTCSupported = CPVRTgles3Ext::IsGLExtensionSupported("GL_IMG_texture_compression_pvrtc");
841#ifndef TARGET_OS_IPHONE
842	bool bIsBGRA8888Supported  = CPVRTgles3Ext::IsGLExtensionSupported("GL_IMG_texture_format_BGRA8888");
843#else
844	bool bIsBGRA8888Supported  = CPVRTgles3Ext::IsGLExtensionSupported("GL_APPLE_texture_format_BGRA8888");
845#endif
846#ifndef TARGET_OS_IPHONE
847	bool bIsETCSupported = CPVRTgles3Ext::IsGLExtensionSupported("GL_OES_compressed_ETC1_RGB8_texture");
848#endif
849
850	//Check for compressed formats
851	if (eTextureFormat==0 && eTextureType==0 && eTextureInternalFormat!=0)
852	{
853		if (eTextureInternalFormat>=GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG && eTextureInternalFormat<=GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG)
854		{
855			//Check for PVRTCI support.
856			if(bIsPVRTCSupported)
857			{
858				bIsCompressedFormatSupported = bIsCompressedFormat = true;
859			}
860			else
861			{
862				//Try to decompress the texture.
863				if(bAllowDecompress)
864				{
865					//Output a warning.
866					PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: PVRTC not supported. Converting to RGBA8888 instead.\n");
867
868					//Modify boolean values.
869					bIsCompressedFormatSupported = false;
870					bIsCompressedFormat = true;
871
872					//Check if it's 2bpp.
873					bool bIs2bppPVRTC = (eTextureInternalFormat==GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG || eTextureInternalFormat==GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG);
874
875					//Change texture format.
876					eTextureFormat = eTextureInternalFormat = GL_RGBA;
877					eTextureType = GL_UNSIGNED_BYTE;
878
879					//Create a near-identical texture header for the decompressed header.
880					sTextureHeaderDecomp = sTextureHeader;
881					sTextureHeaderDecomp.u32ChannelType=ePVRTVarTypeUnsignedByteNorm;
882					sTextureHeaderDecomp.u32ColourSpace=ePVRTCSpacelRGB;
883					sTextureHeaderDecomp.u64PixelFormat=PVRTGENPIXELID4('r','g','b','a',8,8,8,8);
884
885					//Allocate enough memory for the decompressed data. OGLES2, so only decompress one surface/face.
886					pDecompressedData = malloc(PVRTGetTextureDataSize(sTextureHeaderDecomp, PVRTEX_ALLMIPLEVELS, false, true) );
887
888					//Check the malloc.
889					if (!pDecompressedData)
890					{
891						PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: Unable to allocate memory to decompress texture.\n");
892						return PVR_FAIL;
893					}
894
895					//Get the dimensions for the current MIP level.
896					PVRTuint32 uiMIPWidth = sTextureHeaderDecomp.u32Width>>nLoadFromLevel;
897					PVRTuint32 uiMIPHeight = sTextureHeaderDecomp.u32Height>>nLoadFromLevel;
898
899					//Setup temporary variables.
900					PVRTuint8* pTempDecompData = (PVRTuint8*)pDecompressedData;
901					PVRTuint8* pTempCompData = (PVRTuint8*)pTextureData;
902
903					if (bIsLegacyPVR)
904					{
905						//Decompress all the MIP levels.
906						for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace)
907						{
908
909							for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap)
910							{
911								//Get the face offset. Varies per MIP level.
912								PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false);
913								PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false);
914
915								//Decompress the texture data.
916								PVRTDecompressPVRTC(pTempCompData,bIs2bppPVRTC?1:0,uiMIPWidth,uiMIPHeight,pTempDecompData);
917
918								//Move forward through the pointers.
919								pTempDecompData+=decompressedFaceOffset;
920								pTempCompData+=compressedFaceOffset;
921
922								//Work out the current MIP dimensions.
923								uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1);
924								uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1);
925							}
926
927							//Reset the dims.
928							uiMIPWidth=sTextureHeader.u32Width;
929							uiMIPHeight=sTextureHeader.u32Height;
930						}
931					}
932					else
933					{
934						//Decompress all the MIP levels.
935						for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap)
936						{
937							//Get the face offset. Varies per MIP level.
938							PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false);
939							PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false);
940
941							for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace)
942							{
943								//Decompress the texture data.
944								PVRTDecompressPVRTC(pTempCompData,bIs2bppPVRTC?1:0,uiMIPWidth,uiMIPHeight,pTempDecompData);
945
946								//Move forward through the pointers.
947								pTempDecompData+=decompressedFaceOffset;
948								pTempCompData+=compressedFaceOffset;
949							}
950
951							//Work out the current MIP dimensions.
952							uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1);
953							uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1);
954						}
955					}
956				}
957				else
958				{
959					PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: PVRTC not supported.\n");
960					return PVR_FAIL;
961				}
962			}
963		}
964#ifndef TARGET_OS_IPHONE //TODO
965		else if (eTextureInternalFormat==GL_ETC1_RGB8_OES)
966		{
967			if(bIsETCSupported)
968			{
969				bIsCompressedFormatSupported = bIsCompressedFormat = true;
970			}
971			else
972			{
973				if(bAllowDecompress)
974				{
975					//Output a warning.
976					PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: ETC not supported. Converting to RGBA8888 instead.\n");
977
978					//Modify boolean values.
979					bIsCompressedFormatSupported = false;
980					bIsCompressedFormat = true;
981
982					//Change texture format.
983					eTextureFormat = eTextureInternalFormat = GL_RGBA;
984					eTextureType = GL_UNSIGNED_BYTE;
985
986					//Create a near-identical texture header for the decompressed header.
987					sTextureHeaderDecomp = sTextureHeader;
988					sTextureHeaderDecomp.u32ChannelType=ePVRTVarTypeUnsignedByteNorm;
989					sTextureHeaderDecomp.u32ColourSpace=ePVRTCSpacelRGB;
990					sTextureHeaderDecomp.u64PixelFormat=PVRTGENPIXELID4('r','g','b','a',8,8,8,8);
991
992					//Allocate enough memory for the decompressed data. OGLES1, so only decompress one surface/face.
993					pDecompressedData = malloc(PVRTGetTextureDataSize(sTextureHeaderDecomp, PVRTEX_ALLMIPLEVELS, false, true) );
994
995					//Check the malloc.
996					if (!pDecompressedData)
997					{
998						PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: Unable to allocate memory to decompress texture.\n");
999						return PVR_FAIL;
1000					}
1001
1002					//Get the dimensions for the current MIP level.
1003					PVRTuint32 uiMIPWidth = sTextureHeaderDecomp.u32Width>>nLoadFromLevel;
1004					PVRTuint32 uiMIPHeight = sTextureHeaderDecomp.u32Height>>nLoadFromLevel;
1005
1006					//Setup temporary variables.
1007					PVRTuint8* pTempDecompData = (PVRTuint8*)pDecompressedData;
1008					PVRTuint8* pTempCompData = (PVRTuint8*)pTextureData;
1009
1010					if (bIsLegacyPVR)
1011					{
1012						//Decompress all the MIP levels.
1013						for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace)
1014						{
1015
1016							for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap)
1017							{
1018								//Get the face offset. Varies per MIP level.
1019								PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false);
1020								PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false);
1021
1022								//Decompress the texture data.
1023								PVRTDecompressETC(pTempCompData,uiMIPWidth,uiMIPHeight,pTempDecompData,0);
1024
1025								//Move forward through the pointers.
1026								pTempDecompData+=decompressedFaceOffset;
1027								pTempCompData+=compressedFaceOffset;
1028
1029								//Work out the current MIP dimensions.
1030								uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1);
1031								uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1);
1032							}
1033
1034							//Reset the dims.
1035							uiMIPWidth=sTextureHeader.u32Width;
1036							uiMIPHeight=sTextureHeader.u32Height;
1037						}
1038					}
1039					else
1040					{
1041						//Decompress all the MIP levels.
1042						for (PVRTuint32 uiMIPMap=nLoadFromLevel;uiMIPMap<sTextureHeader.u32MIPMapCount;++uiMIPMap)
1043						{
1044							//Get the face offset. Varies per MIP level.
1045							PVRTuint32 decompressedFaceOffset = PVRTGetTextureDataSize(sTextureHeaderDecomp, uiMIPMap, false, false);
1046							PVRTuint32 compressedFaceOffset = PVRTGetTextureDataSize(sTextureHeader, uiMIPMap, false, false);
1047
1048							for (PVRTuint32 uiFace=0;uiFace<sTextureHeader.u32NumFaces;++uiFace)
1049							{
1050								//Decompress the texture data.
1051								PVRTDecompressETC(pTempCompData,uiMIPWidth,uiMIPHeight,pTempDecompData,0);
1052
1053								//Move forward through the pointers.
1054								pTempDecompData+=decompressedFaceOffset;
1055								pTempCompData+=compressedFaceOffset;
1056							}
1057
1058							//Work out the current MIP dimensions.
1059							uiMIPWidth=PVRT_MAX(1,uiMIPWidth>>1);
1060							uiMIPHeight=PVRT_MAX(1,uiMIPHeight>>1);
1061						}
1062					}
1063				}
1064				else
1065				{
1066					PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: ETC not supported.\n");
1067					return PVR_FAIL;
1068				}
1069			}
1070		}
1071#endif
1072	}
1073
1074	//Check for BGRA support.
1075	if(eTextureFormat==GL_BGRA_IMG)
1076	{
1077#ifdef TARGET_OS_IPHONE
1078		eTextureInternalFormat = GL_RGBA;
1079#endif
1080		if(!bIsBGRA8888Supported)
1081		{
1082#ifdef TARGET_OS_IPHONE
1083			PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Unable to load GL_BGRA_IMG texture as extension GL_APPLE_texture_format_BGRA8888 is unsupported.\n");
1084#else
1085			PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Unable to load GL_BGRA_IMG texture as extension GL_IMG_texture_format_BGRA8888 is unsupported.\n");
1086#endif
1087			return PVR_FAIL;
1088		}
1089	}
1090
1091	//Deal with unsupported texture formats
1092	if (eTextureInternalFormat==0)
1093	{
1094		PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: pixel type not supported.\n");
1095		return PVR_FAIL;
1096	}
1097
1098	//PVR files are never row aligned.
1099	glPixelStorei(GL_UNPACK_ALIGNMENT,1);
1100
1101	//Generate a texture
1102	glGenTextures(1, texName);
1103
1104	//Initialise a texture target.
1105	GLint eTarget=GL_TEXTURE_2D;
1106
1107	//A mix of arrays/cubes/depths are not permitted in OpenGL ES. Check.
1108	if (sTextureHeader.u32NumFaces>1 || sTextureHeader.u32NumSurfaces>1 || sTextureHeader.u32Depth>1)
1109	{
1110		if((sTextureHeader.u32NumFaces>1) && (sTextureHeader.u32NumSurfaces>1))
1111		{
1112			PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Arrays of cubemaps are not supported by OpenGL ES 3.0\n");
1113			return PVR_FAIL;
1114		}
1115		else if ((sTextureHeader.u32NumFaces>1) && (sTextureHeader.u32Depth>1))
1116		{
1117			PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: 3D Cubemap textures are not supported by OpenGL ES 3.0\n");
1118			return PVR_FAIL;
1119		}
1120		else if ((sTextureHeader.u32NumSurfaces>1) && (sTextureHeader.u32Depth>1))
1121		{
1122			PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Arrays of 3D textures are not supported by OpenGL ES 3.0\n");
1123			return PVR_FAIL;
1124		}
1125
1126		if(sTextureHeader.u32NumSurfaces>1)
1127		{
1128			eTarget=GL_TEXTURE_2D_ARRAY;
1129			bUsesTexImage3D=true;
1130		}
1131		else if(sTextureHeader.u32NumFaces>1)
1132		{
1133			eTarget=GL_TEXTURE_CUBE_MAP;
1134		}
1135		else if (sTextureHeader.u32Depth>1)
1136		{
1137			eTarget=GL_TEXTURE_3D;
1138			bUsesTexImage3D=true;
1139		}
1140	}
1141
1142	//Bind the texture
1143	glBindTexture(eTarget, *texName);
1144
1145	if(glGetError())
1146	{
1147		PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glBindTexture() failed.\n");
1148		return PVR_FAIL;
1149	}
1150
1151	//Temporary data to save on if statements within the load loops.
1152	PVRTuint8* pTempData=NULL;
1153	PVRTextureHeaderV3 *psTempHeader=NULL;
1154	if (bIsCompressedFormat && !bIsCompressedFormatSupported)
1155	{
1156		pTempData=(PVRTuint8*)pDecompressedData;
1157		psTempHeader=&sTextureHeaderDecomp;
1158	}
1159	else
1160	{
1161		pTempData=pTextureData;
1162		psTempHeader=&sTextureHeader;
1163	}
1164
1165	//Initialise the current MIP size.
1166	PVRTuint32 uiCurrentMIPSize=0;
1167
1168	//Initialise the width/height
1169	PVRTuint32 u32MIPWidth = sTextureHeader.u32Width;
1170	PVRTuint32 u32MIPHeight = sTextureHeader.u32Height;
1171	PVRTuint32 u32MIPDepth;
1172	if (psTempHeader->u32Depth>1)
1173	{
1174		u32MIPDepth=psTempHeader->u32Depth; //3d texture.
1175	}
1176	else
1177	{
1178		u32MIPDepth=psTempHeader->u32NumSurfaces; //2d arrays.
1179	}
1180
1181	//Loop through all MIP levels.
1182	if (bIsLegacyPVR)
1183	{
1184		//Temporary texture target.
1185		GLint eTextureTarget=eTarget;
1186
1187		//Cubemaps are special.
1188		if (eTextureTarget==GL_TEXTURE_CUBE_MAP)
1189		{
1190			eTextureTarget=GL_TEXTURE_CUBE_MAP_POSITIVE_X;
1191		}
1192
1193		//Loop through all the faces.
1194		for (PVRTuint32 uiFace=0; uiFace<psTempHeader->u32NumFaces; ++uiFace)
1195		{
1196			//Loop through all the mip levels.
1197			for (PVRTuint32 uiMIPLevel=0; uiMIPLevel<psTempHeader->u32MIPMapCount; ++uiMIPLevel)
1198			{
1199				//Get the current MIP size.
1200				uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false);
1201
1202				if (uiMIPLevel>=nLoadFromLevel)
1203				{
1204					//Upload the texture
1205					if (bUsesTexImage3D)
1206					{
1207						if (bIsCompressedFormat && bIsCompressedFormatSupported)
1208						{
1209							glCompressedTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, uiCurrentMIPSize, pTempData);
1210						}
1211						else
1212						{
1213							glTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, u32MIPDepth,  0, eTextureFormat, eTextureType, pTempData);
1214						}
1215					}
1216					else
1217					{
1218						if (bIsCompressedFormat && bIsCompressedFormatSupported)
1219						{
1220							glCompressedTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, 0, uiCurrentMIPSize, pTempData);
1221						}
1222						else
1223						{
1224							glTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, eTextureFormat, eTextureType, pTempData);
1225						}
1226					}
1227				}
1228				pTempData+=uiCurrentMIPSize;
1229
1230				//Reduce the MIP Size.
1231				u32MIPWidth=PVRT_MAX(1,u32MIPWidth>>1);
1232				u32MIPHeight=PVRT_MAX(1,u32MIPHeight>>1);
1233				if (psTempHeader->u32Depth>1)
1234				{
1235					u32MIPDepth=PVRT_MAX(1,u32MIPDepth>>1);
1236				}
1237			}
1238
1239			//Increase the texture target.
1240			eTextureTarget++;
1241
1242			//Reset the current MIP dimensions.
1243			u32MIPWidth=psTempHeader->u32Width;
1244			u32MIPHeight=psTempHeader->u32Height;
1245
1246			if (psTempHeader->u32Depth>1)
1247			{
1248				u32MIPDepth=psTempHeader->u32Depth;
1249			}
1250			else
1251			{
1252				u32MIPDepth=psTempHeader->u32NumSurfaces; //2d arrays.
1253			}
1254
1255			//Error check
1256			if(glGetError())
1257			{
1258				FREE(pDecompressedData);
1259				PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n");
1260				return PVR_FAIL;
1261			}
1262		}
1263	}
1264	else
1265	{
1266		for (PVRTuint32 uiMIPLevel=0; uiMIPLevel<psTempHeader->u32MIPMapCount; ++uiMIPLevel)
1267		{
1268			//Get the current MIP size.
1269			uiCurrentMIPSize=PVRTGetTextureDataSize(*psTempHeader,uiMIPLevel,false,false);
1270
1271			GLint eTextureTarget=eTarget;
1272			//Cubemaps are special.
1273			if (eTextureTarget==GL_TEXTURE_CUBE_MAP)
1274			{
1275				eTextureTarget=GL_TEXTURE_CUBE_MAP_POSITIVE_X;
1276			}
1277
1278			for (PVRTuint32 uiFace=0; uiFace<psTempHeader->u32NumFaces; ++uiFace)
1279			{
1280				if (uiMIPLevel>=nLoadFromLevel)
1281				{
1282					//Upload the texture
1283					if (bUsesTexImage3D)
1284					{
1285						//Upload the texture
1286						if (bIsCompressedFormat && bIsCompressedFormatSupported)
1287						{
1288							glCompressedTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, uiCurrentMIPSize, pTempData);
1289						}
1290						else
1291						{
1292							glTexImage3D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, u32MIPDepth, 0, eTextureFormat, eTextureType, pTempData);
1293						}
1294					}
1295					else
1296					{
1297						//Upload the texture
1298						if (bIsCompressedFormat && bIsCompressedFormatSupported)
1299						{
1300							glCompressedTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat,u32MIPWidth, u32MIPHeight, 0, uiCurrentMIPSize, pTempData);
1301						}
1302						else
1303						{
1304							glTexImage2D(eTextureTarget,uiMIPLevel-nLoadFromLevel,eTextureInternalFormat, u32MIPWidth, u32MIPHeight, 0, eTextureFormat, eTextureType, pTempData);
1305						}
1306					}
1307				}
1308				pTempData+=uiCurrentMIPSize;
1309				eTextureTarget++;
1310			}
1311
1312			//Reduce the MIP Size.
1313			u32MIPWidth=PVRT_MAX(1,u32MIPWidth>>1);
1314			u32MIPHeight=PVRT_MAX(1,u32MIPHeight>>1);
1315			if (psTempHeader->u32Depth>1)
1316			{
1317				u32MIPDepth=PVRT_MAX(1,u32MIPDepth>>1); //Only reduce depth for 3D textures, not texture arrays.
1318			}
1319
1320			//Error check
1321			if(glGetError())
1322			{
1323				FREE(pDecompressedData);
1324				PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n");
1325				return PVR_FAIL;
1326			}
1327		}
1328	}
1329
1330	FREE(pDecompressedData);
1331
1332	//Error check
1333	if(glGetError())
1334	{
1335		PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n");
1336		return PVR_FAIL;
1337	}
1338
1339	//Set Minification and Magnification filters according to whether MIP maps are present.
1340	if(eTextureType==GL_FLOAT || eTextureType==GL_HALF_FLOAT)
1341	{
1342		if(sTextureHeader.u32MIPMapCount==1)
1343		{	// Texture filter modes are limited to these for float textures
1344			glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1345			glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1346		}
1347		else
1348		{
1349			glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
1350			glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1351		}
1352	}
1353	else
1354	{
1355		if(sTextureHeader.u32MIPMapCount==1)
1356		{
1357			glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1358			glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1359		}
1360		else
1361		{
1362			glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
1363			glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1364		}
1365	}
1366
1367	if(	(sTextureHeader.u32Width & (sTextureHeader.u32Width - 1)) | (sTextureHeader.u32Height & (sTextureHeader.u32Height - 1)))
1368	{
1369		/*
1370			NPOT textures requires the wrap mode to be set explicitly to
1371			GL_CLAMP_TO_EDGE or the texture will be inconsistent.
1372		*/
1373		glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1374		glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1375	}
1376	else
1377	{
1378		glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, GL_REPEAT);
1379		glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, GL_REPEAT);
1380	}
1381
1382	//Error check
1383	if(glGetError())
1384	{
1385		PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexParameter() failed.\n");
1386		return PVR_FAIL;
1387	}
1388
1389	return PVR_SUCCESS;
1390}
1391
1392/*!***************************************************************************
1393 @Function		PVRTTextureLoadFromPVR
1394 @Input			filename			Filename of the .PVR file to load the texture from
1395 @Modified		texName				the OpenGL ES texture name as returned by glBindTexture
1396 @Modified		psTextureHeader		Pointer to a PVR_Texture_Header struct. Modified to
1397									contain the header data of the returned texture Ignored if NULL.
1398 @Input			bAllowDecompress	Allow decompression if PVRTC is not supported in hardware.
1399 @Input			nLoadFromLevel		Which mipmap level to start loading from (0=all)
1400 @Modified		pMetaData			If a valid map is supplied, this will return any and all
1401									MetaDataBlocks stored in the texture, organised by DevFourCC
1402									then identifier. Supplying NULL will ignore all MetaData.
1403 @Return		PVR_SUCCESS on success
1404 @Description	Allows textures to be stored in binary PVR files and loaded in. Can load parts of a
1405				mipmaped texture (ie skipping the highest detailed levels).
1406				Sets the texture MIN/MAG filter to GL_LINEAR_MIPMAP_NEAREST/GL_LINEAR
1407				if mipmaps are present, GL_LINEAR/GL_LINEAR otherwise.
1408*****************************************************************************/
1409EPVRTError PVRTTextureLoadFromPVR(	const char * const filename,
1410									GLuint * const texName,
1411									const void *psTextureHeader,
1412									bool bAllowDecompress,
1413									const unsigned int nLoadFromLevel,
1414									CPVRTMap<unsigned int, CPVRTMap<unsigned int, MetaDataBlock> > *pMetaData)
1415{
1416	//Attempt to open file.
1417	CPVRTResourceFile TexFile(filename);
1418
1419	//Check file opened successfully.
1420	if (!TexFile.IsOpen())
1421	{
1422		return PVR_FAIL;
1423	}
1424
1425	//Header size.
1426	PVRTuint32 u32HeaderSize=0;
1427
1428	//Boolean whether to byte swap the texture data or not.
1429	bool bSwapDataEndianness=false;
1430
1431	//Texture header to check against.
1432	PVRTextureHeaderV3 sTextureHeader;
1433
1434	//The channel type for endian swapping.
1435	EPVRTVariableType u32CurrentChannelType=ePVRTVarTypeUnsignedByte;
1436
1437	//Check the first word of the file and see if it's equal to the current identifier (or reverse identifier)
1438	if(*(PVRTuint32*)TexFile.DataPtr()!=PVRTEX_CURR_IDENT && *(PVRTuint32*)TexFile.DataPtr()!=PVRTEX_CURR_IDENT_REV)
1439	{
1440		//Swap the header bytes if necessary.
1441		if(!PVRTIsLittleEndian())
1442		{
1443			bSwapDataEndianness=true;
1444			PVRTuint32 u32HeaderSize=PVRTByteSwap32(*(PVRTuint32*)TexFile.DataPtr());
1445
1446			for (PVRTuint32 i=0; i<u32HeaderSize; ++i)
1447			{
1448				PVRTByteSwap( (PVRTuint8*)( ( (PVRTuint32*)TexFile.DataPtr() )+i),sizeof(PVRTuint32) );
1449			}
1450		}
1451
1452		//Get a pointer to the header.
1453		PVR_Texture_Header* sLegacyTextureHeader=(PVR_Texture_Header*)TexFile.DataPtr();
1454
1455		//Set the header size.
1456		u32HeaderSize=sLegacyTextureHeader->dwHeaderSize;
1457
1458		//We only really need the channel type.
1459		PVRTuint64 tempFormat;
1460		EPVRTColourSpace tempColourSpace;
1461		bool tempIsPreMult;
1462
1463		//Map the enum to get the channel type.
1464		PVRTMapLegacyTextureEnumToNewFormat( (PVRTPixelType)( sLegacyTextureHeader->dwpfFlags&0xff),tempFormat,tempColourSpace, u32CurrentChannelType, tempIsPreMult);
1465	}
1466	// If the header file has a reverse identifier, then we need to swap endianness
1467	else if(*(PVRTuint32*)TexFile.DataPtr()==PVRTEX_CURR_IDENT_REV)
1468	{
1469		//Setup the texture header
1470		sTextureHeader=*(PVRTextureHeaderV3*)TexFile.DataPtr();
1471
1472		bSwapDataEndianness=true;
1473		PVRTextureHeaderV3* pTextureHeader=(PVRTextureHeaderV3*)TexFile.DataPtr();
1474
1475		pTextureHeader->u32ChannelType=PVRTByteSwap32(pTextureHeader->u32ChannelType);
1476		pTextureHeader->u32ColourSpace=PVRTByteSwap32(pTextureHeader->u32ColourSpace);
1477		pTextureHeader->u32Depth=PVRTByteSwap32(pTextureHeader->u32Depth);
1478		pTextureHeader->u32Flags=PVRTByteSwap32(pTextureHeader->u32Flags);
1479		pTextureHeader->u32Height=PVRTByteSwap32(pTextureHeader->u32Height);
1480		pTextureHeader->u32MetaDataSize=PVRTByteSwap32(pTextureHeader->u32MetaDataSize);
1481		pTextureHeader->u32MIPMapCount=PVRTByteSwap32(pTextureHeader->u32MIPMapCount);
1482		pTextureHeader->u32NumFaces=PVRTByteSwap32(pTextureHeader->u32NumFaces);
1483		pTextureHeader->u32NumSurfaces=PVRTByteSwap32(pTextureHeader->u32NumSurfaces);
1484		pTextureHeader->u32Version=PVRTByteSwap32(pTextureHeader->u32Version);
1485		pTextureHeader->u32Width=PVRTByteSwap32(pTextureHeader->u32Width);
1486		PVRTByteSwap((PVRTuint8*)&pTextureHeader->u64PixelFormat,sizeof(PVRTuint64));
1487
1488		//Channel type.
1489		u32CurrentChannelType=(EPVRTVariableType)pTextureHeader->u32ChannelType;
1490
1491		//Header size.
1492		u32HeaderSize=PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize;
1493	}
1494	else
1495	{
1496		//Header size.
1497		u32HeaderSize=PVRTEX3_HEADERSIZE+sTextureHeader.u32MetaDataSize;
1498	}
1499
1500	// Convert the data if needed
1501	if(bSwapDataEndianness)
1502	{
1503		//Get the size of the variables types.
1504		PVRTuint32 ui32VariableSize=0;
1505		switch(u32CurrentChannelType)
1506		{
1507		case ePVRTVarTypeFloat:
1508		case ePVRTVarTypeUnsignedInteger:
1509		case ePVRTVarTypeUnsignedIntegerNorm:
1510		case ePVRTVarTypeSignedInteger:
1511		case ePVRTVarTypeSignedIntegerNorm:
1512			{
1513				ui32VariableSize=4;
1514				break;
1515			}
1516		case ePVRTVarTypeUnsignedShort:
1517		case ePVRTVarTypeUnsignedShortNorm:
1518		case ePVRTVarTypeSignedShort:
1519		case ePVRTVarTypeSignedShortNorm:
1520			{
1521				ui32VariableSize=2;
1522				break;
1523			}
1524		case ePVRTVarTypeUnsignedByte:
1525		case ePVRTVarTypeUnsignedByteNorm:
1526		case ePVRTVarTypeSignedByte:
1527		case ePVRTVarTypeSignedByteNorm:
1528			{
1529				ui32VariableSize=1;
1530				break;
1531			}
1532        default:
1533            return PVR_FAIL;
1534		}
1535
1536		//If the size of the variable type is greater than 1, then we need to byte swap.
1537		if (ui32VariableSize>1)
1538		{
1539			//Get the texture data.
1540			PVRTuint8* pu8OrigData = ( (PVRTuint8*)TexFile.DataPtr() + u32HeaderSize);
1541
1542			//Get the size of the texture data.
1543			PVRTuint32 ui32TextureDataSize = PVRTGetTextureDataSize(sTextureHeader);
1544
1545			//Loop through and byte swap all the data. It's swapped in place so no need to do anything special.
1546			for(PVRTuint32 i = 0; i < ui32TextureDataSize; i+=ui32VariableSize)
1547			{
1548				PVRTByteSwap(pu8OrigData+i,ui32VariableSize);
1549			}
1550		}
1551	}
1552
1553	return PVRTTextureLoadFromPointer(TexFile.DataPtr(), texName, psTextureHeader, bAllowDecompress, nLoadFromLevel,NULL,pMetaData);
1554}
1555
1556/*****************************************************************************
1557 End of file (PVRTTextureAPI.cpp)
1558*****************************************************************************/
1559
1560