PVRTTextureAPI.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. /******************************************************************************
  2. @File PVRTTextureAPI.cpp
  3. @Title OGLES2\PVRTTextureAPI
  4. @Version
  5. @Copyright Copyright (C) Imagination Technologies Limited.
  6. @Platform ANSI compatible
  7. @Description OGLES2 texture loading.
  8. ******************************************************************************/
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include "PVRTContext.h"
  12. #include "PVRTgles2Ext.h"
  13. #include "PVRTTexture.h"
  14. #include "PVRTTextureAPI.h"
  15. #include "PVRTDecompress.h"
  16. #include "PVRTFixedPoint.h"
  17. #include "PVRTMatrix.h"
  18. #include "PVRTMisc.h"
  19. #include "PVRTResourceFile.h"
  20. /*****************************************************************************
  21. ** Functions
  22. ****************************************************************************/
  23. /*!***************************************************************************
  24. @Function PVRTTextureTile
  25. @Modified pOut The tiled texture in system memory
  26. @Input pIn The source texture
  27. @Input nRepeatCnt Number of times to repeat the source texture
  28. @Description Allocates and fills, in system memory, a texture large enough
  29. to repeat the source texture specified number of times.
  30. *****************************************************************************/
  31. void PVRTTextureTile(
  32. PVR_Texture_Header **pOut,
  33. const PVR_Texture_Header * const pIn,
  34. const int nRepeatCnt)
  35. {
  36. unsigned int nFormat = 0, nType = 0, nBPP, nSize, nElW = 0, nElH = 0;
  37. PVRTuint8 *pMmSrc, *pMmDst;
  38. unsigned int nLevel;
  39. PVR_Texture_Header *psTexHeaderNew;
  40. _ASSERT(pIn->dwWidth);
  41. _ASSERT(pIn->dwWidth == pIn->dwHeight);
  42. _ASSERT(nRepeatCnt > 1);
  43. switch(pIn->dwpfFlags & PVRTEX_PIXELTYPE)
  44. {
  45. case OGL_RGBA_5551:
  46. nFormat = GL_UNSIGNED_SHORT_5_5_5_1;
  47. nType = GL_RGBA;
  48. nElW = 1;
  49. nElH = 1;
  50. break;
  51. case OGL_RGBA_8888:
  52. nFormat = GL_UNSIGNED_BYTE;
  53. nType = GL_RGBA;
  54. nElW = 1;
  55. nElH = 1;
  56. break;
  57. case OGL_PVRTC2:
  58. nFormat = GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG;
  59. nType = 0;
  60. nElW = 8;
  61. nElH = 4;
  62. break;
  63. case OGL_PVRTC4:
  64. nFormat = GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG;
  65. nType = 0;
  66. nElW = 4;
  67. nElH = 4;
  68. break;
  69. }
  70. nBPP = PVRTTextureFormatGetBPP(nFormat, nType);
  71. nSize = pIn->dwWidth * nRepeatCnt;
  72. psTexHeaderNew = PVRTTextureCreate(nSize, nSize, nElW, nElH, nBPP, true);
  73. *psTexHeaderNew = *pIn;
  74. pMmDst = (PVRTuint8*)psTexHeaderNew + sizeof(*psTexHeaderNew);
  75. pMmSrc = (PVRTuint8*)pIn + sizeof(*pIn);
  76. for(nLevel = 0; ((unsigned int)1 << nLevel) < nSize; ++nLevel)
  77. {
  78. int nBlocksDstW = PVRT_MAX((unsigned int)1, (nSize >> nLevel) / nElW);
  79. int nBlocksDstH = PVRT_MAX((unsigned int)1, (nSize >> nLevel) / nElH);
  80. int nBlocksSrcW = PVRT_MAX((unsigned int)1, (pIn->dwWidth >> nLevel) / nElW);
  81. int nBlocksSrcH = PVRT_MAX((unsigned int)1, (pIn->dwHeight >> nLevel) / nElH);
  82. int nBlocksS = nBPP * nElW * nElH / 8;
  83. PVRTTextureLoadTiled(
  84. pMmDst,
  85. nBlocksDstW,
  86. nBlocksDstH,
  87. pMmSrc,
  88. nBlocksSrcW,
  89. nBlocksSrcH,
  90. nBlocksS,
  91. (pIn->dwpfFlags & PVRTEX_TWIDDLE) ? true : false);
  92. pMmDst += nBlocksDstW * nBlocksDstH * nBlocksS;
  93. pMmSrc += nBlocksSrcW * nBlocksSrcH * nBlocksS;
  94. }
  95. psTexHeaderNew->dwWidth = nSize;
  96. psTexHeaderNew->dwHeight = nSize;
  97. psTexHeaderNew->dwMipMapCount = nLevel;
  98. *pOut = psTexHeaderNew;
  99. }
  100. /*!***************************************************************************
  101. @Function PVRTTextureLoadFromPointer
  102. @Input pointer Pointer to header-texture's structure
  103. @Modified texName the OpenGL ES texture name as returned by glBindTexture
  104. @Modified psTextureHeader Pointer to a PVR_Texture_Header struct. Modified to
  105. contain the header data of the returned texture Ignored if NULL.
  106. @Input bAllowDecompress Allow decompression if PVRTC is not supported in hardware.
  107. @Input nLoadFromLevel Which mipmap level to start loading from (0=all)
  108. @Input texPtr If null, texture follows header, else texture is here.
  109. @Return PVR_SUCCESS on success
  110. @Description Allows textures to be stored in C header files and loaded in. Can load parts of a
  111. mipmaped texture (ie skipping the highest detailed levels).In OpenGL Cube Map, each
  112. texture's up direction is defined as next (view direction, up direction),
  113. (+x,-y)(-x,-y)(+y,+z)(-y,-z)(+z,-y)(-z,-y).
  114. Sets the texture MIN/MAG filter to GL_LINEAR_MIPMAP_NEAREST/GL_LINEAR
  115. if mipmaps are present, GL_LINEAR/GL_LINEAR otherwise.
  116. *****************************************************************************/
  117. EPVRTError PVRTTextureLoadFromPointer( const void* pointer,
  118. GLuint *const texName,
  119. const void *psTextureHeader,
  120. bool bAllowDecompress,
  121. const unsigned int nLoadFromLevel,
  122. const void * const texPtr)
  123. {
  124. PVR_Texture_Header* psPVRHeader = (PVR_Texture_Header*)pointer;
  125. unsigned int u32NumSurfs;
  126. // perform checks for old PVR psPVRHeader
  127. if(psPVRHeader->dwHeaderSize!=sizeof(PVR_Texture_Header))
  128. { // Header V1
  129. if(psPVRHeader->dwHeaderSize==PVRTEX_V1_HEADER_SIZE)
  130. { // react to old psPVRHeader: i.e. fill in numsurfs as this is missing from old header
  131. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: this is an old pvr"
  132. " - you can use PVRTexTool to update its header.\n");
  133. if(psPVRHeader->dwpfFlags&PVRTEX_CUBEMAP)
  134. u32NumSurfs = 6;
  135. else
  136. u32NumSurfs = 1;
  137. }
  138. else
  139. { // not a pvr at all
  140. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: not a valid pvr.\n");
  141. return PVR_FAIL;
  142. }
  143. }
  144. else
  145. { // Header V2
  146. if(psPVRHeader->dwNumSurfs<1)
  147. { // encoded with old version of PVRTexTool before zero numsurfs bug found.
  148. if(psPVRHeader->dwpfFlags & PVRTEX_CUBEMAP)
  149. u32NumSurfs = 6;
  150. else
  151. u32NumSurfs = 1;
  152. }
  153. else
  154. {
  155. u32NumSurfs = psPVRHeader->dwNumSurfs;
  156. }
  157. }
  158. GLuint textureName;
  159. GLenum eTextureFormat = 0;
  160. GLenum eTextureInternalFormat = 0; // often this is the same as textureFormat, but not for BGRA8888 on the iPhone, for instance
  161. GLenum eTextureType = 0;
  162. GLenum eTarget;
  163. bool bIsPVRTCSupported = CPVRTgles2Ext::IsGLExtensionSupported("GL_IMG_texture_compression_pvrtc");
  164. #ifndef TARGET_OS_IPHONE
  165. bool bIsBGRA8888Supported = CPVRTgles2Ext::IsGLExtensionSupported("GL_IMG_texture_format_BGRA8888");
  166. #else
  167. bool bIsBGRA8888Supported = CPVRTgles2Ext::IsGLExtensionSupported("GL_APPLE_texture_format_BGRA8888");
  168. #endif
  169. bool bIsFloat16Supported = CPVRTgles2Ext::IsGLExtensionSupported("GL_OES_texture_half_float");
  170. bool bIsFloat32Supported = CPVRTgles2Ext::IsGLExtensionSupported("GL_OES_texture_float");
  171. #ifndef TARGET_OS_IPHONE
  172. bool bIsETCSupported = CPVRTgles2Ext::IsGLExtensionSupported("GL_OES_compressed_ETC1_RGB8_texture");
  173. #endif
  174. *texName = 0; // install warning value
  175. bool bIsCompressedFormatSupported = false, bIsCompressedFormat = false;
  176. /* Only accept untwiddled data UNLESS texture format is PVRTC */
  177. if ( ((psPVRHeader->dwpfFlags & PVRTEX_TWIDDLE) == PVRTEX_TWIDDLE)
  178. && ((psPVRHeader->dwpfFlags & PVRTEX_PIXELTYPE)!=OGL_PVRTC2)
  179. && ((psPVRHeader->dwpfFlags & PVRTEX_PIXELTYPE)!=OGL_PVRTC4) )
  180. {
  181. // We need to load untwiddled textures -- GL will twiddle for us.
  182. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: texture should be untwiddled.\n");
  183. return PVR_FAIL;
  184. }
  185. unsigned int ePixelType = psPVRHeader->dwpfFlags & PVRTEX_PIXELTYPE;
  186. switch(ePixelType)
  187. {
  188. case OGL_RGBA_4444:
  189. eTextureFormat = eTextureInternalFormat = GL_RGBA;
  190. eTextureType = GL_UNSIGNED_SHORT_4_4_4_4;
  191. break;
  192. case OGL_RGBA_5551:
  193. eTextureFormat = eTextureInternalFormat = GL_RGBA ;
  194. eTextureType = GL_UNSIGNED_SHORT_5_5_5_1;
  195. break;
  196. case OGL_RGBA_8888:
  197. eTextureFormat = eTextureInternalFormat = GL_RGBA;
  198. eTextureType = GL_UNSIGNED_BYTE ;
  199. break;
  200. /* New OGL Specific Formats Added */
  201. case OGL_RGB_565:
  202. eTextureFormat = eTextureInternalFormat = GL_RGB ;
  203. eTextureType = GL_UNSIGNED_SHORT_5_6_5;
  204. break;
  205. case OGL_RGB_555:
  206. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: pixel type OGL_RGB_555 not supported.\n");
  207. return PVR_FAIL; // Deal with exceptional case
  208. case OGL_RGB_888:
  209. eTextureFormat = eTextureInternalFormat = GL_RGB ;
  210. eTextureType = GL_UNSIGNED_BYTE;
  211. break;
  212. case OGL_I_8:
  213. eTextureFormat = eTextureInternalFormat = GL_LUMINANCE;
  214. eTextureType = GL_UNSIGNED_BYTE;
  215. break;
  216. case OGL_AI_88:
  217. eTextureFormat = eTextureInternalFormat = GL_LUMINANCE_ALPHA ;
  218. eTextureType = GL_UNSIGNED_BYTE;
  219. break;
  220. case MGLPT_PVRTC2:
  221. case OGL_PVRTC2:
  222. if(bIsPVRTCSupported)
  223. {
  224. bIsCompressedFormatSupported = bIsCompressedFormat = true;
  225. eTextureFormat = psPVRHeader->dwAlphaBitMask==0 ? GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG : GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG ; // PVRTC2
  226. }
  227. else
  228. {
  229. if(bAllowDecompress)
  230. {
  231. bIsCompressedFormatSupported = false;
  232. bIsCompressedFormat = true;
  233. eTextureFormat = eTextureInternalFormat = GL_RGBA;
  234. eTextureType = GL_UNSIGNED_BYTE;
  235. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: PVRTC2 not supported. Converting to RGBA8888 instead.\n");
  236. }
  237. else
  238. {
  239. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: PVRTC2 not supported.\n");
  240. return PVR_FAIL;
  241. }
  242. }
  243. break;
  244. case MGLPT_PVRTC4:
  245. case OGL_PVRTC4:
  246. if(bIsPVRTCSupported)
  247. {
  248. bIsCompressedFormatSupported = bIsCompressedFormat = true;
  249. eTextureFormat = psPVRHeader->dwAlphaBitMask==0 ? GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG ; // PVRTC4
  250. }
  251. else
  252. {
  253. if(bAllowDecompress)
  254. {
  255. bIsCompressedFormatSupported = false;
  256. bIsCompressedFormat = true;
  257. eTextureFormat = eTextureInternalFormat = GL_RGBA;
  258. eTextureType = GL_UNSIGNED_BYTE;
  259. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: PVRTC4 not supported. Converting to RGBA8888 instead.\n");
  260. }
  261. else
  262. {
  263. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: PVRTC4 not supported.\n");
  264. return PVR_FAIL;
  265. }
  266. }
  267. break;
  268. case OGL_A_8:
  269. eTextureFormat = eTextureInternalFormat = GL_ALPHA;
  270. eTextureType = GL_UNSIGNED_BYTE;
  271. break;
  272. case OGL_BGRA_8888:
  273. if(bIsBGRA8888Supported)
  274. {
  275. eTextureType = GL_UNSIGNED_BYTE;
  276. #ifndef __APPLE__
  277. eTextureFormat = eTextureInternalFormat = GL_BGRA;
  278. #else
  279. eTextureFormat = GL_BGRA;
  280. eTextureInternalFormat = GL_RGBA;
  281. #endif
  282. }
  283. else
  284. {
  285. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: Unable to load GL_BGRA texture as extension GL_IMG_texture_format_BGRA8888 is unsupported.\n");
  286. return PVR_FAIL;
  287. }
  288. break;
  289. case D3D_ABGR_16161616F:
  290. if(bIsFloat16Supported)
  291. {
  292. eTextureFormat = eTextureInternalFormat = GL_RGBA ;
  293. eTextureType = GL_HALF_FLOAT_OES;
  294. }
  295. break;
  296. case D3D_ABGR_32323232F:
  297. if(bIsFloat32Supported)
  298. {
  299. eTextureFormat = eTextureInternalFormat = GL_RGBA ;
  300. eTextureType = GL_FLOAT;
  301. }
  302. break;
  303. #ifndef TARGET_OS_IPHONE
  304. case ETC_RGB_4BPP:
  305. if(bIsETCSupported)
  306. {
  307. bIsCompressedFormatSupported = bIsCompressedFormat = true;
  308. eTextureFormat = GL_ETC1_RGB8_OES;
  309. }
  310. else
  311. {
  312. if(bAllowDecompress)
  313. {
  314. bIsCompressedFormatSupported = false;
  315. bIsCompressedFormat = true;
  316. eTextureFormat = GL_RGBA;
  317. eTextureType = GL_UNSIGNED_BYTE;
  318. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer warning: ETC not supported. Converting to RGBA8888 instead.\n");
  319. }
  320. else
  321. {
  322. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer error: ETC not supported.\n");
  323. return PVR_FAIL;
  324. }
  325. }
  326. break;
  327. #endif
  328. default: // NOT SUPPORTED
  329. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: pixel type not supported.\n");
  330. return PVR_FAIL;
  331. }
  332. // load the texture up
  333. glPixelStorei(GL_UNPACK_ALIGNMENT,1); // Never have row-aligned in psPVRHeaders
  334. glGenTextures(1, &textureName);
  335. // check that this data is cube map data or not.
  336. if(psPVRHeader->dwpfFlags & PVRTEX_CUBEMAP)
  337. eTarget = GL_TEXTURE_CUBE_MAP;
  338. else
  339. eTarget = GL_TEXTURE_2D;
  340. glBindTexture(eTarget, textureName);
  341. if(glGetError())
  342. {
  343. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glBindTexture() failed.\n");
  344. return PVR_FAIL;
  345. }
  346. for(unsigned int i=0; i<u32NumSurfs; i++)
  347. {
  348. char *theTexturePtr = (texPtr? (char*)texPtr : (char*)psPVRHeader + psPVRHeader->dwHeaderSize) + psPVRHeader->dwTextureDataSize * i;
  349. char *theTextureToLoad = 0;
  350. int nMIPMapLevel;
  351. int nTextureLevelsNeeded = (psPVRHeader->dwpfFlags & PVRTEX_MIPMAP)? psPVRHeader->dwMipMapCount : 0;
  352. unsigned int nSizeX= psPVRHeader->dwWidth, nSizeY = psPVRHeader->dwHeight;
  353. unsigned int CompressedImageSize = 0;
  354. for(nMIPMapLevel = 0; nMIPMapLevel <= nTextureLevelsNeeded; nSizeX=PVRT_MAX(nSizeX/2, (unsigned int)1), nSizeY=PVRT_MAX(nSizeY/2, (unsigned int)1), nMIPMapLevel++)
  355. {
  356. theTextureToLoad = theTexturePtr;
  357. // Load the Texture
  358. // If the texture is PVRTC or ETC then use GLCompressedTexImage2D
  359. if(bIsCompressedFormat)
  360. {
  361. /* Calculate how many bytes this MIP level occupies */
  362. if ((psPVRHeader->dwpfFlags & PVRTEX_PIXELTYPE)==OGL_PVRTC2)
  363. {
  364. CompressedImageSize = ( PVRT_MAX(nSizeX, PVRTC2_MIN_TEXWIDTH) * PVRT_MAX(nSizeY, PVRTC2_MIN_TEXHEIGHT) * psPVRHeader->dwBitCount) / 8;
  365. }
  366. else if ((psPVRHeader->dwpfFlags & PVRTEX_PIXELTYPE)==OGL_PVRTC4)
  367. {
  368. CompressedImageSize = ( PVRT_MAX(nSizeX, PVRTC4_MIN_TEXWIDTH) * PVRT_MAX(nSizeY, PVRTC4_MIN_TEXHEIGHT) * psPVRHeader->dwBitCount) / 8;
  369. }
  370. else
  371. {// ETC
  372. CompressedImageSize = ( PVRT_MAX(nSizeX, ETC_MIN_TEXWIDTH) * PVRT_MAX(nSizeY, ETC_MIN_TEXHEIGHT) * psPVRHeader->dwBitCount) / 8;
  373. }
  374. if(((signed int)nMIPMapLevel - (signed int)nLoadFromLevel) >= 0)
  375. {
  376. if(bIsCompressedFormatSupported)
  377. {
  378. if(psPVRHeader->dwpfFlags&PVRTEX_CUBEMAP)
  379. {
  380. /* Load compressed texture data at selected MIP level */
  381. glCompressedTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i, nMIPMapLevel-nLoadFromLevel, eTextureFormat, nSizeX, nSizeY, 0,
  382. CompressedImageSize, theTextureToLoad);
  383. }
  384. else
  385. {
  386. /* Load compressed texture data at selected MIP level */
  387. glCompressedTexImage2D(GL_TEXTURE_2D, nMIPMapLevel-nLoadFromLevel, eTextureFormat, nSizeX, nSizeY, 0,
  388. CompressedImageSize, theTextureToLoad);
  389. }
  390. }
  391. else
  392. {
  393. // Convert PVRTC to 32-bit
  394. PVRTuint8 *u8TempTexture = (PVRTuint8*)malloc(nSizeX*nSizeY*4);
  395. if ((psPVRHeader->dwpfFlags & PVRTEX_PIXELTYPE)==OGL_PVRTC2)
  396. {
  397. PVRTDecompressPVRTC(theTextureToLoad, 1, nSizeX, nSizeY, u8TempTexture);
  398. }
  399. else if((psPVRHeader->dwpfFlags & PVRTEX_PIXELTYPE)==OGL_PVRTC4)
  400. {
  401. PVRTDecompressPVRTC(theTextureToLoad, 0, nSizeX, nSizeY, u8TempTexture);
  402. }
  403. else
  404. { // ETC
  405. PVRTDecompressETC(theTextureToLoad, nSizeX, nSizeY, u8TempTexture, 0);
  406. }
  407. if(psPVRHeader->dwpfFlags&PVRTEX_CUBEMAP)
  408. {// Load compressed cubemap data at selected MIP level
  409. // Upload the texture as 32-bits
  410. glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i,nMIPMapLevel-nLoadFromLevel,GL_RGBA,
  411. nSizeX,nSizeY,0, GL_RGBA,GL_UNSIGNED_BYTE,u8TempTexture);
  412. FREE(u8TempTexture);
  413. }
  414. else
  415. {// Load compressed 2D data at selected MIP level
  416. // Upload the texture as 32-bits
  417. glTexImage2D(GL_TEXTURE_2D,nMIPMapLevel-nLoadFromLevel,GL_RGBA,
  418. nSizeX,nSizeY,0, GL_RGBA,GL_UNSIGNED_BYTE,u8TempTexture);
  419. FREE(u8TempTexture);
  420. }
  421. }
  422. }
  423. }
  424. else
  425. {
  426. if(((signed int)nMIPMapLevel - (signed int)nLoadFromLevel) >= 0)
  427. {
  428. if(psPVRHeader->dwpfFlags&PVRTEX_CUBEMAP)
  429. {
  430. /* Load uncompressed texture data at selected MIP level */
  431. glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X+i,nMIPMapLevel-nLoadFromLevel,eTextureInternalFormat,nSizeX,nSizeY,
  432. 0, eTextureFormat,eTextureType,theTextureToLoad);
  433. }
  434. else
  435. {
  436. /* Load uncompressed texture data at selected MIP level */
  437. glTexImage2D(GL_TEXTURE_2D,nMIPMapLevel-nLoadFromLevel,eTextureInternalFormat,nSizeX,nSizeY,0,eTextureFormat,eTextureType,theTextureToLoad);
  438. }
  439. }
  440. }
  441. if(glGetError())
  442. {
  443. PVRTErrorOutputDebug("PVRTTextureLoadFromPointer failed: glTexImage2D() failed.\n");
  444. return PVR_FAIL;
  445. }
  446. // offset the texture pointer by one mip-map level
  447. /* PVRTC case */
  448. if ( bIsCompressedFormat )
  449. {
  450. theTexturePtr += CompressedImageSize;
  451. }
  452. else
  453. {
  454. /* New formula that takes into account bit counts inferior to 8 (e.g. 1 bpp) */
  455. theTexturePtr += (nSizeX * nSizeY * psPVRHeader->dwBitCount + 7) / 8;
  456. }
  457. }
  458. }
  459. *texName = textureName;
  460. if(psTextureHeader)
  461. {
  462. *(PVR_Texture_Header*)psTextureHeader = *psPVRHeader;
  463. ((PVR_Texture_Header*)psTextureHeader)->dwPVR = PVRTEX_IDENTIFIER;
  464. ((PVR_Texture_Header*)psTextureHeader)->dwNumSurfs = u32NumSurfs;
  465. }
  466. if(eTextureType==GL_FLOAT || eTextureType==GL_HALF_FLOAT_OES)
  467. {
  468. if(!psPVRHeader->dwMipMapCount)
  469. { // Texture filter modes are limited to these for float textures
  470. glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  471. glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  472. }
  473. else
  474. {
  475. glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
  476. glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  477. }
  478. }
  479. else
  480. {
  481. if(!psPVRHeader->dwMipMapCount)
  482. {
  483. glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  484. glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  485. }
  486. else
  487. {
  488. glTexParameteri(eTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
  489. glTexParameteri(eTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  490. }
  491. }
  492. if(
  493. (psPVRHeader->dwWidth & (psPVRHeader->dwWidth - 1)) |
  494. (psPVRHeader->dwHeight & (psPVRHeader->dwHeight - 1)))
  495. {
  496. /*
  497. NPOT textures requires the wrap mode to be set explicitly to
  498. GL_CLAMP_TO_EDGE or the texture will be inconsistent.
  499. */
  500. glTexParameteri(eTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  501. glTexParameteri(eTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
  502. }
  503. else
  504. {
  505. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
  506. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
  507. }
  508. return PVR_SUCCESS;
  509. }
  510. /*!***************************************************************************
  511. @Function PVRTTextureLoadFromPVR
  512. @Input filename Filename of the .PVR file to load the texture from
  513. @Modified texName the OpenGL ES texture name as returned by glBindTexture
  514. @Modified psTextureHeader Pointer to a PVR_Texture_Header struct. Modified to
  515. contain the header data of the returned texture Ignored if NULL.
  516. @Input bAllowDecompress Allow decompression if PVRTC is not supported in hardware.
  517. @Input nLoadFromLevel Which mipmap level to start loading from (0=all)
  518. @Return PVR_SUCCESS on success
  519. @Description Allows textures to be stored in binary PVR files and loaded in. Can load parts of a
  520. mipmaped texture (ie skipping the highest detailed levels).
  521. Sets the texture MIN/MAG filter to GL_LINEAR_MIPMAP_NEAREST/GL_LINEAR
  522. if mipmaps are present, GL_LINEAR/GL_LINEAR otherwise.
  523. *****************************************************************************/
  524. EPVRTError PVRTTextureLoadFromPVR( const char * const filename,
  525. GLuint * const texName,
  526. const void *psTextureHeader,
  527. bool bAllowDecompress,
  528. const unsigned int nLoadFromLevel)
  529. {
  530. CPVRTResourceFile TexFile(filename);
  531. if (!TexFile.IsOpen()) return PVR_FAIL;
  532. return PVRTTextureLoadFromPointer( TexFile.DataPtr(),
  533. texName,
  534. psTextureHeader,
  535. bAllowDecompress,
  536. nLoadFromLevel);
  537. }
  538. /*!***************************************************************************
  539. @Function PVRTTextureFormatGetBPP
  540. @Input nFormat
  541. @Input nType
  542. @Description Returns the bits per pixel (BPP) of the format.
  543. *****************************************************************************/
  544. unsigned int PVRTTextureFormatGetBPP(const GLuint nFormat, const GLuint nType)
  545. {
  546. switch(nFormat)
  547. {
  548. case GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG:
  549. case GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG:
  550. return 2;
  551. case GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG:
  552. case GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG:
  553. return 4;
  554. case GL_UNSIGNED_BYTE:
  555. switch(nType)
  556. {
  557. case GL_RGBA:
  558. return 32;
  559. }
  560. case GL_UNSIGNED_SHORT_5_5_5_1:
  561. switch(nType)
  562. {
  563. case GL_RGBA:
  564. return 16;
  565. }
  566. }
  567. return 0xFFFFFFFF;
  568. }
  569. /*****************************************************************************
  570. End of file (PVRTTextureAPI.cpp)
  571. *****************************************************************************/