Commit 96a10f2d authored by nadro's avatar nadro

- Fixed some methods and variables names in IImage/CImage classes.

- Added query feature related to DXT compressed textures.
- Added compressed textures support for D3D9.
- Fixed minor bugs in OpenGL related to compressed textures handling.
- Properly handle compressed textures in D3D8 and Software drivers (Those drivers doesn't support compressed textures).

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@4450 dfc29bdd-3216-0410-991c-e03cc46cb475
parent e2aee66c
...@@ -118,6 +118,9 @@ namespace video ...@@ -118,6 +118,9 @@ namespace video
//! Support for texture coord transformation via texture matrix //! Support for texture coord transformation via texture matrix
EVDF_TEXTURE_MATRIX, EVDF_TEXTURE_MATRIX,
//! Support for DXTn compressed textures.
EVDF_TEXTURE_COMPRESSED_DXT,
//! Only used for counting the elements of this enum //! Only used for counting the elements of this enum
EVDF_COUNT EVDF_COUNT
}; };
......
...@@ -101,8 +101,9 @@ public: ...@@ -101,8 +101,9 @@ public:
//! Inform whether the image is compressed //! Inform whether the image is compressed
virtual bool isCompressed() const = 0; virtual bool isCompressed() const = 0;
//! Inform wheather the image has mipmaps //! Check whether the image has MipMaps
virtual bool hasMipMap() const = 0; /** \return True if image has MipMaps, else false. */
virtual bool hasMipMaps() 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)
......
...@@ -610,6 +610,8 @@ bool CD3D8Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const ...@@ -610,6 +610,8 @@ bool CD3D8Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
case EVDF_BLEND_OPERATIONS: case EVDF_BLEND_OPERATIONS:
case EVDF_TEXTURE_MATRIX: case EVDF_TEXTURE_MATRIX:
return true; return true;
case EVDF_TEXTURE_COMPRESSED_DXT:
return false; // TO-DO
default: default:
return false; return false;
}; };
......
...@@ -67,6 +67,15 @@ HasMipMaps(false), IsRenderTarget(false) ...@@ -67,6 +67,15 @@ HasMipMaps(false), IsRenderTarget(false)
if (image) if (image)
{ {
if(image->getColorFormat() == ECF_DXT1 || image->getColorFormat() == ECF_DXT2 || image->getColorFormat() == ECF_DXT3 || image->getColorFormat() == ECF_DXT4 || image->getColorFormat() == ECF_DXT5)
{
if(!Driver->queryFeature(EVDF_TEXTURE_COMPRESSED_DXT))
{
os::Printer::log("DXT texture compression not available.", ELL_ERROR);
return;
}
}
if (createTexture(flags, image)) if (createTexture(flags, image))
{ {
if (copyTexture(image)) if (copyTexture(image))
......
...@@ -682,6 +682,8 @@ bool CD3D9Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const ...@@ -682,6 +682,8 @@ bool CD3D9Driver::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
case EVDF_BLEND_OPERATIONS: case EVDF_BLEND_OPERATIONS:
case EVDF_TEXTURE_MATRIX: case EVDF_TEXTURE_MATRIX:
return true; return true;
case EVDF_TEXTURE_COMPRESSED_DXT:
return true;
default: default:
return false; return false;
}; };
......
...@@ -34,7 +34,7 @@ CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& si ...@@ -34,7 +34,7 @@ CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& si
const io::path& name, const ECOLOR_FORMAT format) const io::path& name, const ECOLOR_FORMAT format)
: ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0), : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0),
TextureSize(size), ImageSize(size), Pitch(0), ColorFormat(ECF_UNKNOWN), TextureSize(size), ImageSize(size), Pitch(0), ColorFormat(ECF_UNKNOWN),
HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(true) HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(true), IsCompressed(false)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CD3D9Texture"); setDebugName("CD3D9Texture");
...@@ -53,7 +53,7 @@ CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver, ...@@ -53,7 +53,7 @@ CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver,
u32 flags, const io::path& name, void* mipmapData) u32 flags, const io::path& name, void* mipmapData)
: ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0), : ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0),
TextureSize(0,0), ImageSize(0,0), Pitch(0), ColorFormat(ECF_UNKNOWN), TextureSize(0,0), ImageSize(0,0), Pitch(0), ColorFormat(ECF_UNKNOWN),
HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false) HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false), IsCompressed(false)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("CD3D9Texture"); setDebugName("CD3D9Texture");
...@@ -67,10 +67,34 @@ CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver, ...@@ -67,10 +67,34 @@ CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver,
if (image) if (image)
{ {
if(image->getColorFormat() == ECF_DXT1 || image->getColorFormat() == ECF_DXT2 || image->getColorFormat() == ECF_DXT3 || image->getColorFormat() == ECF_DXT4 || image->getColorFormat() == ECF_DXT5)
{
if(!Driver->queryFeature(EVDF_TEXTURE_COMPRESSED_DXT))
{
os::Printer::log("DXT texture compression not available.", ELL_ERROR);
return;
}
}
if (createTexture(flags, image)) if (createTexture(flags, image))
{ {
if (copyTexture(image)) if (copyTexture(image))
{ {
if (IsCompressed && !mipmapData)
if (HasMipMaps && image->hasMipMaps())
{
u32 compressedDataSize = 0;
if(ColorFormat == ECF_DXT1)
compressedDataSize = ((image->getDimension().Width + 3) / 4) * ((image->getDimension().Height + 3) / 4) * 8;
else if (ColorFormat == ECF_DXT2 || ColorFormat == ECF_DXT3 || ColorFormat == ECF_DXT4 || ColorFormat == ECF_DXT5)
compressedDataSize = ((image->getDimension().Width + 3) / 4) * ((image->getDimension().Height + 3) / 4) * 16;
mipmapData = static_cast<u8*>(image->lock())+compressedDataSize;
}
else
HasMipMaps = false;
regenerateMipMapLevels(mipmapData); regenerateMipMapLevels(mipmapData);
} }
} }
...@@ -303,12 +327,43 @@ bool CD3D9Texture::createTexture(u32 flags, IImage * image) ...@@ -303,12 +327,43 @@ bool CD3D9Texture::createTexture(u32 flags, IImage * image)
format = D3DFMT_R5G6B5; format = D3DFMT_R5G6B5;
} }
const bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS); if(image->getColorFormat() == ECF_DXT1 || image->getColorFormat() == ECF_DXT2 || image->getColorFormat() == ECF_DXT3 || image->getColorFormat() == ECF_DXT4 || image->getColorFormat() == ECF_DXT5)
{
ColorFormat = image->getColorFormat();
switch(ColorFormat)
{
case ECF_DXT1:
format = D3DFMT_DXT1;
break;
case ECF_DXT2:
format = D3DFMT_DXT2;
break;
case ECF_DXT3:
format = D3DFMT_DXT3;
break;
case ECF_DXT4:
format = D3DFMT_DXT4;
break;
case ECF_DXT5:
format = D3DFMT_DXT5;
break;
default:
break;
}
IsCompressed = true;
}
bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
if (IsCompressed && !image->hasMipMaps())
mipmaps = false;
DWORD usage = 0; DWORD usage = 0;
// This enables hardware mip map generation. // This enables hardware mip map generation.
if (mipmaps && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) if (!IsCompressed && mipmaps && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
{ {
LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9; LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9;
D3DDISPLAYMODE d3ddm; D3DDISPLAYMODE d3ddm;
...@@ -326,7 +381,7 @@ bool CD3D9Texture::createTexture(u32 flags, IImage * image) ...@@ -326,7 +381,7 @@ bool CD3D9Texture::createTexture(u32 flags, IImage * image)
usage, // usage usage, // usage
format, D3DPOOL_MANAGED , &Texture, NULL); format, D3DPOOL_MANAGED , &Texture, NULL);
if (FAILED(hr)) if (!IsCompressed && FAILED(hr))
{ {
// try brute force 16 bit // try brute force 16 bit
HardwareMipMaps = false; HardwareMipMaps = false;
...@@ -342,8 +397,11 @@ bool CD3D9Texture::createTexture(u32 flags, IImage * image) ...@@ -342,8 +397,11 @@ bool CD3D9Texture::createTexture(u32 flags, IImage * image)
0, format, D3DPOOL_MANAGED, &Texture, NULL); 0, format, D3DPOOL_MANAGED, &Texture, NULL);
} }
ColorFormat = Driver->getColorFormatFromD3DFormat(format); if (!IsCompressed)
ColorFormat = Driver->getColorFormatFromD3DFormat(format);
setPitch(format); setPitch(format);
return (SUCCEEDED(hr)); return (SUCCEEDED(hr));
} }
...@@ -367,8 +425,22 @@ bool CD3D9Texture::copyTexture(IImage * image) ...@@ -367,8 +425,22 @@ bool CD3D9Texture::copyTexture(IImage * image)
return false; return false;
} }
Pitch = rect.Pitch; if (IsCompressed)
image->copyToScaling(rect.pBits, TextureSize.Width, TextureSize.Height, ColorFormat, Pitch); {
u32 compressedDataSize = 0;
if(ColorFormat == ECF_DXT1)
compressedDataSize = ((TextureSize.Width + 3) / 4) * ((TextureSize.Height + 3) / 4) * 8;
else if (ColorFormat == ECF_DXT2 || ColorFormat == ECF_DXT3 || ColorFormat == ECF_DXT4 || ColorFormat == ECF_DXT5)
compressedDataSize = ((TextureSize.Width + 3) / 4) * ((TextureSize.Height + 3) / 4) * 16;
memcpy(rect.pBits, image->lock(), compressedDataSize);
}
else
{
Pitch = rect.Pitch;
image->copyToScaling(rect.pBits, TextureSize.Width, TextureSize.Height, ColorFormat, Pitch);
}
hr = Texture->UnlockRect(0); hr = Texture->UnlockRect(0);
if (FAILED(hr)) if (FAILED(hr))
...@@ -385,6 +457,9 @@ bool CD3D9Texture::copyTexture(IImage * image) ...@@ -385,6 +457,9 @@ bool CD3D9Texture::copyTexture(IImage * image)
//! lock function //! lock function
void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
{ {
if (IsCompressed) // TO-DO
return 0;
if (!Texture) if (!Texture)
return 0; return 0;
...@@ -443,6 +518,9 @@ void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) ...@@ -443,6 +518,9 @@ void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
//! unlock function //! unlock function
void CD3D9Texture::unlock() void CD3D9Texture::unlock()
{ {
if (IsCompressed) // TO-DO
return;
if (!Texture) if (!Texture)
return; return;
...@@ -591,8 +669,15 @@ void CD3D9Texture::copy32BitMipMap(char* src, char* tgt, ...@@ -591,8 +669,15 @@ void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,
//! modifying the texture //! modifying the texture
void CD3D9Texture::regenerateMipMapLevels(void* mipmapData) void CD3D9Texture::regenerateMipMapLevels(void* mipmapData)
{ {
if (!HasMipMaps)
return;
if (IsCompressed && !mipmapData)
return;
if (mipmapData) if (mipmapData)
{ {
u32 compressedDataSize = 0;
core::dimension2du size = TextureSize; core::dimension2du size = TextureSize;
u32 level=0; u32 level=0;
do do
...@@ -602,6 +687,7 @@ void CD3D9Texture::regenerateMipMapLevels(void* mipmapData) ...@@ -602,6 +687,7 @@ void CD3D9Texture::regenerateMipMapLevels(void* mipmapData)
if (size.Height>1) if (size.Height>1)
size.Height /=2; size.Height /=2;
++level; ++level;
IDirect3DSurface9* mipSurface = 0; IDirect3DSurface9* mipSurface = 0;
HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface); HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface);
if (FAILED(hr) || !mipSurface) if (FAILED(hr) || !mipSurface)
...@@ -621,8 +707,22 @@ void CD3D9Texture::regenerateMipMapLevels(void* mipmapData) ...@@ -621,8 +707,22 @@ void CD3D9Texture::regenerateMipMapLevels(void* mipmapData)
return; return;
} }
memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width); if (IsCompressed)
mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width; {
if(ColorFormat == ECF_DXT1)
compressedDataSize = ((size.Width + 3) / 4) * ((size.Height + 3) / 4) * 8;
else if (ColorFormat == ECF_DXT2 || ColorFormat == ECF_DXT3 || ColorFormat == ECF_DXT4 || ColorFormat == ECF_DXT5)
compressedDataSize = ((size.Width + 3) / 4) * ((size.Height + 3) / 4) * 16;
memcpy(miplr.pBits, mipmapData, compressedDataSize);
mipmapData = static_cast<u8*>(mipmapData)+compressedDataSize;
}
else
{
memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width);
mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width;
}
// unlock // unlock
mipSurface->UnlockRect(); mipSurface->UnlockRect();
// release // release
...@@ -687,6 +787,14 @@ void CD3D9Texture::setPitch(D3DFORMAT d3dformat) ...@@ -687,6 +787,14 @@ void CD3D9Texture::setPitch(D3DFORMAT d3dformat)
case D3DFMT_R8G8B8: case D3DFMT_R8G8B8:
Pitch = TextureSize.Width * 3; Pitch = TextureSize.Width * 3;
break; break;
case D3DFMT_DXT1:
Pitch = TextureSize.Width * 2;
break;
case D3DFMT_DXT2:
case D3DFMT_DXT3:
case D3DFMT_DXT4:
case D3DFMT_DXT5:
Pitch = TextureSize.Width * 4;
default: default:
Pitch = 0; Pitch = 0;
}; };
......
...@@ -117,6 +117,7 @@ private: ...@@ -117,6 +117,7 @@ private:
bool HasMipMaps; bool HasMipMaps;
bool HardwareMipMaps; bool HardwareMipMaps;
bool IsRenderTarget; bool IsRenderTarget;
bool IsCompressed;
}; };
......
...@@ -15,7 +15,7 @@ namespace video ...@@ -15,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), Compressed(false) :Data(0), Size(size), Format(format), DeleteMemory(true), IsCompressed(false), HasMipMaps(false)
{ {
initData(); initData();
} }
...@@ -23,8 +23,8 @@ CImage::CImage(ECOLOR_FORMAT format, const core::dimension2d<u32>& size) ...@@ -23,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 compressed, bool hasMipMapData) bool ownForeignMemory, bool deleteForeignMemory, bool compressed, bool mipMaps)
: Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory), Compressed(compressed), HasMipMap(hasMipMapData) : Data(0), Size(size), Format(format), DeleteMemory(deleteForeignMemory), IsCompressed(compressed), HasMipMaps(mipMaps)
{ {
if (ownForeignMemory) if (ownForeignMemory)
{ {
...@@ -182,7 +182,7 @@ u32 CImage::getAlphaMask() const ...@@ -182,7 +182,7 @@ 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) if (IsCompressed)
{ {
os::Printer::log("IImage::setPixel method doesn't work with compressed images.", ELL_WARNING); os::Printer::log("IImage::setPixel method doesn't work with compressed images.", ELL_WARNING);
return; return;
...@@ -229,7 +229,7 @@ void CImage::setPixel(u32 x, u32 y, const SColor &color, bool blend) ...@@ -229,7 +229,7 @@ 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) if (IsCompressed)
{ {
os::Printer::log("IImage::getPixel method doesn't work with compressed images.", ELL_WARNING); os::Printer::log("IImage::getPixel method doesn't work with compressed images.", ELL_WARNING);
return SColor(0); return SColor(0);
...@@ -271,7 +271,7 @@ ECOLOR_FORMAT CImage::getColorFormat() const ...@@ -271,7 +271,7 @@ 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) if (IsCompressed)
{ {
os::Printer::log("IImage::copyTo method doesn't work with compressed images.", ELL_WARNING); os::Printer::log("IImage::copyTo method doesn't work with compressed images.", ELL_WARNING);
return; return;
...@@ -284,7 +284,7 @@ void CImage::copyTo(IImage* target, const core::position2d<s32>& pos) ...@@ -284,7 +284,7 @@ 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) if (IsCompressed)
{ {
os::Printer::log("IImage::copyTo method doesn't work with compressed images.", ELL_WARNING); os::Printer::log("IImage::copyTo method doesn't work with compressed images.", ELL_WARNING);
return; return;
...@@ -297,7 +297,7 @@ void CImage::copyTo(IImage* target, const core::position2d<s32>& pos, const core ...@@ -297,7 +297,7 @@ 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) if (IsCompressed)
{ {
os::Printer::log("IImage::copyToWithAlpha method doesn't work with compressed images.", ELL_WARNING); os::Printer::log("IImage::copyToWithAlpha method doesn't work with compressed images.", ELL_WARNING);
return; return;
...@@ -313,7 +313,7 @@ void CImage::copyToWithAlpha(IImage* target, const core::position2d<s32>& pos, c ...@@ -313,7 +313,7 @@ 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) if (IsCompressed)
{ {
os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING); os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING);
return; return;
...@@ -375,7 +375,7 @@ void CImage::copyToScaling(void* target, u32 width, u32 height, ECOLOR_FORMAT fo ...@@ -375,7 +375,7 @@ 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) if (IsCompressed)
{ {
os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING); os::Printer::log("IImage::copyToScaling method doesn't work with compressed images.", ELL_WARNING);
return; return;
...@@ -400,7 +400,7 @@ void CImage::copyToScaling(IImage* target) ...@@ -400,7 +400,7 @@ 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) if (IsCompressed)
{ {
os::Printer::log("IImage::copyToScalingBoxFilter method doesn't work with compressed images.", ELL_WARNING); os::Printer::log("IImage::copyToScalingBoxFilter method doesn't work with compressed images.", ELL_WARNING);
return; return;
...@@ -438,7 +438,7 @@ void CImage::copyToScalingBoxFilter(IImage* target, s32 bias, bool blend) ...@@ -438,7 +438,7 @@ 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) if (IsCompressed)
{ {
os::Printer::log("IImage::fill method doesn't work with compressed images.", ELL_WARNING); os::Printer::log("IImage::fill method doesn't work with compressed images.", ELL_WARNING);
return; return;
...@@ -482,20 +482,21 @@ void CImage::fill(const SColor &color) ...@@ -482,20 +482,21 @@ void CImage::fill(const SColor &color)
//! Inform whether the image is compressed //! Inform whether the image is compressed
bool CImage::isCompressed() const bool CImage::isCompressed() const
{ {
return Compressed; return IsCompressed;
} }
//! Inform wheather the image store mipmaps //! Check whether the image has MipMaps
bool CImage::hasMipMap() const bool CImage::hasMipMaps() const
{ {
return HasMipMap; return HasMipMaps;
} }
//! 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) if (IsCompressed)
{ {
os::Printer::log("IImage::getPixelBox method doesn't work with compressed images.", ELL_WARNING); os::Printer::log("IImage::getPixelBox method doesn't work with compressed images.", ELL_WARNING);
return SColor(0); return SColor(0);
......
...@@ -24,7 +24,8 @@ public: ...@@ -24,7 +24,8 @@ 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, bool compressed = false, bool hasMipMapData = false); void* data, bool ownForeignMemory=true, bool deleteMemory = true,
bool compressed = false, bool mipMaps = 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);
...@@ -106,8 +107,9 @@ public: ...@@ -106,8 +107,9 @@ public:
//! Inform whether the image is compressed //! Inform whether the image is compressed
virtual bool isCompressed() const; virtual bool isCompressed() const;
//! Inform wheather the image has mipmaps //! Check whether the image has MipMaps
virtual bool hasMipMap() const; /** \return True if image has MipMaps, else false. */
virtual bool hasMipMaps() const;
private: private:
...@@ -122,10 +124,10 @@ private: ...@@ -122,10 +124,10 @@ private:
u32 Pitch; u32 Pitch;
ECOLOR_FORMAT Format; ECOLOR_FORMAT Format;
bool DeleteMemory; bool IsCompressed;
bool HasMipMaps;
bool Compressed; bool DeleteMemory;
bool HasMipMap;
}; };
} // end namespace video } // end namespace video
......
...@@ -789,6 +789,8 @@ bool COpenGLExtensionHandler::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const ...@@ -789,6 +789,8 @@ bool COpenGLExtensionHandler::queryFeature(E_VIDEO_DRIVER_FEATURE feature) const
FeatureAvailable[IRR_EXT_blend_subtract] || FeatureAvailable[IRR_EXT_blend_logic_op]; FeatureAvailable[IRR_EXT_blend_subtract] || FeatureAvailable[IRR_EXT_blend_logic_op];
case EVDF_TEXTURE_MATRIX: case EVDF_TEXTURE_MATRIX:
return true; return true;
case EVDF_TEXTURE_COMPRESSED_DXT:
return FeatureAvailable[IRR_EXT_texture_compression_s3tc];
default: default:
return false; return false;
}; };
......
...@@ -25,7 +25,7 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mi ...@@ -25,7 +25,7 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mi
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT),
PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), MipmapLegacyMode(true), PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), MipmapLegacyMode(true),
IsRenderTarget(false), AutomaticMipmapUpdate(false), IsRenderTarget(false), AutomaticMipmapUpdate(false),
ReadOnlyLock(false), KeepImage(true), Compressed(false) ReadOnlyLock(false), KeepImage(true), IsCompressed(false)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("COpenGLTexture"); setDebugName("COpenGLTexture");
...@@ -34,10 +34,14 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mi ...@@ -34,10 +34,14 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mi
HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS); HasMipMaps = Driver->getTextureCreationFlag(ETCF_CREATE_MIP_MAPS);
getImageValues(origImage); getImageValues(origImage);
glGenTextures(1, &TextureName);
if (ColorFormat == ECF_DXT1 || ColorFormat == ECF_DXT2 || ColorFormat == ECF_DXT3 || ColorFormat == ECF_DXT4 || ColorFormat == ECF_DXT5) if (ColorFormat == ECF_DXT1 || ColorFormat == ECF_DXT2 || ColorFormat == ECF_DXT3 || ColorFormat == ECF_DXT4 || ColorFormat == ECF_DXT5)
{ {
if(!Driver->queryFeature(EVDF_TEXTURE_COMPRESSED_DXT))
{
os::Printer::log("DXT texture compression not available.", ELL_ERROR);
return;
}
if(ImageSize != TextureSize) if(ImageSize != TextureSize)
{ {
os::Printer::log("Invalid size of image for compressed texture, size of image must be POT.", ELL_ERROR); os::Printer::log("Invalid size of image for compressed texture, size of image must be POT.", ELL_ERROR);
...@@ -45,9 +49,10 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mi ...@@ -45,9 +49,10 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mi
} }
else else
{ {
Compressed = true; IsCompressed = true;
Image = origImage; Image = origImage;
Image->grab(); Image->grab();
KeepImage = false;
} }
} }
else if (ImageSize==TextureSize) else if (ImageSize==TextureSize)
...@@ -61,6 +66,7 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mi ...@@ -61,6 +66,7 @@ COpenGLTexture::COpenGLTexture(IImage* origImage, const io::path& name, void* mi
// scale texture // scale texture
origImage->copyToScaling(Image); origImage->copyToScaling(Image);
} }
glGenTextures(1, &TextureName);
uploadTexture(true, mipmapData); uploadTexture(true, mipmapData);
if (!KeepImage) if (!KeepImage)
{ {
...@@ -76,7 +82,7 @@ COpenGLTexture::COpenGLTexture(const io::path& name, COpenGLDriver* driver) ...@@ -76,7 +82,7 @@ COpenGLTexture::COpenGLTexture(const io::path& name, COpenGLDriver* driver)
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT), TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_BGRA_EXT),
PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), HasMipMaps(true), PixelType(GL_UNSIGNED_BYTE), MipLevelStored(0), HasMipMaps(true),
MipmapLegacyMode(true), IsRenderTarget(false), AutomaticMipmapUpdate(false), MipmapLegacyMode(true), IsRenderTarget(false), AutomaticMipmapUpdate(false),
ReadOnlyLock(false), KeepImage(true), Compressed(false) ReadOnlyLock(false), KeepImage(true), IsCompressed(false)
{ {
#ifdef _DEBUG #ifdef _DEBUG
setDebugName("COpenGLTexture"); setDebugName("COpenGLTexture");
...@@ -359,7 +365,7 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) ...@@ -359,7 +365,7 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
if (!level && newTexture) if (!level && newTexture)
{ {
// auto generate if possible and no mipmap data is given // auto generate if possible and no mipmap data is given
if (!Compressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) if (!IsCompressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
{ {
if (!Driver->queryFeature(EVDF_FRAMEBUFFER_OBJECT)) if (!Driver->queryFeature(EVDF_FRAMEBUFFER_OBJECT))
{ {
...@@ -405,7 +411,7 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) ...@@ -405,7 +411,7 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
void* source = image->lock(); void* source = image->lock();
if (newTexture) if (newTexture)
{ {
if(Compressed) if (IsCompressed)
{ {
if(ColorFormat == ECF_DXT1) if(ColorFormat == ECF_DXT1)
compressedDataSize = ((image->getDimension().Width + 3) / 4) * ((image->getDimension().Height + 3) / 4) * 8; compressedDataSize = ((image->getDimension().Width + 3) / 4) * ((image->getDimension().Height + 3) / 4) * 8;
...@@ -421,7 +427,7 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) ...@@ -421,7 +427,7 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
} }
else else
{ {
if(Compressed) if (IsCompressed)
{ {
if(ColorFormat == ECF_DXT1) if(ColorFormat == ECF_DXT1)
compressedDataSize = ((image->getDimension().Width + 3) / 4) * ((image->getDimension().Height + 3) / 4) * 8; compressedDataSize = ((image->getDimension().Width + 3) / 4) * ((image->getDimension().Height + 3) / 4) * 8;
...@@ -439,7 +445,7 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) ...@@ -439,7 +445,7 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
if (!level && newTexture) if (!level && newTexture)
{ {
if (!Compressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE)) if (!IsCompressed && HasMipMaps && !mipmapData && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
{ {
if (!MipmapLegacyMode && AutomaticMipmapUpdate) if (!MipmapLegacyMode && AutomaticMipmapUpdate)
{ {
...@@ -453,8 +459,8 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) ...@@ -453,8 +459,8 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
// or use predefined mipmap data eg. for compressed textures // or use predefined mipmap data eg. for compressed textures
AutomaticMipmapUpdate=false; AutomaticMipmapUpdate=false;
if (Compressed) if (IsCompressed && !mipmapData)
if (image->hasMipMap()) if (image->hasMipMaps())
mipmapData = static_cast<u8*>(image->lock())+compressedDataSize; mipmapData = static_cast<u8*>(image->lock())+compressedDataSize;
else else
HasMipMaps = false; HasMipMaps = false;
...@@ -482,7 +488,7 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level) ...@@ -482,7 +488,7 @@ void COpenGLTexture::uploadTexture(bool newTexture, void* mipmapData, u32 level)
//! lock function //! lock function
void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
{ {
if (Compressed) // TO-DO if (IsCompressed) // TO-DO
return 0; return 0;
// store info about which image is locked // store info about which image is locked
...@@ -590,7 +596,7 @@ void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel) ...@@ -590,7 +596,7 @@ void* COpenGLTexture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
//! unlock function //! unlock function
void COpenGLTexture::unlock() void COpenGLTexture::unlock()
{ {
if (Compressed) // TO-DO if (IsCompressed) // TO-DO
return; return;
// test if miplevel or main texture was locked // test if miplevel or main texture was locked
...@@ -678,11 +684,10 @@ bool COpenGLTexture::hasMipMaps() const ...@@ -678,11 +684,10 @@ bool COpenGLTexture::hasMipMaps() const
//! modifying the texture //! modifying the texture
void COpenGLTexture::regenerateMipMapLevels(void* mipmapData) void COpenGLTexture::regenerateMipMapLevels(void* mipmapData)
{ {
if(Compressed && !mipmapData)
return;
if (AutomaticMipmapUpdate || !HasMipMaps || !Image) if (AutomaticMipmapUpdate || !HasMipMaps || !Image)
return; return;
if (IsCompressed && !mipmapData)
return;
if ((Image->getDimension().Width==1) && (Image->getDimension().Height==1)) if ((Image->getDimension().Width==1) && (Image->getDimension().Height==1))
return; return;
...@@ -708,7 +713,7 @@ void COpenGLTexture::regenerateMipMapLevels(void* mipmapData) ...@@ -708,7 +713,7 @@ void COpenGLTexture::regenerateMipMapLevels(void* mipmapData)
if (!mipmapData) if (!mipmapData)
Image->copyToScaling(target, width, height, Image->getColorFormat()); Image->copyToScaling(target, width, height, Image->getColorFormat());
if (Compressed) if (IsCompressed)
{ {
if(ColorFormat == ECF_DXT1) if(ColorFormat == ECF_DXT1)
compressedDataSize = ((width + 3) / 4) * ((height + 3) / 4) * 8; compressedDataSize = ((width + 3) / 4) * ((height + 3) / 4) * 8;
...@@ -725,7 +730,7 @@ void COpenGLTexture::regenerateMipMapLevels(void* mipmapData) ...@@ -725,7 +730,7 @@ void COpenGLTexture::regenerateMipMapLevels(void* mipmapData)
// get next prepared mipmap data if available // get next prepared mipmap data if available
if (mipmapData) if (mipmapData)
{ {
if (Compressed) if (IsCompressed)
mipmapData = static_cast<u8*>(mipmapData)+compressedDataSize; mipmapData = static_cast<u8*>(mipmapData)+compressedDataSize;
else else
mipmapData = static_cast<u8*>(mipmapData)+width*height*Image->getBytesPerPixel(); mipmapData = static_cast<u8*>(mipmapData)+width*height*Image->getBytesPerPixel();
......
...@@ -165,12 +165,11 @@ protected: ...@@ -165,12 +165,11 @@ protected:
bool HasMipMaps; bool HasMipMaps;
bool MipmapLegacyMode; bool MipmapLegacyMode;
bool IsRenderTarget; bool IsRenderTarget;
bool IsCompressed;
bool AutomaticMipmapUpdate; bool AutomaticMipmapUpdate;
bool ReadOnlyLock; bool ReadOnlyLock;
bool KeepImage; bool KeepImage;
bool Compressed;
mutable SStatesCache StatesCache; mutable SStatesCache StatesCache;
}; };
......
...@@ -24,11 +24,21 @@ CSoftwareTexture::CSoftwareTexture(IImage* image, const io::path& name, ...@@ -24,11 +24,21 @@ CSoftwareTexture::CSoftwareTexture(IImage* image, const io::path& name,
if (image) if (image)
{ {
bool IsCompressed = false;
if(image->getColorFormat() == ECF_DXT1 || image->getColorFormat() == ECF_DXT2 || image->getColorFormat() == ECF_DXT3 || image->getColorFormat() == ECF_DXT4 || image->getColorFormat() == ECF_DXT5)
{
os::Printer::log("DXT texture compression not available.", ELL_ERROR);
IsCompressed = true;
}
OrigSize = image->getDimension(); OrigSize = image->getDimension();
core::dimension2d<u32> optSize=OrigSize.getOptimalSize(); core::dimension2d<u32> optSize=OrigSize.getOptimalSize();
Image = new CImage(ECF_A1R5G5B5, OrigSize); Image = new CImage(ECF_A1R5G5B5, OrigSize);
image->copyTo(Image);
if (!IsCompressed)
image->copyTo(Image);
if (optSize == OrigSize) if (optSize == OrigSize)
{ {
......
...@@ -32,6 +32,14 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, ...@@ -32,6 +32,14 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name,
if (image) if (image)
{ {
bool IsCompressed = false;
if(image->getColorFormat() == ECF_DXT1 || image->getColorFormat() == ECF_DXT2 || image->getColorFormat() == ECF_DXT3 || image->getColorFormat() == ECF_DXT4 || image->getColorFormat() == ECF_DXT5)
{
os::Printer::log("DXT texture compression not available.", ELL_ERROR);
IsCompressed = true;
}
OrigSize = image->getDimension(); OrigSize = image->getDimension();
OriginalFormat = image->getColorFormat(); OriginalFormat = image->getColorFormat();
...@@ -49,7 +57,9 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, ...@@ -49,7 +57,9 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name,
if ( OrigSize == optSize ) if ( OrigSize == optSize )
{ {
MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, image->getDimension()); MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, image->getDimension());
image->copyTo(MipMap[0]);
if (!IsCompressed)
image->copyTo(MipMap[0]);
} }
else else
{ {
...@@ -64,7 +74,9 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name, ...@@ -64,7 +74,9 @@ CSoftwareTexture2::CSoftwareTexture2(IImage* image, const io::path& name,
OrigSize = optSize; OrigSize = optSize;
os::Printer::log ( buf, ELL_WARNING ); os::Printer::log ( buf, ELL_WARNING );
MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, optSize); MipMap[0] = new CImage(BURNINGSHADER_COLOR_FORMAT, optSize);
image->copyToScalingBoxFilter ( MipMap[0],0, false );
if (!IsCompressed)
image->copyToScalingBoxFilter ( MipMap[0],0, false );
} }
OrigImageDataSizeInPixels = (f32) 0.3f * MipMap[0]->getImageDataSizeInPixels(); OrigImageDataSizeInPixels = (f32) 0.3f * MipMap[0]->getImageDataSizeInPixels();
......
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