Commit d72c407e authored by nadro's avatar nadro

- Fixed issue with DXT file formats in D3D9.

- Added cube maps support to PVR file loader.
- Added support for load cube maps directly via IVideoDriver::getTexture call.

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@5259 dfc29bdd-3216-0410-991c-e03cc46cb475
parent deacb5b9
...@@ -16,6 +16,16 @@ namespace irr ...@@ -16,6 +16,16 @@ namespace irr
namespace video namespace video
{ {
//! Enumeration describing the type of ITexture.
enum E_TEXTURE_TYPE
{
//! 2D texture.
ETT_2D,
//! Cubemap texture.
ETT_CUBEMAP
};
//! Interface for software image data. //! Interface for software image data.
/** Image loaders create these images from files. IVideoDrivers convert /** Image loaders create these images from files. IVideoDrivers convert
these images into their (hardware) textures. these images into their (hardware) textures.
......
...@@ -47,8 +47,9 @@ public: ...@@ -47,8 +47,9 @@ public:
//! Creates a multiple surfaces from the file eg. whole cube map. //! Creates a multiple surfaces from the file eg. whole cube map.
/** \param file File handle to check. /** \param file File handle to check.
\param type Pointer to E_TEXTURE_TYPE where a recommended type of the texture will be stored.
\return Array of pointers to newly created images. */ \return Array of pointers to newly created images. */
virtual core::array<IImage*> IImageLoader::loadImages(io::IReadFile* file) const virtual core::array<IImage*> IImageLoader::loadImages(io::IReadFile* file, E_TEXTURE_TYPE* type) const
{ {
core::array<IImage*> image; core::array<IImage*> image;
......
...@@ -92,16 +92,6 @@ enum E_TEXTURE_LOCK_MODE ...@@ -92,16 +92,6 @@ enum E_TEXTURE_LOCK_MODE
ETLM_WRITE_ONLY ETLM_WRITE_ONLY
}; };
//! Enumeration describing the type of ITexture.
enum E_TEXTURE_TYPE
{
//! 2D texture.
ETT_2D,
//! Cubemap texture.
ETT_CUBEMAP
};
//! Where did the last IVideoDriver::getTexture call find this texture //! Where did the last IVideoDriver::getTexture call find this texture
enum E_TEXTURE_SOURCE enum E_TEXTURE_SOURCE
{ {
......
...@@ -1189,20 +1189,22 @@ namespace video ...@@ -1189,20 +1189,22 @@ namespace video
method is useful for example if you want to read a heightmap method is useful for example if you want to read a heightmap
for a terrain renderer. for a terrain renderer.
\param filename Name of the file from which the images are created. \param filename Name of the file from which the images are created.
\param type Pointer to E_TEXTURE_TYPE where a recommended type of the texture will be stored.
\return The array of created images. \return The array of created images.
If you no longer need those images, you should call IImage::drop() on each of them. If you no longer need those images, you should call IImage::drop() on each of them.
See IReferenceCounted::drop() for more information. */ See IReferenceCounted::drop() for more information. */
virtual core::array<IImage*> createImagesFromFile(const io::path& filename) = 0; virtual core::array<IImage*> createImagesFromFile(const io::path& filename, E_TEXTURE_TYPE* type = 0) = 0;
//! Creates a software images from a file. //! Creates a software images from a file.
/** No hardware texture will be created for those images. This /** No hardware texture will be created for those images. This
method is useful for example if you want to read a heightmap method is useful for example if you want to read a heightmap
for a terrain renderer. for a terrain renderer.
\param file File from which the image is created. \param file File from which the image is created.
\param type Pointer to E_TEXTURE_TYPE where a recommended type of the texture will be stored.
\return The array of created images. \return The array of created images.
If you no longer need those images, you should call IImage::drop() on each of them. If you no longer need those images, you should call IImage::drop() on each of them.
See IReferenceCounted::drop() for more information. */ See IReferenceCounted::drop() for more information. */
virtual core::array<IImage*> createImagesFromFile(io::IReadFile* file) = 0; virtual core::array<IImage*> createImagesFromFile(io::IReadFile* file, E_TEXTURE_TYPE* type = 0) = 0;
//! Creates a software image from a file. //! Creates a software image from a file.
/** No hardware texture will be created for this image. This /** No hardware texture will be created for this image. This
......
...@@ -3375,6 +3375,16 @@ D3DFORMAT CD3D9Driver::getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const ...@@ -3375,6 +3375,16 @@ D3DFORMAT CD3D9Driver::getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const
return D3DFMT_R8G8B8; return D3DFMT_R8G8B8;
case ECF_A8R8G8B8: case ECF_A8R8G8B8:
return D3DFMT_A8R8G8B8; return D3DFMT_A8R8G8B8;
case ECF_DXT1:
return D3DFMT_DXT1;
case ECF_DXT2:
return D3DFMT_DXT2;
case ECF_DXT3:
return D3DFMT_DXT3;
case ECF_DXT4:
return D3DFMT_DXT4;
case ECF_DXT5:
return D3DFMT_DXT5;
case ECF_R16F: case ECF_R16F:
return D3DFMT_R16F; return D3DFMT_R16F;
case ECF_G16R16F: case ECF_G16R16F:
......
...@@ -264,8 +264,8 @@ void CD3D9Texture::regenerateMipMapLevels(void* data, u32 layer) ...@@ -264,8 +264,8 @@ void CD3D9Texture::regenerateMipMapLevels(void* data, u32 layer)
if (data) if (data)
{ {
u32 width = Size.Width >> layer; u32 width = Size.Width;
u32 height = Size.Height >> layer; u32 height = Size.Height;
u8* tmpData = static_cast<u8*>(data); u8* tmpData = static_cast<u8*>(data);
u32 dataSize = 0; u32 dataSize = 0;
u32 level = 0; u32 level = 0;
......
// Copyright (C) 2013-2015 Patryk Nadrowski // Copyright (C) 2013-2016 Patryk Nadrowski
// This file is part of the "Irrlicht Engine". // This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h // For conditions of distribution and use, see copyright notice in irrlicht.h
...@@ -13,19 +13,14 @@ ...@@ -13,19 +13,14 @@
namespace irr namespace irr
{ {
namespace video namespace video
{ {
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
bool CImageLoaderPVR::isALoadableFileExtension(const io::path& filename) const bool CImageLoaderPVR::isALoadableFileExtension(const io::path& filename) const
{ {
return core::hasFileExtension(filename, "pvr"); return core::hasFileExtension(filename, "pvr");
} }
//! returns true if the file maybe is able to be loaded by this class
bool CImageLoaderPVR::isALoadableFileFormat(io::IReadFile* file) const bool CImageLoaderPVR::isALoadableFileFormat(io::IReadFile* file) const
{ {
if (!file) if (!file)
...@@ -37,7 +32,6 @@ bool CImageLoaderPVR::isALoadableFileFormat(io::IReadFile* file) const ...@@ -37,7 +32,6 @@ bool CImageLoaderPVR::isALoadableFileFormat(io::IReadFile* file) const
/*if (header.Version == 0x03525650) // TO-DO - fix endiannes /*if (header.Version == 0x03525650) // TO-DO - fix endiannes
{ {
printf("Bad endian2\n");
fourCC[0] = os::Byteswap::byteswap(fourCC[0]); fourCC[0] = os::Byteswap::byteswap(fourCC[0]);
fourCC[1] = os::Byteswap::byteswap(fourCC[1]); fourCC[1] = os::Byteswap::byteswap(fourCC[1]);
fourCC[2] = os::Byteswap::byteswap(fourCC[2]); fourCC[2] = os::Byteswap::byteswap(fourCC[2]);
...@@ -47,15 +41,35 @@ bool CImageLoaderPVR::isALoadableFileFormat(io::IReadFile* file) const ...@@ -47,15 +41,35 @@ bool CImageLoaderPVR::isALoadableFileFormat(io::IReadFile* file) const
return (fourCC[0] == 'P' && fourCC[1] == 'V' && fourCC[2] == 'R'); return (fourCC[0] == 'P' && fourCC[1] == 'V' && fourCC[2] == 'R');
} }
//! creates a surface from the file
IImage* CImageLoaderPVR::loadImage(io::IReadFile* file) const IImage* CImageLoaderPVR::loadImage(io::IReadFile* file) const
{ {
core::array<IImage*> imageArray = loadImages(file, 0);
const u32 imageCount = imageArray.size();
for (u32 i = 1; i < imageCount; ++i)
{
if (imageArray[i])
imageArray[i]->drop();
}
if (imageCount > 1)
imageArray.erase(1, imageCount - 1);
return (imageCount > 1) ? imageArray[0] : 0;
}
core::array<IImage*> CImageLoaderPVR::loadImages(io::IReadFile* file, E_TEXTURE_TYPE* type) const
{
// TO-DO -> use 'move' feature from C++11 standard.
SPVRHeader header; SPVRHeader header;
IImage* image = 0;
core::array<IImage*> imageArray;
core::array<u8*> mipMapsDataArray;
ECOLOR_FORMAT format = ECF_UNKNOWN; ECOLOR_FORMAT format = ECF_UNKNOWN;
u32 dataSize = 0; u32 dataSize = 0;
u32 mipMapsDataSize = 0;
file->seek(0); file->seek(0);
file->read(&header, sizeof(SPVRHeader)); file->read(&header, sizeof(SPVRHeader));
...@@ -93,102 +107,144 @@ IImage* CImageLoaderPVR::loadImage(io::IReadFile* file) const ...@@ -93,102 +107,144 @@ IImage* CImageLoaderPVR::loadImage(io::IReadFile* file) const
} }
else // Compressed texture formats else // Compressed texture formats
{ {
switch(header.PixelFormat) switch (header.PixelFormat)
{ {
case 0: // PVRTC 2bpp RGB case 0: // PVRTC 2bpp RGB
format = ECF_PVRTC_RGB2; format = ECF_PVRTC_RGB2;
break; break;
case 1: // PVRTC 2bpp RGBA case 1: // PVRTC 2bpp RGBA
format = ECF_PVRTC_ARGB2; format = ECF_PVRTC_ARGB2;
break; break;
case 2: // PVRTC 4bpp RGB case 2: // PVRTC 4bpp RGB
format = ECF_PVRTC_RGB4; format = ECF_PVRTC_RGB4;
break; break;
case 3: // PVRTC 4bpp RGBA case 3: // PVRTC 4bpp RGBA
format = ECF_PVRTC_ARGB4; format = ECF_PVRTC_ARGB4;
break; break;
case 4: // PVRTC-II 2bpp case 4: // PVRTC-II 2bpp
format = ECF_PVRTC2_ARGB2; format = ECF_PVRTC2_ARGB2;
break; break;
case 5: // PVRTC-II 4bpp case 5: // PVRTC-II 4bpp
format = ECF_PVRTC2_ARGB4; format = ECF_PVRTC2_ARGB4;
break; break;
case 6: // ETC1 case 6: // ETC1
format = ECF_ETC1; format = ECF_ETC1;
break; break;
case 7: // DXT1 / BC1 case 7: // DXT1 / BC1
format = ECF_DXT1; format = ECF_DXT1;
break; break;
case 8: // DXT2 case 8: // DXT2
case 9: // DXT3 / BC2 case 9: // DXT3 / BC2
format = ECF_DXT3; format = ECF_DXT3;
break; break;
case 10: // DXT4 case 10: // DXT4
case 11: // DXT5 / BC3 case 11: // DXT5 / BC3
format = ECF_DXT5; format = ECF_DXT5;
break; break;
case 22: // ETC2 RGB case 22: // ETC2 RGB
format = ECF_ETC2_RGB; format = ECF_ETC2_RGB;
break; break;
case 23: // ETC2 RGBA case 23: // ETC2 RGBA
format = ECF_ETC2_ARGB; format = ECF_ETC2_ARGB;
break; break;
default: default:
format = ECF_UNKNOWN; format = ECF_UNKNOWN;
break; break;
} }
if (format != ECF_UNKNOWN) if (format != ECF_UNKNOWN)
{ {
// 3D textures, texture arrays, cube maps textures aren't currently supported imageArray.set_used(1);
if (header.Depth < 2 && header.NumSurfaces < 2 && header.NumFaces < 2) E_TEXTURE_TYPE tmpType = ETT_2D;
// check for texture type
if (header.NumFaces == 6) // cube map
{ {
dataSize = IImage::getDataSizeFromFormat(format, header.Width, header.Height); imageArray.set_used(6);
tmpType = ETT_CUBEMAP;
u8* data = new u8[dataSize]; imageArray.reallocate(6);
file->read(data, dataSize); }
else if (header.Depth > 1) // 3d texture
{
// TO-DO
}
else if (header.NumSurfaces > 1) // texture array
{
// To-DO
}
image = new CImage(format, core::dimension2d<u32>(header.Width, header.Height), data, true, true); if (type)
*type = tmpType;
if (header.MipMapCount > 1) // prepare mipmaps data
{
u32 tmpWidth = header.Width;
u32 tmpHeight = header.Height;
do dataSize = 0;
for (u32 i = 1; i < header.MipMapCount; ++i)
{
u32 tmpWidth = header.Width >> i;
u32 tmpHeight = header.Height >> i;
dataSize += IImage::getDataSizeFromFormat(format, tmpWidth, tmpHeight);
}
if (header.MipMapCount > 1)
{
for (u32 j = 0; j < imageArray.size(); ++j)
mipMapsDataArray.push_back(new u8[dataSize]);
}
// read texture
dataSize = 0;
long offset = 0;
for (u32 i = 0; i < header.MipMapCount; ++i)
{
if (i == 0)
{
for (u32 j = 0; j < imageArray.size(); ++j)
{ {
if (tmpWidth > 1) dataSize = IImage::getDataSizeFromFormat(format, header.Width, header.Height);
tmpWidth >>= 1;
if (tmpHeight > 1) u8* data = new u8[dataSize];
tmpHeight >>= 1; file->read(data, dataSize);
mipMapsDataSize += IImage::getDataSizeFromFormat(format, tmpWidth, tmpHeight); imageArray[j] = new CImage(format, core::dimension2d<u32>(header.Width, header.Height), data, true, true);
} }
while (tmpWidth != 1 || tmpHeight != 1); }
else
{
u32 tmpWidth = header.Width >> i;
u32 tmpHeight = header.Height >> i;
u8* mipMapsData = new u8[mipMapsDataSize]; dataSize = IImage::getDataSizeFromFormat(format, tmpWidth, tmpHeight);
file->read(mipMapsData, mipMapsDataSize);
image->setMipMapsData(mipMapsData, true, true); for (u32 j = 0; j < imageArray.size(); ++j)
file->read(mipMapsDataArray[j] + offset, dataSize);
offset += dataSize;
} }
} }
// assign mipmaps data
for (u32 i = 0; i < mipMapsDataArray.size(); ++i)
imageArray[i]->setMipMapsData(mipMapsDataArray[i], true, true);
} }
} }
return image; return imageArray;
} }
//! creates a loader which is able to load pvr images
IImageLoader* createImageLoaderPVR() IImageLoader* createImageLoaderPVR()
{ {
return new CImageLoaderPVR(); return new CImageLoaderPVR();
} }
}
} // end namespace video }
} // end namespace irr
#endif #endif
// Copyright (C) 2013-2015 Patryk Nadrowski // Copyright (C) 2013-2016 Patryk Nadrowski
// This file is part of the "Irrlicht Engine". // This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h // For conditions of distribution and use, see copyright notice in irrlicht.h
...@@ -16,10 +16,8 @@ namespace irr ...@@ -16,10 +16,8 @@ namespace irr
namespace video namespace video
{ {
// byte-align structures
#include "irrpack.h" #include "irrpack.h"
/* structures */
struct SPVRHeader struct SPVRHeader
{ {
u32 Version; u32 Version;
...@@ -36,29 +34,22 @@ struct SPVRHeader ...@@ -36,29 +34,22 @@ struct SPVRHeader
u32 MetDataSize; u32 MetDataSize;
} PACK_STRUCT; } PACK_STRUCT;
// Default alignment
#include "irrunpack.h" #include "irrunpack.h"
/*!
Surface Loader for PVR images
*/
class CImageLoaderPVR : public IImageLoader class CImageLoaderPVR : public IImageLoader
{ {
public: public:
//! returns true if the file maybe is able to be loaded by this class
//! based on the file extension (e.g. ".tga")
virtual bool isALoadableFileExtension(const io::path& filename) const; virtual bool isALoadableFileExtension(const io::path& filename) const;
//! returns true if the file maybe is able to be loaded by this class
virtual bool isALoadableFileFormat(io::IReadFile* file) const; virtual bool isALoadableFileFormat(io::IReadFile* file) const;
//! creates a surface from the file
virtual IImage* loadImage(io::IReadFile* file) const; virtual IImage* loadImage(io::IReadFile* file) const;
virtual core::array<IImage*> loadImages(io::IReadFile* file, E_TEXTURE_TYPE* type) const;
}; };
} // end namespace video }
} // end namespace irr }
#endif // compiled with PVR loader #endif
#endif #endif
...@@ -493,7 +493,7 @@ ITexture* CNullDriver::addTextureCubemap(const io::path& name, IImage* imagePosX ...@@ -493,7 +493,7 @@ ITexture* CNullDriver::addTextureCubemap(const io::path& name, IImage* imagePosX
ITexture* t = 0; ITexture* t = 0;
core::array<IImage*> imageArray(1); core::array<IImage*> imageArray(6);
imageArray.push_back(imagePosX); imageArray.push_back(imagePosX);
imageArray.push_back(imageNegX); imageArray.push_back(imageNegX);
imageArray.push_back(imagePosY); imageArray.push_back(imagePosY);
...@@ -614,20 +614,37 @@ ITexture* CNullDriver::getTexture(io::IReadFile* file) ...@@ -614,20 +614,37 @@ ITexture* CNullDriver::getTexture(io::IReadFile* file)
video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const io::path& hashName ) video::ITexture* CNullDriver::loadTextureFromFile(io::IReadFile* file, const io::path& hashName )
{ {
ITexture* texture = 0; ITexture* texture = 0;
IImage* image = createImageFromFile(file);
if (image) E_TEXTURE_TYPE type = ETT_2D;
{
core::array<IImage*> imageArray(1);
imageArray.push_back(image);
if (checkImage(imageArray)) core::array<IImage*> imageArray = createImagesFromFile(file, &type);
if (checkImage(imageArray))
{
switch (type)
{ {
texture = createDeviceDependentTexture(hashName.size() ? hashName : file->getFileName(), image); case ETT_2D:
texture = createDeviceDependentTexture(hashName.size() ? hashName : file->getFileName(), imageArray[0]);
break;
case ETT_CUBEMAP:
if (imageArray.size() >= 6 && imageArray[0] && imageArray[1] && imageArray[2] && imageArray[3] && imageArray[4] && imageArray[5])
{
texture = createDeviceDependentTextureCubemap(hashName.size() ? hashName : file->getFileName(), imageArray);
}
break;
default:
_IRR_DEBUG_BREAK_IF(true);
break;
} }
os::Printer::log("Loaded texture", file->getFileName()); if (texture)
image->drop(); os::Printer::log("Loaded texture", file->getFileName());
}
for (u32 i = 0; i < imageArray.size(); ++i)
{
if (imageArray[i])
imageArray[i]->drop();
} }
return texture; return texture;
...@@ -1481,7 +1498,7 @@ bool CNullDriver::getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const ...@@ -1481,7 +1498,7 @@ bool CNullDriver::getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const
return (TextureCreationFlags & flag)!=0; return (TextureCreationFlags & flag)!=0;
} }
core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename) core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename, E_TEXTURE_TYPE* type)
{ {
// TO-DO -> use 'move' feature from C++11 standard. // TO-DO -> use 'move' feature from C++11 standard.
...@@ -1493,7 +1510,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename) ...@@ -1493,7 +1510,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename)
if (file) if (file)
{ {
imageArray = createImagesFromFile(file); imageArray = createImagesFromFile(file, type);
file->drop(); file->drop();
} }
else else
...@@ -1503,7 +1520,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename) ...@@ -1503,7 +1520,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(const io::path& filename)
return imageArray; return imageArray;
} }
core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file) core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file, E_TEXTURE_TYPE* type)
{ {
// TO-DO -> use 'move' feature from C++11 standard. // TO-DO -> use 'move' feature from C++11 standard.
...@@ -1520,7 +1537,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file) ...@@ -1520,7 +1537,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file)
{ {
// reset file position which might have changed due to previous loadImage calls // reset file position which might have changed due to previous loadImage calls
file->seek(0); file->seek(0);
imageArray = SurfaceLoader[i]->loadImages(file); imageArray = SurfaceLoader[i]->loadImages(file, type);
if (imageArray.size() == 0) if (imageArray.size() == 0)
{ {
...@@ -1544,7 +1561,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file) ...@@ -1544,7 +1561,7 @@ core::array<IImage*> CNullDriver::createImagesFromFile(io::IReadFile* file)
if (SurfaceLoader[i]->isALoadableFileFormat(file)) if (SurfaceLoader[i]->isALoadableFileFormat(file))
{ {
file->seek(0); file->seek(0);
imageArray = SurfaceLoader[i]->loadImages(file); imageArray = SurfaceLoader[i]->loadImages(file, type);
if (imageArray.size() == 0) if (imageArray.size() == 0)
{ {
......
...@@ -341,9 +341,9 @@ namespace video ...@@ -341,9 +341,9 @@ namespace video
//! Returns if a texture creation flag is enabled or disabled. //! Returns if a texture creation flag is enabled or disabled.
virtual bool getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const _IRR_OVERRIDE_; virtual bool getTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag) const _IRR_OVERRIDE_;
virtual core::array<IImage*> createImagesFromFile(const io::path& filename) _IRR_OVERRIDE_; virtual core::array<IImage*> createImagesFromFile(const io::path& filename, E_TEXTURE_TYPE* type = 0) _IRR_OVERRIDE_;
virtual core::array<IImage*> createImagesFromFile(io::IReadFile* file) _IRR_OVERRIDE_; virtual core::array<IImage*> createImagesFromFile(io::IReadFile* file, E_TEXTURE_TYPE* type = 0) _IRR_OVERRIDE_;
//! Creates a software image from a byte array. //! Creates a software image from a byte array.
/** \param useForeignMemory: If true, the image will use the data pointer /** \param useForeignMemory: If true, the image will use the data pointer
......
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