Blender V2.61 - r43446
|
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