#include "DDSreader.h"

/*
PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB=NULL;

void init_DDS_ARB(void)
{
	 glCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)wglGetProcAddress("glCompressedTexImage2DARB");
}
*/

bool DDSreader::readDDSfile(const string& path, DDSdata& dstData)
{
    DDSURFACEDESC2 ddsd;
    char filecode[4];
    FILE *pFile;
    int factor;
    int bufferSize;

    // Open the file
	pFile = fopen( path.c_str(), "rb" );

    if( pFile == NULL )
    {
		assert(!" Couldnt load the DDS file");
		return false;
    }

    // Verify the file is a true .dds file
    fread( filecode, 1, 4, pFile );

    if( strncmp( filecode, "DDS ", 4 ) != 0 )
    {
		assert(!" Couldnt load the DDS file...it doesnt look like DDS file");
		return false;
    }

    // Get the surface descriptor
    fread( &ddsd, sizeof(ddsd), 1, pFile );

   

    memset( &dstData, 0, sizeof(DDSdata) );

    //
    // This .dds loader supports the loading of compressed formats DXT1, DXT3 
    // and DXT5.
    //

    switch( ddsd.ddpfPixelFormat.dwFourCC )
    {
        case FOURCC_DXT1:
            // DXT1's compression ratio is 8:1
            dstData.format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
            factor = 2;
            break;

        case FOURCC_DXT3:
            // DXT3's compression ratio is 4:1
            dstData.format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
            factor = 4;
            break;

        case FOURCC_DXT5:
            // DXT5's compression ratio is 4:1
            dstData.format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
            factor = 4;
            break;

        default:
			assert(!" The DDS file is not compressed with any of: DXT1, DXT3, DXT5 (others not supported!) " );
            return false;
    }

    //
    // How big will the buffer need to be to load all of the pixel data 
    // including mip-maps?
    //

    if( ddsd.dwLinearSize == 0 )
    {
		assert(! "dwLinearSize is 0!");

		return false;
    }

    if( ddsd.dwMipMapCount > 1 )
	{
        bufferSize = ddsd.dwLinearSize * factor;
	}
    else
	{
        bufferSize = ddsd.dwLinearSize;
	}


	dstData.pixels.resize(bufferSize);
    fread( &dstData.pixels[0], 1, bufferSize, pFile );

    // Close the file
    fclose( pFile );

    dstData.width      = ddsd.dwWidth;
    dstData.height     = ddsd.dwHeight;
    dstData.numMipMaps = ddsd.dwMipMapCount;

    if( ddsd.ddpfPixelFormat.dwFourCC == FOURCC_DXT1 )
	{
        dstData.components = 3;
	}
    else
	{
        dstData.components = 4;
	}

    return true;
}

unsigned int DDSreader::loadDDSfile(DDSdata& srcData, GLint interpolation)
{
	    // NOTE: Unlike "lena.bmp", "lena.dds" actually contains its own mip-map 
    // levels, which are also compressed.
	unsigned int textureId;

    int nHeight     = srcData.height;
    int nWidth      = srcData.width;
    int nNumMipMaps = srcData.numMipMaps;

    int nBlockSize;

    if( srcData.format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT )
	{
        nBlockSize = 8;
	}
    else
	{
        nBlockSize = 16;
	}

    glGenTextures( 1, &textureId );
    glBindTexture( GL_TEXTURE_2D, textureId );

    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, interpolation );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, interpolation );

    int nSize;
    int nOffset = 0;

    // Load the mip-map levels

    for( int i = 0; i < nNumMipMaps; ++i )
    {
        if( nWidth  == 0 ) nWidth  = 1;
        if( nHeight == 0 ) nHeight = 1;

        nSize = ((nWidth+3)/4) * ((nHeight+3)/4) * nBlockSize;

        glCompressedTexImage2DARB( GL_TEXTURE_2D, i, srcData.format, nWidth, nHeight, 0, nSize, &srcData.pixels[nOffset] );

        nOffset += nSize;

        // Half the image size for the next mip-map level...
        nWidth  = (nWidth  / 2);
        nHeight = (nHeight / 2);
    }
   
	return textureId;
}