Browse Source

Updated how textures get serialized (needs serious testing)

Marko Pintera 13 years ago
parent
commit
7aefc7c854

+ 0 - 1
CamelotRenderer/Include/CmPrerequisites.h

@@ -145,7 +145,6 @@ namespace CamelotEngine
 	typedef std::shared_ptr<WorkQueue> WorkQueuePtr;
 	typedef std::shared_ptr<PassParameters> PassParametersPtr;
 	typedef std::shared_ptr<RenderSystemContext> RenderSystemContextPtr;
-
 	typedef std::shared_ptr<Component> ComponentPtr;
 	typedef std::shared_ptr<GameObject> GameObjectPtr;
 }

+ 17 - 0
CamelotRenderer/Include/CmTexture.h

@@ -174,6 +174,21 @@ namespace CamelotEngine {
 		 */
 		TextureDataPtr getTextureData(UINT32 face);
 
+		/**
+		 * @brief	Sets raw texture pixels for the specified mip level and texture face. Pixel format
+		 * 			must match the format of the texture.
+		 */
+		void setRawPixels(const PixelData& data, UINT32 face = 0, UINT32 mip = 0);
+		void setRawPixels_internal(const PixelData& data, UINT32 face = 0, UINT32 mip = 0);
+
+		/**
+		 * @brief	Gets raw pixels from the texture. This is a slow operation
+		 * 			as it will read data from the GPU. If the texture is compressed
+		 * 			the returned data will be contain compressed pixels as well.
+		 */
+		PixelDataPtr getRawPixels(UINT32 face = 0, UINT32 mip = 0);
+		PixelDataPtr getRawPixels_internal(UINT32 face = 0, UINT32 mip = 0);
+
 		/**
 		 * @brief	Sets the texture data that will be used for initializing the texture.
 		 * 			You must call loadFromTextureData after setting the data for all faces. 
@@ -218,6 +233,8 @@ namespace CamelotEngine {
 		void initialize(TextureType textureType, size_t width, size_t height, size_t depth, size_t numMipmaps, 
 			PixelFormat format, int usage, bool hwGamma, UINT32 fsaa, const String& fsaaHint);
 		
+		void initialize_internal();
+
 		/// @copydoc Resource::calculateSize
 		size_t calculateSize(void) const;
 

+ 46 - 10
CamelotRenderer/Include/CmTextureRTTI.h

@@ -5,6 +5,7 @@
 #include "CmTexture.h"
 #include "CmTextureData.h"
 #include "CmManagedDataBlock.h"
+#include "CmMath.h"
 
 // DEBUG ONLY
 #include "CmTextureManager.h"
@@ -27,24 +28,29 @@ namespace CamelotEngine
 		CM_SETGET_MEMBER(mFormat, PixelFormat, Texture)
 		CM_SETGET_MEMBER(mUsage, INT32, Texture)
 
-		std::shared_ptr<TextureData> getTextureData(Texture* obj, UINT32 face)
+		PixelDataPtr getPixelData(Texture* obj, UINT32 idx)
 		{
-			return obj->getTextureData(face);
+			size_t face = (size_t)Math::Floor(idx / (float)(obj->getNumMipmaps() + 1));
+			size_t mipmap = idx % (obj->getNumMipmaps() + 1);
+
+			return obj->getRawPixels(face, mipmap);
 		}
 
-		void setTextureData(Texture* obj, UINT32 face, TextureDataPtr data)
+		void setPixelData(Texture* obj, UINT32 idx, PixelDataPtr data)
 		{
-			obj->setTextureData(face, data);
+			mPixelData[idx] = data;
 		}
 
-		UINT32 getTextureDataArraySize(Texture* obj)
+		UINT32 getPixelDataArraySize(Texture* obj)
 		{
-			return obj->getNumFaces();
+			return obj->getNumFaces() * obj->getNumMipmaps();
 		}
 
-		void setTextureDataArraySize(Texture* obj, UINT32 size)
+		void setPixelDataArraySize(Texture* obj, UINT32 size)
 		{
-			// Not allowed to change size this way
+			vector<PixelDataPtr>::type* pixelData = boost::any_cast<vector<PixelDataPtr>::type*>(obj->mRTTIData);
+
+			pixelData->resize(size);
 		}
 
 	public:
@@ -63,8 +69,35 @@ namespace CamelotEngine
 			CM_ADD_PLAINFIELD(mFormat, 10, TextureRTTI)
 			CM_ADD_PLAINFIELD(mUsage, 11, TextureRTTI)
 
-			addReflectablePtrArrayField("mTextureData", 18, &TextureRTTI::getTextureData, &TextureRTTI::getTextureDataArraySize, 
-				&TextureRTTI::setTextureData, &TextureRTTI::setTextureDataArraySize);
+			addReflectablePtrArrayField("mPixelData", 12, &TextureRTTI::getPixelData, &TextureRTTI::getPixelDataArraySize, 
+				&TextureRTTI::setPixelData, &TextureRTTI::setPixelDataArraySize);
+		}
+
+		virtual void onDeserializationStarted(IReflectable* obj)
+		{
+			Texture* texture = static_cast<Texture*>(obj);
+
+			texture->mRTTIData = new vector<PixelDataPtr>::type();
+		}
+
+		virtual void onDeserializationEnded(IReflectable* obj)
+		{
+			Texture* texture = static_cast<Texture*>(obj);
+
+			if(texture->mRTTIData.empty())
+				return;
+
+			vector<PixelDataPtr>::type* pixelData = boost::any_cast<vector<PixelDataPtr>::type*>(texture->mRTTIData);
+			for(size_t i = 0; i < pixelData->size(); i++)
+			{
+				size_t face = (size_t)Math::Floor(i / (float)(texture->getNumMipmaps() + 1));
+				size_t mipmap = i % (texture->getNumMipmaps() + 1);
+
+				texture->setRawPixels(*pixelData->at(i), face, mipmap);
+			}
+
+			delete pixelData;
+			texture->mRTTIData = nullptr;			
 		}
 
 		virtual const String& getRTTIName()
@@ -85,5 +118,8 @@ namespace CamelotEngine
 
 			//CM_EXCEPT(InternalErrorException, "Cannot instantiate abstract class!");
 		}
+
+	private:
+		vector<PixelDataPtr>::type mPixelData;
 	};
 }

+ 72 - 1
CamelotRenderer/Source/CmTexture.cpp

@@ -36,7 +36,7 @@ THE SOFTWARE.
 namespace CamelotEngine {
 	//--------------------------------------------------------------------------
     Texture::Texture()
-        : // init defaults; can be overridden before load()
+        : 
             mHeight(512),
             mWidth(512),
             mDepth(1),
@@ -65,6 +65,11 @@ namespace CamelotEngine {
 		mFSAA = fsaa;
 		mFSAAHint = fsaaHint;
 	}
+	//-------------------------------------------------------------------------
+	void Texture::initialize_internal()
+	{
+		createInternalResources();
+	}
     //--------------------------------------------------------------------------
     bool Texture::hasAlpha(void) const
     {
@@ -149,6 +154,72 @@ namespace CamelotEngine {
 
 		mTextureData[face] = textureData;
 	}
+
+	void Texture::setRawPixels(const PixelData& data, UINT32 face, UINT32 mip)
+	{
+		// TODO - Queue command
+	}
+
+	void Texture::setRawPixels_internal(const PixelData& data, UINT32 face, UINT32 mip)
+	{
+		if(mip < 0 || mip > mNumMipmaps)
+			CM_EXCEPT(InvalidParametersException, "Invalid mip level: " + toString(mip) + ". Min is 0, max is " + toString(mNumMipmaps));
+
+		if(face < 0 || mip > getNumFaces())
+			CM_EXCEPT(InvalidParametersException, "Invalid face index: " + toString(face) + ". Min is 0, max is " + toString(getNumFaces()));
+
+		if(mFormat != data.format)
+			CM_EXCEPT(InvalidParametersException, "Provided PixelData has invalid format. Needed: " + toString(mFormat) + ". Got: " + toString(data.format));
+
+		if(mWidth != data.getWidth() || mHeight != data.getHeight() || mDepth != data.getDepth())
+		{
+			CM_EXCEPT(InvalidParametersException, "Provided PixelData size doesn't match the texture size." \
+				" Width: " + toString(mWidth) + "/" + toString(data.getWidth()) + 
+				" Height: " + toString(mHeight) + "/" + toString(data.getHeight()) + 
+				" Depth: " + toString(mDepth) + "/" + toString(data.getDepth()));
+		}
+
+		getBuffer(face, mip)->blitFromMemory(data);
+	}
+
+	PixelDataPtr Texture::getRawPixels(UINT32 face, UINT32 mip)
+	{
+		// TODO - Queue command
+		return nullptr;
+	}
+
+	PixelDataPtr Texture::getRawPixels_internal(UINT32 face, UINT32 mip)
+	{
+		if(mip < 0 || mip > mNumMipmaps)
+			CM_EXCEPT(InvalidParametersException, "Invalid mip level: " + toString(mip) + ". Min is 0, max is " + toString(mNumMipmaps));
+
+		if(face < 0 || mip > getNumFaces())
+			CM_EXCEPT(InvalidParametersException, "Invalid face index: " + toString(face) + ". Min is 0, max is " + toString(getNumFaces()));
+
+		UINT32 numMips = getNumMipmaps();
+
+		UINT32 totalSize = 0;
+		UINT32 width = getWidth();
+		UINT32 height = getHeight();
+		UINT32 depth = getDepth();
+
+		for(UINT32 j = 0; j <= mip; j++)
+		{
+			totalSize = PixelUtil::getMemorySize(width, height, depth, mFormat);
+
+			if(width != 1) width /= 2;
+			if(height != 1) height /= 2;
+			if(depth != 1) depth /= 2;
+		}
+
+		UINT8* buffer = new UINT8[totalSize]; 
+		PixelDataPtr src(new PixelData(width, height, depth, getFormat(), buffer, true));
+
+		getBuffer(face, mip)->blitToMemory(*src);
+
+		return src;
+	}
+
 	//-----------------------------------------------------------------------------
 	void Texture::initializeFromTextureData()
 	{

+ 10 - 0
CamelotRenderer/TODO.txt

@@ -20,6 +20,16 @@ Command buffer TODO:
  - Make sure the user knows resources are shared between contexts. All resource updates are executed before rendering a frame, so whichever context updated the resource last,
    was the version that will be used.
 
+ Texture updates:
+   - Seems that deleting resources (textures for example) gets freeInternalResources called from the destruction. Which will be trouble if the resource is destroyed on an invalid thread.
+   - Make TextureData private to FreeImgImporter (as its not used anywhere else)
+   - Make this per texture and apply when texture is applied:
+	 filterMode
+	 anisoLevel
+	 wrapMode
+	 mipMapBias
+   - After texture initialize() schedule createInternalResources command
+
  Immediate:
   - Resource updates shouldn't happen once per frame. Resources should be submitted to render thread immediately.
   - Port resource creation to use RenderContext (texture/mesh/shader/etc initialization and updates)

+ 3 - 0
CamelotUtility/CamelotUtility.vcxproj

@@ -84,6 +84,7 @@
   <ItemGroup>
     <ClCompile Include="..\CamelotRenderer\Source\CmManagedDataBlock.cpp" />
     <ClCompile Include="Source\CmInt2.cpp" />
+    <ClCompile Include="Source\CmPixelData.cpp" />
     <ClCompile Include="Source\CmUUID.cpp" />
     <ClCompile Include="Source\CmWorkQueue.cpp" />
     <ClCompile Include="Source\Win32\CmTimer.cpp" />
@@ -106,6 +107,8 @@
     <ClInclude Include="Include\CmMathAsm.h" />
     <ClInclude Include="Include\CmModule.h" />
     <ClInclude Include="Include\CmPath.h" />
+    <ClInclude Include="Include\CmPixelData.h" />
+    <ClInclude Include="Include\CmPixelDataRTTI.h" />
     <ClInclude Include="Include\CmPixelUtil.h" />
     <ClInclude Include="Include\CmPoint.h" />
     <ClInclude Include="Include\CmRect.h" />

+ 9 - 0
CamelotUtility/CamelotUtility.vcxproj.filters

@@ -204,6 +204,12 @@
     <ClInclude Include="Include\CmLockedPtr.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\CmPixelData.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
+    <ClInclude Include="Include\CmPixelDataRTTI.h">
+      <Filter>Header Files\RTTI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Include\CmAxisAlignedBox.cpp">
@@ -299,5 +305,8 @@
     <ClCompile Include="Source\CmInt2.cpp">
       <Filter>Source Files\Math</Filter>
     </ClCompile>
+    <ClCompile Include="Source\CmPixelData.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 2 - 0
CamelotUtility/Include/CmFwdDeclUtil.h

@@ -28,6 +28,7 @@ namespace CamelotEngine {
 	class MeshData;
 	class FileSystem;
 	class Timer;
+	class PixelData;
 	// Reflection
 	class IReflectable;
 	class RTTITypeBase;
@@ -40,4 +41,5 @@ namespace CamelotEngine {
 	typedef std::shared_ptr<FileDataStream> FileDataStreamPtr;
 	typedef std::shared_ptr<TextureData> TextureDataPtr;
 	typedef std::shared_ptr<MeshData> MeshDataPtr;
+	typedef std::shared_ptr<PixelData> PixelDataPtr;
 }

+ 287 - 0
CamelotUtility/Include/CmPixelData.h

@@ -0,0 +1,287 @@
+#pragma once
+
+#include "CmPrerequisitesUtil.h"
+#include "CmBox.h"
+#include "CmIReflectable.h"
+
+namespace CamelotEngine
+{
+	/** The pixel format used for images, textures, and render surfaces */
+    enum PixelFormat
+    {
+        /// Unknown pixel format.
+        PF_UNKNOWN = 0,
+        /// 8-bit pixel format, all bits luminace.
+        PF_L8 = 1,
+		PF_BYTE_L = PF_L8,
+        /// 16-bit pixel format, all bits luminace.
+        PF_L16 = 2,
+		PF_SHORT_L = PF_L16,
+        /// 8-bit pixel format, all bits alpha.
+        PF_A8 = 3,
+		PF_BYTE_A = PF_A8,
+        /// 8-bit pixel format, 4 bits alpha, 4 bits luminance.
+        PF_A4L4 = 4,
+		/// 2 byte pixel format, 1 byte luminance, 1 byte alpha
+		PF_BYTE_LA = 5,
+        /// 16-bit pixel format, 5 bits red, 6 bits green, 5 bits blue.
+        PF_R5G6B5 = 6,
+		/// 16-bit pixel format, 5 bits red, 6 bits green, 5 bits blue.
+        PF_B5G6R5 = 7,
+        /// 8-bit pixel format, 2 bits blue, 3 bits green, 3 bits red.
+        PF_R3G3B2 = 31,
+        /// 16-bit pixel format, 4 bits for alpha, red, green and blue.
+        PF_A4R4G4B4 = 8,
+        /// 16-bit pixel format, 5 bits for blue, green, red and 1 for alpha.
+        PF_A1R5G5B5 = 9,
+        /// 24-bit pixel format, 8 bits for red, green and blue.
+        PF_R8G8B8 = 10,
+        /// 24-bit pixel format, 8 bits for blue, green and red.
+        PF_B8G8R8 = 11,
+        /// 32-bit pixel format, 8 bits for alpha, red, green and blue.
+        PF_A8R8G8B8 = 12,
+        /// 32-bit pixel format, 8 bits for blue, green, red and alpha.
+        PF_A8B8G8R8 = 13,
+        /// 32-bit pixel format, 8 bits for blue, green, red and alpha.
+        PF_B8G8R8A8 = 14,
+		/// 32-bit pixel format, 8 bits for red, green, blue and alpha.
+		PF_R8G8B8A8 = 28,
+        /// 32-bit pixel format, 8 bits for red, 8 bits for green, 8 bits for blue
+        /// like PF_A8R8G8B8, but alpha will get discarded
+        PF_X8R8G8B8 = 26,
+        /// 32-bit pixel format, 8 bits for blue, 8 bits for green, 8 bits for red
+        /// like PF_A8B8G8R8, but alpha will get discarded
+        PF_X8B8G8R8 = 27,
+#if CM_ENDIAN == CM_ENDIAN_BIG
+		/// 3 byte pixel format, 1 byte for red, 1 byte for green, 1 byte for blue
+		PF_BYTE_RGB = PF_R8G8B8,
+		/// 3 byte pixel format, 1 byte for blue, 1 byte for green, 1 byte for red
+		PF_BYTE_BGR = PF_B8G8R8,
+		/// 4 byte pixel format, 1 byte for blue, 1 byte for green, 1 byte for red and one byte for alpha
+		PF_BYTE_BGRA = PF_B8G8R8A8,
+		/// 4 byte pixel format, 1 byte for red, 1 byte for green, 1 byte for blue, and one byte for alpha
+		PF_BYTE_RGBA = PF_R8G8B8A8,
+#else
+		/// 3 byte pixel format, 1 byte for red, 1 byte for green, 1 byte for blue
+		PF_BYTE_RGB = PF_B8G8R8,
+		/// 3 byte pixel format, 1 byte for blue, 1 byte for green, 1 byte for red
+		PF_BYTE_BGR = PF_R8G8B8,
+		/// 4 byte pixel format, 1 byte for blue, 1 byte for green, 1 byte for red and one byte for alpha
+		PF_BYTE_BGRA = PF_A8R8G8B8,
+		/// 4 byte pixel format, 1 byte for red, 1 byte for green, 1 byte for blue, and one byte for alpha
+		PF_BYTE_RGBA = PF_A8B8G8R8,
+#endif        
+        /// 32-bit pixel format, 2 bits for alpha, 10 bits for red, green and blue.
+        PF_A2R10G10B10 = 15,
+        /// 32-bit pixel format, 10 bits for blue, green and red, 2 bits for alpha.
+        PF_A2B10G10R10 = 16,
+        /// DDS (DirectDraw Surface) DXT1 format
+        PF_DXT1 = 17,
+        /// DDS (DirectDraw Surface) DXT2 format
+        PF_DXT2 = 18,
+        /// DDS (DirectDraw Surface) DXT3 format
+        PF_DXT3 = 19,
+        /// DDS (DirectDraw Surface) DXT4 format
+        PF_DXT4 = 20,
+        /// DDS (DirectDraw Surface) DXT5 format
+        PF_DXT5 = 21,
+		// 16-bit pixel format, 16 bits (float) for red
+        PF_FLOAT16_R = 32,
+        // 48-bit pixel format, 16 bits (float) for red, 16 bits (float) for green, 16 bits (float) for blue
+        PF_FLOAT16_RGB = 22,
+        // 64-bit pixel format, 16 bits (float) for red, 16 bits (float) for green, 16 bits (float) for blue, 16 bits (float) for alpha
+        PF_FLOAT16_RGBA = 23,
+		// 32-bit pixel format, 32 bits (float) for red
+        PF_FLOAT32_R = 33,
+        // 96-bit pixel format, 32 bits (float) for red, 32 bits (float) for green, 32 bits (float) for blue
+        PF_FLOAT32_RGB = 24,
+        // 128-bit pixel format, 32 bits (float) for red, 32 bits (float) for green, 32 bits (float) for blue, 32 bits (float) for alpha
+        PF_FLOAT32_RGBA = 25,
+		// 32-bit, 2-channel s10e5 floating point pixel format, 16-bit green, 16-bit red
+		PF_FLOAT16_GR = 35,
+		// 64-bit, 2-channel floating point pixel format, 32-bit green, 32-bit red
+		PF_FLOAT32_GR = 36,
+		// Depth texture format
+		PF_DEPTH = 29,
+		// 64-bit pixel format, 16 bits for red, green, blue and alpha
+		PF_SHORT_RGBA = 30,
+		// 32-bit pixel format, 16-bit green, 16-bit red
+		PF_SHORT_GR = 34,
+		// 48-bit pixel format, 16 bits for red, green and blue
+		PF_SHORT_RGB = 37,
+        /// PVRTC (PowerVR) RGB 2 bpp
+        PF_PVRTC_RGB2 = 38,
+        /// PVRTC (PowerVR) RGBA 2 bpp
+        PF_PVRTC_RGBA2 = 39,
+        /// PVRTC (PowerVR) RGB 4 bpp
+        PF_PVRTC_RGB4 = 40,
+        /// PVRTC (PowerVR) RGBA 4 bpp
+        PF_PVRTC_RGBA4 = 41,
+		// Number of pixel formats currently defined
+        PF_COUNT = 42
+    };
+	typedef vector<PixelFormat>::type PixelFormatList;
+
+    /**
+     * Flags defining some on/off properties of pixel formats
+     */
+    enum PixelFormatFlags {
+        // This format has an alpha channel
+        PFF_HASALPHA        = 0x00000001,      
+        // This format is compressed. This invalidates the values in elemBytes,
+        // elemBits and the bit counts as these might not be fixed in a compressed format.
+        PFF_COMPRESSED    = 0x00000002,
+        // This is a floating point format
+        PFF_FLOAT           = 0x00000004,         
+        // This is a depth format (for depth textures)
+        PFF_DEPTH           = 0x00000008,
+        // Format is in native endian. Generally true for the 16, 24 and 32 bits
+        // formats which can be represented as machine integers.
+        PFF_NATIVEENDIAN    = 0x00000010,
+        // This is an intensity format instead of a RGB one. The luminance
+        // replaces R,G and B. (but not A)
+        PFF_LUMINANCE       = 0x00000020
+    };
+    
+    /** Pixel component format */
+    enum PixelComponentType
+    {
+        PCT_BYTE = 0,    /// Byte per component (8 bit fixed 0.0..1.0)
+        PCT_SHORT = 1,   /// Short per component (16 bit fixed 0.0..1.0))
+        PCT_FLOAT16 = 2, /// 16 bit float per component
+        PCT_FLOAT32 = 3, /// 32 bit float per component
+        PCT_COUNT = 4    /// Number of pixel types
+    };
+    
+	/** A primitive describing a volume (3D), image (2D) or line (1D) of pixels in memory.
+     	In case of a rectangle, depth must be 1. 
+     	Pixels are stored as a succession of "depth" slices, each containing "height" rows of 
+     	"width" pixels.
+    */
+    class CM_UTILITY_EXPORT PixelData: public Box, public IReflectable
+	{
+    public:
+    	/// Parameter constructor for setting the members manually
+    	PixelData() {}
+		~PixelData() 
+		{
+			if(ownsData && data != nullptr)
+				delete[] data;
+
+			data = nullptr;
+		}
+		/** Constructor providing extents in the form of a Box object. This constructor
+    		assumes the pixel data is laid out consecutively in memory. (this
+    		means row after row, slice after slice, with no space in between)
+    		@param extents	    Extents of the region defined by data
+    		@param pixelFormat	Format of this buffer
+    		@param pixelData	Pointer to the actual data
+			@param ownsPixelData  If true then PixelData owns the data buffer and will release it when destroyed.
+    	*/
+		PixelData(const Box &extents, PixelFormat pixelFormat, void *pixelData = 0, bool ownsPixelData = false):
+			Box(extents), data(pixelData), format(pixelFormat), ownsData(ownsPixelData)
+		{
+			setConsecutive();
+		}
+    	/** Constructor providing width, height and depth. This constructor
+    		assumes the pixel data is laid out consecutively in memory. (this
+    		means row after row, slice after slice, with no space in between)
+    		@param width	    Width of the region
+    		@param height	    Height of the region
+    		@param depth	    Depth of the region
+    		@param pixelFormat	Format of this buffer
+    		@param pixelData    Pointer to the actual data
+			@param ownsPixelData  If true then PixelData owns the data buffer and will release it when destroyed.
+    	*/
+    	PixelData(size_t width, size_t height, size_t depth, PixelFormat pixelFormat, 
+				void *pixelData = 0, bool ownsPixelData = false):
+    		Box(0, 0, 0, width, height, depth),
+    		data(pixelData), format(pixelFormat), ownsData(ownsPixelData)
+    	{
+    		setConsecutive();
+    	}
+    	
+        /// The data pointer 
+        void *data;
+        /// The pixel format 
+        PixelFormat format;
+        /** Number of elements between the leftmost pixel of one row and the left
+         	pixel of the next. This value must always be equal to getWidth() (consecutive) 
+			for compressed formats.
+        */
+        size_t rowPitch;
+        /** Number of elements between the top left pixel of one (depth) slice and 
+         	the top left pixel of the next. This can be a negative value. Must be a multiple of
+         	rowPitch. This value must always be equal to getWidth()*getHeight() (consecutive) 
+			for compressed formats.
+        */
+        size_t slicePitch;
+
+		/**
+		 * @brief	If true then PixelData owns the data buffer and will release it when destroyed.
+		 */
+		bool ownsData;
+        
+        /** Set the rowPitch and slicePitch so that the buffer is laid out consecutive 
+         	in memory.
+        */        
+        void setConsecutive()
+        {
+            rowPitch = getWidth();
+            slicePitch = getWidth()*getHeight();
+        }
+        /**	Get the number of elements between one past the rightmost pixel of 
+         	one row and the leftmost pixel of the next row. (IE this is zero if rows
+         	are consecutive).
+        */
+        size_t getRowSkip() const { return rowPitch - getWidth(); }
+        /** Get the number of elements between one past the right bottom pixel of
+         	one slice and the left top pixel of the next slice. (IE this is zero if slices
+         	are consecutive).
+        */
+        size_t getSliceSkip() const { return slicePitch - (getHeight() * rowPitch); }
+
+        /** Return whether this buffer is laid out consecutive in memory (ie the pitches
+         	are equal to the dimensions)
+        */        
+        bool isConsecutive() const 
+		{ 
+			return rowPitch == getWidth() && slicePitch == getWidth()*getHeight(); 
+		}
+        /** Return the size (in bytes) this image would take if it was
+        	laid out consecutive in memory
+      	*/
+      	size_t getConsecutiveSize() const;
+      	/** Return a subvolume of this PixelBox.
+      		@param def	Defines the bounds of the subregion to return
+      		@returns	A pixel box describing the region and the data in it
+      		@remarks	This function does not copy any data, it just returns
+      			a PixelBox object with a data pointer pointing somewhere inside 
+      			the data of object.
+      		@throws	Exception(ERR_INVALIDPARAMS) if def is not fully contained
+      	*/
+      	PixelData getSubVolume(const Box &def) const;
+        
+        /**
+         * Get colour value from a certain location in the PixelBox. The z coordinate
+         * is only valid for cubemaps and volume textures. This uses the first (largest)
+         * mipmap.
+         */
+        Color getColourAt(size_t x, size_t y, size_t z);
+
+        /**
+         * Set colour value at a certain location in the PixelBox. The z coordinate
+         * is only valid for cubemaps and volume textures. This uses the first (largest)
+         * mipmap.
+         */
+        void setColourAt(Color const &cv, size_t x, size_t y, size_t z);
+
+		/************************************************************************/
+		/* 								SERIALIZATION                      		*/
+		/************************************************************************/
+	public:
+		friend class PixelDataRTTI;
+		static RTTITypeBase* getRTTIStatic();
+		virtual RTTITypeBase* getRTTI() const;
+    };
+}

+ 81 - 0
CamelotUtility/Include/CmPixelDataRTTI.h

@@ -0,0 +1,81 @@
+#pragma once
+
+#include "CmPrerequisitesUtil.h"
+#include "CmPixelData.h"
+#include "CmRTTIType.h"
+#include "CmManagedDataBlock.h"
+
+namespace CamelotEngine
+{
+	class CM_UTILITY_EXPORT PixelDataRTTI : public RTTIType<PixelData, IReflectable, PixelDataRTTI>
+	{
+		size_t& getLeft(PixelData* obj) { return obj->left; }
+		void setLeft(PixelData* obj, size_t& val) { obj->left = val; }
+
+		size_t& getTop(PixelData* obj) { return obj->top; }
+		void setTop(PixelData* obj, size_t& val) { obj->top = val; }
+
+		size_t& getRight(PixelData* obj) { return obj->right; }
+		void setRight(PixelData* obj, size_t& val) { obj->right = val; }
+
+		size_t& getBottom(PixelData* obj) { return obj->bottom; }
+		void setBottom(PixelData* obj, size_t& val) { obj->bottom = val; }
+
+		size_t& getFront(PixelData* obj) { return obj->front; }
+		void setFront(PixelData* obj, size_t& val) { obj->front = val; }
+
+		size_t& getBack(PixelData* obj) { return obj->back; }
+		void setBack(PixelData* obj, size_t& val) { obj->back = val; }
+
+		size_t& getRowPitch(PixelData* obj) { return obj->rowPitch; }
+		void setRowPitch(PixelData* obj, size_t& val) { obj->rowPitch = val; }
+
+		size_t& getSlicePitch(PixelData* obj) { return obj->slicePitch; }
+		void setSlicePitch(PixelData* obj, size_t& val) { obj->slicePitch = val; }
+
+		ManagedDataBlock getData(PixelData* obj) 
+		{ 
+			ManagedDataBlock dataBlock((UINT8*)obj->data, obj->getConsecutiveSize(), false);
+			return dataBlock; 
+		}
+
+		void setData(PixelData* obj, ManagedDataBlock val) 
+		{ 
+			obj->data = val.getData();
+		}
+
+	public:
+		PixelDataRTTI()
+		{
+			addPlainField("left", 0, &PixelDataRTTI::getLeft, &PixelDataRTTI::setLeft);
+			addPlainField("top", 1, &PixelDataRTTI::getTop, &PixelDataRTTI::setTop);
+			addPlainField("right", 2, &PixelDataRTTI::getRight, &PixelDataRTTI::setRight);
+			addPlainField("bottom", 3, &PixelDataRTTI::getBottom, &PixelDataRTTI::setBottom);
+			addPlainField("front", 4, &PixelDataRTTI::getFront, &PixelDataRTTI::setFront);
+			addPlainField("back", 5, &PixelDataRTTI::getBack, &PixelDataRTTI::setBack);
+			addPlainField("rowPitch", 6, &PixelDataRTTI::getRowPitch, &PixelDataRTTI::setRowPitch);
+			addPlainField("slicePitch", 7, &PixelDataRTTI::getSlicePitch, &PixelDataRTTI::setSlicePitch);
+
+			addDataBlockField("data", 8, &PixelDataRTTI::getData, &PixelDataRTTI::setData);
+		}
+
+		virtual const String& getRTTIName()
+		{
+			static String name = "PixelData";
+			return name;
+		}
+
+		virtual UINT32 getRTTIId()
+		{
+			return TID_PixelData;
+		}
+
+		virtual std::shared_ptr<IReflectable> newRTTIObject()
+		{
+			PixelDataPtr newPixelData(new PixelData());
+			newPixelData->ownsData = true;
+
+			return newPixelData;
+		}
+	};
+}

+ 1 - 264
CamelotUtility/Include/CmPixelUtil.h

@@ -29,272 +29,9 @@ THE SOFTWARE.
 #define _PixelFormat_H__
 
 #include "CmPrerequisitesUtil.h"
-#include "CmBox.h"
+#include "CmPixelData.h"
 
 namespace CamelotEngine {
-	/** \addtogroup Core
-	*  @{
-	*/
-	/** \addtogroup Image
-	*  @{
-	*/
-	/** The pixel format used for images, textures, and render surfaces */
-    enum PixelFormat
-    {
-        /// Unknown pixel format.
-        PF_UNKNOWN = 0,
-        /// 8-bit pixel format, all bits luminace.
-        PF_L8 = 1,
-		PF_BYTE_L = PF_L8,
-        /// 16-bit pixel format, all bits luminace.
-        PF_L16 = 2,
-		PF_SHORT_L = PF_L16,
-        /// 8-bit pixel format, all bits alpha.
-        PF_A8 = 3,
-		PF_BYTE_A = PF_A8,
-        /// 8-bit pixel format, 4 bits alpha, 4 bits luminance.
-        PF_A4L4 = 4,
-		/// 2 byte pixel format, 1 byte luminance, 1 byte alpha
-		PF_BYTE_LA = 5,
-        /// 16-bit pixel format, 5 bits red, 6 bits green, 5 bits blue.
-        PF_R5G6B5 = 6,
-		/// 16-bit pixel format, 5 bits red, 6 bits green, 5 bits blue.
-        PF_B5G6R5 = 7,
-        /// 8-bit pixel format, 2 bits blue, 3 bits green, 3 bits red.
-        PF_R3G3B2 = 31,
-        /// 16-bit pixel format, 4 bits for alpha, red, green and blue.
-        PF_A4R4G4B4 = 8,
-        /// 16-bit pixel format, 5 bits for blue, green, red and 1 for alpha.
-        PF_A1R5G5B5 = 9,
-        /// 24-bit pixel format, 8 bits for red, green and blue.
-        PF_R8G8B8 = 10,
-        /// 24-bit pixel format, 8 bits for blue, green and red.
-        PF_B8G8R8 = 11,
-        /// 32-bit pixel format, 8 bits for alpha, red, green and blue.
-        PF_A8R8G8B8 = 12,
-        /// 32-bit pixel format, 8 bits for blue, green, red and alpha.
-        PF_A8B8G8R8 = 13,
-        /// 32-bit pixel format, 8 bits for blue, green, red and alpha.
-        PF_B8G8R8A8 = 14,
-		/// 32-bit pixel format, 8 bits for red, green, blue and alpha.
-		PF_R8G8B8A8 = 28,
-        /// 32-bit pixel format, 8 bits for red, 8 bits for green, 8 bits for blue
-        /// like PF_A8R8G8B8, but alpha will get discarded
-        PF_X8R8G8B8 = 26,
-        /// 32-bit pixel format, 8 bits for blue, 8 bits for green, 8 bits for red
-        /// like PF_A8B8G8R8, but alpha will get discarded
-        PF_X8B8G8R8 = 27,
-#if CM_ENDIAN == CM_ENDIAN_BIG
-		/// 3 byte pixel format, 1 byte for red, 1 byte for green, 1 byte for blue
-		PF_BYTE_RGB = PF_R8G8B8,
-		/// 3 byte pixel format, 1 byte for blue, 1 byte for green, 1 byte for red
-		PF_BYTE_BGR = PF_B8G8R8,
-		/// 4 byte pixel format, 1 byte for blue, 1 byte for green, 1 byte for red and one byte for alpha
-		PF_BYTE_BGRA = PF_B8G8R8A8,
-		/// 4 byte pixel format, 1 byte for red, 1 byte for green, 1 byte for blue, and one byte for alpha
-		PF_BYTE_RGBA = PF_R8G8B8A8,
-#else
-		/// 3 byte pixel format, 1 byte for red, 1 byte for green, 1 byte for blue
-		PF_BYTE_RGB = PF_B8G8R8,
-		/// 3 byte pixel format, 1 byte for blue, 1 byte for green, 1 byte for red
-		PF_BYTE_BGR = PF_R8G8B8,
-		/// 4 byte pixel format, 1 byte for blue, 1 byte for green, 1 byte for red and one byte for alpha
-		PF_BYTE_BGRA = PF_A8R8G8B8,
-		/// 4 byte pixel format, 1 byte for red, 1 byte for green, 1 byte for blue, and one byte for alpha
-		PF_BYTE_RGBA = PF_A8B8G8R8,
-#endif        
-        /// 32-bit pixel format, 2 bits for alpha, 10 bits for red, green and blue.
-        PF_A2R10G10B10 = 15,
-        /// 32-bit pixel format, 10 bits for blue, green and red, 2 bits for alpha.
-        PF_A2B10G10R10 = 16,
-        /// DDS (DirectDraw Surface) DXT1 format
-        PF_DXT1 = 17,
-        /// DDS (DirectDraw Surface) DXT2 format
-        PF_DXT2 = 18,
-        /// DDS (DirectDraw Surface) DXT3 format
-        PF_DXT3 = 19,
-        /// DDS (DirectDraw Surface) DXT4 format
-        PF_DXT4 = 20,
-        /// DDS (DirectDraw Surface) DXT5 format
-        PF_DXT5 = 21,
-		// 16-bit pixel format, 16 bits (float) for red
-        PF_FLOAT16_R = 32,
-        // 48-bit pixel format, 16 bits (float) for red, 16 bits (float) for green, 16 bits (float) for blue
-        PF_FLOAT16_RGB = 22,
-        // 64-bit pixel format, 16 bits (float) for red, 16 bits (float) for green, 16 bits (float) for blue, 16 bits (float) for alpha
-        PF_FLOAT16_RGBA = 23,
-		// 32-bit pixel format, 32 bits (float) for red
-        PF_FLOAT32_R = 33,
-        // 96-bit pixel format, 32 bits (float) for red, 32 bits (float) for green, 32 bits (float) for blue
-        PF_FLOAT32_RGB = 24,
-        // 128-bit pixel format, 32 bits (float) for red, 32 bits (float) for green, 32 bits (float) for blue, 32 bits (float) for alpha
-        PF_FLOAT32_RGBA = 25,
-		// 32-bit, 2-channel s10e5 floating point pixel format, 16-bit green, 16-bit red
-		PF_FLOAT16_GR = 35,
-		// 64-bit, 2-channel floating point pixel format, 32-bit green, 32-bit red
-		PF_FLOAT32_GR = 36,
-		// Depth texture format
-		PF_DEPTH = 29,
-		// 64-bit pixel format, 16 bits for red, green, blue and alpha
-		PF_SHORT_RGBA = 30,
-		// 32-bit pixel format, 16-bit green, 16-bit red
-		PF_SHORT_GR = 34,
-		// 48-bit pixel format, 16 bits for red, green and blue
-		PF_SHORT_RGB = 37,
-        /// PVRTC (PowerVR) RGB 2 bpp
-        PF_PVRTC_RGB2 = 38,
-        /// PVRTC (PowerVR) RGBA 2 bpp
-        PF_PVRTC_RGBA2 = 39,
-        /// PVRTC (PowerVR) RGB 4 bpp
-        PF_PVRTC_RGB4 = 40,
-        /// PVRTC (PowerVR) RGBA 4 bpp
-        PF_PVRTC_RGBA4 = 41,
-		// Number of pixel formats currently defined
-        PF_COUNT = 42
-    };
-	typedef vector<PixelFormat>::type PixelFormatList;
-
-    /**
-     * Flags defining some on/off properties of pixel formats
-     */
-    enum PixelFormatFlags {
-        // This format has an alpha channel
-        PFF_HASALPHA        = 0x00000001,      
-        // This format is compressed. This invalidates the values in elemBytes,
-        // elemBits and the bit counts as these might not be fixed in a compressed format.
-        PFF_COMPRESSED    = 0x00000002,
-        // This is a floating point format
-        PFF_FLOAT           = 0x00000004,         
-        // This is a depth format (for depth textures)
-        PFF_DEPTH           = 0x00000008,
-        // Format is in native endian. Generally true for the 16, 24 and 32 bits
-        // formats which can be represented as machine integers.
-        PFF_NATIVEENDIAN    = 0x00000010,
-        // This is an intensity format instead of a RGB one. The luminance
-        // replaces R,G and B. (but not A)
-        PFF_LUMINANCE       = 0x00000020
-    };
-    
-    /** Pixel component format */
-    enum PixelComponentType
-    {
-        PCT_BYTE = 0,    /// Byte per component (8 bit fixed 0.0..1.0)
-        PCT_SHORT = 1,   /// Short per component (16 bit fixed 0.0..1.0))
-        PCT_FLOAT16 = 2, /// 16 bit float per component
-        PCT_FLOAT32 = 3, /// 32 bit float per component
-        PCT_COUNT = 4    /// Number of pixel types
-    };
-    
-	/** A primitive describing a volume (3D), image (2D) or line (1D) of pixels in memory.
-     	In case of a rectangle, depth must be 1. 
-     	Pixels are stored as a succession of "depth" slices, each containing "height" rows of 
-     	"width" pixels.
-    */
-    class CM_UTILITY_EXPORT PixelData: public Box {
-    public:
-    	/// Parameter constructor for setting the members manually
-    	PixelData() {}
-		~PixelData() {}
-		/** Constructor providing extents in the form of a Box object. This constructor
-    		assumes the pixel data is laid out consecutively in memory. (this
-    		means row after row, slice after slice, with no space in between)
-    		@param extents	    Extents of the region defined by data
-    		@param pixelFormat	Format of this buffer
-    		@param pixelData	Pointer to the actual data
-    	*/
-		PixelData(const Box &extents, PixelFormat pixelFormat, void *pixelData=0):
-			Box(extents), data(pixelData), format(pixelFormat)
-		{
-			setConsecutive();
-		}
-    	/** Constructor providing width, height and depth. This constructor
-    		assumes the pixel data is laid out consecutively in memory. (this
-    		means row after row, slice after slice, with no space in between)
-    		@param width	    Width of the region
-    		@param height	    Height of the region
-    		@param depth	    Depth of the region
-    		@param pixelFormat	Format of this buffer
-    		@param pixelData    Pointer to the actual data
-    	*/
-    	PixelData(size_t width, size_t height, size_t depth, PixelFormat pixelFormat, void *pixelData=0):
-    		Box(0, 0, 0, width, height, depth),
-    		data(pixelData), format(pixelFormat)
-    	{
-    		setConsecutive();
-    	}
-    	
-        /// The data pointer 
-        void *data;
-        /// The pixel format 
-        PixelFormat format;
-        /** Number of elements between the leftmost pixel of one row and the left
-         	pixel of the next. This value must always be equal to getWidth() (consecutive) 
-			for compressed formats.
-        */
-        size_t rowPitch;
-        /** Number of elements between the top left pixel of one (depth) slice and 
-         	the top left pixel of the next. This can be a negative value. Must be a multiple of
-         	rowPitch. This value must always be equal to getWidth()*getHeight() (consecutive) 
-			for compressed formats.
-        */
-        size_t slicePitch;
-        
-        /** Set the rowPitch and slicePitch so that the buffer is laid out consecutive 
-         	in memory.
-        */        
-        void setConsecutive()
-        {
-            rowPitch = getWidth();
-            slicePitch = getWidth()*getHeight();
-        }
-        /**	Get the number of elements between one past the rightmost pixel of 
-         	one row and the leftmost pixel of the next row. (IE this is zero if rows
-         	are consecutive).
-        */
-        size_t getRowSkip() const { return rowPitch - getWidth(); }
-        /** Get the number of elements between one past the right bottom pixel of
-         	one slice and the left top pixel of the next slice. (IE this is zero if slices
-         	are consecutive).
-        */
-        size_t getSliceSkip() const { return slicePitch - (getHeight() * rowPitch); }
-
-        /** Return whether this buffer is laid out consecutive in memory (ie the pitches
-         	are equal to the dimensions)
-        */        
-        bool isConsecutive() const 
-		{ 
-			return rowPitch == getWidth() && slicePitch == getWidth()*getHeight(); 
-		}
-        /** Return the size (in bytes) this image would take if it was
-        	laid out consecutive in memory
-      	*/
-      	size_t getConsecutiveSize() const;
-      	/** Return a subvolume of this PixelBox.
-      		@param def	Defines the bounds of the subregion to return
-      		@returns	A pixel box describing the region and the data in it
-      		@remarks	This function does not copy any data, it just returns
-      			a PixelBox object with a data pointer pointing somewhere inside 
-      			the data of object.
-      		@throws	Exception(ERR_INVALIDPARAMS) if def is not fully contained
-      	*/
-      	PixelData getSubVolume(const Box &def) const;
-        
-        /**
-         * Get colour value from a certain location in the PixelBox. The z coordinate
-         * is only valid for cubemaps and volume textures. This uses the first (largest)
-         * mipmap.
-         */
-        Color getColourAt(size_t x, size_t y, size_t z);
-
-        /**
-         * Set colour value at a certain location in the PixelBox. The z coordinate
-         * is only valid for cubemaps and volume textures. This uses the first (largest)
-         * mipmap.
-         */
-        void setColourAt(Color const &cv, size_t x, size_t y, size_t z);
-    };
-    
-
     /**
      * Some utility functions for packing and unpacking pixel data
      */

+ 1 - 1
CamelotUtility/Include/CmTextureDataRTTI.h

@@ -17,7 +17,7 @@ namespace CamelotEngine
 		CM_SETGET_MEMBER(mFlags, INT32, TextureData)
 		CM_SETGET_MEMBER(mBPP, UINT8, TextureData)
 		CM_SETGET_MEMBER(mFormat, PixelFormat, TextureData)
-		
+
 		ManagedDataBlock getData(TextureData* obj) 
 		{
 			return ManagedDataBlock(obj->mData, obj->mSize, false);

+ 2 - 1
CamelotUtility/Include/CmTypes.h

@@ -22,6 +22,7 @@ namespace CamelotEngine
 
 	enum TypeID_Utility
 	{
-		TID_Abstract = 50 // Special type ID used for Abstract classes. Only type ID that may be used by more than one class.
+		TID_Abstract = 50, // Special type ID used for Abstract classes. Only type ID that may be used by more than one class.
+		TID_PixelData = 51
 	};
 }

+ 19 - 0
CamelotUtility/Source/CmPixelData.cpp

@@ -0,0 +1,19 @@
+#include "CmPixelData.h"
+#include "CmPixelDataRTTI.h"
+
+namespace CamelotEngine
+{
+	/************************************************************************/
+	/* 								SERIALIZATION                      		*/
+	/************************************************************************/
+
+	RTTITypeBase* PixelData::getRTTIStatic()
+	{
+		return PixelDataRTTI::instance();
+	}
+
+	RTTITypeBase* PixelData::getRTTI() const
+	{
+		return PixelData::getRTTIStatic();
+	}
+}