#include "PreCompile.h"
#include "ImagePVR.h"
#include "CommonBuffer.h"
#include "PVRHeader.h"
ImagePVR::ImagePVR()
{
}
ImagePVR::~ImagePVR()
{
}
void ImagePVR::Load(const string& fileName)
{
m_name = fileName;
PVRHeader pvrHeader;
FILE* pFile = pvrHeader.LoadHeader(fileName);
GLenum textureFormat = 0;
switch(pvrHeader.m_pfFlags & PVRTEX_PIXELTYPE)
{
case OGL_PVRTC2:
textureFormat = pvrHeader.m_alphaBitMask==0 ?
GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG : GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG ; // PVRTC2
break;
case OGL_PVRTC4:
textureFormat = pvrHeader.m_alphaBitMask==0 ?
GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG : GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG ; // PVRTC4
break;
default: // NOT SUPPORTED
fclose(pFile);
throw RacException("pixel type not supported.\n",
(pvrHeader.m_pfFlags & PVRTEX_PIXELTYPE));
}
Allocator<char> &bufferOut = g_commonBuffer.GetBufferOut();
bufferOut.Init(pvrHeader.m_textureDataSize);
int bytesRead = (int)fread(bufferOut.GetCache(), 1, pvrHeader.m_textureDataSize, pFile);
fclose(pFile);
if (bytesRead != pvrHeader.m_textureDataSize)
{
throw RacException("can't read compressed texture from file ", fileName);
}
// load the texture up
glPixelStorei(GL_UNPACK_ALIGNMENT,1); // Never have row-aligned in psPVRHeaders
glEnable(GL_TEXTURE_2D); // use texturing
glGenTextures(1, &m_textureID);
glBindTexture(GL_TEXTURE_2D, m_textureID);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
if (glGetError())
{
throw RacException("glBindTexture() failed for ", fileName);
}
// only do first mip level
int mipMapLevel = 0;
int mipMapLevels = (pvrHeader.m_pfFlags & PVRTEX_MIPMAP) ? pvrHeader.m_mipMapCount : 0;
int compressedImageSize = 0;
char* pLevelData = bufferOut.GetCache();
int minSize = 0;
if ((pvrHeader.m_pfFlags & PVRTEX_PIXELTYPE)==OGL_PVRTC2)
{
minSize = (PVRTC2_MIN_TEXWIDTH * PVRTC2_MIN_TEXHEIGHT* pvrHeader.m_bitCount + 7) / 8;
}
else
{// PVRTC4 case
minSize = (PVRTC4_MIN_TEXWIDTH * PVRTC4_MIN_TEXHEIGHT* pvrHeader.m_bitCount + 7) / 8;
}
// width and height are the same
m_width = pvrHeader.m_width;
m_height = pvrHeader.m_height;
int levelWidth = m_width;
const int divider[] = { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024 };
for (mipMapLevel = 0; mipMapLevel <= mipMapLevels; mipMapLevel++)
{
/* If the texture is PVRTC then use GLCompressedTexImage2D */
/* Calculate how many bytes this MIP level occupies */
levelWidth = m_width/divider[mipMapLevel];
compressedImageSize = (levelWidth * levelWidth * pvrHeader.m_bitCount + 7) / 8;
if (compressedImageSize < minSize)
compressedImageSize = minSize;
/* Load compressed texture data at selected MIP level */
glCompressedTexImage2D(GL_TEXTURE_2D, mipMapLevel, textureFormat, levelWidth, levelWidth, 0,
compressedImageSize, pLevelData);
if (glGetError())
{
throw RacException("glCompressedTexImage2D() failed.", fileName);
}
pLevelData += compressedImageSize;
}
if (pvrHeader.m_mipMapCount == 0)
{
m_minFilter = GL_LINEAR;
}
else
{
m_minFilter = GL_LINEAR_MIPMAP_NEAREST;
// m_minFilter = GL_NEAREST_MIPMAP_NEAREST;
}
}