Blender V2.61 - r43446

DirectDrawSurface.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * Contributors: Amorilia (amorilia@users.sourceforge.net)
00019  *
00020  * ***** END GPL LICENSE BLOCK *****
00021  */
00022 
00028 /*
00029  * This file is based on a similar file from the NVIDIA texture tools
00030  * (http://nvidia-texture-tools.googlecode.com/)
00031  *
00032  * Original license from NVIDIA follows.
00033  */
00034 
00035 // Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
00036 // 
00037 // Permission is hereby granted, free of charge, to any person
00038 // obtaining a copy of this software and associated documentation
00039 // files (the "Software"), to deal in the Software without
00040 // restriction, including without limitation the rights to use,
00041 // copy, modify, merge, publish, distribute, sublicense, and/or sell
00042 // copies of the Software, and to permit persons to whom the
00043 // Software is furnished to do so, subject to the following
00044 // conditions:
00045 // 
00046 // The above copyright notice and this permission notice shall be
00047 // included in all copies or substantial portions of the Software.
00048 // 
00049 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00050 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
00051 // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00052 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
00053 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
00054 // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00055 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
00056 // OTHER DEALINGS IN THE SOFTWARE.
00057 
00058 #include <DirectDrawSurface.h>
00059 #include <BlockDXT.h>
00060 #include <PixelFormat.h>
00061 
00062 #include <stdio.h> // printf
00063 #include <math.h>  // sqrt
00064 #include <sys/types.h>
00065 
00066 /*** declarations ***/
00067 
00068 #if !defined(MAKEFOURCC)
00069 #   define MAKEFOURCC(ch0, ch1, ch2, ch3) \
00070     (uint(uint8(ch0)) | (uint(uint8(ch1)) << 8) | \
00071     (uint(uint8(ch2)) << 16) | (uint(uint8(ch3)) << 24 ))
00072 #endif
00073 
00074 static const uint FOURCC_NVTT = MAKEFOURCC('N', 'V', 'T', 'T');
00075 static const uint FOURCC_DDS = MAKEFOURCC('D', 'D', 'S', ' ');
00076 static const uint FOURCC_DXT1 = MAKEFOURCC('D', 'X', 'T', '1');
00077 static const uint FOURCC_DXT2 = MAKEFOURCC('D', 'X', 'T', '2');
00078 static const uint FOURCC_DXT3 = MAKEFOURCC('D', 'X', 'T', '3');
00079 static const uint FOURCC_DXT4 = MAKEFOURCC('D', 'X', 'T', '4');
00080 static const uint FOURCC_DXT5 = MAKEFOURCC('D', 'X', 'T', '5');
00081 static const uint FOURCC_RXGB = MAKEFOURCC('R', 'X', 'G', 'B');
00082 static const uint FOURCC_ATI1 = MAKEFOURCC('A', 'T', 'I', '1');
00083 static const uint FOURCC_ATI2 = MAKEFOURCC('A', 'T', 'I', '2');
00084 
00085 static const uint FOURCC_A2XY = MAKEFOURCC('A', '2', 'X', 'Y');
00086     
00087 static const uint FOURCC_DX10 = MAKEFOURCC('D', 'X', '1', '0');
00088 
00089 static const uint FOURCC_UVER = MAKEFOURCC('U', 'V', 'E', 'R');
00090 
00091 // 32 bit RGB formats.
00092 static const uint D3DFMT_R8G8B8 = 20;
00093 static const uint D3DFMT_A8R8G8B8 = 21;
00094 static const uint D3DFMT_X8R8G8B8 = 22;
00095 static const uint D3DFMT_R5G6B5 = 23;
00096 static const uint D3DFMT_X1R5G5B5 = 24;
00097 static const uint D3DFMT_A1R5G5B5 = 25;
00098 static const uint D3DFMT_A4R4G4B4 = 26;
00099 static const uint D3DFMT_R3G3B2 = 27;
00100 static const uint D3DFMT_A8 = 28;
00101 static const uint D3DFMT_A8R3G3B2 = 29;
00102 static const uint D3DFMT_X4R4G4B4 = 30;
00103 static const uint D3DFMT_A2B10G10R10 = 31;
00104 static const uint D3DFMT_A8B8G8R8 = 32;
00105 static const uint D3DFMT_X8B8G8R8 = 33;
00106 static const uint D3DFMT_G16R16 = 34;
00107 static const uint D3DFMT_A2R10G10B10 = 35;
00108 
00109 static const uint D3DFMT_A16B16G16R16 = 36;
00110 
00111 // Palette formats.
00112 static const uint D3DFMT_A8P8 = 40;
00113 static const uint D3DFMT_P8 = 41;
00114     
00115 // Luminance formats.
00116 static const uint D3DFMT_L8 = 50;
00117 static const uint D3DFMT_A8L8 = 51;
00118 static const uint D3DFMT_A4L4 = 52;
00119 static const uint D3DFMT_L16 = 81;
00120 
00121 // Floating point formats
00122 static const uint D3DFMT_R16F = 111;
00123 static const uint D3DFMT_G16R16F = 112;
00124 static const uint D3DFMT_A16B16G16R16F = 113;
00125 static const uint D3DFMT_R32F = 114;
00126 static const uint D3DFMT_G32R32F = 115;
00127 static const uint D3DFMT_A32B32G32R32F = 116;
00128     
00129 static const uint DDSD_CAPS = 0x00000001U;
00130 static const uint DDSD_PIXELFORMAT = 0x00001000U;
00131 static const uint DDSD_WIDTH = 0x00000004U;
00132 static const uint DDSD_HEIGHT = 0x00000002U;
00133 static const uint DDSD_PITCH = 0x00000008U;
00134 static const uint DDSD_MIPMAPCOUNT = 0x00020000U;
00135 static const uint DDSD_LINEARSIZE = 0x00080000U;
00136 static const uint DDSD_DEPTH = 0x00800000U;
00137     
00138 static const uint DDSCAPS_COMPLEX = 0x00000008U;
00139 static const uint DDSCAPS_TEXTURE = 0x00001000U;
00140 static const uint DDSCAPS_MIPMAP = 0x00400000U;
00141 static const uint DDSCAPS2_VOLUME = 0x00200000U;
00142 static const uint DDSCAPS2_CUBEMAP = 0x00000200U;
00143 
00144 static const uint DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400U;
00145 static const uint DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800U;
00146 static const uint DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000U;
00147 static const uint DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000U;
00148 static const uint DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000U;
00149 static const uint DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000U;
00150 static const uint DDSCAPS2_CUBEMAP_ALL_FACES = 0x0000FC00U;
00151 
00152 static const uint DDPF_ALPHAPIXELS = 0x00000001U;
00153 static const uint DDPF_ALPHA = 0x00000002U;
00154 static const uint DDPF_FOURCC = 0x00000004U;
00155 static const uint DDPF_RGB = 0x00000040U;
00156 static const uint DDPF_PALETTEINDEXED1 = 0x00000800U;
00157 static const uint DDPF_PALETTEINDEXED2 = 0x00001000U;
00158 static const uint DDPF_PALETTEINDEXED4 = 0x00000008U;
00159 static const uint DDPF_PALETTEINDEXED8 = 0x00000020U;
00160 static const uint DDPF_LUMINANCE = 0x00020000U;
00161 static const uint DDPF_ALPHAPREMULT = 0x00008000U;
00162 
00163 // Custom NVTT flags.
00164 static const uint DDPF_NORMAL = 0x80000000U;  
00165 static const uint DDPF_SRGB = 0x40000000U;
00166 
00167     // DX10 formats.
00168     enum DXGI_FORMAT
00169     {
00170         DXGI_FORMAT_UNKNOWN = 0,
00171         
00172         DXGI_FORMAT_R32G32B32A32_TYPELESS = 1,
00173         DXGI_FORMAT_R32G32B32A32_FLOAT = 2,
00174         DXGI_FORMAT_R32G32B32A32_UINT = 3,
00175         DXGI_FORMAT_R32G32B32A32_SINT = 4,
00176         
00177         DXGI_FORMAT_R32G32B32_TYPELESS = 5,
00178         DXGI_FORMAT_R32G32B32_FLOAT = 6,
00179         DXGI_FORMAT_R32G32B32_UINT = 7,
00180         DXGI_FORMAT_R32G32B32_SINT = 8,
00181         
00182         DXGI_FORMAT_R16G16B16A16_TYPELESS = 9,
00183         DXGI_FORMAT_R16G16B16A16_FLOAT = 10,
00184         DXGI_FORMAT_R16G16B16A16_UNORM = 11,
00185         DXGI_FORMAT_R16G16B16A16_UINT = 12,
00186         DXGI_FORMAT_R16G16B16A16_SNORM = 13,
00187         DXGI_FORMAT_R16G16B16A16_SINT = 14,
00188         
00189         DXGI_FORMAT_R32G32_TYPELESS = 15,
00190         DXGI_FORMAT_R32G32_FLOAT = 16,
00191         DXGI_FORMAT_R32G32_UINT = 17,
00192         DXGI_FORMAT_R32G32_SINT = 18,
00193         
00194         DXGI_FORMAT_R32G8X24_TYPELESS = 19,
00195         DXGI_FORMAT_D32_FLOAT_S8X24_UINT = 20,
00196         DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS = 21,
00197         DXGI_FORMAT_X32_TYPELESS_G8X24_UINT = 22,
00198         
00199         DXGI_FORMAT_R10G10B10A2_TYPELESS = 23,
00200         DXGI_FORMAT_R10G10B10A2_UNORM = 24,
00201         DXGI_FORMAT_R10G10B10A2_UINT = 25,
00202         
00203         DXGI_FORMAT_R11G11B10_FLOAT = 26,
00204         
00205         DXGI_FORMAT_R8G8B8A8_TYPELESS = 27,
00206         DXGI_FORMAT_R8G8B8A8_UNORM = 28,
00207         DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29,
00208         DXGI_FORMAT_R8G8B8A8_UINT = 30,
00209         DXGI_FORMAT_R8G8B8A8_SNORM = 31,
00210         DXGI_FORMAT_R8G8B8A8_SINT = 32,
00211         
00212         DXGI_FORMAT_R16G16_TYPELESS = 33,
00213         DXGI_FORMAT_R16G16_FLOAT = 34,
00214         DXGI_FORMAT_R16G16_UNORM = 35,
00215         DXGI_FORMAT_R16G16_UINT = 36,
00216         DXGI_FORMAT_R16G16_SNORM = 37,
00217         DXGI_FORMAT_R16G16_SINT = 38,
00218         
00219         DXGI_FORMAT_R32_TYPELESS = 39,
00220         DXGI_FORMAT_D32_FLOAT = 40,
00221         DXGI_FORMAT_R32_FLOAT = 41,
00222         DXGI_FORMAT_R32_UINT = 42,
00223         DXGI_FORMAT_R32_SINT = 43,
00224         
00225         DXGI_FORMAT_R24G8_TYPELESS = 44,
00226         DXGI_FORMAT_D24_UNORM_S8_UINT = 45,
00227         DXGI_FORMAT_R24_UNORM_X8_TYPELESS = 46,
00228         DXGI_FORMAT_X24_TYPELESS_G8_UINT = 47,
00229         
00230         DXGI_FORMAT_R8G8_TYPELESS = 48,
00231         DXGI_FORMAT_R8G8_UNORM = 49,
00232         DXGI_FORMAT_R8G8_UINT = 50,
00233         DXGI_FORMAT_R8G8_SNORM = 51,
00234         DXGI_FORMAT_R8G8_SINT = 52,
00235         
00236         DXGI_FORMAT_R16_TYPELESS = 53,
00237         DXGI_FORMAT_R16_FLOAT = 54,
00238         DXGI_FORMAT_D16_UNORM = 55,
00239         DXGI_FORMAT_R16_UNORM = 56,
00240         DXGI_FORMAT_R16_UINT = 57,
00241         DXGI_FORMAT_R16_SNORM = 58,
00242         DXGI_FORMAT_R16_SINT = 59,
00243         
00244         DXGI_FORMAT_R8_TYPELESS = 60,
00245         DXGI_FORMAT_R8_UNORM = 61,
00246         DXGI_FORMAT_R8_UINT = 62,
00247         DXGI_FORMAT_R8_SNORM = 63,
00248         DXGI_FORMAT_R8_SINT = 64,
00249         DXGI_FORMAT_A8_UNORM = 65,
00250         
00251         DXGI_FORMAT_R1_UNORM = 66,
00252         
00253         DXGI_FORMAT_R9G9B9E5_SHAREDEXP = 67,
00254         
00255         DXGI_FORMAT_R8G8_B8G8_UNORM = 68,
00256         DXGI_FORMAT_G8R8_G8B8_UNORM = 69,
00257         
00258         DXGI_FORMAT_BC1_TYPELESS = 70,
00259         DXGI_FORMAT_BC1_UNORM = 71,
00260         DXGI_FORMAT_BC1_UNORM_SRGB = 72,
00261         
00262         DXGI_FORMAT_BC2_TYPELESS = 73,
00263         DXGI_FORMAT_BC2_UNORM = 74,
00264         DXGI_FORMAT_BC2_UNORM_SRGB = 75,
00265         
00266         DXGI_FORMAT_BC3_TYPELESS = 76,
00267         DXGI_FORMAT_BC3_UNORM = 77,
00268         DXGI_FORMAT_BC3_UNORM_SRGB = 78,
00269         
00270         DXGI_FORMAT_BC4_TYPELESS = 79,
00271         DXGI_FORMAT_BC4_UNORM = 80,
00272         DXGI_FORMAT_BC4_SNORM = 81,
00273         
00274         DXGI_FORMAT_BC5_TYPELESS = 82,
00275         DXGI_FORMAT_BC5_UNORM = 83,
00276         DXGI_FORMAT_BC5_SNORM = 84,
00277         
00278         DXGI_FORMAT_B5G6R5_UNORM = 85,
00279         DXGI_FORMAT_B5G5R5A1_UNORM = 86,
00280         DXGI_FORMAT_B8G8R8A8_UNORM = 87,
00281         DXGI_FORMAT_B8G8R8X8_UNORM = 88,
00282 
00283         DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM = 89,
00284         DXGI_FORMAT_B8G8R8A8_TYPELESS = 90,
00285         DXGI_FORMAT_B8G8R8A8_UNORM_SRGB = 91,
00286         DXGI_FORMAT_B8G8R8X8_TYPELESS = 92,
00287         DXGI_FORMAT_B8G8R8X8_UNORM_SRGB = 93,
00288 
00289         DXGI_FORMAT_BC6H_TYPELESS = 94,
00290         DXGI_FORMAT_BC6H_UF16 = 95,
00291         DXGI_FORMAT_BC6H_SF16 = 96,
00292 
00293         DXGI_FORMAT_BC7_TYPELESS = 97,
00294         DXGI_FORMAT_BC7_UNORM = 98,
00295         DXGI_FORMAT_BC7_UNORM_SRGB = 99,
00296     };
00297 
00298     enum D3D10_RESOURCE_DIMENSION
00299     {
00300         D3D10_RESOURCE_DIMENSION_UNKNOWN = 0,
00301         D3D10_RESOURCE_DIMENSION_BUFFER = 1,
00302         D3D10_RESOURCE_DIMENSION_TEXTURE1D = 2,
00303         D3D10_RESOURCE_DIMENSION_TEXTURE2D = 3,
00304         D3D10_RESOURCE_DIMENSION_TEXTURE3D = 4,
00305     };
00306 
00307 
00308     const char * getDxgiFormatString(DXGI_FORMAT dxgiFormat)
00309     {
00310 #define CASE(format) case DXGI_FORMAT_##format: return #format
00311         switch(dxgiFormat)
00312         {
00313             CASE(UNKNOWN);
00314             
00315             CASE(R32G32B32A32_TYPELESS);
00316             CASE(R32G32B32A32_FLOAT);
00317             CASE(R32G32B32A32_UINT);
00318             CASE(R32G32B32A32_SINT);
00319             
00320             CASE(R32G32B32_TYPELESS);
00321             CASE(R32G32B32_FLOAT);
00322             CASE(R32G32B32_UINT);
00323             CASE(R32G32B32_SINT);
00324             
00325             CASE(R16G16B16A16_TYPELESS);
00326             CASE(R16G16B16A16_FLOAT);
00327             CASE(R16G16B16A16_UNORM);
00328             CASE(R16G16B16A16_UINT);
00329             CASE(R16G16B16A16_SNORM);
00330             CASE(R16G16B16A16_SINT);
00331             
00332             CASE(R32G32_TYPELESS);
00333             CASE(R32G32_FLOAT);
00334             CASE(R32G32_UINT);
00335             CASE(R32G32_SINT);
00336             
00337             CASE(R32G8X24_TYPELESS);
00338             CASE(D32_FLOAT_S8X24_UINT);
00339             CASE(R32_FLOAT_X8X24_TYPELESS);
00340             CASE(X32_TYPELESS_G8X24_UINT);
00341             
00342             CASE(R10G10B10A2_TYPELESS);
00343             CASE(R10G10B10A2_UNORM);
00344             CASE(R10G10B10A2_UINT);
00345             
00346             CASE(R11G11B10_FLOAT);
00347             
00348             CASE(R8G8B8A8_TYPELESS);
00349             CASE(R8G8B8A8_UNORM);
00350             CASE(R8G8B8A8_UNORM_SRGB);
00351             CASE(R8G8B8A8_UINT);
00352             CASE(R8G8B8A8_SNORM);
00353             CASE(R8G8B8A8_SINT);
00354             
00355             CASE(R16G16_TYPELESS);
00356             CASE(R16G16_FLOAT);
00357             CASE(R16G16_UNORM);
00358             CASE(R16G16_UINT);
00359             CASE(R16G16_SNORM);
00360             CASE(R16G16_SINT);
00361             
00362             CASE(R32_TYPELESS);
00363             CASE(D32_FLOAT);
00364             CASE(R32_FLOAT);
00365             CASE(R32_UINT);
00366             CASE(R32_SINT);
00367             
00368             CASE(R24G8_TYPELESS);
00369             CASE(D24_UNORM_S8_UINT);
00370             CASE(R24_UNORM_X8_TYPELESS);
00371             CASE(X24_TYPELESS_G8_UINT);
00372             
00373             CASE(R8G8_TYPELESS);
00374             CASE(R8G8_UNORM);
00375             CASE(R8G8_UINT);
00376             CASE(R8G8_SNORM);
00377             CASE(R8G8_SINT);
00378             
00379             CASE(R16_TYPELESS);
00380             CASE(R16_FLOAT);
00381             CASE(D16_UNORM);
00382             CASE(R16_UNORM);
00383             CASE(R16_UINT);
00384             CASE(R16_SNORM);
00385             CASE(R16_SINT);
00386             
00387             CASE(R8_TYPELESS);
00388             CASE(R8_UNORM);
00389             CASE(R8_UINT);
00390             CASE(R8_SNORM);
00391             CASE(R8_SINT);
00392             CASE(A8_UNORM);
00393 
00394             CASE(R1_UNORM);
00395         
00396             CASE(R9G9B9E5_SHAREDEXP);
00397             
00398             CASE(R8G8_B8G8_UNORM);
00399             CASE(G8R8_G8B8_UNORM);
00400 
00401             CASE(BC1_TYPELESS);
00402             CASE(BC1_UNORM);
00403             CASE(BC1_UNORM_SRGB);
00404         
00405             CASE(BC2_TYPELESS);
00406             CASE(BC2_UNORM);
00407             CASE(BC2_UNORM_SRGB);
00408         
00409             CASE(BC3_TYPELESS);
00410             CASE(BC3_UNORM);
00411             CASE(BC3_UNORM_SRGB);
00412         
00413             CASE(BC4_TYPELESS);
00414             CASE(BC4_UNORM);
00415             CASE(BC4_SNORM);
00416         
00417             CASE(BC5_TYPELESS);
00418             CASE(BC5_UNORM);
00419             CASE(BC5_SNORM);
00420 
00421             CASE(B5G6R5_UNORM);
00422             CASE(B5G5R5A1_UNORM);
00423             CASE(B8G8R8A8_UNORM);
00424             CASE(B8G8R8X8_UNORM);
00425 
00426             default: 
00427                 return "UNKNOWN";
00428         }
00429 #undef CASE
00430     }
00431     
00432     const char * getD3d10ResourceDimensionString(D3D10_RESOURCE_DIMENSION resourceDimension)
00433     {
00434         switch(resourceDimension)
00435         {
00436             default:
00437             case D3D10_RESOURCE_DIMENSION_UNKNOWN: return "UNKNOWN";
00438             case D3D10_RESOURCE_DIMENSION_BUFFER: return "BUFFER";
00439             case D3D10_RESOURCE_DIMENSION_TEXTURE1D: return "TEXTURE1D";
00440             case D3D10_RESOURCE_DIMENSION_TEXTURE2D: return "TEXTURE2D";
00441             case D3D10_RESOURCE_DIMENSION_TEXTURE3D: return "TEXTURE3D";
00442         }
00443     }
00444 
00445 /*** implementation ***/
00446 
00447 void mem_read(Stream & mem, DDSPixelFormat & pf)
00448 {
00449     mem_read(mem, pf.size);
00450     mem_read(mem, pf.flags);
00451     mem_read(mem, pf.fourcc);
00452     mem_read(mem, pf.bitcount);
00453     mem_read(mem, pf.rmask);
00454     mem_read(mem, pf.gmask);
00455     mem_read(mem, pf.bmask);
00456     mem_read(mem, pf.amask);
00457 }
00458 
00459 void mem_read(Stream & mem, DDSCaps & caps)
00460 {
00461     mem_read(mem, caps.caps1);
00462     mem_read(mem, caps.caps2);
00463     mem_read(mem, caps.caps3);
00464     mem_read(mem, caps.caps4);
00465 }
00466 
00467 void mem_read(Stream & mem, DDSHeader10 & header)
00468 {
00469     mem_read(mem, header.dxgiFormat);
00470     mem_read(mem, header.resourceDimension);
00471     mem_read(mem, header.miscFlag);
00472     mem_read(mem, header.arraySize);
00473     mem_read(mem, header.reserved);
00474 }
00475 
00476 void mem_read(Stream & mem, DDSHeader & header)
00477 {
00478     mem_read(mem, header.fourcc);
00479     mem_read(mem, header.size);
00480     mem_read(mem, header.flags);
00481     mem_read(mem, header.height);
00482     mem_read(mem, header.width);
00483     mem_read(mem, header.pitch);
00484     mem_read(mem, header.depth);
00485     mem_read(mem, header.mipmapcount);
00486     for (uint i = 0; i < 11; i++) mem_read(mem, header.reserved[i]);
00487     mem_read(mem, header.pf);
00488     mem_read(mem, header.caps);
00489     mem_read(mem, header.notused);
00490 
00491     if (header.hasDX10Header())
00492     {
00493         mem_read(mem, header.header10);
00494     }
00495 }
00496 
00497 namespace
00498 {
00499     struct FormatDescriptor
00500     {
00501         uint format;
00502         uint bitcount;
00503         uint rmask;
00504         uint gmask;
00505         uint bmask;
00506         uint amask;
00507     };
00508 
00509     static const FormatDescriptor s_d3dFormats[] =
00510     {
00511         { D3DFMT_R8G8B8,        24, 0xFF0000,   0xFF00,     0xFF,       0 },
00512         { D3DFMT_A8R8G8B8,      32, 0xFF0000,   0xFF00,     0xFF,       0xFF000000 },  // DXGI_FORMAT_B8G8R8A8_UNORM
00513         { D3DFMT_X8R8G8B8,      32, 0xFF0000,   0xFF00,     0xFF,       0 },           // DXGI_FORMAT_B8G8R8X8_UNORM
00514         { D3DFMT_R5G6B5,        16, 0xF800,     0x7E0,      0x1F,       0 },           // DXGI_FORMAT_B5G6R5_UNORM
00515         { D3DFMT_X1R5G5B5,      16, 0x7C00,     0x3E0,      0x1F,       0 },
00516         { D3DFMT_A1R5G5B5,      16, 0x7C00,     0x3E0,      0x1F,       0x8000 },      // DXGI_FORMAT_B5G5R5A1_UNORM
00517         { D3DFMT_A4R4G4B4,      16, 0xF00,      0xF0,       0xF,        0xF000 },
00518         { D3DFMT_R3G3B2,        8,  0xE0,       0x1C,       0x3,        0 },
00519         { D3DFMT_A8,            8,  0,          0,          0,          8 },           // DXGI_FORMAT_A8_UNORM
00520         { D3DFMT_A8R3G3B2,      16, 0xE0,       0x1C,       0x3,        0xFF00 },
00521         { D3DFMT_X4R4G4B4,      16, 0xF00,      0xF0,       0xF,        0 },
00522         { D3DFMT_A2B10G10R10,   32, 0x3FF,      0xFFC00,    0x3FF00000, 0xC0000000 },  // DXGI_FORMAT_R10G10B10A2
00523         { D3DFMT_A8B8G8R8,      32, 0xFF,       0xFF00,     0xFF0000,   0xFF000000 },  // DXGI_FORMAT_R8G8B8A8_UNORM
00524         { D3DFMT_X8B8G8R8,      32, 0xFF,       0xFF00,     0xFF0000,   0 },
00525         { D3DFMT_G16R16,        32, 0xFFFF,     0xFFFF0000, 0,          0 },           // DXGI_FORMAT_R16G16_UNORM
00526         { D3DFMT_A2R10G10B10,   32, 0x3FF00000, 0xFFC00,    0x3FF,      0xC0000000 },
00527         { D3DFMT_A2B10G10R10,   32, 0x3FF,      0xFFC00,    0x3FF00000, 0xC0000000 },
00528 
00529         { D3DFMT_L8,            8,  8,          0,          0,          0 },           // DXGI_FORMAT_R8_UNORM 
00530         { D3DFMT_L16,           16, 16,         0,          0,          0 },           // DXGI_FORMAT_R16_UNORM
00531     };
00532 
00533     static const uint s_d3dFormatCount = sizeof(s_d3dFormats) / sizeof(s_d3dFormats[0]);
00534 
00535 } // namespace
00536 
00537 uint findD3D9Format(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
00538 {
00539     for (int i = 0; i < s_d3dFormatCount; i++)
00540         {
00541             if (s_d3dFormats[i].bitcount == bitcount &&
00542                 s_d3dFormats[i].rmask == rmask &&
00543                 s_d3dFormats[i].gmask == gmask &&
00544                 s_d3dFormats[i].bmask == bmask &&
00545                 s_d3dFormats[i].amask == amask)
00546             {
00547                 return s_d3dFormats[i].format;
00548             }
00549         }
00550 
00551         return 0;
00552     }
00553 
00554 
00555 
00556 DDSHeader::DDSHeader()
00557 {
00558     this->fourcc = FOURCC_DDS;
00559     this->size = 124;
00560     this->flags  = (DDSD_CAPS|DDSD_PIXELFORMAT);
00561     this->height = 0;
00562     this->width = 0;
00563     this->pitch = 0;
00564     this->depth = 0;
00565     this->mipmapcount = 0;
00566     for (uint i = 0; i < 11; i++) this->reserved[i] = 0;
00567 
00568     // Store version information on the reserved header attributes.
00569     this->reserved[9] = FOURCC_NVTT;
00570     this->reserved[10] = (2 << 16) | (1 << 8) | (0);    // major.minor.revision
00571 
00572     this->pf.size = 32;
00573     this->pf.flags = 0;
00574     this->pf.fourcc = 0;
00575     this->pf.bitcount = 0;
00576     this->pf.rmask = 0;
00577     this->pf.gmask = 0;
00578     this->pf.bmask = 0;
00579     this->pf.amask = 0;
00580     this->caps.caps1 = DDSCAPS_TEXTURE;
00581     this->caps.caps2 = 0;
00582     this->caps.caps3 = 0;
00583     this->caps.caps4 = 0;
00584     this->notused = 0;
00585 
00586     this->header10.dxgiFormat = DXGI_FORMAT_UNKNOWN;
00587     this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_UNKNOWN;
00588     this->header10.miscFlag = 0;
00589     this->header10.arraySize = 0;
00590     this->header10.reserved = 0;
00591 }
00592 
00593 void DDSHeader::setWidth(uint w)
00594 {
00595     this->flags |= DDSD_WIDTH;
00596     this->width = w;
00597 }
00598 
00599 void DDSHeader::setHeight(uint h)
00600 {
00601     this->flags |= DDSD_HEIGHT;
00602     this->height = h;
00603 }
00604 
00605 void DDSHeader::setDepth(uint d)
00606 {
00607     this->flags |= DDSD_DEPTH;
00608     this->depth = d;
00609 }
00610 
00611 void DDSHeader::setMipmapCount(uint count)
00612 {
00613     if (count == 0 || count == 1)
00614     {
00615         this->flags &= ~DDSD_MIPMAPCOUNT;
00616         this->mipmapcount = 1;
00617 
00618         if (this->caps.caps2 == 0) {
00619             this->caps.caps1 = DDSCAPS_TEXTURE;
00620         }
00621         else {
00622             this->caps.caps1 = DDSCAPS_TEXTURE | DDSCAPS_COMPLEX;
00623         }
00624     }
00625     else
00626     {
00627         this->flags |= DDSD_MIPMAPCOUNT;
00628         this->mipmapcount = count;
00629 
00630         this->caps.caps1 |= DDSCAPS_COMPLEX | DDSCAPS_MIPMAP;
00631     }
00632 }
00633 
00634 void DDSHeader::setTexture2D()
00635 {
00636     this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
00637     this->header10.arraySize = 1;
00638 }
00639 
00640 void DDSHeader::setTexture3D()
00641 {
00642     this->caps.caps2 = DDSCAPS2_VOLUME;
00643 
00644     this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE3D;
00645     this->header10.arraySize = 1;
00646 }
00647 
00648 void DDSHeader::setTextureCube()
00649 {
00650     this->caps.caps1 |= DDSCAPS_COMPLEX;
00651     this->caps.caps2 = DDSCAPS2_CUBEMAP | DDSCAPS2_CUBEMAP_ALL_FACES;
00652 
00653     this->header10.resourceDimension = D3D10_RESOURCE_DIMENSION_TEXTURE2D;
00654     this->header10.arraySize = 6;
00655 }
00656 
00657 void DDSHeader::setLinearSize(uint size)
00658 {
00659     this->flags &= ~DDSD_PITCH;
00660     this->flags |= DDSD_LINEARSIZE;
00661     this->pitch = size;
00662 }
00663 
00664 void DDSHeader::setPitch(uint pitch)
00665 {
00666     this->flags &= ~DDSD_LINEARSIZE;
00667     this->flags |= DDSD_PITCH;
00668     this->pitch = pitch;
00669 }
00670 
00671 void DDSHeader::setFourCC(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
00672 {
00673     // set fourcc pixel format.
00674     this->pf.flags = DDPF_FOURCC;
00675     this->pf.fourcc = MAKEFOURCC(c0, c1, c2, c3);
00676 
00677     this->pf.bitcount = 0;
00678     this->pf.rmask = 0;
00679     this->pf.gmask = 0;
00680     this->pf.bmask = 0;
00681     this->pf.amask = 0;
00682 }
00683 
00684 void DDSHeader::setFormatCode(uint32 code)
00685 {
00686     // set fourcc pixel format.
00687     this->pf.flags = DDPF_FOURCC;
00688     this->pf.fourcc = code;
00689     
00690     this->pf.bitcount = 0;
00691     this->pf.rmask = 0;
00692     this->pf.gmask = 0;
00693     this->pf.bmask = 0;
00694     this->pf.amask = 0;
00695 }
00696 
00697 void DDSHeader::setSwizzleCode(uint8 c0, uint8 c1, uint8 c2, uint8 c3)
00698 {
00699     this->pf.bitcount = MAKEFOURCC(c0, c1, c2, c3);
00700 }
00701 
00702 
00703 void DDSHeader::setPixelFormat(uint bitcount, uint rmask, uint gmask, uint bmask, uint amask)
00704 {
00705     // Make sure the masks are correct.
00706     if ((rmask & gmask) ||
00707         (rmask & bmask) ||
00708         (rmask & amask) ||
00709         (gmask & bmask) ||
00710         (gmask & amask) ||
00711         (bmask & amask)) {
00712         printf("DDS: bad RGBA masks, pixel format not set\n");
00713         return;
00714     }
00715 
00716     if (rmask != 0 || gmask != 0 || bmask != 0)
00717     {
00718         if (gmask == 0 && bmask == 0)
00719         {
00720             this->pf.flags = DDPF_LUMINANCE;
00721         }
00722         else
00723         {
00724             this->pf.flags = DDPF_RGB;
00725         }
00726 
00727         if (amask != 0) {
00728             this->pf.flags |= DDPF_ALPHAPIXELS;
00729         }
00730     }
00731     else if (amask != 0)
00732     {
00733         this->pf.flags |= DDPF_ALPHA;
00734     }
00735 
00736     if (bitcount == 0)
00737     {
00738         // Compute bit count from the masks.
00739         uint total = rmask | gmask | bmask | amask;
00740         while(total != 0) {
00741             bitcount++;
00742             total >>= 1;
00743         }
00744     }
00745 
00746     // D3DX functions do not like this:
00747     this->pf.fourcc = 0; //findD3D9Format(bitcount, rmask, gmask, bmask, amask);
00748     /*if (this->pf.fourcc) {
00749         this->pf.flags |= DDPF_FOURCC;
00750     }*/
00751 
00752     if (!(bitcount > 0 && bitcount <= 32)) {
00753         printf("DDS: bad bit count, pixel format not set\n");
00754         return;
00755     }
00756     this->pf.bitcount = bitcount;
00757     this->pf.rmask = rmask;
00758     this->pf.gmask = gmask;
00759     this->pf.bmask = bmask;
00760     this->pf.amask = amask;
00761 }
00762 
00763 void DDSHeader::setDX10Format(uint format)
00764 {
00765     //this->pf.flags = 0;
00766     this->pf.fourcc = FOURCC_DX10;
00767     this->header10.dxgiFormat = format;
00768 }
00769 
00770 void DDSHeader::setNormalFlag(bool b)
00771 {
00772     if (b) this->pf.flags |= DDPF_NORMAL;
00773     else this->pf.flags &= ~DDPF_NORMAL;
00774 }
00775 
00776 void DDSHeader::setSrgbFlag(bool b)
00777 {
00778     if (b) this->pf.flags |= DDPF_SRGB;
00779     else this->pf.flags &= ~DDPF_SRGB;
00780 }
00781 
00782 void DDSHeader::setHasAlphaFlag(bool b)
00783 {
00784     if (b) this->pf.flags |= DDPF_ALPHAPIXELS;
00785     else this->pf.flags &= ~DDPF_ALPHAPIXELS;
00786 }
00787 
00788 void DDSHeader::setUserVersion(int version)
00789 {
00790     this->reserved[7] = FOURCC_UVER;
00791     this->reserved[8] = version;
00792 }
00793 
00794 /*
00795 void DDSHeader::swapBytes()
00796 {
00797     this->fourcc = POSH_LittleU32(this->fourcc);
00798     this->size = POSH_LittleU32(this->size);
00799     this->flags = POSH_LittleU32(this->flags);
00800     this->height = POSH_LittleU32(this->height);
00801     this->width = POSH_LittleU32(this->width);
00802     this->pitch = POSH_LittleU32(this->pitch);
00803     this->depth = POSH_LittleU32(this->depth);
00804     this->mipmapcount = POSH_LittleU32(this->mipmapcount);
00805     
00806     for(int i = 0; i < 11; i++) {
00807         this->reserved[i] = POSH_LittleU32(this->reserved[i]);
00808     }
00809 
00810     this->pf.size = POSH_LittleU32(this->pf.size);
00811     this->pf.flags = POSH_LittleU32(this->pf.flags);
00812     this->pf.fourcc = POSH_LittleU32(this->pf.fourcc);
00813     this->pf.bitcount = POSH_LittleU32(this->pf.bitcount);
00814     this->pf.rmask = POSH_LittleU32(this->pf.rmask);
00815     this->pf.gmask = POSH_LittleU32(this->pf.gmask);
00816     this->pf.bmask = POSH_LittleU32(this->pf.bmask);
00817     this->pf.amask = POSH_LittleU32(this->pf.amask);
00818     this->caps.caps1 = POSH_LittleU32(this->caps.caps1);
00819     this->caps.caps2 = POSH_LittleU32(this->caps.caps2);
00820     this->caps.caps3 = POSH_LittleU32(this->caps.caps3);
00821     this->caps.caps4 = POSH_LittleU32(this->caps.caps4);
00822     this->notused = POSH_LittleU32(this->notused);
00823 
00824     this->header10.dxgiFormat = POSH_LittleU32(this->header10.dxgiFormat);
00825     this->header10.resourceDimension = POSH_LittleU32(this->header10.resourceDimension);
00826     this->header10.miscFlag = POSH_LittleU32(this->header10.miscFlag);
00827     this->header10.arraySize = POSH_LittleU32(this->header10.arraySize);
00828     this->header10.reserved = POSH_LittleU32(this->header10.reserved);
00829 }
00830 */
00831 
00832 bool DDSHeader::hasDX10Header() const
00833 {
00834     return this->pf.fourcc == FOURCC_DX10;
00835 }
00836 
00837 uint DDSHeader::signature() const
00838 {
00839     return this->reserved[9];
00840 }
00841 
00842 uint DDSHeader::toolVersion() const
00843 {
00844     return this->reserved[10];
00845 }
00846 
00847 uint DDSHeader::userVersion() const
00848 {
00849     if (this->reserved[7] == FOURCC_UVER) {
00850         return this->reserved[8];
00851     }
00852     return 0;
00853 }
00854 
00855 bool DDSHeader::isNormalMap() const
00856 {
00857     return (pf.flags & DDPF_NORMAL) != 0;
00858 }
00859 
00860 bool DDSHeader::isSrgb() const
00861 {
00862     return (pf.flags & DDPF_SRGB) != 0;
00863 }
00864 
00865 bool DDSHeader::hasAlpha() const
00866 {
00867     return (pf.flags & DDPF_ALPHAPIXELS) != 0;
00868 }
00869 
00870 uint DDSHeader::d3d9Format() const
00871 {
00872     if (pf.flags & DDPF_FOURCC) {
00873         return pf.fourcc;
00874     }
00875     else {
00876         return findD3D9Format(pf.bitcount, pf.rmask, pf.gmask, pf.bmask, pf.amask);
00877     }
00878 }
00879 
00880 DirectDrawSurface::DirectDrawSurface(unsigned char *mem, uint size) : stream(mem, size), header()
00881 {
00882     mem_read(stream, header);
00883 
00884     // some ATI2 compressed normal maps do not have their
00885     // normal flag set, so force it here (the original nvtt don't do
00886     // this, but the decompressor has a -forcenormal flag)
00887     if (header.pf.fourcc == FOURCC_ATI2) header.setNormalFlag(true);
00888 }
00889 
00890 DirectDrawSurface::~DirectDrawSurface()
00891 {
00892 }
00893 
00894 bool DirectDrawSurface::isValid() const
00895 {
00896     if (header.fourcc != FOURCC_DDS || header.size != 124)
00897     {
00898         return false;
00899     }
00900     
00901     const uint required = (DDSD_WIDTH|DDSD_HEIGHT/*|DDSD_CAPS|DDSD_PIXELFORMAT*/);
00902     if( (header.flags & required) != required ) {
00903         return false;
00904     }
00905     
00906     if (header.pf.size != 32) {
00907         return false;
00908     }
00909 
00910     /* in some files DDSCAPS_TEXTURE is missing: silently ignore */
00911     /*
00912     if( !(header.caps.caps1 & DDSCAPS_TEXTURE) ) {
00913         return false;
00914     }
00915     */
00916 
00917     return true;
00918 }
00919 
00920 bool DirectDrawSurface::isSupported() const
00921 {
00922     if (header.hasDX10Header())
00923     {
00924         if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM ||
00925             header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM ||
00926             header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM ||
00927             header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM ||
00928             header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM)
00929         {
00930             return true;
00931         }
00932 
00933         return false;
00934     }
00935     else
00936     {
00937         if (header.pf.flags & DDPF_FOURCC)
00938         {
00939             if (header.pf.fourcc != FOURCC_DXT1 &&
00940                 header.pf.fourcc != FOURCC_DXT2 &&
00941                 header.pf.fourcc != FOURCC_DXT3 &&
00942                 header.pf.fourcc != FOURCC_DXT4 &&
00943                 header.pf.fourcc != FOURCC_DXT5 &&
00944                 header.pf.fourcc != FOURCC_RXGB &&
00945                 header.pf.fourcc != FOURCC_ATI1 &&
00946                 header.pf.fourcc != FOURCC_ATI2)
00947             {
00948                 // Unknown fourcc code.
00949                 return false;
00950             }
00951         }
00952         else if ((header.pf.flags & DDPF_RGB) || (header.pf.flags & DDPF_LUMINANCE))
00953         {
00954             // All RGB and luminance formats are supported now.
00955         }
00956         else
00957         {
00958             return false;
00959         }
00960         
00961         if (isTextureCube() && (header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) != DDSCAPS2_CUBEMAP_ALL_FACES)
00962         {
00963             // Cubemaps must contain all faces.
00964             return false;
00965         }
00966     
00967         if (isTexture3D())
00968         {
00969             // @@ 3D textures not supported yet.
00970             return false;
00971         }
00972     }
00973     
00974     return true;
00975 }
00976 
00977 bool DirectDrawSurface::hasAlpha() const
00978 {
00979     if (header.hasDX10Header())
00980     {
00981         /* TODO: Update hasAlpha to handle all DX10 formats. */
00982         return 
00983             header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM ||
00984             header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM ||
00985             header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM;
00986     }
00987     else
00988     {
00989         if (header.pf.flags & DDPF_RGB) 
00990         {
00991             return header.pf.amask != 0;
00992         }
00993         else if (header.pf.flags & DDPF_FOURCC)
00994         {
00995             if (header.pf.fourcc == FOURCC_RXGB ||
00996                 header.pf.fourcc == FOURCC_ATI1 ||
00997                 header.pf.fourcc == FOURCC_ATI2 ||
00998                 header.pf.flags & DDPF_NORMAL)
00999             {
01000                 return false;
01001             }
01002             else
01003             {
01004                 // @@ Here we could check the ALPHA_PIXELS flag, but nobody sets it. (except us?)
01005                 return true;
01006             }
01007         }
01008 
01009         return false;
01010     }
01011 }
01012 
01013 uint DirectDrawSurface::mipmapCount() const
01014 {
01015     if (header.flags & DDSD_MIPMAPCOUNT) return header.mipmapcount;
01016     else return 1;
01017 }
01018 
01019 
01020 uint DirectDrawSurface::width() const
01021 {
01022     if (header.flags & DDSD_WIDTH) return header.width;
01023     else return 1;
01024 }
01025 
01026 uint DirectDrawSurface::height() const
01027 {
01028     if (header.flags & DDSD_HEIGHT) return header.height;
01029     else return 1;
01030 }
01031 
01032 uint DirectDrawSurface::depth() const
01033 {
01034     if (header.flags & DDSD_DEPTH) return header.depth;
01035     else return 1;
01036 }
01037 
01038 bool DirectDrawSurface::isTexture1D() const
01039 {
01040     if (header.hasDX10Header())
01041     {
01042         return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE1D;
01043     }
01044     return false;
01045 }
01046 
01047 bool DirectDrawSurface::isTexture2D() const
01048 {
01049     if (header.hasDX10Header())
01050     {
01051         return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE2D;
01052     }
01053     else
01054     {
01055         return !isTexture3D() && !isTextureCube();
01056     }
01057 }
01058 
01059 bool DirectDrawSurface::isTexture3D() const
01060 {
01061     if (header.hasDX10Header())
01062     {
01063         return header.header10.resourceDimension == D3D10_RESOURCE_DIMENSION_TEXTURE3D;
01064     }
01065     else
01066     {
01067     return (header.caps.caps2 & DDSCAPS2_VOLUME) != 0;
01068     }
01069 }
01070 
01071 bool DirectDrawSurface::isTextureCube() const
01072 {
01073     return (header.caps.caps2 & DDSCAPS2_CUBEMAP) != 0;
01074 }
01075 
01076 void DirectDrawSurface::setNormalFlag(bool b)
01077 {
01078     header.setNormalFlag(b);
01079 }
01080 
01081 void DirectDrawSurface::setHasAlphaFlag(bool b)
01082 {
01083     header.setHasAlphaFlag(b);
01084 }
01085 
01086 void DirectDrawSurface::setUserVersion(int version)
01087 {
01088     header.setUserVersion(version);
01089 }
01090 
01091 void DirectDrawSurface::mipmap(Image * img, uint face, uint mipmap)
01092 {
01093     stream.seek(offset(face, mipmap));
01094     
01095     uint w = width();
01096     uint h = height();
01097     
01098     // Compute width and height.
01099     for (uint m = 0; m < mipmap; m++)
01100     {
01101         w = max(1U, w / 2);
01102         h = max(1U, h / 2);
01103     }
01104     
01105     img->allocate(w, h);
01106     
01107     if (hasAlpha())
01108     {
01109         img->setFormat(Image::Format_ARGB);
01110     }
01111     else
01112     {
01113         img->setFormat(Image::Format_RGB);
01114     }
01115 
01116     if (header.hasDX10Header())
01117     {
01118         // So far only block formats supported.
01119         readBlockImage(img);
01120     }
01121     else
01122     {
01123         if (header.pf.flags & DDPF_RGB) 
01124         {
01125             readLinearImage(img);
01126         }
01127         else if (header.pf.flags & DDPF_FOURCC)
01128         {
01129             readBlockImage(img);
01130         }
01131     }
01132 }
01133 
01134 void DirectDrawSurface::readLinearImage(Image * img)
01135 {
01136     
01137     const uint w = img->width();
01138     const uint h = img->height();
01139     
01140     uint rshift, rsize;
01141     PixelFormat::maskShiftAndSize(header.pf.rmask, &rshift, &rsize);
01142     
01143     uint gshift, gsize;
01144     PixelFormat::maskShiftAndSize(header.pf.gmask, &gshift, &gsize);
01145     
01146     uint bshift, bsize;
01147     PixelFormat::maskShiftAndSize(header.pf.bmask, &bshift, &bsize);
01148     
01149     uint ashift, asize;
01150     PixelFormat::maskShiftAndSize(header.pf.amask, &ashift, &asize);
01151 
01152     uint byteCount = (header.pf.bitcount + 7) / 8;
01153 
01154     if (byteCount > 4)
01155     {
01156         /* just in case... we could have segfaults later on if byteCount > 4 */
01157         printf("DDS: bitcount too large");
01158         return;
01159     }
01160 
01161     // Read linear RGB images.
01162     for (uint y = 0; y < h; y++)
01163     {
01164         for (uint x = 0; x < w; x++)
01165         {
01166             uint c = 0;
01167             mem_read(stream, (unsigned char *)(&c), byteCount);
01168 
01169             Color32 pixel(0, 0, 0, 0xFF);
01170             pixel.r = PixelFormat::convert((c & header.pf.rmask) >> rshift, rsize, 8);
01171             pixel.g = PixelFormat::convert((c & header.pf.gmask) >> gshift, gsize, 8);
01172             pixel.b = PixelFormat::convert((c & header.pf.bmask) >> bshift, bsize, 8);
01173             pixel.a = PixelFormat::convert((c & header.pf.amask) >> ashift, asize, 8);
01174 
01175             img->pixel(x, y) = pixel;
01176         }
01177     }
01178 }
01179 
01180 void DirectDrawSurface::readBlockImage(Image * img)
01181 {
01182 
01183     const uint w = img->width();
01184     const uint h = img->height();
01185     
01186     const uint bw = (w + 3) / 4;
01187     const uint bh = (h + 3) / 4;
01188     
01189     for (uint by = 0; by < bh; by++)
01190     {
01191         for (uint bx = 0; bx < bw; bx++)
01192         {
01193             ColorBlock block;
01194             
01195             // Read color block.
01196             readBlock(&block);
01197             
01198             // Write color block.
01199             for (uint y = 0; y < min(4U, h-4*by); y++)
01200             {
01201                 for (uint x = 0; x < min(4U, w-4*bx); x++)
01202                 {
01203                     img->pixel(4*bx+x, 4*by+y) = block.color(x, y);
01204                 }
01205             }
01206         }
01207     }
01208 }
01209 
01210 static Color32 buildNormal(uint8 x, uint8 y)
01211 {
01212     float nx = 2 * (x / 255.0f) - 1;
01213     float ny = 2 * (y / 255.0f) - 1;
01214     float nz = 0.0f;
01215     if (1 - nx*nx - ny*ny > 0) nz = sqrt(1 - nx*nx - ny*ny);
01216     uint8 z = clamp(int(255.0f * (nz + 1) / 2.0f), 0, 255);
01217     
01218     return Color32(x, y, z);
01219 }
01220 
01221 
01222 void DirectDrawSurface::readBlock(ColorBlock * rgba)
01223 {
01224     uint fourcc = header.pf.fourcc;
01225 
01226     // Map DX10 block formats to fourcc codes.
01227     if (header.hasDX10Header())
01228     {
01229         if (header.header10.dxgiFormat == DXGI_FORMAT_BC1_UNORM) fourcc = FOURCC_DXT1;
01230         if (header.header10.dxgiFormat == DXGI_FORMAT_BC2_UNORM) fourcc = FOURCC_DXT3;
01231         if (header.header10.dxgiFormat == DXGI_FORMAT_BC3_UNORM) fourcc = FOURCC_DXT5;
01232         if (header.header10.dxgiFormat == DXGI_FORMAT_BC4_UNORM) fourcc = FOURCC_ATI1;
01233         if (header.header10.dxgiFormat == DXGI_FORMAT_BC5_UNORM) fourcc = FOURCC_ATI2;
01234     }
01235 
01236 
01237     if (fourcc == FOURCC_DXT1)
01238     {
01239         BlockDXT1 block;
01240         mem_read(stream, block);
01241         block.decodeBlock(rgba);
01242     }
01243     else if (fourcc == FOURCC_DXT2 ||
01244         header.pf.fourcc == FOURCC_DXT3)
01245     {
01246         BlockDXT3 block;
01247         mem_read(stream, block);
01248         block.decodeBlock(rgba);
01249     }
01250     else if (fourcc == FOURCC_DXT4 ||
01251         header.pf.fourcc == FOURCC_DXT5 ||
01252         header.pf.fourcc == FOURCC_RXGB)
01253     {
01254         BlockDXT5 block;
01255         mem_read(stream, block);
01256         block.decodeBlock(rgba);
01257         
01258         if (fourcc == FOURCC_RXGB)
01259         {
01260             // Swap R & A.
01261             for (int i = 0; i < 16; i++)
01262             {
01263                 Color32 & c = rgba->color(i);
01264                 uint tmp = c.r;
01265                 c.r = c.a;
01266                 c.a = tmp;
01267             }
01268         }
01269     }
01270     else if (fourcc == FOURCC_ATI1)
01271     {
01272         BlockATI1 block;
01273         mem_read(stream, block);
01274         block.decodeBlock(rgba);
01275     }
01276     else if (fourcc == FOURCC_ATI2)
01277     {
01278         BlockATI2 block;
01279         mem_read(stream, block);
01280         block.decodeBlock(rgba);
01281     }
01282     
01283     // If normal flag set, convert to normal.
01284     if (header.pf.flags & DDPF_NORMAL)
01285     {
01286         if (fourcc == FOURCC_ATI2)
01287         {
01288             for (int i = 0; i < 16; i++)
01289             {
01290                 Color32 & c = rgba->color(i);
01291                 c = buildNormal(c.r, c.g);
01292             }
01293         }
01294         else if (fourcc == FOURCC_DXT5)
01295         {
01296             for (int i = 0; i < 16; i++)
01297             {
01298                 Color32 & c = rgba->color(i);
01299                 c = buildNormal(c.a, c.g);
01300             }
01301         }
01302     }
01303 }
01304 
01305 
01306 uint DirectDrawSurface::blockSize() const
01307 {
01308     switch(header.pf.fourcc)
01309     {
01310         case FOURCC_DXT1:
01311         case FOURCC_ATI1:
01312             return 8;
01313         case FOURCC_DXT2:
01314         case FOURCC_DXT3:
01315         case FOURCC_DXT4:
01316         case FOURCC_DXT5:
01317         case FOURCC_RXGB:
01318         case FOURCC_ATI2:
01319             return 16;
01320         case FOURCC_DX10:
01321             switch(header.header10.dxgiFormat)
01322             {
01323                 case DXGI_FORMAT_BC1_TYPELESS:
01324                 case DXGI_FORMAT_BC1_UNORM:
01325                 case DXGI_FORMAT_BC1_UNORM_SRGB:
01326                 case DXGI_FORMAT_BC4_TYPELESS:
01327                 case DXGI_FORMAT_BC4_UNORM:
01328                 case DXGI_FORMAT_BC4_SNORM:
01329                     return 8;
01330                 case DXGI_FORMAT_BC2_TYPELESS:
01331                 case DXGI_FORMAT_BC2_UNORM:
01332                 case DXGI_FORMAT_BC2_UNORM_SRGB:
01333                 case DXGI_FORMAT_BC3_TYPELESS:
01334                 case DXGI_FORMAT_BC3_UNORM:
01335                 case DXGI_FORMAT_BC3_UNORM_SRGB:
01336                 case DXGI_FORMAT_BC5_TYPELESS:
01337                 case DXGI_FORMAT_BC5_UNORM:
01338                 case DXGI_FORMAT_BC5_SNORM:
01339                     return 16;
01340             };
01341     };
01342 
01343     // Not a block image.
01344     return 0;
01345 }
01346 
01347 uint DirectDrawSurface::mipmapSize(uint mipmap) const
01348 {
01349     uint w = width();
01350     uint h = height();
01351     uint d = depth();
01352     
01353     for (uint m = 0; m < mipmap; m++)
01354     {
01355         w = max(1U, w / 2);
01356         h = max(1U, h / 2);
01357         d = max(1U, d / 2);
01358     }
01359 
01360     if (header.pf.flags & DDPF_FOURCC)
01361     {
01362         // @@ How are 3D textures aligned?
01363         w = (w + 3) / 4;
01364         h = (h + 3) / 4;
01365         return blockSize() * w * h;
01366     }
01367     else if (header.pf.flags & DDPF_RGB || (header.pf.flags & DDPF_LUMINANCE))
01368     {
01369         uint pitch = computePitch(w, header.pf.bitcount, 8); // Asuming 8 bit alignment, which is the same D3DX expects.
01370     
01371         return pitch * h * d;
01372     }
01373     else {
01374         printf("DDS: mipmap format not supported\n");
01375         return(0);
01376     };
01377 }
01378 
01379 uint DirectDrawSurface::faceSize() const
01380 {
01381     const uint count = mipmapCount();
01382     uint size = 0;
01383     
01384     for (uint m = 0; m < count; m++)
01385     {
01386         size += mipmapSize(m);
01387     }
01388     
01389     return size;
01390 }
01391 
01392 uint DirectDrawSurface::offset(const uint face, const uint mipmap)
01393 {
01394     uint size = 128; // sizeof(DDSHeader);
01395     
01396     if (header.hasDX10Header())
01397     {
01398         size += 20; // sizeof(DDSHeader10);
01399     }
01400 
01401     if (face != 0)
01402     {
01403         size += face * faceSize();
01404     }
01405     
01406     for (uint m = 0; m < mipmap; m++)
01407     {
01408         size += mipmapSize(m);
01409     }
01410     
01411     return size;
01412 }
01413 
01414 
01415 void DirectDrawSurface::printInfo() const
01416 {
01417     printf("Flags: 0x%.8X\n", header.flags);
01418     if (header.flags & DDSD_CAPS) printf("\tDDSD_CAPS\n");
01419     if (header.flags & DDSD_PIXELFORMAT) printf("\tDDSD_PIXELFORMAT\n");
01420     if (header.flags & DDSD_WIDTH) printf("\tDDSD_WIDTH\n");
01421     if (header.flags & DDSD_HEIGHT) printf("\tDDSD_HEIGHT\n");
01422     if (header.flags & DDSD_DEPTH) printf("\tDDSD_DEPTH\n");
01423     if (header.flags & DDSD_PITCH) printf("\tDDSD_PITCH\n");
01424     if (header.flags & DDSD_LINEARSIZE) printf("\tDDSD_LINEARSIZE\n");
01425     if (header.flags & DDSD_MIPMAPCOUNT) printf("\tDDSD_MIPMAPCOUNT\n");
01426 
01427     printf("Height: %u\n", header.height);
01428     printf("Width: %u\n", header.width);
01429     printf("Depth: %u\n", header.depth);
01430     if (header.flags & DDSD_PITCH) printf("Pitch: %u\n", header.pitch);
01431     else if (header.flags & DDSD_LINEARSIZE) printf("Linear size: %u\n", header.pitch);
01432     printf("Mipmap count: %u\n", header.mipmapcount);
01433     
01434     printf("Pixel Format:\n");
01435     printf("\tFlags: 0x%.8X\n", header.pf.flags);
01436     if (header.pf.flags & DDPF_RGB) printf("\t\tDDPF_RGB\n");
01437     if (header.pf.flags & DDPF_LUMINANCE) printf("\t\tDDPF_LUMINANCE\n");
01438     if (header.pf.flags & DDPF_FOURCC) printf("\t\tDDPF_FOURCC\n");
01439     if (header.pf.flags & DDPF_ALPHAPIXELS) printf("\t\tDDPF_ALPHAPIXELS\n");
01440     if (header.pf.flags & DDPF_ALPHA) printf("\t\tDDPF_ALPHA\n");
01441     if (header.pf.flags & DDPF_PALETTEINDEXED1) printf("\t\tDDPF_PALETTEINDEXED1\n");
01442     if (header.pf.flags & DDPF_PALETTEINDEXED2) printf("\t\tDDPF_PALETTEINDEXED2\n");
01443     if (header.pf.flags & DDPF_PALETTEINDEXED4) printf("\t\tDDPF_PALETTEINDEXED4\n");
01444     if (header.pf.flags & DDPF_PALETTEINDEXED8) printf("\t\tDDPF_PALETTEINDEXED8\n");
01445     if (header.pf.flags & DDPF_ALPHAPREMULT) printf("\t\tDDPF_ALPHAPREMULT\n");
01446     if (header.pf.flags & DDPF_NORMAL) printf("\t\tDDPF_NORMAL\n");
01447     
01448     if (header.pf.fourcc != 0) { 
01449         // Display fourcc code even when DDPF_FOURCC flag not set.
01450         printf("\tFourCC: '%c%c%c%c' (0x%.8X)\n",
01451             ((header.pf.fourcc >> 0) & 0xFF),
01452             ((header.pf.fourcc >> 8) & 0xFF),
01453             ((header.pf.fourcc >> 16) & 0xFF),
01454             ((header.pf.fourcc >> 24) & 0xFF), 
01455             header.pf.fourcc);
01456     }
01457 
01458     if ((header.pf.flags & DDPF_FOURCC) && (header.pf.bitcount != 0))
01459     {
01460         printf("\tSwizzle: '%c%c%c%c' (0x%.8X)\n", 
01461             (header.pf.bitcount >> 0) & 0xFF,
01462             (header.pf.bitcount >> 8) & 0xFF,
01463             (header.pf.bitcount >> 16) & 0xFF,
01464             (header.pf.bitcount >> 24) & 0xFF,
01465             header.pf.bitcount);
01466     }
01467     else
01468     {
01469         printf("\tBit count: %u\n", header.pf.bitcount);
01470     }
01471 
01472     printf("\tRed mask: 0x%.8X\n", header.pf.rmask);
01473     printf("\tGreen mask: 0x%.8X\n", header.pf.gmask);
01474     printf("\tBlue mask: 0x%.8X\n", header.pf.bmask);
01475     printf("\tAlpha mask: 0x%.8X\n", header.pf.amask);
01476 
01477     printf("Caps:\n");
01478     printf("\tCaps 1: 0x%.8X\n", header.caps.caps1);
01479     if (header.caps.caps1 & DDSCAPS_COMPLEX) printf("\t\tDDSCAPS_COMPLEX\n");
01480     if (header.caps.caps1 & DDSCAPS_TEXTURE) printf("\t\tDDSCAPS_TEXTURE\n");
01481     if (header.caps.caps1 & DDSCAPS_MIPMAP) printf("\t\tDDSCAPS_MIPMAP\n");
01482 
01483     printf("\tCaps 2: 0x%.8X\n", header.caps.caps2);
01484     if (header.caps.caps2 & DDSCAPS2_VOLUME) printf("\t\tDDSCAPS2_VOLUME\n");
01485     else if (header.caps.caps2 & DDSCAPS2_CUBEMAP)
01486     {
01487         printf("\t\tDDSCAPS2_CUBEMAP\n");
01488         if ((header.caps.caps2 & DDSCAPS2_CUBEMAP_ALL_FACES) == DDSCAPS2_CUBEMAP_ALL_FACES) printf("\t\tDDSCAPS2_CUBEMAP_ALL_FACES\n");
01489         else {
01490             if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEX) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEX\n");
01491             if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEX\n");
01492             if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEY) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEY\n");
01493             if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEY\n");
01494             if (header.caps.caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_POSITIVEZ\n");
01495             if (header.caps.caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ) printf("\t\tDDSCAPS2_CUBEMAP_NEGATIVEZ\n");
01496         }
01497     }
01498 
01499     printf("\tCaps 3: 0x%.8X\n", header.caps.caps3);
01500     printf("\tCaps 4: 0x%.8X\n", header.caps.caps4);
01501 
01502     if (header.hasDX10Header())
01503     {
01504         printf("DX10 Header:\n");
01505         printf("\tDXGI Format: %u (%s)\n", header.header10.dxgiFormat, getDxgiFormatString((DXGI_FORMAT)header.header10.dxgiFormat));
01506         printf("\tResource dimension: %u (%s)\n", header.header10.resourceDimension, getD3d10ResourceDimensionString((D3D10_RESOURCE_DIMENSION)header.header10.resourceDimension));
01507         printf("\tMisc flag: %u\n", header.header10.miscFlag);
01508         printf("\tArray size: %u\n", header.header10.arraySize);
01509     }
01510     
01511     if (header.reserved[9] == FOURCC_NVTT)
01512     {
01513         int major = (header.reserved[10] >> 16) & 0xFF;
01514         int minor = (header.reserved[10] >> 8) & 0xFF;
01515         int revision= header.reserved[10] & 0xFF;
01516         
01517         printf("Version:\n");
01518         printf("\tNVIDIA Texture Tools %d.%d.%d\n", major, minor, revision);
01519     }
01520 
01521     if (header.reserved[7] == FOURCC_UVER)
01522     {
01523         printf("User Version: %u\n", header.reserved[8]);
01524     }
01525 }
01526