소스 검색

Refactored Texture part #2

Marko Pintera 13 년 전
부모
커밋
03f4bb7402

+ 7 - 17
CamelotD3D9Renderer/Include/CmD3D9Texture.h

@@ -78,12 +78,8 @@ namespace CamelotEngine {
 		D3DMULTISAMPLE_TYPE mFSAAType;
 		D3DMULTISAMPLE_TYPE mFSAAType;
 		DWORD mFSAAQuality;
 		DWORD mFSAAQuality;
 
 
-		/// internal method, load a cube texture
-		void _loadCubeTex(IDirect3DDevice9* d3d9Device);
-		/// internal method, load a normal texture
-		void _loadNormTex(IDirect3DDevice9* d3d9Device);
-		/// internal method, load a volume texture
-		void _loadVolumeTex(IDirect3DDevice9* d3d9Device);
+		/// overriden from Resource
+		void initialize_internal();	
 
 
 		/// 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);
@@ -127,9 +123,6 @@ namespace CamelotEngine {
 		/// mipmap level. This method must be called after the D3D texture object was created
 		/// mipmap level. This method must be called after the D3D texture object was created
 		void _createSurfaceList(IDirect3DDevice9* d3d9Device, TextureResources* textureResources);
 		void _createSurfaceList(IDirect3DDevice9* d3d9Device, TextureResources* textureResources);
 	 
 	 
-		/// Loads this texture into the specified device.
-		void initImpl(IDirect3DDevice9* d3d9Device);
-
 		/// gets the texture resources attached to the given device.
 		/// gets the texture resources attached to the given device.
 		TextureResources* getTextureResources(IDirect3DDevice9* d3d9Device);
 		TextureResources* getTextureResources(IDirect3DDevice9* d3d9Device);
 
 
@@ -152,20 +145,17 @@ namespace CamelotEngine {
 		~D3D9Texture();
 		~D3D9Texture();
 
 
 		/// overridden from Texture
 		/// overridden from Texture
-		void copyToTexture( TexturePtr& target );
-
-		/// overriden from Resource
-		void initImpl();	
+		void copy_internal( TexturePtr& target );
 
 
 		/// @copydoc Texture::getBuffer
 		/// @copydoc Texture::getBuffer
-		HardwarePixelBufferPtr getBuffer(size_t face, size_t mipmap);
+		HardwarePixelBufferPtr getBuffer_internal(size_t face, size_t mipmap);
 		
 		
 		/// retrieves a pointer to the actual texture
 		/// retrieves a pointer to the actual texture
-		IDirect3DBaseTexture9 *getTexture();		
+		IDirect3DBaseTexture9 *getTexture_internal();		
 		/// retrieves a pointer to the normal 1D/2D texture
 		/// retrieves a pointer to the normal 1D/2D texture
-		IDirect3DTexture9 *getNormTexture();
+		IDirect3DTexture9 *getNormTexture_internal();
 		/// retrieves a pointer to the cube texture
 		/// retrieves a pointer to the cube texture
-		IDirect3DCubeTexture9 *getCubeTexture();
+		IDirect3DCubeTexture9 *getCubeTexture_internal();
 
 
 		/** Indicates whether the hardware gamma is actually enabled and supported. 
 		/** Indicates whether the hardware gamma is actually enabled and supported. 
 		@remarks
 		@remarks

+ 2 - 2
CamelotD3D9Renderer/Source/CmD3D9RenderSystem.cpp

@@ -533,7 +533,7 @@ namespace CamelotEngine
 		D3D9TexturePtr dt = std::static_pointer_cast<D3D9Texture>(tex);
 		D3D9TexturePtr dt = std::static_pointer_cast<D3D9Texture>(tex);
 		if (enabled && (dt != nullptr))
 		if (enabled && (dt != nullptr))
 		{
 		{
-			IDirect3DBaseTexture9 *pTex = dt->getTexture();
+			IDirect3DBaseTexture9 *pTex = dt->getTexture_internal();
 			if (mTexStageDesc[stage].pTex != pTex)
 			if (mTexStageDesc[stage].pTex != pTex)
 			{
 			{
 				hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(stage), pTex);
 				hr = getActiveD3D9Device()->SetTexture(static_cast<DWORD>(stage), pTex);
@@ -610,7 +610,7 @@ namespace CamelotEngine
 		{
 		{
 			D3D9TexturePtr dt = std::static_pointer_cast<D3D9Texture>(tex);
 			D3D9TexturePtr dt = std::static_pointer_cast<D3D9Texture>(tex);
 
 
-			IDirect3DBaseTexture9 *pTex = dt->getTexture();
+			IDirect3DBaseTexture9 *pTex = dt->getTexture_internal();
 			if (mTexStageDesc[stage].pVertexTex != pTex)
 			if (mTexStageDesc[stage].pVertexTex != pTex)
 			{
 			{
 				HRESULT hr = getActiveD3D9Device()->SetTexture(D3DVERTEXTEXTURESAMPLER0 + static_cast<DWORD>(stage), pTex);
 				HRESULT hr = getActiveD3D9Device()->SetTexture(D3DVERTEXTEXTURESAMPLER0 + static_cast<DWORD>(stage), pTex);

+ 36 - 92
CamelotD3D9Renderer/Source/CmD3D9Texture.cpp

@@ -36,7 +36,12 @@ THE SOFTWARE.
 #include "CmD3D9DeviceManager.h"
 #include "CmD3D9DeviceManager.h"
 #include "CmD3D9ResourceManager.h"
 #include "CmD3D9ResourceManager.h"
 #include "CmRenderSystemManager.h"
 #include "CmRenderSystemManager.h"
-#include "CmTextureData.h"
+
+#if CM_DEBUG_MODE
+#define THROW_IF_NOT_RENDER_THREAD throwIfNotRenderThread();
+#else
+#define THROW_IF_NOT_RENDER_THREAD 
+#endif
 
 
 namespace CamelotEngine 
 namespace CamelotEngine 
 {
 {
@@ -55,6 +60,8 @@ namespace CamelotEngine
 	/****************************************************************************************/
 	/****************************************************************************************/
 	D3D9Texture::~D3D9Texture()
 	D3D9Texture::~D3D9Texture()
 	{	
 	{	
+		THROW_IF_NOT_RENDER_THREAD;
+
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 		D3D9_DEVICE_ACCESS_CRITICAL_SECTION
 		
 		
         // have to call this here reather than in Resource destructor
         // have to call this here reather than in Resource destructor
@@ -74,8 +81,10 @@ namespace CamelotEngine
 		mSurfaceList.clear();		
 		mSurfaceList.clear();		
 	}
 	}
 	/****************************************************************************************/
 	/****************************************************************************************/
-	void D3D9Texture::copyToTexture(TexturePtr& target)
+	void D3D9Texture::copy_internal(TexturePtr& target)
 	{
 	{
+		THROW_IF_NOT_RENDER_THREAD
+
         // check if this & target are the same format and type
         // check if this & target are the same format and type
 		// blitting from or to cube textures is not supported yet
 		// blitting from or to cube textures is not supported yet
 		if (target->getUsage() != getUsage() ||
 		if (target->getUsage() != getUsage() ||
@@ -181,8 +190,12 @@ namespace CamelotEngine
 		}		
 		}		
 	}
 	}
 	/****************************************************************************************/
 	/****************************************************************************************/
-	void D3D9Texture::initImpl()
-	{
+	void D3D9Texture::initialize_internal()
+	{ 
+		THROW_IF_NOT_RENDER_THREAD
+
+		createInternalResources();
+
 		if (!mInternalResourcesCreated)
 		if (!mInternalResourcesCreated)
 		{
 		{
 			// NB: Need to initialise pool to some value other than D3DPOOL_DEFAULT,
 			// NB: Need to initialise pool to some value other than D3DPOOL_DEFAULT,
@@ -197,37 +210,13 @@ namespace CamelotEngine
 		{
 		{
 			IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
 			IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getResourceCreationDevice(i);
 
 
-			initImpl(d3d9Device);
+			if (mUsage & TU_RENDERTARGET)
+			{
+				createInternalResourcesImpl(d3d9Device);
+				return;
+			}	
 		}		
 		}		
 	}
 	}
-
-	/****************************************************************************************/
-	void D3D9Texture::initImpl(IDirect3DDevice9* d3d9Device)
-	{		
-		if (mUsage & TU_RENDERTARGET)
-		{
-			createInternalResourcesImpl(d3d9Device);
-			return;
-		}
-
-		// load based on tex.type
-		switch (getTextureType())
-		{
-		case TEX_TYPE_1D:
-		case TEX_TYPE_2D:
-			_loadNormTex(d3d9Device);
-			break;
-		case TEX_TYPE_3D:
-			_loadVolumeTex(d3d9Device);
-			break;
-		case TEX_TYPE_CUBE_MAP:
-			_loadCubeTex(d3d9Device);
-			break;
-		default:
-			CM_EXCEPT(InternalErrorException, "Unknown texture type");
-		}				
-	}
-
 	/****************************************************************************************/
 	/****************************************************************************************/
 	void D3D9Texture::freeInternalResources(void)
 	void D3D9Texture::freeInternalResources(void)
 	{
 	{
@@ -311,61 +300,6 @@ namespace CamelotEngine
 		SAFE_RELEASE(textureResources->pVolumeTex);
 		SAFE_RELEASE(textureResources->pVolumeTex);
 		SAFE_RELEASE(textureResources->pFSAASurface);
 		SAFE_RELEASE(textureResources->pFSAASurface);
 	}
 	}
-
-	/****************************************************************************************/
-	void D3D9Texture::_loadCubeTex(IDirect3DDevice9* d3d9Device)
-	{
-		assert(getTextureType() == TEX_TYPE_CUBE_MAP);
-		assert(mTextureData.size() == 6);
-
-        initializeFromTextureData();
-	}
-	/****************************************************************************************/
-	void D3D9Texture::_loadVolumeTex(IDirect3DDevice9* d3d9Device)
-	{
-		assert(getTextureType() == TEX_TYPE_3D);
-        assert(mTextureData.size()==1);
-
-		TextureDataPtr texData = mTextureData[0];
-
-		if (texData->getHeight() == 0)
-		{
-			CM_EXCEPT(InternalErrorException, "Image height == 0");
-		}
-
-		if (texData->getWidth() == 0)
-		{
-			CM_EXCEPT(InternalErrorException, "Image width == 0");
-		}
-
-		if (texData->getDepth() == 0)
-		{
-			CM_EXCEPT(InternalErrorException, "Image depth == 0");
-		}
-			
-		initializeFromTextureData();
-    }
-	/****************************************************************************************/
-	void D3D9Texture::_loadNormTex(IDirect3DDevice9* d3d9Device)
-	{
-		assert(getTextureType() == TEX_TYPE_1D || getTextureType() == TEX_TYPE_2D);
-		assert(mTextureData.size()==1);
-
-		TextureDataPtr texData = mTextureData[0];
-
-		if (texData->getHeight() == 0)
-		{
-			CM_EXCEPT(InternalErrorException, "Image height == 0");
-		}
-
-		if (texData->getWidth() == 0)
-		{
-			CM_EXCEPT(InternalErrorException, "Image width == 0");
-		}
-
-		initializeFromTextureData();
-	}
-
 	/****************************************************************************************/
 	/****************************************************************************************/
 	size_t D3D9Texture::calculateSize(void) const
 	size_t D3D9Texture::calculateSize(void) const
 	{
 	{
@@ -1111,8 +1045,10 @@ namespace CamelotEngine
 	}
 	}
 	#undef GETLEVEL
 	#undef GETLEVEL
 	/****************************************************************************************/
 	/****************************************************************************************/
-	HardwarePixelBufferPtr D3D9Texture::getBuffer(size_t face, size_t mipmap) 
+	HardwarePixelBufferPtr D3D9Texture::getBuffer_internal(size_t face, size_t mipmap) 
 	{
 	{
+		THROW_IF_NOT_RENDER_THREAD;
+
 		if(face >= getNumFaces())
 		if(face >= getNumFaces())
 			CM_EXCEPT(InvalidParametersException, "A three dimensional cube has six faces");
 			CM_EXCEPT(InvalidParametersException, "A three dimensional cube has six faces");
 		if(mipmap > mNumMipmaps)
 		if(mipmap > mNumMipmaps)
@@ -1213,8 +1149,10 @@ namespace CamelotEngine
 	}
 	}
 
 
 	//---------------------------------------------------------------------
 	//---------------------------------------------------------------------
-	IDirect3DBaseTexture9* D3D9Texture::getTexture()
+	IDirect3DBaseTexture9* D3D9Texture::getTexture_internal()
 	{
 	{
+		THROW_IF_NOT_RENDER_THREAD;
+
 		TextureResources* textureResources;			
 		TextureResources* textureResources;			
 		IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
 		IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
 			
 			
@@ -1231,8 +1169,10 @@ namespace CamelotEngine
 	}
 	}
 
 
 	//---------------------------------------------------------------------
 	//---------------------------------------------------------------------
-	IDirect3DTexture9* D3D9Texture::getNormTexture()
+	IDirect3DTexture9* D3D9Texture::getNormTexture_internal()
 	{
 	{
+		THROW_IF_NOT_RENDER_THREAD;
+
 		TextureResources* textureResources;
 		TextureResources* textureResources;
 		IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
 		IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
 		
 		
@@ -1249,8 +1189,10 @@ namespace CamelotEngine
 	}
 	}
 
 
 	//---------------------------------------------------------------------
 	//---------------------------------------------------------------------
-	IDirect3DCubeTexture9* D3D9Texture::getCubeTexture()
+	IDirect3DCubeTexture9* D3D9Texture::getCubeTexture_internal()
 	{
 	{
+		THROW_IF_NOT_RENDER_THREAD;
+
 		TextureResources* textureResources;
 		TextureResources* textureResources;
 		IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
 		IDirect3DDevice9* d3d9Device = D3D9RenderSystem::getActiveD3D9Device();
 		
 		
@@ -1362,3 +1304,5 @@ namespace CamelotEngine
 		}			
 		}			
 	}	
 	}	
 }
 }
+
+#undef THROW_IF_NOT_RENDER_THREAD

+ 2 - 0
CamelotFreeImgImporter/CamelotFreeImgImporter.vcxproj

@@ -13,10 +13,12 @@
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="Include\CmFreeImgImporter.h" />
     <ClInclude Include="Include\CmFreeImgImporter.h" />
     <ClInclude Include="Include\CmFreeImgPrerequisites.h" />
     <ClInclude Include="Include\CmFreeImgPrerequisites.h" />
+    <ClInclude Include="Include\CmTextureData.h" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmFreeImgImporter.cpp" />
     <ClCompile Include="Source\CmFreeImgImporter.cpp" />
     <ClCompile Include="Source\CmFreeImgPlugin.cpp" />
     <ClCompile Include="Source\CmFreeImgPlugin.cpp" />
+    <ClCompile Include="Source\CmTextureData.cpp" />
   </ItemGroup>
   </ItemGroup>
   <PropertyGroup Label="Globals">
   <PropertyGroup Label="Globals">
     <ProjectGuid>{122B7A22-0C62-4B35-B661-EBF3F394EA79}</ProjectGuid>
     <ProjectGuid>{122B7A22-0C62-4B35-B661-EBF3F394EA79}</ProjectGuid>

+ 6 - 0
CamelotFreeImgImporter/CamelotFreeImgImporter.vcxproj.filters

@@ -21,6 +21,9 @@
     <ClInclude Include="Include\CmFreeImgImporter.h">
     <ClInclude Include="Include\CmFreeImgImporter.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\CmTextureData.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\CmFreeImgPlugin.cpp">
     <ClCompile Include="Source\CmFreeImgPlugin.cpp">
@@ -29,5 +32,8 @@
     <ClCompile Include="Source\CmFreeImgImporter.cpp">
     <ClCompile Include="Source\CmFreeImgImporter.cpp">
       <Filter>Source Files</Filter>
       <Filter>Source Files</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\CmTextureData.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 7 - 1
CamelotFreeImgImporter/Include/CmFreeImgPrerequisites.h

@@ -16,4 +16,10 @@
 #    define CM_FREEIMG_EXPORT  __attribute__ ((visibility("default")))
 #    define CM_FREEIMG_EXPORT  __attribute__ ((visibility("default")))
 #else
 #else
 #    define CM_FREEIMG_EXPORT
 #    define CM_FREEIMG_EXPORT
-#endif
+#endif
+
+namespace CamelotEngine
+{
+	class TextureData;
+	typedef std::shared_ptr<TextureData> TextureDataPtr;
+}

+ 87 - 0
CamelotFreeImgImporter/Include/CmTextureData.h

@@ -0,0 +1,87 @@
+#pragma once
+
+#include "CmFreeImgPrerequisites.h"
+#include "CmPixelUtil.h"
+
+namespace CamelotEngine
+{
+	enum TextureDataFlags
+	{
+		TDF_COMPRESSED = 0x00000001,
+		TDF_CUBEMAP    = 0x00000002,
+		TDF_3D_TEXTURE = 0x00000004
+	};
+
+	class CM_FREEIMG_EXPORT TextureData
+	{
+	public:
+		TextureData(UINT32 width, UINT32 height, UINT32 size, 
+			PixelFormat format, UINT8* data, UINT32 depth = 1, INT32 flags = 0, UINT32 numMipmaps = 1);
+		~TextureData();
+
+		/** Returns a pointer to the internal image buffer.
+		@remarks
+			Be careful with this method. You will almost certainly
+			prefer to use getPixels, especially with complex images
+			which include custom mipmaps.
+        */
+        UINT8* getData(void) { return mData; }
+
+        /** Returns a const pointer to the internal image buffer.
+		@remarks
+			Be careful with this method. You will almost certainly
+			prefer to use getPixels, especially with complex images
+			which include custom mipmaps.
+        */
+        const UINT8* getData() const { return mData; } 
+
+        /** Returns the size of the data buffer.
+        */
+		UINT32 getSize() const { return mSize; }
+
+        /** Returns the number of mipmaps contained in the image.
+        */
+		UINT32 getNumMipmaps() const { return mNumMipmaps; }
+
+        /** Returns true if the image has the appropriate flag set.
+        */
+		bool hasFlag(const TextureDataFlags flag) const { return (mFlags & flag) != 0; }
+
+        /** Gets the width of the image in pixels.
+        */
+        UINT32 getWidth(void) const { return mWidth; }
+
+        /** Gets the height of the image in pixels.
+        */
+        UINT32 getHeight(void) const { return mHeight; }
+
+        /** Gets the depth of the image.
+        */
+        UINT32 getDepth(void) const { return mDepth; }
+
+        /** Returns the image format.
+        */
+        PixelFormat getFormat() const { return mFormat; }
+
+        /** Returns the number of bits per pixel.
+        */
+        UINT8 getBPP() const { return mBPP; }
+
+        /** Returns true if the image has an alpha component.
+        */
+        bool getHasAlpha() const { return PixelUtil::getFlags(mFormat) & PFF_HASALPHA; }
+
+		PixelData getPixels(UINT32 mip);
+
+	private:
+		UINT32 mNumMipmaps;
+		UINT32 mWidth;
+		UINT32 mHeight;
+		UINT32 mSize;
+		UINT32 mDepth;
+		INT32 mFlags;
+		UINT8 mBPP;
+		PixelFormat mFormat;
+		UINT8* mData;
+	};
+}

+ 6 - 1
CamelotFreeImgImporter/Source/CmFreeImgImporter.cpp

@@ -138,7 +138,12 @@ namespace CamelotEngine
 		TextureHandle newTexture(Texture::create(TEX_TYPE_2D, 
 		TextureHandle newTexture(Texture::create(TEX_TYPE_2D, 
 			imgData->getWidth(), imgData->getHeight(), imgData->getNumMipmaps(), imgData->getFormat()));
 			imgData->getWidth(), imgData->getHeight(), imgData->getNumMipmaps(), imgData->getFormat()));
 
 
-		newTexture->setTextureData(0, imgData);
+		for(size_t mip = 0; mip <= imgData->getNumMipmaps(); ++mip)
+		{
+			PixelData src = imgData->getPixels(mip);
+
+			newTexture->setRawPixels(src, 0, mip);
+		}
 
 
 		fileData->close();
 		fileData->close();
 
 

+ 57 - 0
CamelotFreeImgImporter/Source/CmTextureData.cpp

@@ -0,0 +1,57 @@
+#include "CmTextureData.h"
+#include "CmException.h"
+
+namespace CamelotEngine
+{
+	TextureData::TextureData(UINT32 width, UINT32 height, UINT32 size, 
+		PixelFormat format, UINT8* data, UINT32 depth, INT32 flags, UINT32 numMipmaps)
+		:mWidth(width), mHeight(height), mDepth(depth), mSize(size), mFormat(format),
+		mFlags(flags), mNumMipmaps(numMipmaps), mData(data)
+	{
+		mBPP = static_cast<UINT8>(PixelUtil::getNumElemBytes(mFormat)) * 8;
+	}
+
+	TextureData::~TextureData()
+	{
+		if(mData != nullptr)
+			delete[] mData;
+	}
+
+	PixelData TextureData::getPixels(UINT32 mip)
+	{
+		if(mip < 0 || mip > mNumMipmaps)
+		{
+			CM_EXCEPT(InvalidParametersException, "Mip out of range: " + toString(mip) + ". While maximum available mip is: " + toString((mNumMipmaps)));
+		}
+
+		// Calculate mipmap offset and size
+		UINT8 *offset = const_cast<UINT8*>(getData());
+		UINT8 offsetSoFar = 0;
+
+		UINT32 width = getWidth(), height = getHeight(), depth = getDepth();
+		UINT32 numMips = getNumMipmaps();
+
+		// Figure out the offsets 
+		UINT32 finalWidth = 0, finalHeight = 0, finalDepth = 0;
+		for(UINT32 curMip = 0; curMip <= numMips; ++curMip)
+		{
+			if (curMip == mip)
+			{
+				offset += offsetSoFar;
+				finalWidth = width;
+				finalHeight = height;
+				finalDepth = depth;
+			}
+			offsetSoFar += PixelUtil::getMemorySize(width, height, depth, getFormat());
+
+			/// Half size in each dimension
+			if(width!=1) width /= 2;
+			if(height!=1) height /= 2;
+			if(depth!=1) depth /= 2;
+		}
+
+		// Return subface as pixelbox
+		PixelData src(finalWidth, finalHeight, finalDepth, getFormat(), offset);
+		return src;
+	}
+}

+ 8 - 22
CamelotGLRenderer/Include/CmGLTexture.h

@@ -45,25 +45,19 @@ namespace CamelotEngine {
 
 
         virtual ~GLTexture();      
         virtual ~GLTexture();      
 
 
-        void createRenderTexture();
-			
 		/// @copydoc Texture::getBuffer
 		/// @copydoc Texture::getBuffer
-		HardwarePixelBufferPtr getBuffer(size_t face, size_t mipmap);
+		HardwarePixelBufferPtr getBuffer_internal(size_t face, size_t mipmap);
 
 
         // Takes the OGRE texture type (1d/2d/3d/cube) and returns the appropriate GL one
         // Takes the OGRE texture type (1d/2d/3d/cube) and returns the appropriate GL one
-        GLenum getGLTextureTarget(void) const;
+        GLenum getGLTextureTarget_internal(void) const;
 
 
-        GLuint getGLID() const
-        {
-            return mTextureID;
-        }
+        GLuint getGLID_internal() const;
 		
 		
-		void getCustomAttribute(const String& name, void* pData);
-
-		/// @copydoc Resource::loadImpl
-		void initImpl();
+		void getCustomAttribute_internal(const String& name, void* pData);
 
 
     protected:
     protected:
+		void initialize_internal();
+
 		/// @copydoc Texture::createInternalResourcesImpl
 		/// @copydoc Texture::createInternalResourcesImpl
 		void createInternalResourcesImpl(void);
 		void createInternalResourcesImpl(void);
         /// @copydoc Resource::freeInternalResourcesImpl
         /// @copydoc Resource::freeInternalResourcesImpl
@@ -74,17 +68,9 @@ namespace CamelotEngine {
 			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
 			actually allocate the buffer
 			actually allocate the buffer
 		*/
 		*/
-		void _createSurfaceList();
-
-        /// Used to hold images between calls to prepare and load.
-        //typedef SharedPtr<vector<Image>::type > LoadedImages;
-
-        /** Vector of images that were pulled from disk by
-            prepareLoad but have yet to be pushed into texture memory
-            by loadImpl.  Images should be deleted by loadImpl and unprepareImpl.
-        */
-        //LoadedImages mLoadedImages;
+		void createSurfaceList();
 
 
+		void createRenderTexture();
 
 
     private:
     private:
         GLuint mTextureID;
         GLuint mTextureID;

+ 2 - 2
CamelotGLRenderer/Source/CmGLRenderSystem.cpp

@@ -482,7 +482,7 @@ namespace CamelotEngine {
 			if (tex)
 			if (tex)
 			{
 			{
 				// note used
 				// note used
-				mTextureTypes[stage] = tex->getGLTextureTarget();
+				mTextureTypes[stage] = tex->getGLTextureTarget_internal();
 			}
 			}
 			else
 			else
 				// assume 2D
 				// assume 2D
@@ -502,7 +502,7 @@ namespace CamelotEngine {
 			}
 			}
 
 
 			if(tex)
 			if(tex)
-				glBindTexture( mTextureTypes[stage], tex->getGLID() );
+				glBindTexture( mTextureTypes[stage], tex->getGLID_internal() );
 			else
 			else
 			{
 			{
 				glBindTexture( mTextureTypes[stage], static_cast<GLTextureManager*>(&TextureManager::instance())->getWarningTextureID() );
 				glBindTexture( mTextureTypes[stage], static_cast<GLTextureManager*>(&TextureManager::instance())->getWarningTextureID() );

+ 44 - 29
CamelotGLRenderer/Source/CmGLTexture.cpp

@@ -49,9 +49,13 @@ THE SOFTWARE.
 #  include <wingdi.h>
 #  include <wingdi.h>
 #endif
 #endif
 
 
-namespace CamelotEngine {
-
+#if CM_DEBUG_MODE
+#define THROW_IF_NOT_RENDER_THREAD throwIfNotRenderThread();
+#else
+#define THROW_IF_NOT_RENDER_THREAD 
+#endif
 
 
+namespace CamelotEngine {
 
 
     GLTexture::GLTexture(GLSupport& support) 
     GLTexture::GLTexture(GLSupport& support) 
         : Texture(),
         : Texture(),
@@ -62,10 +66,23 @@ namespace CamelotEngine {
 
 
     GLTexture::~GLTexture()
     GLTexture::~GLTexture()
     {
     {
+		THROW_IF_NOT_RENDER_THREAD;
+
 		freeInternalResources();
 		freeInternalResources();
     }
     }
 
 
-    GLenum GLTexture::getGLTextureTarget(void) const
+	void GLTexture::initialize_internal()
+	{
+		createInternalResources();
+
+		if( mUsage & TU_RENDERTARGET )
+		{
+			createRenderTexture();
+			return;
+		}
+	}
+
+    GLenum GLTexture::getGLTextureTarget_internal(void) const
     {
     {
         switch(mTextureType)
         switch(mTextureType)
         {
         {
@@ -82,6 +99,13 @@ namespace CamelotEngine {
         };
         };
     }
     }
 
 
+	GLuint GLTexture::getGLID_internal() const
+	{
+		THROW_IF_NOT_RENDER_THREAD;
+
+		return mTextureID;
+	}
+
 	//* Creation / loading methods ********************************************
 	//* Creation / loading methods ********************************************
 	void GLTexture::createInternalResourcesImpl(void)
 	void GLTexture::createInternalResourcesImpl(void)
     {
     {
@@ -107,19 +131,19 @@ namespace CamelotEngine {
         glGenTextures( 1, &mTextureID );
         glGenTextures( 1, &mTextureID );
 		
 		
 		// Set texture type
 		// Set texture type
-		glBindTexture( getGLTextureTarget(), mTextureID );
+		glBindTexture( getGLTextureTarget_internal(), mTextureID );
         
         
 		// This needs to be set otherwise the texture doesn't get rendered
 		// This needs to be set otherwise the texture doesn't get rendered
 		if (GLEW_VERSION_1_2)
 		if (GLEW_VERSION_1_2)
-			glTexParameteri( getGLTextureTarget(), GL_TEXTURE_MAX_LEVEL, mNumMipmaps );
+			glTexParameteri( getGLTextureTarget_internal(), GL_TEXTURE_MAX_LEVEL, mNumMipmaps );
         
         
         // Set some misc default parameters so NVidia won't complain, these can of course be changed later
         // Set some misc default parameters so NVidia won't complain, these can of course be changed later
-        glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(getGLTextureTarget(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glTexParameteri(getGLTextureTarget_internal(), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(getGLTextureTarget_internal(), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 		if (GLEW_VERSION_1_2)
 		if (GLEW_VERSION_1_2)
 		{
 		{
-			glTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-			glTexParameteri(getGLTextureTarget(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+			glTexParameteri(getGLTextureTarget_internal(), GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+			glTexParameteri(getGLTextureTarget_internal(), GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 		}
 		}
 		
 		
 		// Allocate internal buffer so that glTexSubImageXD can be used
 		// Allocate internal buffer so that glTexSubImageXD can be used
@@ -210,9 +234,9 @@ namespace CamelotEngine {
 				if(depth>1)		depth = depth/2;
 				if(depth>1)		depth = depth/2;
 			}
 			}
 		}
 		}
-		_createSurfaceList();
+		createSurfaceList();
 		// Get final internal format
 		// Get final internal format
-		mFormat = getBuffer(0,0)->getFormat();
+		mFormat = getBuffer_internal(0,0)->getFormat();
 	}
 	}
 	
 	
     void GLTexture::createRenderTexture(void)
     void GLTexture::createRenderTexture(void)
@@ -221,20 +245,6 @@ namespace CamelotEngine {
 		// This already does everything neccessary
 		// This already does everything neccessary
         createInternalResources();
         createInternalResources();
     }
     }
-
-    void GLTexture::initImpl()
-    {
-        if( mUsage & TU_RENDERTARGET )
-        {
-            createRenderTexture();
-            return;
-        }
-
-		initializeFromTextureData();
-
-		mTextureData.clear();
-    }
-
 	//*************************************************************************
 	//*************************************************************************
     
     
     void GLTexture::freeInternalResourcesImpl()
     void GLTexture::freeInternalResourcesImpl()
@@ -245,7 +255,7 @@ namespace CamelotEngine {
 
 
 	
 	
 	//---------------------------------------------------------------------------------------------
 	//---------------------------------------------------------------------------------------------
-	void GLTexture::_createSurfaceList()
+	void GLTexture::createSurfaceList()
 	{
 	{
 		mSurfaceList.clear();
 		mSurfaceList.clear();
 		
 		
@@ -253,7 +263,7 @@ namespace CamelotEngine {
 		{
 		{
 			for(size_t mip=0; mip<=getNumMipmaps(); mip++)
 			for(size_t mip=0; mip<=getNumMipmaps(); mip++)
 			{
 			{
-                GLHardwarePixelBuffer *buf = new GLTextureBuffer("", getGLTextureTarget(), mTextureID, face, mip,
+                GLHardwarePixelBuffer *buf = new GLTextureBuffer("", getGLTextureTarget_internal(), mTextureID, face, mip,
 						static_cast<HardwareBuffer::Usage>(mUsage), false, mHwGamma, mFSAA);
 						static_cast<HardwareBuffer::Usage>(mUsage), false, mHwGamma, mFSAA);
 				mSurfaceList.push_back(HardwarePixelBufferPtr(buf));
 				mSurfaceList.push_back(HardwarePixelBufferPtr(buf));
                 
                 
@@ -271,8 +281,10 @@ namespace CamelotEngine {
 	}
 	}
 	
 	
 	//---------------------------------------------------------------------------------------------
 	//---------------------------------------------------------------------------------------------
-	HardwarePixelBufferPtr GLTexture::getBuffer(size_t face, size_t mipmap)
+	HardwarePixelBufferPtr GLTexture::getBuffer_internal(size_t face, size_t mipmap)
 	{
 	{
+		THROW_IF_NOT_RENDER_THREAD;
+
 		if(face >= getNumFaces())
 		if(face >= getNumFaces())
 			CM_EXCEPT(InvalidParametersException, "Face index out of range");
 			CM_EXCEPT(InvalidParametersException, "Face index out of range");
 		if(mipmap > mNumMipmaps)
 		if(mipmap > mNumMipmaps)
@@ -282,11 +294,14 @@ namespace CamelotEngine {
 		return mSurfaceList[idx];
 		return mSurfaceList[idx];
 	}
 	}
 	//---------------------------------------------------------------------------------------------
 	//---------------------------------------------------------------------------------------------
-	void GLTexture::getCustomAttribute(const String& name, void* pData)
+	void GLTexture::getCustomAttribute_internal(const String& name, void* pData)
 	{
 	{
+		THROW_IF_NOT_RENDER_THREAD;
+
 		if (name == "GLID")
 		if (name == "GLID")
 			*static_cast<GLuint*>(pData) = mTextureID;
 			*static_cast<GLuint*>(pData) = mTextureID;
 	}
 	}
 	
 	
 }
 }
 
 
+#undef THROW_IF_NOT_RENDER_THREAD

+ 14 - 0
CamelotRenderer/Include/CmRenderSystem.h

@@ -1089,6 +1089,20 @@ namespace CamelotEngine
 		 */
 		 */
 		void setActiveContext(RenderSystemContextPtr context);
 		void setActiveContext(RenderSystemContextPtr context);
 
 
+		/**
+		 * @brief	Queues a new command that will be added to the resource context.
+		 * 	
+		 * @see		RenderSystemContext::queueReturnCommand
+		 */
+		AsyncOp queueResourceReturnCommand(boost::function<void(AsyncOp&)> commandCallback, bool blockUntilComplete = false, UINT32 _callbackId = 0);
+
+		/**
+		 * @brief	Queues a new command that will be added to the resource context.
+		 * 	
+		 * @see		RenderSystemContext::queueCommand
+		 */
+		void queueResourceCommand(boost::function<void()> commandCallback, bool blockUntilComplete = false, UINT32 _callbackId = 0);
+
 		/**
 		/**
 		 * @brief	Callback that is called from the render thread before it starts processing
 		 * @brief	Callback that is called from the render thread before it starts processing
 		 * 			deferred render commands.
 		 * 			deferred render commands.

+ 1 - 1
CamelotRenderer/Include/CmResource.h

@@ -15,7 +15,7 @@ namespace CamelotEngine
 		virtual ~Resource() {};
 		virtual ~Resource() {};
 
 
 		void init();
 		void init();
-		virtual void initImpl() = 0;
+		virtual void initImpl() {}
 
 
 		const String& getUUID() const { return mUUID; }
 		const String& getUUID() const { return mUUID; }
 
 

+ 42 - 29
CamelotRenderer/Include/CmTexture.h

@@ -157,52 +157,73 @@ namespace CamelotEngine {
 			@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.
 		*/
 		*/
-		virtual HardwarePixelBufferPtr getBuffer(size_t face=0, size_t mipmap=0) = 0;
+		virtual HardwarePixelBufferPtr getBuffer_internal(size_t face=0, size_t mipmap=0) = 0;
 		
 		
 		/** Retrieve a platform or API-specific piece of information from this texture.
 		/** Retrieve a platform or API-specific piece of information from this texture.
 		 This method of retrieving information should only be used if you know what you're doing.
 		 This method of retrieving information should only be used if you know what you're doing.
 		 @param name The name of the attribute to retrieve
 		 @param name The name of the attribute to retrieve
 		 @param pData Pointer to memory matching the type of data you want to retrieve.
 		 @param pData Pointer to memory matching the type of data you want to retrieve.
 		*/
 		*/
-		virtual void getCustomAttribute(const String& name, void* pData) {}
+		virtual void getCustomAttribute_internal(const String& name, void* pData);
 
 
 		/**
 		/**
-		 * @brief	Retrieves the texture data from the GPU, loads it into system memory
-		 * 			and returns it in the form of TextureData for the specified.
-		 *
-		 * @return	Texture data for the wanted face.
+		 * @brief	Sets raw texture pixels for the specified mip level and texture face. Pixel format
+		 * 			must match the format of the texture.
+		 * 			
+		 * @note	Not-async. This operation will block the current thread until the render thread
+		 *			executes the command.
 		 */
 		 */
-		TextureDataPtr getTextureData(UINT32 face);
+		void setRawPixels(const PixelData& data, UINT32 face = 0, UINT32 mip = 0);
 
 
 		/**
 		/**
 		 * @brief	Sets raw texture pixels for the specified mip level and texture face. Pixel format
 		 * @brief	Sets raw texture pixels for the specified mip level and texture face. Pixel format
-		 * 			must match the format of the texture.
+		 * 			must match the format of the texture. Returns immediately
+		 * 			but the texture won't be updated until the command
+		 * 			executes on the render thread.
+		 * 			
+		 * @see		Texture::setRawPixels		
+		 */
+		void setRawPixels_async(const PixelData& data, UINT32 face = 0, UINT32 mip = 0);
+
+		/**
+		 * @brief	Internal version of Texture::setRawPixels. Only callable
+		 * 			from the render thread.
+		 *
+		 * @see		Texture::setRawPixels
 		 */
 		 */
-		void setRawPixels(const PixelData& data, UINT32 face = 0, UINT32 mip = 0);
 		void setRawPixels_internal(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
 		 * @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
 		 * 			as it will read data from the GPU. If the texture is compressed
 		 * 			the returned data will be contain compressed pixels as well.
 		 * 			the returned data will be contain compressed pixels as well.
+		 * 			
+		 * @note	Not-async. This operation will block the current thread until the render thread
+		 *			executes the command.
 		 */
 		 */
 		PixelDataPtr getRawPixels(UINT32 face = 0, UINT32 mip = 0);
 		PixelDataPtr getRawPixels(UINT32 face = 0, UINT32 mip = 0);
-		PixelDataPtr getRawPixels_internal(UINT32 face = 0, UINT32 mip = 0);
+		
+
+		/**
+		 * @brief	Async version of Texture::getRawPixels. Returns immediately
+		 * 			but you won't have access to the pixel data until the command
+		 * 			executes on the render thread.
+		 *
+		 * @see		Texture::getRawPixels
+		 */
+		AsyncOp getRawPixels_async(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. 
-		 * 			Texture data array will be cleared after the texture is fully loaded.
+		 * @brief	Internal version of Texture::getRawPixels. Only callable
+		 * 			from the render thread.
 		 *
 		 *
-		 * @param	face	  	The face index. Cubemaps have six faces in this order:
-		 * 						+X (0), -X (1), +Y (2), -Y (3), +Z (4), -Z (5)
-		 * @param	textureData	Texture data for the face.
+		 * @see		Texture::getRawPixels
 		 */
 		 */
-		void setTextureData(UINT32 face, TextureDataPtr textureData);
+		void getRawPixels_internal(UINT32 face, UINT32 mip, AsyncOp& op);
 
 
 		/** Copies (and maybe scales to fit) the contents of this texture to
 		/** Copies (and maybe scales to fit) the contents of this texture to
 			another texture. */
 			another texture. */
-		virtual void copyToTexture( TexturePtr& target );
+		virtual void copy_internal( TexturePtr& target );
 
 
     protected:
     protected:
 		friend class TextureManager;
 		friend class TextureManager;
@@ -222,8 +243,6 @@ namespace CamelotEngine {
 
 
 		bool mInternalResourcesCreated;
 		bool mInternalResourcesCreated;
 
 
-		public:
-		vector<TextureDataPtr>::type mTextureData;
 		protected:
 		protected:
 
 
 		/**
 		/**
@@ -233,7 +252,7 @@ namespace CamelotEngine {
 		void initialize(TextureType textureType, size_t width, size_t height, size_t depth, size_t numMipmaps, 
 		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);
 			PixelFormat format, int usage, bool hwGamma, UINT32 fsaa, const String& fsaaHint);
 		
 		
-		void initialize_internal();
+		virtual void initialize_internal() = 0;
 
 
 		/// @copydoc Resource::calculateSize
 		/// @copydoc Resource::calculateSize
 		size_t calculateSize(void) const;
 		size_t calculateSize(void) const;
@@ -263,17 +282,11 @@ namespace CamelotEngine {
 		*/
 		*/
 		virtual void freeInternalResourcesImpl(void) = 0;
 		virtual void freeInternalResourcesImpl(void) = 0;
 
 
-		/**
-		 * @brief	Initializes the texture from texture data array that was previously populated using
-		 * 			setTextureData.
-		 *
-		 * @param	textureData	Array with texture data for each face of the texture.
-		 */
-		virtual void initializeFromTextureData();
-
 		/** Default implementation of unload which calls freeInternalResources */
 		/** Default implementation of unload which calls freeInternalResources */
 		void unloadImpl(void);
 		void unloadImpl(void);
 
 
+		void throwIfNotRenderThread() const;
+
 		/************************************************************************/
 		/************************************************************************/
 		/* 								SERIALIZATION                      		*/
 		/* 								SERIALIZATION                      		*/
 		/************************************************************************/
 		/************************************************************************/

+ 1 - 2
CamelotRenderer/Include/CmTextureRTTI.h

@@ -3,7 +3,6 @@
 #include "CmPrerequisites.h"
 #include "CmPrerequisites.h"
 #include "CmRTTIType.h"
 #include "CmRTTIType.h"
 #include "CmTexture.h"
 #include "CmTexture.h"
-#include "CmTextureData.h"
 #include "CmManagedDataBlock.h"
 #include "CmManagedDataBlock.h"
 #include "CmMath.h"
 #include "CmMath.h"
 
 
@@ -93,7 +92,7 @@ namespace CamelotEngine
 				size_t face = (size_t)Math::Floor(i / (float)(texture->getNumMipmaps() + 1));
 				size_t face = (size_t)Math::Floor(i / (float)(texture->getNumMipmaps() + 1));
 				size_t mipmap = i % (texture->getNumMipmaps() + 1);
 				size_t mipmap = i % (texture->getNumMipmaps() + 1);
 
 
-				texture->setRawPixels(*pixelData->at(i), face, mipmap);
+				texture->setRawPixels_async(*pixelData->at(i), face, mipmap);
 			}
 			}
 
 
 			delete pixelData;
 			delete pixelData;

+ 24 - 3
CamelotRenderer/Source/CmRenderSystem.cpp

@@ -155,8 +155,6 @@ namespace CamelotEngine {
 	RenderWindow* RenderSystem::createRenderWindow(const String &name, unsigned int width, unsigned int height, 
 	RenderWindow* RenderSystem::createRenderWindow(const String &name, unsigned int width, unsigned int height, 
 		bool fullScreen, const NameValuePairList *miscParams)
 		bool fullScreen, const NameValuePairList *miscParams)
 	{
 	{
-		THROW_IF_INVALID_CONTEXT;
-
 		AsyncOp op;
 		AsyncOp op;
 		{
 		{
 			CM_LOCK_MUTEX(mResourceContextMutex)
 			CM_LOCK_MUTEX(mResourceContextMutex)
@@ -933,7 +931,6 @@ namespace CamelotEngine {
 			// Play commands
 			// Play commands
 			for(auto iter = renderSystemContextsCopy.begin(); iter != renderSystemContextsCopy.end(); ++iter)
 			for(auto iter = renderSystemContextsCopy.begin(); iter != renderSystemContextsCopy.end(); ++iter)
 			{
 			{
-				setActiveContext(*iter);
 				(*iter)->playbackCommands();
 				(*iter)->playbackCommands();
 			}
 			}
 
 
@@ -1013,6 +1010,30 @@ namespace CamelotEngine {
 		mActiveContext = context;
 		mActiveContext = context;
 	}
 	}
 
 
+	AsyncOp RenderSystem::queueResourceReturnCommand(boost::function<void(AsyncOp&)> commandCallback, bool blockUntilComplete, UINT32 _callbackId)
+	{
+		AsyncOp op;
+		{
+			CM_LOCK_MUTEX(mResourceContextMutex)
+
+			op = mResourceContext->queueReturnCommand(commandCallback);
+		}
+
+		submitToGpu(mResourceContext, blockUntilComplete);
+		return op;
+	}
+
+	void RenderSystem::queueResourceCommand(boost::function<void()> commandCallback, bool blockUntilComplete, UINT32 _callbackId)
+	{
+		{
+			CM_LOCK_MUTEX(mResourceContextMutex)
+
+			mResourceContext->queueCommand(commandCallback);
+		}
+
+		submitToGpu(mResourceContext, blockUntilComplete);
+	}
+
 	RenderSystemContextPtr RenderSystem::getActiveContext() const
 	RenderSystemContextPtr RenderSystem::getActiveContext() const
 	{
 	{
 		CM_LOCK_MUTEX(mActiveContextMutex);
 		CM_LOCK_MUTEX(mActiveContextMutex);

+ 52 - 134
CamelotRenderer/Source/CmTexture.cpp

@@ -28,10 +28,18 @@ THE SOFTWARE.
 #include "CmHardwarePixelBuffer.h"
 #include "CmHardwarePixelBuffer.h"
 #include "CmTexture.h"
 #include "CmTexture.h"
 #include "CmTextureRTTI.h"
 #include "CmTextureRTTI.h"
-#include "CmTextureData.h"
 #include "CmDataStream.h"
 #include "CmDataStream.h"
 #include "CmException.h"
 #include "CmException.h"
 #include "CmDebug.h"
 #include "CmDebug.h"
+#include "CmRenderSystem.h"
+#include "CmRenderSystemManager.h"
+#include "CmAsyncOp.h"
+
+#if CM_DEBUG_MODE
+#define THROW_IF_NOT_RENDER_THREAD throwIfNotRenderThread();
+#else
+#define THROW_IF_NOT_RENDER_THREAD 
+#endif
 
 
 namespace CamelotEngine {
 namespace CamelotEngine {
 	//--------------------------------------------------------------------------
 	//--------------------------------------------------------------------------
@@ -64,11 +72,10 @@ namespace CamelotEngine {
 		mHwGamma = hwGamma;
 		mHwGamma = hwGamma;
 		mFSAA = fsaa;
 		mFSAA = fsaa;
 		mFSAAHint = fsaaHint;
 		mFSAAHint = fsaaHint;
-	}
-	//-------------------------------------------------------------------------
-	void Texture::initialize_internal()
-	{
-		createInternalResources();
+
+		mSize = getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
+
+		RenderSystemManager::getActive()->queueResourceCommand(boost::bind(&Texture::initialize_internal, this));
 	}
 	}
     //--------------------------------------------------------------------------
     //--------------------------------------------------------------------------
     bool Texture::hasAlpha(void) const
     bool Texture::hasAlpha(void) const
@@ -85,6 +92,11 @@ namespace CamelotEngine {
 	{
 	{
 		return getTextureType() == TEX_TYPE_CUBE_MAP ? 6 : 1;
 		return getTextureType() == TEX_TYPE_CUBE_MAP ? 6 : 1;
 	}
 	}
+	//-------------------------------------------------------------------------
+	void Texture::getCustomAttribute_internal(const String& name, void* pData)
+	{
+		THROW_IF_NOT_RENDER_THREAD;
+	}
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	void Texture::createInternalResources(void)
 	void Texture::createInternalResources(void)
 	{
 	{
@@ -103,65 +115,21 @@ namespace CamelotEngine {
 			mInternalResourcesCreated = false;
 			mInternalResourcesCreated = false;
 		}
 		}
 	}
 	}
-	//-----------------------------------------------------------------------------
-	TextureDataPtr Texture::getTextureData(UINT32 face)
-	{
-		if(face < 0 || face >= getNumFaces())
-		{
-			CM_EXCEPT(InvalidParametersException, "Face index out of range: " + toString(face));
-		}
 
 
-		UINT32 numMips = getNumMipmaps();
-
-		UINT32 totalSize = 0;
-		UINT32 width = getWidth();
-		UINT32 height = getHeight();
-		UINT32 depth = getDepth();
-
-		for(UINT32 j = 0; j <= numMips; j++)
-		{
-			UINT32 currentMipSize = PixelUtil::getMemorySize(
-					width, height, depth, mFormat);
-
-			totalSize += currentMipSize;
-
-			if(width != 1) width /= 2;
-			if(height != 1) height /= 2;
-			if(depth != 1) depth /= 2;
-		}
-
-		UINT8* buffer = new UINT8[totalSize]; // TextureData frees this
-		TextureDataPtr texData(new TextureData(getWidth(), getHeight(), totalSize, mFormat, buffer, getDepth(), 0, getNumMipmaps()));
-
-		for(UINT32 j = 0; j <= numMips; j++)
-		{
-			PixelData pixels = texData->getPixels(j);
-			getBuffer(face, j)->blitToMemory(pixels);
-		}
-
-		return texData;
-	}
-	//-----------------------------------------------------------------------------
-	void Texture::setTextureData(UINT32 face, TextureDataPtr textureData)
+	void Texture::setRawPixels(const PixelData& data, UINT32 face, UINT32 mip)
 	{
 	{
-		if(face < 0 || face >= getNumFaces())
-		{
-			CM_EXCEPT(InvalidParametersException, "Face index out of range: " + toString(face));
-		}
-
-		if(mTextureData.size() <= face)
-			mTextureData.resize(face + 1);
-
-		mTextureData[face] = textureData;
+		RenderSystemManager::getActive()->queueResourceCommand(boost::bind(&Texture::setRawPixels_internal, this, data, face, mip), true);
 	}
 	}
 
 
-	void Texture::setRawPixels(const PixelData& data, UINT32 face, UINT32 mip)
+	void Texture::setRawPixels_async(const PixelData& data, UINT32 face, UINT32 mip)
 	{
 	{
-		// TODO - Queue command
+		RenderSystemManager::getActive()->queueResourceCommand(boost::bind(&Texture::setRawPixels_internal, this, data, face, mip));
 	}
 	}
 
 
 	void Texture::setRawPixels_internal(const PixelData& data, UINT32 face, UINT32 mip)
 	void Texture::setRawPixels_internal(const PixelData& data, UINT32 face, UINT32 mip)
 	{
 	{
+		THROW_IF_NOT_RENDER_THREAD
+
 		if(mip < 0 || mip > mNumMipmaps)
 		if(mip < 0 || mip > mNumMipmaps)
 			CM_EXCEPT(InvalidParametersException, "Invalid mip level: " + toString(mip) + ". Min is 0, max is " + toString(mNumMipmaps));
 			CM_EXCEPT(InvalidParametersException, "Invalid mip level: " + toString(mip) + ". Min is 0, max is " + toString(mNumMipmaps));
 
 
@@ -179,17 +147,25 @@ namespace CamelotEngine {
 				" Depth: " + toString(mDepth) + "/" + toString(data.getDepth()));
 				" Depth: " + toString(mDepth) + "/" + toString(data.getDepth()));
 		}
 		}
 
 
-		getBuffer(face, mip)->blitFromMemory(data);
+		getBuffer_internal(face, mip)->blitFromMemory(data);
 	}
 	}
 
 
 	PixelDataPtr Texture::getRawPixels(UINT32 face, UINT32 mip)
 	PixelDataPtr Texture::getRawPixels(UINT32 face, UINT32 mip)
 	{
 	{
-		// TODO - Queue command
-		return nullptr;
+		AsyncOp op = RenderSystemManager::getActive()->queueResourceReturnCommand(boost::bind(&Texture::getRawPixels_internal, this, face, mip, _1), true);
+
+		return op.getReturnValue<PixelDataPtr>();
+	}
+
+	AsyncOp Texture::getRawPixels_async(UINT32 face, UINT32 mip)
+	{
+		return RenderSystemManager::getActive()->queueResourceReturnCommand(boost::bind(&Texture::getRawPixels_internal, this, face, mip, _1));
 	}
 	}
 
 
-	PixelDataPtr Texture::getRawPixels_internal(UINT32 face, UINT32 mip)
+	void Texture::getRawPixels_internal(UINT32 face, UINT32 mip, AsyncOp& op)
 	{
 	{
+		THROW_IF_NOT_RENDER_THREAD;
+
 		if(mip < 0 || mip > mNumMipmaps)
 		if(mip < 0 || mip > mNumMipmaps)
 			CM_EXCEPT(InvalidParametersException, "Invalid mip level: " + toString(mip) + ". Min is 0, max is " + toString(mNumMipmaps));
 			CM_EXCEPT(InvalidParametersException, "Invalid mip level: " + toString(mip) + ". Min is 0, max is " + toString(mNumMipmaps));
 
 
@@ -215,88 +191,22 @@ namespace CamelotEngine {
 		UINT8* buffer = new UINT8[totalSize]; 
 		UINT8* buffer = new UINT8[totalSize]; 
 		PixelDataPtr src(new PixelData(width, height, depth, getFormat(), buffer, true));
 		PixelDataPtr src(new PixelData(width, height, depth, getFormat(), buffer, true));
 
 
-		getBuffer(face, mip)->blitToMemory(*src);
-
-		return src;
-	}
-
-	//-----------------------------------------------------------------------------
-	void Texture::initializeFromTextureData()
-	{
-		if(mTextureData.size() < 1)
-			CM_EXCEPT(InvalidParametersException, "Cannot load empty vector of images");
-
-		if(getTextureType() == TEX_TYPE_CUBE_MAP)
-		{
-			if(mTextureData.size() != 6)
-				CM_EXCEPT(InvalidParametersException, "Cube map textures require six faces.");
-		}
-		else
-		{
-			if(mTextureData.size() > 1)
-			{
-				gDebug().log("Non-cube textures can only have one face. Loading only first face from the provided array.", "D3D9RenderSystem");
-			}
-		}
-
-		// Set desired texture size and properties from images[0]
-		mWidth = mTextureData[0]->getWidth();
-		mHeight = mTextureData[0]->getHeight();
-		mDepth = mTextureData[0]->getDepth();
-
-		// Get source image format and adjust if required
-		PixelFormat srcFormat = mTextureData[0]->getFormat();
-
-		// The custom mipmaps in the image have priority over everything
-		size_t imageMips = mTextureData[0]->getNumMipmaps();
-
-		if(imageMips > 0)
-		{
-			mNumMipmaps = mTextureData[0]->getNumMipmaps();
-		}
-
-		// Create the texture
-		createInternalResources();
-		// Check if we're loading one image with multiple faces
-		// or a vector of images representing the faces
-		size_t faces;
-		if(mTextureData.size() > 1)
-			faces = mTextureData.size();
-		else
-			faces = 1;
-
-		// Check whether number of faces in images exceeds number of faces
-		// in this texture. If so, clamp it.
-		if(faces > getNumFaces())
-			faces = getNumFaces();
-
-		// Main loading loop
-		// imageMips == 0 if the image has no custom mipmaps, otherwise contains the number of custom mips
-		for(size_t mip = 0; mip<=imageMips; ++mip)
-		{
-			for(size_t i = 0; i < faces; ++i)
-			{
-				PixelData src = mTextureData[i]->getPixels(mip);
-
-				// Sets to treated format in case is difference
-				src.format = srcFormat;
+		getBuffer_internal(face, mip)->blitToMemory(*src);
 
 
-				// Destination: entire texture. blitFromMemory does the scaling to
-				// a power of two for us when needed
-				getBuffer(i, mip)->blitFromMemory(src);
-			}
-		}
-		// Update size (the final size, not including temp space)
-		mSize = getNumFaces() * PixelUtil::getMemorySize(mWidth, mHeight, mDepth, mFormat);
+		op.completeOperation(src);
 	}
 	}
 	//-----------------------------------------------------------------------------
 	//-----------------------------------------------------------------------------
 	void Texture::unloadImpl(void)
 	void Texture::unloadImpl(void)
 	{
 	{
+		THROW_IF_NOT_RENDER_THREAD;
+
 		freeInternalResources();
 		freeInternalResources();
 	}
 	}
     //-----------------------------------------------------------------------------   
     //-----------------------------------------------------------------------------   
-    void Texture::copyToTexture( TexturePtr& target )
+    void Texture::copy_internal( TexturePtr& target )
     {
     {
+		THROW_IF_NOT_RENDER_THREAD;
+
         if(target->getNumFaces() != getNumFaces())
         if(target->getNumFaces() != getNumFaces())
         {
         {
             CM_EXCEPT(InvalidParametersException, 
             CM_EXCEPT(InvalidParametersException, 
@@ -308,10 +218,16 @@ namespace CamelotEngine {
         {
         {
             for(unsigned int mip=0; mip<=numMips; mip++)
             for(unsigned int mip=0; mip<=numMips; mip++)
             {
             {
-                target->getBuffer(face, mip)->blit(getBuffer(face, mip));
+                target->getBuffer_internal(face, mip)->blit(getBuffer_internal(face, mip));
             }
             }
         }
         }
     }
     }
+	//----------------------------------------------------------------------------- 
+	void Texture::throwIfNotRenderThread() const
+	{
+		if(CM_THREAD_CURRENT_ID != RenderSystemManager::getActive()->getRenderThreadId())
+			CM_EXCEPT(InternalErrorException, "Calling an internal texture method from a non-render thread!");
+	}
 
 
 	/************************************************************************/
 	/************************************************************************/
 	/* 								SERIALIZATION                      		*/
 	/* 								SERIALIZATION                      		*/
@@ -344,3 +260,5 @@ namespace CamelotEngine {
 			width, height, num_mips, format, usage, hwGammaCorrection, fsaa, fsaaHint);
 			width, height, num_mips, format, usage, hwGammaCorrection, fsaa, fsaaHint);
 	}
 	}
 }
 }
+
+#undef THROW_IF_NOT_RENDER_THREAD

+ 4 - 2
CamelotRenderer/TODO.txt

@@ -17,18 +17,20 @@ High-level TODO:
 
 
 Command buffer TODO:
 Command buffer TODO:
  - My current approach doesn't allow multiple threads to use the RenderSystem (contexts should be handled differently)
  - My current approach doesn't allow multiple threads to use the RenderSystem (contexts should be handled differently)
+   - Instead of requiring the user to constantly call setActiveContext, make the call peristent per thread. 
+   - Store sequential thread idx in local thread storage, and then we can easily look up a context for a thread and
+     automatically use it, if it's set.
  - 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,
  - 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.
    was the version that will be used.
 
 
  Texture updates:
  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 TextureData private to FreeImgImporter (as its not used anywhere else)
    - Make this per texture and apply when texture is applied:
    - Make this per texture and apply when texture is applied:
 	 filterMode
 	 filterMode
 	 anisoLevel
 	 anisoLevel
 	 wrapMode
 	 wrapMode
 	 mipMapBias
 	 mipMapBias
-   - After texture initialize() schedule createInternalResources command
+   - Make sure resource deletion is handled on the proper thread
 
 
  Immediate:
  Immediate:
   - Resource updates shouldn't happen once per frame. Resources should be submitted to render thread immediately.
   - Resource updates shouldn't happen once per frame. Resources should be submitted to render thread immediately.

+ 0 - 5
CamelotUtility/CamelotUtility.vcxproj

@@ -119,7 +119,6 @@
     <ClInclude Include="Include\CmRTTIReflectablePtrField.h" />
     <ClInclude Include="Include\CmRTTIReflectablePtrField.h" />
     <ClInclude Include="Include\CmRTTIType.h" />
     <ClInclude Include="Include\CmRTTIType.h" />
     <ClInclude Include="Include\CmString.h" />
     <ClInclude Include="Include\CmString.h" />
-    <ClInclude Include="Include\CmTextureDataRTTI.h" />
     <ClInclude Include="Include\CmThreadDefines.h" />
     <ClInclude Include="Include\CmThreadDefines.h" />
     <ClInclude Include="Include\CmTime.h" />
     <ClInclude Include="Include\CmTime.h" />
     <ClInclude Include="Include\CmTimer.h" />
     <ClInclude Include="Include\CmTimer.h" />
@@ -142,16 +141,12 @@
     <ClInclude Include="Include\CmVector4.h" />
     <ClInclude Include="Include\CmVector4.h" />
     <ClInclude Include="Include\CmDynLib.h" />
     <ClInclude Include="Include\CmDynLib.h" />
     <ClInclude Include="Include\CmDataStream.h" />
     <ClInclude Include="Include\CmDataStream.h" />
-    <ClInclude Include="Include\CmTextureData.h" />
     <ClCompile Include="Source\CmBinarySerializer.cpp" />
     <ClCompile Include="Source\CmBinarySerializer.cpp" />
     <ClCompile Include="Source\CmFileSerializer.cpp" />
     <ClCompile Include="Source\CmFileSerializer.cpp" />
     <ClCompile Include="Source\CmFileSystem.cpp" />
     <ClCompile Include="Source\CmFileSystem.cpp" />
     <ClCompile Include="Source\CmIReflectable.cpp" />
     <ClCompile Include="Source\CmIReflectable.cpp" />
     <ClCompile Include="Source\CmRTTIField.cpp" />
     <ClCompile Include="Source\CmRTTIField.cpp" />
     <ClCompile Include="Source\CmRTTIType.cpp" />
     <ClCompile Include="Source\CmRTTIType.cpp" />
-    <ClCompile Include="Source\CmTextureData.cpp">
-      <FileType>CppHeader</FileType>
-    </ClCompile>
     <ClInclude Include="Include\CmWorkQueue.h" />
     <ClInclude Include="Include\CmWorkQueue.h" />
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>

+ 0 - 9
CamelotUtility/CamelotUtility.vcxproj.filters

@@ -138,9 +138,6 @@
     <ClInclude Include="Include\CmDataStream.h">
     <ClInclude Include="Include\CmDataStream.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="Include\CmTextureData.h">
-      <Filter>Header Files</Filter>
-    </ClInclude>
     <ClInclude Include="Include\CmIReflectable.h">
     <ClInclude Include="Include\CmIReflectable.h">
       <Filter>Header Files\Reflection</Filter>
       <Filter>Header Files\Reflection</Filter>
     </ClInclude>
     </ClInclude>
@@ -174,9 +171,6 @@
     <ClInclude Include="Include\CmFileSystem.h">
     <ClInclude Include="Include\CmFileSystem.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
-    <ClInclude Include="Include\CmTextureDataRTTI.h">
-      <Filter>Header Files\RTTI</Filter>
-    </ClInclude>
     <ClInclude Include="Include\CmPoint.h">
     <ClInclude Include="Include\CmPoint.h">
       <Filter>Header Files\Math</Filter>
       <Filter>Header Files\Math</Filter>
     </ClInclude>
     </ClInclude>
@@ -266,9 +260,6 @@
     <ClCompile Include="Source\CmDataStream.cpp">
     <ClCompile Include="Source\CmDataStream.cpp">
       <Filter>Source Files</Filter>
       <Filter>Source Files</Filter>
     </ClCompile>
     </ClCompile>
-    <ClCompile Include="Source\CmTextureData.cpp">
-      <Filter>Source Files</Filter>
-    </ClCompile>
     <ClCompile Include="Source\CmRTTIField.cpp">
     <ClCompile Include="Source\CmRTTIField.cpp">
       <Filter>Source Files\RTTI</Filter>
       <Filter>Source Files\RTTI</Filter>
     </ClCompile>
     </ClCompile>

+ 0 - 2
CamelotUtility/Include/CmFwdDeclUtil.h

@@ -24,7 +24,6 @@ namespace CamelotEngine {
 	class DataStream;
 	class DataStream;
 	class MemoryDataStream;
 	class MemoryDataStream;
 	class FileDataStream;
 	class FileDataStream;
-	class TextureData;
 	class MeshData;
 	class MeshData;
 	class FileSystem;
 	class FileSystem;
 	class Timer;
 	class Timer;
@@ -39,7 +38,6 @@ namespace CamelotEngine {
 	typedef std::shared_ptr<DataStream> DataStreamPtr;
 	typedef std::shared_ptr<DataStream> DataStreamPtr;
 	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
 	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;
 	typedef std::shared_ptr<FileDataStream> FileDataStreamPtr;
 	typedef std::shared_ptr<FileDataStream> FileDataStreamPtr;
-	typedef std::shared_ptr<TextureData> TextureDataPtr;
 	typedef std::shared_ptr<MeshData> MeshDataPtr;
 	typedef std::shared_ptr<MeshData> MeshDataPtr;
 	typedef std::shared_ptr<PixelData> PixelDataPtr;
 	typedef std::shared_ptr<PixelData> PixelDataPtr;
 }
 }