Commit e2aee66c authored by nadro's avatar nadro

- Removed IImageCompressed and derived.

- Extended IImage class for support compressed textures.
- Improved DDS loader for support mip map loading.
- Added DXT1-5 compressed textures support for OpenGL.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4449 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 6f278dd4
...@@ -98,6 +98,12 @@ public: ...@@ -98,6 +98,12 @@ public:
//! fills the surface with given color //! fills the surface with given color
virtual void fill(const SColor &color) =0; virtual void fill(const SColor &color) =0;
//! Inform whether the image is compressed
virtual bool isCompressed() const = 0;
//! Inform wheather the image has mipmaps
virtual bool hasMipMap() const = 0;
//! get the amount of Bits per Pixel of the given color format //! get the amount of Bits per Pixel of the given color format
static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format) static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format)
{ {
...@@ -111,6 +117,13 @@ public: ...@@ -111,6 +117,13 @@ public:
return 24; return 24;
case ECF_A8R8G8B8: case ECF_A8R8G8B8:
return 32; return 32;
case ECF_DXT1:
return 16;
case ECF_DXT2:
case ECF_DXT3:
case ECF_DXT4:
case ECF_DXT5:
return 32;
case ECF_R16F: case ECF_R16F:
return 16; return 16;
case ECF_G16R16F: case ECF_G16R16F:
...@@ -128,6 +141,22 @@ public: ...@@ -128,6 +141,22 @@ public:
} }
} }
//! test if this is compressed color format
static bool isCompressedFormat(const ECOLOR_FORMAT format)
{
switch(format)
{
case ECF_DXT1:
case ECF_DXT2:
case ECF_DXT3:
case ECF_DXT4:
case ECF_DXT5:
return true;
default:
return false;
}
}
//! test if the color format is only viable for RenderTarget textures //! test if the color format is only viable for RenderTarget textures
/** Since we don't have support for e.g. floating point IImage formats /** Since we don't have support for e.g. floating point IImage formats
one should test if the color format can be used for arbitrary usage, or one should test if the color format can be used for arbitrary usage, or
...@@ -148,56 +177,6 @@ public: ...@@ -148,56 +177,6 @@ public:
}; };
//! Interface for software compressed image data.
/** Image loaders create these images from files. IVideoDrivers convert
these images into their (hardware) textures.
*/
class IImageCompressed : public virtual IReferenceCounted
{
public:
//! Use this to get a pointer to the image data.
virtual const void* getData() const = 0;
//! Returns width and height of image data.
virtual const core::dimension2d<u32>& getDimension() const = 0;
//! Returns bits per pixel.
virtual u32 getBitsPerPixel() const = 0;
//! Returns bytes per pixel
virtual u32 getBytesPerPixel() const = 0;
//! Returns image data size in bytes
virtual u32 getImageDataSizeInBytes() const = 0;
//! Returns image data size in pixels
virtual u32 getImageDataSizeInPixels() const = 0;
//! Returns the color format
virtual ECOLOR_FORMAT getColorFormat() const = 0;
//! Returns pitch of image
virtual u32 getPitch() const = 0;
//! get the amount of Bits per Pixel of the given color format
static u32 getBitsPerPixelFromFormat(const ECOLOR_FORMAT format)
{
switch(format)
{
case ECF_DXT1:
return 16;
case ECF_DXT2:
case ECF_DXT3:
case ECF_DXT4:
case ECF_DXT5:
return 32;
default:
return 0;
}
}
};
} // end namespace video } // end namespace video
} // end namespace irr } // end namespace irr
......
...@@ -43,15 +43,6 @@ public: ...@@ -43,15 +43,6 @@ public:
/** \param file File handle to check. /** \param file File handle to check.
\return Pointer to newly created image, or 0 upon error. */ \return Pointer to newly created image, or 0 upon error. */
virtual IImage* loadImage(io::IReadFile* file) const = 0; virtual IImage* loadImage(io::IReadFile* file) const = 0;
//! Creates a compressed surface from the file
/** \param file File handle to check.
\return Pointer to newly created image, or 0 upon error. */
virtual IImageCompressed* loadImageCompressed(io::IReadFile* file) const
{
// The most of supported file formats are uncompressed, so we define it here.
return 0;
}
}; };
......
...@@ -1218,18 +1218,6 @@ namespace video ...@@ -1218,18 +1218,6 @@ namespace video
bool ownForeignMemory=false, bool ownForeignMemory=false,
bool deleteMemory = true) =0; bool deleteMemory = true) =0;
//! Creates a compressed software image from a file.
virtual IImageCompressed* createImageCompressedFromFile(const io::path& filename) = 0;
//! Creates a compressed software image from a file.
virtual IImageCompressed* createImageCompressedFromFile(io::IReadFile* file) = 0;
//! Creates a software compressed image from a byte array.
virtual IImageCompressed* createImageCompressedFromData(ECOLOR_FORMAT format,
const core::dimension2d<u32>& size, void *data,
bool ownForeignMemory=false,
bool deleteMemory = true) = 0;
//! Creates an empty software image. //! Creates an empty software image.
/** /**
\param format Desired color format of the image. \param format Desired color format of the image.
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include "irrString.h" #include "irrString.h"
#include "CColorConverter.h" #include "CColorConverter.h"
#include "CBlit.h" #include "CBlit.h"
#include "os.h"
namespace irr namespace irr
{ {
...@@ -14,7 +15,7 @@ namespace video ...@@ -14,7 +15,7 @@ namespace video
//! Constructor of empty image //! Constructor of empty image
CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size) CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size)
:Data(0), Size(size), Format(format), DeleteMemory(true) :Data(0), Size(size), Format(format), DeleteMemory(true), Compressed(false)
{ {
initData(); initData();
} }
...@@ -22,8 +23,8 @@ CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size) ...@@ -22,8 +23,8 @@ CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size)
//! Constructor from raw data //! Constructor from raw data
CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size, void* data, CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size, void* data,
bool ownForeignMemory, bool deleteForeignMemory) bool ownForeignMemory, bool deleteForeignMemory, bool compressed, bool hasMipMapData)
: Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory) : Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory), Compressed(compressed), HasMipMap(hasMipMapData)
{ {
if (ownForeignMemory) if (ownForeignMemory)
{ {
...@@ -181,6 +182,12 @@ u32 CImage::getAlphaMask() const ...@@ -181,6 +182,12 @@ u32 CImage::getAlphaMask() const
//! sets a pixel //! sets a pixel
void CImage::setPixel(u32 x, u32 y, const SColor &color, bool blend) void CImage::setPixel(u32 x, u32 y, const SColor &color, bool blend)
{ {
if (Compressed)
{
os::Printer::log("IImage::setPixel method doesn't work with compressed images.", ELL_WARNING);
return;
}
if (x >= Size.Width || y >= Size.Height) if (x >= Size.Width || y >= Size.Height)
return; return;
...@@ -222,6 +229,12 @@ void CImage::setPixel(u32 x, u32 y, const SColor &color, bool blend) ...@@ -222,6 +229,12 @@ void CImage::setPixel(u32 x, u32 y, const SColor &color, bool blend)
//! returns a pixel //! returns a pixel
SColor CImage::getPixel(u32 x, u32 y) const SColor CImage::getPixel(u32 x, u32 y) const
{ {
if (Compressed)
{
os::Printer::log("IImage::getPixel method doesn't work with compressed images.", ELL_WARNING);
return SColor(0);
}
if (x >= Size.Width || y >= Size.Height) if (x >= Size.Width || y >= Size.Height)
return SColor(0); return SColor(0);
...@@ -258,6 +271,12 @@ ECOLOR_FORMAT CImage::getColorFormat() const ...@@ -258,6 +271,12 @@ ECOLOR_FORMAT CImage::getColorFormat() const
//! copies this surface into another at given position //! copies this surface into another at given position
void CImage::copyTo(IImage* target, const core::position2d<s32>& pos) void CImage::copyTo(IImage* target, const core::position2d<s32>& pos)
{ {
if (Compressed)
{
os::Printer::log("IImage::copyTo method doesn't work with compressed images.", ELL_WARNING);
return;
}
Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0); Blit(BLITTER_TEXTURE, target, 0, &pos, this, 0, 0);
} }
...@@ -265,6 +284,12 @@ void CImage::copyTo(IImage* target, const core::position2d<s32>& pos) ...@@ -265,6 +284,12 @@ void CImage::copyTo(IImage* target, const core::position2d<s32>& pos)
//! copies this surface partially into another at given position //! copies this surface partially into another at given position
void CImage::copyTo(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect) void CImage::copyTo(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect)
{ {
if (Compressed)
{
os::Printer::log("IImage::copyTo method doesn't work with compressed images.", ELL_WARNING);
return;
}
Blit(BLITTER_TEXTURE, target, clipRect, &pos, this, &sourceRect, 0); Blit(BLITTER_TEXTURE, target, clipRect, &pos, this, &sourceRect, 0);
} }
...@@ -272,6 +297,12 @@ void CImage::copyTo(IImage* target, const core::position2d<s32>& pos, const core ...@@ -272,6 +297,12 @@ void CImage::copyTo(IImage* target, const core::position2d<s32>& pos, const core
//! copies this surface into another, using the alpha mask, a cliprect and a color to add with //! copies this surface into another, using the alpha mask, a cliprect and a color to add with
void CImage::copyToWithAlpha(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const SColor &color, const core::rect<s32>* clipRect) void CImage::copyToWithAlpha(IImage* target, const core::position2d<s32>& pos, const core::rect<s32>& sourceRect, const SColor &color, const core::rect<s32>* clipRect)
{ {
if (Compressed)
{
os::Printer::log("IImage::copyToWithAlpha method doesn't work with compressed images.", ELL_WARNING);
return;
}
// color blend only necessary on not full spectrum aka. color.color != 0xFFFFFFFF // color blend only necessary on not full spectrum aka. color.color != 0xFFFFFFFF
Blit(color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND: BLITTER_TEXTURE_ALPHA_COLOR_BLEND, Blit(color.color == 0xFFFFFFFF ? BLITTER_TEXTURE_ALPHA_BLEND: BLITTER_TEXTURE_ALPHA_COLOR_BLEND,
target, clipRect, &pos, this, &sourceRect, color.color); target, clipRect, &pos, this, &sourceRect, color.color);
...@@ -282,6 +313,12 @@ void CImage::copyToWithAlpha(IImage* target, const core::position2d<s32>& pos, c ...@@ -282,6 +313,12 @@ void CImage::copyToWithAlpha(IImage* target, const core::position2d<s32>& pos, c
// note: this is very very slow. // note: this is very very slow.
void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch) void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT format, u32 pitch)
{ {
if (Compressed)
{
os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING);
return;
}
if (!target || !width || !height) if (!target || !width || !height)
return; return;
...@@ -338,6 +375,12 @@ void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT fo ...@@ -338,6 +375,12 @@ void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT fo
// note: this is very very slow. // note: this is very very slow.
void CImage::copyToScaling(IImage* target) void CImage::copyToScaling(IImage* target)
{ {
if (Compressed)
{
os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING);
return;
}
if (!target) if (!target)
return; return;
...@@ -357,6 +400,12 @@ void CImage::copyToScaling(IImage* target) ...@@ -357,6 +400,12 @@ void CImage::copyToScaling(IImage* target)
//! copies this surface into another, scaling it to fit it. //! copies this surface into another, scaling it to fit it.
void CImage::copyToScalingBoxFilter(IImage* target, s32 bias, bool blend) void CImage::copyToScalingBoxFilter(IImage* target, s32 bias, bool blend)
{ {
if (Compressed)
{
os::Printer::log("IImage::copyToScalingBoxFilter method doesn't work with compressed images.", ELL_WARNING);
return;
}
const core::dimension2d<u32> destSize = target->getDimension(); const core::dimension2d<u32> destSize = target->getDimension();
const f32 sourceXStep = (f32) Size.Width / (f32) destSize.Width; const f32 sourceXStep = (f32) Size.Width / (f32) destSize.Width;
...@@ -389,6 +438,12 @@ void CImage::copyToScalingBoxFilter(IImage* target, s32 bias, bool blend) ...@@ -389,6 +438,12 @@ void CImage::copyToScalingBoxFilter(IImage* target, s32 bias, bool blend)
//! fills the surface with given color //! fills the surface with given color
void CImage::fill(const SColor &color) void CImage::fill(const SColor &color)
{ {
if (Compressed)
{
os::Printer::log("IImage::fill method doesn't work with compressed images.", ELL_WARNING);
return;
}
u32 c; u32 c;
switch ( Format ) switch ( Format )
...@@ -424,9 +479,28 @@ void CImage::fill(const SColor &color) ...@@ -424,9 +479,28 @@ void CImage::fill(const SColor &color)
} }
//! Inform whether the image is compressed
bool CImage::isCompressed() const
{
return Compressed;
}
//! Inform wheather the image store mipmaps
bool CImage::hasMipMap() const
{
return HasMipMap;
}
//! get a filtered pixel //! get a filtered pixel
inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) const
{ {
if (Compressed)
{
os::Printer::log("IImage::getPixelBox method doesn't work with compressed images.", ELL_WARNING);
return SColor(0);
}
SColor c; SColor c;
s32 a = 0, r = 0, g = 0, b = 0; s32 a = 0, r = 0, g = 0, b = 0;
...@@ -458,111 +532,5 @@ inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) cons ...@@ -458,111 +532,5 @@ inline SColor CImage::getPixelBox( s32 x, s32 y, s32 fx, s32 fy, s32 bias ) cons
} }
/** Compressed image **/
//! Constructor
CImageCompressed::CImageCompressed(ECOLOR_FORMAT format, const core::dimension2d<u32>& size, void* data,
bool ownForeignMemory, bool deleteForeignMemory)
: Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory)
{
if (ownForeignMemory)
{
Data = (u8*)0xbadf00d;
initData();
Data = (u8*)data;
}
else
{
Data = 0;
initData();
memcpy(Data, data, Size.Height * Pitch);
}
}
//! Destructor
CImageCompressed::~CImageCompressed()
{
if (DeleteMemory)
delete [] Data;
}
//! assumes format and size has been set and creates the rest
void CImageCompressed::initData()
{
#ifdef _DEBUG
setDebugName("CImageCompressed");
#endif
BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8;
// Pitch should be aligned...
Pitch = BytesPerPixel * Size.Width;
if (!Data)
{
DeleteMemory=true;
Data = new u8[Size.Height * Pitch];
}
}
//! Use this to get a pointer to the image data.
const void* CImageCompressed::getData() const
{
return Data;
}
//! Returns width and height of image data.
const core::dimension2d<u32>& CImageCompressed::getDimension() const
{
return Size;
}
//! Returns bits per pixel.
u32 CImageCompressed::getBitsPerPixel() const
{
return getBitsPerPixelFromFormat(Format);
}
//! Returns bytes per pixel
u32 CImageCompressed::getBytesPerPixel() const
{
return BytesPerPixel;
}
//! Returns image data size in bytes
u32 CImageCompressed::getImageDataSizeInBytes() const
{
return Pitch * Size.Height;
}
//! Returns image data size in pixels
u32 CImageCompressed::getImageDataSizeInPixels() const
{
return Size.Width * Size.Height;
}
//! returns the color format
ECOLOR_FORMAT CImageCompressed::getColorFormat() const
{
return Format;
}
//! returns pitch of image
u32 CImageCompressed::getPitch() const
{
return Pitch;
}
} // end namespace video } // end namespace video
} // end namespace irr } // end namespace irr
...@@ -24,7 +24,7 @@ public: ...@@ -24,7 +24,7 @@ public:
directly and own it from now on, which means it will also try to delete [] the directly and own it from now on, which means it will also try to delete [] the
data when the image will be destructed. If false, the memory will by copied. */ data when the image will be destructed. If false, the memory will by copied. */
CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size, CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size,
void* data, bool ownForeignMemory=true, bool deleteMemory = true); void* data, bool ownForeignMemory=true, bool deleteMemory = true, bool compressed = false, bool hasMipMapData = false);
//! constructor for empty image //! constructor for empty image
CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size); CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size);
...@@ -103,6 +103,12 @@ public: ...@@ -103,6 +103,12 @@ public:
//! fills the surface with given color //! fills the surface with given color
virtual void fill(const SColor &color); virtual void fill(const SColor &color);
//! Inform whether the image is compressed
virtual bool isCompressed() const;
//! Inform wheather the image has mipmaps
virtual bool hasMipMap() const;
private: private:
//! assumes format and size has been set and creates the rest //! assumes format and size has been set and creates the rest
...@@ -117,59 +123,9 @@ private: ...@@ -117,59 +123,9 @@ private:
ECOLOR_FORMAT Format; ECOLOR_FORMAT Format;
bool DeleteMemory; bool DeleteMemory;
};
//! Internal interface for software compressed image data.
class CImageCompressed : public IImageCompressed
{
public:
//! Constructor
/** \param useForeignMemory: If true, the image will use the data pointer
directly and own it from now on, which means it will also try to delete [] the
data when the image will be destructed. If false, the memory will by copied. */
CImageCompressed(ECOLOR_FORMAT format, const core::dimension2d<u32>& size,
void* data, bool ownForeignMemory=true, bool deleteMemory = true);
//! Destructor
virtual ~CImageCompressed();
//! Use this to get a pointer to the image data.
virtual const void* getData() const;
//! Returns width and height of image data.
virtual const core::dimension2d<u32>& getDimension() const;
//! Returns bits per pixel.
virtual u32 getBitsPerPixel() const;
//! Returns bytes per pixel
virtual u32 getBytesPerPixel() const;
//! Returns image data size in bytes
virtual u32 getImageDataSizeInBytes() const;
//! Returns image data size in pixels
virtual u32 getImageDataSizeInPixels() const;
//! returns the color format
virtual ECOLOR_FORMAT getColorFormat() const;
//! returns pitch of image
virtual u32 getPitch() const;
private:
//! assumes format and size has been set and creates the rest
void initData();
u8* Data; bool Compressed;
core::dimension2d<u32> Size; bool HasMipMap;
u32 BytesPerPixel;
u32 Pitch;
ECOLOR_FORMAT Format;
bool DeleteMemory;
}; };
} // end namespace video } // end namespace video
......
...@@ -113,6 +113,8 @@ s32 DDSGetInfo(ddsHeader* dds, s32* width, s32* height, eDDSPixelFormat* pf) ...@@ -113,6 +113,8 @@ s32 DDSGetInfo(ddsHeader* dds, s32* width, s32* height, eDDSPixelFormat* pf)
} }
#ifdef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_
/* /*
DDSDecompressARGB8888() DDSDecompressARGB8888()
decompresses an argb 8888 format texture decompresses an argb 8888 format texture
...@@ -141,8 +143,6 @@ s32 DDSDecompressARGB8888(ddsHeader* dds, u8* data, s32 width, s32 height, u8* p ...@@ -141,8 +143,6 @@ s32 DDSDecompressARGB8888(ddsHeader* dds, u8* data, s32 width, s32 height, u8* p
} }
#ifdef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_
/*! /*!
DDSGetColorBlockColors() DDSGetColorBlockColors()
extracts colors from a dds color block extracts colors from a dds color block
...@@ -692,92 +692,188 @@ IImage* CImageLoaderDDS::loadImage(io::IReadFile* file) const ...@@ -692,92 +692,188 @@ IImage* CImageLoaderDDS::loadImage(io::IReadFile* file) const
IImage* image = 0; IImage* image = 0;
s32 width, height; s32 width, height;
eDDSPixelFormat pixelFormat; eDDSPixelFormat pixelFormat;
ECOLOR_FORMAT format = ECF_UNKNOWN;
u32 dataSize = 0;
bool is3D = false;
bool useAlpha = false;
u32 mipMapCount = 0;
file->seek(0); file->seek(0);
file->read(&header, sizeof(ddsHeader)); file->read(&header, sizeof(ddsHeader));
if (0 == DDSGetInfo(&header, &width, &height, &pixelFormat)) if (0 == DDSGetInfo(&header, &width, &height, &pixelFormat))
{ {
#ifndef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_ is3D = header.Depth > 0 && (header.Flags & DDSD_DEPTH);
if(pixelFormat == DDS_PF_ARGB8888)
#endif
{
u32 newSize = file->getSize() - sizeof(ddsHeader);
u8* memFile = new u8[newSize];
file->read(memFile, newSize);
image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height)); if (!is3D)
header.Depth = 1;
#ifndef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_ useAlpha = header.PixelFormat.Flags & DDPF_ALPHAPIXELS;
DDSDecompressARGB8888(&header, memFile, width, height, (u8*)image->lock());
#else
if (DDSDecompress(&header, memFile, (u8*)image->lock()) == -1)
{
image->unlock();
image->drop();
image = 0;
}
#endif
delete[] memFile; if (header.MipMapCount > 0 && (header.Flags & DDSD_MIPMAPCOUNT))
mipMapCount = header.MipMapCount;
if (image) #ifdef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_
image->unlock(); u32 newSize = file->getSize() - sizeof(ddsHeader);
} u8* memFile = new u8[newSize];
} file->read(memFile, newSize);
return image; image = new CImage(ECF_A8R8G8B8, core::dimension2d<u32>(width, height));
}
if (DDSDecompress(&header, memFile, (u8*)image->lock()) == -1)
{
image->unlock();
image->drop();
image = 0;
}
//! creates a compressed surface from the file delete[] memFile;
IImageCompressed* CImageLoaderDDS::loadImageCompressed(io::IReadFile* file) const #else
{ if (header.PixelFormat.Flags & DDPF_RGB) // Uncompressed formats
#ifndef _IRR_COMPILE_WITH_DDS_DECODER_LOADER_ {
ddsHeader header; u32 byteCount = header.PixelFormat.RGBBitCount / 8;
IImageCompressed* image = 0;
s32 width, height; if( header.Flags & DDSD_PITCH )
eDDSPixelFormat pixelFormat; dataSize = header.PitchOrLinearSize * header.Height * header.Depth * (header.PixelFormat.RGBBitCount / 8);
else
dataSize = header.Width * header.Height * header.Depth * (header.PixelFormat.RGBBitCount / 8);
file->seek(0); u8* data = new u8[dataSize];
file->read(&header, sizeof(ddsHeader)); file->read(data, dataSize);
ECOLOR_FORMAT format = ECF_UNKNOWN; switch (header.PixelFormat.RGBBitCount) // Bytes per pixel
u32 dataSize = 0; {
bool is3D = false; case 16:
{
if (useAlpha)
{
if (header.PixelFormat.ABitMask == 0x8000)
format = ECF_A1R5G5B5;
}
else
{
if (header.PixelFormat.RBitMask == 0xf800)
format = ECF_R5G6B5;
}
if (0 == DDSGetInfo(&header, &width, &height, &pixelFormat)) break;
{ }
is3D = header.Depth > 0 && (header.Flags & DDSD_DEPTH); case 24:
{
if (!useAlpha)
{
if (header.PixelFormat.RBitMask == 0xff0000)
format = ECF_R8G8B8;
}
if (!is3D) break;
header.Depth = 1; }
case 32:
{
if (useAlpha)
{
if (header.PixelFormat.RBitMask & 0xff0000)
format = ECF_A8R8G8B8;
else if (header.PixelFormat.RBitMask & 0xff)
{
// convert from A8B8G8R8 to A8R8G8B8
u8 tmp = 0;
for (u32 i = 0; i < dataSize; i += 4)
{
tmp = data[i];
data[i] = data[i+2];
data[i+2] = tmp;
}
}
}
break;
}
}
if (header.PixelFormat.Flags & DDPF_FOURCC) // Compressed formats if (format != ECF_UNKNOWN)
{
if (!is3D) // Currently 3D textures are unsupported.
{
image = new CImage(format, core::dimension2d<u32>(header.Width, header.Height ), data, true, true, false);
}
}
else
{
delete[] data;
}
}
else if (header.PixelFormat.Flags & DDPF_FOURCC) // Compressed formats
{ {
switch(pixelFormat) switch(pixelFormat)
{ {
case DDS_PF_DXT1: case DDS_PF_DXT1:
{ {
dataSize = (header.Width / 4 ) * (header.Height / 4) * 8; u32 curWidth = header.Width;
u32 curHeight = header.Height;
dataSize = ((curWidth + 3) / 4) * ((curHeight + 3) / 4) * 8;
do
{
if (curWidth > 1)
curWidth >>= 1;
if (curHeight > 1)
curHeight >>= 1;
dataSize += ((curWidth + 3) / 4) * ((curHeight + 3) / 4) * 8;
}
while (curWidth != 1 || curWidth != 1);
format = ECF_DXT1; format = ECF_DXT1;
os::Printer::log("Detected ECF_DXT1 format", ELL_DEBUG);
break; break;
} }
case DDS_PF_DXT2: case DDS_PF_DXT2:
case DDS_PF_DXT3: case DDS_PF_DXT3:
{ {
dataSize = (header.Width / 4 ) * (header.Height / 4) * 16; u32 curWidth = header.Width;
u32 curHeight = header.Height;
dataSize = ((curWidth + 3) / 4) * ((curHeight + 3) / 4) * 16;
do
{
if (curWidth > 1)
curWidth >>= 1;
if (curHeight > 1)
curHeight >>= 1;
dataSize += ((curWidth + 3) / 4) * ((curHeight + 3) / 4) * 16;
}
while (curWidth != 1 || curWidth != 1);
format = ECF_DXT3; format = ECF_DXT3;
os::Printer::log("Detected ECF_DXT3 format", ELL_DEBUG);
break; break;
} }
case DDS_PF_DXT4: case DDS_PF_DXT4:
case DDS_PF_DXT5: case DDS_PF_DXT5:
{ {
dataSize = (header.Width / 4 ) * (header.Height / 4) * 16; u32 curWidth = header.Width;
u32 curHeight = header.Height;
dataSize = ((curWidth + 3) / 4) * ((curHeight + 3) / 4) * 16;
do
{
if (curWidth > 1)
curWidth >>= 1;
if (curHeight > 1)
curHeight >>= 1;
dataSize += ((curWidth + 3) / 4) * ((curHeight + 3) / 4) * 16;
}
while (curWidth != 1 || curWidth != 1);
format = ECF_DXT5; format = ECF_DXT5;
os::Printer::log("Detected ECF_DXT5 format", ELL_DEBUG);
break; break;
} }
} }
...@@ -789,16 +885,16 @@ IImageCompressed* CImageLoaderDDS::loadImageCompressed(io::IReadFile* file) cons ...@@ -789,16 +885,16 @@ IImageCompressed* CImageLoaderDDS::loadImageCompressed(io::IReadFile* file) cons
u8* data = new u8[dataSize]; u8* data = new u8[dataSize];
file->read(data, dataSize); file->read(data, dataSize);
image = new CImageCompressed(format, core::dimension2d<u32>(header.Width, header.Height ), data); bool hasMipMap = (mipMapCount > 0) ? true : false;
image = new CImage(format, core::dimension2d<u32>(header.Width, header.Height), data, true, true, true, hasMipMap);
} }
} }
} }
#endif
} }
return image; return image;
#else
return 0;
#endif
} }
......
...@@ -204,9 +204,6 @@ public: ...@@ -204,9 +204,6 @@ public:
//! creates a surface from the file //! creates a surface from the file
virtual IImage* loadImage(io::IReadFile* file) const; virtual IImage* loadImage(io::IReadFile* file) const;
//! creates a compressed surface from the file
virtual IImageCompressed* loadImageCompressed(io::IReadFile* file) const;
}; };
......
...@@ -1402,77 +1402,6 @@ IImage* CNullDriver::createImageFromData(ECOLOR_FORMAT format, ...@@ -1402,77 +1402,6 @@ IImage* CNullDriver::createImageFromData(ECOLOR_FORMAT format,
} }
//! Creates a compressed software image from a file.
IImageCompressed* CNullDriver::createImageCompressedFromFile(const io::path& filename)
{
if (!filename.size())
return 0;
IImageCompressed* image = 0;
io::IReadFile* file = FileSystem->createAndOpenFile(filename);
if (file)
{
image = createImageCompressedFromFile(file);
file->drop();
}
else
os::Printer::log("Could not open file of image", filename, ELL_WARNING);
return image;
}
//! Creates a compressed software image from a file.
IImageCompressed* CNullDriver::createImageCompressedFromFile(io::IReadFile* file)
{
if (!file)
return 0;
IImageCompressed* image = 0;
s32 i;
// try to load file based on file extension
for (i=SurfaceLoader.size()-1; i>=0; --i)
{
if (SurfaceLoader[i]->isALoadableFileExtension(file->getFileName()))
{
// reset file position which might have changed due to previous loadImage calls
file->seek(0);
image = SurfaceLoader[i]->loadImageCompressed(file);
if (image)
return image;
}
}
// try to load file based on what is in it
for (i=SurfaceLoader.size()-1; i>=0; --i)
{
// dito
file->seek(0);
if (SurfaceLoader[i]->isALoadableFileFormat(file))
{
file->seek(0);
image = SurfaceLoader[i]->loadImageCompressed(file);
if (image)
return image;
}
}
return 0; // failed to load
}
//! Creates a software compressed image from a byte array.
IImageCompressed* CNullDriver::createImageCompressedFromData(ECOLOR_FORMAT format,
const core::dimension2d<u32>& size, void *data,
bool ownForeignMemory, bool deleteMemory)
{
return new CImageCompressed(format, size, data, ownForeignMemory, deleteMemory);
}
//! Creates an empty software image. //! Creates an empty software image.
IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size) IImage* CNullDriver::createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size)
{ {
......
...@@ -352,17 +352,6 @@ namespace video ...@@ -352,17 +352,6 @@ namespace video
const core::dimension2d<u32>& size, void *data, const core::dimension2d<u32>& size, void *data,
bool ownForeignMemory=true, bool deleteForeignMemory = true); bool ownForeignMemory=true, bool deleteForeignMemory = true);
//! Creates a compressed software image from a file.
virtual IImageCompressed* createImageCompressedFromFile(const io::path& filename);
//! Creates a compressed software image from a file.
virtual IImageCompressed* createImageCompressedFromFile(io::IReadFile* file);
//! Creates a software compressed image from a byte array.
virtual IImageCompressed* createImageCompressedFromData(ECOLOR_FORMAT format,
const core::dimension2d<u32>& size, void *data,
bool ownForeignMemory=false, bool deleteMemory = true);
//! Creates an empty software image. //! Creates an empty software image.
virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size); virtual IImage* createImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size);
......
...@@ -50,7 +50,7 @@ COpenGLExtensionHandler::COpenGLExtensionHandler() : ...@@ -50,7 +50,7 @@ COpenGLExtensionHandler::COpenGLExtensionHandler() :
pGlPointParameterfARB(0), pGlPointParameterfvARB(0), pGlPointParameterfARB(0), pGlPointParameterfvARB(0),
pGlStencilFuncSeparate(0), pGlStencilOpSeparate(0), pGlStencilFuncSeparate(0), pGlStencilOpSeparate(0),
pGlStencilFuncSeparateATI(0), pGlStencilOpSeparateATI(0), pGlStencilFuncSeparateATI(0), pGlStencilOpSeparateATI(0),
pGlCompressedTexImage2D(0), pGlCompressedTexImage2D(0), pGlCompressedTexSubImage2D(0),
// ARB framebuffer object // ARB framebuffer object
pGlBindFramebuffer(0), pGlDeleteFramebuffers(0), pGlGenFramebuffers(0), pGlBindFramebuffer(0), pGlDeleteFramebuffers(0), pGlGenFramebuffers(0),
pGlCheckFramebufferStatus(0), pGlFramebufferTexture2D(0), pGlCheckFramebufferStatus(0), pGlFramebufferTexture2D(0),
...@@ -473,6 +473,7 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer) ...@@ -473,6 +473,7 @@ void COpenGLExtensionHandler::initExtensions(bool stencilBuffer)
// compressed textures // compressed textures
pGlCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) IRR_OGL_LOAD_EXTENSION("glCompressedTexImage2D"); pGlCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) IRR_OGL_LOAD_EXTENSION("glCompressedTexImage2D");
pGlCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) IRR_OGL_LOAD_EXTENSION("glCompressedTexSubImage2D");
// ARB FrameBufferObjects // ARB FrameBufferObjects
pGlBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) IRR_OGL_LOAD_EXTENSION("glBindFramebuffer"); pGlBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) IRR_OGL_LOAD_EXTENSION("glBindFramebuffer");
......
...@@ -992,6 +992,9 @@ class COpenGLExtensionHandler ...@@ -992,6 +992,9 @@ class COpenGLExtensionHandler
void extGlCompressedTexImage2D(GLenum target, GLint level, void extGlCompressedTexImage2D(GLenum target, GLint level,
GLenum internalformat, GLsizei width, GLsizei height, GLenum internalformat, GLsizei width, GLsizei height,
GLint border, GLsizei imageSize, const void* data); GLint border, GLsizei imageSize, const void* data);
void extGlCompressedTexSubImage2D(GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
GLenum format, GLsizei imageSize, const void* data);
// shader programming // shader programming
void extGlGenPrograms(GLsizei n, GLuint *programs); void extGlGenPrograms(GLsizei n, GLuint *programs);
...@@ -1168,6 +1171,7 @@ class COpenGLExtensionHandler ...@@ -1168,6 +1171,7 @@ class COpenGLExtensionHandler
PFNGLSTENCILFUNCSEPARATEATIPROC pGlStencilFuncSeparateATI; PFNGLSTENCILFUNCSEPARATEATIPROC pGlStencilFuncSeparateATI;
PFNGLSTENCILOPSEPARATEATIPROC pGlStencilOpSeparateATI; PFNGLSTENCILOPSEPARATEATIPROC pGlStencilOpSeparateATI;
PFNGLCOMPRESSEDTEXIMAGE2DPROC pGlCompressedTexImage2D; PFNGLCOMPRESSEDTEXIMAGE2DPROC pGlCompressedTexImage2D;
PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC pGlCompressedTexSubImage2D;
// ARB framebuffer object // ARB framebuffer object
PFNGLBINDFRAMEBUFFERPROC pGlBindFramebuffer; PFNGLBINDFRAMEBUFFERPROC pGlBindFramebuffer;
PFNGLDELETEFRAMEBUFFERSPROC pGlDeleteFramebuffers; PFNGLDELETEFRAMEBUFFERSPROC pGlDeleteFramebuffers;
...@@ -1934,6 +1938,19 @@ inline void COpenGLExtensionHandler::extGlCompressedTexImage2D (GLenum target, G ...@@ -1934,6 +1938,19 @@ inline void COpenGLExtensionHandler::extGlCompressedTexImage2D (GLenum target, G
#endif #endif
} }
inline void COpenGLExtensionHandler::extGlCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void* data)
{
#ifdef _IRR_OPENGL_USE_EXTPOINTER_
if (pGlCompressedTexSubImage2D)
pGlCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
#elif defined(GL_ARB_texture_compression)
glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
#else
os::Printer::log("glCompressedTexSubImage2D not supported", ELL_ERROR);
#endif
}
inline void COpenGLExtensionHandler::extGlBindFramebuffer(GLenum target, GLuint framebuffer) inline void COpenGLExtensionHandler::extGlBindFramebuffer(GLenum target, GLuint framebuffer)
{ {
#ifdef _IRR_OPENGL_USE_EXTPOINTER_ #ifdef _IRR_OPENGL_USE_EXTPOINTER_
......
This diff is collapsed.
...@@ -169,6 +169,8 @@ protected: ...@@ -169,6 +169,8 @@ protected:
bool ReadOnlyLock; bool ReadOnlyLock;
bool KeepImage; bool KeepImage;
bool Compressed;
mutable SStatesCache StatesCache; mutable SStatesCache StatesCache;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment