1 /*---------------------------------------------------------------------------*\
5 * Copyright (C) 2000-2002 by the OpenSG Forum *
9 * contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de *
11 \*---------------------------------------------------------------------------*/
12 /*---------------------------------------------------------------------------*\
15 * This library is free software; you can redistribute it and/or modify it *
16 * under the terms of the GNU Library General Public License as published *
17 * by the Free Software Foundation, version 2. *
19 * This library is distributed in the hope that it will be useful, but *
20 * WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
22 * Library General Public License for more details. *
24 * You should have received a copy of the GNU Library General Public *
25 * License along with this library; if not, write to the Free Software *
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
28 \*---------------------------------------------------------------------------*/
29 /*---------------------------------------------------------------------------*\
37 \*---------------------------------------------------------------------------*/
38 //-------------------------------
40 //-------------------------------
46 #include "OSGConfig.h"
58 #include "OSGDDSImageFileType.h"
64 #define INT_MAX numeric_limits<Int32>::max()
70 // Static Class Varible implementations:
71 static const OSG::Char8
*suffixArray
[] =
78 /*! \class DDSImageFileType
80 Image File Type to read/write and store/restore Image objects as
81 DDS data. Should work with binary and ascii dds/pbm/pgm/ppm data.
83 All the type specific code is included in the class. Does
84 not depend on external libs.
88 DDSImageFileType
DDSImageFileType::_the("image/x-dds",
92 OSG_WRITE_SUPPORTED
));
98 const UInt32 DDS_DDPF_ALPHAPIXELS
= 0x00000001;
99 const UInt32 DDS_DDPF_ALPHA
= 0x00000002;
100 const UInt32 DDS_DDPF_FOURCC
= 0x00000004;
101 const UInt32 DDS_DDPF_RGB
= 0x00000040;
102 const UInt32 DDS_DDPF_YUV
= 0x00000200;
103 const UInt32 DDS_DDPF_LUMINANCE
= 0x00020000;
104 const UInt32 DDS_DDPF_OPENGL
= 0x00200000;
105 const UInt32 DDS_DDPF_OPENGL_NV
= 0x00600000;
106 const UInt32 DDS_DDPF_OPENGL_STD
= 0x00A00000;
107 const UInt32 DDS_DDPF_RGBA
= 0x00000041;
109 const UInt32 DDS_CAPS_COMPLEX
= 0x00000008;
111 const UInt32 DDS_CAPS2_CUBEMAP
= 0x00000200;
112 const UInt32 DDS_CAPS2_VOLUME
= 0x00200000;
115 const UInt32 FOURCC_DXT1
= 0x31545844;
116 const UInt32 FOURCC_DXT3
= 0x33545844;
117 const UInt32 FOURCC_DXT5
= 0x35545844;
119 //const UInt32 DDS_DEPTH = 0x00800000;
120 //const UInt32 DDS_COMPRESSED = 0x00000080;
125 struct DDS_PIXELFORMAT
130 UInt32 dwRGBBitCount
;
151 struct DXT3AlphaBlock
159 struct DXT5AlphaBlock
176 UInt32 dwPitchOrLinearSize
;
178 UInt32 dwMipMapCount
;
179 UInt32 dwReserved1
[11];
180 DDS_PIXELFORMAT ddspf
;
183 UInt32 dwReserved2
[3];
191 friend class CTexture
;
192 friend class CDDSImage
;
197 CSurface(Int32 w
, Int32 h
, Int32 d
, Int32 imgsize
);
198 CSurface(const CSurface
©
);
199 CSurface
&operator= (const CSurface
&rhs
);
202 // operator char *();
204 void create(Int32 w
, Int32 h
, Int32 d
, Int32 imgsize
);
207 Int32
get_width () { return width
; }
208 Int32
get_height() { return height
; }
209 Int32
get_depth () { return depth
; }
210 Int32
get_size () { return size
; }
211 char* get_pixels() { return pixels
; }
213 void swapPixels(CSurface
&other
);
228 class CTexture
: public CSurface
230 friend class CDDSImage
;
235 CTexture(Int32 w
, Int32 h
, Int32 d
, Int32 imgSize
);
236 CTexture(const CTexture
©
);
237 CTexture
&operator= (const CTexture
&rhs
);
240 CSurface
&get_mipmap(Int32 index
)
242 assert(index
< Int32(mipmaps
.size()));
243 return mipmaps
[index
];
246 int get_num_mipmaps() { return Int32(mipmaps
.size()); }
249 std::vector
<CSurface
> mipmaps
;
261 bool load(std::istream
&is
,
262 bool flipImage
= true,
263 bool swapCubeMap
= true,
264 bool flipCubeMap
= false);
268 CTexture
&operator[](Int32 index
);
270 Int32
get_num_images(void) { return Int32(images
.size()); }
271 CTexture
&get_image(Int32 index
)
273 assert(index
< Int32(images
.size()));
274 return images
[index
];
277 Int32
get_components() { return components
; }
278 Int32
get_format () { return format
; }
280 bool is_compressed() { return compressed
; }
281 bool is_cubemap() { return cubemap
; }
282 bool is_volume() { return volume
; }
283 bool is_valid() { return valid
; }
287 Int32
clamp_size(Int32 size
);
288 Int32
get_line_width(Int32 width
, Int32 bpp
);
289 Int32
size_dxtc(Int32 width
, Int32 height
);
290 Int32
size_rgb(Int32 width
, Int32 height
);
291 void swap_endian(void *val
);
292 void align_memory(CTexture
*surface
);
294 void flip (CSurface
&image
,
295 Int32 width
, Int32 height
, Int32 depth
,
296 Int32 size
, UInt32 ddpfFlags
);
297 bool check_dxt1_alpha_data (char *image
, Int32 size
);
299 void swap(void *byte1
, void *byte2
, Int32 size
);
301 void flip_blocks_dxtc1(DXTColBlock
*line
, Int32 numBlocks
);
302 void flip_blocks_dxtc3(DXTColBlock
*line
, Int32 numBlocks
);
303 void flip_blocks_dxtc5(DXTColBlock
*line
, Int32 numBlocks
);
304 void flip_dxt5_alpha(DXT5AlphaBlock
*block
);
306 void flipDXT (CSurface
&image
,
307 Int32 width
, Int32 height
, Int32 depth
,
310 void flipDXTStdToNV(CSurface
&image
,
311 Int32 width
, Int32 height
, Int32 depth
,
314 void changeLayout (CSurface
&image
,
315 Int32 width
, Int32 height
, Int32 depth
,
316 Int32 size
, bool bNVToStd
);
325 std::vector
<CTexture
> images
;
329 void DDSImageFileType::setFlipImage(bool s
)
334 bool DDSImageFileType::getFlipImage(void)
339 void DDSImageFileType::setFlipCubeMap(bool s
)
344 bool DDSImageFileType::getFlipCubeMap(void)
349 void DDSImageFileType::setSwapCubeMap(bool s
)
354 bool DDSImageFileType::getSwapCubeMap(void)
360 //-------------------------------------------------------------------------
361 /*! Tries to fill the image object with the data read from
362 the given stream. Returns true on success.
365 bool DDSImageFileType::read( Image
*pImage
,
367 const std::string
&mimetype
)
369 bool validImage
= false;
373 Int32 i
,j
,w
,h
,d
, mm
= 0, components
, format
,size
;
374 Int32 width
= 0, height
= 0, depth
= 0, numMipMaps
= 0;
375 bool isCompressed
, isCubeMap
, isVolume
;
379 SINFO
<< "DDS File Info: " << ": ";
381 if(ddsImage
.load(is
, _flipImage
, _swapCubeMap
, _flipCubeMap
) &&
382 (validImage
= ddsImage
.is_valid()))
384 components
= ddsImage
.get_components();
385 format
= ddsImage
.get_format();
386 isCompressed
= ddsImage
.is_compressed();
387 isCubeMap
= ddsImage
.is_cubemap();
388 isVolume
= ddsImage
.is_volume();
390 SINFO
<< "cs: " << components
392 << ", cd: " << isCompressed
393 << ", cm: " << isCubeMap
394 << ", vo: " << isVolume
397 for (i
= 0; i
< ddsImage
.get_num_images(); ++i
)
399 w
= ddsImage
[i
].get_width();
400 h
= ddsImage
[i
].get_height();
401 d
= ddsImage
[i
].get_depth();
402 size
= ddsImage
[i
].get_size();
406 mm
= ddsImage
[i
].get_num_mipmaps();
410 if((w
!= width
) || (h
!= height
) || (d
!= depth
) ||
425 << ", " << w
<< "x" << h
<< "x" << d
426 << ", size: " << size
430 for (j
= 0; j
< mm
; ++j
)
432 w
= ddsImage
[i
].get_mipmap(j
).get_width();
433 h
= ddsImage
[i
].get_mipmap(j
).get_height();
434 d
= ddsImage
[i
].get_mipmap(j
).get_depth();
435 size
= ddsImage
[i
].get_mipmap(j
).get_size();
439 << ", " << w
<< "x" << h
<< "x" << d
440 << ", size: " << size
449 pImage
->set( OSG::Image::PixelFormat(format
),
450 width
, height
, depth
,
452 1, 0.0, 0, OSG::Image::OSG_UINT8_IMAGEDATA
,
454 ddsImage
.get_num_images() );
456 if(dataSize
== pImage
->getSize())
458 data
= pImage
->editData();
461 for (i
= 0; i
< ddsImage
.get_num_images(); ++i
)
463 size
= ddsImage
[i
].get_size();
464 memcpy (data
, ddsImage
[i
].get_pixels(), size
);
466 for(j
= 0; j
< mm
; ++j
)
468 size
= ddsImage
[i
].get_mipmap(j
).get_size();
471 ddsImage
[i
].get_mipmap(j
).get_pixels(),
479 SWARNING
<< "ERROR: Invalid data size; cannot cp dds data"
487 SWARNING
<< "DDS Load Failed !" << endLog
;
493 //-------------------------------------------------------------------------
494 /*! Tries to write the image object to the given fileName.
495 Returns true on success.
498 bool DDSImageFileType::write(const Image
*,
502 SWARNING
<< getMimeType()
503 << " write is not implemented "
510 //-------------------------------------------------------------------------
512 Tries to determine the mime type of the data provided by an input stream
513 by searching for magic bytes. Returns the mime type or an empty string
514 when the function could not determine the mime type.
517 std::string
DDSImageFileType::determineMimetypeFromStream(std::istream
&is
)
521 is
.read(filecode
, 4);
522 is
.seekg(-4, std::ios::cur
);
524 return strncmp(filecode
, "DDS ", 4) == 0 ?
525 std::string(getMimeType()) : std::string();
528 /**constructors & destructors**/
530 //-------------------------------------------------------------------------
531 /*! Constructor used for the singleton object
534 DDSImageFileType::DDSImageFileType(const Char8
*mimeType
,
535 const Char8
*suffixArray
[],
536 UInt16 suffixByteCount
,
539 Inherited (mimeType
,suffixArray
, suffixByteCount
, flags
),
546 //-------------------------------------------------------------------------
550 DDSImageFileType::~DDSImageFileType(void)
555 ///////////////////////////////////////////////////////////////////////////////
556 // CDDSImage public functions
558 ///////////////////////////////////////////////////////////////////////////////
559 // default constructor
561 CDDSImage::CDDSImage() :
572 CDDSImage::~CDDSImage()
576 ///////////////////////////////////////////////////////////////////////////////
577 // Swap the bytes in a 32 bit value
578 inline void CDDSImage::swap_endian(void *val
)
580 #if BYTE_ORDER == BIG_ENDIAN
581 UInt32
*ival
= (UInt32
*)val
;
583 *ival
= ((*ival
>> 24) & 0x000000ff) |
584 ((*ival
>> 8) & 0x0000ff00) |
585 ((*ival
<< 8) & 0x00ff0000) |
586 ((*ival
<< 24) & 0xff000000);
590 ///////////////////////////////////////////////////////////////////////////////
591 // clamps input size to [1-size]
592 inline int CDDSImage::clamp_size(Int32 size
)
601 ///////////////////////////////////////////////////////////////////////////////
604 // filename - fully qualified name of DDS image
605 // flipImage - specifies whether image is flipped on load, default is true
607 bool CDDSImage::load(std::istream
&is
,
614 Int32 width
, height
, depth
;
615 Int32 (CDDSImage::*sizefunc
)(Int32
, Int32
);
617 // clear any previously loaded images
620 // read in file marker, make sure its a DDS file
621 is
.read(filecode
, 4);
622 if (strncmp(filecode
, "DDS ", 4) != 0)
625 // read in DDS header
626 is
.read(reinterpret_cast<char*>(&ddsh
), sizeof(ddsh
));
628 swap_endian(&ddsh
.dwSize
);
629 swap_endian(&ddsh
.dwFlags
);
630 swap_endian(&ddsh
.dwHeight
);
631 swap_endian(&ddsh
.dwWidth
);
632 swap_endian(&ddsh
.dwPitchOrLinearSize
);
633 swap_endian(&ddsh
.dwDepth
);
634 swap_endian(&ddsh
.dwMipMapCount
);
635 swap_endian(&ddsh
.ddspf
.dwSize
);
636 swap_endian(&ddsh
.ddspf
.dwFlags
);
637 swap_endian(&ddsh
.ddspf
.dwFourCC
);
638 swap_endian(&ddsh
.ddspf
.dwRGBBitCount
);
639 swap_endian(&ddsh
.dwCaps1
);
640 swap_endian(&ddsh
.dwCaps2
);
642 // check if image is a cubempa
643 if (ddsh
.dwCaps2
& DDS_CAPS2_CUBEMAP
)
646 // check if image is a volume texture
647 if ((ddsh
.dwCaps2
& DDS_CAPS2_VOLUME
) && (ddsh
.dwDepth
> 0))
650 // figure out what the image format is
651 if (ddsh
.ddspf
.dwFlags
& DDS_DDPF_FOURCC
)
653 switch(ddsh
.ddspf
.dwFourCC
)
656 format
= GL_COMPRESSED_RGB_S3TC_DXT1_EXT
;
661 format
= GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
;
666 format
= GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
;
671 SWARNING
<< "ERROR: unknown compressed format("
672 << ddsh
.ddspf
.dwFourCC
678 else if((ddsh
.ddspf
.dwFlags
& DDS_DDPF_RGBA
) == DDS_DDPF_RGBA
&& ddsh
.ddspf
.dwRGBBitCount
== 32)
680 format
= Image::OSG_BGRA_PF
;
684 else if((ddsh
.ddspf
.dwFlags
& DDS_DDPF_RGB
) == DDS_DDPF_RGB
&& ddsh
.ddspf
.dwRGBBitCount
== 32)
686 format
= Image::OSG_BGRA_PF
;
690 else if((ddsh
.ddspf
.dwFlags
& DDS_DDPF_RGB
) == DDS_DDPF_RGB
&& ddsh
.ddspf
.dwRGBBitCount
== 24)
692 format
= Image::OSG_BGR_PF
;
696 else if ((ddsh
.ddspf
.dwFlags
& DDS_DDPF_LUMINANCE
) == DDS_DDPF_LUMINANCE
&& ddsh
.ddspf
.dwRGBBitCount
== 8)
698 format
= Image::OSG_L_PF
;
704 SWARNING
<< "ERROR: unknown image format!" << endLog
;
708 // store primary surface width/height/depth
709 width
= ddsh
.dwWidth
;
710 height
= ddsh
.dwHeight
;
711 depth
= clamp_size(ddsh
.dwDepth
); // set to 1 if 0
713 // use correct size calculation function depending on whether image is
715 sizefunc
= (compressed
? &CDDSImage::size_dxtc
: &CDDSImage::size_rgb
);
717 bool doFlipImage
= false;
719 if((flipImage
&& !cubemap
) || (flipCubeMap
&& cubemap
))
722 if((ddsh
.ddspf
.dwFlags
& DDS_DDPF_OPENGL
) != 0x00000000 && volume
== false)
727 "dds status : opengl 0x%x | layout nv 0x%x "
728 "| layout std 0x%x | flip %d\n",
729 UInt32(ddsh
.ddspf
.dwFlags
& DDS_DDPF_OPENGL
),
730 UInt32((ddsh
.ddspf
.dwFlags
& DDS_DDPF_OPENGL_NV
) == DDS_DDPF_OPENGL_NV
),
731 UInt32((ddsh
.ddspf
.dwFlags
& DDS_DDPF_OPENGL_STD
) == DDS_DDPF_OPENGL_STD
),
732 UInt32(doFlipImage
));
735 // load all surfaces for the image (6 surfaces for cubemaps)
736 for(Int32 n
= 0; n
< (cubemap
? 6 : 1); n
++)
740 // calculate surface size
741 size
= (this->*sizefunc
)(width
, height
)*depth
;
744 CTexture
img(width
, height
, depth
, size
);
745 is
.read(img
.get_pixels(), img
.size
);
749 if((format
== GL_COMPRESSED_RGB_S3TC_DXT1_EXT
) &&
750 check_dxt1_alpha_data(img
.get_pixels(), img
.size
))
752 format
= GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
;
756 if(doFlipImage
== true)
758 flip(img
, img
.width
, img
.height
, img
.depth
, img
.size
, ddsh
.ddspf
.dwFlags
);
761 Int32 w
= clamp_size(width
>> 1);
762 Int32 h
= clamp_size(height
>> 1);
763 Int32 d
= clamp_size(depth
>> 1);
765 // store number of mipmaps
766 Int32 numMipmaps
= ddsh
.dwMipMapCount
;
768 // number of mipmaps in file includes main surface so decrease count
773 // load all mipmaps for current surface
774 for (Int32 i
= 0; i
< numMipmaps
&& (w
|| h
); i
++)
776 // calculate mipmap size
777 size
= (this->*sizefunc
)(w
, h
)*d
;
779 CSurface
mipmap(w
, h
, d
, size
);
780 is
.read(mipmap
.get_pixels(), mipmap
.size
);
782 if(doFlipImage
== true)
784 flip(mipmap
, mipmap
.width
, mipmap
.height
, mipmap
.depth
,
785 mipmap
.size
, ddsh
.ddspf
.dwFlags
);
788 img
.mipmaps
.push_back(mipmap
);
790 // shrink to next power of 2
791 w
= clamp_size(w
>> 1);
792 h
= clamp_size(h
>> 1);
793 d
= clamp_size(d
>> 1);
796 images
.push_back(img
);
799 // swap cubemaps on y axis (since image is flipped in OGL)
800 if (cubemap
&& swapCubeMap
)
804 images
[3] = images
[2];
813 ///////////////////////////////////////////////////////////////////////////////
816 void CDDSImage::clear()
829 ///////////////////////////////////////////////////////////////////////////////
830 // returns individual texture when multiple textures are loaded (as is the case
831 // with volume textures and cubemaps)
833 CTexture
&CDDSImage::operator[](Int32 index
)
835 // make sure an image has been loaded
837 assert(index
< Int32(images
.size()));
839 return images
[index
];
842 ///////////////////////////////////////////////////////////////////////////////
843 // returns pointer to main image
845 CDDSImage::operator char*()
854 ///////////////////////////////////////////////////////////////////////////////
855 // CDDSImage private functions
856 ///////////////////////////////////////////////////////////////////////////////
858 ///////////////////////////////////////////////////////////////////////////////
859 // calculates 4-byte aligned width of image
860 inline int CDDSImage::get_line_width(Int32 width
, Int32 bpp
)
862 return ((width
* bpp
+ 31) & -32) >> 3;
865 ///////////////////////////////////////////////////////////////////////////////
866 // calculates size of DXTC texture in bytes
867 int CDDSImage::size_dxtc(Int32 width
, Int32 height
)
869 Int32
comp( ( (format
== GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
) ||
870 (format
== GL_COMPRESSED_RGB_S3TC_DXT1_EXT
) ) ? 8 : 16 );
872 return ((width
+3)/4)*((height
+3)/4)*comp
;
875 ///////////////////////////////////////////////////////////////////////////////
876 // calculates size of uncompressed RGB texture in bytes
877 int CDDSImage::size_rgb(Int32 width
, Int32 height
)
879 return width
*height
*components
;
882 ///////////////////////////////////////////////////////////////////////////////
883 // align to 4 byte boundary (add pad bytes to end of each line in the image)
884 void CDDSImage::align_memory(CTexture
*surface
)
886 // don't bother with compressed images, volume textures, or cubemaps
887 if (compressed
|| volume
|| cubemap
)
890 // calculate new image size
891 Int32 linesize
= get_line_width(surface
->width
, components
*8);
892 Int32 imagesize
= linesize
*surface
->height
;
894 // exit if already aligned
895 if (surface
->size
== imagesize
)
898 // create new image of new size
899 CTexture
newSurface(surface
->width
, surface
->height
, surface
->depth
,
902 // add pad bytes to end of each line
903 char *srcimage
= static_cast<char*>(surface
->get_pixels());
904 char *dstimage
= static_cast<char*>(newSurface
.get_pixels());
905 for (Int32 n
= 0; n
< surface
->depth
; n
++)
907 char *curline
= srcimage
;
908 char *newline
= dstimage
;
910 Int32 imsize
= surface
->size
/ surface
->depth
;
911 Int32 lnsize
= imsize
/ surface
->height
;
913 for (Int32 i
= 0; i
< surface
->height
; i
++)
915 memcpy(newline
, curline
, lnsize
);
922 *surface
= newSurface
;
925 ///////////////////////////////////////////////////////////////////////////////
926 // flip image around X axis
927 bool CDDSImage::check_dxt1_alpha_data (char *image
, Int32 size
)
929 bool hasAlpha(false);
930 DXTColBlock
*colBlock(reinterpret_cast<DXTColBlock
*>(image
));
932 for (unsigned i
= 0, n
= (size
/ 8); i
< n
; i
++)
933 if (colBlock
[i
].col0
<= colBlock
[i
].col1
)
935 for (unsigned j
= 0; j
< 4; j
++) {
936 UInt8 byte
= colBlock
[i
].row
[j
];
937 for (unsigned p
= 0; p
< 4; p
++/*, byte >> 2*/) {
938 if ((byte
& 3) == 3) {
947 FNOTICE (( "Found alpha in DXT1 %d/%d, col0:%d, col1:%d\n",
948 i
, n
, colBlock
[i
].col0
, colBlock
[i
].col1
));
950 for (unsigned j
= 0; j
< 4; j
++)
951 FNOTICE (( " DXT Col Index: %d %d %d %d\n",
952 ((colBlock
[i
].row
[j
] >> 0) & 3),
953 ((colBlock
[i
].row
[j
] >> 2) & 3),
954 ((colBlock
[i
].row
[j
] >> 4) & 3),
955 ((colBlock
[i
].row
[j
] >> 6) & 3) ));
965 ///////////////////////////////////////////////////////////////////////////////
966 // flip image around X axis
967 void CDDSImage::flip(CSurface
&image
,
979 if((ddpfFlags
& DDS_DDPF_OPENGL
) != 0x00)
982 fprintf(stderr
, "already OpenGL data\n");
989 Int32 imagesize
= size
/depth
;
990 linesize
= imagesize
/ height
;
992 for (Int32 n
= 0; n
< depth
; n
++)
994 offset
= imagesize
* n
;
995 char *top
= image
.get_pixels() + offset
;
996 char *bottom
= top
+ (imagesize
-linesize
);
998 for (Int32 i
= 0; i
< (height
>> 1); i
++)
1000 swap(bottom
, top
, linesize
);
1011 void (CDDSImage::*flipblocks
)(DXTColBlock
*, Int32
);
1013 Int32 xblocks
= width
/ 4;
1014 Int32 yblocks
= height
/ 4;
1019 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
1021 flipblocks
= &CDDSImage::flip_blocks_dxtc1
;
1023 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
1025 flipblocks
= &CDDSImage::flip_blocks_dxtc1
;
1027 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
1029 flipblocks
= &CDDSImage::flip_blocks_dxtc3
;
1031 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
1033 flipblocks
= &CDDSImage::flip_blocks_dxtc5
;
1039 linesize
= xblocks
* blocksize
;
1042 DXTColBlock
*bottom
;
1045 for(; j
< (yblocks
>> 1); j
++)
1047 top
= reinterpret_cast<DXTColBlock
*>(image
.get_pixels() + j
* linesize
);
1048 bottom
= reinterpret_cast<DXTColBlock
*>(image
.get_pixels() + (((yblocks
- j
) - 1) * linesize
));
1050 (this->*flipblocks
)(top
, xblocks
);
1051 (this->*flipblocks
)(bottom
, xblocks
);
1053 swap(bottom
, top
, linesize
);
1056 if((yblocks
& 0x01) == 0x01)
1058 top
= reinterpret_cast<DXTColBlock
*>(image
.get_pixels() + j
* linesize
);
1060 (this->*flipblocks
)(top
, xblocks
);
1066 fprintf(stderr
, "compressed volume\n");
1069 if(format
!= GL_COMPRESSED_RGB_S3TC_DXT1_EXT
)
1072 fprintf(stderr
, "sorry, only dxt1 rgb volumes supported yet\n");
1080 "dds status : opengl 0x%x | layout nv 0x%x "
1081 "| layout std 0x%x\n",
1082 UInt32(ddpfFlags
& DDS_DDPF_OPENGL
),
1083 UInt32((ddpfFlags
& DDS_DDPF_OPENGL_NV
) == DDS_DDPF_OPENGL_NV
),
1084 UInt32((ddpfFlags
& DDS_DDPF_OPENGL_STD
) == DDS_DDPF_OPENGL_STD
));
1087 char *szEnvGPU
= getenv("OSG_GPU_NVIDIA");
1090 fprintf(stderr
, "env nv : %p\n", szEnvGPU
);
1093 if((ddpfFlags
& DDS_DDPF_OPENGL
) == 0x00)
1095 if(szEnvGPU
== NULL
)
1098 fprintf(stderr
, "flip\n");
1101 this->flipDXT(image
,
1110 fprintf(stderr
, "flip + adjust layout std->nv\n");
1113 this->flipDXTStdToNV(image
,
1122 if((ddpfFlags
& DDS_DDPF_OPENGL_NV
) == DDS_DDPF_OPENGL_NV
)
1124 if(szEnvGPU
== NULL
)
1127 fprintf(stderr
, "adjust layout nv->std\n");
1130 this->changeLayout(image
,
1140 fprintf(stderr
, "do nothing (nv)\n");
1146 if(szEnvGPU
== NULL
)
1149 fprintf(stderr
, "do nothing (std)\n");
1155 fprintf(stderr
, "adjust layout std->nv\n");
1158 this->changeLayout(image
,
1171 void CDDSImage::flipDXT(CSurface
&image
,
1172 Int32 width
, Int32 height
, Int32 depth
,
1175 void (CDDSImage::*flipblocks
)(DXTColBlock
*, Int32
);
1177 Int32 xblocks
= width
/ 4;
1178 Int32 yblocks
= height
/ 4;
1183 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
1185 flipblocks
= &CDDSImage::flip_blocks_dxtc1
;
1187 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
1189 flipblocks
= &CDDSImage::flip_blocks_dxtc1
;
1191 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
1193 flipblocks
= &CDDSImage::flip_blocks_dxtc3
;
1195 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
1197 flipblocks
= &CDDSImage::flip_blocks_dxtc5
;
1203 Int32 linesize
= xblocks
* blocksize
;
1206 DXTColBlock
*bottom
;
1208 Int32 SliceSize
= xblocks
* yblocks
* blocksize
;
1210 for(Int32 d
= 0; d
< depth
; ++d
)
1213 for(; j
< (yblocks
>> 1); j
++)
1215 top
= reinterpret_cast<DXTColBlock
*>(image
.get_pixels() + d
* SliceSize
+ j
* linesize
);
1216 bottom
= reinterpret_cast<DXTColBlock
*>(image
.get_pixels() + d
* SliceSize
+ (((yblocks
- j
) - 1) * linesize
));
1218 (this->*flipblocks
)(top
, xblocks
);
1219 (this->*flipblocks
)(bottom
, xblocks
);
1221 swap(bottom
, top
, linesize
);
1224 if((yblocks
& 0x01) == 0x01)
1226 top
= reinterpret_cast<DXTColBlock
*>(image
.get_pixels() + d
* SliceSize
+ j
* linesize
);
1228 (this->*flipblocks
)(top
, xblocks
);
1233 void CDDSImage::flipDXTStdToNV(CSurface
&image
,
1234 Int32 width
, Int32 height
, Int32 depth
,
1237 CSurface
tmp(image
.get_width (),
1242 DXTColBlock
*src
= reinterpret_cast<DXTColBlock
*>(image
.get_pixels());
1243 DXTColBlock
*dst
= reinterpret_cast<DXTColBlock
*>(tmp
.get_pixels());
1245 Int32 xblocks
= width
/ 4;
1246 Int32 yblocks
= height
/ 4;
1252 Int32 iSliceSize
= xblocks
* yblocks
;
1256 Int32 iLastD
= depth
% 4;
1257 Int32 iLastDStart
= Int32(floor(Real32(depth
) / 4.f
)) * 4;
1259 for(Int32 srcD
= 0; srcD
< depth
; ++srcD
)
1261 if(srcD
== iLastDStart
)
1264 for(Int32 srcY
= 0; srcY
< yblocks
; ++srcY
)
1266 for(Int32 srcX
= 0; srcX
< xblocks
; ++srcX
)
1268 Int32 srcIndex
= srcD
* iSliceSize
+ srcY
* xblocks
+ srcX
;
1269 Int32 dstIndex
= (dstD
+ dOffset
) * iSliceSize
+ (yblocks
- 1 - dstY
) * xblocks
+ dstX
;
1294 flip_blocks_dxtc1(&(src
[dstIndex
]), 1);
1296 dst
[srcIndex
] = src
[dstIndex
];
1301 image
.swapPixels(tmp
);
1304 void CDDSImage:: changeLayout(CSurface
&image
,
1305 Int32 width
, Int32 height
, Int32 depth
,
1306 Int32 size
, bool bNVToStd
)
1308 CSurface
tmp(image
.get_width (),
1313 DXTColBlock
*src
= reinterpret_cast<DXTColBlock
*>(image
.get_pixels());
1314 DXTColBlock
*dst
= reinterpret_cast<DXTColBlock
*>(tmp
.get_pixels());
1316 Int32 xblocks
= width
/ 4;
1317 Int32 yblocks
= height
/ 4;
1323 Int32 iSliceSize
= xblocks
* yblocks
;
1327 Int32 iLastD
= depth
% 4;
1328 Int32 iLastDStart
= Int32(floor(Real32(depth
) / 4.f
)) * 4;
1330 for(Int32 srcD
= 0; srcD
< depth
; ++srcD
)
1332 if(srcD
== iLastDStart
)
1335 for(Int32 srcY
= 0; srcY
< yblocks
; ++srcY
)
1337 for(Int32 srcX
= 0; srcX
< xblocks
; ++srcX
)
1339 Int32 srcIndex
= srcD
* iSliceSize
+ srcY
* xblocks
+ srcX
;
1340 Int32 dstIndex
= (dstD
+ dOffset
) * iSliceSize
+ dstY
* xblocks
+ dstX
;
1364 if(bNVToStd
== true)
1366 dst
[dstIndex
] = src
[srcIndex
];
1370 dst
[srcIndex
] = src
[dstIndex
];
1376 image
.swapPixels(tmp
);
1379 ///////////////////////////////////////////////////////////////////////////////
1380 // swap to sections of memory
1381 void CDDSImage::swap(void *byte1
, void *byte2
, Int32 size
)
1383 UInt8
*tmp
= new UInt8
[size
];
1385 memcpy(tmp
, byte1
, size
);
1386 memcpy(byte1
, byte2
, size
);
1387 memcpy(byte2
, tmp
, size
);
1392 ///////////////////////////////////////////////////////////////////////////////
1393 // flip a DXT1 color block
1394 void CDDSImage::flip_blocks_dxtc1(DXTColBlock
*line
, Int32 numBlocks
)
1396 DXTColBlock
*curblock
= line
;
1398 for (Int32 i
= 0; i
< numBlocks
; i
++)
1400 swap(&(curblock
->row
[0]), &(curblock
->row
[3]), sizeof(UInt8
));
1401 swap(&(curblock
->row
[1]), &(curblock
->row
[2]), sizeof(UInt8
));
1407 ///////////////////////////////////////////////////////////////////////////////
1408 // flip a DXT3 color block
1409 void CDDSImage::flip_blocks_dxtc3(DXTColBlock
*line
, Int32 numBlocks
)
1411 DXTColBlock
*curblock
= line
;
1412 DXT3AlphaBlock
*alphablock
;
1414 for (Int32 i
= 0; i
< numBlocks
; i
++)
1416 alphablock
= reinterpret_cast<DXT3AlphaBlock
*>(curblock
);
1418 swap(&alphablock
->row
[0], &alphablock
->row
[3], sizeof(UInt16
));
1419 swap(&alphablock
->row
[1], &alphablock
->row
[2], sizeof(UInt16
));
1423 swap(&curblock
->row
[0], &curblock
->row
[3], sizeof(UInt8
));
1424 swap(&curblock
->row
[1], &curblock
->row
[2], sizeof(UInt8
));
1430 ///////////////////////////////////////////////////////////////////////////////
1431 // flip a DXT5 alpha block
1432 void CDDSImage::flip_dxt5_alpha(DXT5AlphaBlock
*block
)
1436 const UInt32 mask
= 0x00000007; // bits = 00 00 01 11
1438 memcpy(&bits
, &block
->row
[0], sizeof(UInt8
) * 3);
1440 gBits
[0][0] = UInt8(bits
& mask
);
1442 gBits
[0][1] = UInt8(bits
& mask
);
1444 gBits
[0][2] = UInt8(bits
& mask
);
1446 gBits
[0][3] = UInt8(bits
& mask
);
1448 gBits
[1][0] = UInt8(bits
& mask
);
1450 gBits
[1][1] = UInt8(bits
& mask
);
1452 gBits
[1][2] = UInt8(bits
& mask
);
1454 gBits
[1][3] = UInt8(bits
& mask
);
1457 memcpy(&bits
, &block
->row
[3], sizeof(UInt8
) * 3);
1459 gBits
[2][0] = UInt8(bits
& mask
);
1461 gBits
[2][1] = UInt8(bits
& mask
);
1463 gBits
[2][2] = UInt8(bits
& mask
);
1465 gBits
[2][3] = UInt8(bits
& mask
);
1467 gBits
[3][0] = UInt8(bits
& mask
);
1469 gBits
[3][1] = UInt8(bits
& mask
);
1471 gBits
[3][2] = UInt8(bits
& mask
);
1473 gBits
[3][3] = UInt8(bits
& mask
);
1475 UInt32
*pBits
= (reinterpret_cast<UInt32
*>(&(block
->row
[0])));
1477 *pBits
= *pBits
| (gBits
[3][0] << 0);
1478 *pBits
= *pBits
| (gBits
[3][1] << 3);
1479 *pBits
= *pBits
| (gBits
[3][2] << 6);
1480 *pBits
= *pBits
| (gBits
[3][3] << 9);
1482 *pBits
= *pBits
| (gBits
[2][0] << 12);
1483 *pBits
= *pBits
| (gBits
[2][1] << 15);
1484 *pBits
= *pBits
| (gBits
[2][2] << 18);
1485 *pBits
= *pBits
| (gBits
[2][3] << 21);
1487 pBits
= (reinterpret_cast<UInt32
*>(&(block
->row
[3])));
1489 #if BYTE_ORDER == BIG_ENDIAN
1490 *pBits
&= 0x000000ff;
1492 *pBits
&= 0xff000000;
1495 *pBits
= *pBits
| (gBits
[1][0] << 0);
1496 *pBits
= *pBits
| (gBits
[1][1] << 3);
1497 *pBits
= *pBits
| (gBits
[1][2] << 6);
1498 *pBits
= *pBits
| (gBits
[1][3] << 9);
1500 *pBits
= *pBits
| (gBits
[0][0] << 12);
1501 *pBits
= *pBits
| (gBits
[0][1] << 15);
1502 *pBits
= *pBits
| (gBits
[0][2] << 18);
1503 *pBits
= *pBits
| (gBits
[0][3] << 21);
1506 ///////////////////////////////////////////////////////////////////////////////
1507 // flip a DXT5 color block
1508 void CDDSImage::flip_blocks_dxtc5(DXTColBlock
*line
, Int32 numBlocks
)
1510 DXTColBlock
*curblock
= line
;
1511 DXT5AlphaBlock
*alphablock
;
1513 for (Int32 i
= 0; i
< numBlocks
; i
++)
1515 alphablock
= reinterpret_cast<DXT5AlphaBlock
*>(curblock
);
1517 flip_dxt5_alpha(alphablock
);
1521 swap(&curblock
->row
[0], &curblock
->row
[3], sizeof(UInt8
));
1522 swap(&curblock
->row
[1], &curblock
->row
[2], sizeof(UInt8
));
1528 ///////////////////////////////////////////////////////////////////////////////
1529 // CTexture implementation
1530 ///////////////////////////////////////////////////////////////////////////////
1532 ///////////////////////////////////////////////////////////////////////////////
1533 // default constructor
1534 CTexture::CTexture()
1535 : CSurface(), // initialize base class part
1540 ///////////////////////////////////////////////////////////////////////////////
1541 // creates an empty texture
1542 CTexture::CTexture(Int32 w
, Int32 h
, Int32 d
, Int32 imgSize
)
1543 : CSurface(w
, h
, d
, imgSize
), // initialize base class part
1548 ///////////////////////////////////////////////////////////////////////////////
1550 CTexture::CTexture(const CTexture
©
)
1554 for (UInt32 i
= 0; i
< copy
.mipmaps
.size(); i
++)
1555 mipmaps
.push_back(copy
.mipmaps
[i
]);
1558 ///////////////////////////////////////////////////////////////////////////////
1559 // assignment operator
1560 CTexture
&CTexture::operator= (const CTexture
&rhs
)
1564 CSurface::operator = (rhs
);
1567 for (UInt32 i
= 0; i
< rhs
.mipmaps
.size(); i
++)
1569 mipmaps
.push_back(rhs
.mipmaps
[i
]);
1576 ///////////////////////////////////////////////////////////////////////////////
1577 // clean up texture memory
1578 CTexture::~CTexture()
1583 ///////////////////////////////////////////////////////////////////////////////
1584 // CSurface implementation
1585 ///////////////////////////////////////////////////////////////////////////////
1587 ///////////////////////////////////////////////////////////////////////////////
1588 // default constructor
1589 CSurface::CSurface()
1598 ///////////////////////////////////////////////////////////////////////////////
1599 // creates an empty image
1600 CSurface::CSurface(Int32 w
, Int32 h
, Int32 d
, Int32 imgsize
):
1607 create(w
, h
, d
, imgsize
);
1610 ///////////////////////////////////////////////////////////////////////////////
1612 CSurface::CSurface(const CSurface
©
)
1624 height
= copy
.height
;
1626 pixels
= new char[size
];
1627 memcpy(pixels
, copy
.pixels
, copy
.size
);
1631 ///////////////////////////////////////////////////////////////////////////////
1632 // assignment operator
1633 CSurface
&CSurface::operator= (const CSurface
&rhs
)
1643 height
= rhs
.height
;
1646 pixels
= new char[size
];
1647 memcpy(pixels
, rhs
.pixels
, size
);
1654 ///////////////////////////////////////////////////////////////////////////////
1655 // clean up image memory
1657 CSurface::~CSurface()
1662 ///////////////////////////////////////////////////////////////////////////////
1663 // returns a pointer to image
1666 CSurface::operator char*()
1672 ///////////////////////////////////////////////////////////////////////////////
1673 // creates an empty image
1675 void CSurface::create(Int32 w
, Int32 h
, Int32 d
, Int32 imgsize
)
1683 pixels
= new char[imgsize
];
1686 ///////////////////////////////////////////////////////////////////////////////
1687 // free surface memory
1689 void CSurface::clear()
1695 void CSurface::swapPixels(CSurface
&other
)
1699 pixels
= other
.pixels
;