|
Blender
V2.59
|
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