mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 09:15:29 +01:00 
			
		
		
		
	Drop support for storing mipmap data alongside IImage
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user