Skip to content

Commit b193dc4

Browse files
committed
Force the DDS/DXT stream decompression.
The DDSCodec keeps the DXT format if the hardware supports it. However using this stack object it is possible to enforce the DXT decompression into RGB(A) format. This is useful e.g. when we have DDS texture without mipmaps and we need them. DirectX11 does not generate mipmaps if the texture is compressed (DirectX9 does it automatically). Also added support to obtain the DDS stream (not only saving to file).
1 parent 57fc7df commit b193dc4

File tree

2 files changed

+77
-16
lines changed

2 files changed

+77
-16
lines changed

OgreMain/src/OgreDDSCodec.cpp

+59-16
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,27 @@ namespace {
159159
const uint32 D3DFMT_A32B32G32R32F = 116;
160160
}
161161

162+
//---------------------------------------------------------------------
163+
// Force the DXT stream decompression
164+
//---------------------------------------------------------------------
165+
int DDSDecodeEnforcer::mCount = 0;
166+
167+
DDSDecodeEnforcer::DDSDecodeEnforcer()
168+
{
169+
++mCount;
170+
}
171+
172+
DDSDecodeEnforcer::~DDSDecodeEnforcer()
173+
{
174+
--mCount;
175+
assert(mCount >= 0);
176+
}
177+
178+
bool DDSDecodeEnforcer::isEnabled()
179+
{
180+
return mCount > 0;
181+
}
182+
162183
//---------------------------------------------------------------------
163184
DDSCodec* DDSCodec::msInstance = 0;
164185
//---------------------------------------------------------------------
@@ -193,7 +214,7 @@ namespace {
193214
{
194215
}
195216
//---------------------------------------------------------------------
196-
void DDSCodec::encodeToFile(const Any& input, const String& outFileName) const
217+
DataStreamPtr DDSCodec::encode(const Any& input) const
197218
{
198219
Image* image = any_cast<Image*>(input);
199220

@@ -402,21 +423,42 @@ namespace {
402423
dataPtr = tmpData;
403424
}
404425

405-
try
406-
{
407-
// Write the file
408-
std::ofstream of;
409-
of.open(outFileName.c_str(), std::ios_base::binary|std::ios_base::out);
410-
of.write((const char *)&ddsMagic, sizeof(uint32));
411-
of.write((const char *)&ddsHeader, DDS_HEADER_SIZE);
412-
// XXX flipEndian on each pixel chunk written unless isFloat32r ?
413-
of.write(dataPtr, image->getSize());
414-
of.close();
415-
}
416-
catch(...)
417-
{
418-
}
426+
size_t totalSize = sizeof(uint32) + DDS_HEADER_SIZE + image->getSize();
427+
auto pMemStream = OGRE_NEW Ogre::MemoryDataStream(totalSize);
428+
429+
pMemStream->write(&ddsMagic, sizeof(uint32));
430+
pMemStream->write(&ddsHeader, DDS_HEADER_SIZE);
431+
pMemStream->write(dataPtr, image->getSize());
432+
pMemStream->seek(0);
433+
419434
delete [] tmpData;
435+
436+
return Ogre::DataStreamPtr(pMemStream);
437+
}
438+
}
439+
//---------------------------------------------------------------------
440+
void DDSCodec::encodeToFile(const Any& input, const String& outFileName) const
441+
{
442+
DataStreamPtr strm = encode(input);
443+
444+
try
445+
{
446+
// Write the file
447+
std::ofstream of;
448+
of.open(outFileName.c_str(), std::ios_base::binary | std::ios_base::out);
449+
450+
const size_t buffSize = 4096;
451+
char buffer[buffSize];
452+
453+
while (!strm->eof()) {
454+
size_t bytesRead = strm->read(buffer, buffSize);
455+
of.write(buffer, bytesRead);
456+
}
457+
458+
of.close();
459+
}
460+
catch(...)
461+
{
420462
}
421463
}
422464
//---------------------------------------------------------------------
@@ -824,7 +866,8 @@ namespace {
824866
if (PixelUtil::isCompressed(sourceFormat))
825867
{
826868
if (Root::getSingleton().getRenderSystem() == NULL ||
827-
!Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_TEXTURE_COMPRESSION_DXT))
869+
!Root::getSingleton().getRenderSystem()->getCapabilities()->hasCapability(RSC_TEXTURE_COMPRESSION_DXT) ||
870+
DDSDecodeEnforcer::isEnabled())
828871
{
829872
// We'll need to decompress
830873
decompressDXT = true;

OgreMain/src/OgreDDSCodec.h

+18
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,23 @@ namespace Ogre {
4444
struct DXTExplicitAlphaBlock;
4545
struct DXTInterpolatedAlphaBlock;
4646

47+
/** Force the DXT stream decompression.
48+
49+
The DDSCodec keeps the DXT format if the hardware supports it.
50+
However this stack object can enforce the DXT decompression into RGB(A) format.
51+
*/
52+
class _OgreExport DDSDecodeEnforcer
53+
{
54+
public:
55+
DDSDecodeEnforcer();
56+
~DDSDecodeEnforcer();
57+
58+
static bool isEnabled();
59+
60+
private:
61+
static int mCount;
62+
};
63+
4764
/** Codec specialized in loading DDS (Direct Draw Surface) images.
4865
4966
We implement our own codec here since we need to be able to keep DXT
@@ -72,6 +89,7 @@ namespace Ogre {
7289
DDSCodec();
7390
virtual ~DDSCodec() { }
7491

92+
DataStreamPtr encode(const Any& input) const override;
7593
void encodeToFile(const Any& input, const String& outFileName) const override;
7694
void decode(const DataStreamPtr& input, const Any& output) const override;
7795
String magicNumberToFileExt(const char *magicNumberPtr, size_t maxbytes) const override;

0 commit comments

Comments
 (0)