Browse Source

Improved performance of static Texture write updates
Fixed image importer so it correctly coverts format before sending data to the texture (conversion within texture is not longer supported)

Marko Pintera 12 years ago
parent
commit
d8d41821ad

+ 2 - 1
CamelotCore/Include/CmMesh.h

@@ -74,7 +74,7 @@ namespace CamelotFramework
 		UINT32 mapToSubresourceIdx() const { return 0; }
 		UINT32 mapToSubresourceIdx() const { return 0; }
 
 
 		const SubMesh& getSubMesh(UINT32 subMeshIdx = 0) const;
 		const SubMesh& getSubMesh(UINT32 subMeshIdx = 0) const;
-		UINT32 getNumSubMeshes() const { return (UINT32)mSubMeshes.size(); }
+		UINT32 getNumSubMeshes() const { return mNumSubMeshes.load(); }
 
 
 		const AABox& getBounds() const;
 		const AABox& getBounds() const;
 		const AABox& getBounds(UINT32 submeshIdx) const;
 		const AABox& getBounds(UINT32 submeshIdx) const;
@@ -99,6 +99,7 @@ namespace CamelotFramework
 		std::shared_ptr<IndexData> mIndexData;
 		std::shared_ptr<IndexData> mIndexData;
 
 
 		Vector<SubMesh>::type mSubMeshes;
 		Vector<SubMesh>::type mSubMeshes;
+		std::atomic<UINT32> mNumSubMeshes;
 
 
 		UINT32 mNumVertices;
 		UINT32 mNumVertices;
 		UINT32 mNumIndices;
 		UINT32 mNumIndices;

+ 4 - 2
CamelotCore/Include/CmMeshData.h

@@ -111,12 +111,14 @@ namespace CamelotFramework
 
 
 		/**
 		/**
 		 * @brief	Informs the internal buffer that it needs to make room for an index buffer of the
 		 * @brief	Informs the internal buffer that it needs to make room for an index buffer of the
-		 * 			specified size. If specified submesh already exists it will just be updated. This
-		 * 			must be called between beginDesc and endDesc.
+		 * 			specified size. If specified submesh already exists it will just be updated. 
 		 *
 		 *
 		 * @param	numIndices	Number of indices.
 		 * @param	numIndices	Number of indices.
 		 * @param	subMesh   	(optional) Index of the sub-mesh to add/update.
 		 * @param	subMesh   	(optional) Index of the sub-mesh to add/update.
 		 * @param	drawOp	  	(optional) Specifies the primitive type contained by the mesh.
 		 * @param	drawOp	  	(optional) Specifies the primitive type contained by the mesh.
+		 * 						
+		 * @note	When updating a Mesh with MeshData, even if just a portion of it,
+		 * 			all sub-mesh information will be replaced with the one from MeshData.
 		 */
 		 */
 		void addSubMesh(UINT32 numIndices, UINT32 subMesh = 0, DrawOperationType drawOp = DOT_TRIANGLE_LIST);
 		void addSubMesh(UINT32 numIndices, UINT32 subMesh = 0, DrawOperationType drawOp = DOT_TRIANGLE_LIST);
 
 

+ 0 - 59
CamelotCore/Include/CmPixelBuffer.h

@@ -101,66 +101,7 @@ namespace CamelotFramework {
 		/// @copydoc HardwareBuffer::writeData
 		/// @copydoc HardwareBuffer::writeData
 		virtual void writeData(UINT32 offset, UINT32 length, const void* pSource,
 		virtual void writeData(UINT32 offset, UINT32 length, const void* pSource,
 				bool discardWholeBuffer = false);
 				bool discardWholeBuffer = false);
-        
-        /** Copies a box from another PixelBuffer to a region of the 
-        	this PixelBuffer. 
-			@param dst		Source pixel buffer
-        	@param srcBox	Image::Box describing the source region in src
-        	@param dstBox	Image::Box describing the destination region in this buffer
-			@remarks The source and destination regions dimensions don't have to match, in which
-		   	case scaling is done. This scaling is generally done using a bilinear filter in hardware,
-            but it is faster to pass the source image in the right dimensions.
-			@note Only call this function when both  buffers are unlocked. 
-         */        
-        virtual void blit(const PixelBufferPtr &src, const Box &srcBox, const Box &dstBox);
-
-		/** Convenience function that blits the entire source pixel buffer to this buffer. 
-			If source and destination dimensions don't match, scaling is done.
-			@param src		PixelBox containing the source pixels and format in memory
-			@note Only call this function when the buffer is unlocked. 
-		*/
-		void blit(const PixelBufferPtr &src); 
-		
-		/** Copies a region from normal memory to a region of this pixelbuffer. The source
-			image can be in any pixel format supported by OGRE, and in any size. 
-		   	@param src		PixelBox containing the source pixels and format in memory
-		   	@param dstBox	Image::Box describing the destination region in this buffer
-            @remarks The source and destination regions dimensions don't have to match, in which
-            case scaling is done. This scaling is generally done using a bilinear filter in hardware,
-            but it is faster to pass the source image in the right dimensions.
-			@note Only call this function when the buffer is unlocked. 
-		*/
-		virtual void blitFromMemory(const PixelData &src, const Box &dstBox) = 0;
-		
-		/** Convenience function that blits a pixelbox from memory to the entire 
-			buffer. The source image is scaled as needed.
-			@param src		PixelBox containing the source pixels and format in memory
-			@note Only call this function when the buffer is unlocked. 
-		*/
-		void blitFromMemory(const PixelData &src)
-		{
-			blitFromMemory(src, Box(0,0,0,mWidth,mHeight,mDepth));
-		}
-		
-		/** Copies a region of this pixelbuffer to normal memory.
-		   	@param srcBox	Image::Box describing the source region of this buffer
-		   	@param dst		PixelBox describing the destination pixels and format in memory
-		   	@remarks The source and destination regions don't have to match, in which
-		   	case scaling is done.
-			@note Only call this function when the buffer is unlocked. 
-		 */
-		virtual void blitToMemory(const Box &srcBox, const PixelData &dst) = 0;
 
 
-		/** Convience function that blits this entire buffer to a pixelbox.
-			The image is scaled as needed.
-			@param src		PixelBox containing the source pixels and format in memory
-			@note Only call this function when the buffer is unlocked. 
-		*/
-		void blitToMemory(const PixelData &dst)
-		{
-			blitToMemory(Box(0,0,0,mWidth,mHeight,mDepth), dst);
-		}
-        
         /// Gets the width of this buffer
         /// Gets the width of this buffer
         UINT32 getWidth() const { return mWidth; }
         UINT32 getWidth() const { return mWidth; }
         /// Gets the height of this buffer
         /// Gets the height of this buffer

+ 31 - 2
CamelotCore/Include/CmTexture.h

@@ -182,13 +182,42 @@ namespace CamelotFramework {
 		 */
 		 */
 		UINT32 mapToSubresourceIdx(UINT32 face, UINT32 mip) const;
 		UINT32 mapToSubresourceIdx(UINT32 face, UINT32 mip) const;
 
 
+		/**
+		 * @brief	Locks the buffer for reading or writing.
+		 *
+		 * @param	options 	Options for controlling the operation.
+		 * @param	mipLevel	(optional) the mip level.
+		 * @param	face		(optional) the face.
+		 * 						
+		 * @return	Pointer to the buffer data. Only valid until you call unlock.
+		 * 			
+		 * @note If you are just reading or writing one block of data use
+		 * 		readData/writeData methods as they can be must faster in certain situations.
+		 */
 		PixelData lock(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0);
 		PixelData lock(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0);
+
+		/**
+		 * @brief	Unlocks a previously locked buffer. After the buffer is unlocked,
+		 * 			any data returned by lock becomes invalid.
+		 */
 		void unlock();
 		void unlock();
 
 
-		/** Copies the contents of this texture to
-			another texture. */
+		/**
+		* @brief	Copies the contents of this texture to another texture. Texture format
+		* 			and size must match.
+		 */
 		void copy(TexturePtr& target);
 		void copy(TexturePtr& target);
 
 
+		/**
+		 * @brief Reads data from the texture buffer into the provided buffer.
+		 */
+		virtual void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0) = 0;
+
+		/**
+		 * @brief Writes data from the provided buffer into the texture buffer.
+		 */
+		virtual void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false) = 0;
+
 		/**
 		/**
 		 * @brief	Returns a dummy 2x2 texture. Don't modify the returned texture.
 		 * @brief	Returns a dummy 2x2 texture. Don't modify the returned texture.
 		 */
 		 */

+ 9 - 6
CamelotCore/Source/CmMesh.cpp

@@ -18,23 +18,24 @@ namespace CamelotFramework
 	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
 	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
 		MeshBufferType bufferType, IndexBuffer::IndexType indexType)
 		MeshBufferType bufferType, IndexBuffer::IndexType indexType)
 		:mVertexData(nullptr), mIndexData(nullptr), mNumVertices(numVertices), mNumIndices(numIndices), 
 		:mVertexData(nullptr), mIndexData(nullptr), mNumVertices(numVertices), mNumIndices(numIndices), 
-		mVertexDesc(vertexDesc), mBufferType(bufferType), mIndexType(indexType)
+		mVertexDesc(vertexDesc), mBufferType(bufferType), mIndexType(indexType), mNumSubMeshes(0)
 	{ }
 	{ }
 
 
 	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
 	Mesh::Mesh(UINT32 numVertices, UINT32 numIndices, const VertexDataDescPtr& vertexDesc, 
 		const MeshDataPtr& initialMeshData, MeshBufferType bufferType, IndexBuffer::IndexType indexType)
 		const MeshDataPtr& initialMeshData, MeshBufferType bufferType, IndexBuffer::IndexType indexType)
 		:mVertexData(nullptr), mIndexData(nullptr), mNumVertices(numVertices), mNumIndices(numIndices), 
 		:mVertexData(nullptr), mIndexData(nullptr), mNumVertices(numVertices), mNumIndices(numIndices), 
-		mVertexDesc(vertexDesc), mBufferType(bufferType), mIndexType(indexType), mTempInitialMeshData(initialMeshData)
+		mVertexDesc(vertexDesc), mBufferType(bufferType), mIndexType(indexType), mTempInitialMeshData(initialMeshData), mNumSubMeshes(0)
 	{ }
 	{ }
 
 
 	Mesh::Mesh(const MeshDataPtr& initialMeshData, MeshBufferType bufferType)
 	Mesh::Mesh(const MeshDataPtr& initialMeshData, MeshBufferType bufferType)
 		:mVertexData(nullptr), mIndexData(nullptr), mNumVertices(initialMeshData->getNumVertices()), 
 		:mVertexData(nullptr), mIndexData(nullptr), mNumVertices(initialMeshData->getNumVertices()), 
 		mNumIndices(initialMeshData->getNumIndices()), mBufferType(bufferType), mIndexType(initialMeshData->getIndexType()),
 		mNumIndices(initialMeshData->getNumIndices()), mBufferType(bufferType), mIndexType(initialMeshData->getIndexType()),
-		mVertexDesc(initialMeshData->getVertexDesc()), mTempInitialMeshData(initialMeshData)
+		mVertexDesc(initialMeshData->getVertexDesc()), mTempInitialMeshData(initialMeshData), mNumSubMeshes(0)
 	{ }
 	{ }
 
 
 	Mesh::Mesh()
 	Mesh::Mesh()
-		:mVertexData(nullptr), mIndexData(nullptr), mNumVertices(0), mNumIndices(0), mBufferType(MeshBufferType::Static), mIndexType(IndexBuffer::IT_32BIT)
+		:mVertexData(nullptr), mIndexData(nullptr), mNumVertices(0), mNumIndices(0), 
+		mBufferType(MeshBufferType::Static), mIndexType(IndexBuffer::IT_32BIT), mNumSubMeshes(0)
 	{ }
 	{ }
 
 
 	Mesh::~Mesh()
 	Mesh::~Mesh()
@@ -52,7 +53,7 @@ namespace CamelotFramework
 		{
 		{
 			if(mBufferType == MeshBufferType::Static)
 			if(mBufferType == MeshBufferType::Static)
 			{
 			{
-				LOGWRN("Buffer discard was set but buffer was created as static.");
+				LOGWRN("Buffer discard is enabled but buffer was not created as dynamic. Disabling discard.");
 				discardEntireBuffer = false;
 				discardEntireBuffer = false;
 			}
 			}
 		}
 		}
@@ -60,7 +61,7 @@ namespace CamelotFramework
 		{
 		{
 			if(mBufferType == MeshBufferType::Dynamic)
 			if(mBufferType == MeshBufferType::Dynamic)
 			{
 			{
-				LOGWRN("Buffer discard was not set but buffer was created as dynamic.");
+				LOGWRN("Buffer discard is not enabled but buffer was created as dynamic. Enabling discard.");
 				discardEntireBuffer = true;
 				discardEntireBuffer = true;
 			}
 			}
 		}
 		}
@@ -151,6 +152,8 @@ namespace CamelotFramework
 				mSubMeshes.push_back(SubMesh(0, numIndices, meshData.getDrawOp(), mVertexData, mIndexData, true));
 				mSubMeshes.push_back(SubMesh(0, numIndices, meshData.getDrawOp(), mVertexData, mIndexData, true));
 			}
 			}
 		}
 		}
+
+		mNumSubMeshes.store((UINT32)mSubMeshes.size());
 	}
 	}
 
 
 	void Mesh::readSubresource(UINT32 subresourceIdx, GpuResourceData& data)
 	void Mesh::readSubresource(UINT32 subresourceIdx, GpuResourceData& data)

+ 4 - 62
CamelotCore/Source/CmPixelBuffer.cpp

@@ -30,8 +30,6 @@ THE SOFTWARE.
 
 
 namespace CamelotFramework 
 namespace CamelotFramework 
 {
 {
-  
-    //-----------------------------------------------------------------------------    
     PixelBuffer::PixelBuffer(UINT32 width, UINT32 height, UINT32 depth,
     PixelBuffer::PixelBuffer(UINT32 width, UINT32 height, UINT32 depth,
             PixelFormat format,
             PixelFormat format,
             GpuBufferUsage usage, bool useSystemMemory):
             GpuBufferUsage usage, bool useSystemMemory):
@@ -44,13 +42,11 @@ namespace CamelotFramework
         mSlicePitch = mHeight*mWidth;
         mSlicePitch = mHeight*mWidth;
 		mSizeInBytes = mHeight*mWidth*PixelUtil::getNumElemBytes(mFormat);
 		mSizeInBytes = mHeight*mWidth*PixelUtil::getNumElemBytes(mFormat);
     }
     }
-    
-    //-----------------------------------------------------------------------------    
+
     PixelBuffer::~PixelBuffer()
     PixelBuffer::~PixelBuffer()
     {
     {
     }
     }
-    
-    //-----------------------------------------------------------------------------    
+
     void* PixelBuffer::lock(UINT32 offset, UINT32 length, GpuLockOptions options)
     void* PixelBuffer::lock(UINT32 offset, UINT32 length, GpuLockOptions options)
     {
     {
         assert(!isLocked() && "Cannot lock this buffer, it is already locked!");
         assert(!isLocked() && "Cannot lock this buffer, it is already locked!");
@@ -60,8 +56,7 @@ namespace CamelotFramework
         const PixelData &rv = lock(myBox, options);
         const PixelData &rv = lock(myBox, options);
         return rv.getData();
         return rv.getData();
     }
     }
-    
-    //-----------------------------------------------------------------------------    
+
     const PixelData& PixelBuffer::lock(const Box& lockBox, GpuLockOptions options)
     const PixelData& PixelBuffer::lock(const Box& lockBox, GpuLockOptions options)
     {
     {
         // Lock the real buffer if there is no shadow buffer 
         // Lock the real buffer if there is no shadow buffer 
@@ -71,77 +66,24 @@ namespace CamelotFramework
         return mCurrentLock;
         return mCurrentLock;
     }
     }
     
     
-    //-----------------------------------------------------------------------------    
     const PixelData& PixelBuffer::getCurrentLock() 
     const PixelData& PixelBuffer::getCurrentLock() 
 	{ 
 	{ 
         assert(isLocked() && "Cannot get current lock: buffer not locked");
         assert(isLocked() && "Cannot get current lock: buffer not locked");
         
         
         return mCurrentLock; 
         return mCurrentLock; 
     }
     }
-    
-    //-----------------------------------------------------------------------------    
-    /// Internal implementation of lock()
+
     void* PixelBuffer::lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options)
     void* PixelBuffer::lockImpl(UINT32 offset, UINT32 length, GpuLockOptions options)
     {
     {
 		CM_EXCEPT(InternalErrorException, "lockImpl(offset,length) is not valid for PixelBuffers and should never be called");
 		CM_EXCEPT(InternalErrorException, "lockImpl(offset,length) is not valid for PixelBuffers and should never be called");
     }
     }
 
 
-    //-----------------------------------------------------------------------------    
-
-    void PixelBuffer::blit(const PixelBufferPtr &src, const Box &srcBox, const Box &dstBox)
-	{
-		if(isLocked() || src->isLocked())
-		{
-			CM_EXCEPT(InternalErrorException,
-				"Source and destination buffer may not be locked!");
-		}
-		if(src.get() == this)
-		{
-			CM_EXCEPT(InternalErrorException,
-                "Source must not be the same object") ;
-		}
-		const PixelData &srclock = src->lock(srcBox, GBL_READ_ONLY);
-
-		GpuLockOptions method = GBL_READ_WRITE;
-		if(dstBox.left == 0 && dstBox.top == 0 && dstBox.front == 0 &&
-		   dstBox.right == mWidth && dstBox.bottom == mHeight &&
-		   dstBox.back == mDepth)
-			// Entire buffer -- we can discard the previous contents
-			method = GBL_WRITE_ONLY_DISCARD;
-			
-		const PixelData &dstlock = lock(dstBox, method);
-		if(dstlock.getWidth() != srclock.getWidth() ||
-        	dstlock.getHeight() != srclock.getHeight() ||
-        	dstlock.getDepth() != srclock.getDepth())
-		{
-			// Scaling desired
-			PixelUtil::scale(srclock, dstlock);
-		}
-		else
-		{
-			// No scaling needed
-			PixelUtil::bulkPixelConversion(srclock, dstlock);
-		}
-
-		unlock();
-		src->unlock();
-	}
-    //-----------------------------------------------------------------------------       
-    void PixelBuffer::blit(const PixelBufferPtr &src)
-    {
-        blit(src, 
-            Box(0,0,0,src->getWidth(),src->getHeight(),src->getDepth()), 
-            Box(0,0,0,mWidth,mHeight,mDepth)
-        );
-    }
-    //-----------------------------------------------------------------------------    
 	void PixelBuffer::readData(UINT32 offset, UINT32 length, void* pDest)
 	void PixelBuffer::readData(UINT32 offset, UINT32 length, void* pDest)
 	{
 	{
 		// TODO
 		// TODO
 		CM_EXCEPT(NotImplementedException,
 		CM_EXCEPT(NotImplementedException,
 				"Reading a byte range is not implemented. Use blitToMemory.");
 				"Reading a byte range is not implemented. Use blitToMemory.");
 	}
 	}
-	//-----------------------------------------------------------------------------    
 
 
 	void PixelBuffer::writeData(UINT32 offset, UINT32 length, const void* pSource,
 	void PixelBuffer::writeData(UINT32 offset, UINT32 length, const void* pSource,
 			bool discardWholeBuffer)
 			bool discardWholeBuffer)

+ 28 - 19
CamelotCore/Source/CmTexture.cpp

@@ -93,21 +93,36 @@ namespace CamelotFramework {
 		if(data.getTypeId() != TID_PixelData)
 		if(data.getTypeId() != TID_PixelData)
 			CM_EXCEPT(InvalidParametersException, "Invalid GpuResourceData type. Only PixelData is supported.");
 			CM_EXCEPT(InvalidParametersException, "Invalid GpuResourceData type. Only PixelData is supported.");
 
 
-		if(!discardEntireBuffer) // TODO - Textures can currently only be dynamic
+		if(discardEntireBuffer)
 		{
 		{
-			LOGWRN("Buffer discard was not set but buffer was created as dynamic.");
-			discardEntireBuffer = true;
+			if(mUsage != TU_DYNAMIC)
+			{
+				LOGWRN("Buffer discard is enabled but buffer was not created as dynamic. Disabling discard.");
+				discardEntireBuffer = false;
+			}
+		}
+		else
+		{
+			if(mUsage == TU_DYNAMIC)
+			{
+				LOGWRN("Buffer discard is not enabled but buffer was not created as dynamic. Enabling discard.");
+				discardEntireBuffer = true;
+			}
 		}
 		}
 
 
 		const PixelData& pixelData = static_cast<const PixelData&>(data);
 		const PixelData& pixelData = static_cast<const PixelData&>(data);
 
 
+		if(pixelData.getWidth() != getWidth() ||pixelData.getHeight() != getHeight() || 
+			pixelData.getDepth() != getDepth() || pixelData.getFormat() != getFormat())
+		{
+			CM_EXCEPT(RenderingAPIException, "Provided buffer is not of valid dimensions or format in order to write to this texture.");
+		}
+
 		UINT32 face = 0;
 		UINT32 face = 0;
 		UINT32 mip = 0;
 		UINT32 mip = 0;
 		mapFromSubresourceIdx(subresourceIdx, face, mip);
 		mapFromSubresourceIdx(subresourceIdx, face, mip);
 
 
-		PixelData myData = lock(discardEntireBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mip, face);
-		PixelUtil::bulkPixelConversion(pixelData, myData);
-		unlock();
+		writeData(pixelData, mip, face, discardEntireBuffer);
 	}
 	}
 
 
 	void Texture::readSubresource(UINT32 subresourceIdx, GpuResourceData& data)
 	void Texture::readSubresource(UINT32 subresourceIdx, GpuResourceData& data)
@@ -119,23 +134,17 @@ namespace CamelotFramework {
 
 
 		PixelData& pixelData = static_cast<PixelData&>(data);
 		PixelData& pixelData = static_cast<PixelData&>(data);
 
 
-		UINT32 face = 0;
-		UINT32 mip = 0;
-		mapFromSubresourceIdx(subresourceIdx, face, mip);
-
-		PixelData myData = lock(GBL_READ_ONLY, mip, face);
-
-#if CM_DEBUG_MODE
-		if(pixelData.getConsecutiveSize() != myData.getConsecutiveSize())
+		if(pixelData.getWidth() != getWidth() ||pixelData.getHeight() != getHeight() || 
+			pixelData.getDepth() != getDepth() || pixelData.getFormat() != getFormat())
 		{
 		{
-			unlock();
-			CM_EXCEPT(InternalErrorException, "Buffer sizes don't match");
+			CM_EXCEPT(RenderingAPIException, "Provided buffer is not of valid dimensions or format in order to read from this texture.");
 		}
 		}
-#endif
 
 
-		PixelUtil::bulkPixelConversion(myData, pixelData);
+		UINT32 face = 0;
+		UINT32 mip = 0;
+		mapFromSubresourceIdx(subresourceIdx, face, mip);
 
 
-		unlock();
+		readData(pixelData, mip, face);
 	}
 	}
 
 
 	PixelDataPtr Texture::allocateSubresourceBuffer(UINT32 subresourceIdx) const
 	PixelDataPtr Texture::allocateSubresourceBuffer(UINT32 subresourceIdx) const

+ 1 - 1
CamelotCore/Source/CmTextureManager.cpp

@@ -58,7 +58,7 @@ namespace CamelotFramework
 		data->setColorAt(Color::Red, 1, 1);
 		data->setColorAt(Color::Red, 1, 1);
 
 
 		AsyncOp op;
 		AsyncOp op;
-		RenderSystem::instance().writeSubresource(mDummyTexture.getInternalPtr(), mDummyTexture->mapToSubresourceIdx(0, 0), data, true, op);
+		RenderSystem::instance().writeSubresource(mDummyTexture.getInternalPtr(), mDummyTexture->mapToSubresourceIdx(0, 0), data, false, op);
 	}
 	}
 
 
     TexturePtr TextureManager::createTexture(TextureType texType, UINT32 width, UINT32 height, UINT32 depth, int numMipmaps,
     TexturePtr TextureManager::createTexture(TextureType texType, UINT32 width, UINT32 height, UINT32 depth, int numMipmaps,

+ 23 - 13
CamelotD3D11RenderSystem/Include/CmD3D11Texture.h

@@ -36,37 +36,47 @@ namespace CamelotFramework
 		bool mLockedForReading;
 		bool mLockedForReading;
 
 
 		/**
 		/**
-		 * @copydoc Texture::lockImpl
+		 * @copydoc Texture::lock
 		 */
 		 */
 		PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0);
 		PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0);
 
 
 		/**
 		/**
-		 * @copydoc Texture::unlockImpl
+		 * @copydoc Texture::unlock
 		 */
 		 */
 		void unlockImpl();
 		void unlockImpl();
 
 
 		/**
 		/**
-		 * @copydoc Texture::copy_internal
+		 * @copydoc Texture::copy
 		 */
 		 */
 		void copyImpl(TexturePtr& target);
 		void copyImpl(TexturePtr& target);
 
 
+		/**
+		 * @copydoc Texture::readData
+		 */
+		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0);
+
+		/**
+		 * @copydoc Texture::writeData
+		 */
+		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false);
+
 		/// internal method, create a blank normal 1D Dtexture
 		/// internal method, create a blank normal 1D Dtexture
-		void _create1DTex();
+		void create1DTex();
 		/// internal method, create a blank normal 2D texture
 		/// internal method, create a blank normal 2D texture
-		void _create2DTex();
+		void create2DTex();
 		/// internal method, create a blank cube texture
 		/// internal method, create a blank cube texture
-		void _create3DTex();
+		void create3DTex();
 
 
-		void _createStagingBuffer();
+		void createStagingBuffer();
 
 
-		void* _map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch);
-		void _unmap(ID3D11Resource* res);
+		void* map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch);
+		void unmap(ID3D11Resource* res);
 
 
-		void* _mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch);
-		void _unmapstagingbuffer();
+		void* mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch);
+		void unmapstagingbuffer();
 		
 		
-		void* _mapstaticbuffer(PixelData lock, UINT32 mipLevel, UINT32 slice);
-		void _unmapstaticbuffer();
+		void* mapstaticbuffer(PixelData lock, UINT32 mipLevel, UINT32 slice);
+		void unmapstaticbuffer();
 
 
 		/**
 		/**
 		 * @copydoc	Texture::initialize_internal()
 		 * @copydoc	Texture::initialize_internal()

+ 77 - 22
CamelotD3D11RenderSystem/Source/CmD3D11Texture.cpp

@@ -6,6 +6,7 @@
 #include "CmCoreThread.h"
 #include "CmCoreThread.h"
 #include "CmException.h"
 #include "CmException.h"
 #include "CmAsyncOp.h"
 #include "CmAsyncOp.h"
+#include "CmDebug.h"
 
 
 namespace CamelotFramework
 namespace CamelotFramework
 {
 {
@@ -58,7 +59,7 @@ namespace CamelotFramework
 
 
 		if(flags == D3D11_MAP_READ || flags == D3D11_MAP_READ_WRITE)
 		if(flags == D3D11_MAP_READ || flags == D3D11_MAP_READ_WRITE)
 		{
 		{
-			UINT8* data = (UINT8*)_mapstagingbuffer(flags, face, mipLevel, rowPitch, slicePitch);
+			UINT8* data = (UINT8*)mapstagingbuffer(flags, face, mipLevel, rowPitch, slicePitch);
 			lockedArea.setExternalBuffer(data);
 			lockedArea.setExternalBuffer(data);
 			lockedArea.setRowPitch(rowPitch);
 			lockedArea.setRowPitch(rowPitch);
 			lockedArea.setSlicePitch(slicePitch);
 			lockedArea.setSlicePitch(slicePitch);
@@ -68,13 +69,13 @@ namespace CamelotFramework
 		{
 		{
 			if(mUsage == TU_DYNAMIC)
 			if(mUsage == TU_DYNAMIC)
 			{
 			{
-				UINT8* data = (UINT8*)_map(mTex, flags, face, mipLevel, rowPitch, slicePitch);
+				UINT8* data = (UINT8*)map(mTex, flags, face, mipLevel, rowPitch, slicePitch);
 				lockedArea.setExternalBuffer(data);
 				lockedArea.setExternalBuffer(data);
 				lockedArea.setRowPitch(rowPitch);
 				lockedArea.setRowPitch(rowPitch);
 				lockedArea.setSlicePitch(slicePitch);
 				lockedArea.setSlicePitch(slicePitch);
 			}
 			}
 			else
 			else
-				lockedArea.setExternalBuffer((UINT8*)_mapstaticbuffer(lockedArea, mipLevel, face));
+				lockedArea.setExternalBuffer((UINT8*)mapstaticbuffer(lockedArea, mipLevel, face));
 
 
 			mLockedForReading = false;
 			mLockedForReading = false;
 		}
 		}
@@ -85,13 +86,67 @@ namespace CamelotFramework
 	void D3D11Texture::unlockImpl()
 	void D3D11Texture::unlockImpl()
 	{
 	{
 		if(mLockedForReading)
 		if(mLockedForReading)
-			_unmapstagingbuffer();
+			unmapstagingbuffer();
 		else
 		else
 		{
 		{
 			if(mUsage == TU_DYNAMIC)
 			if(mUsage == TU_DYNAMIC)
-				_unmap(mTex);
+				unmap(mTex);
 			else
 			else
-				_unmapstaticbuffer();
+				unmapstaticbuffer();
+		}
+	}
+
+	void D3D11Texture::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
+	{
+		PixelData myData = lock(GBL_READ_ONLY, mipLevel, face);
+
+#if CM_DEBUG_MODE
+		if(dest.getConsecutiveSize() != myData.getConsecutiveSize())
+		{
+			unlock();
+			CM_EXCEPT(InternalErrorException, "Buffer sizes don't match");
+		}
+#endif
+
+		PixelUtil::bulkPixelConversion(myData, dest);
+
+		unlock();
+	}
+
+	void D3D11Texture::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
+	{
+		if(mUsage == TU_DYNAMIC)
+		{
+			PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
+			PixelUtil::bulkPixelConversion(src, myData);
+			unlock();
+		}
+		else if(mUsage == TU_STATIC)
+		{
+			mipLevel = Math::Clamp(mipLevel, (UINT32)mipLevel, getNumMipmaps());
+			face = Math::Clamp(face, (UINT32)0, mDepth - 1);
+
+			if(getTextureType() == TEX_TYPE_3D)
+				face = 0;
+
+			D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
+			D3D11Device& device = rs->getPrimaryDevice();
+
+			UINT subresourceIdx = D3D11CalcSubresource(mipLevel, face, getNumMipmaps()+1);
+			UINT32 rowWidth = D3D11Mappings::_getSizeInBytes(mFormat, src.getWidth());
+			UINT32 sliceWidth = D3D11Mappings::_getSizeInBytes(mFormat, src.getWidth(), src.getHeight());
+
+			device.getImmediateContext()->UpdateSubresource(mTex, subresourceIdx, nullptr, src.getData(), rowWidth, sliceWidth);
+
+			if (device.hasError())
+			{
+				String errorDescription = device.getErrorDescription();
+				CM_EXCEPT(RenderingAPIException, "D3D11 device cannot map texture\nError Description:" + errorDescription);
+			}
+		}
+		else
+		{
+			CM_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mUsage));
 		}
 		}
 	}
 	}
 
 
@@ -105,14 +160,14 @@ namespace CamelotFramework
 		switch (getTextureType())
 		switch (getTextureType())
 		{
 		{
 			case TEX_TYPE_1D:
 			case TEX_TYPE_1D:
-				_create1DTex();
+				create1DTex();
 				break;
 				break;
 			case TEX_TYPE_2D:
 			case TEX_TYPE_2D:
 			case TEX_TYPE_CUBE_MAP:
 			case TEX_TYPE_CUBE_MAP:
-				_create2DTex();
+				create2DTex();
 				break;
 				break;
 			case TEX_TYPE_3D:
 			case TEX_TYPE_3D:
-				_create3DTex();
+				create3DTex();
 				break;
 				break;
 			default:
 			default:
 				destroy_internal();
 				destroy_internal();
@@ -134,7 +189,7 @@ namespace CamelotFramework
 		Texture::destroy_internal();
 		Texture::destroy_internal();
 	}
 	}
 
 
-	void D3D11Texture::_create1DTex()
+	void D3D11Texture::create1DTex()
 	{
 	{
 		// We must have those defined here
 		// We must have those defined here
 		assert(mWidth > 0);
 		assert(mWidth > 0);
@@ -218,7 +273,7 @@ namespace CamelotFramework
 		}
 		}
 	}
 	}
 
 
-	void D3D11Texture::_create2DTex()
+	void D3D11Texture::create2DTex()
 	{
 	{
 		// We must have those defined here
 		// We must have those defined here
 		assert(mWidth > 0 || mHeight > 0);
 		assert(mWidth > 0 || mHeight > 0);
@@ -375,7 +430,7 @@ namespace CamelotFramework
 		}
 		}
 	}
 	}
 
 
-	void D3D11Texture::_create3DTex()
+	void D3D11Texture::create3DTex()
 	{
 	{
 		// We must have those defined here
 		// We must have those defined here
 		assert(mWidth > 0 && mHeight > 0 && mDepth > 0);
 		assert(mWidth > 0 && mHeight > 0 && mDepth > 0);
@@ -462,7 +517,7 @@ namespace CamelotFramework
 		}
 		}
 	}
 	}
 
 
-	void* D3D11Texture::_map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
+	void* D3D11Texture::map(ID3D11Resource* res, D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
 	{
 	{
 		D3D11_MAPPED_SUBRESOURCE pMappedResource;
 		D3D11_MAPPED_SUBRESOURCE pMappedResource;
 		pMappedResource.pData = nullptr;
 		pMappedResource.pData = nullptr;
@@ -492,7 +547,7 @@ namespace CamelotFramework
 		return pMappedResource.pData;
 		return pMappedResource.pData;
 	}
 	}
 
 
-	void D3D11Texture::_unmap(ID3D11Resource* res)
+	void D3D11Texture::unmap(ID3D11Resource* res)
 	{
 	{
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11Device& device = rs->getPrimaryDevice();
 		D3D11Device& device = rs->getPrimaryDevice();
@@ -505,24 +560,24 @@ namespace CamelotFramework
 		}
 		}
 	}
 	}
 
 
-	void* D3D11Texture::_mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
+	void* D3D11Texture::mapstagingbuffer(D3D11_MAP flags, UINT32 mipLevel, UINT32 face, UINT32& rowPitch, UINT32& slicePitch)
 	{
 	{
 		if(!mStagingBuffer)
 		if(!mStagingBuffer)
-			_createStagingBuffer();
+			createStagingBuffer();
 
 
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11Device& device = rs->getPrimaryDevice();
 		D3D11Device& device = rs->getPrimaryDevice();
 		device.getImmediateContext()->CopyResource(mStagingBuffer, mTex);
 		device.getImmediateContext()->CopyResource(mStagingBuffer, mTex);
 
 
-		return _map(mStagingBuffer, flags, face, mipLevel, rowPitch, slicePitch);
+		return map(mStagingBuffer, flags, face, mipLevel, rowPitch, slicePitch);
 	}
 	}
 
 
-	void D3D11Texture::_unmapstagingbuffer()
+	void D3D11Texture::unmapstagingbuffer()
 	{
 	{
-		_unmap(mStagingBuffer);
+		unmap(mStagingBuffer);
 	}
 	}
 
 
-	void* D3D11Texture::_mapstaticbuffer(PixelData lock, UINT32 mipLevel, UINT32 face)
+	void* D3D11Texture::mapstaticbuffer(PixelData lock, UINT32 mipLevel, UINT32 face)
 	{
 	{
 		UINT32 sizeOfImage = lock.getConsecutiveSize();
 		UINT32 sizeOfImage = lock.getConsecutiveSize();
 		mLockedSubresourceIdx = D3D11CalcSubresource(mipLevel, face, getNumMipmaps()+1);
 		mLockedSubresourceIdx = D3D11CalcSubresource(mipLevel, face, getNumMipmaps()+1);
@@ -533,7 +588,7 @@ namespace CamelotFramework
 		return mStaticBuffer->getData();
 		return mStaticBuffer->getData();
 	}
 	}
 
 
-	void D3D11Texture::_unmapstaticbuffer()
+	void D3D11Texture::unmapstaticbuffer()
 	{
 	{
 		UINT32 rowWidth = D3D11Mappings::_getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth());
 		UINT32 rowWidth = D3D11Mappings::_getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth());
 		UINT32 sliceWidth = D3D11Mappings::_getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth(), mStaticBuffer->getHeight());
 		UINT32 sliceWidth = D3D11Mappings::_getSizeInBytes(mStaticBuffer->getFormat(), mStaticBuffer->getWidth(), mStaticBuffer->getHeight());
@@ -552,7 +607,7 @@ namespace CamelotFramework
 			cm_delete<PoolAlloc>(mStaticBuffer);
 			cm_delete<PoolAlloc>(mStaticBuffer);
 	}
 	}
 
 
-	void D3D11Texture::_createStagingBuffer()
+	void D3D11Texture::createStagingBuffer()
 	{
 	{
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
 		D3D11Device& device = rs->getPrimaryDevice();
 		D3D11Device& device = rs->getPrimaryDevice();

+ 0 - 10
CamelotD3D9Renderer/Include/CmD3D9PixelBuffer.h

@@ -47,16 +47,6 @@ namespace CamelotFramework {
 		void bind(IDirect3DDevice9 *dev, IDirect3DSurface9 *mSurface,
 		void bind(IDirect3DDevice9 *dev, IDirect3DSurface9 *mSurface,
 			bool writeGamma, UINT32 fsaa, const String& srcName, IDirect3DBaseTexture9 *mipTex);
 			bool writeGamma, UINT32 fsaa, const String& srcName, IDirect3DBaseTexture9 *mipTex);
 		void bind(IDirect3DDevice9 *dev, IDirect3DVolume9 *mVolume, IDirect3DBaseTexture9 *mipTex);
 		void bind(IDirect3DDevice9 *dev, IDirect3DVolume9 *mVolume, IDirect3DBaseTexture9 *mipTex);
-
-		/// @copydoc HardwarePixelBuffer::blit
-		void blit(const PixelBufferPtr &src, const Box &srcBox, const Box &dstBox);
-
-		/// @copydoc HardwarePixelBuffer::blitFromMemory
-		void blitFromMemory(const PixelData &src, const Box &dstBox);
-
-		/// @copydoc HardwarePixelBuffer::blitToMemory
-		void blitToMemory(const Box &srcBox, const PixelData &dst);
-
 		/// Internal function to update mipmaps on update of level 0
 		/// Internal function to update mipmaps on update of level 0
 		void _genMipmaps(IDirect3DBaseTexture9* mipTex);
 		void _genMipmaps(IDirect3DBaseTexture9* mipTex);
 
 

+ 22 - 3
CamelotD3D9Renderer/Include/CmD3D9Texture.h

@@ -147,12 +147,31 @@ namespace CamelotFramework {
 		 */
 		 */
 		void destroy_internal();
 		void destroy_internal();
 
 
-		/// overridden from Texture
-		void copyImpl(TexturePtr& target);
-
+		/**
+		 * @copydoc Texture::lock
+		 */
 		PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0);
 		PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0);
+
+		/**
+		 * @copydoc Texture::unlock
+		 */
 		void unlockImpl();
 		void unlockImpl();
 
 
+		/**
+		 * @copydoc Texture::copy
+		 */
+		void copyImpl(TexturePtr& target);
+
+		/**
+		 * @copydoc Texture::readData
+		 */
+		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0);
+
+		/**
+		 * @copydoc Texture::writeData
+		 */
+		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false);
+
 		/// internal method, create a blank normal 1D/2D texture		
 		/// internal method, create a blank normal 1D/2D texture		
 		void _createNormTex(IDirect3DDevice9* d3d9Device);
 		void _createNormTex(IDirect3DDevice9* d3d9Device);
 		/// internal method, create a blank cube texture		
 		/// internal method, create a blank cube texture		

+ 1 - 469
CamelotD3D9Renderer/Source/CmD3D9PixelBuffer.cpp

@@ -94,34 +94,6 @@ namespace CamelotFramework
 		mRowPitch = mWidth;
 		mRowPitch = mWidth;
 		mSlicePitch = mHeight*mWidth;
 		mSlicePitch = mHeight*mWidth;
 		mSizeInBytes = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);	
 		mSizeInBytes = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);	
-	
-		// TODO PORT - My Texture doesn't inherit from Resource and doesn't have that method. Not sure why it needs to call it,
-		// but since we're not there's potential for trouble here.
-		if (isNewBuffer /*&& mOwnerTexture->isManuallyLoaded()*/)
-		{
-			DeviceToBufferResourcesIterator it = mMapDeviceToBufferResources.begin();
-
-			while (it != mMapDeviceToBufferResources.end())
-			{
-				if (it->second != bufferResources && 
-					it->second->surface != NULL &&
-					it->first->TestCooperativeLevel() == D3D_OK &&
-					dev->TestCooperativeLevel() == D3D_OK)
-				{
-					Box fullBufferBox(0,0,0,mWidth,mHeight,mDepth);
-					PixelData dstBox(fullBufferBox, mFormat);
-					dstBox.allocateInternalBuffer();
-
-					blitToMemory(fullBufferBox, dstBox, it->second, it->first);
-					blitFromMemory(dstBox, fullBufferBox, bufferResources);
-
-					dstBox.freeInternalBuffer();
-
-					break;
-				}
-				++it;			
-			}				
-		}
 	}
 	}
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	void D3D9PixelBuffer::bind(IDirect3DDevice9 *dev, IDirect3DVolume9 *volume, IDirect3DBaseTexture9 *mipTex)
 	void D3D9PixelBuffer::bind(IDirect3DDevice9 *dev, IDirect3DVolume9 *volume, IDirect3DBaseTexture9 *mipTex)
@@ -153,34 +125,6 @@ namespace CamelotFramework
 		mRowPitch = mWidth;
 		mRowPitch = mWidth;
 		mSlicePitch = mHeight*mWidth;
 		mSlicePitch = mHeight*mWidth;
 		mSizeInBytes = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
 		mSizeInBytes = PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
-
-		// TODO PORT - My Texture doesn't inherit from Resource and doesn't have that method. Not sure why it needs to call it,
-		// but since we're not there's potential for trouble here.
-		if (isNewBuffer /*&& mOwnerTexture->isManuallyLoaded()*/)
-		{
-			DeviceToBufferResourcesIterator it = mMapDeviceToBufferResources.begin();
-		
-			while (it != mMapDeviceToBufferResources.end())
-			{
-				if (it->second != bufferResources &&
-					it->second->volume != NULL &&
-					it->first->TestCooperativeLevel() == D3D_OK &&
-					dev->TestCooperativeLevel() == D3D_OK)
-				{
-					Box fullBufferBox(0,0,0,mWidth,mHeight,mDepth);
-					PixelData dstBox(fullBufferBox, mFormat);
-					dstBox.allocateInternalBuffer();
-
-					blitToMemory(fullBufferBox, dstBox, it->second, it->first);
-					blitFromMemory(dstBox, fullBufferBox, bufferResources);
-					
-					dstBox.freeInternalBuffer();
-
-					break;
-				}
-				++it;			
-			}				
-		}
 	}
 	}
 
 
 	//-----------------------------------------------------------------------------  
 	//-----------------------------------------------------------------------------  
@@ -372,7 +316,6 @@ namespace CamelotFramework
 		// PixelBox will be re-based from the locking point onwards
 		// PixelBox will be re-based from the locking point onwards
 		PixelData rval(lockBox.getWidth(), lockBox.getHeight(), lockBox.getDepth(), mFormat);
 		PixelData rval(lockBox.getWidth(), lockBox.getHeight(), lockBox.getDepth(), mFormat);
 
 
-
 		if (bufferResources->surface != NULL) 
 		if (bufferResources->surface != NULL) 
 		{
 		{
 			// Surface
 			// Surface
@@ -419,22 +362,7 @@ namespace CamelotFramework
 			CM_EXCEPT(RenderingAPIException, "There are no resources attached to this pixel buffer !!");	
 			CM_EXCEPT(RenderingAPIException, "There are no resources attached to this pixel buffer !!");	
 		}
 		}
 
 
-		DeviceToBufferResourcesIterator it;
-	
-		// 1. Update duplicates buffers.
-		it = mMapDeviceToBufferResources.begin();
-		++it;
-		while (it != mMapDeviceToBufferResources.end())
-		{			
-			BufferResources* bufferResources = it->second;
-		
-			// Update duplicated buffer from the from the locked buffer content.					
-			blitFromMemory(mCurrentLock, mLockedBox, bufferResources);										
-			++it;			
-		}
-
-		// 2. Unlock the locked buffer.
-		it = mMapDeviceToBufferResources.begin();							
+		DeviceToBufferResourcesIterator it = mMapDeviceToBufferResources.begin();							
 		unlockBuffer( it->second);		
 		unlockBuffer( it->second);		
 		if(mDoMipmapGen)
 		if(mDoMipmapGen)
 			_genMipmaps(it->second->mipTex);	
 			_genMipmaps(it->second->mipTex);	
@@ -454,402 +382,6 @@ namespace CamelotFramework
 			bufferResources->volume->UnlockBox();
 			bufferResources->volume->UnlockBox();
 		}
 		}
 	}
 	}
-
-	//-----------------------------------------------------------------------------  
-	void D3D9PixelBuffer::blit(const PixelBufferPtr &rsrc, 
-									   const Box &srcBox, 
-									   const Box &dstBox)
-	{
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
-		D3D9PixelBuffer *src = static_cast<D3D9PixelBuffer*>(rsrc.get());
-		DeviceToBufferResourcesIterator it = mMapDeviceToBufferResources.begin();
-
-		// Update all the buffer copies.
-		while (it != mMapDeviceToBufferResources.end())
-		{
-			BufferResources* srcBufferResources = src->getBufferResources(it->first);
-			BufferResources* dstBufferResources = it->second;
-
-			if (srcBufferResources == NULL)
-			{
-				CM_EXCEPT(RenderingAPIException, "There are no matching resources attached to the source pixel buffer !!");	
-			}
-
-			blit(it->first, rsrc, srcBox, dstBox, srcBufferResources, dstBufferResources);
-			++it;
-		}
-	}
-
-	//-----------------------------------------------------------------------------  
-	void D3D9PixelBuffer::blit(IDirect3DDevice9* d3d9Device, 
-									   const PixelBufferPtr &rsrc, 
-									   const Box &srcBox, 
-									   const Box &dstBox,
-									   BufferResources* srcBufferResources, 
-									   BufferResources* dstBufferResources)
-	{
-		if(dstBufferResources->surface && srcBufferResources->surface)
-		{
-			// Surface-to-surface
-			RECT dsrcRect = toD3DRECT(srcBox);
-			RECT ddestRect = toD3DRECT(dstBox);
-
-			D3DSURFACE_DESC srcDesc;
-			if(srcBufferResources->surface->GetDesc(&srcDesc) != D3D_OK)
-				CM_EXCEPT(RenderingAPIException, "Could not get surface information");
-
-			// If we're blitting from a RTT, try GetRenderTargetData
-			// if we're going to try to use GetRenderTargetData, need to use system mem pool
-			bool tryGetRenderTargetData = false;
-			if ((srcDesc.Usage & D3DUSAGE_RENDERTARGET) != 0
-				&& srcDesc.MultiSampleType == D3DMULTISAMPLE_NONE)
-			{
-
-				// Temp texture
-				IDirect3DTexture9 *tmptex;
-				IDirect3DSurface9 *tmpsurface;
-
-				if(D3DXCreateTexture(
-					d3d9Device,
-					srcDesc.Width, srcDesc.Height,
-					1, // 1 mip level ie topmost, generate no mipmaps
-					0, srcDesc.Format, D3DPOOL_SYSTEMMEM,
-					&tmptex
-					) != D3D_OK)
-				{
-					CM_EXCEPT(RenderingAPIException, "Create temporary texture failed");
-				}
-				if(tmptex->GetSurfaceLevel(0, &tmpsurface) != D3D_OK)
-				{
-					tmptex->Release();
-					CM_EXCEPT(RenderingAPIException, "Get surface level failed");
-				}
-				if(d3d9Device->GetRenderTargetData(srcBufferResources->surface, tmpsurface) == D3D_OK)
-				{
-					// Hey, it worked
-					// Copy from this surface instead
-					if(D3DXLoadSurfaceFromSurface(
-						dstBufferResources->surface, NULL, &ddestRect, 
-						tmpsurface, NULL, &dsrcRect,
-						D3DX_DEFAULT, 0) != D3D_OK)
-					{
-						tmpsurface->Release();
-						tmptex->Release();
-						CM_EXCEPT(RenderingAPIException, "D3DXLoadSurfaceFromSurface failed");
-					}
-					tmpsurface->Release();
-					tmptex->Release();
-					return;
-				}
-
-			}
-
-			// Otherwise, try the normal method
-
-			// D3DXLoadSurfaceFromSurface
-			if(D3DXLoadSurfaceFromSurface(
-				dstBufferResources->surface, NULL, &ddestRect, 
-				srcBufferResources->surface, NULL, &dsrcRect,
-				D3DX_DEFAULT, 0) != D3D_OK)
-			{
-				CM_EXCEPT(RenderingAPIException, "D3DXLoadSurfaceFromSurface failed");
-			}
-		}
-		else if(dstBufferResources->volume && srcBufferResources->volume)
-		{
-			// Volume-to-volume
-			D3DBOX dsrcBox = toD3DBOX(srcBox);
-			D3DBOX ddestBox = toD3DBOX(dstBox);
-
-			// D3DXLoadVolumeFromVolume
-			if(D3DXLoadVolumeFromVolume(
-				dstBufferResources->volume, NULL, &ddestBox, 
-				srcBufferResources->volume, NULL, &dsrcBox,
-				D3DX_DEFAULT, 0) != D3D_OK)
-			{
-				CM_EXCEPT(RenderingAPIException, "D3DXLoadVolumeFromVolume failed");
-			}
-		}
-		else
-		{
-			// Software fallback   
-			PixelBuffer::blit(rsrc, srcBox, dstBox);
-		}
-	}
-
-	//-----------------------------------------------------------------------------  
-	void D3D9PixelBuffer::blitFromMemory(const PixelData &src, const Box &dstBox)
-	{	
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
-		DeviceToBufferResourcesIterator it = mMapDeviceToBufferResources.begin();
-
-		while (it != mMapDeviceToBufferResources.end())
-		{		
-			BufferResources* dstBufferResources = it->second;
-		
-			blitFromMemory(src, dstBox, dstBufferResources);	
-			++it;
-		}
-	}
-
-	//-----------------------------------------------------------------------------  
-	void D3D9PixelBuffer::blitFromMemory(const PixelData &src, const Box &dstBox, BufferResources* dstBufferResources)
-	{
-		// for scoped deletion of conversion buffer
-		PixelData converted = src;
-
-		// convert to pixelbuffer's native format if necessary
-		if (D3D9Mappings::_getPF(src.getFormat()) == D3DFMT_UNKNOWN)
-		{
-			converted = PixelData(src.getWidth(), src.getHeight(), src.getDepth(), mFormat);
-			converted.allocateInternalBuffer();
-			PixelUtil::bulkPixelConversion(src, converted);
-		}
-
-		UINT32 rowWidth;
-		if (PixelUtil::isCompressed(converted.getFormat()))
-		{
-			// D3D wants the width of one row of cells in bytes
-			if (converted.getFormat() == PF_DXT1)
-			{
-				// 64 bits (8 bytes) per 4x4 block
-				rowWidth = (converted.getRowPitch() / 4) * 8;
-			}
-			else
-			{
-				// 128 bits (16 bytes) per 4x4 block
-				rowWidth = (converted.getRowPitch() / 4) * 16;
-			}
-
-		}
-		else
-		{
-			rowWidth = converted.getRowPitch() * PixelUtil::getNumElemBytes(converted.getFormat());
-		}
-
-		if (dstBufferResources->surface)
-		{
-			RECT destRect, srcRect;
-			srcRect = toD3DRECT(converted.getExtents());
-			destRect = toD3DRECT(dstBox);
-
-			if(D3DXLoadSurfaceFromMemory(dstBufferResources->surface, NULL, &destRect, 
-				converted.getData(), D3D9Mappings::_getPF(converted.getFormat()),
-				static_cast<UINT>(rowWidth),
-				NULL, &srcRect, D3DX_DEFAULT, 0) != D3D_OK)
-			{
-				CM_EXCEPT(RenderingAPIException, "D3DXLoadSurfaceFromMemory failed");
-			}
-		}
-		else if (dstBufferResources->volume)
-		{
-			D3DBOX destBox, srcBox;
-			srcBox = toD3DBOX(converted.getExtents());
-			destBox = toD3DBOX(dstBox);
-			UINT32 sliceWidth;
-			if (PixelUtil::isCompressed(converted.getFormat()))
-			{
-				// D3D wants the width of one slice of cells in bytes
-				if (converted.getFormat() == PF_DXT1)
-				{
-					// 64 bits (8 bytes) per 4x4 block
-					sliceWidth = (converted.getSlicePitch() / 16) * 8;
-				}
-				else
-				{
-					// 128 bits (16 bytes) per 4x4 block
-					sliceWidth = (converted.getSlicePitch() / 16) * 16;
-				}
-
-			}
-			else
-			{
-				sliceWidth = converted.getSlicePitch() * PixelUtil::getNumElemBytes(converted.getFormat());
-			}
-
-			if(D3DXLoadVolumeFromMemory(dstBufferResources->volume, NULL, &destBox, 
-				converted.getData(), D3D9Mappings::_getPF(converted.getFormat()),
-				static_cast<UINT>(rowWidth), static_cast<UINT>(sliceWidth),
-				NULL, &srcBox, D3DX_DEFAULT, 0) != D3D_OK)
-			{
-				CM_EXCEPT(RenderingAPIException, "D3DXLoadSurfaceFromMemory failed");
-			}
-		}
-
-		if(mDoMipmapGen)
-			_genMipmaps(dstBufferResources->mipTex);
-
-		converted.freeInternalBuffer();
-	}
-
-	//-----------------------------------------------------------------------------  
-	void D3D9PixelBuffer::blitToMemory(const Box &srcBox, const PixelData &dst)
-	{
-		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
-
-		DeviceToBufferResourcesIterator it = mMapDeviceToBufferResources.begin();
-		BufferResources* bufferResources = it->second;
-
-		blitToMemory(srcBox, dst, bufferResources, it->first);
-	}
-
-	//-----------------------------------------------------------------------------  
-	void D3D9PixelBuffer::blitToMemory(const Box &srcBox, const PixelData &dst, 
-											   BufferResources* srcBufferResources,
-											   IDirect3DDevice9* d3d9Device)
-	{
-		// Decide on pixel format of temp surface
-		PixelFormat tmpFormat = mFormat; 
-		if(D3D9Mappings::_getPF(dst.getFormat()) != D3DFMT_UNKNOWN)
-		{
-			tmpFormat = dst.getFormat();
-		}
-
-		if (srcBufferResources->surface)
-		{
-			assert(srcBox.getDepth() == 1 && dst.getDepth() == 1);
-			// Create temp texture
-			IDirect3DTexture9 *tmp;
-			IDirect3DSurface9 *surface;
-
-			D3DSURFACE_DESC srcDesc;
-			if(srcBufferResources->surface->GetDesc(&srcDesc) != D3D_OK)
-				CM_EXCEPT(RenderingAPIException, "Could not get surface information");
-
-			D3DPOOL temppool = D3DPOOL_SCRATCH;
-			// if we're going to try to use GetRenderTargetData, need to use system mem pool
-			bool tryGetRenderTargetData = false;
-			if (((srcDesc.Usage & D3DUSAGE_RENDERTARGET) != 0) &&
-				(srcBox.getWidth() == dst.getWidth()) && (srcBox.getHeight() == dst.getHeight()) &&
-				(srcBox.getWidth() == getWidth()) && (srcBox.getHeight() == getHeight()) &&
-				(mFormat == tmpFormat))
-			{
-				tryGetRenderTargetData = true;
-				temppool = D3DPOOL_SYSTEMMEM;
-			}
-
-			if(D3DXCreateTexture(
-				d3d9Device,
-				static_cast<UINT>(dst.getWidth()), static_cast<UINT>(dst.getHeight()), 
-				1, // 1 mip level ie topmost, generate no mipmaps
-				0, D3D9Mappings::_getPF(tmpFormat), temppool,
-				&tmp
-				) != D3D_OK)
-			{
-				CM_EXCEPT(RenderingAPIException, "Create temporary texture failed");
-			}
-			if(tmp->GetSurfaceLevel(0, &surface) != D3D_OK)
-			{
-				tmp->Release();
-				CM_EXCEPT(RenderingAPIException, "Get surface level failed");
-			}
-			// Copy texture to this temp surface
-			RECT destRect, srcRect;
-			srcRect = toD3DRECT(srcBox);
-			destRect = toD3DRECTExtent(dst);
-
-			// Get the real temp surface format
-			D3DSURFACE_DESC dstDesc;
-			if(surface->GetDesc(&dstDesc) != D3D_OK)
-				CM_EXCEPT(RenderingAPIException, "Could not get surface information");
-			tmpFormat = D3D9Mappings::_getPF(dstDesc.Format);
-
-			// Use fast GetRenderTargetData if we are in its usage conditions
-			bool fastLoadSuccess = false;
-			if (tryGetRenderTargetData)
-			{
-				if(d3d9Device->GetRenderTargetData(srcBufferResources->surface, surface) == D3D_OK)
-				{
-					fastLoadSuccess = true;
-				}
-			}
-			if (!fastLoadSuccess)
-			{
-				if(D3DXLoadSurfaceFromSurface(
-					surface, NULL, &destRect, 
-					srcBufferResources->surface, NULL, &srcRect,
-					D3DX_DEFAULT, 0) != D3D_OK)
-				{
-					surface->Release();
-					tmp->Release();
-					CM_EXCEPT(RenderingAPIException, "D3DXLoadSurfaceFromSurface failed");
-				}
-			}
-
-			// Lock temp surface and copy it to memory
-			D3DLOCKED_RECT lrect; // Filled in by D3D
-			if(surface->LockRect(&lrect, NULL,  D3DLOCK_READONLY) != D3D_OK)
-			{
-				surface->Release();
-				tmp->Release();
-				CM_EXCEPT(RenderingAPIException, "surface->LockRect");
-			}
-			// Copy it
-			PixelData locked(dst.getWidth(), dst.getHeight(), dst.getDepth(), tmpFormat);
-			fromD3DLock(locked, lrect);
-			PixelUtil::bulkPixelConversion(locked, dst);
-			surface->UnlockRect();
-			// Release temporary surface and texture
-			surface->Release();
-			tmp->Release();
-		}
-		else if (srcBufferResources->volume)
-		{
-			// Create temp texture
-			IDirect3DVolumeTexture9 *tmp;
-			IDirect3DVolume9 *surface;
-
-			if(D3DXCreateVolumeTexture(
-				d3d9Device,
-				static_cast<UINT>(dst.getWidth()), 
-				static_cast<UINT>(dst.getHeight()), 
-				static_cast<UINT>(dst.getDepth()), 0,
-				0, D3D9Mappings::_getPF(tmpFormat), D3DPOOL_SCRATCH,
-				&tmp
-				) != D3D_OK)
-			{
-				CM_EXCEPT(RenderingAPIException, "Create temporary texture failed");
-			}
-			if(tmp->GetVolumeLevel(0, &surface) != D3D_OK)
-			{
-				tmp->Release();
-				CM_EXCEPT(RenderingAPIException, "Get volume level failed");
-			}
-			// Volume
-			D3DBOX ddestBox, dsrcBox;
-			ddestBox = toD3DBOXExtent(dst);
-			dsrcBox = toD3DBOX(srcBox);
-
-			if(D3DXLoadVolumeFromVolume(
-				surface, NULL, &ddestBox, 
-				srcBufferResources->volume, NULL, &dsrcBox,
-				D3DX_DEFAULT, 0) != D3D_OK)
-			{
-				surface->Release();
-				tmp->Release();
-				CM_EXCEPT(RenderingAPIException, "D3DXLoadVolumeFromVolume failed");
-			}
-			// Lock temp surface and copy it to memory
-			D3DLOCKED_BOX lbox; // Filled in by D3D
-			if(surface->LockBox(&lbox, NULL,  D3DLOCK_READONLY) != D3D_OK)
-			{
-				surface->Release();
-				tmp->Release();
-				CM_EXCEPT(RenderingAPIException, "surface->LockBox");
-			}
-			// Copy it
-			PixelData locked(dst.getWidth(), dst.getHeight(), dst.getDepth(), tmpFormat);
-			fromD3DLock(locked, lbox);
-			PixelUtil::bulkPixelConversion(locked, dst);
-			surface->UnlockBox();
-			// Release temporary surface and texture
-			surface->Release();
-			tmp->Release();
-		}
-	}
-
 	//-----------------------------------------------------------------------------  
 	//-----------------------------------------------------------------------------  
 	void D3D9PixelBuffer::_genMipmaps(IDirect3DBaseTexture9* mipTex)
 	void D3D9PixelBuffer::_genMipmaps(IDirect3DBaseTexture9* mipTex)
 	{
 	{

+ 31 - 0
CamelotD3D9Renderer/Source/CmD3D9Texture.cpp

@@ -85,6 +85,37 @@ namespace CamelotFramework
 		mLockedBuffer->unlock();
 		mLockedBuffer->unlock();
 		mLockedBuffer = nullptr;
 		mLockedBuffer = nullptr;
 	}
 	}
+
+	void D3D9Texture::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
+	{
+		PixelData myData = lock(GBL_READ_ONLY, mipLevel, face);
+
+#if CM_DEBUG_MODE
+		if(dest.getConsecutiveSize() != myData.getConsecutiveSize())
+		{
+			unlock();
+			CM_EXCEPT(InternalErrorException, "Buffer sizes don't match");
+		}
+#endif
+
+		PixelUtil::bulkPixelConversion(myData, dest);
+
+		unlock();
+	}
+
+	void D3D9Texture::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
+	{
+		if(mUsage == TU_DYNAMIC || mUsage == TU_STATIC)
+		{
+			PixelData myData = lock(discardWholeBuffer ? GBL_WRITE_ONLY_DISCARD : GBL_WRITE_ONLY, mipLevel, face);
+			PixelUtil::bulkPixelConversion(src, myData);
+			unlock();
+		}
+		else
+		{
+			CM_EXCEPT(RenderingAPIException, "Trying to write into a buffer with unsupported usage: " + toString(mUsage));
+		}
+	}
 	
 	
 	void D3D9Texture::copyImpl(TexturePtr& target)
 	void D3D9Texture::copyImpl(TexturePtr& target)
 	{
 	{

+ 1 - 1
CamelotFreeImgImporter/Include/CmTextureData.h

@@ -71,7 +71,7 @@ namespace CamelotFramework
         */
         */
         bool getHasAlpha() const { return PixelUtil::getFlags(mFormat) & PFF_HASALPHA; }
         bool getHasAlpha() const { return PixelUtil::getFlags(mFormat) & PFF_HASALPHA; }
 
 
-		PixelDataPtr getPixels(UINT32 mip);
+		void getPixels(UINT32 mip, PixelData& output);
 
 
 	private:
 	private:
 		UINT32 mNumMipmaps;
 		UINT32 mNumMipmaps;

+ 4 - 2
CamelotFreeImgImporter/Source/CmFreeImgImporter.cpp

@@ -132,9 +132,11 @@ namespace CamelotFramework
 
 
 		for(UINT32 mip = 0; mip <= imgData->getNumMipmaps(); ++mip)
 		for(UINT32 mip = 0; mip <= imgData->getNumMipmaps(); ++mip)
 		{
 		{
-			PixelDataPtr src = imgData->getPixels(mip);
-
 			UINT32 subresourceIdx = newTexture->mapToSubresourceIdx(0, mip);
 			UINT32 subresourceIdx = newTexture->mapToSubresourceIdx(0, mip);
+			PixelDataPtr src = newTexture->allocateSubresourceBuffer(subresourceIdx);
+
+			imgData->getPixels(mip, *src);
+
 			gMainSyncedCA().writeSubresource(newTexture.getInternalPtr(), subresourceIdx, src);
 			gMainSyncedCA().writeSubresource(newTexture.getInternalPtr(), subresourceIdx, src);
 		}
 		}
 
 

+ 4 - 7
CamelotFreeImgImporter/Source/CmTextureData.cpp

@@ -18,7 +18,7 @@ namespace CamelotFramework
 			cm_free<ScratchAlloc>(mData);
 			cm_free<ScratchAlloc>(mData);
 	}
 	}
 
 
-	PixelDataPtr TextureData::getPixels(UINT32 mip)
+	void TextureData::getPixels(UINT32 mip, PixelData& output)
 	{
 	{
 		if(mip < 0 || mip > mNumMipmaps)
 		if(mip < 0 || mip > mNumMipmaps)
 		{
 		{
@@ -51,12 +51,9 @@ namespace CamelotFramework
 			if(depth!=1) depth /= 2;
 			if(depth!=1) depth /= 2;
 		}
 		}
 
 
-		// Return subface as pixelbox
-		PixelDataPtr src = cm_shared_ptr<PixelData>(finalWidth, finalHeight, finalDepth, getFormat());
-		src->allocateInternalBuffer();
+		PixelData myData(finalWidth, finalHeight, finalDepth, getFormat());
+		myData.setExternalBuffer(offset);
 
 
-		memcpy(src->getData(), offset, src->getConsecutiveSize());
-
-		return src;
+		PixelUtil::bulkPixelConversion(myData, output);
 	}
 	}
 }
 }

+ 15 - 18
CamelotGLRenderer/Include/CmGLPixelBuffer.h

@@ -31,9 +31,21 @@ THE SOFTWARE.
 #include "CmGLPrerequisites.h"
 #include "CmGLPrerequisites.h"
 #include "CmPixelBuffer.h"
 #include "CmPixelBuffer.h"
 
 
-namespace CamelotFramework {
+namespace CamelotFramework 
+{
+	class GLTextureBuffer;
+
 	class CM_RSGL_EXPORT GLPixelBuffer: public PixelBuffer
 	class CM_RSGL_EXPORT GLPixelBuffer: public PixelBuffer
 	{
 	{
+	public:
+		// Upload a box of pixels to this buffer on the card
+		virtual void upload(const PixelData &data, const Box &dest);
+		// Download a box of pixels from the card
+		virtual void download(const PixelData &data);
+
+		virtual void blitFromTexture(GLTextureBuffer *src);
+		virtual void blitFromTexture(GLTextureBuffer *src, const Box &srcBox, const Box &dstBox);
+
 	protected:  
 	protected:  
 		/// Lock a box
 		/// Lock a box
 		PixelData lockImpl(const Box lockBox,  GpuLockOptions options);
 		PixelData lockImpl(const Box lockBox,  GpuLockOptions options);
@@ -50,22 +62,12 @@ namespace CamelotFramework {
 		// Buffer allocation/freeage
 		// Buffer allocation/freeage
 		void allocateBuffer();
 		void allocateBuffer();
 		void freeBuffer();
 		void freeBuffer();
-		// Upload a box of pixels to this buffer on the card
-		virtual void upload(const PixelData &data, const Box &dest);
-		// Download a box of pixels from the card
-		virtual void download(const PixelData &data);
 	public:
 	public:
         /// Should be called by HardwareBufferManager
         /// Should be called by HardwareBufferManager
         GLPixelBuffer(UINT32 mWidth, UINT32 mHeight, UINT32 mDepth,
         GLPixelBuffer(UINT32 mWidth, UINT32 mHeight, UINT32 mDepth,
                 PixelFormat mFormat,
                 PixelFormat mFormat,
                 GpuBufferUsage usage);
                 GpuBufferUsage usage);
 		
 		
-		/// @copydoc HardwarePixelBuffer::blitFromMemory
-		void blitFromMemory(const PixelData &src, const Box &dstBox);
-		
-		/// @copydoc HardwarePixelBuffer::blitToMemory
-		void blitToMemory(const Box &srcBox, const PixelData &dst);
-		
 		~GLPixelBuffer();
 		~GLPixelBuffer();
         
         
         /** Bind surface to frame buffer. Needs FBO extension.
         /** Bind surface to frame buffer. Needs FBO extension.
@@ -91,15 +93,10 @@ namespace CamelotFramework {
 		// Download a box of pixels from the card
 		// Download a box of pixels from the card
 		virtual void download(const PixelData &data);
 		virtual void download(const PixelData &data);
   
   
-        /// Hardware implementation of blitFromMemory
-        virtual void blitFromMemory(const PixelData &src_orig, const Box &dstBox);
-        
         /// Copy from framebuffer
         /// Copy from framebuffer
         void copyFromFramebuffer(UINT32 zoffset);
         void copyFromFramebuffer(UINT32 zoffset);
-        /// @copydoc HardwarePixelBuffer::blit
-        void blit(const PixelBufferPtr &src, const Box &srcBox, const Box &dstBox);
-        // Blitting implementation
-        void blitFromTexture(GLTextureBuffer *src, const Box &srcBox, const Box &dstBox);
+
+		void blitFromTexture(GLTextureBuffer *src, const Box &srcBox, const Box &dstBox);
     protected:
     protected:
         // In case this is a texture level
         // In case this is a texture level
 		GLenum mTarget;
 		GLenum mTarget;

+ 24 - 4
CamelotGLRenderer/Include/CmGLTexture.h

@@ -59,7 +59,7 @@ namespace CamelotFramework {
 			@remarks	The buffer is invalidated when the resource is unloaded or destroyed.
 			@remarks	The buffer is invalidated when the resource is unloaded or destroyed.
 						Do not use it after the lifetime of the containing texture.
 						Do not use it after the lifetime of the containing texture.
 		*/
 		*/
-		PixelBufferPtr getBuffer(UINT32 face, UINT32 mipmap);
+		std::shared_ptr<GLPixelBuffer> getBuffer(UINT32 face, UINT32 mipmap);
 
 
     protected:
     protected:
 		friend class GLTextureManager;
 		friend class GLTextureManager;
@@ -77,11 +77,31 @@ namespace CamelotFramework {
 		 */
 		 */
 		void destroy_internal();
 		void destroy_internal();
 
 
-		PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face);
+		/**
+		 * @copydoc Texture::lock
+		 */
+		PixelData lockImpl(GpuLockOptions options, UINT32 mipLevel = 0, UINT32 face = 0);
+
+		/**
+		 * @copydoc Texture::unlock
+		 */
 		void unlockImpl();
 		void unlockImpl();
 
 
+		/**
+		 * @copydoc Texture::copy
+		 */
 		void copyImpl(TexturePtr& target);
 		void copyImpl(TexturePtr& target);
 
 
+		/**
+		 * @copydoc Texture::readData
+		 */
+		void readData(PixelData& dest, UINT32 mipLevel = 0, UINT32 face = 0);
+
+		/**
+		 * @copydoc Texture::writeData
+		 */
+		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false);
+
 		/** internal method, create GLHardwarePixelBuffers for every face and
 		/** internal method, create GLHardwarePixelBuffers for every face and
 			 mipmap level. This method must be called after the GL texture object was created,
 			 mipmap level. This method must be called after the GL texture object was created,
 			the number of mipmaps was set (GL_TEXTURE_MAX_LEVEL) and glTexImageXD was called to
 			the number of mipmaps was set (GL_TEXTURE_MAX_LEVEL) and glTexImageXD was called to
@@ -92,10 +112,10 @@ namespace CamelotFramework {
     private:
     private:
         GLuint mTextureID;
         GLuint mTextureID;
         GLSupport& mGLSupport;
         GLSupport& mGLSupport;
-		PixelBufferPtr mLockedBuffer;
+		std::shared_ptr<GLPixelBuffer> mLockedBuffer;
 		
 		
 		/// Vector of pointers to subsurfaces
 		/// Vector of pointers to subsurfaces
-		typedef Vector<PixelBufferPtr>::type SurfaceList;
+		typedef Vector<std::shared_ptr<GLPixelBuffer>>::type SurfaceList;
 		SurfaceList	mSurfaceList;
 		SurfaceList	mSurfaceList;
     };
     };
 
 

+ 6 - 4
CamelotGLRenderer/Source/CmGLMultiRenderTexture.cpp

@@ -26,8 +26,9 @@ namespace CamelotFramework
 			if(mColorSurfaces[i] != nullptr)
 			if(mColorSurfaces[i] != nullptr)
 			{
 			{
 				GLTexture* glColorSurface = static_cast<GLTexture*>(mColorSurfaces[i]->getTexture().get());
 				GLTexture* glColorSurface = static_cast<GLTexture*>(mColorSurfaces[i]->getTexture().get());
-				GLPixelBufferPtr colorBuffer = std::static_pointer_cast<GLPixelBuffer>(
-					glColorSurface->getBuffer(mColorSurfaces[i]->getDesc().firstArraySlice, mColorSurfaces[i]->getDesc().mostDetailMip));
+				GLPixelBufferPtr colorBuffer = 
+					glColorSurface->getBuffer(mColorSurfaces[i]->getDesc().firstArraySlice, 
+					mColorSurfaces[i]->getDesc().mostDetailMip);
 
 
 				GLSurfaceDesc surfaceDesc;
 				GLSurfaceDesc surfaceDesc;
 				surfaceDesc.numSamples = mFSAA;
 				surfaceDesc.numSamples = mFSAA;
@@ -45,8 +46,9 @@ namespace CamelotFramework
 		if(mDepthStencilSurface != nullptr)
 		if(mDepthStencilSurface != nullptr)
 		{
 		{
 			GLTexture* glDepthStencilSurface = static_cast<GLTexture*>(mDepthStencilSurface->getTexture().get());
 			GLTexture* glDepthStencilSurface = static_cast<GLTexture*>(mDepthStencilSurface->getTexture().get());
-			GLPixelBufferPtr depthStencilBuffer = std::static_pointer_cast<GLPixelBuffer>(
-				glDepthStencilSurface->getBuffer(mDepthStencilSurface->getDesc().firstArraySlice, mDepthStencilSurface->getDesc().mostDetailMip));
+			GLPixelBufferPtr depthStencilBuffer = 
+				glDepthStencilSurface->getBuffer(mDepthStencilSurface->getDesc().firstArraySlice, 
+				mDepthStencilSurface->getDesc().mostDetailMip);
 
 
 			mFB->bindDepthStencil(depthStencilBuffer);
 			mFB->bindDepthStencil(depthStencilBuffer);
 		}
 		}

+ 41 - 198
CamelotGLRenderer/Source/CmGLPixelBuffer.cpp

@@ -35,7 +35,6 @@ THE SOFTWARE.
 
 
 namespace CamelotFramework 
 namespace CamelotFramework 
 {
 {
-	//----------------------------------------------------------------------------- 
 	GLPixelBuffer::GLPixelBuffer(UINT32 inWidth, UINT32 inHeight, UINT32 inDepth,
 	GLPixelBuffer::GLPixelBuffer(UINT32 inWidth, UINT32 inHeight, UINT32 inDepth,
 					PixelFormat inFormat,
 					PixelFormat inFormat,
 					GpuBufferUsage usage):
 					GpuBufferUsage usage):
@@ -46,13 +45,12 @@ namespace CamelotFramework
 		mCurrentLockOptions = (GpuLockOptions)0;
 		mCurrentLockOptions = (GpuLockOptions)0;
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------  
 	GLPixelBuffer::~GLPixelBuffer()
 	GLPixelBuffer::~GLPixelBuffer()
 	{
 	{
 		// Force free buffer
 		// Force free buffer
 		mBuffer.freeInternalBuffer();
 		mBuffer.freeInternalBuffer();
 	}
 	}
-	//-----------------------------------------------------------------------------  
+
 	void GLPixelBuffer::allocateBuffer()
 	void GLPixelBuffer::allocateBuffer()
 	{
 	{
 		if(mBuffer.getData())
 		if(mBuffer.getData())
@@ -62,7 +60,7 @@ namespace CamelotFramework
 		mBuffer.allocateInternalBuffer();
 		mBuffer.allocateInternalBuffer();
 		// TODO: use PBO if we're HBU_DYNAMIC
 		// TODO: use PBO if we're HBU_DYNAMIC
 	}
 	}
-	//-----------------------------------------------------------------------------  
+
 	void GLPixelBuffer::freeBuffer()
 	void GLPixelBuffer::freeBuffer()
 	{
 	{
 		// Free buffer if we're STATIC to save memory
 		// Free buffer if we're STATIC to save memory
@@ -71,7 +69,7 @@ namespace CamelotFramework
 			mBuffer.freeInternalBuffer();
 			mBuffer.freeInternalBuffer();
 		}
 		}
 	}
 	}
-	//-----------------------------------------------------------------------------  
+
 	PixelData GLPixelBuffer::lockImpl(const Box lockBox,  GpuLockOptions options)
 	PixelData GLPixelBuffer::lockImpl(const Box lockBox,  GpuLockOptions options)
 	{
 	{
 		allocateBuffer();
 		allocateBuffer();
@@ -84,7 +82,7 @@ namespace CamelotFramework
 		mLockedBox = lockBox;
 		mLockedBox = lockBox;
 		return mBuffer.getSubVolume(lockBox);
 		return mBuffer.getSubVolume(lockBox);
 	}
 	}
-	//-----------------------------------------------------------------------------  
+
 	void GLPixelBuffer::unlockImpl(void)
 	void GLPixelBuffer::unlockImpl(void)
 	{
 	{
 		if (mCurrentLockOptions != GBL_READ_ONLY)
 		if (mCurrentLockOptions != GBL_READ_ONLY)
@@ -96,97 +94,35 @@ namespace CamelotFramework
 		freeBuffer();
 		freeBuffer();
 	}
 	}
 
 
-	//-----------------------------------------------------------------------------  
-	void GLPixelBuffer::blitFromMemory(const PixelData &src, const Box &dstBox)
-	{
-		if(!mBuffer.getExtents().contains(dstBox))
-			CM_EXCEPT(InvalidParametersException, "destination box out of range");
-		PixelData scaled;
-	
-		if(src.getWidth() != dstBox.getWidth() ||
-			src.getHeight() != dstBox.getHeight() ||
-			src.getDepth() != dstBox.getDepth())
-		{
-			// Scale to destination size. Use DevIL and not iluScale because ILU screws up for 
-			// floating point textures and cannot cope with 3D images.
-			// This also does pixel format conversion if needed
-			allocateBuffer();
-			scaled = mBuffer.getSubVolume(dstBox);
-			PixelUtil::scale(src, scaled, PixelUtil::FILTER_BILINEAR);
-		}
-		else if(GLPixelUtil::getGLOriginFormat(src.getFormat()) == 0)
-		{
-			// Extents match, but format is not accepted as valid source format for GL
-			// do conversion in temporary buffer
-			allocateBuffer();
-			scaled = mBuffer.getSubVolume(dstBox);
-			PixelUtil::bulkPixelConversion(src, scaled);
-		}
-		else
-		{
-			allocateBuffer();
-			// No scaling or conversion needed
-			scaled = src;
-		}
-	
-		upload(scaled, dstBox);
-		freeBuffer();
-	}
-	//-----------------------------------------------------------------------------  
-	void GLPixelBuffer::blitToMemory(const Box &srcBox, const PixelData &dst)
-	{
-		if(!mBuffer.getExtents().contains(srcBox))
-			CM_EXCEPT(InvalidParametersException, "source box out of range");
-		if(srcBox.left == 0 && srcBox.right == getWidth() &&
-		   srcBox.top == 0 && srcBox.bottom == getHeight() &&
-		   srcBox.front == 0 && srcBox.back == getDepth() &&
-		   dst.getWidth() == getWidth() &&
-		   dst.getHeight() == getHeight() &&
-		   dst.getDepth() == getDepth() &&
-		   GLPixelUtil::getGLOriginFormat(dst.getFormat()) != 0)
-		{
-			// The direct case: the user wants the entire texture in a format supported by GL
-			// so we don't need an intermediate buffer
-			download(dst);
-		}
-		else
-		{
-			// Use buffer for intermediate copy
-			allocateBuffer();
-			// Download entire buffer
-			download(mBuffer);
-			if(srcBox.getWidth() != dst.getWidth() ||
-				srcBox.getHeight() != dst.getHeight() ||
-				srcBox.getDepth() != dst.getDepth())
-			{
-				// We need scaling
-				PixelUtil::scale(mBuffer.getSubVolume(srcBox), dst, PixelUtil::FILTER_BILINEAR);
-			}
-			else
-			{
-				// Just copy the bit that we need
-				PixelUtil::bulkPixelConversion(mBuffer.getSubVolume(srcBox), dst);
-			}
-			freeBuffer();
-		}
-	}
-	//-----------------------------------------------------------------------------
 	void GLPixelBuffer::upload(const PixelData &data, const Box &dest)
 	void GLPixelBuffer::upload(const PixelData &data, const Box &dest)
 	{
 	{
 		CM_EXCEPT(RenderingAPIException, 
 		CM_EXCEPT(RenderingAPIException, 
 			"Upload not possible for this pixelbuffer type");
 			"Upload not possible for this pixelbuffer type");
 	}
 	}
-	//-----------------------------------------------------------------------------  
+
 	void GLPixelBuffer::download(const PixelData &data)
 	void GLPixelBuffer::download(const PixelData &data)
 	{
 	{
 		CM_EXCEPT(RenderingAPIException, "Download not possible for this pixelbuffer type");
 		CM_EXCEPT(RenderingAPIException, "Download not possible for this pixelbuffer type");
 	}
 	}
-	//-----------------------------------------------------------------------------  
+
+	void GLPixelBuffer::blitFromTexture(GLTextureBuffer *src)
+	{
+		blitFromTexture(src, 
+			Box(0,0,0,src->getWidth(),src->getHeight(),src->getDepth()), 
+			Box(0,0,0,mWidth,mHeight,mDepth)
+			);
+	}
+
+	void GLPixelBuffer::blitFromTexture(GLTextureBuffer *src, const Box &srcBox, const Box &dstBox)
+	{
+		CM_EXCEPT(RenderingAPIException, "BlitFromTexture not possible for this pixelbuffer type");
+	}
+
 	void GLPixelBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
 	void GLPixelBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
 	{
 	{
 		CM_EXCEPT(RenderingAPIException, "Framebuffer bind not possible for this pixelbuffer type");
 		CM_EXCEPT(RenderingAPIException, "Framebuffer bind not possible for this pixelbuffer type");
 	}
 	}
-	//********* GLTextureBuffer
+
 	GLTextureBuffer::GLTextureBuffer(const String &baseName, GLenum target, GLuint id, 
 	GLTextureBuffer::GLTextureBuffer(const String &baseName, GLenum target, GLuint id, 
 									 GLint face, GLint level, GpuBufferUsage usage, bool crappyCard, 
 									 GLint face, GLint level, GpuBufferUsage usage, bool crappyCard, 
 									 bool writeGamma, UINT32 fsaa):
 									 bool writeGamma, UINT32 fsaa):
@@ -239,9 +175,10 @@ namespace CamelotFramework
 			/// We are invalid, do not allocate a buffer
 			/// We are invalid, do not allocate a buffer
 			return;
 			return;
 	}
 	}
+
 	GLTextureBuffer::~GLTextureBuffer()
 	GLTextureBuffer::~GLTextureBuffer()
 	{ }
 	{ }
-	//-----------------------------------------------------------------------------
+
 	void GLTextureBuffer::upload(const PixelData &data, const Box &dest)
 	void GLTextureBuffer::upload(const PixelData &data, const Box &dest)
 	{
 	{
 		if((mUsage & TU_RENDERTARGET) != 0)
 		if((mUsage & TU_RENDERTARGET) != 0)
@@ -372,7 +309,7 @@ namespace CamelotFramework
 		glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
 		glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
 		glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 		glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
 	}
 	}
-	//-----------------------------------------------------------------------------  
+
 	void GLTextureBuffer::download(const PixelData &data)
 	void GLTextureBuffer::download(const PixelData &data)
 	{
 	{
 		if((mUsage & TU_RENDERTARGET) != 0)
 		if((mUsage & TU_RENDERTARGET) != 0)
@@ -418,7 +355,7 @@ namespace CamelotFramework
 			glPixelStorei(GL_PACK_ALIGNMENT, 4);
 			glPixelStorei(GL_PACK_ALIGNMENT, 4);
 		}
 		}
 	}
 	}
-	//-----------------------------------------------------------------------------  
+
 	void GLTextureBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
 	void GLTextureBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
 	{
 	{
 		assert(zoffset < mDepth);
 		assert(zoffset < mDepth);
@@ -444,7 +381,7 @@ namespace CamelotFramework
 			break;
 			break;
 		}
 		}
 	}
 	}
-	//-----------------------------------------------------------------------------
+
 	void GLTextureBuffer::copyFromFramebuffer(UINT32 zoffset)
 	void GLTextureBuffer::copyFromFramebuffer(UINT32 zoffset)
 	{
 	{
 		glBindTexture(mTarget, mTextureID);
 		glBindTexture(mTarget, mTextureID);
@@ -462,28 +399,7 @@ namespace CamelotFramework
 			break;
 			break;
 		}
 		}
 	}
 	}
-	//-----------------------------------------------------------------------------  
-	void GLTextureBuffer::blit(const PixelBufferPtr &src, const Box &srcBox, const Box &dstBox)
-	{
-		GLTextureBuffer *srct = static_cast<GLTextureBuffer *>(src.get());
-		/// Check for FBO support first
-		/// Destination texture must be 1D, 2D, 3D, or Cube
-		/// Source texture must be 1D, 2D or 3D
-	
-		// This does not sem to work for RTTs after the first update
-		// I have no idea why! For the moment, disable 
-		if(GLEW_EXT_framebuffer_object && (src->getUsage() & TU_RENDERTARGET) == 0 &&
-			(srct->mTarget==GL_TEXTURE_1D||srct->mTarget==GL_TEXTURE_2D||srct->mTarget==GL_TEXTURE_3D))
-		{
-			blitFromTexture(srct, srcBox, dstBox);
-		}
-		else
-		{
-			GLPixelBuffer::blit(src, srcBox, dstBox);
-		}
-	}
 
 
-	//-----------------------------------------------------------------------------  
 	/// Very fast texture-to-texture blitter and hardware bi/trilinear scaling implementation using FBO
 	/// Very fast texture-to-texture blitter and hardware bi/trilinear scaling implementation using FBO
 	/// Destination texture must be 1D, 2D, 3D, or Cube
 	/// Destination texture must be 1D, 2D, 3D, or Cube
 	/// Source texture must be 1D, 2D or 3D
 	/// Source texture must be 1D, 2D or 3D
@@ -497,7 +413,7 @@ namespace CamelotFramework
 		//mTextureID << ":" << dstBox.left << "," << dstBox.top << "," << dstBox.right << "," << dstBox.bottom << std::endl;
 		//mTextureID << ":" << dstBox.left << "," << dstBox.top << "," << dstBox.right << "," << dstBox.bottom << std::endl;
 		/// Store reference to FBO manager
 		/// Store reference to FBO manager
 		GLRTTManager *fboMan = static_cast<GLRTTManager *>(GLRTTManager::instancePtr());
 		GLRTTManager *fboMan = static_cast<GLRTTManager *>(GLRTTManager::instancePtr());
-    
+
 		/// Save and clear GL state for rendering
 		/// Save and clear GL state for rendering
 		glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | 
 		glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT | 
 			GL_FOG_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT | GL_SCISSOR_BIT | GL_STENCIL_BUFFER_BIT |
 			GL_FOG_BIT | GL_LIGHTING_BIT | GL_POLYGON_BIT | GL_SCISSOR_BIT | GL_STENCIL_BUFFER_BIT |
@@ -521,7 +437,7 @@ namespace CamelotFramework
 		glDisable(GL_LIGHTING);
 		glDisable(GL_LIGHTING);
 		glDisable(GL_FOG);
 		glDisable(GL_FOG);
 		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
 		glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
-    
+
 		/// Save and reset matrices
 		/// Save and reset matrices
 		glMatrixMode(GL_MODELVIEW);
 		glMatrixMode(GL_MODELVIEW);
 		glPushMatrix();
 		glPushMatrix();
@@ -532,10 +448,10 @@ namespace CamelotFramework
 		glMatrixMode(GL_TEXTURE);
 		glMatrixMode(GL_TEXTURE);
 		glPushMatrix();
 		glPushMatrix();
 		glLoadIdentity();
 		glLoadIdentity();
-    
+
 		/// Set up source texture
 		/// Set up source texture
 		glBindTexture(src->mTarget, src->mTextureID);
 		glBindTexture(src->mTarget, src->mTextureID);
-    
+
 		/// Set filtering modes depending on the dimensions and source
 		/// Set filtering modes depending on the dimensions and source
 		if(srcBox.getWidth()==dstBox.getWidth() &&
 		if(srcBox.getWidth()==dstBox.getWidth() &&
 			srcBox.getHeight()==dstBox.getHeight() &&
 			srcBox.getHeight()==dstBox.getHeight() &&
@@ -556,18 +472,18 @@ namespace CamelotFramework
 		glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 		glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
 		glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 		glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 		glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
 		glTexParameteri(src->mTarget, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
-    
+
 		/// Set origin base level mipmap to make sure we source from the right mip
 		/// Set origin base level mipmap to make sure we source from the right mip
 		/// level.
 		/// level.
 		glTexParameteri(src->mTarget, GL_TEXTURE_BASE_LEVEL, src->mLevel);
 		glTexParameteri(src->mTarget, GL_TEXTURE_BASE_LEVEL, src->mLevel);
-    
+
 		/// Store old binding so it can be restored later
 		/// Store old binding so it can be restored later
 		GLint oldfb;
 		GLint oldfb;
 		glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb);
 		glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldfb);
-    
+
 		/// Set up temporary FBO
 		/// Set up temporary FBO
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboMan->getTemporaryFBO());
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboMan->getTemporaryFBO());
-    
+
 		GLuint tempTex = 0;
 		GLuint tempTex = 0;
 		if(!fboMan->checkFormat(mFormat))
 		if(!fboMan->checkFormat(mFormat))
 		{
 		{
@@ -590,7 +506,7 @@ namespace CamelotFramework
 			/// We are going to bind directly, so set viewport to size and position of destination slice
 			/// We are going to bind directly, so set viewport to size and position of destination slice
 			glViewport(dstBox.left, dstBox.top, dstBox.getWidth(), dstBox.getHeight());
 			glViewport(dstBox.left, dstBox.top, dstBox.getWidth(), dstBox.getHeight());
 		}
 		}
-    
+
 		/// Process each destination slice
 		/// Process each destination slice
 		for(UINT32 slice=dstBox.front; slice<dstBox.back; ++slice)
 		for(UINT32 slice=dstBox.front; slice<dstBox.back; ++slice)
 		{
 		{
@@ -610,7 +526,7 @@ namespace CamelotFramework
 			w = w * (float)(srcBox.getDepth() + srcBox.front);
 			w = w * (float)(srcBox.getDepth() + srcBox.front);
 			/// Normalise to texture coordinate in 0.0 .. 1.0
 			/// Normalise to texture coordinate in 0.0 .. 1.0
 			w = (w+0.5f) / (float)src->mDepth;
 			w = (w+0.5f) / (float)src->mDepth;
-        
+
 			/// Finally we're ready to rumble	
 			/// Finally we're ready to rumble	
 			glBindTexture(src->mTarget, src->mTextureID);
 			glBindTexture(src->mTarget, src->mTextureID);
 			glEnable(src->mTarget);
 			glEnable(src->mTarget);
@@ -625,7 +541,7 @@ namespace CamelotFramework
 			glVertex2f(-1.0f, 1.0f);
 			glVertex2f(-1.0f, 1.0f);
 			glEnd();
 			glEnd();
 			glDisable(src->mTarget);
 			glDisable(src->mTarget);
-        
+
 			if(tempTex)
 			if(tempTex)
 			{
 			{
 				/// Copy temporary texture
 				/// Copy temporary texture
@@ -655,10 +571,10 @@ namespace CamelotFramework
 		/// Reset source texture to sane state
 		/// Reset source texture to sane state
 		glBindTexture(src->mTarget, src->mTextureID);
 		glBindTexture(src->mTarget, src->mTextureID);
 		glTexParameteri(src->mTarget, GL_TEXTURE_BASE_LEVEL, 0);
 		glTexParameteri(src->mTarget, GL_TEXTURE_BASE_LEVEL, 0);
-    
+
 		/// Detach texture from temporary framebuffer
 		/// Detach texture from temporary framebuffer
 		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
 		glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
-						GL_RENDERBUFFER_EXT, 0);
+			GL_RENDERBUFFER_EXT, 0);
 		/// Restore old framebuffer
 		/// Restore old framebuffer
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldfb);
 		glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, oldfb);
 		/// Restore matrix stacks and render state
 		/// Restore matrix stacks and render state
@@ -671,80 +587,7 @@ namespace CamelotFramework
 		glPopAttrib();
 		glPopAttrib();
 		glDeleteTextures(1, &tempTex);
 		glDeleteTextures(1, &tempTex);
 	}
 	}
-	//-----------------------------------------------------------------------------  
-	/// blitFromMemory doing hardware trilinear scaling
-	void GLTextureBuffer::blitFromMemory(const PixelData &src_orig, const Box &dstBox)
-	{
-		/// Fall back to normal GLHardwarePixelBuffer::blitFromMemory in case 
-		/// - FBO is not supported
-		/// - Either source or target is luminance due doesn't looks like supported by hardware
-		/// - the source dimensions match the destination ones, in which case no scaling is needed
-		if(!GLEW_EXT_framebuffer_object ||
-			(src_orig.getWidth() == dstBox.getWidth() &&
-			src_orig.getHeight() == dstBox.getHeight() &&
-			src_orig.getDepth() == dstBox.getDepth()))
-		{
-			GLPixelBuffer::blitFromMemory(src_orig, dstBox);
-			return;
-		}
-		if(!mBuffer.getExtents().contains(dstBox))
-			CM_EXCEPT(InvalidParametersException, "destination box out of range");
-		/// For scoped deletion of conversion buffer
-		PixelData src;
-    
-		/// First, convert the srcbox to a OpenGL compatible pixel format
-		if(GLPixelUtil::getGLOriginFormat(src_orig.getFormat()) == 0)
-		{
-			/// Convert to buffer internal format
-			src = PixelData(src_orig.getWidth(), src_orig.getHeight(), src_orig.getDepth(), mFormat);
-			src.allocateInternalBuffer();
-			PixelUtil::bulkPixelConversion(src_orig, src);
-		}
-		else
-		{
-			/// No conversion needed
-			src = src_orig;
-		}
-    
-		/// Create temporary texture to store source data
-		GLuint id;
-		GLenum target = (src.getDepth()!=1)?GL_TEXTURE_3D:GL_TEXTURE_2D;
-		GLsizei width = GLPixelUtil::optionalPO2(src.getWidth());
-		GLsizei height = GLPixelUtil::optionalPO2(src.getHeight());
-		GLsizei depth = GLPixelUtil::optionalPO2(src.getDepth());
-		GLenum format = GLPixelUtil::getClosestGLInternalFormat(src.getFormat());
-    
-		/// Generate texture name
-		glGenTextures(1, &id);
-    
-		/// Set texture type
-		glBindTexture(target, id);
-    
-		/// Set automatic mipmap generation; nice for minimisation
-		glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, 1000 );
-		glTexParameteri(target, GL_GENERATE_MIPMAP, GL_TRUE );
-    
-		/// Allocate texture memory
-		if(target == GL_TEXTURE_3D)
-			glTexImage3D(target, 0, format, width, height, depth, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-		else
-			glTexImage2D(target, 0, format, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-
-		/// GL texture buffer
-		GLTextureBuffer tex(StringUtil::BLANK, target, id, 0, 0, (GpuBufferUsage)(GBU_STATIC), false, false, 0);
-    
-		/// Upload data to 0,0,0 in temporary texture
-		Box tempTarget(0, 0, 0, src.getWidth(), src.getHeight(), src.getDepth());
-		tex.upload(src, tempTarget);
-    
-		/// Blit
-		blitFromTexture(&tex, tempTarget, dstBox);
-    
-		/// Delete temp texture
-		glDeleteTextures(1, &id);
-	}
-	//********* GLRenderBuffer
-	//----------------------------------------------------------------------------- 
+	
 	GLRenderBuffer::GLRenderBuffer(GLenum format, UINT32 width, UINT32 height, GLsizei numSamples):
 	GLRenderBuffer::GLRenderBuffer(GLenum format, UINT32 width, UINT32 height, GLsizei numSamples):
 		GLPixelBuffer(width, height, 1, GLPixelUtil::getClosestEngineFormat(format), GBU_DYNAMIC),
 		GLPixelBuffer(width, height, 1, GLPixelUtil::getClosestEngineFormat(format), GBU_DYNAMIC),
 		mRenderbufferID(0)
 		mRenderbufferID(0)
@@ -767,13 +610,13 @@ namespace CamelotFramework
 								width, height);
 								width, height);
 		}
 		}
 	}
 	}
-	//----------------------------------------------------------------------------- 
+
 	GLRenderBuffer::~GLRenderBuffer()
 	GLRenderBuffer::~GLRenderBuffer()
 	{
 	{
 		/// Generate renderbuffer
 		/// Generate renderbuffer
 		glDeleteRenderbuffersEXT(1, &mRenderbufferID);
 		glDeleteRenderbuffersEXT(1, &mRenderbufferID);
 	}
 	}
-	//-----------------------------------------------------------------------------  
+
 	void GLRenderBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
 	void GLRenderBuffer::bindToFramebuffer(GLenum attachment, UINT32 zoffset)
 	{
 	{
 		assert(zoffset < mDepth);
 		assert(zoffset < mDepth);

+ 3 - 4
CamelotGLRenderer/Source/CmGLRenderTexture.cpp

@@ -62,14 +62,13 @@ namespace CamelotFramework
 		surfaceDesc.zoffset = 0;
 		surfaceDesc.zoffset = 0;
 
 
 		GLTexture* glTexture = static_cast<GLTexture*>(mColorSurface->getTexture().get());
 		GLTexture* glTexture = static_cast<GLTexture*>(mColorSurface->getTexture().get());
-		surfaceDesc.buffer = std::static_pointer_cast<GLPixelBuffer>(
-			glTexture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip()));
+		surfaceDesc.buffer = glTexture->getBuffer(mColorSurface->getFirstArraySlice(), mColorSurface->getMostDetailedMip());
 
 
 		mFB->bindSurface(0, surfaceDesc);
 		mFB->bindSurface(0, surfaceDesc);
 
 
 		GLTexture* glDepthStencilTexture = static_cast<GLTexture*>(mDepthStencilSurface->getTexture().get());
 		GLTexture* glDepthStencilTexture = static_cast<GLTexture*>(mDepthStencilSurface->getTexture().get());
-		GLPixelBufferPtr depthStencilBuffer = std::static_pointer_cast<GLPixelBuffer>(
-			glDepthStencilTexture->getBuffer(mDepthStencilSurface->getFirstArraySlice(), mDepthStencilSurface->getMostDetailedMip()));
+		GLPixelBufferPtr depthStencilBuffer = 
+			glDepthStencilTexture->getBuffer(mDepthStencilSurface->getFirstArraySlice(), mDepthStencilSurface->getMostDetailedMip());
 
 
 		mFB->bindDepthStencil(depthStencilBuffer);
 		mFB->bindDepthStencil(depthStencilBuffer);
 
 

+ 18 - 7
CamelotGLRenderer/Source/CmGLTexture.cpp

@@ -229,7 +229,6 @@ namespace CamelotFramework {
 		return mTextureID;
 		return mTextureID;
 	}
 	}
 
 
-	//* Creation / loading methods ********************************************
 	PixelData GLTexture::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
 	PixelData GLTexture::lockImpl(GpuLockOptions options, UINT32 mipLevel, UINT32 face)
 	{
 	{
 		if(mLockedBuffer != nullptr)
 		if(mLockedBuffer != nullptr)
@@ -246,7 +245,7 @@ namespace CamelotFramework {
 
 
 		return lockedArea;
 		return lockedArea;
 	}
 	}
-	/****************************************************************************************/
+
 	void GLTexture::unlockImpl()
 	void GLTexture::unlockImpl()
 	{
 	{
 		if(mLockedBuffer == nullptr)
 		if(mLockedBuffer == nullptr)
@@ -255,7 +254,18 @@ namespace CamelotFramework {
 		mLockedBuffer->unlock();
 		mLockedBuffer->unlock();
 		mLockedBuffer = nullptr;
 		mLockedBuffer = nullptr;
 	}
 	}
-	/****************************************************************************************/ 
+
+
+	void GLTexture::readData(PixelData& dest, UINT32 mipLevel, UINT32 face)
+	{
+		getBuffer(face, mipLevel)->download(dest);
+	}
+
+	void GLTexture::writeData(const PixelData& src, UINT32 mipLevel, UINT32 face, bool discardWholeBuffer)
+	{
+		getBuffer(face, mipLevel)->upload(src, src.getExtents());
+	}
+
 	void GLTexture::copyImpl(TexturePtr& target)
 	void GLTexture::copyImpl(TexturePtr& target)
 	{
 	{
 		size_t numMips = std::min(getNumMipmaps(), target->getNumMipmaps());
 		size_t numMips = std::min(getNumMipmaps(), target->getNumMipmaps());
@@ -265,11 +275,13 @@ namespace CamelotFramework {
 		{
 		{
 			for(unsigned int mip=0; mip<=numMips; mip++)
 			for(unsigned int mip=0; mip<=numMips; mip++)
 			{
 			{
-				glTexture->getBuffer(face, mip)->blit(getBuffer(face, mip));
+				GLTextureBuffer *src = static_cast<GLTextureBuffer*>(getBuffer(face, mip).get());
+
+				glTexture->getBuffer(face, mip)->blitFromTexture(src);
 			}
 			}
 		}
 		}
 	}
 	}
-	//---------------------------------------------------------------------------------------------
+
 	void GLTexture::createSurfaceList()
 	void GLTexture::createSurfaceList()
 	{
 	{
 		mSurfaceList.clear();
 		mSurfaceList.clear();
@@ -295,8 +307,7 @@ namespace CamelotFramework {
 		}
 		}
 	}
 	}
 	
 	
-	//---------------------------------------------------------------------------------------------
-	PixelBufferPtr GLTexture::getBuffer(UINT32 face, UINT32 mipmap)
+	std::shared_ptr<GLPixelBuffer> GLTexture::getBuffer(UINT32 face, UINT32 mipmap)
 	{
 	{
 		THROW_IF_NOT_CORE_THREAD;
 		THROW_IF_NOT_CORE_THREAD;
 
 

+ 3 - 4
Opts.txt

@@ -40,10 +40,9 @@ from a transient mesh by drawing only parts of its buffer. But only do this afte
 ---------
 ---------
 
 
 Other possible improvements:
 Other possible improvements:
- - When setting buffers I should modify RenderSystem::setVertexBuffer so it can accept multiple buffers. So when mesh is bound all its streams can be bound in one call.
- - Fix how I handle sub-meshes: right now they are read on sim thread, but set on core thread which is wrong
+ - MeshData always completely overwrites destination mesh sub-meshes, plus it doesn't allow empty spaces or overlapping between the sub-meshes, they are always
+   sequential.
  - Textures do lock/unlock when writing data to them. This causes an unnecessary copy in DX11 (and possibly other APIs)
  - Textures do lock/unlock when writing data to them. This causes an unnecessary copy in DX11 (and possibly other APIs)
    - add writeData/readData methods that do those things as efficiently as possible
    - add writeData/readData methods that do those things as efficiently as possible
  - Textures always create dynamic buffers
  - Textures always create dynamic buffers
- - When writing to mesh vertex buffer that requires a color flip I need to create a temporary copy of the entire buffer. It would be better to handle this differently. 
- - Update Mesh DX11 buffers so they get initialized with data immediately and see if OpenGL has something similar (ADD THIS TO LOW PRIORITY LIST BUT DON'T IMPLEMENT ATM)
+ - When writing to mesh vertex buffer that requires a color flip I need to create a temporary copy of the entire buffer. It would be better to handle this differently. 

+ 1 - 7
TODO.txt

@@ -63,9 +63,6 @@ Other:
 
 
 -----------------------BACKLOG TODO---------------------------------------------------------------
 -----------------------BACKLOG TODO---------------------------------------------------------------
 
 
-----------------------------------------------------------------------------------------------
-High priority:
- - GetRenderOperation doesn't consider sub-meshes
 
 
 ----------------------------------------------------------------------------------------------
 ----------------------------------------------------------------------------------------------
 Medium priority:
 Medium priority:
@@ -81,13 +78,11 @@ Medium priority:
  - Make sure that I am able to blit contents from render textures on all render systems
  - Make sure that I am able to blit contents from render textures on all render systems
  - Command buffer:
  - Command buffer:
    - Make CommandQueue not use mutexes and use atomics instead??
    - Make CommandQueue not use mutexes and use atomics instead??
-   - Figure out how to handle accessing texture from a non-render thread?
    - When importing a resource, and registering it with Resources I don't think it properly gets added to the loaded resources array? For some reason shaders get created twice.
    - When importing a resource, and registering it with Resources I don't think it properly gets added to the loaded resources array? For some reason shaders get created twice.
-   - Doing setPixels_async in the texture doesn't make sure that the user doesn't actually modify the provided PixelData after that call.
-   - In general I need to rethink how to handle modifying resources with multithreading
  - Closing down a window (any window) will shut down main rendering loop
  - Closing down a window (any window) will shut down main rendering loop
  - GUIManager draw call merging:
  - GUIManager draw call merging:
     I merge two GUI elements if they don't overlap each other, however I don't consider if there is some world geometry between them. Another reason to move batching out of GUIManager.
     I merge two GUI elements if they don't overlap each other, however I don't consider if there is some world geometry between them. Another reason to move batching out of GUIManager.
+ - Update Mesh DX11 buffers so they get initialized with data immediately upon construction as an optimization and see if OpenGL has something similar
 
 
 ----------------------------------------------------------------------------------------------
 ----------------------------------------------------------------------------------------------
 Low priority TODO
 Low priority TODO
@@ -126,7 +121,6 @@ Low priority TODO
   - OpenGL render window no longer looks for a monitor index
   - OpenGL render window no longer looks for a monitor index
   - Material RTTI should also serialize shared buffers (they need to be made into a resource)
   - Material RTTI should also serialize shared buffers (they need to be made into a resource)
     - BE CAREFUL on how this will be implemented. Likely it will have much of the same interface as a material and/or GpuParams
     - BE CAREFUL on how this will be implemented. Likely it will have much of the same interface as a material and/or GpuParams
-  - Mesh::setMeshData is currently always synced
   - queueGpuCommand is handled weird. shared_ptr isn't used for setting (this) parameter, and could be optimized out by the compiler
   - queueGpuCommand is handled weird. shared_ptr isn't used for setting (this) parameter, and could be optimized out by the compiler
     - test if everything is okay in release mode
     - test if everything is okay in release mode
   - Resources::unload will deadlock if the resource isn't being loaded!
   - Resources::unload will deadlock if the resource isn't being loaded!