1
0
Fork 0
mirror of https://github.com/luanti-org/luanti.git synced 2025-06-27 16:36:03 +00:00

Drop support for storing mipmap data alongside IImage

This commit is contained in:
sfan5 2025-04-06 17:47:18 +02:00
parent 03affa1bbb
commit 38c3876c4e
4 changed files with 19 additions and 164 deletions

View file

@ -25,7 +25,7 @@ class IImage : public virtual IReferenceCounted
public:
//! constructor
IImage(ECOLOR_FORMAT format, const core::dimension2d<u32> &size, bool deleteMemory) :
Format(format), Size(size), Data(0), MipMapsData(0), BytesPerPixel(0), Pitch(0), DeleteMemory(deleteMemory), DeleteMipMapsMemory(false)
Format(format), Size(size), Data(0), BytesPerPixel(0), Pitch(0), DeleteMemory(deleteMemory)
{
BytesPerPixel = getBitsPerPixelFromFormat(Format) / 8;
Pitch = BytesPerPixel * Size.Width;
@ -36,9 +36,6 @@ public:
{
if (DeleteMemory)
delete[] Data;
if (DeleteMipMapsMemory)
delete[] MipMapsData;
}
//! Returns the color format
@ -188,87 +185,6 @@ public:
return result;
}
//! Get mipmaps data.
/** Note that different mip levels are just behind each other in memory block.
So if you just get level 1 you also have the data for all other levels.
There is no level 0 - use getData to get the original image data.
*/
void *getMipMapsData(irr::u32 mipLevel = 1) const
{
if (MipMapsData && mipLevel > 0) {
size_t dataSize = 0;
core::dimension2du mipSize(Size);
u32 i = 1; // We want the start of data for this level, not end.
while (i != mipLevel) {
if (mipSize.Width > 1)
mipSize.Width >>= 1;
if (mipSize.Height > 1)
mipSize.Height >>= 1;
dataSize += getDataSizeFromFormat(Format, mipSize.Width, mipSize.Height);
++i;
if (mipSize.Width == 1 && mipSize.Height == 1 && i < mipLevel)
return 0;
}
return MipMapsData + dataSize;
}
return 0;
}
//! Set mipmaps data.
/** This method allows you to put custom mipmaps data for
image.
\param data A byte array with pixel color information
\param ownForeignMemory If true, the image will use the data
pointer directly and own it afterward. If false, the memory
will by copied internally.
\param deleteMemory Whether the memory is deallocated upon
destruction. */
void setMipMapsData(void *data, bool ownForeignMemory)
{
if (data != MipMapsData) {
if (DeleteMipMapsMemory) {
delete[] MipMapsData;
DeleteMipMapsMemory = false;
}
if (data) {
if (ownForeignMemory) {
MipMapsData = static_cast<u8 *>(data);
DeleteMipMapsMemory = false;
} else {
u32 dataSize = 0;
u32 width = Size.Width;
u32 height = Size.Height;
do {
if (width > 1)
width >>= 1;
if (height > 1)
height >>= 1;
dataSize += getDataSizeFromFormat(Format, width, height);
} while (width != 1 || height != 1);
MipMapsData = new u8[dataSize];
memcpy(MipMapsData, data, dataSize);
DeleteMipMapsMemory = true;
}
} else {
MipMapsData = 0;
}
}
}
//! Returns a pixel
virtual SColor getPixel(u32 x, u32 y) const = 0;
@ -276,30 +192,24 @@ public:
virtual void setPixel(u32 x, u32 y, const SColor &color, bool blend = false) = 0;
//! Copies this surface into another, if it has the exact same size and format.
/** NOTE: mipmaps are ignored
\return True if it was copied, false otherwise.
/** \return True if it was copied, false otherwise.
*/
virtual bool copyToNoScaling(void *target, u32 width, u32 height, ECOLOR_FORMAT format = ECF_A8R8G8B8, u32 pitch = 0) const = 0;
//! Copies the image into the target, scaling the image to fit
/** NOTE: mipmaps are ignored */
virtual void copyToScaling(void *target, u32 width, u32 height, ECOLOR_FORMAT format = ECF_A8R8G8B8, u32 pitch = 0) = 0;
//! Copies the image into the target, scaling the image to fit
/** NOTE: mipmaps are ignored */
virtual void copyToScaling(IImage *target) = 0;
//! copies this surface into another
/** NOTE: mipmaps are ignored */
virtual void copyTo(IImage *target, const core::position2d<s32> &pos = core::position2d<s32>(0, 0)) = 0;
//! copies this surface into another
/** NOTE: mipmaps are ignored */
virtual void copyTo(IImage *target, const core::position2d<s32> &pos, const core::rect<s32> &sourceRect, const core::rect<s32> *clipRect = 0) = 0;
//! copies this surface into another, using the alpha mask and cliprect and a color to add with
/** NOTE: mipmaps are ignored
\param combineAlpha - When true then combine alpha channels. When false replace target image alpha with source image alpha.
/** \param combineAlpha - When true then combine alpha channels. When false replace target image alpha with source image alpha.
*/
virtual void copyToWithAlpha(IImage *target, const core::position2d<s32> &pos,
const core::rect<s32> &sourceRect, const SColor &color,
@ -307,7 +217,6 @@ public:
bool combineAlpha = false) = 0;
//! copies this surface into another, scaling it to fit, applying a box filter
/** NOTE: mipmaps are ignored */
virtual void copyToScalingBoxFilter(IImage *target, s32 bias = 0, bool blend = false) = 0;
//! fills the surface with given color
@ -415,13 +324,11 @@ protected:
core::dimension2d<u32> Size;
u8 *Data;
u8 *MipMapsData;
u32 BytesPerPixel;
u32 Pitch;
bool DeleteMemory;
bool DeleteMipMapsMemory;
};
} // end namespace video

View file

@ -166,9 +166,7 @@ public:
only mode or read from in write only mode.
Support for this feature depends on the driver, so don't rely on the
texture being write-protected when locking with read-only, etc.
\param mipmapLevel NOTE: Currently broken, sorry, we try if we can repair it for 1.9 release.
Number of the mipmapLevel to lock. 0 is main texture.
Non-existing levels will silently fail and return 0.
\param mipmapLevel Number of the mipmapLevel to lock. 0 is main texture.
\param layer It determines which cubemap face or texture array layer should be locked.
\param lockFlags See E_TEXTURE_LOCK_FLAGS documentation.
\return Returns a pointer to the pixel data. The format of the pixel can
@ -184,14 +182,9 @@ public:
//! Regenerates the mip map levels of the texture.
/** Required after modifying the texture, usually after calling unlock().
\param data Optional parameter to pass in image data which will be
used instead of the previously stored or automatically generated mipmap
data. The data has to be a continuous pixel data for all mipmaps until
1x1 pixel. Each mipmap has to be half the width and height of the previous
level. At least one pixel will be always kept.
\param layer It informs a texture about which cubemap or texture array layer
needs mipmap regeneration. */
virtual void regenerateMipMapLevels(void *data = 0, u32 layer = 0) = 0;
virtual void regenerateMipMapLevels(u32 layer = 0) = 0;
//! Get original size of the texture.
/** The texture is usually scaled, if it was created with an unoptimal

View file

@ -616,7 +616,7 @@ protected:
void *lock(E_TEXTURE_LOCK_MODE mode = ETLM_READ_WRITE, u32 mipmapLevel = 0, u32 layer = 0, E_TEXTURE_LOCK_FLAGS lockFlags = ETLF_FLIP_Y_UP_RTT) override { return 0; }
void unlock() override {}
void regenerateMipMapLevels(void *data = 0, u32 layer = 0) override {}
void regenerateMipMapLevels(u32 layer = 0) override {}
};
core::array<SSurface> Textures;

View file

@ -46,7 +46,7 @@ public:
COpenGLCoreTexture(const io::path &name, const std::vector<IImage *> &srcImages, E_TEXTURE_TYPE type, TOpenGLDriver *driver) :
ITexture(name, type), Driver(driver), TextureType(GL_TEXTURE_2D),
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_RGBA), PixelType(GL_UNSIGNED_BYTE), MSAA(0), Converter(0), LockReadOnly(false), LockImage(0), LockLayer(0),
KeepImage(false), MipLevelStored(0), LegacyAutoGenerateMipMaps(false)
KeepImage(false), MipLevelStored(0)
{
_IRR_DEBUG_BREAK_IF(srcImages.empty())
@ -82,15 +82,6 @@ public:
srcImages[i]->copyTo(Images[i]);
else
srcImages[i]->copyToScaling(Images[i]);
if (srcImages[i]->getMipMapsData()) {
if (OriginalSize == Size && OriginalColorFormat == ColorFormat) {
Images[i]->setMipMapsData(srcImages[i]->getMipMapsData(), false);
} else {
// TODO: handle at least mipmap with changing color format
os::Printer::log("COpenGLCoreTexture: Can't handle format changes for mipmap data. Mipmap data dropped", ELL_WARNING);
}
}
}
tmpImages = &Images;
@ -122,12 +113,9 @@ public:
for (size_t i = 0; i < tmpImages->size(); ++i)
uploadTexture(true, i, 0, (*tmpImages)[i]->getData());
if (HasMipMaps && !LegacyAutoGenerateMipMaps) {
// Create mipmaps (either from image mipmaps or generate them)
for (size_t i = 0; i < tmpImages->size(); ++i) {
void *mipmapsData = (*tmpImages)[i]->getMipMapsData();
regenerateMipMapLevels(mipmapsData, i);
}
if (HasMipMaps) {
for (size_t i = 0; i < tmpImages->size(); ++i)
regenerateMipMapLevels(i);
}
if (!KeepImage) {
@ -149,7 +137,7 @@ public:
ITexture(name, type),
Driver(driver), TextureType(GL_TEXTURE_2D),
TextureName(0), InternalFormat(GL_RGBA), PixelFormat(GL_RGBA), PixelType(GL_UNSIGNED_BYTE), MSAA(msaa), Converter(0), LockReadOnly(false), LockImage(0), LockLayer(0), KeepImage(false),
MipLevelStored(0), LegacyAutoGenerateMipMaps(false)
MipLevelStored(0)
{
DriverType = Driver->getDriverType();
TextureType = TextureTypeIrrToGL(Type);
@ -279,7 +267,7 @@ public:
void *lock(E_TEXTURE_LOCK_MODE mode = ETLM_READ_WRITE, u32 mipmapLevel = 0, u32 layer = 0, E_TEXTURE_LOCK_FLAGS lockFlags = ETLF_FLIP_Y_UP_RTT) override
{
if (LockImage)
return getLockImageData(MipLevelStored);
return LockImage->getData();
if (IImage::isCompressedFormat(ColorFormat))
return 0;
@ -291,7 +279,7 @@ public:
if (KeepImage) {
_IRR_DEBUG_BREAK_IF(LockLayer > Images.size())
if (mipmapLevel == 0 || (Images[LockLayer] && Images[LockLayer]->getMipMapsData(mipmapLevel))) {
if (mipmapLevel == 0) {
LockImage = Images[LockLayer];
LockImage->grab();
}
@ -301,7 +289,6 @@ public:
core::dimension2d<u32> lockImageSize(IImage::getMipMapsSize(Size, MipLevelStored));
_IRR_DEBUG_BREAK_IF(lockImageSize.Width == 0 || lockImageSize.Height == 0)
// note: we save mipmap data also in the image because IImage doesn't allow saving single mipmap levels to the mipmap data
LockImage = Driver->createImage(ColorFormat, lockImageSize);
if (LockImage && mode != ETLM_WRITE_ONLY) {
@ -403,7 +390,7 @@ public:
TEST_GL_ERROR(Driver);
}
return (LockImage) ? getLockImageData(MipLevelStored) : 0;
return (LockImage) ? LockImage->getData() : 0;
}
void unlock() override
@ -415,7 +402,7 @@ public:
const COpenGLCoreTexture *prevTexture = Driver->getCacheHandler()->getTextureCache().get(0);
Driver->getCacheHandler()->getTextureCache().set(0, this);
uploadTexture(false, LockLayer, MipLevelStored, getLockImageData(MipLevelStored));
uploadTexture(false, LockLayer, MipLevelStored, LockImage->getData());
Driver->getCacheHandler()->getTextureCache().set(0, prevTexture);
}
@ -427,39 +414,16 @@ public:
LockLayer = 0;
}
void regenerateMipMapLevels(void *data = 0, u32 layer = 0) override
void regenerateMipMapLevels(u32 layer = 0) override
{
if (!HasMipMaps || LegacyAutoGenerateMipMaps || (Size.Width <= 1 && Size.Height <= 1))
if (!HasMipMaps || (Size.Width <= 1 && Size.Height <= 1))
return;
const COpenGLCoreTexture *prevTexture = Driver->getCacheHandler()->getTextureCache().get(0);
Driver->getCacheHandler()->getTextureCache().set(0, this);
if (data) {
u32 width = Size.Width;
u32 height = Size.Height;
u8 *tmpData = static_cast<u8 *>(data);
u32 dataSize = 0;
u32 level = 0;
do {
if (width > 1)
width >>= 1;
if (height > 1)
height >>= 1;
dataSize = IImage::getDataSizeFromFormat(ColorFormat, width, height);
++level;
uploadTexture(true, layer, level, tmpData);
tmpData += dataSize;
} while (width != 1 || height != 1);
} else {
Driver->irrGlGenerateMipmap(TextureType);
TEST_GL_ERROR(Driver);
}
Driver->irrGlGenerateMipmap(TextureType);
TEST_GL_ERROR(Driver);
Driver->getCacheHandler()->getTextureCache().set(0, prevTexture);
}
@ -480,14 +444,6 @@ public:
}
protected:
void *getLockImageData(irr::u32 miplevel) const
{
if (KeepImage && MipLevelStored > 0 && LockImage->getMipMapsData(MipLevelStored)) {
return LockImage->getMipMapsData(MipLevelStored);
}
return LockImage->getData();
}
ECOLOR_FORMAT getBestColorFormat(ECOLOR_FORMAT format)
{
// We only try for to adapt "simple" formats
@ -671,7 +627,6 @@ protected:
std::vector<IImage*> Images;
u8 MipLevelStored;
bool LegacyAutoGenerateMipMaps;
mutable SStatesCache StatesCache;
};