From 0ce03af6e877adebeda12787e249871c1fca43f2 Mon Sep 17 00:00:00 2001
From: pixel <pixel>
Date: Tue, 17 Jul 2007 03:26:32 +0000
Subject: Adding DDS support.

---
 lib/dds.c | 298 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 298 insertions(+)
 create mode 100644 lib/dds.c

(limited to 'lib')

diff --git a/lib/dds.c b/lib/dds.c
new file mode 100644
index 0000000..82684d5
--- /dev/null
+++ b/lib/dds.c
@@ -0,0 +1,298 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <inttypes.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glext.h> // Your local header file
+
+PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
+
+#define MAKEFOURCC(ch0, ch1, ch2, ch3)  \
+    ((uint32_t)(uint8_t)(ch0) | ((uint32_t)(uint8_t)(ch1) << 8) |  \
+    ((uint32_t)(uint8_t)(ch2) << 16) | ((uint32_t)(uint8_t)(ch3) << 24 ))
+
+typedef enum _D3DFORMAT {
+    D3DFMT_DXT1                 =  MAKEFOURCC('D', 'X', 'T', '1'),
+    D3DFMT_DXT2                 =  MAKEFOURCC('D', 'X', 'T', '2'),
+    D3DFMT_DXT3                 =  MAKEFOURCC('D', 'X', 'T', '3'),
+    D3DFMT_DXT4                 =  MAKEFOURCC('D', 'X', 'T', '4'),
+    D3DFMT_DXT5                 =  MAKEFOURCC('D', 'X', 'T', '5'),
+} D3DFORMAT;
+
+typedef struct _DDCOLORKEY
+{
+        uint32_t   dwColorSpaceLowValue;/* low boundary of color space that is to
+                                      * be treated as Color Key, inclusive
+                                      */
+        uint32_t   dwColorSpaceHighValue;/* high boundary of color space that is
+                                       * to be treated as Color Key, inclusive
+                                       */
+} DDCOLORKEY,*LPDDCOLORKEY;
+
+typedef struct _DDPIXELFORMAT {
+    uint32_t       dwSize;                 /* 0: size of structure */
+    uint32_t       dwFlags;                /* 4: pixel format flags */
+    uint32_t       dwFourCC;               /* 8: (FOURCC code) */
+    union {
+        uint32_t   dwRGBBitCount;          /* C: how many bits per pixel */
+        uint32_t   dwYUVBitCount;          /* C: how many bits per pixel */
+        uint32_t   dwZBufferBitDepth;      /* C: how many bits for z buffers */
+        uint32_t   dwAlphaBitDepth;        /* C: how many bits for alpha channels*/
+        uint32_t   dwLuminanceBitCount;
+        uint32_t   dwBumpBitCount;
+    } DUMMYUNIONNAME1;
+    union {
+        uint32_t   dwRBitMask;             /* 10: mask for red bit*/
+        uint32_t   dwYBitMask;             /* 10: mask for Y bits*/
+        uint32_t   dwStencilBitDepth;
+        uint32_t   dwLuminanceBitMask;
+        uint32_t   dwBumpDuBitMask;
+    } DUMMYUNIONNAME2;
+    union {
+        uint32_t   dwGBitMask;             /* 14: mask for green bits*/
+        uint32_t   dwUBitMask;             /* 14: mask for U bits*/
+        uint32_t   dwZBitMask;
+        uint32_t   dwBumpDvBitMask;
+    } DUMMYUNIONNAME3;
+    union {
+        uint32_t   dwBBitMask;             /* 18: mask for blue bits*/
+        uint32_t   dwVBitMask;             /* 18: mask for V bits*/
+        uint32_t   dwStencilBitMask;
+        uint32_t   dwBumpLuminanceBitMask;
+    } DUMMYUNIONNAME4;
+    union {
+        uint32_t   dwRGBAlphaBitMask;      /* 1C: mask for alpha channel */
+        uint32_t   dwYUVAlphaBitMask;      /* 1C: mask for alpha channel */
+        uint32_t   dwLuminanceAlphaBitMask;
+        uint32_t   dwRGBZBitMask;          /* 1C: mask for Z channel */
+        uint32_t   dwYUVZBitMask;          /* 1C: mask for Z channel */
+    } DUMMYUNIONNAME5;
+                                        /* 20: next structure */
+} DDPIXELFORMAT,*LPDDPIXELFORMAT;
+
+typedef struct _DDSCAPS2 {
+        uint32_t   dwCaps; /* capabilities of surface wanted */
+        uint32_t   dwCaps2; /* additional capabilities */
+        uint32_t   dwCaps3; /* reserved capabilities */
+        uint32_t   dwCaps4; /* more reserved capabilities */
+} DDSCAPS2,*LPDDSCAPS2;
+
+typedef struct _DDSURFACEDESC2
+{
+        uint32_t   dwSize;         /* 0: size of the DDSURFACEDESC2 structure*/
+        uint32_t   dwFlags;        /* 4: determines what fields are valid*/
+        uint32_t   dwHeight;       /* 8: height of surface to be created*/
+        uint32_t   dwWidth;        /* C: width of input surface*/
+        union {
+                uint32_t   lPitch;       /*10: distance to start of next line (return value only)*/
+                uint32_t   dwLinearSize; /*10: formless late-allocated optimized surface size */
+        } x;
+        uint32_t   dwBackBufferCount;/* 14: number of back buffers requested*/
+        union {
+                uint32_t   dwMipMapCount;/* 18:number of mip-map levels requested*/
+                uint32_t   dwRefreshRate;/* 18:refresh rate (used when display mode is described)*/
+                uint32_t   dwSrcVBHandle;/* 18:source used in VB::Optimize */
+        } y;
+        uint32_t   dwAlphaBitDepth;/* 1C:depth of alpha buffer requested*/
+        uint32_t   dwReserved;     /* 20:reserved*/
+        void *     lpSurface;      /* 24:pointer to the associated surface memory*/
+        union {
+                DDCOLORKEY      ddckCKDestOverlay; /* 28: CK for dest overlay use*/
+                uint32_t           dwEmptyFaceColor;  /* 28: color for empty cubemap faces */
+        } z;
+        DDCOLORKEY      ddckCKDestBlt;  /* 30: CK for destination blt use*/
+        DDCOLORKEY      ddckCKSrcOverlay;/* 38: CK for source overlay use*/
+        DDCOLORKEY      ddckCKSrcBlt;   /* 40: CK for source blt use*/
+
+        union {
+                DDPIXELFORMAT   ddpfPixelFormat;/* 48: pixel format description of the surface*/
+                uint32_t           dwFVF;  /* 48: vertex format description of vertex buffers */
+        } t;
+        DDSCAPS2        ddsCaps;  /* 68: DDraw surface caps */
+        uint32_t           dwTextureStage; /* 78: stage in multitexture cascade */
+} DDSURFACEDESC2,*LPDDSURFACEDESC2;
+
+typedef struct
+{
+    GLsizei  width;
+    GLsizei  height;
+    GLint    components;
+    GLenum   format;
+    int      numMipMaps;
+    GLubyte *pixels;
+} DDS_IMAGE_DATA;
+
+static DDS_IMAGE_DATA* loadDDSTextureFile( const char *filename )
+{
+    DDS_IMAGE_DATA *pDDSImageData;
+    DDSURFACEDESC2 ddsd;
+    char filecode[4];
+    FILE *pFile;
+    int factor;
+    int bufferSize;
+
+    // Open the file
+    pFile = fopen( filename, "rb" );
+
+    if( pFile == NULL )
+    {
+        char str[255];
+        sprintf( str, "loadDDSTextureFile couldn't find, or failed to load \"%s\"", filename );
+//        MessageBox( NULL, str, "ERROR", MB_OK|MB_ICONEXCLAMATION );
+        return NULL;
+    }
+
+    // Verify the file is a true .dds file
+    fread( filecode, 1, 4, pFile );
+
+    if( strncmp( filecode, "DDS ", 4 ) != 0 )
+    {
+        char str[255];
+        sprintf( str, "The file \"%s\" doesn't appear to be a valid .dds file!", filename );
+//        MessageBox( NULL, str, "ERROR", MB_OK|MB_ICONEXCLAMATION );
+        fclose( pFile );
+        return NULL;
+    }
+
+    // Get the surface descriptor
+    fread( &ddsd, sizeof(ddsd), 1, pFile );
+
+    pDDSImageData = (DDS_IMAGE_DATA*) malloc(sizeof(DDS_IMAGE_DATA));
+
+    memset( pDDSImageData, 0, sizeof(DDS_IMAGE_DATA) );
+
+    //
+    // This .dds loader supports the loading of compressed formats DXT1, DXT3
+    // and DXT5.
+    //
+
+    switch( ddsd.t.ddpfPixelFormat.dwFourCC )
+    {
+        case D3DFMT_DXT1:
+            // DXT1's compression ratio is 8:1
+            pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
+            factor = 2;
+            break;
+
+        case D3DFMT_DXT3:
+            // DXT3's compression ratio is 4:1
+            pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT;
+            factor = 4;
+            break;
+
+        case D3DFMT_DXT5:
+            // DXT5's compression ratio is 4:1
+            pDDSImageData->format = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
+            factor = 4;
+            break;
+
+        default: {
+            char str[255];
+            sprintf( str, "The file \"%s\" doesn't appear to be compressed "
+                "using DXT1, DXT3, or DXT5!", filename );
+//            MessageBox( NULL, str, "ERROR", MB_OK|MB_ICONEXCLAMATION );
+            return NULL;
+	}
+    }
+
+    //
+    // How big will the buffer need to be to load all of the pixel data
+    // including mip-maps?
+    //
+
+    if( ddsd.x.dwLinearSize == 0 )
+    {
+//        MessageBox( NULL, "dwLinearSize is 0!","ERROR",
+//            MB_OK|MB_ICONEXCLAMATION);
+	return NULL;
+    }
+
+    if( ddsd.y.dwMipMapCount > 1 )
+        bufferSize = ddsd.x.dwLinearSize * factor;
+    else
+        bufferSize = ddsd.x.dwLinearSize;
+
+    pDDSImageData->pixels = (unsigned char*)malloc(bufferSize * sizeof(unsigned char));
+
+    fread( pDDSImageData->pixels, 1, bufferSize, pFile );
+
+    // Close the file
+    fclose( pFile );
+
+    pDDSImageData->width      = ddsd.dwWidth;
+    pDDSImageData->height     = ddsd.dwHeight;
+    pDDSImageData->numMipMaps = ddsd.y.dwMipMapCount;
+
+    if( ddsd.t.ddpfPixelFormat.dwFourCC == D3DFMT_DXT1 )
+        pDDSImageData->components = 3;
+    else
+        pDDSImageData->components = 4;
+
+    return pDDSImageData;
+}
+
+int loadCompressedTexture( const char *fname )
+{
+    int g_compressedTextureID;
+    DDS_IMAGE_DATA *pDDSImageData = loadDDSTextureFile( fname );
+
+    if( pDDSImageData != NULL )
+    {
+        int nHeight     = pDDSImageData->height;
+        int nWidth      = pDDSImageData->width;
+        int nNumMipMaps = pDDSImageData->numMipMaps;
+
+        int nBlockSize;
+
+        if( pDDSImageData->format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT )
+            nBlockSize = 8;
+        else
+            nBlockSize = 16;
+
+        glGenTextures( 1, &g_compressedTextureID );
+        glBindTexture( GL_TEXTURE_2D, g_compressedTextureID );
+
+        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
+        glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
+
+        int nSize;
+        int nOffset = 0;
+	int i;
+
+        // Load the mip-map levels
+
+        for( 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,
+                                       pDDSImageData->format,
+                                       nWidth,
+                                       nHeight,
+                                       0,
+                                       nSize,
+                                       pDDSImageData->pixels + nOffset );
+
+            nOffset += nSize;
+
+            // Half the image size for the next mip-map level...
+            nWidth  = (nWidth  / 2);
+            nHeight = (nHeight / 2);
+        }
+    }
+
+    if( pDDSImageData != NULL )
+    {
+        if( pDDSImageData->pixels != NULL )
+            free( pDDSImageData->pixels );
+
+        free( pDDSImageData );
+    }
+
+    return g_compressedTextureID;
+}
-- 
cgit v1.2.3