Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreDDSCodec.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 22.0 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4(Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29
30#include "OgreStableHeaders.h"
31
32#include "OgreRoot.h"
33#include "OgreRenderSystem.h"
34#include "OgreDDSCodec.h"
35#include "OgreImage.h"
36#include "OgreException.h"
37
38#include "OgreLogManager.h"
39#include "OgreStringConverter.h"
40
41
42namespace Ogre {
43        // Internal DDS structure definitions
44#define FOURCC(c0, c1, c2, c3) (c0 | (c1 << 8) | (c2 << 16) | (c3 << 24))
45       
46#if OGRE_COMPILER == OGRE_COMPILER_MSVC
47#pragma pack (push, 1)
48#else
49#pragma pack (1)
50#endif
51
52        // Nested structure
53        struct DDSPixelFormat
54        {
55                uint32 size;
56                uint32 flags;
57                uint32 fourCC;
58                uint32 rgbBits;
59                uint32 redMask;
60                uint32 greenMask;
61                uint32 blueMask;
62                uint32 alphaMask;
63        };
64       
65        // Nested structure
66        struct DDSCaps
67        {
68                uint32 caps1;
69                uint32 caps2;
70                uint32 reserved[2];
71        };
72        // Main header, note preceded by 'DDS '
73        struct DDSHeader
74        {
75                uint32 size;           
76                uint32 flags;
77                uint32 height;
78                uint32 width;
79                uint32 sizeOrPitch;
80                uint32 depth;
81                uint32 mipMapCount;
82                uint32 reserved1[11];
83                DDSPixelFormat pixelFormat;
84                DDSCaps caps;
85                uint32 reserved2;
86        };
87
88        // An 8-byte DXT colour block, represents a 4x4 texel area. Used by all DXT formats
89        struct DXTColourBlock
90        {
91                // 2 colour ranges
92                uint16 colour_0;
93                uint16 colour_1;
94                // 16 2-bit indexes, each byte here is one row
95                uint8 indexRow[4];
96        };
97        // An 8-byte DXT explicit alpha block, represents a 4x4 texel area. Used by DXT2/3
98        struct DXTExplicitAlphaBlock
99        {
100                // 16 4-bit values, each 16-bit value is one row
101                uint16 alphaRow[4];
102        };
103        // An 8-byte DXT interpolated alpha block, represents a 4x4 texel area. Used by DXT4/5
104        struct DXTInterpolatedAlphaBlock
105        {
106                // 2 alpha ranges
107                uint8 alpha_0;
108                uint8 alpha_1;
109                // 16 3-bit indexes. Unfortunately 3 bits doesn't map too well to row bytes
110                // so just stored raw
111                uint8 indexes[6];
112        };
113       
114#if OGRE_COMPILER == OGRE_COMPILER_MSVC
115#pragma pack (pop)
116#else
117#pragma pack ()
118#endif
119
120        const uint32 DDS_PIXELFORMAT_SIZE = 8 * sizeof(uint32);
121        const uint32 DDS_CAPS_SIZE = 4 * sizeof(uint32);
122        const uint32 DDS_HEADER_SIZE = 19 * sizeof(uint32) + DDS_PIXELFORMAT_SIZE + DDS_CAPS_SIZE;
123
124        const uint32 DDSD_CAPS = 0x00000001;
125        const uint32 DDSD_HEIGHT = 0x00000002;
126        const uint32 DDSD_WIDTH = 0x00000004;
127        const uint32 DDSD_PITCH = 0x00000008;
128        const uint32 DDSD_PIXELFORMAT = 0x00001000;
129        const uint32 DDSD_MIPMAPCOUNT = 0x00020000;
130        const uint32 DDSD_LINEARSIZE = 0x00080000;
131        const uint32 DDSD_DEPTH = 0x00800000;
132        const uint32 DDPF_ALPHAPIXELS = 0x00000001;
133        const uint32 DDPF_FOURCC = 0x00000004;
134        const uint32 DDPF_RGB = 0x00000040;
135        const uint32 DDSCAPS_COMPLEX = 0x00000008;
136        const uint32 DDSCAPS_TEXTURE = 0x00001000;
137        const uint32 DDSCAPS_MIPMAP = 0x00400000;
138        const uint32 DDSCAPS2_CUBEMAP = 0x00000200;
139        const uint32 DDSCAPS2_CUBEMAP_POSITIVEX = 0x00000400;
140        const uint32 DDSCAPS2_CUBEMAP_NEGATIVEX = 0x00000800;
141        const uint32 DDSCAPS2_CUBEMAP_POSITIVEY = 0x00001000;
142        const uint32 DDSCAPS2_CUBEMAP_NEGATIVEY = 0x00002000;
143        const uint32 DDSCAPS2_CUBEMAP_POSITIVEZ = 0x00004000;
144        const uint32 DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x00008000;
145        const uint32 DDSCAPS2_VOLUME = 0x00200000;
146
147        // Special FourCC codes
148        const uint32 D3DFMT_R16F                        = 111;
149        const uint32 D3DFMT_G16R16F                     = 112;
150        const uint32 D3DFMT_A16B16G16R16F       = 113;
151        const uint32 D3DFMT_R32F            = 114;
152        const uint32 D3DFMT_G32R32F         = 115;
153        const uint32 D3DFMT_A32B32G32R32F   = 116;
154
155
156        //---------------------------------------------------------------------
157        DDSCodec* DDSCodec::msInstance = 0;
158        //---------------------------------------------------------------------
159        void DDSCodec::startup(void)
160        {
161                if (!msInstance)
162                {
163
164                        LogManager::getSingleton().logMessage(
165                                LML_NORMAL,
166                                "DDS codec registering");
167
168                        msInstance = new DDSCodec();
169                        Codec::registerCodec(msInstance);
170                }
171
172        }
173        //---------------------------------------------------------------------
174        void DDSCodec::shutdown(void)
175        {
176                if(msInstance)
177                {
178                        Codec::unRegisterCodec(msInstance);
179                        delete msInstance;
180                        msInstance = 0;
181                }
182
183        }
184        //---------------------------------------------------------------------
185    DDSCodec::DDSCodec():
186        mType("dds")
187    { 
188    }
189    //---------------------------------------------------------------------
190    DataStreamPtr DDSCodec::code(MemoryDataStreamPtr& input, Codec::CodecDataPtr& pData) const
191    {       
192                OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
193                        "DDS encoding not supported",
194                        "DDSCodec::code" ) ;
195    }
196    //---------------------------------------------------------------------
197    void DDSCodec::codeToFile(MemoryDataStreamPtr& input, 
198        const String& outFileName, Codec::CodecDataPtr& pData) const
199    {
200                OGRE_EXCEPT(Exception::ERR_NOT_IMPLEMENTED,
201                        "DDS encoding not supported",
202                        "DDSCodec::codeToFile" ) ;
203    }
204        //---------------------------------------------------------------------
205        PixelFormat DDSCodec::convertFourCCFormat(uint32 fourcc) const
206        {
207                // convert dxt pixel format
208                switch(fourcc)
209                {
210                case FOURCC('D','X','T','1'):
211                        return PF_DXT1;
212                case FOURCC('D','X','T','2'):
213                        return PF_DXT2;
214                case FOURCC('D','X','T','3'):
215                        return PF_DXT3;
216                case FOURCC('D','X','T','4'):
217                        return PF_DXT4;
218                case FOURCC('D','X','T','5'):
219                        return PF_DXT5;
220                case D3DFMT_R16F:
221                        return PF_FLOAT16_R;
222                case D3DFMT_G16R16F:
223                        return PF_FLOAT16_GR;
224                case D3DFMT_A16B16G16R16F:
225                        return PF_FLOAT16_RGBA;
226                case D3DFMT_R32F:
227                        return PF_FLOAT32_R;
228                case D3DFMT_G32R32F:
229                        return PF_FLOAT32_GR;
230                case D3DFMT_A32B32G32R32F:
231                        return PF_FLOAT32_RGBA;
232                // We could support 3Dc here, but only ATI cards support it, not nVidia
233                default:
234                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
235                                "Unsupported FourCC format found in DDS file", 
236                                "DDSCodec::decode");
237                };
238
239        }
240        //---------------------------------------------------------------------
241        PixelFormat DDSCodec::convertPixelFormat(uint32 rgbBits, uint32 rMask, 
242                uint32 gMask, uint32 bMask, uint32 aMask) const
243        {
244                // General search through pixel formats
245                for (int i = PF_UNKNOWN + 1; i < PF_COUNT; ++i)
246                {
247                        PixelFormat pf = static_cast<PixelFormat>(i);
248                        if (PixelUtil::getNumElemBits(pf) == rgbBits)
249                        {
250                                uint32 testMasks[4];
251                                PixelUtil::getBitMasks(pf, testMasks);
252                                int testBits[4];
253                                PixelUtil::getBitDepths(pf, testBits);
254                                if (testMasks[0] == rMask && testMasks[1] == gMask &&
255                                        testMasks[2] == bMask && 
256                                        // for alpha, deal with 'X8' formats by checking bit counts
257                                        (testMasks[3] == aMask || (aMask == 0 && testBits[3] == 0)))
258                                {
259                                        return pf;
260                                }
261                        }
262
263                }
264
265                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "Cannot determine pixel format",
266                        "DDSCodec::convertPixelFormat");
267
268        }
269        //---------------------------------------------------------------------
270        void DDSCodec::unpackDXTColour(PixelFormat pf, const DXTColourBlock& block, 
271                ColourValue* pCol) const
272        {
273                // Note - we assume all values have already been endian swapped
274
275                // Colour lookup table
276                ColourValue derivedColours[4];
277
278                if (pf == PF_DXT1 && block.colour_0 <= block.colour_1)
279                {
280                        // 1-bit alpha
281                        PixelUtil::unpackColour(&(derivedColours[0]), PF_R5G6B5, &(block.colour_0));
282                        PixelUtil::unpackColour(&(derivedColours[1]), PF_R5G6B5, &(block.colour_1));
283                        // one intermediate colour, half way between the other two
284                        derivedColours[2] = (derivedColours[0] + derivedColours[1]) / 2;
285                        // transparent colour
286                        derivedColours[3] = ColourValue::ZERO;
287                }
288                else
289                {
290                        PixelUtil::unpackColour(&(derivedColours[0]), PF_R5G6B5, &(block.colour_0));
291                        PixelUtil::unpackColour(&(derivedColours[1]), PF_R5G6B5, &(block.colour_1));
292                        // first interpolated colour, 1/3 of the way along
293                        derivedColours[2] = (2 * derivedColours[0] + derivedColours[1]) / 3;
294                        // second interpolated colour, 2/3 of the way along
295                        derivedColours[3] = (derivedColours[0] + 2 * derivedColours[1]) / 3;
296                }
297
298                // Process 4x4 block of texels
299                for (size_t row = 0; row < 4; ++row)
300                {
301                        for (size_t x = 0; x < 4; ++x)
302                        {
303                                // LSB come first
304                                uint8 colIdx = static_cast<uint8>(block.indexRow[row] >> (x * 2) & 0x3);
305                                if (pf == PF_DXT1)
306                                {
307                                        // Overwrite entire colour
308                                        pCol[(row * 4) + x] = derivedColours[colIdx];
309                                }
310                                else
311                                {
312                                        // alpha has already been read (alpha precedes colour)
313                                        ColourValue& col = pCol[(row * 4) + x];
314                                        col.r = derivedColours[colIdx].r;
315                                        col.g = derivedColours[colIdx].g;
316                                        col.b = derivedColours[colIdx].b;
317                                }
318                        }
319
320                }
321
322
323        }
324        //---------------------------------------------------------------------
325        void DDSCodec::unpackDXTAlpha(
326                const DXTExplicitAlphaBlock& block, ColourValue* pCol) const
327        {
328                // Note - we assume all values have already been endian swapped
329               
330                // This is an explicit alpha block, 4 bits per pixel, LSB first
331                for (size_t row = 0; row < 4; ++row)
332                {
333                        for (size_t x = 0; x < 4; ++x)
334                        {
335                                // Shift and mask off to 4 bits
336                                uint8 val = static_cast<uint8>(block.alphaRow[row] >> (x * 4) & 0xF);
337                                // Convert to [0,1]
338                                pCol->a = (Real)val / (Real)0xF;
339                                pCol++;
340                               
341                        }
342                       
343                }
344
345        }
346        //---------------------------------------------------------------------
347        void DDSCodec::unpackDXTAlpha(
348                const DXTInterpolatedAlphaBlock& block, ColourValue* pCol) const
349        {
350                // 8 derived alpha values to be indexed
351                Real derivedAlphas[8];
352
353                // Explicit extremes
354                derivedAlphas[0] = block.alpha_0 / (Real)0xFF;
355                derivedAlphas[1] = block.alpha_1 / (Real)0xFF;
356               
357               
358                if (block.alpha_0 <= block.alpha_1)
359                {
360                        // 4 interpolated alphas, plus zero and one                     
361                        // full range including extremes at [0] and [5]
362                        // we want to fill in [1] through [4] at weights ranging
363                        // from 1/5 to 4/5
364                        Real denom = 1.0f / 5.0f;
365                        for (size_t i = 0; i < 4; ++i) 
366                        {
367                                Real factor0 = (4 - i) * denom;
368                                Real factor1 = (i + 1) * denom;
369                                derivedAlphas[i + 2] = 
370                                        (factor0 * block.alpha_0) + (factor1 * block.alpha_1);
371                        }
372                        derivedAlphas[6] = 0.0f;
373                        derivedAlphas[7] = 1.0f;
374
375                }
376                else
377                {
378                        // 6 interpolated alphas
379                        // full range including extremes at [0] and [7]
380                        // we want to fill in [1] through [6] at weights ranging
381                        // from 1/7 to 6/7
382                        Real denom = 1.0f / 7.0f;
383                        for (size_t i = 0; i < 6; ++i) 
384                        {
385                                Real factor0 = (6 - i) * denom;
386                                Real factor1 = (i + 1) * denom;
387                                derivedAlphas[i + 2] = 
388                                        (factor0 * block.alpha_0) + (factor1 * block.alpha_1);
389                        }
390                       
391                }
392
393                // Ok, now we've built the reference values, process the indexes
394                for (size_t i = 0; i < 16; ++i)
395                {
396                        size_t baseByte = (i * 3) / 8;
397                        size_t baseBit = (i * 3) % 8;
398                        uint8 bits = static_cast<uint8>(block.indexes[baseByte] >> baseBit & 0x7);
399                        // do we need to stitch in next byte too?
400                        if (baseBit > 5)
401                        {
402                                uint8 extraBits = static_cast<uint8>(
403                                        (block.indexes[baseByte+1] << (8 - baseBit)) & 0xFF);
404                                bits |= extraBits & 0x7;
405                        }
406                        pCol[i].a = derivedAlphas[bits];
407
408                }
409
410        }
411    //---------------------------------------------------------------------
412    Codec::DecodeResult DDSCodec::decode(DataStreamPtr& stream) const
413    {
414                // Read 4 character code
415                uint32 fileType;
416                stream->read(&fileType, sizeof(uint32));
417                flipEndian(&fileType, sizeof(uint32), 1);
418               
419                if (FOURCC('D', 'D', 'S', ' ') != fileType)
420                {
421                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
422                                "This is not a DDS file!", "DDSCodec::decode");
423                }
424               
425                // Read header in full
426                DDSHeader header;
427                stream->read(&header, sizeof(DDSHeader));
428
429                // Endian flip if required, all 32-bit values
430                flipEndian(&header, 4, sizeof(DDSHeader) / 4);
431
432                // Check some sizes
433                if (header.size != DDS_HEADER_SIZE)
434                {
435                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
436                                "DDS header size mismatch!", "DDSCodec::decode");
437                }
438                if (header.pixelFormat.size != DDS_PIXELFORMAT_SIZE)
439                {
440                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, 
441                                "DDS header size mismatch!", "DDSCodec::decode");
442                }
443
444                ImageData* imgData = new ImageData();
445                MemoryDataStreamPtr output;
446
447                imgData->depth = 1; // (deal with volume later)
448                imgData->width = header.width;
449                imgData->height = header.height;
450                size_t numFaces = 1; // assume one face until we know otherwise
451
452                if (header.caps.caps1 & DDSCAPS_MIPMAP)
453                {
454                imgData->num_mipmaps = header.mipMapCount - 1;
455                }
456                else
457                {
458                        imgData->num_mipmaps = 0;
459                }
460                imgData->flags = 0;
461
462                bool decompressDXT = false;
463                // Figure out basic image type
464                if (header.caps.caps2 & DDSCAPS2_CUBEMAP)
465                {
466                        imgData->flags |= IF_CUBEMAP;
467                        numFaces = 6;
468                }
469                else if (header.caps.caps2 & DDSCAPS2_VOLUME)
470                {
471                        imgData->flags |= IF_3D_TEXTURE;
472                        imgData->depth = header.depth;
473                }
474                // Pixel format
475                PixelFormat sourceFormat = PF_UNKNOWN;
476
477                if (header.pixelFormat.flags & DDPF_FOURCC)
478                {
479                        sourceFormat = convertFourCCFormat(header.pixelFormat.fourCC);
480                }
481                else
482                {
483                        sourceFormat = convertPixelFormat(header.pixelFormat.rgbBits, 
484                                header.pixelFormat.redMask, header.pixelFormat.greenMask, 
485                                header.pixelFormat.blueMask, 
486                                header.pixelFormat.flags & DDPF_ALPHAPIXELS ? 
487                                header.pixelFormat.alphaMask : 0);
488                }
489
490                if (PixelUtil::isCompressed(sourceFormat))
491                {
492                        if (!Root::getSingleton().getRenderSystem()->getCapabilities()
493                                ->hasCapability(RSC_TEXTURE_COMPRESSION_DXT))
494                        {
495                                // We'll need to decompress
496                                decompressDXT = true;
497                                // Convert format
498                                switch (sourceFormat)
499                                {
500                                case PF_DXT1:
501                                        // source can be either 565 or 5551 depending on whether alpha present
502                                        // unfortunately you have to read a block to figure out which
503                                        // Note that we upgrade to 32-bit pixel formats here, even
504                                        // though the source is 16-bit; this is because the interpolated
505                                        // values will benefit from the 32-bit results, and the source
506                                        // from which the 16-bit samples are calculated may have been
507                                        // 32-bit so can benefit from this.
508                                        DXTColourBlock block;
509                                        stream->read(&block, sizeof(DXTColourBlock));
510                                        flipEndian(&(block.colour_0), sizeof(uint16), 1);
511                                        flipEndian(&(block.colour_1), sizeof(uint16), 1);
512                                        // skip back since we'll need to read this again
513                                        stream->skip(0 - sizeof(DXTColourBlock));
514                                        // colour_0 <= colour_1 means transparency in DXT1
515                                        if (block.colour_0 <= block.colour_1)
516                                        {
517                                                imgData->format = PF_BYTE_RGBA;
518                                        }
519                                        else
520                                        {
521                                                imgData->format = PF_BYTE_RGB;
522                                        }
523                                        break;
524                                case PF_DXT2:
525                                case PF_DXT3:
526                                case PF_DXT4:
527                                case PF_DXT5:
528                                        // full alpha present, formats vary only in encoding
529                                        imgData->format = PF_BYTE_RGBA;
530                                        break;
531                default:
532                    // all other cases need no special format handling
533                    break;
534                                }
535                        }
536                        else
537                        {
538                                // Use original format
539                                imgData->format = sourceFormat;
540                                // Keep DXT data compressed
541                                imgData->flags |= IF_COMPRESSED;
542                        }
543                }
544                else // not compressed
545                {
546                        // Don't test against DDPF_RGB since greyscale DDS doesn't set this
547                        // just derive any other kind of format
548                        imgData->format = sourceFormat;
549                }
550
551                // Calculate total size from number of mipmaps, faces and size
552                imgData->size = Image::calculateSize(imgData->num_mipmaps, numFaces, 
553                        imgData->width, imgData->height, imgData->depth, imgData->format);
554
555                // Bind output buffer
556                output.bind(new MemoryDataStream(imgData->size));
557
558               
559                // Now deal with the data
560                void* destPtr = output->getPtr();
561
562                // all mips for a face, then each face
563                for(size_t i = 0; i < numFaces; ++i)
564                {   
565                        size_t width = imgData->width;
566                        size_t height = imgData->height;
567                        size_t depth = imgData->depth;
568
569                        for(size_t mip = 0; mip <= imgData->num_mipmaps; ++mip)
570                        {
571                                size_t dstPitch = width * PixelUtil::getNumElemBytes(imgData->format);
572
573                                if (PixelUtil::isCompressed(sourceFormat))
574                                {
575                                        // Compressed data
576                                        if (decompressDXT)
577                                        {
578                                                DXTColourBlock col;
579                                                DXTInterpolatedAlphaBlock iAlpha;
580                                                DXTExplicitAlphaBlock eAlpha;
581                                                // 4x4 block of decompressed colour
582                                                ColourValue tempColours[16];
583                                                size_t destBpp = PixelUtil::getNumElemBytes(imgData->format);
584                                                size_t destPitchMinus4 = dstPitch - destBpp * 4;
585                                                // slices are done individually
586                                                for(size_t z = 0; z < depth; ++z)
587                                                {
588                                                        // 4x4 blocks in x/y
589                                                        for (size_t y = 0; y < height; y += 4)
590                                                        {
591                                                                for (size_t x = 0; x < width; x += 4)
592                                                                {
593                                                                        if (sourceFormat == PF_DXT2 || 
594                                                                                sourceFormat == PF_DXT3)
595                                                                        {
596                                                                                // explicit alpha
597                                                                                stream->read(&eAlpha, sizeof(DXTExplicitAlphaBlock));
598                                                                                flipEndian(eAlpha.alphaRow, sizeof(uint16), 4);
599                                                                                unpackDXTAlpha(eAlpha, tempColours) ;
600                                                                        }
601                                                                        else if (sourceFormat == PF_DXT4 || 
602                                                                                sourceFormat == PF_DXT5)
603                                                                        {
604                                                                                // interpolated alpha
605                                                                                stream->read(&iAlpha, sizeof(DXTInterpolatedAlphaBlock));
606                                                                                flipEndian(&(iAlpha.alpha_0), sizeof(uint16), 1);
607                                                                                flipEndian(&(iAlpha.alpha_1), sizeof(uint16), 1);
608                                                                                unpackDXTAlpha(iAlpha, tempColours) ;
609                                                                        }
610                                                                        // always read colour
611                                                                        stream->read(&col, sizeof(DXTColourBlock));
612                                                                        flipEndian(&(col.colour_0), sizeof(uint16), 1);
613                                                                        flipEndian(&(col.colour_1), sizeof(uint16), 1);
614                                                                        unpackDXTColour(sourceFormat, col, tempColours);
615
616                                                                        // write 4x4 block to uncompressed version
617                                                                        for (size_t by = 0; by < 4; ++by)
618                                                                        {
619                                                                                for (size_t bx = 0; bx < 4; ++bx)
620                                                                                {
621                                                                                        PixelUtil::packColour(tempColours[by*4+bx],
622                                                                                                imgData->format, destPtr);
623                                                                                        destPtr = static_cast<void*>(
624                                                                                                static_cast<uchar*>(destPtr) + destBpp);
625                                                                                }
626                                                                                // advance to next row
627                                                                                destPtr = static_cast<void*>(
628                                                                                        static_cast<uchar*>(destPtr) + destPitchMinus4);
629                                                                        }
630                                                                        // next block. Our dest pointer is 4 lines down
631                                                                        // from where it started
632                                                                        if (x + 4 == width)
633                                                                        {
634                                                                                // Jump back to the start of the line
635                                                                                destPtr = static_cast<void*>(
636                                                                                        static_cast<uchar*>(destPtr) - destPitchMinus4);
637                                                                        }
638                                                                        else
639                                                                        {
640                                                                                // Jump back up 4 rows and 4 pixels to the
641                                                                                // right to be at the next block to the right
642                                                                                destPtr = static_cast<void*>(
643                                                                                        static_cast<uchar*>(destPtr) - dstPitch * 4 + destBpp * 4);
644
645                                                                        }
646
647                                                                }
648
649                                                        }
650                                                }
651
652                                        }
653                                        else
654                                        {
655                                                // load directly
656                                                // DDS format lies! sizeOrPitch is not always set for DXT!!
657                                                size_t dxtSize = PixelUtil::getMemorySize(width, height, depth, imgData->format);
658                                                stream->read(destPtr, dxtSize);
659                                                destPtr = static_cast<void*>(static_cast<uchar*>(destPtr) + dxtSize);
660                                        }
661
662                                }
663                                else
664                                {
665                                        // Final data - trim incoming pitch
666                                        size_t srcPitch;
667                                        if (header.flags & DDSD_PITCH)
668                                        {
669                                                srcPitch = header.sizeOrPitch / 
670                                                        std::max((size_t)1, mip * 2);
671                                        }
672                                        else
673                                        {
674                                                // assume same as final pitch
675                                                srcPitch = dstPitch;
676                                        }
677                                        assert (dstPitch <= srcPitch);
678                                        long srcAdvance = static_cast<long>(srcPitch) - static_cast<long>(dstPitch);
679
680                                        for (size_t z = 0; z < imgData->depth; ++z)
681                                        {
682                                                for (size_t y = 0; y < imgData->height; ++y)
683                                                {
684                                                        stream->read(destPtr, dstPitch);
685                                                        if (srcAdvance > 0)
686                                                                stream->skip(srcAdvance);
687
688                                                        destPtr = static_cast<void*>(static_cast<uchar*>(destPtr) + dstPitch);
689                                                }
690                                        }
691
692                                }
693
694                               
695                                /// Next mip
696                                if(width!=1) width /= 2;
697                                if(height!=1) height /= 2;
698                                if(depth!=1) depth /= 2;
699                        }
700
701                }
702
703                DecodeResult ret;
704                ret.first = output;
705                ret.second = CodecDataPtr(imgData);
706                return ret;
707               
708
709
710    }
711    //---------------------------------------------------------------------   
712    String DDSCodec::getType() const 
713    {
714        return mType;
715    }
716    //---------------------------------------------------------------------   
717    void DDSCodec::flipEndian(void * pData, size_t size, size_t count) const
718    {
719#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
720                for(unsigned int index = 0; index < count; index++)
721        {
722            flipEndian((void *)((long)pData + (index * size)), size);
723        }
724#endif
725    }
726    //---------------------------------------------------------------------   
727    void DDSCodec::flipEndian(void * pData, size_t size) const
728    {
729#if OGRE_ENDIAN == OGRE_ENDIAN_BIG
730        char swapByte;
731        for(unsigned int byteIndex = 0; byteIndex < size/2; byteIndex++)
732        {
733            swapByte = *(char *)((long)pData + byteIndex);
734            *(char *)((long)pData + byteIndex) = *(char *)((long)pData + size - byteIndex - 1);
735            *(char *)((long)pData + size - byteIndex - 1) = swapByte;
736        }
737#endif
738    }
739       
740}
741
Note: See TracBrowser for help on using the repository browser.