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