Browse Source

Major RenderTarget refactor to separate sim and core thread functionality
OpenGL fix for VAO management to solve memory corruption

Marko Pintera 11 years ago
parent
commit
492ad2cac2
68 changed files with 2375 additions and 1424 deletions
  1. 3 0
      BansheeCore/Include/BsCorePrerequisites.h
  2. 12 7
      BansheeCore/Include/BsCoreThreadAccessor.h
  3. 69 18
      BansheeCore/Include/BsMultiRenderTexture.h
  4. 180 51
      BansheeCore/Include/BsRenderTarget.h
  5. 86 27
      BansheeCore/Include/BsRenderTexture.h
  6. 116 60
      BansheeCore/Include/BsRenderWindow.h
  7. 3 3
      BansheeCore/Include/BsRenderWindowManager.h
  8. 4 0
      BansheeCore/Include/BsTexture.h
  9. 12 0
      BansheeCore/Include/BsViewport.h
  10. 9 9
      BansheeCore/Include/Win32/BsPlatformImpl.h
  11. 65 16
      BansheeCore/Source/BsCoreThreadAccessor.cpp
  12. 6 1
      BansheeCore/Source/BsMesh.cpp
  13. 4 0
      BansheeCore/Source/BsMeshHeap.cpp
  14. 74 42
      BansheeCore/Source/BsMultiRenderTexture.cpp
  15. 1 1
      BansheeCore/Source/BsRenderSystem.cpp
  16. 60 5
      BansheeCore/Source/BsRenderTarget.cpp
  17. 100 67
      BansheeCore/Source/BsRenderTexture.cpp
  18. 67 27
      BansheeCore/Source/BsRenderWindow.cpp
  19. 8 8
      BansheeCore/Source/BsRenderWindowManager.cpp
  20. 4 0
      BansheeCore/Source/BsTexture.cpp
  21. 6 6
      BansheeCore/Source/BsViewport.cpp
  22. 14 14
      BansheeCore/Source/Win32/BsPlatformImpl.cpp
  23. 10 10
      BansheeCore/Source/Win32/BsPlatformWndProc.cpp
  24. 33 9
      BansheeD3D11RenderSystem/Include/BsD3D11MultiRenderTexture.h
  25. 35 8
      BansheeD3D11RenderSystem/Include/BsD3D11RenderTexture.h
  26. 93 56
      BansheeD3D11RenderSystem/Include/BsD3D11RenderWindow.h
  27. 15 4
      BansheeD3D11RenderSystem/Source/BsD3D11MultiRenderTexture.cpp
  28. 14 10
      BansheeD3D11RenderSystem/Source/BsD3D11RenderSystem.cpp
  29. 16 10
      BansheeD3D11RenderSystem/Source/BsD3D11RenderTexture.cpp
  30. 208 158
      BansheeD3D11RenderSystem/Source/BsD3D11RenderWindow.cpp
  31. 1 1
      BansheeD3D11RenderSystem/Source/BsD3D11RenderWindowManager.cpp
  32. 18 18
      BansheeD3D9RenderSystem/Include/BsD3D9Device.h
  33. 3 3
      BansheeD3D9RenderSystem/Include/BsD3D9DeviceManager.h
  34. 33 14
      BansheeD3D9RenderSystem/Include/BsD3D9MultiRenderTexture.h
  35. 1 0
      BansheeD3D9RenderSystem/Include/BsD3D9Prerequisites.h
  36. 1 1
      BansheeD3D9RenderSystem/Include/BsD3D9RenderSystem.h
  37. 37 15
      BansheeD3D9RenderSystem/Include/BsD3D9RenderTexture.h
  38. 92 64
      BansheeD3D9RenderSystem/Include/BsD3D9RenderWindow.h
  39. 46 43
      BansheeD3D9RenderSystem/Source/BsD3D9Device.cpp
  40. 5 5
      BansheeD3D9RenderSystem/Source/BsD3D9DeviceManager.cpp
  41. 20 17
      BansheeD3D9RenderSystem/Source/BsD3D9MultiRenderTexture.cpp
  42. 30 25
      BansheeD3D9RenderSystem/Source/BsD3D9RenderSystem.cpp
  43. 24 18
      BansheeD3D9RenderSystem/Source/BsD3D9RenderTexture.cpp
  44. 209 175
      BansheeD3D9RenderSystem/Source/BsD3D9RenderWindow.cpp
  45. 1 1
      BansheeD3D9RenderSystem/Source/BsD3D9RenderWindowManager.cpp
  46. 4 4
      BansheeEditor/Source/BsEditorWindowBase.cpp
  47. 1 1
      BansheeEditor/Source/BsGUIResourceTreeView.cpp
  48. 1 1
      BansheeEditor/Source/BsGUIWindowFrameWidget.cpp
  49. 2 1
      BansheeEditor/Source/BsSceneEditorWidget.cpp
  50. 1 1
      BansheeEditorExec/BsEditorExec.cpp
  51. 3 2
      BansheeEngine/Source/BsGUIManager.cpp
  52. 5 4
      BansheeEngine/Source/BsGUIViewport.cpp
  53. 33 13
      BansheeGLRenderSystem/Include/BsGLMultiRenderTexture.h
  54. 36 14
      BansheeGLRenderSystem/Include/BsGLRenderTexture.h
  55. 1 1
      BansheeGLRenderSystem/Include/BsGLVertexArrayObjectManager.h
  56. 0 1
      BansheeGLRenderSystem/Include/BsWin32VideoModeInfo.h
  57. 87 53
      BansheeGLRenderSystem/Include/BsWin32Window.h
  58. 24 28
      BansheeGLRenderSystem/Source/BsGLMultiRenderTexture.cpp
  59. 21 16
      BansheeGLRenderSystem/Source/BsGLRenderSystem.cpp
  60. 23 25
      BansheeGLRenderSystem/Source/BsGLRenderTexture.cpp
  61. 24 11
      BansheeGLRenderSystem/Source/BsGLVertexArrayObjectManager.cpp
  62. 3 3
      BansheeGLRenderSystem/Source/BsWin32GLSupport.cpp
  63. 0 5
      BansheeGLRenderSystem/Source/BsWin32VideoModeInfo.cpp
  64. 213 183
      BansheeGLRenderSystem/Source/BsWin32Window.cpp
  65. 2 1
      BansheeRenderer/Source/BsBansheeRenderer.cpp
  66. 6 0
      BansheeUtility/Include/BsThreadPool.h
  67. 18 6
      BansheeUtility/Source/BsThreadPool.cpp
  68. 19 23
      SceneView.txt

+ 3 - 0
BansheeCore/Include/BsCorePrerequisites.h

@@ -81,6 +81,7 @@ namespace BansheeEngine
     class RenderTexture;
 	class MultiRenderTexture;
     class RenderWindow;
+	class RenderWindowCore;
     struct RenderOpMesh;
     class StringInterface;
     class SamplerState;
@@ -134,6 +135,7 @@ namespace BansheeEngine
 	struct MaterialProxyPass;
 	struct MeshProxy;
 	struct ShaderProxy;
+	class ViewportProxy;
 	class DrawList;
 	// Asset import
 	class SpecificImporter;
@@ -235,6 +237,7 @@ namespace BansheeEngine
 	typedef std::shared_ptr<MaterialProxy> MaterialProxyPtr;
 	typedef std::shared_ptr<MeshProxy> MeshProxyPtr;
 	typedef std::shared_ptr<ShaderProxy> ShaderProxyPtr;
+	typedef std::shared_ptr<ViewportProxy> ViewportProxyPtr;
 	typedef std::shared_ptr<GpuParamDesc> GpuParamDescPtr;
 	typedef std::shared_ptr<ResourceMetaData> ResourceMetaDataPtr;
 }

+ 12 - 7
BansheeCore/Include/BsCoreThreadAccessor.h

@@ -119,37 +119,42 @@ namespace BansheeEngine
 		/**
 		 * @brief	Resize the provided window to specified width and height in pixels.
 		 */
-		void resizeWindow(RenderWindowPtr& renderWindow, UINT32 width, UINT32 height);
+		void resizeWindow(const RenderWindowPtr& renderWindow, UINT32 width, UINT32 height);
 
 		/**
 		 * @brief	Move the provided window to specified screen coordinates.
 		 */
-		void moveWindow(RenderWindowPtr& renderWindow, INT32 left, INT32 top);
+		void moveWindow(const RenderWindowPtr& renderWindow, INT32 left, INT32 top);
 
 		/**
 		 * @brief	Hide the provided window. (Does not destroy it, just hides it).
 		 */
-		void hideWindow(RenderWindowPtr& renderWindow);
+		void hideWindow(const RenderWindowPtr& renderWindow);
 
 		/**
 		 * @brief	Shows a previously hidden window.
 		 */
-		void showWindow(RenderWindowPtr& renderWindow);
+		void showWindow(const RenderWindowPtr& renderWindow);
 
 		/**
 		 * @copydoc RenderWindow::setFullscreen(UINT32, UINT32, float, UINT32)
 		 */
-		void setFullscreen(RenderWindowPtr& renderWindow, UINT32 width, UINT32 height, float refreshRate = 60.0f, UINT32 monitorIdx = 0);
+		void setFullscreen(const RenderWindowPtr& renderWindow, UINT32 width, UINT32 height, float refreshRate = 60.0f, UINT32 monitorIdx = 0);
 
 		/**
 		 * @copydoc RenderWindow::setFullscreen(const VideoMode&)
 		 */
-		void setFullscreen(RenderWindowPtr& renderWindow, const VideoMode& mode);
+		void setFullscreen(const RenderWindowPtr& renderWindow, const VideoMode& mode);
 
 		/**
 		 * @copydoc RenderWindow::setWindowed
 		 */
-		void setWindowed(RenderWindowPtr& renderWindow, UINT32 width, UINT32 height);
+		void setWindowed(const RenderWindowPtr& renderWindow, UINT32 width, UINT32 height);
+
+		/**
+		 * @copydoc RenderTargetcore::setPriority
+		 */
+		void setPriority(const RenderTargetPtr& renderTarget, UINT32 priority);
 
 		/**
 		* @brief	Queues a new generic command that will be added to the command queue.

+ 69 - 18
BansheeCore/Include/BsMultiRenderTexture.h

@@ -16,14 +16,63 @@ namespace BansheeEngine
 		RENDER_SURFACE_DESC depthStencilSurface;
 	};
 
+	/**
+	 * @brief	Contains various properties that describe a render texture.
+	 */
+	class BS_CORE_EXPORT MultiRenderTextureProperties : public RenderTargetProperties
+	{
+	public:
+		virtual ~MultiRenderTextureProperties() { }
+
+	private:
+		friend class MultiRenderTextureCore;
+		friend class MultiRenderTexture;
+	};
+
+	/**
+	 * @brief	Object representing multiple render textures. You may bind this to the pipeline
+	 *			in order to render to all or some of the textures at once.
+	 *
+	 * @note	Core thread only.
+	 */
+	class BS_CORE_EXPORT MultiRenderTextureCore : public RenderTargetCore
+	{
+	public:
+		virtual ~MultiRenderTextureCore();
+
+	protected:
+		MultiRenderTextureCore(MultiRenderTexture* parent, MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc);
+
+		/**
+		 * @copydoc	RenderTargetCore::getNonCore
+		 */
+		MultiRenderTexture* getNonCore() const;
+
+	private:
+		/**
+		 * @brief	Checks that all render surfaces and depth/stencil surface match. If they do not match
+		 *			an exception is thrown.
+		 */
+		void throwIfBuffersDontMatch() const;
+
+		// TODO - Not implemented
+		virtual void copyToMemory(PixelData &dst, FrameBuffer buffer = FB_AUTO);
+
+	protected:
+		Vector<TextureViewPtr> mColorSurfaces;
+		TextureViewPtr mDepthStencilSurface;
+	};
+
 	/**
 	 * @brief	Object representing multiple render textures. You may bind this to the pipeline
 	 *			in order to render to all or some of the textures at once.
+	 *
+	 * @note	Sim thread only.
 	 */
 	class BS_CORE_EXPORT MultiRenderTexture : public RenderTarget
 	{
 	public:
-		virtual ~MultiRenderTexture();
+		virtual ~MultiRenderTexture() { }
 
 		/**
 		 * @copydoc	RenderTarget::initialize
@@ -31,35 +80,37 @@ namespace BansheeEngine
 		void initialize(const MULTI_RENDER_TEXTURE_DESC& desc);
 
 		/**
-		 * @copydoc RenderTarget::isWindow.
+		 * @copydoc	RenderTexture::requiresTextureFlipping
+		 */
+		virtual bool requiresTextureFlipping() const { return false; }
+
+		/**
+		 * @brief	Returns properties that describe the render texture.
 		 */
-		bool isWindow() const { return true; }
+		const MultiRenderTextureProperties& getProperties() const;
 
 		/**
-		 * @copydoc RenderTarget::requiresTextureFlipping.
+		 * @brief	Retrieves a core implementation of a render texture usable only from the
+		 *			core thread.
+		 *
+		 * @note	Core thread only.
 		 */
-		bool requiresTextureFlipping() const { return false; }
+		MultiRenderTextureCore* getCore() const;
 
 	protected:
-		MultiRenderTexture();
+		MultiRenderTexture() { }
 
 		/**
-		 * @copydoc RenderTarget::destroy_internal()
+		 * @copydoc	RenderTexture::createCore
 		 */
-		virtual void destroy_internal();
+		virtual RenderTargetCore* createCore();
 
-	private:
 		/**
-		 * @brief	Checks that all render surfaces and depth/stencil surface match. If they do not match
-		 *			an exception is thrown.
+		 * @brief	Creates a core implementation of a render texture. This implementation
+		 *			is to be used on the core thread only.
 		 */
-		void throwIfBuffersDontMatch() const;
+		virtual MultiRenderTextureCore* createCore(MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc) = 0;
 
-		// TODO - Not implemented
-		virtual void copyToMemory(PixelData &dst, FrameBuffer buffer = FB_AUTO);
-
-	protected:
-		Vector<TextureViewPtr> mColorSurfaces;
-		TextureViewPtr mDepthStencilSurface;
+		MULTI_RENDER_TEXTURE_DESC mDesc;
 	};
 }

+ 180 - 51
BansheeCore/Include/BsRenderTarget.h

@@ -22,25 +22,12 @@ namespace BansheeEngine
 	};
 
 	/**
-	 * @brief	Render target is a frame buffer or a texture that the render
-	 *			system renders to.
-	 *
-	 * @note	Thread safe, except where noted otherwise.
+	 * @brief	Contains various properties that describe a render target.
 	 */
-    class BS_CORE_EXPORT RenderTarget : public CoreObject
-    {
-    public:
-		/**
-		 * @brief	Frame buffer type when double-buffering is used.
-		 */
-		enum FrameBuffer
-		{
-			FB_FRONT,
-			FB_BACK,
-			FB_AUTO
-		};
-
-        virtual ~RenderTarget();
+	class BS_CORE_EXPORT RenderTargetProperties
+	{
+	public:
+		virtual ~RenderTargetProperties() { }
 
 		/**
 		 * @brief	Returns a name of the render target, used for easier identification.
@@ -49,11 +36,15 @@ namespace BansheeEngine
 
 		/**
 		 * @brief	Returns width of the render target, in pixels.
+		 * 
+		 * @note	Sim thread only.
 		 */
         UINT32 getWidth() const { return mWidth; }
 
 		/**
 		 * @brief	Returns height of the render target, in pixels.
+		 *
+		 * @note	Sim thread only.
 		 */
         UINT32 getHeight() const { return mHeight; }
 
@@ -77,17 +68,18 @@ namespace BansheeEngine
 		bool getVSync() const { return mVSync; }
 
 		/**
-		 * @brief	Queries the render target for a custom attribute. This may be anything and is
-		 *			implementation specific.
-		 *
-		 * @note	Core thread only.
+		 * @brief	Returns how often should the frame be presented in respect to
+		 *			display device refresh rate. Normal value is 1 where it will
+		 *			match the refresh rate. Higher values will decrease the frame
+		 *			rate (e.g. present interval of 2 on 60Hz refresh rate will display
+		 *			at most 30 frames per second).
 		 */
-		virtual void getCustomAttribute(const String& name, void* pData) const;
+		UINT32 getVSyncInterval() const { return mVSyncInterval; }
 
 		/**
-		 * @brief	Returns true if the render target is a render window.
+		 * @brief	Returns true if pixels written to the render target will be gamma corrected.
 		 */
-		virtual bool isWindow() const = 0;
+		bool isHwGammaEnabled() const { return mHwGamma; }
 
 		/**
 		 * @brief	Returns true if the render target can be used for rendering.
@@ -97,39 +89,89 @@ namespace BansheeEngine
 		bool isActive() const { return mActive; }
 
 		/**
-		 * @brief	Returns true if pixels written to the render target will be gamma corrected.
+		 * @brief	Returns render target priority. Targets with higher priority will be 
+		 *			rendered before ones with lower priority.
 		 */
-		bool isHwGammaEnabled() const { return mHwGamma; }
+		INT32 getPriority() const { return mPriority; }
 
 		/**
-		 * @brief	Makes the render target active or inactive. (e.g. for a window, it will hide or restore the window).
-		 *
-		 * @note	Core thread only.
+		 * @brief	Returns true if the render target is a render window.
 		 */
-		virtual void setActive(bool state) { mActive = state; }
+		bool isWindow() const { return mIsWindow; }
 
 		/**
-		 * @brief	Returns render target priority. Targets with higher priority will be 
-		 *			rendered before ones with lower priority.
+		 * @brief	Does the texture need to be vertically flipped because of different screen space coordinate systems.
+		 *			(i.e. is origin top left or bottom left. Engine default is top left.)
 		 */
-		INT32 getPriority() const { return mPriority; }
+		bool requiresTextureFlipping() const { return mRequiresTextureFlipping; }
+
+	protected:
+		friend class RenderTargetCore;
+		friend class RenderTarget;
+
+		String mName;
+
+		UINT32 mWidth = 0;
+		UINT32 mHeight = 0;
+		UINT32 mColorDepth = 32;
+
+		INT32 mPriority = 0;
+		UINT32 mVSyncInterval = 1;
+
+		bool mActive = true;
+		bool mHwGamma = false;
+		bool mVSync = false;
+		bool mRequiresTextureFlipping = false;
+		bool mIsWindow = false;
+
+		UINT32 mMultisampleCount = 0;
+		String mMultisampleHint;
+	};
+
+	/**
+	 * @brief	Provides access to internal render target implementation usable only from the core thread.
+	 *
+	 * @note	Core thread only.
+	 */
+	class BS_CORE_EXPORT RenderTargetCore
+	{
+	public:
+		/**
+		 * @brief	Frame buffer type when double-buffering is used.
+		 */
+		enum FrameBuffer
+		{
+			FB_FRONT,
+			FB_BACK,
+			FB_AUTO
+		};
+
+		RenderTargetCore(RenderTarget* parent, RenderTargetProperties* properties);
+		virtual ~RenderTargetCore();
+
+		/**
+		 * @brief	Makes the render target active or inactive. (e.g. for a window, it will hide or restore the window).
+		 *
+		 * @note	Core thread only.
+		 */
+		virtual void setActive(bool state) { mProperties->mActive = state; markCoreDirty(); }
 
 		/**
 		 * @brief	Sets a priority that determines in which orders the render targets the processed.
 		 * 			
 		 * @param	priority	The priority. Higher value means the target will be rendered sooner.
 		 */
-		void setPriority(INT32 priority) { mPriority = priority; }
+		void setPriority(INT32 priority) { mProperties->mPriority = priority; markCoreDirty(); }
 
-        /**
-         * @brief	Swaps the frame buffers to display the next frame.
-         * 			
+		/**
+		 * @brief	Swaps the frame buffers to display the next frame.
+		 *
 		 * @note	Core thread only.
-         */
+		 */
 		virtual void swapBuffers() {};
 
 		/**
-		 * @brief	Copy data from the render target into the provided pixel buffer. 
+		 * @brief	Copy data from the render target into the provided pixel buffer.
 		 *
 		 * @param	dst		Destination buffer to copy the data to. Caller must ensure the buffer is of adequate size.
 		 * @param	buffer	Which buffer is data taken from. This is irrelevant for single buffer render targets.
@@ -138,33 +180,120 @@ namespace BansheeEngine
 		 */
 		virtual void copyToMemory(PixelData &dst, FrameBuffer buffer = FB_AUTO) = 0;
 
+		/**
+		 * @brief	Queries the render target for a custom attribute. This may be anything and is
+		 *			implementation specific.
+		 *
+		 * @note	Core thread only.
+		 */
+		virtual void getCustomAttribute(const String& name, void* pData) const;
+
+		/**
+		 * @brief	Returns properties that describe the render target.
+		 */
+		const RenderTargetProperties& getProperties() const;
+
+		/**
+		 * @brief	Returns the non core version of the render target.
+		 */
+		RenderTarget* getNonCore() const { return mParent; }
+
+		/**
+		 * @brief	Returns true if this object was modified and the sim thread version requires an update.
+		 */
+		bool _isCoreDirty() const { return mCoreDirty; }
+
+		/**
+		 * @brief	Marks the object as clean. Usually called after the sim thread version was updated.
+		 */
+		void _markCoreClean() { mCoreDirty = false; }
+
+	protected:
+		friend class RenderTarget;
+
+		/**
+		 * @brief	Marks this object as modified. Signals the system that the sim thread verison
+		 *			of the object needs an update.
+		 */
+		void markCoreDirty() { mCoreDirty = true; }
+
+		RenderTargetProperties* mProperties;
+		RenderTarget* mParent;
+
+	private:
+		bool mCoreDirty = true;
+	};
+
+	/**
+	 * @brief	Render target is a frame buffer or a texture that the render
+	 *			system renders to.
+	 *
+	 * @note	Sim thread unless noted otherwise. Retrieve core implementation from getCore() 
+	 *			for core thread only functionality.
+	 */
+    class BS_CORE_EXPORT RenderTarget : public CoreObject
+    {
+    public:
+        virtual ~RenderTarget();
+
 		/**
 		 * @brief	Does the texture need to be vertically flipped because of different screen space coordinate systems.
 		 *			(i.e. is origin top left or bottom left. Engine default is top left.)
 		 */
 		virtual bool requiresTextureFlipping() const = 0;
 
+		/**
+		 * @brief	Queries the render target for a custom attribute. This may be anything and is
+		 *			implementation specific.
+		 */
+		virtual void getCustomAttribute(const String& name, void* pData) const;
+
+		/**
+		 * @brief	Returns properties that describe the render target.
+		 *
+		 * @note	Sim thread only.
+		 */
+		const RenderTargetProperties& getProperties() const;
+
+		/**
+		 * @brief	Retrieves a core implementation of a render target usable only from the
+		 *			core thread.
+		 */
+		RenderTargetCore* getCore() const;
+
 		/**
 		 * @brief	Event that gets triggered whenever the render target is resized.
 		 *
 		 * @note	Sim thread only.
 		 */
 		mutable Event<void()> onResized;
+
     protected:
 		RenderTarget();
 
-        String mName;
+		/**
+		 * @brief	Creates a new instance of render target properties used for storing
+		 *			render target data and providing easy access to it.
+		 */
+		virtual RenderTargetProperties* createProperties() const = 0;
 
-        UINT32 mWidth;
-        UINT32 mHeight;
-        UINT32 mColorDepth;
-		
-		INT32 mPriority;
+		/**
+		 * @brief	Creates a core implementation of a render target. This implementation
+		 *			is to be used on the core thread only.
+		 */
+		virtual RenderTargetCore* createCore() = 0;
 
-        bool mActive;
-		bool mHwGamma;
-		bool mVSync;
-		UINT32 mMultisampleCount;
-		String mMultisampleHint;
+		/**
+		 * @copydoc	CoreObject::initialize_internal
+		 */
+		virtual void initialize_internal();
+
+		/**
+		 * @copydoc	CoreObject::destroy_internal
+		 */
+		virtual void destroy_internal();
+
+		RenderTargetCore* mCore;
+		RenderTargetProperties* mProperties;
     };
 }

+ 86 - 27
BansheeCore/Include/BsRenderTexture.h

@@ -15,16 +15,70 @@ namespace BansheeEngine
 		RENDER_SURFACE_DESC depthStencilSurface;
 	};
 
+	/**
+	 * @brief	Contains various properties that describe a render texture.
+	 */
+	class BS_CORE_EXPORT RenderTextureProperties : public RenderTargetProperties
+	{
+	public:
+		virtual ~RenderTextureProperties() { }
+
+	private:
+		friend class RenderTextureCore;
+		friend class RenderTexture;
+	};
+
+	/**
+	 * @brief	Provides access to internal render texture implementation usable only from the core thread.
+	 *
+	 * @note	Core thread only.
+	 */
+	class BS_CORE_EXPORT RenderTextureCore : public RenderTargetCore
+	{
+	public:
+		RenderTextureCore(RenderTexture* parent, RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+			const RENDER_SURFACE_DESC& depthStencilSurfaceDesc);
+		virtual ~RenderTextureCore();
+
+		/**
+		 * @copydoc	RenderTargetCore::copyToMemory
+		 */
+		virtual void copyToMemory(PixelData &dst, FrameBuffer buffer = FB_AUTO);
+
+		/**
+		 * @brief	Returns properties that describe the render texture.
+		 */
+		const RenderTextureProperties& getProperties() const { return *static_cast<RenderTextureProperties*>(mProperties); }
+
+		/**
+		 * @copydoc	RenderTargetCore::getNonCore
+		 */
+		RenderTexture* getNonCore() const;
+
+	private:
+		/**
+		 * @brief	Throws an exception of the color and depth/stencil buffers aren't compatible.
+		 */
+		void throwIfBuffersDontMatch() const;
+
+	protected:
+		friend class RenderTexture;
+
+		TextureViewPtr mColorSurface;
+		TextureViewPtr mDepthStencilSurface;
+	};
+
 	/**
 	 * @brief	Render target specialization that allows you to render into a texture you may
 	 *			later bind in further render operations.
 	 *
-	 * @note	Thread safe, except where noted otherwise.
+	 * @note	Sim thread only. Retrieve core implementation from getCore()
+	 *			for core thread only functionality.
 	 */
     class BS_CORE_EXPORT RenderTexture : public RenderTarget
     {
 	public:
-		virtual ~RenderTexture();
+		virtual ~RenderTexture() { }
 
 		/**
 		 * @brief	Creates a new render texture with color and optionally depth/stencil surfaces.
@@ -44,14 +98,9 @@ namespace BansheeEngine
 			const String& multisampleHint = "", bool createDepth = true, PixelFormat depthStencilFormat = PF_D24S8);
 
 		/**
-		 * @copydoc RenderTarget::isWindow.
+		 * @copydoc	RenderTexture::requiresTextureFlipping
 		 */
-		bool isWindow() const { return false; }
-
-		/**
-		 * @copydoc RenderTarget::requiresTextureFlipping.
-		 */
-		bool requiresTextureFlipping() const { return false; }
+		virtual bool requiresTextureFlipping() const { return false; }
 
 		/**
 		 * @brief	Returns a color surface texture you may bind as an input to an GPU program.
@@ -61,42 +110,52 @@ namespace BansheeEngine
 		const HTexture& getBindableColorTexture() const { return mBindableColorTex; }
 
 		/**
-		* @brief	Returns a depth/stencil surface texture you may bind as an input to an GPU program.
-		*
-		* @note		Be aware that you cannot bind a render texture for reading and writing at the same time.
-		*/
+		 * @brief	Returns a depth/stencil surface texture you may bind as an input to an GPU program.
+		 *
+		 * @note		Be aware that you cannot bind a render texture for reading and writing at the same time.
+		 */
 		const HTexture& getBindableDepthStencilTexture() const { return mBindableDepthStencilTex; }
 
+		/**
+		 * @brief	Returns properties that describe the render texture.
+		 */
+		const RenderTextureProperties& getProperties() const;
+
+		/**
+		 * @brief	Retrieves a core implementation of a render texture usable only from the
+		 *			core thread.
+		 *
+		 * @note	Core thread only.
+		 */
+		RenderTextureCore* getCore() const;
+
 	protected:
 		friend class TextureManager;
 
-		RenderTexture();
+		RenderTexture() { }
 
 		/**
 		 * @copydoc	RenderTarget::initialize
 		 */
-		void initialize(const RENDER_TEXTURE_DESC& desc);
+		virtual void initialize(const RENDER_TEXTURE_DESC& desc);
 
 		/**
-		 * @copydoc RenderTarget::destroy_internal()
-		 */
-		virtual void destroy_internal();
-	private:
-		/**
-		 * @brief	Throws an exception of the color and depth/stencil buffers aren't compatible.
+		 * @copydoc	RenderTexture::createCore
 		 */
-		void throwIfBuffersDontMatch() const;
+		virtual RenderTargetCore* createCore();
 
 		/**
-		 * @copydoc	RenderTarget::copyToMemory
+		 * @brief	Creates a core implementation of a render texture. This implementation
+		 *			is to be used on the core thread only.
 		 */
-		virtual void copyToMemory(PixelData &dst, FrameBuffer buffer = FB_AUTO);
+		virtual RenderTextureCore* createCore(RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+			const RENDER_SURFACE_DESC& depthStencilSurfaceDesc) = 0;
 
 	protected:
-		TextureViewPtr mColorSurface;
-		TextureViewPtr mDepthStencilSurface;
-
 		HTexture mBindableColorTex;
 		HTexture mBindableDepthStencilTex;
+
+		RENDER_SURFACE_DESC mColorSurfaceDesc;
+		RENDER_SURFACE_DESC mDepthStencilSurfaceDesc;
 	};
 }

+ 116 - 60
BansheeCore/Include/BsRenderWindow.h

@@ -52,15 +52,66 @@ namespace BansheeEngine
 	};
 
 	/**
-	 * @brief	Render target specialization that allows you to render into window
-	 *			frame buffer(s).
+	 * @brief	Contains various properties that describe a render window.
+	 */
+	class BS_CORE_EXPORT RenderWindowProperties : public RenderTargetProperties
+	{
+	public:
+		virtual ~RenderWindowProperties() { }
+
+		/**
+		 * @brief	Gets the horizontal origin of the window in pixels.
+		 */
+		INT32 getLeft() const { return mLeft; }
+
+		/**
+		 * @brief	Gets the vertical origin of the window in pixels.
+		 */
+		INT32 getTop() const { return mTop; }
+
+		/**
+		 * @brief	Indicates whether the window currently has keyboard focus.
+		 */
+		bool hasFocus() const { return mHasFocus; }
+
+		/**
+		 * @brief	Returns true if window is running in fullscreen mode.
+		 */
+		bool isFullScreen() const { return mIsFullScreen; }
+
+		/**
+		 * @brief	Returns true if the window is modal (blocks interaction with
+		 *			any non-modal window until closed).
+		 */
+		bool isModal() const { return mIsModal; }
+
+		/**
+		 * @brief	Returns true if the window is hidden.
+		 */
+		bool isHidden() const { return mHidden; }
+
+	protected:
+		friend class RenderWindowCore;
+		friend class RenderWindow;
+
+		bool mIsFullScreen = false;
+		INT32 mLeft = 0;
+		INT32 mTop = 0;
+		bool mHasFocus = false;
+		bool mHidden = false;
+		bool mIsModal = false;
+	};
+
+	/**
+	 * @brief	Provides access to internal render window implementation usable only from the core thread.
 	 *
-	 * @note	Thread safe, except where noted otherwise.
+	 * @note	Core thread only.
 	 */
-    class BS_CORE_EXPORT RenderWindow : public RenderTarget
-    {
-    public:
-		virtual ~RenderWindow();
+	class BS_CORE_EXPORT RenderWindowCore : public RenderTargetCore
+	{
+	public:
+		RenderWindowCore(RenderWindow* parent, RenderWindowProperties* properties);
+		virtual ~RenderWindowCore() { }
 
 		/** 
 		 * @brief	Switches the window to fullscreen mode. Child windows cannot go into fullscreen mode.
@@ -116,49 +167,62 @@ namespace BansheeEngine
         virtual void move(INT32 left, INT32 top) = 0;
 
 		/**
-		 * @copydoc RenderTarget::isWindow.
+		 * @brief	Returns properties that describe the render texture.
 		 */
-		bool isWindow() const { return true; }
+		const RenderWindowProperties& getProperties() const { return *static_cast<RenderWindowProperties*>(mProperties); }
 
-        /**
-         * @brief	Indicates whether the window is visible (not minimized or obscured).
-         */
-        virtual bool isVisible() const { return true; }
+		/**
+		 * @copydoc	RenderTargetCore::getNonCore
+		 */
+		RenderWindow* getNonCore() const;
 
-        /** 
-        * @copydoc RenderTarget::isActive
-		*/
-        virtual bool isActive() const { return mActive && isVisible(); }
+	protected:
+		friend class RenderWindow;
+		friend class RenderWindowManager;
 
-        /** 
-        * @brief	Indicates whether the window has been closed by the user.
-		*/
-        virtual bool isClosed() const = 0;
-        
-        /** 
-        * @brief	Returns true if window is running in fullscreen mode.
-		*/
-        virtual bool isFullScreen() const;
+		/**
+		 * @brief	Called when window is moved or resized.
+		 *
+		 * @note	Core thread.
+		 */
+		virtual void _windowMovedOrResized();
 
 		/**
-		 * @brief	Returns true if the window is modal.
+		 * @brief	Called when window has received focus.
+		 *
+		 * @note	Core thread.
 		 */
-		bool isModal() const { return mDesc.modal; }
+		virtual void _windowFocusReceived();
 
 		/**
-		 * @brief	Gets the horizontal origin of the window in pixels.
+		 * @brief	Called when window has lost focus.
+		 *
+		 * @note	Core thread.
 		 */
-		INT32 getLeft() const { return mLeft; }
+		virtual void _windowFocusLost();
+	};
+
+	/**
+	 * @brief	Render target specialization that allows you to render into window
+	 *			frame buffer(s).
+	 *
+	 * @note	Sim thread only. Retrieve core implementation from getCore()
+	 *			for core thread only functionality.
+	 */
+    class BS_CORE_EXPORT RenderWindow : public RenderTarget
+    {
+    public:
+		virtual ~RenderWindow() { }
 
 		/**
-		 * @brief	Gets the vertical origin of the window in pixels.
+		 * @copydoc	RenderTarget::initialize
 		 */
-		INT32 getTop() const { return mTop; }
+		virtual void initialize(const RENDER_WINDOW_DESC& desc);
 
 		/**
-		 * @brief	Indicates whether the window currently has keyboard focus.
+		 * @copydoc	RenderTarget::destroy
 		 */
-		bool hasFocus() const { return mHasFocus; }
+		virtual void destroy();	
 
 		/**
 		 * @brief	Converts screen position into window local position.
@@ -171,9 +235,17 @@ namespace BansheeEngine
 		virtual Vector2I windowToScreenPos(const Vector2I& windowPos) const = 0;
 
 		/**
-		 * @copydoc	RenderTarget::destroy
+		 * @brief	Returns properties that describe the render window.
+		 */
+		const RenderWindowProperties& getProperties() const;
+
+		/**
+		 * @brief	Retrieves a core implementation of a render window usable only from the
+		 *			core thread.
+		 *
+		 * @note	Core thread only.
 		 */
-		virtual void destroy();
+		RenderWindowCore* getCore() const;
 
 		/**
 		 * @brief	Creates a new render window using the specified options. Optionally
@@ -184,36 +256,20 @@ namespace BansheeEngine
     protected:
 		friend class RenderWindowManager;
 
-        RenderWindow(const RENDER_WINDOW_DESC& desc);
-
-		/**
-         * @brief	Called when window is moved or resized.
-		 *
-		 * @note	Core thread.
-         */
-        virtual void _windowMovedOrResized();
+		RenderWindow() { }
 
 		/**
-         * @brief	Called when window has received focus.
-		 *
-		 * @note	Core thread.
-         */
-		virtual void _windowFocusReceived();
+		 * @copydoc	RenderWindow::createCore
+		 */
+		virtual RenderTargetCore* createCore();
 
 		/**
-         * @brief	Called when window has lost focus.
-		 *
-		 * @note	Core thread.
-         */
-		virtual void _windowFocusLost();
+		 * @brief	Creates a core implementation of a render window. This implementation
+		 *			is to be used on the core thread only.
+		 */
+		virtual RenderWindowCore* createCore(RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc) = 0;
         
 	protected:
-		bool mIsFullScreen;
-		INT32 mLeft;
-		INT32 mTop;
-		bool mHasFocus;
-		bool mHidden;
-
 		RENDER_WINDOW_DESC mDesc;
     };
 }

+ 3 - 3
BansheeCore/Include/BsRenderWindowManager.h

@@ -60,17 +60,17 @@ namespace BansheeEngine
 		/**
 		 * @brief	Called by the core thread when window receives focus.
 		 */
-		void windowFocusReceived(RenderWindow* window);
+		void windowFocusReceived(RenderWindowCore* window);
 
 		/**
 		 * @brief	Called by the core thread when window loses focus.
 		 */
-		void windowFocusLost(RenderWindow* window);
+		void windowFocusLost(RenderWindowCore* window);
 
 		/**
 		 * @brief	Called by the core thread when window is moved or resized.
 		 */
-		void windowMovedOrResized(RenderWindow* window);
+		void windowMovedOrResized(RenderWindowCore* window);
 
 	protected:
 		BS_MUTEX(mWindowMutex);

+ 4 - 0
BansheeCore/Include/BsTexture.h

@@ -259,11 +259,15 @@ namespace BansheeEngine
 		 * @brief	Requests a texture view for the specified mip and array ranges. Returns an existing view of one for
 		 *			the specified ranges already exists, otherwise creates a new one. You must release all views
 		 *			by calling "releaseView" when done.
+		 *
+		 * @note	Core thread only.
 		 */
 		static TextureViewPtr requestView(TexturePtr texture, UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices, GpuViewUsage usage);
 
 		/**
 		 * @brief	Releases the view. View won't actually get destroyed until all references to it are released.
+		 *
+		 * @note	Core thread only.
 		 */
 		static void releaseView(TextureViewPtr view);
 

+ 12 - 0
BansheeCore/Include/BsViewport.h

@@ -12,6 +12,8 @@ namespace BansheeEngine
 	 * @brief	Viewport provides you with a way to render to only a part of a 
 	 * 			RenderTarget. It also allows you to set up color/depth/stencil
 	 * 			clear values for that specific region.
+	 *
+	 * @note	Thread safe unless noted otherwise.
 	 */
 	class BS_CORE_EXPORT Viewport
     {
@@ -58,21 +60,29 @@ namespace BansheeEngine
 
         /**
          * @brief	Gets the actual x coordinate of the viewport in pixels, in [0, RenderTargetWidth] range.
+		 *
+		 * @note	Sim thread only.
          */
 		INT32 getX() const;
 
         /**
          * @brief	Gets the actual y coordinate of the viewport in pixels, in [0, RenderTargetHeight] range.
+		 *
+		 * @note	Sim thread only.
          */
 		INT32 getY() const;
 
 		/**
          * @brief	Gets the actual width coordinate of the viewport in pixels, in [0, RenderTargetWidth] range.
+		 *
+		 * @note	Sim thread only.
          */
 		INT32 getWidth() const;
 
 		/**
          * @brief	Gets the actual height coordinate of the viewport in pixels, in [0, RenderTargetHeight] range.
+		 *
+		 * @note	Sim thread only.
          */
 		INT32 getHeight() const;
                
@@ -85,6 +95,8 @@ namespace BansheeEngine
 
 		/**
 		 * @brief	Returns actual area of the viewport, in pixels.
+		 *
+		 * @note	Sim thread only.
 		 */
 		RectI getArea() const;
 

+ 9 - 9
BansheeCore/Include/Win32/BsPlatformImpl.h

@@ -326,21 +326,21 @@ namespace BansheeEngine
 		 * 			
 		 * @note	Core thread only.
 		 */
-		static Event<void(RenderWindow*)> onWindowFocusReceived;
+		static Event<void(RenderWindowCore*)> onWindowFocusReceived;
 
 		/**
 		 * @brief	Triggered whenever a window loses focus.
 		 * 			
 		 * @note	Core thread only.
 		 */
-		static Event<void(RenderWindow*)> onWindowFocusLost;
+		static Event<void(RenderWindowCore*)> onWindowFocusLost;
 
 		/**
 		 * @brief	Triggered whenever a window gets moved or resized.
 		 * 			
 		 * @note	Core thread only.
 		 */
-		static Event<void(RenderWindow*)> onWindowMovedOrResized;
+		static Event<void(RenderWindowCore*)> onWindowMovedOrResized;
 
 		/**
 		 * @brief	Triggered whenever mouse capture state for the window is changed
@@ -353,11 +353,11 @@ namespace BansheeEngine
 		static bool mIsCursorHidden;
 		static NativeCursorData mCursor;
 		static bool mUsingCustomCursor;
-		static Map<const RenderWindow*, WindowNonClientAreaData> mNonClientAreas;
+		static Map<const RenderWindowCore*, WindowNonClientAreaData> mNonClientAreas;
 
 		static bool mIsTrackingMouse;
-		static Vector<RenderWindow*> mMouseLeftWindows;
-		static Stack<RenderWindow*> mModalWindowStack;
+		static Vector<RenderWindowCore*> mMouseLeftWindows;
+		static Stack<RenderWindowCore*> mModalWindowStack;
 
 		static NativeDropTargetData mDropTargets;
 
@@ -369,8 +369,8 @@ namespace BansheeEngine
 		static void win32ShowCursor();
 		static void win32HideCursor();
 
-		static void windowFocusReceived(RenderWindow* window);
-		static void windowFocusLost(RenderWindow* window);
-		static void windowMovedOrResized(RenderWindow* window);
+		static void windowFocusReceived(RenderWindowCore* window);
+		static void windowFocusLost(RenderWindowCore* window);
+		static void windowMovedOrResized(RenderWindowCore* window);
 	};
 }

+ 65 - 16
BansheeCore/Source/BsCoreThreadAccessor.cpp

@@ -161,44 +161,93 @@ namespace BansheeEngine
 			resource, subresourceIdx, data, std::placeholders::_1));
 	}
 
-	void CoreThreadAccessorBase::resizeWindow(RenderWindowPtr& renderWindow, UINT32 width, UINT32 height)
+	void CoreThreadAccessorBase::resizeWindow(const RenderWindowPtr& renderWindow, UINT32 width, UINT32 height)
 	{
-		mCommandQueue->queue(std::bind(&RenderWindow::resize, renderWindow.get(), width, height));
+		std::function<void(RenderWindowPtr, UINT32, UINT32)> resizeFunc = 
+			[](RenderWindowPtr renderWindow, UINT32 width, UINT32 height)
+		{
+			renderWindow->getCore()->resize(width, height);
+		};
+
+		mCommandQueue->queue(std::bind(resizeFunc, renderWindow, width, height));
 	}
 
-	void CoreThreadAccessorBase::moveWindow(RenderWindowPtr& renderWindow, INT32 left, INT32 top)
+	void CoreThreadAccessorBase::moveWindow(const RenderWindowPtr& renderWindow, INT32 left, INT32 top)
 	{
-		mCommandQueue->queue(std::bind(&RenderWindow::move, renderWindow.get(), left, top));
+		std::function<void(RenderWindowPtr, INT32, INT32)> moveFunc =
+			[](RenderWindowPtr renderWindow, INT32 left, INT32 top)
+		{
+			renderWindow->getCore()->move(left, top);
+		};
+
+		mCommandQueue->queue(std::bind(moveFunc, renderWindow, left, top));
 	}
 
-	void CoreThreadAccessorBase::hideWindow(RenderWindowPtr& renderWindow)
+	void CoreThreadAccessorBase::hideWindow(const RenderWindowPtr& renderWindow)
 	{
-		mCommandQueue->queue(std::bind(&RenderWindow::setHidden, renderWindow.get(), true));
+		std::function<void(RenderWindowPtr)> hideFunc =
+			[](RenderWindowPtr renderWindow)
+		{
+			renderWindow->getCore()->setHidden(true);
+		};
+
+		mCommandQueue->queue(std::bind(hideFunc, renderWindow));
 	}
 
-	void CoreThreadAccessorBase::showWindow(RenderWindowPtr& renderWindow)
+	void CoreThreadAccessorBase::showWindow(const RenderWindowPtr& renderWindow)
 	{
-		mCommandQueue->queue(std::bind(&RenderWindow::setHidden, renderWindow.get(), false));
+		std::function<void(RenderWindowPtr)> showFunc =
+			[](RenderWindowPtr renderWindow)
+		{
+			renderWindow->getCore()->setHidden(false);
+		};
+
+		mCommandQueue->queue(std::bind(showFunc, renderWindow));
 	}
 
-	void CoreThreadAccessorBase::setFullscreen(RenderWindowPtr& renderWindow, UINT32 width, UINT32 height, 
+	void CoreThreadAccessorBase::setFullscreen(const RenderWindowPtr& renderWindow, UINT32 width, UINT32 height,
 		float refreshRate, UINT32 monitorIdx)
 	{
-		void(RenderWindow::*funcPtr)(UINT32, UINT32, float, UINT32) = &RenderWindow::setFullscreen;
+		std::function<void(RenderWindowPtr, UINT32, UINT32, float, UINT32)> fullscreenFunc =
+			[](RenderWindowPtr renderWindow, UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
+		{
+			renderWindow->getCore()->setFullscreen(width, height, refreshRate, monitorIdx);
+		};
 
-		mCommandQueue->queue(std::bind(funcPtr, renderWindow.get(), width, height, refreshRate, monitorIdx));
+		mCommandQueue->queue(std::bind(fullscreenFunc, renderWindow, width, height, refreshRate, monitorIdx));
 	}
 
-	void CoreThreadAccessorBase::setFullscreen(RenderWindowPtr& renderWindow, const VideoMode& mode)
+	void CoreThreadAccessorBase::setFullscreen(const RenderWindowPtr& renderWindow, const VideoMode& mode)
 	{
-		void(RenderWindow::*funcPtr)(const VideoMode&) = &RenderWindow::setFullscreen;
+		std::function<void(RenderWindowPtr, const VideoMode&)> fullscreenFunc =
+			[](RenderWindowPtr renderWindow, const VideoMode& mode)
+		{
+			renderWindow->getCore()->setFullscreen(mode);
+		};
 
-		mCommandQueue->queue(std::bind(funcPtr, renderWindow.get(), std::cref(mode)));
+		mCommandQueue->queue(std::bind(fullscreenFunc, renderWindow, std::cref(mode)));
 	}
 
-	void CoreThreadAccessorBase::setWindowed(RenderWindowPtr& renderWindow, UINT32 width, UINT32 height)
+	void CoreThreadAccessorBase::setWindowed(const RenderWindowPtr& renderWindow, UINT32 width, UINT32 height)
 	{
-		mCommandQueue->queue(std::bind(&RenderWindow::setWindowed, renderWindow.get(), width, height));
+		std::function<void(RenderWindowPtr, UINT32, UINT32)> windowedFunc =
+			[](RenderWindowPtr renderWindow, UINT32 width, UINT32 height)
+		{
+			renderWindow->getCore()->setWindowed(width, height);
+		};
+
+		mCommandQueue->queue(std::bind(windowedFunc, renderWindow, width, height));
+	}
+
+	void CoreThreadAccessorBase::setPriority(const RenderTargetPtr& renderTarget, UINT32 priority)
+	{
+		std::function<void(RenderTargetPtr, UINT32)> windowedFunc =
+			[](RenderTargetPtr renderTarget, UINT32 priority)
+		{
+			renderTarget->getCore()->setPriority(priority);
+		};
+
+		mCommandQueue->queue(std::bind(windowedFunc, renderTarget, priority));
 	}
 
 	AsyncOp CoreThreadAccessorBase::queueReturnCommand(std::function<void(AsyncOp&)> commandCallback)

+ 6 - 1
BansheeCore/Source/BsMesh.cpp

@@ -55,7 +55,7 @@ namespace BansheeEngine
 
 	Mesh::~Mesh()
 	{
-
+		
 	}
 
 	void Mesh::_writeSubresourceSim(UINT32 subresourceIdx, const GpuResourceData& data, bool discardEntireBuffer)
@@ -320,6 +320,11 @@ namespace BansheeEngine
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
+		mVertexData = nullptr;
+		mIndexBuffer = nullptr;
+		mVertexDesc = nullptr;
+		mTempInitialMeshData = nullptr;
+
 		MeshBase::destroy_internal();
 	}
 

+ 4 - 0
BansheeCore/Source/BsMeshHeap.cpp

@@ -61,6 +61,10 @@ namespace BansheeEngine
 		if(mCPUIndexData != nullptr)
 			bs_free(mCPUIndexData);
 
+		mVertexData = nullptr;
+		mIndexBuffer = nullptr;
+		mVertexDesc = nullptr;
+
 		CoreObject::destroy_internal();
 	}
 

+ 74 - 42
BansheeCore/Source/BsMultiRenderTexture.cpp

@@ -2,29 +2,22 @@
 #include "BsTexture.h"
 #include "BsException.h"
 #include "BsDebug.h"
+#include "BsCoreThread.h"
 
 namespace BansheeEngine
 {
-	MultiRenderTexture::MultiRenderTexture()
+	MultiRenderTextureCore::MultiRenderTextureCore(MultiRenderTexture* parent, MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc)
+		:RenderTargetCore(parent, properties)
 	{
 		mColorSurfaces.resize(BS_MAX_MULTIPLE_RENDER_TARGETS);
-	}
-
-	MultiRenderTexture::~MultiRenderTexture()
-	{
-
-	}
 
-	void MultiRenderTexture::initialize(const MULTI_RENDER_TEXTURE_DESC& desc)
-	{
-		bool colorSurfacePropertiesSet = false;
-		for(size_t i = 0; i < desc.colorSurfaces.size(); i++)
+		for (size_t i = 0; i < desc.colorSurfaces.size(); i++)
 		{
-			if(desc.colorSurfaces[i].texture != nullptr)
+			if (desc.colorSurfaces[i].texture != nullptr)
 			{
-				if(i >= BS_MAX_MULTIPLE_RENDER_TARGETS)
+				if (i >= BS_MAX_MULTIPLE_RENDER_TARGETS)
 				{
-					LOGWRN("Render texture index is larger than the maximum number of supported render targets. Index: " + toString((int)i) + 
+					LOGWRN("Render texture index is larger than the maximum number of supported render targets. Index: " + toString((int)i) +
 						". Max. number of render targets: " + toString(BS_MAX_MULTIPLE_RENDER_TARGETS));
 
 					continue;
@@ -32,58 +25,41 @@ namespace BansheeEngine
 
 				TexturePtr texture = desc.colorSurfaces[i].texture;
 
-				if(texture->getUsage() != TU_RENDERTARGET)
+				if (texture->getUsage() != TU_RENDERTARGET)
 					BS_EXCEPT(InvalidParametersException, "Provided texture is not created with render target usage.");
 
-				mColorSurfaces[i] = Texture::requestView(texture, desc.colorSurfaces[i].mipLevel, 1, 
+				mColorSurfaces[i] = Texture::requestView(texture, desc.colorSurfaces[i].mipLevel, 1,
 					desc.colorSurfaces[i].face, desc.colorSurfaces[i].numFaces, GVU_RENDERTARGET);
-
-				if(!colorSurfacePropertiesSet)
-				{
-					mWidth = texture->getWidth();
-					mHeight = texture->getWidth();
-					mColorDepth = BansheeEngine::PixelUtil::getNumElemBits(texture->getFormat());
-					mActive = true;
-					mHwGamma = texture->isHardwareGammaEnabled();
-					mMultisampleCount = texture->getMultisampleCount();
-					mMultisampleHint = texture->getMultisampleHint();
-
-					colorSurfacePropertiesSet = true;
-				}
 			}
 		}
 
-		if(desc.depthStencilSurface.texture != nullptr)
+		if (desc.depthStencilSurface.texture != nullptr)
 		{
 			TexturePtr texture = desc.depthStencilSurface.texture;
 
-			if(texture->getUsage() != TU_DEPTHSTENCIL)
+			if (texture->getUsage() != TU_DEPTHSTENCIL)
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with depth stencil usage.");
 
-			mDepthStencilSurface = Texture::requestView(texture, desc.depthStencilSurface.mipLevel, 1, 
+			mDepthStencilSurface = Texture::requestView(texture, desc.depthStencilSurface.mipLevel, 1,
 				desc.depthStencilSurface.face, desc.depthStencilSurface.numFaces, GVU_DEPTHSTENCIL);
 		}
 
 		throwIfBuffersDontMatch();
-
-		RenderTarget::initialize();
 	}
 
-	void MultiRenderTexture::destroy_internal()
+	MultiRenderTextureCore::~MultiRenderTextureCore()
 	{
-		for(auto iter = mColorSurfaces.begin(); iter != mColorSurfaces.end(); ++iter)
+		for (auto iter = mColorSurfaces.begin(); iter != mColorSurfaces.end(); ++iter)
 		{
-			if(*iter != nullptr)
+			if (*iter != nullptr)
 				Texture::releaseView(*iter);
 		}
 
-		if(mDepthStencilSurface != nullptr)
+		if (mDepthStencilSurface != nullptr)
 			Texture::releaseView(mDepthStencilSurface);
-
-		RenderTarget::destroy_internal();
 	}
 
-	void MultiRenderTexture::throwIfBuffersDontMatch() const
+	void MultiRenderTextureCore::throwIfBuffersDontMatch() const
 	{
 		TextureViewPtr firstSurfaceDesc = nullptr;
 		for(size_t i = 0; i < mColorSurfaces.size(); i++)
@@ -146,8 +122,64 @@ namespace BansheeEngine
 		}
 	}
 
-	void MultiRenderTexture::copyToMemory(PixelData &dst, FrameBuffer buffer)
+	void MultiRenderTextureCore::copyToMemory(PixelData &dst, FrameBuffer buffer)
 	{
 		throw std::exception("The method or operation is not implemented.");
 	}
+
+	MultiRenderTexture* MultiRenderTextureCore::getNonCore() const
+	{
+		return static_cast<MultiRenderTexture*>(mParent);
+	}
+
+	void MultiRenderTexture::initialize(const MULTI_RENDER_TEXTURE_DESC& desc)
+	{
+		mDesc = desc;
+
+		mProperties = createProperties();
+		MultiRenderTextureProperties* properties = static_cast<MultiRenderTextureProperties*>(mProperties);
+		for (size_t i = 0; i < desc.colorSurfaces.size(); i++)
+		{
+			TexturePtr texture = desc.colorSurfaces[i].texture;
+
+			if (texture != nullptr)
+			{
+				properties->mWidth = texture->getWidth();
+				properties->mHeight = texture->getWidth();
+				properties->mColorDepth = BansheeEngine::PixelUtil::getNumElemBits(texture->getFormat());
+				properties->mActive = true;
+				properties->mHwGamma = texture->isHardwareGammaEnabled();
+				properties->mMultisampleCount = texture->getMultisampleCount();
+				properties->mMultisampleHint = texture->getMultisampleHint();
+				properties->mIsWindow = false;
+				properties->mRequiresTextureFlipping = requiresTextureFlipping();
+
+				break;
+			}
+		}
+
+		RenderTarget::initialize();
+	}
+
+	const MultiRenderTextureProperties& MultiRenderTexture::getProperties() const
+	{
+		THROW_IF_CORE_THREAD;
+
+		return static_cast<const MultiRenderTextureProperties&>(RenderTarget::getProperties());
+	}
+
+	MultiRenderTextureCore* MultiRenderTexture::getCore() const
+	{
+		return static_cast<MultiRenderTextureCore*>(mCore);
+	}
+
+	RenderTargetCore* MultiRenderTexture::createCore()
+	{
+		MultiRenderTextureProperties* coreProperties = bs_new<MultiRenderTextureProperties>();
+		MultiRenderTextureProperties* myProperties = static_cast<MultiRenderTextureProperties*>(mProperties);
+
+		*coreProperties = *myProperties;
+
+		return createCore(coreProperties, mDesc);
+	}
 }

+ 1 - 1
BansheeCore/Source/BsRenderSystem.cpp

@@ -271,7 +271,7 @@ namespace BansheeEngine {
 
 		if (target->isInitialized())
 		{
-			target->swapBuffers();
+			target->getCore()->swapBuffers();
 
 			BS_INC_RENDER_STAT(NumPresents);
 		}

+ 60 - 5
BansheeCore/Source/BsRenderTarget.cpp

@@ -2,21 +2,76 @@
 #include "BsViewport.h"
 #include "BsException.h"
 #include "BsRenderSystem.h"
+#include "BsCoreThread.h"
 
 namespace BansheeEngine 
 {
+	RenderTargetCore::RenderTargetCore(RenderTarget* parent, RenderTargetProperties* properties)
+		:mProperties(properties), mParent(parent)
+	{
+
+	}
+
+	RenderTargetCore::~RenderTargetCore()
+	{
+		bs_delete(mProperties);
+	}
+
+	void RenderTargetCore::getCustomAttribute(const String& name, void* pData) const
+	{
+		BS_EXCEPT(InvalidParametersException, "Attribute not found.");
+	}
+
+	const RenderTargetProperties& RenderTargetCore::getProperties() const 
+	{ 
+		THROW_IF_NOT_CORE_THREAD;
+
+		return *mProperties; 
+	}
+
     RenderTarget::RenderTarget()
-		:mActive(true), mHwGamma(false), mVSync(false), mMultisampleCount(0),
-		mWidth(0), mHeight(0), mColorDepth(0), mPriority(0)
+		:mCore(nullptr), mProperties(nullptr)
     {
     }
 
     RenderTarget::~RenderTarget()
     {
+		bs_delete(mProperties);
     }
 
+	const RenderTargetProperties& RenderTarget::getProperties() const
+	{
+		THROW_IF_CORE_THREAD;
+
+		// DEBUG ONLY
+		if (mCore != nullptr)
+			*mProperties = *mCore->mProperties;
+
+		return *mProperties;
+	}
+
+	RenderTargetCore* RenderTarget::getCore() const
+	{
+		return mCore;
+	}
+
+	void RenderTarget::initialize_internal()
+	{
+		CoreObject::initialize_internal();
+
+		mCore = createCore();
+	}
+
+	void RenderTarget::destroy_internal()
+	{
+		bs_delete(mCore);
+		mCore = nullptr;
+
+		CoreObject::destroy_internal();
+	}
+
 	void RenderTarget::getCustomAttribute(const String& name, void* pData) const
-    {
-        BS_EXCEPT(InvalidParametersException, "Attribute not found.");
-    }
+	{
+		BS_EXCEPT(InvalidParametersException, "Attribute not found.");
+	}
 }        

+ 100 - 67
BansheeCore/Source/BsRenderTexture.cpp

@@ -4,69 +4,34 @@
 #include "BsTexture.h"
 #include "BsTextureManager.h"
 #include "BsResources.h"
+#include "BsCoreThread.h"
 
 namespace BansheeEngine
 {
-	RenderTexture::RenderTexture()
-		:mColorSurface(nullptr), mDepthStencilSurface(nullptr)
+	RenderTextureCore::RenderTextureCore(RenderTexture* parent, RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+		const RENDER_SURFACE_DESC& depthStencilSurfaceDesc)
+		:RenderTargetCore(parent, properties), mColorSurface(nullptr), mDepthStencilSurface(nullptr)
 	{
-
-	}
-
-	RenderTexture::~RenderTexture()
-	{
-
-	}
-
-	RenderTexturePtr RenderTexture::create(TextureType textureType, UINT32 width, UINT32 height, 
-		PixelFormat format, bool hwGamma, UINT32 multisampleCount, const String& multisampleHint, 
-		bool createDepth, PixelFormat depthStencilFormat)
-	{
-		return TextureManager::instance().createRenderTexture(textureType, width, height, format, hwGamma, 
-			multisampleCount, multisampleHint, createDepth, depthStencilFormat);
-	}
-
-	void RenderTexture::destroy_internal()
-	{
-		if(mColorSurface != nullptr)
-			Texture::releaseView(mColorSurface);
-
-		if(mDepthStencilSurface != nullptr)
-			Texture::releaseView(mDepthStencilSurface);
-
-		RenderTarget::destroy_internal();
-	}
-
-	void RenderTexture::initialize(const RENDER_TEXTURE_DESC& desc)
-	{
-		if(desc.colorSurface.texture != nullptr)
+		if (colorSurfaceDesc.texture != nullptr)
 		{
-			TexturePtr texture = desc.colorSurface.texture;
+			TexturePtr texture = colorSurfaceDesc.texture;
 
-			if(texture->getUsage() != TU_RENDERTARGET)
+			if (texture->getUsage() != TU_RENDERTARGET)
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with render target usage.");
 
-			mColorSurface = Texture::requestView(texture, desc.colorSurface.mipLevel, 1, 
-				desc.colorSurface.face, desc.colorSurface.numFaces, GVU_RENDERTARGET);
-
-			mWidth = texture->getWidth();
-			mHeight = texture->getHeight();
-			mColorDepth = BansheeEngine::PixelUtil::getNumElemBits(texture->getFormat());
-			mActive = true;
-			mHwGamma = texture->isHardwareGammaEnabled();
-			mMultisampleCount = texture->getMultisampleCount();
-			mMultisampleHint = texture->getMultisampleHint();
+			mColorSurface = Texture::requestView(texture, colorSurfaceDesc.mipLevel, 1,
+				colorSurfaceDesc.face, colorSurfaceDesc.numFaces, GVU_RENDERTARGET);
 		}
 
-		if(desc.depthStencilSurface.texture != nullptr)
+		if (depthStencilSurfaceDesc.texture != nullptr)
 		{
-			TexturePtr texture = desc.depthStencilSurface.texture;
+			TexturePtr texture = depthStencilSurfaceDesc.texture;
 
-			if(texture->getUsage() != TU_DEPTHSTENCIL)
+			if (texture->getUsage() != TU_DEPTHSTENCIL)
 				BS_EXCEPT(InvalidParametersException, "Provided texture is not created with depth stencil usage.");
 
-			mDepthStencilSurface = Texture::requestView(texture, desc.depthStencilSurface.mipLevel, 1, 
-				desc.depthStencilSurface.face, desc.depthStencilSurface.numFaces, GVU_DEPTHSTENCIL);
+			mDepthStencilSurface = Texture::requestView(texture, depthStencilSurfaceDesc.mipLevel, 1,
+				depthStencilSurfaceDesc.face, depthStencilSurfaceDesc.numFaces, GVU_DEPTHSTENCIL);
 		}
 
 		throwIfBuffersDontMatch();
@@ -74,39 +39,38 @@ namespace BansheeEngine
 		assert(mColorSurface != nullptr);
 		assert(mColorSurface->getTexture() != nullptr);
 
-		if(mColorSurface->getTexture()->getTextureType() != TEX_TYPE_2D)
+		if (mColorSurface->getTexture()->getTextureType() != TEX_TYPE_2D)
 			BS_EXCEPT(NotImplementedException, "Render textures are currently only implemented for 2D surfaces.");
 
-		if((mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) > mColorSurface->getTexture()->getNumFaces())
+		if ((mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) > mColorSurface->getTexture()->getNumFaces())
 		{
-			BS_EXCEPT(InvalidParametersException, "Provided number of faces is out of range. Face: " + 
-				toString(mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) + 
+			BS_EXCEPT(InvalidParametersException, "Provided number of faces is out of range. Face: " +
+				toString(mColorSurface->getFirstArraySlice() + mColorSurface->getNumArraySlices()) +
 				". Max num faces: " + toString(mColorSurface->getTexture()->getNumFaces()));
 		}
 
-		if(mColorSurface->getMostDetailedMip() > mColorSurface->getTexture()->getNumMipmaps())
+		if (mColorSurface->getMostDetailedMip() > mColorSurface->getTexture()->getNumMipmaps())
 		{
-			BS_EXCEPT(InvalidParametersException, "Provided number of mip maps is out of range. Mip level: " + 
+			BS_EXCEPT(InvalidParametersException, "Provided number of mip maps is out of range. Mip level: " +
 				toString(mColorSurface->getMostDetailedMip()) + ". Max num mipmaps: " + toString(mColorSurface->getTexture()->getNumMipmaps()));
 		}
+	}
 
-		RenderTarget::initialize();
-
-		// Create non-persistent resource handles for the used textures (we only need them because a lot of the code accepts only handles,
-		// since they're non persistent they don't really have any benefit over shared pointers)
-		if(mColorSurface != nullptr)
-			mBindableColorTex = gResources()._createResourceHandle(mColorSurface->getTexture());
+	RenderTextureCore::~RenderTextureCore()
+	{
+		if (mColorSurface != nullptr)
+			Texture::releaseView(mColorSurface);
 
-		if(mDepthStencilSurface != nullptr)
-			mBindableDepthStencilTex = gResources()._createResourceHandle(mDepthStencilSurface->getTexture());
+		if (mDepthStencilSurface != nullptr)
+			Texture::releaseView(mDepthStencilSurface);
 	}
 
-	void RenderTexture::throwIfBuffersDontMatch() const
+	void RenderTextureCore::throwIfBuffersDontMatch() const
 	{
-		if(mColorSurface == nullptr || mDepthStencilSurface == nullptr)
+		if (mColorSurface == nullptr || mDepthStencilSurface == nullptr)
 			return;
 
-		if(mColorSurface->getTexture()->getWidth() != mDepthStencilSurface->getTexture()->getWidth() ||
+		if (mColorSurface->getTexture()->getWidth() != mDepthStencilSurface->getTexture()->getWidth() ||
 			mColorSurface->getTexture()->getHeight() != mDepthStencilSurface->getTexture()->getHeight() ||
 			mColorSurface->getTexture()->getMultisampleCount() != mDepthStencilSurface->getTexture()->getMultisampleCount() ||
 			mColorSurface->getTexture()->getMultisampleHint() != mDepthStencilSurface->getTexture()->getMultisampleHint())
@@ -120,8 +84,77 @@ namespace BansheeEngine
 		}
 	}
 
-	void RenderTexture::copyToMemory(PixelData &dst, FrameBuffer buffer)
+	void RenderTextureCore::copyToMemory(PixelData &dst, FrameBuffer buffer)
 	{
 		throw std::exception("The method or operation is not implemented.");
 	}
+
+	RenderTexture* RenderTextureCore::getNonCore() const
+	{
+		return static_cast<RenderTexture*>(mParent);
+	}
+
+	RenderTexturePtr RenderTexture::create(TextureType textureType, UINT32 width, UINT32 height, 
+		PixelFormat format, bool hwGamma, UINT32 multisampleCount, const String& multisampleHint, 
+		bool createDepth, PixelFormat depthStencilFormat)
+	{
+		return TextureManager::instance().createRenderTexture(textureType, width, height, format, hwGamma, 
+			multisampleCount, multisampleHint, createDepth, depthStencilFormat);
+	}
+
+	const RenderTextureProperties& RenderTexture::getProperties() const 
+	{ 
+		THROW_IF_CORE_THREAD;
+
+		return static_cast<const RenderTextureProperties&>(RenderTarget::getProperties()); 
+	}
+
+	RenderTextureCore* RenderTexture::getCore() const 
+	{ 
+		return static_cast<RenderTextureCore*>(mCore); 
+	}
+
+	void RenderTexture::initialize(const RENDER_TEXTURE_DESC& desc)
+	{
+		mColorSurfaceDesc = desc.colorSurface;
+		mDepthStencilSurfaceDesc = desc.depthStencilSurface;
+
+		TexturePtr texture = desc.colorSurface.texture;
+
+		mProperties = createProperties();
+		RenderTextureProperties* properties = static_cast<RenderTextureProperties*>(mProperties);
+		if (texture != nullptr)
+		{
+			properties->mWidth = texture->getWidth();
+			properties->mHeight = texture->getHeight();
+			properties->mColorDepth = BansheeEngine::PixelUtil::getNumElemBits(texture->getFormat());
+			properties->mHwGamma = texture->isHardwareGammaEnabled();
+			properties->mMultisampleCount = texture->getMultisampleCount();
+			properties->mMultisampleHint = texture->getMultisampleHint();
+		}
+
+		properties->mActive = true;
+		properties->mIsWindow = false;
+		properties->mRequiresTextureFlipping = requiresTextureFlipping();
+
+		// Create non-persistent resource handles for the used textures (we only need them because a lot of the code accepts only handles,
+		// since they're non persistent they don't really have any benefit over shared pointers)
+		if (desc.colorSurface.texture != nullptr)
+			mBindableColorTex = gResources()._createResourceHandle(desc.colorSurface.texture);
+
+		if (desc.depthStencilSurface.texture != nullptr)
+			mBindableDepthStencilTex = gResources()._createResourceHandle(desc.depthStencilSurface.texture);
+
+		RenderTarget::initialize();
+	}
+
+	RenderTargetCore* RenderTexture::createCore()
+	{
+		RenderTextureProperties* coreProperties = bs_new<RenderTextureProperties>();
+		RenderTextureProperties* myProperties = static_cast<RenderTextureProperties*>(mProperties);
+
+		*coreProperties = *myProperties;
+
+		return createCore(coreProperties, mColorSurfaceDesc, mDepthStencilSurfaceDesc);
+	}
 }

+ 67 - 27
BansheeCore/Source/BsRenderWindow.cpp

@@ -6,52 +6,70 @@
 
 namespace BansheeEngine 
 {
-    RenderWindow::RenderWindow(const RENDER_WINDOW_DESC& desc)
-		: RenderTarget(), mIsFullScreen(false), mDesc(desc), mHasFocus(false), mLeft(0), mTop(0), mHidden(false)
-    {
-		mWidth = desc.videoMode.getWidth();
-		mHeight = desc.videoMode.getHeight();
-		mHwGamma = desc.gamma;
-		mVSync = desc.vsync;
-		mMultisampleCount = desc.multisampleCount;
-		mLeft = desc.left; 
-		mTop = desc.top;
-		mIsFullScreen = desc.fullscreen;
-		mHidden = desc.hidden;
-    }
-
-	RenderWindow::~RenderWindow() 
+	RenderWindowCore::RenderWindowCore(RenderWindow* parent, RenderWindowProperties* properties)
+		:RenderTargetCore(parent, properties)
 	{
-		
+
 	}
 
-	void RenderWindow::setHidden(bool hidden)
+	void RenderWindowCore::setHidden(bool hidden)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 	}
 
-    bool RenderWindow::isFullScreen(void) const
-    {
-        return mIsFullScreen;
-    }
-
-	void RenderWindow::_windowMovedOrResized()
+	void RenderWindowCore::_windowMovedOrResized()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 	}
 
-	void RenderWindow::_windowFocusReceived()
+	void RenderWindowCore::_windowFocusReceived()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		mHasFocus = true;
+		RenderWindowProperties* properties = static_cast<RenderWindowProperties*>(mProperties);
+		properties->mHasFocus = true;
+
+		markCoreDirty();
 	}
 
-	void RenderWindow::_windowFocusLost()
+	void RenderWindowCore::_windowFocusLost()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		mHasFocus = false;
+		RenderWindowProperties* properties = static_cast<RenderWindowProperties*>(mProperties);
+		properties->mHasFocus = false;
+
+		markCoreDirty();
+	}
+
+	RenderWindow* RenderWindowCore::getNonCore() const 
+	{ 
+		return static_cast<RenderWindow*>(mParent); 
+	}
+
+	void RenderWindow::initialize(const RENDER_WINDOW_DESC& desc)
+	{
+		mDesc = desc;
+
+		mProperties = createProperties();
+		RenderWindowProperties* properties = static_cast<RenderWindowProperties*>(mProperties);
+
+		properties->mWidth = desc.videoMode.getWidth();
+		properties->mHeight = desc.videoMode.getHeight();
+		properties->mHwGamma = desc.gamma;
+		properties->mVSync = desc.vsync;
+		properties->mVSyncInterval = desc.vsyncInterval;
+		properties->mMultisampleCount = desc.multisampleCount;
+		properties->mMultisampleHint = desc.multisampleHint;
+		properties->mLeft = desc.left;
+		properties->mTop = desc.top;
+		properties->mIsFullScreen = desc.fullscreen;
+		properties->mHidden = desc.hidden;
+		properties->mIsModal = desc.modal;
+		properties->mIsWindow = true;
+		properties->mRequiresTextureFlipping = requiresTextureFlipping();
+
+		RenderTarget::initialize();
 	}
 
 	void RenderWindow::destroy()
@@ -63,6 +81,28 @@ namespace BansheeEngine
 		RenderTarget::destroy();
 	}
 
+	const RenderWindowProperties& RenderWindow::getProperties() const
+	{
+		THROW_IF_CORE_THREAD;
+
+		return static_cast<const RenderWindowProperties&>(RenderTarget::getProperties());
+	}
+
+	RenderWindowCore* RenderWindow::getCore() const
+	{
+		return static_cast<RenderWindowCore*>(mCore);
+	}
+
+	RenderTargetCore* RenderWindow::createCore()
+	{
+		RenderWindowProperties* coreProperties = bs_new<RenderWindowProperties>();
+		RenderWindowProperties* myProperties = static_cast<RenderWindowProperties*>(mProperties);
+
+		*coreProperties = *myProperties;
+
+		return createCore(coreProperties, mDesc);
+	}
+
 	RenderWindowPtr RenderWindow::create(RENDER_WINDOW_DESC& desc, RenderWindowPtr parentWindow)
 	{
 		return RenderWindowManager::instance().create(desc, parentWindow);

+ 8 - 8
BansheeCore/Source/BsRenderWindowManager.cpp

@@ -17,7 +17,7 @@ namespace BansheeEngine
 	{
 		RenderWindowPtr renderWindow = createImpl(desc, parentWindow);
 		renderWindow->_setThisPtr(renderWindow);
-		renderWindow->initialize();
+		renderWindow->initialize(desc);
 
 		{
 			BS_LOCK_MUTEX(mWindowMutex);
@@ -47,15 +47,15 @@ namespace BansheeEngine
 		}
 	}
 
-	void RenderWindowManager::windowFocusReceived(RenderWindow* window)
+	void RenderWindowManager::windowFocusReceived(RenderWindowCore* window)
 	{
 		window->_windowFocusReceived();
 
 		BS_LOCK_MUTEX(mWindowMutex);
-		mNewWindowInFocus = window;
+		mNewWindowInFocus = window->getNonCore();
 	}
 
-	void RenderWindowManager::windowFocusLost(RenderWindow* window)
+	void RenderWindowManager::windowFocusLost(RenderWindowCore* window)
 	{
 		window->_windowFocusLost();
 
@@ -63,13 +63,13 @@ namespace BansheeEngine
 		mNewWindowInFocus = nullptr;
 	}
 
-	void RenderWindowManager::windowMovedOrResized(RenderWindow* window)
+	void RenderWindowManager::windowMovedOrResized(RenderWindowCore* window)
 	{
 		bool isValidWindow = false;
 		{
 			BS_LOCK_MUTEX(mWindowMutex);
 
-			isValidWindow = std::find(begin(mCreatedWindows), end(mCreatedWindows), window) != mCreatedWindows.end();
+			isValidWindow = std::find(begin(mCreatedWindows), end(mCreatedWindows), window->getNonCore()) != mCreatedWindows.end();
 		}
 
 		if(!isValidWindow)
@@ -79,10 +79,10 @@ namespace BansheeEngine
 
 		BS_LOCK_MUTEX(mWindowMutex);
 
-		auto iterFind = std::find(begin(mMovedOrResizedWindows), end(mMovedOrResizedWindows), window);
+		auto iterFind = std::find(begin(mMovedOrResizedWindows), end(mMovedOrResizedWindows), window->getNonCore());
 
 		if(iterFind == end(mMovedOrResizedWindows))
-			mMovedOrResizedWindows.push_back(window);
+			mMovedOrResizedWindows.push_back(window->getNonCore());
 	}
 
 	void RenderWindowManager::_update()

+ 4 - 0
BansheeCore/Source/BsTexture.cpp

@@ -222,6 +222,8 @@ namespace BansheeEngine
 
 	TextureViewPtr Texture::requestView(TexturePtr texture, UINT32 mostDetailMip, UINT32 numMips, UINT32 firstArraySlice, UINT32 numArraySlices, GpuViewUsage usage)
 	{
+		THROW_IF_NOT_CORE_THREAD;
+
 		assert(texture != nullptr);
 
 		TEXTURE_VIEW_DESC key;
@@ -247,6 +249,8 @@ namespace BansheeEngine
 
 	void Texture::releaseView(TextureViewPtr view)
 	{
+		THROW_IF_NOT_CORE_THREAD;
+
 		assert(view != nullptr);
 
 		TexturePtr texture = view->getTexture();

+ 6 - 6
BansheeCore/Source/BsViewport.cpp

@@ -39,8 +39,8 @@ namespace BansheeEngine
 
 	RectI Viewport::getArea() const
 	{
-		float width = (float)mTarget->getWidth();
-		float height = (float)mTarget->getHeight();
+		float width = (float)mTarget->getProperties().getWidth();
+		float height = (float)mTarget->getProperties().getHeight();
 		
 		RectI area;
 		area.x = (int)(mNormArea.x * width);
@@ -71,22 +71,22 @@ namespace BansheeEngine
 
 	INT32 Viewport::getX() const 
 	{ 
-		return (INT32)(mNormArea.x * mTarget->getWidth());
+		return (INT32)(mNormArea.x * mTarget->getProperties().getWidth());
 	}
 
 	INT32 Viewport::getY() const 
 	{ 
-		return (INT32)(mNormArea.y * mTarget->getHeight());
+		return (INT32)(mNormArea.y * mTarget->getProperties().getHeight());
 	}
 
 	INT32 Viewport::getWidth() const 
 	{ 
-		return (INT32)(mNormArea.width * mTarget->getWidth());
+		return (INT32)(mNormArea.width * mTarget->getProperties().getWidth());
 	}
 
 	INT32 Viewport::getHeight() const 
 	{ 
-		return (INT32)(mNormArea.height * mTarget->getHeight());
+		return (INT32)(mNormArea.height * mTarget->getProperties().getHeight());
 	}
 
 	Viewport Viewport::clone()

+ 14 - 14
BansheeCore/Source/Win32/BsPlatformImpl.cpp

@@ -19,16 +19,16 @@ namespace BansheeEngine
 	Event<void(float)> Platform::onMouseWheelScrolled;
 	Event<void(UINT32)> Platform::onCharInput;
 
-	Event<void(RenderWindow*)> Platform::onWindowFocusReceived;
-	Event<void(RenderWindow*)> Platform::onWindowFocusLost;
-	Event<void(RenderWindow*)> Platform::onWindowMovedOrResized;
+	Event<void(RenderWindowCore*)> Platform::onWindowFocusReceived;
+	Event<void(RenderWindowCore*)> Platform::onWindowFocusLost;
+	Event<void(RenderWindowCore*)> Platform::onWindowMovedOrResized;
 	Event<void()> Platform::onMouseCaptureChanged;
 
-	Map<const RenderWindow*, WindowNonClientAreaData> Platform::mNonClientAreas;
+	Map<const RenderWindowCore*, WindowNonClientAreaData> Platform::mNonClientAreas;
 	bool Platform::mIsTrackingMouse = false;
-	Vector<RenderWindow*> Platform::mMouseLeftWindows;
+	Vector<RenderWindowCore*> Platform::mMouseLeftWindows;
 
-	Stack<RenderWindow*> Platform::mModalWindowStack;
+	Stack<RenderWindowCore*> Platform::mModalWindowStack;
 
 	NativeDropTargetData Platform::mDropTargets;
 
@@ -263,21 +263,21 @@ namespace BansheeEngine
 	{
 		BS_LOCK_MUTEX(mSync);
 
-		mNonClientAreas[&window].moveAreas = nonClientAreas;
+		mNonClientAreas[window.getCore()].moveAreas = nonClientAreas;
 	}
 
 	void Platform::setResizeNonClientAreas(const RenderWindow& window, const Vector<NonClientResizeArea>& nonClientAreas)
 	{
 		BS_LOCK_MUTEX(mSync);
 
-		mNonClientAreas[&window].resizeAreas = nonClientAreas;
+		mNonClientAreas[window.getCore()].resizeAreas = nonClientAreas;
 	}
 
 	void Platform::resetNonClientAreas(const RenderWindow& window)
 	{
 		BS_LOCK_MUTEX(mSync);
 
-		auto iterFind = mNonClientAreas.find(&window);
+		auto iterFind = mNonClientAreas.find(window.getCore());
 
 		if(iterFind != end(mNonClientAreas))
 			mNonClientAreas.erase(iterFind);
@@ -453,7 +453,7 @@ namespace BansheeEngine
 
 	void Platform::_update()
 	{
-		Vector<RenderWindow*> windowsCopy;
+		Vector<RenderWindowCore*> windowsCopy;
 		{
 			BS_LOCK_MUTEX(mSync);
 
@@ -464,7 +464,7 @@ namespace BansheeEngine
 		for(auto& window : windowsCopy)
 		{
 			if(!onMouseLeftWindow.empty())
-				onMouseLeftWindow(window);
+				onMouseLeftWindow(window->getNonCore());
 		}
 
 		for(auto& dropTarget : mDropTargets.data->dropTargetsPerWindow)
@@ -525,19 +525,19 @@ namespace BansheeEngine
 		mRequiresShutDown = true;
 	}
 
-	void Platform::windowFocusReceived(RenderWindow* window)
+	void Platform::windowFocusReceived(RenderWindowCore* window)
 	{
 		if(!onWindowFocusReceived.empty())
 			onWindowFocusReceived(window);
 	}
 
-	void Platform::windowFocusLost(RenderWindow* window)
+	void Platform::windowFocusLost(RenderWindowCore* window)
 	{
 		if(!onWindowFocusLost.empty())
 			onWindowFocusLost(window);
 	}
 	
-	void Platform::windowMovedOrResized(RenderWindow* window)
+	void Platform::windowMovedOrResized(RenderWindowCore* window)
 	{
 		if(!onWindowMovedOrResized.empty())
 			onWindowMovedOrResized(window);

+ 10 - 10
BansheeCore/Source/Win32/BsPlatformWndProc.cpp

@@ -16,12 +16,12 @@ namespace BansheeEngine
 		{	// Store pointer to Win32Window in user data area
 			SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)(((LPCREATESTRUCT)lParam)->lpCreateParams));
 
-			RenderWindow* newWindow = (RenderWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
-			if(newWindow->isModal())
+			RenderWindowCore* newWindow = (RenderWindowCore*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+			if(newWindow->getProperties().isModal())
 			{
 				if(!mModalWindowStack.empty())
 				{
-					RenderWindow* curModalWindow = mModalWindowStack.top();
+					RenderWindowCore* curModalWindow = mModalWindowStack.top();
 
 					HWND curHwnd;
 					curModalWindow->getCustomAttribute("WINDOW", &curHwnd);
@@ -32,7 +32,7 @@ namespace BansheeEngine
 					Vector<RenderWindow*> renderWindows = RenderWindowManager::instance().getRenderWindows();
 					for(auto& renderWindow : renderWindows)
 					{
-						if(renderWindow == newWindow)
+						if(renderWindow->getCore() == newWindow)
 							continue;
 
 						HWND curHwnd;
@@ -49,7 +49,7 @@ namespace BansheeEngine
 
 		// look up window instance
 		// note: it is possible to get a WM_SIZE before WM_CREATE
-		RenderWindow* win = (RenderWindow*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+		RenderWindowCore* win = (RenderWindowCore*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
 		if (!win)
 			return DefWindowProc(hWnd, uMsg, wParam, lParam);
 
@@ -74,11 +74,11 @@ namespace BansheeEngine
 					}
 					else // Possibly some other window was closed somehow, see if it was modal and remove from stack if it is
 					{
-						Stack<RenderWindow*> newStack;
+						Stack<RenderWindowCore*> newStack;
 
 						while(!mModalWindowStack.empty())
 						{
-							RenderWindow* curWindow = mModalWindowStack.top();
+							RenderWindowCore* curWindow = mModalWindowStack.top();
 							mModalWindowStack.pop();
 
 							if(curWindow == win)
@@ -92,7 +92,7 @@ namespace BansheeEngine
 
 					if(!mModalWindowStack.empty()) // Enable next modal window
 					{
-						RenderWindow* curModalWindow = mModalWindowStack.top();
+						RenderWindowCore* curModalWindow = mModalWindowStack.top();
 
 						HWND curHwnd;
 						curModalWindow->getCustomAttribute("WINDOW", &curHwnd);
@@ -117,14 +117,14 @@ namespace BansheeEngine
 			}
 		case WM_SETFOCUS:
 			{
-				if(!win->hasFocus())
+				if (!win->getProperties().hasFocus())
 					windowFocusReceived(win);
 
 				break;
 			}
 		case WM_KILLFOCUS:
 			{
-				if(win->hasFocus())
+				if (win->getProperties().hasFocus())
 					windowFocusLost(win);
 
 				break;

+ 33 - 9
BansheeD3D11RenderSystem/Include/BsD3D11MultiRenderTexture.h

@@ -5,26 +5,50 @@
 
 namespace BansheeEngine
 {
+	class D3D11MultiRenderTexture;
+
+	/**
+	 * @brief	DirectX 11 implementation of a render texture with multiple color surfaces.
+	 *
+	 * @note	Core thread only.
+	 */
+	class BS_D3D11_EXPORT D3D11MultiRenderTextureCore : public MultiRenderTextureCore
+	{
+	public:
+		D3D11MultiRenderTextureCore(D3D11MultiRenderTexture* parent, MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc);
+		virtual ~D3D11MultiRenderTextureCore();
+		
+		/**
+		 * @copydoc	MultiRenderTextureCore::getCustomAttribute
+		 */
+		void getCustomAttribute(const String& name, void* pData) const;
+	protected:
+		friend class D3D11MultiRenderTexture;
+	};
+
 	/**
 	 * @brief	DirectX 11 implementation of a render texture with multiple color surfaces.
+	 *
+	 * @note	Sim thread only.
 	 */
 	class BS_D3D11_EXPORT D3D11MultiRenderTexture : public MultiRenderTexture
 	{
 	public:
-		virtual ~D3D11MultiRenderTexture();
+		virtual ~D3D11MultiRenderTexture() { }
+
+	protected:
+		friend class D3D11TextureManager;
+
+		D3D11MultiRenderTexture() { }
 
 		/**
-		 * @copydoc	MultiRenderTexture::requiresTextureFlipping
+		 * @copydoc	MultiRenderTexture::createProperties
 		 */
-		bool requiresTextureFlipping() const { return false; }
+		virtual RenderTargetProperties* createProperties() const;
 
 		/**
-		 * @copydoc	MultiRenderTexture::getCustomAttribute
+		 * @copydoc	MultiRenderTexture::createCore
 		 */
-		void getCustomAttribute(const String& name, void* pData) const;
-	protected:
-		friend class D3D11TextureManager;
-
-		D3D11MultiRenderTexture();
+		virtual MultiRenderTextureCore* createCore(MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc);
 	};
 }

+ 35 - 8
BansheeD3D11RenderSystem/Include/BsD3D11RenderTexture.h

@@ -6,27 +6,54 @@
 
 namespace BansheeEngine
 {
+	class D3D11RenderTexture;
+
 	/**
 	 * @brief	DirectX 11 implementation of a render texture.
+	 *
+	 * @note	Core thread only.
 	 */
-	class D3D11RenderTexture : public RenderTexture
+	class D3D11RenderTextureCore : public RenderTextureCore
 	{
 	public:
-		virtual ~D3D11RenderTexture();
+		D3D11RenderTextureCore(D3D11RenderTexture* parent, RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+			const RENDER_SURFACE_DESC& depthStencilSurfaceDesc);
 
-		/**
-		 * @copydoc	RenderTexture::requiresTextureFlipping
-		 */
-		bool requiresTextureFlipping() const { return false; }
+		virtual ~D3D11RenderTextureCore() { }
 
 		/**
-		 * @copydoc	RenderTexture::getCustomAttribute
+		 * @copydoc	RenderTextureCore::getCustomAttribute
 		 */
 		void getCustomAttribute(const String& name, void* pData) const;
 
+	protected:
+		friend class D3D11RenderTexture;
+	};
+
+	/**
+	 * @brief	DirectX 11 implementation of a render texture.
+	 *
+	 * @note	Sim thread only.
+	 */
+	class D3D11RenderTexture : public RenderTexture
+	{
+	public:
+		virtual ~D3D11RenderTexture() { }
+
 	protected:
 		friend class D3D11TextureManager;
 
-		D3D11RenderTexture();
+		D3D11RenderTexture() { }
+
+		/**
+		 * @copydoc	RenderTexture::createProperties
+		 */
+		virtual RenderTargetProperties* createProperties() const;
+
+		/**
+		 * @copydoc	RenderTexture::createCore
+		 */
+		virtual RenderTextureCore* createCore(RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+			const RENDER_SURFACE_DESC& depthStencilSurfaceDesc);
 	};
 }

+ 93 - 56
BansheeD3D11RenderSystem/Include/BsD3D11RenderWindow.h

@@ -5,91 +5,89 @@
 
 namespace BansheeEngine
 {
+	class D3D11RenderWindow;
+
+	/**
+	 * @brief	Contains various properties that describe a render window.
+	 */
+	class BS_D3D11_EXPORT D3D11RenderWindowProperties : public RenderWindowProperties
+	{
+	public:
+		virtual ~D3D11RenderWindowProperties() { }
+
+	private:
+		friend class D3D11RenderWindowCore;
+		friend class D3D11RenderWindow;
+	};
+
 	/**
 	 * @brief	Render window implementation for Windows and DirectX 11.
+	 *
+	 * @note	Core thread only.
 	 */
-	class BS_D3D11_EXPORT D3D11RenderWindow : public RenderWindow
+	class BS_D3D11_EXPORT D3D11RenderWindowCore : public RenderWindowCore
 	{
 	public:
-		~D3D11RenderWindow();
+		/**
+		 * @copydoc	RenderWindowCore::RenderWindowCore
+		 */
+		D3D11RenderWindowCore(D3D11RenderWindow* parent, RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc,
+			D3D11Device& device, IDXGIFactory* DXGIFactory);
+
+		~D3D11RenderWindowCore();
 
 		/**
-		 * @copydoc RenderWindow::move
+		 * @copydoc RenderWindowCore::move
 		 */
 		void move(INT32 left, INT32 top);
 
 		/**
-		 * @copydoc RenderWindow::resize
+		 * @copydoc RenderWindowCore::resize
 		 */
 		void resize(UINT32 width, UINT32 height);
 
 		/**
-		 * @copydoc RenderWindow::setHidden
+		 * @copydoc RenderWindowCore::setHidden
 		 */
 		void setHidden(bool hidden);
 
 		/**
-		 * @copydoc RenderWindow::setActive
+		 * @copydoc RenderWindowCore::setActive
 		 */
 		void setActive(bool state);
 
 		/**
-		 * @copydoc RenderWindow::setFullscreen(UINT32, UINT32, float, UINT32)
+		 * @copydoc RenderWindowCore::setFullscreen(UINT32, UINT32, float, UINT32)
 		 */
 		void setFullscreen(UINT32 width, UINT32 height, float refreshRate = 60.0f, UINT32 monitorIdx = 0);
 
 		/**
-		 * @copydoc RenderWindow::setFullscreen(const VideoMode&)
+		 * @copydoc RenderWindowCore::setFullscreen(const VideoMode&)
 		 */
 		void setFullscreen(const VideoMode& mode);
 
 		/**
-		* @copydoc RenderWindow::setWindowed
+		* @copydoc RenderWindowCore::setWindowed
 		*/
 		void setWindowed(UINT32 width, UINT32 height);
 
 		/**
-		 * @copydoc RenderWindow::copyContentsToMemory
+		 * @copydoc RenderWindowCore::copyContentsToMemory
 		 */
 		void copyToMemory(PixelData &dst, FrameBuffer buffer);
 
 		/**
-		 * @copydoc RenderWindow::swapBuffers
+		 * @copydoc RenderWindowCore::swapBuffers
 		 */
 		void swapBuffers();
 
 		/**
-		 * @copydoc RenderWindow::isClosed
-		 */
-		bool isClosed() const { return mClosed; }
-
-		/**
-		 * @copydoc RenderWindow::isHidden
-		 */
-		bool isHidden() const { return mHidden; }
-
-		/**
-		 * @copydoc RenderWindow::screenToWindowPos
-		 */
-		Vector2I screenToWindowPos(const Vector2I& screenPos) const;
-
-		/**
-		 * @copydoc RenderWindow::windowToScreenPos
-		 */
-		Vector2I windowToScreenPos(const Vector2I& windowPos) const;
-
-		/**
-		 * @copydoc RenderWindow::getCustomAttribute
+		 * @copydoc RenderWindowCore::getCustomAttribute
 		 */
 		void getCustomAttribute(const String& name, void* pData) const;
 
 		/**
-		 * @copydoc RenderWindow::requiresTextureFlipping
-		 */
-		bool requiresTextureFlipping() const { return false; }
-
-		/**
-		 * @copydoc	RenderWindow::_windowMovedOrResized
+		 * @copydoc	RenderWindowCore::_windowMovedOrResized
 		 */
 		void _windowMovedOrResized();
 
@@ -104,12 +102,7 @@ namespace BansheeEngine
 		HWND _getWindowHandle() const { return mHWnd; }
 
 	protected:
-		friend class D3D11RenderWindowManager;
-
-		/**
-		 * @copydoc	RenderWindow::RenderWindow
-		 */
-		D3D11RenderWindow(const RENDER_WINDOW_DESC& desc, D3D11Device& device, IDXGIFactory* DXGIFactory);
+		friend class D3D11RenderWindow;
 
 		/**
 		 * @brief	Creates internal resources dependent on window size.
@@ -135,27 +128,15 @@ namespace BansheeEngine
 		 * @brief	Resizes all buffers attached to the swap chain to the specified size.
 		 */
 		void resizeSwapChainBuffers(UINT32 width, UINT32 height);
-		
-		/**
-		 * @copydoc RenderWindow::initialize_internal
-		 */
-		void initialize_internal();
 
-		/**
-		 * @copydoc RenderWindow::destroy_internal
-		 */
-		void destroy_internal();
 	protected:
 		D3D11Device& mDevice;
 		IDXGIFactory* mDXGIFactory;
 		bool mIsExternal;
 		bool mSizing;
-		bool mClosed;
 		bool mIsChild;
 
 		DXGI_SAMPLE_DESC mMultisampleType;
-		bool mVSync;
-		UINT32 mVSyncInterval;
 		UINT32 mRefreshRateNumerator;
 		UINT32 mRefreshRateDenominator;
 
@@ -169,4 +150,60 @@ namespace BansheeEngine
 
 		HWND mHWnd;
 	};
+
+	/**
+	 * @brief	Render window implementation for Windows and DirectX 11.
+	 *
+	 * @note	Sim thread only.
+	 */
+	class BS_D3D11_EXPORT D3D11RenderWindow : public RenderWindow
+	{
+	public:
+		~D3D11RenderWindow() { }
+
+		/**
+		 * @copydoc RenderWindow::requiresTextureFlipping
+		 */
+		bool requiresTextureFlipping() const { return false; }
+
+		/**
+		 * @copydoc RenderWindow::getCustomAttribute
+		 */
+		void getCustomAttribute(const String& name, void* pData) const;
+
+		/**
+		 * @copydoc RenderWindow::screenToWindowPos
+		 */
+		Vector2I screenToWindowPos(const Vector2I& screenPos) const;
+
+		/**
+		 * @copydoc RenderWindow::windowToScreenPos
+		 */
+		Vector2I windowToScreenPos(const Vector2I& windowPos) const;
+
+	protected:
+		friend class D3D11RenderWindowManager;
+
+		D3D11RenderWindow(D3D11Device& device, IDXGIFactory* DXGIFactory);
+
+		/**
+		 * @copydoc	RenderWindow::initialize_internal
+		 */
+		virtual void initialize_internal();
+
+		/**
+		 * @copydoc	RenderWindow::createProperties
+		 */
+		virtual RenderTargetProperties* createProperties() const;
+
+		/**
+		 * @copydoc	RenderWindow::createCore
+		 */
+		virtual RenderWindowCore* createCore(RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc);
+
+	private:
+		D3D11Device& mDevice;
+		IDXGIFactory* mDXGIFactory;
+		HWND mHWnd;
+	};
 }

+ 15 - 4
BansheeD3D11RenderSystem/Source/BsD3D11MultiRenderTexture.cpp

@@ -5,18 +5,19 @@
 
 namespace BansheeEngine
 {
-	D3D11MultiRenderTexture::D3D11MultiRenderTexture()
-		:MultiRenderTexture()
+	D3D11MultiRenderTextureCore::D3D11MultiRenderTextureCore(D3D11MultiRenderTexture* parent, 
+		MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc)
+		:MultiRenderTextureCore(parent, properties, desc)
 	{
 
 	}
 
-	D3D11MultiRenderTexture::~D3D11MultiRenderTexture()
+	D3D11MultiRenderTextureCore::~D3D11MultiRenderTextureCore()
 	{
 
 	}
 
-	void D3D11MultiRenderTexture::getCustomAttribute(const String& name, void* pData) const
+	void D3D11MultiRenderTextureCore::getCustomAttribute(const String& name, void* pData) const
 	{
 		if(name == "RTV")
 		{
@@ -38,4 +39,14 @@ namespace BansheeEngine
 			return;
 		}
 	}
+
+	RenderTargetProperties* D3D11MultiRenderTexture::createProperties() const
+	{
+		return bs_new<MultiRenderTextureProperties>();
+	}
+
+	MultiRenderTextureCore* D3D11MultiRenderTexture::createCore(MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc)
+	{
+		return bs_new<D3D11MultiRenderTextureCore>(this, properties, desc);
+	}
 }

+ 14 - 10
BansheeD3D11RenderSystem/Source/BsD3D11RenderSystem.cpp

@@ -320,16 +320,18 @@ namespace BansheeEngine
 		RenderTargetPtr target = vp.getTarget();
 		setRenderTarget(target);
 
+		const RenderTargetProperties& rtProps = target->getCore()->getProperties();
+
 		// Set viewport dimensions
-		mViewport.TopLeftX = (FLOAT)vp.getX();
-		mViewport.TopLeftY = (FLOAT)vp.getY();
-		mViewport.Width = (FLOAT)vp.getWidth();
-		mViewport.Height = (FLOAT)vp.getHeight();
+		mViewport.TopLeftX = (FLOAT)(rtProps.getWidth() * vp.getNormalizedX());
+		mViewport.TopLeftY = (FLOAT)(rtProps.getHeight() * vp.getNormalizedY());
+		mViewport.Width = (FLOAT)(rtProps.getWidth() * vp.getNormalizedWidth());
+		mViewport.Height = (FLOAT)(rtProps.getHeight() * vp.getNormalizedHeight());
 
 		if (target->requiresTextureFlipping())
 		{
 			// Convert "top-left" to "bottom-left"
-			mViewport.TopLeftY = target->getHeight() - mViewport.Height - mViewport.TopLeftY;
+			mViewport.TopLeftY = target->getCore()->getProperties().getHeight() - mViewport.Height - mViewport.TopLeftY;
 		}
 
 		mViewport.MinDepth = 0.0f;
@@ -617,10 +619,12 @@ namespace BansheeEngine
 		if(mActiveRenderTarget == nullptr)
 			return;
 
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getCore()->getProperties();
+
 		RectI clearArea((int)mViewport.TopLeftX, (int)mViewport.TopLeftY, (int)mViewport.Width, (int)mViewport.Height);
 
 		bool clearEntireTarget = clearArea.width == 0 || clearArea.height == 0;
-		clearEntireTarget |= (clearArea.x == 0 && clearArea.y == 0 && clearArea.width == mActiveRenderTarget->getWidth() && clearArea.height == mActiveRenderTarget->getHeight());
+		clearEntireTarget |= (clearArea.x == 0 && clearArea.y == 0 && clearArea.width == rtProps.getWidth() && clearArea.height == rtProps.getHeight());
 
 		if (!clearEntireTarget)
 		{
@@ -646,7 +650,7 @@ namespace BansheeEngine
 			ID3D11RenderTargetView** views = bs_newN<ID3D11RenderTargetView*, ScratchAlloc>(maxRenderTargets);
 			memset(views, 0, sizeof(ID3D11RenderTargetView*) * maxRenderTargets);
 
-			mActiveRenderTarget->getCustomAttribute("RTV", views);
+			mActiveRenderTarget->getCore()->getCustomAttribute("RTV", views);
 			if (!views[0])
 			{
 				bs_deleteN<ScratchAlloc>(views, maxRenderTargets);
@@ -672,7 +676,7 @@ namespace BansheeEngine
 		if((buffers & FBT_DEPTH) != 0 || (buffers & FBT_STENCIL) != 0)
 		{
 			ID3D11DepthStencilView* depthStencilView = nullptr;
-			mActiveRenderTarget->getCustomAttribute("DSV", &depthStencilView);
+			mActiveRenderTarget->getCore()->getCustomAttribute("DSV", &depthStencilView);
 
 			D3D11_CLEAR_FLAG clearFlag;
 
@@ -700,7 +704,7 @@ namespace BansheeEngine
 		UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
 		ID3D11RenderTargetView** views = bs_newN<ID3D11RenderTargetView*, ScratchAlloc>(maxRenderTargets);
 		memset(views, 0, sizeof(ID3D11RenderTargetView*) * maxRenderTargets);
-		target->getCustomAttribute("RTV", views);
+		target->getCore()->getCustomAttribute("RTV", views);
 		if (!views[0])
 		{
 			bs_deleteN<ScratchAlloc>(views, maxRenderTargets);
@@ -709,7 +713,7 @@ namespace BansheeEngine
 
 		// Retrieve depth stencil
 		ID3D11DepthStencilView* depthStencilView = nullptr;
-		target->getCustomAttribute("DSV", &depthStencilView);
+		target->getCore()->getCustomAttribute("DSV", &depthStencilView);
 
 		// Bind render targets
 		mDevice->getImmediateContext()->OMSetRenderTargets(maxRenderTargets, views, depthStencilView);

+ 16 - 10
BansheeD3D11RenderSystem/Source/BsD3D11RenderTexture.cpp

@@ -9,17 +9,12 @@
 
 namespace BansheeEngine
 {
-	D3D11RenderTexture::D3D11RenderTexture()
-		:RenderTexture()
-	{
-
-	}
-
-	D3D11RenderTexture::~D3D11RenderTexture()
-	{
-	}
+	D3D11RenderTextureCore::D3D11RenderTextureCore(D3D11RenderTexture* parent, RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+		const RENDER_SURFACE_DESC& depthStencilSurfaceDesc)
+		:RenderTextureCore(parent, properties, colorSurfaceDesc, depthStencilSurfaceDesc)
+	{ }
 
-	void D3D11RenderTexture::getCustomAttribute(const String& name, void* pData) const
+	void D3D11RenderTextureCore::getCustomAttribute(const String& name, void* pData) const
 	{
 		if(name == "RTV")
 		{
@@ -37,4 +32,15 @@ namespace BansheeEngine
 			return;
 		}
 	}
+
+	RenderTargetProperties* D3D11RenderTexture::createProperties() const
+	{
+		return bs_new<RenderTextureProperties>();
+	}
+
+	RenderTextureCore* D3D11RenderTexture::createCore(RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+		const RENDER_SURFACE_DESC& depthStencilSurfaceDesc)
+	{
+		return bs_new<D3D11RenderTextureCore>(this, properties, colorSurfaceDesc, depthStencilSurfaceDesc);
+	}
 }

+ 208 - 158
BansheeD3D11RenderSystem/Source/BsD3D11RenderWindow.cpp

@@ -15,56 +15,45 @@
 
 namespace BansheeEngine
 {
-	D3D11RenderWindow::D3D11RenderWindow(const RENDER_WINDOW_DESC& desc,D3D11Device& device, IDXGIFactory* DXGIFactory)
-		: RenderWindow(desc), mDevice(device), mDXGIFactory(DXGIFactory), mIsExternal(false), mSizing(false), 
-		mClosed(false), mRenderTargetView(nullptr), mBackBuffer(nullptr), mSwapChain(nullptr), mHWnd(0), 
+	D3D11RenderWindowCore::D3D11RenderWindowCore(D3D11RenderWindow* parent, RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc, D3D11Device& device, IDXGIFactory* DXGIFactory)
+		: RenderWindowCore(parent, properties), mDevice(device), mDXGIFactory(DXGIFactory), mIsExternal(false), mSizing(false),
+		 mRenderTargetView(nullptr), mBackBuffer(nullptr), mSwapChain(nullptr), mHWnd(0), 
 		mDepthStencilView(nullptr), mIsChild(false), mRefreshRateNumerator(0), mRefreshRateDenominator(0)
 	{
 		ZeroMemory(&mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
-	}
 
-	D3D11RenderWindow::~D3D11RenderWindow()
-	{
-	}
+		D3D11RenderWindowProperties* props = static_cast<D3D11RenderWindowProperties*>(mProperties);
 
-	void D3D11RenderWindow::initialize_internal()
-	{
 		mMultisampleType.Count = 1;
 		mMultisampleType.Quality = 0;
-		mMultisampleCount = 0;
-		mMultisampleHint = "";
-		mVSync = false;
-		mVSyncInterval = 1;
 		HWND parentHWnd = 0;
 		HWND externalHandle = 0;
-		
+
 
 		NameValuePairList::const_iterator opt;
-		opt = mDesc.platformSpecific.find("parentWindowHandle");
-		if(opt != mDesc.platformSpecific.end())
+		opt = desc.platformSpecific.find("parentWindowHandle");
+		if (opt != desc.platformSpecific.end())
 			parentHWnd = (HWND)parseUnsignedInt(opt->second);
 
-		opt = mDesc.platformSpecific.find("externalWindowHandle");
-		if(opt != mDesc.platformSpecific.end())
+		opt = desc.platformSpecific.find("externalWindowHandle");
+		if (opt != desc.platformSpecific.end())
 			externalHandle = (HWND)parseUnsignedInt(opt->second);
 
-		mName = mDesc.title;
+		props->mName = desc.title;
 		mIsChild = parentHWnd != 0;
-		mIsFullScreen = mDesc.fullscreen && !mIsChild;
-		mColorDepth = 32;
-		mWidth = mHeight = mLeft = mTop = 0;
+		props->mIsFullScreen = desc.fullscreen && !mIsChild;
+		props->mColorDepth = 32;
 
-		mActive = true;
-		mClosed = false;
+		props->mActive = true;
 
-		if (mDesc.videoMode.isCustom())
+		if (desc.videoMode.isCustom())
 		{
-			mRefreshRateNumerator = Math::roundToInt(mDesc.videoMode.getRefreshRate());
+			mRefreshRateNumerator = Math::roundToInt(desc.videoMode.getRefreshRate());
 			mRefreshRateDenominator = 1;
 		}
 		else
 		{
-			const D3D11VideoMode& d3d11videoMode = static_cast<const D3D11VideoMode&>(mDesc.videoMode);
+			const D3D11VideoMode& d3d11videoMode = static_cast<const D3D11VideoMode&>(desc.videoMode);
 			mRefreshRateNumerator = d3d11videoMode.getRefreshRateNumerator();
 			mRefreshRateDenominator = d3d11videoMode.getRefreshRateDenominator();
 		}
@@ -76,7 +65,7 @@ namespace BansheeEngine
 		UINT32 numOutputs = videoModeInfo.getNumOutputs();
 		if (numOutputs > 0)
 		{
-			UINT32 actualMonitorIdx = std::min(mDesc.videoMode.getOutputIdx(), numOutputs - 1);
+			UINT32 actualMonitorIdx = std::min(desc.videoMode.getOutputIdx(), numOutputs - 1);
 			outputInfo = static_cast<const D3D11VideoOutputInfo*>(&videoModeInfo.getOutputInfo(actualMonitorIdx));
 
 			DXGI_OUTPUT_DESC desc;
@@ -87,7 +76,7 @@ namespace BansheeEngine
 
 		if (!externalHandle)
 		{
-			DWORD dwStyle = (mHidden ? 0 : WS_VISIBLE) | WS_CLIPCHILDREN;
+			DWORD dwStyle = (getProperties().isHidden() ? 0 : WS_VISIBLE) | WS_CLIPCHILDREN;
 			DWORD dwStyleEx = 0;
 			RECT rc;
 			MONITORINFO monitorInfo;
@@ -98,8 +87,8 @@ namespace BansheeEngine
 				POINT windowAnchorPoint;
 
 				// Fill in anchor point.
-				windowAnchorPoint.x = mDesc.left;
-				windowAnchorPoint.y = mDesc.top;
+				windowAnchorPoint.x = desc.left;
+				windowAnchorPoint.y = desc.top;
 
 				// Get the nearest monitor to this window.
 				hMonitor = MonitorFromPoint(windowAnchorPoint, MONITOR_DEFAULTTOPRIMARY);
@@ -110,23 +99,22 @@ namespace BansheeEngine
 			monitorInfo.cbSize = sizeof(MONITORINFO);
 			GetMonitorInfo(hMonitor, &monitorInfo);
 
-
 			unsigned int winWidth, winHeight;
-			winWidth = mDesc.videoMode.getWidth();
-			winHeight = mDesc.videoMode.getHeight();
+			winWidth = desc.videoMode.getWidth();
+			winHeight = desc.videoMode.getHeight();
 
-			UINT32 left = mDesc.left;
-			UINT32 top = mDesc.top;
+			UINT32 left = desc.left;
+			UINT32 top = desc.top;
 
 			// No specified top left -> Center the window in the middle of the monitor
 			if (left == -1 || top == -1)
-			{				
-				int screenw = monitorInfo.rcWork.right  - monitorInfo.rcWork.left;
+			{
+				int screenw = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
 				int screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
 
 				// clamp window dimensions to screen size
-				int outerw = (int(winWidth) < screenw)? int(winWidth) : screenw;
-				int outerh = (int(winHeight) < screenh)? int(winHeight) : screenh;
+				int outerw = (int(winWidth) < screenw) ? int(winWidth) : screenw;
+				int outerh = (int(winHeight) < screenh) ? int(winHeight) : screenh;
 
 				if (left == -1)
 					left = monitorInfo.rcWork.left + (screenw - outerw) / 2;
@@ -144,62 +132,63 @@ namespace BansheeEngine
 				top += monitorInfo.rcWork.top;
 			}
 
-			mWidth = mDesc.videoMode.getWidth();
-			mHeight = mDesc.videoMode.getHeight();
-			mTop = top;
-			mLeft = left;
+			props->mWidth = desc.videoMode.getWidth();
+			props->mHeight = desc.videoMode.getHeight();
+			props->mTop = top;
+			props->mLeft = left;
 
-			if (!mDesc.fullscreen)
+			if (!desc.fullscreen)
 			{
 				if (parentHWnd)
 				{
-					if(mDesc.toolWindow)
+					if (desc.toolWindow)
 						dwStyleEx = WS_EX_TOOLWINDOW;
 					else
 						dwStyle |= WS_CHILD;
 				}
 
-				if (!parentHWnd || mDesc.toolWindow)
+				if (!parentHWnd || desc.toolWindow)
 				{
-					if (mDesc.border == WindowBorder::None)
+					if (desc.border == WindowBorder::None)
 						dwStyle |= WS_POPUP;
-					else if (mDesc.border == WindowBorder::Fixed)
+					else if (desc.border == WindowBorder::Fixed)
 						dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
 						WS_SYSMENU | WS_MINIMIZEBOX;
 					else
 						dwStyle |= WS_OVERLAPPEDWINDOW;
 				}
 
-				if (!mDesc.outerDimensions)
+				if (!desc.outerDimensions)
 				{
 					// Calculate window dimensions required
 					// to get the requested client area
-					SetRect(&rc, 0, 0, mWidth, mHeight);
+					SetRect(&rc, 0, 0, props->mWidth, props->mHeight);
 					AdjustWindowRect(&rc, dwStyle, false);
-					mWidth = rc.right - rc.left;
-					mHeight = rc.bottom - rc.top;
+					props->mWidth = rc.right - rc.left;
+					props->mHeight = rc.bottom - rc.top;
 
 					// Clamp width and height to the desktop dimensions
 					int screenw = GetSystemMetrics(SM_CXSCREEN);
 					int screenh = GetSystemMetrics(SM_CYSCREEN);
-					if ((int)mWidth > screenw)
-						mWidth = screenw;
-					if ((int)mHeight > screenh)
-						mHeight = screenh;
-					if (mLeft < 0)
-						mLeft = (screenw - mWidth) / 2;
-					if (mTop < 0)
-						mTop = (screenh - mHeight) / 2;
+					if ((int)props->mWidth > screenw)
+						props->mWidth = screenw;
+					if ((int)props->mHeight > screenh)
+						props->mHeight = screenh;
+					if (props->mLeft < 0)
+						props->mLeft = (screenw - props->mWidth) / 2;
+					if (props->mTop < 0)
+						props->mTop = (screenh - props->mHeight) / 2;
 				}
 			}
 			else
 			{
 				dwStyle |= WS_POPUP;
-				mTop = mLeft = 0;
+				props->mTop = 0;
+				props->mLeft = 0;
 			}
 
 			UINT classStyle = 0;
-			if (mDesc.enableDoubleClick)
+			if (desc.enableDoubleClick)
 				classStyle |= CS_DBLCLKS;
 
 			HINSTANCE hInst = NULL;
@@ -208,15 +197,15 @@ namespace BansheeEngine
 			// Allow 4 bytes of window data for D3D11RenderWindow pointer
 			WNDCLASS wc = { classStyle, PlatformWndProc::_win32WndProc, 0, 0, hInst,
 				LoadIcon(0, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW),
-				(HBRUSH)GetStockObject(BLACK_BRUSH), 0, "D3D11Wnd" };	
+				(HBRUSH)GetStockObject(BLACK_BRUSH), 0, "D3D11Wnd" };
 
 			RegisterClass(&wc);
 
 			// Create our main window
 			// Pass pointer to self
 			mIsExternal = false;
-			mHWnd = CreateWindowEx(dwStyleEx, "D3D11Wnd", mDesc.title.c_str(), dwStyle,
-				mLeft, mTop, mWidth, mHeight, parentHWnd, 0, hInst, this);
+			mHWnd = CreateWindowEx(dwStyleEx, "D3D11Wnd", desc.title.c_str(), dwStyle,
+				props->mLeft, props->mTop, props->mWidth, props->mHeight, parentHWnd, 0, hInst, this);
 		}
 		else
 		{
@@ -226,16 +215,16 @@ namespace BansheeEngine
 
 		RECT rc;
 		GetWindowRect(mHWnd, &rc);
-		mTop = rc.top;
-		mLeft = rc.left;
+		props->mTop = rc.top;
+		props->mLeft = rc.left;
 
 		GetClientRect(mHWnd, &rc);
-		mWidth = rc.right;
-		mHeight = rc.bottom;
+		props->mWidth = rc.right;
+		props->mHeight = rc.bottom;
 
 		createSwapChain();
 
-		if (mIsFullScreen)
+		if (getProperties().isFullScreen())
 		{
 			if (outputInfo != nullptr)
 				mSwapChain->SetFullscreenState(true, outputInfo->getDXGIOutput());
@@ -245,15 +234,15 @@ namespace BansheeEngine
 
 		createSizeDependedD3DResources();
 		mDXGIFactory->MakeWindowAssociation(mHWnd, NULL);
-		setHidden(mHidden);
-
-		RenderWindow::initialize_internal();
+		setHidden(getProperties().isHidden());
 	}
 
-	void D3D11RenderWindow::destroy_internal()
+	D3D11RenderWindowCore::~D3D11RenderWindowCore()
 	{
-		mActive = false;
-		mClosed = true;
+		D3D11RenderWindowProperties* properties = static_cast<D3D11RenderWindowProperties*>(mProperties);
+
+		properties->mActive = false;
+		markCoreDirty();
 
 		SAFE_RELEASE(mSwapChain);
 		BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_SwapChain);
@@ -263,7 +252,7 @@ namespace BansheeEngine
 			DestroyWindow(mHWnd);
 		}
 
-		if(mDepthStencilView != nullptr)
+		if (mDepthStencilView != nullptr)
 		{
 			Texture::releaseView(mDepthStencilView);
 			mDepthStencilView = nullptr;
@@ -272,65 +261,70 @@ namespace BansheeEngine
 		mHWnd = nullptr;
 
 		destroySizeDependedD3DResources();
-
-		RenderWindow::destroy_internal();
 	}
 
-	void D3D11RenderWindow::swapBuffers()
+	void D3D11RenderWindowCore::swapBuffers()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		if(mDevice.getD3D11Device() != nullptr)
 		{
-			HRESULT hr = mSwapChain->Present(mVSync ? mVSyncInterval : 0, 0);
+			HRESULT hr = mSwapChain->Present(getProperties().getVSync() ? getProperties().getVSyncInterval() : 0, 0);
 
 			if( FAILED(hr) )
 				BS_EXCEPT(RenderingAPIException, "Error Presenting surfaces");
 		}
 	}
 
-	void D3D11RenderWindow::move(INT32 top, INT32 left)
+	void D3D11RenderWindowCore::move(INT32 top, INT32 left)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if (mHWnd && !mIsFullScreen)
+		D3D11RenderWindowProperties* properties = static_cast<D3D11RenderWindowProperties*>(mProperties);
+
+		if (mHWnd && !properties->mIsFullScreen)
 		{
-			mTop = top;
-			mLeft = left;
+			properties->mTop = top;
+			properties->mLeft = left;
 
-			SetWindowPos(mHWnd, 0, top, left, 0, 0,
-				SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+			SetWindowPos(mHWnd, 0, top, left, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+			markCoreDirty();			
 		}
 	}
 
-	void D3D11RenderWindow::resize(UINT32 width, UINT32 height)
+	void D3D11RenderWindowCore::resize(UINT32 width, UINT32 height)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if (mHWnd && !mIsFullScreen)
+		D3D11RenderWindowProperties* properties = static_cast<D3D11RenderWindowProperties*>(mProperties);
+
+		if (mHWnd && !properties->mIsFullScreen)
 		{
-			mWidth = width;
-			mHeight = height;
+			properties->mWidth = width;
+			properties->mHeight = height;
 
 			RECT rc = { 0, 0, width, height };
 			AdjustWindowRect(&rc, GetWindowLong(mHWnd, GWL_STYLE), false);
 			width = rc.right - rc.left;
 			height = rc.bottom - rc.top;
-			SetWindowPos(mHWnd, 0, 0, 0, width, height,
-				SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+
+			SetWindowPos(mHWnd, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+			markCoreDirty();
 		}
 	}
 
-	void D3D11RenderWindow::setActive(bool state)
+	void D3D11RenderWindowCore::setActive(bool state)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
+		D3D11RenderWindowProperties* properties = static_cast<D3D11RenderWindowProperties*>(mProperties);
+
 		if (mHWnd && mSwapChain)
 		{
 			if (state)
 			{
 				ShowWindow(mHWnd, SW_RESTORE);
-				mSwapChain->SetFullscreenState(mIsFullScreen, nullptr);
+				mSwapChain->SetFullscreenState(properties->mIsFullScreen, nullptr);
 			}
 			else
 			{
@@ -339,14 +333,16 @@ namespace BansheeEngine
 			}
 		}
 
-		RenderWindow::setActive(state);
+		RenderWindowCore::setActive(state);
 	}
 
-	void D3D11RenderWindow::setHidden(bool hidden)
+	void D3D11RenderWindowCore::setHidden(bool hidden)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		mHidden = hidden;
+		D3D11RenderWindowProperties* properties = static_cast<D3D11RenderWindowProperties*>(mProperties);
+
+		properties->mHidden = hidden;
 		if (!mIsExternal)
 		{
 			if (hidden)
@@ -354,9 +350,11 @@ namespace BansheeEngine
 			else
 				ShowWindow(mHWnd, SW_SHOWNORMAL);
 		}
+
+		markCoreDirty();
 	}
 
-	void D3D11RenderWindow::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
+	void D3D11RenderWindowCore::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -387,15 +385,18 @@ namespace BansheeEngine
 
 		outputInfo.getDXGIOutput()->FindClosestMatchingMode(&modeDesc, &nearestMode, nullptr);
 
-		mIsFullScreen = true;
-		mWidth = width;
-		mHeight = height;
+		D3D11RenderWindowProperties* properties = static_cast<D3D11RenderWindowProperties*>(mProperties);
+		properties->mIsFullScreen = true;
+		properties->mWidth = width;
+		properties->mHeight = height;
 
 		mSwapChain->ResizeTarget(&nearestMode);
 		mSwapChain->SetFullscreenState(true, outputInfo.getDXGIOutput()); 
+
+		markCoreDirty();
 	}
 
-	void D3D11RenderWindow::setFullscreen(const VideoMode& mode)
+	void D3D11RenderWindowCore::setFullscreen(const VideoMode& mode)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -418,42 +419,48 @@ namespace BansheeEngine
 
 		const D3D11VideoMode& videoMode = static_cast<const D3D11VideoMode&>(mode);
 
-		mIsFullScreen = true;
-		mWidth = mode.getWidth();
-		mHeight = mode.getHeight();
+		D3D11RenderWindowProperties* properties = static_cast<D3D11RenderWindowProperties*>(mProperties);
+		properties->mIsFullScreen = true;
+		properties->mWidth = mode.getWidth();
+		properties->mHeight = mode.getHeight();
 
 		mSwapChain->ResizeTarget(&videoMode.getDXGIModeDesc());
 		mSwapChain->SetFullscreenState(true, outputInfo.getDXGIOutput());
+
+		markCoreDirty();
 	}
 
-	void D3D11RenderWindow::setWindowed(UINT32 width, UINT32 height)
+	void D3D11RenderWindowCore::setWindowed(UINT32 width, UINT32 height)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		mWidth = width;
-		mHeight = height;
-		mIsFullScreen = false;
+		D3D11RenderWindowProperties* properties = static_cast<D3D11RenderWindowProperties*>(mProperties);
+		properties->mWidth = width;
+		properties->mHeight = height;
+		properties->mIsFullScreen = false;
 
 		mSwapChainDesc.Windowed = true;
 		mSwapChainDesc.BufferDesc.RefreshRate.Numerator = 0;
 		mSwapChainDesc.BufferDesc.RefreshRate.Denominator = 0;
-		mSwapChainDesc.BufferDesc.Width = mWidth;
-		mSwapChainDesc.BufferDesc.Height = mHeight;
+		mSwapChainDesc.BufferDesc.Width = width;
+		mSwapChainDesc.BufferDesc.Height = height;
 
 		DXGI_MODE_DESC modeDesc;
 		ZeroMemory(&modeDesc, sizeof(modeDesc));
 
-		modeDesc.Width = mWidth;
-		modeDesc.Height = mHeight;
+		modeDesc.Width = width;
+		modeDesc.Height = height;
 		modeDesc.RefreshRate.Numerator = 0;
 		modeDesc.RefreshRate.Denominator = 0;
 		modeDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
 
 		mSwapChain->SetFullscreenState(false, nullptr);
 		mSwapChain->ResizeTarget(&modeDesc);
+
+		markCoreDirty();
 	}
 
-	void D3D11RenderWindow::getCustomAttribute( const String& name, void* pData ) const
+	void D3D11RenderWindowCore::getCustomAttribute(const String& name, void* pData) const
 	{
 		if(name == "WINDOW")
 		{
@@ -474,10 +481,10 @@ namespace BansheeEngine
 			return;
 		}
 
-		RenderWindow::getCustomAttribute(name, pData);
+		RenderWindowCore::getCustomAttribute(name, pData);
 	}
 
-	void D3D11RenderWindow::copyToMemory(PixelData &dst, FrameBuffer buffer)
+	void D3D11RenderWindowCore::copyToMemory(PixelData &dst, FrameBuffer buffer)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -535,7 +542,7 @@ namespace BansheeEngine
 		mDevice.getImmediateContext()->Map(tempTexture, 0,D3D11_MAP_READ, 0, &mappedTex2D);
 
 		// Copy the the texture to the dest
-		PixelData src(mWidth, mHeight, 1, PF_A8B8G8R8);
+		PixelData src(getProperties().getWidth(), getProperties().getHeight(), 1, PF_A8B8G8R8);
 		src.setExternalBuffer((UINT8*)mappedTex2D.pData);
 		PixelUtil::bulkPixelConversion(src, dst);
 
@@ -547,27 +554,7 @@ namespace BansheeEngine
 		SAFE_RELEASE(backbuffer);
 	}
 
-	Vector2I D3D11RenderWindow::screenToWindowPos(const Vector2I& screenPos) const
-	{
-		POINT pos;
-		pos.x = screenPos.x;
-		pos.y = screenPos.y;
-
-		ScreenToClient(mHWnd, &pos);
-		return Vector2I(pos.x, pos.y);
-	}
-
-	Vector2I D3D11RenderWindow::windowToScreenPos(const Vector2I& windowPos) const
-	{
-		POINT pos;
-		pos.x = windowPos.x;
-		pos.y = windowPos.y;
-
-		ClientToScreen(mHWnd, &pos);
-		return Vector2I(pos.x, pos.y);
-	}
-
-	void D3D11RenderWindow::_windowMovedOrResized()
+	void D3D11RenderWindowCore::_windowMovedOrResized()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -576,8 +563,11 @@ namespace BansheeEngine
 
 		RECT rc;
 		GetWindowRect(mHWnd, &rc);
-		mTop = rc.top;
-		mLeft = rc.left;
+
+		D3D11RenderWindowProperties* properties = static_cast<D3D11RenderWindowProperties*>(mProperties);
+		properties->mTop = rc.top;
+		properties->mLeft = rc.left;
+		markCoreDirty();
 
 		GetClientRect(mHWnd, &rc);
 		unsigned int width = rc.right - rc.left;
@@ -591,10 +581,10 @@ namespace BansheeEngine
 
 		resizeSwapChainBuffers(width, height);
 
-		RenderWindow::_windowMovedOrResized();
+		RenderWindowCore::_windowMovedOrResized();
 	}
 
-	void D3D11RenderWindow::createSwapChain()
+	void D3D11RenderWindowCore::createSwapChain()
 	{
 		ZeroMemory(&mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
 
@@ -603,11 +593,11 @@ namespace BansheeEngine
 		ZeroMemory(&mSwapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
 		DXGI_FORMAT format = DXGI_FORMAT_R8G8B8A8_UNORM;
 		mSwapChainDesc.OutputWindow	= mHWnd;
-		mSwapChainDesc.BufferDesc.Width = mWidth;
-		mSwapChainDesc.BufferDesc.Height = mHeight;
+		mSwapChainDesc.BufferDesc.Width = getProperties().getWidth();
+		mSwapChainDesc.BufferDesc.Height = getProperties().getHeight();
 		mSwapChainDesc.BufferDesc.Format = format;
 
-		if (mIsFullScreen)
+		if (getProperties().isFullScreen())
 		{
 			mSwapChainDesc.BufferDesc.RefreshRate.Numerator = mRefreshRateNumerator;
 			mSwapChainDesc.BufferDesc.RefreshRate.Denominator = mRefreshRateDenominator;
@@ -629,7 +619,7 @@ namespace BansheeEngine
 		mSwapChainDesc.Windowed	= true;
 
 		D3D11RenderSystem* rs = static_cast<D3D11RenderSystem*>(RenderSystem::instancePtr());
-		rs->determineMultisampleSettings(mMultisampleCount, mMultisampleHint, format, &mMultisampleType);
+		rs->determineMultisampleSettings(getProperties().getMultisampleCount(), getProperties().getMultisampleHint(), format, &mMultisampleType);
 		mSwapChainDesc.SampleDesc.Count = mMultisampleType.Count;
 		mSwapChainDesc.SampleDesc.Quality = mMultisampleType.Quality;
 		
@@ -653,7 +643,7 @@ namespace BansheeEngine
 		BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_SwapChain);
 	}
 
-	void D3D11RenderWindow::createSizeDependedD3DResources()
+	void D3D11RenderWindowCore::createSizeDependedD3DResources()
 	{
 		SAFE_RELEASE(mBackBuffer);
 
@@ -670,7 +660,7 @@ namespace BansheeEngine
 		ZeroMemory( &RTVDesc, sizeof(RTVDesc) );
 
 		RTVDesc.Format = BBDesc.Format;
-		RTVDesc.ViewDimension = mMultisampleCount ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
+		RTVDesc.ViewDimension = getProperties().getMultisampleCount() ? D3D11_RTV_DIMENSION_TEXTURE2DMS : D3D11_RTV_DIMENSION_TEXTURE2D;
 		RTVDesc.Texture2D.MipSlice = 0;
 		hr = mDevice.getD3D11Device()->CreateRenderTargetView(mBackBuffer, &RTVDesc, &mRenderTargetView);
 
@@ -681,7 +671,8 @@ namespace BansheeEngine
 		}
 
 		mDepthStencilBuffer = TextureManager::instance().createTexture(TEX_TYPE_2D, 
-			BBDesc.Width, BBDesc.Height, 0, PF_D24S8, TU_DEPTHSTENCIL, false, mMultisampleCount, mMultisampleHint);
+			BBDesc.Width, BBDesc.Height, 0, PF_D24S8, TU_DEPTHSTENCIL, false, 
+			getProperties().getMultisampleCount(), getProperties().getMultisampleHint());
 
 		if(mDepthStencilView != nullptr)
 		{
@@ -692,7 +683,7 @@ namespace BansheeEngine
 		mDepthStencilView = Texture::requestView(mDepthStencilBuffer, 0, 1, 0, 1, GVU_DEPTHSTENCIL);
 	}
 
-	void D3D11RenderWindow::destroySizeDependedD3DResources()
+	void D3D11RenderWindowCore::destroySizeDependedD3DResources()
 	{
 		SAFE_RELEASE(mBackBuffer);
 		SAFE_RELEASE(mRenderTargetView);
@@ -700,27 +691,29 @@ namespace BansheeEngine
 		mDepthStencilBuffer = nullptr;
 	}
 
-	void D3D11RenderWindow::resizeSwapChainBuffers(UINT32 width, UINT32 height)
+	void D3D11RenderWindowCore::resizeSwapChainBuffers(UINT32 width, UINT32 height)
 	{
 		destroySizeDependedD3DResources();
 
-		UINT Flags = mIsFullScreen ? DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH : 0;
+		UINT Flags = getProperties().isFullScreen() ? DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH : 0;
 		HRESULT hr = mSwapChain->ResizeBuffers(mSwapChainDesc.BufferCount, width, height, mSwapChainDesc.BufferDesc.Format, Flags);
 
 		if(hr != S_OK)
 			BS_EXCEPT(InternalErrorException, "Call to ResizeBuffers failed.");
 
+		D3D11RenderWindowProperties* properties = static_cast<D3D11RenderWindowProperties*>(mProperties);
 		mSwapChain->GetDesc(&mSwapChainDesc);
-		mWidth = mSwapChainDesc.BufferDesc.Width;
-		mHeight = mSwapChainDesc.BufferDesc.Height;
-		mIsFullScreen = (0 == mSwapChainDesc.Windowed); // Alt-Enter together with SetWindowAssociation() can change this state
+		properties->mWidth = mSwapChainDesc.BufferDesc.Width;
+		properties->mHeight = mSwapChainDesc.BufferDesc.Height;
+		properties->mIsFullScreen = (0 == mSwapChainDesc.Windowed); // Alt-Enter together with SetWindowAssociation() can change this state
+		markCoreDirty();
 
 		createSizeDependedD3DResources();
 
 		mDevice.getImmediateContext()->OMSetRenderTargets(0, 0, 0);
 	}
 
-	IDXGIDevice* D3D11RenderWindow::queryDxgiDevice()
+	IDXGIDevice* D3D11RenderWindowCore::queryDxgiDevice()
 	{
 		if (mDevice.getD3D11Device() == nullptr)
 		{
@@ -735,4 +728,61 @@ namespace BansheeEngine
 
 		return pDXGIDevice;
 	}
+
+	D3D11RenderWindow::D3D11RenderWindow(D3D11Device& device, IDXGIFactory* DXGIFactory)
+		:mDevice(device), mDXGIFactory(DXGIFactory), mHWnd(0)
+	{
+
+	}
+
+	void D3D11RenderWindow::getCustomAttribute(const String& name, void* pData) const
+	{
+		THROW_IF_CORE_THREAD;
+
+		if (name == "WINDOW")
+		{
+			HWND *pWnd = (HWND*)pData;
+			*pWnd = mHWnd;
+			return;
+		}
+
+		RenderWindow::getCustomAttribute(name, pData);
+	}
+
+	Vector2I D3D11RenderWindow::screenToWindowPos(const Vector2I& screenPos) const
+	{
+		POINT pos;
+		pos.x = screenPos.x;
+		pos.y = screenPos.y;
+
+		ScreenToClient(mHWnd, &pos);
+		return Vector2I(pos.x, pos.y);
+	}
+
+	Vector2I D3D11RenderWindow::windowToScreenPos(const Vector2I& windowPos) const
+	{
+		POINT pos;
+		pos.x = windowPos.x;
+		pos.y = windowPos.y;
+
+		ClientToScreen(mHWnd, &pos);
+		return Vector2I(pos.x, pos.y);
+	}
+
+	void D3D11RenderWindow::initialize_internal()
+	{
+		RenderWindow::initialize_internal();
+
+		mCore->getCustomAttribute("WINDOW", (void*)&mHWnd);
+	}
+
+	RenderTargetProperties* D3D11RenderWindow::createProperties() const
+	{
+		return bs_new<RenderWindowProperties>();
+	}
+
+	RenderWindowCore* D3D11RenderWindow::createCore(RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc)
+	{
+		return bs_new<D3D11RenderWindowCore>(this, properties, desc, mDevice, mDXGIFactory);
+	}
 }

+ 1 - 1
BansheeD3D11RenderSystem/Source/BsD3D11RenderWindowManager.cpp

@@ -24,7 +24,7 @@ namespace BansheeEngine
 		}
 
 		// Create the window
-		D3D11RenderWindow* renderWindow = new (bs_alloc<D3D11RenderWindow, PoolAlloc>()) D3D11RenderWindow(desc, d3d11rs->getPrimaryDevice(), d3d11rs->getDXGIFactory());
+		D3D11RenderWindow* renderWindow = new (bs_alloc<D3D11RenderWindow, PoolAlloc>()) D3D11RenderWindow(d3d11rs->getPrimaryDevice(), d3d11rs->getDXGIFactory());
 		return bs_core_ptr<D3D11RenderWindow, PoolAlloc>(renderWindow);
 	}
 }

+ 18 - 18
BansheeD3D9RenderSystem/Include/BsD3D9Device.h

@@ -35,12 +35,12 @@ namespace BansheeEngine
 		 * @brief	Attaches a new render window to this device. Caller must ensure
 		 *			the window is not attached to multiple devices.
 		 */
-		void attachRenderWindow(const D3D9RenderWindow* renderWindow);
+		void attachRenderWindow(const D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Detaches the render window from this device.
 		 */
-		void detachRenderWindow(const D3D9RenderWindow* renderWindow);
+		void detachRenderWindow(const D3D9RenderWindowCore* renderWindow);
 	
 		/**
 		 * @brief	Acquires the device. This will cause a device reset in case present parameters changed.
@@ -106,37 +106,37 @@ namespace BansheeEngine
 		/**
 		 * @brief	Validates that the window is valid for this device. Will reset device if needed.
 		 */
-		bool validate(D3D9RenderWindow* renderWindow);
+		bool validate(D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Invalidates the window so on the next call to validate, the device will be re-acquired.
 		 */
-		void invalidate(const D3D9RenderWindow* renderWindow);
+		void invalidate(const D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Swap back and front buffers for the specified window.
 		 */
-		void present(const D3D9RenderWindow* renderWindow);
+		void present(const D3D9RenderWindowCore* renderWindow);
 		
 		/**
 		 * @brief	Returns internal DX9 represention of the depth/stencil buffer.
 		 */
-		IDirect3DSurface9* getDepthBuffer(const D3D9RenderWindow* renderWindow);
+		IDirect3DSurface9* getDepthBuffer(const D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Returns internal DX9 represention of the backbuffer.
 		 */
-		IDirect3DSurface9* getBackBuffer(const D3D9RenderWindow* renderWindow);
+		IDirect3DSurface9* getBackBuffer(const D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Sets adapter index for the specified window.
 		 */
-		void setAdapterOrdinalIndex(const D3D9RenderWindow* renderWindow, UINT32 adapterOrdinalInGroupIndex);
+		void setAdapterOrdinalIndex(const D3D9RenderWindowCore* renderWindow, UINT32 adapterOrdinalInGroupIndex);
 
 		/**
 		 * @brief	Copies contents of the back or depth/stencil buffer in to the provided object.
 		 */
-		void copyContentsToMemory(const D3D9RenderWindow* window, PixelData &dst, RenderTarget::FrameBuffer buffer);
+		void copyContentsToMemory(const D3D9RenderWindowCore* window, PixelData &dst, RenderTargetCore::FrameBuffer buffer);
 
 		/**
 		 * @brief	Resets bound pipeline states/streams to null.
@@ -147,18 +147,18 @@ namespace BansheeEngine
 		friend class D3D9DeviceManager;
 		friend class D3D9RenderSystem;
 
-		typedef Map<const D3D9RenderWindow*, RenderWindowResources*> RenderWindowToResorucesMap;
-		typedef RenderWindowToResorucesMap::iterator				 RenderWindowToResorucesIterator;
+		typedef Map<const D3D9RenderWindowCore*, RenderWindowResources*> RenderWindowToResorucesMap;
+		typedef RenderWindowToResorucesMap::iterator RenderWindowToResorucesIterator;
 
 		/**
 		 * @brief	Find iterator for the specified window in the render window resource list.
 		 */
-		RenderWindowToResorucesIterator getRenderWindowIterator(const D3D9RenderWindow* renderWindow);
+		RenderWindowToResorucesIterator getRenderWindowIterator(const D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Acquires the device for the provided render window.
 		 */
-		bool acquire(const D3D9RenderWindow* renderWindow);
+		bool acquire(const D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Forcibly reset the device.
@@ -209,27 +209,27 @@ namespace BansheeEngine
 		/**
 		 * @brief	Checks if back buffer size has changed and invalidates the window if it has.
 		 */
-		void validateBackBufferSize(const D3D9RenderWindow* renderWindow);
+		void validateBackBufferSize(const D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Checks if window monitor changed and re-links the window if needed.
 		 */
-		bool validateDisplayMonitor(D3D9RenderWindow* renderWindow);
+		bool validateDisplayMonitor(D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Checks if device has been lost or active window invalidated and acquires the device if needed.
 		 */
-		bool validateDeviceState(const D3D9RenderWindow* renderWindow);
+		bool validateDeviceState(const D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Checks if the render window contains a custom swap chain.
 		 */
-		bool isSwapChainWindow(const D3D9RenderWindow* renderWindow);
+		bool isSwapChainWindow(const D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Returns primary window for this device.
 		 */
-		const D3D9RenderWindow*	getPrimaryWindow();
+		const D3D9RenderWindowCore*	getPrimaryWindow();
 
 		/**
 		 * @brief	Sets the shared window handle.

+ 3 - 3
BansheeD3D9RenderSystem/Include/BsD3D9DeviceManager.h

@@ -49,7 +49,7 @@ namespace BansheeEngine
 		 *			assigned an existing device if a match one can be found, otherwise
 		 *			a new device will be created.
 		 */
-		void linkRenderWindow(D3D9RenderWindow* renderWindow);
+		void linkRenderWindow(D3D9RenderWindowCore* renderWindow);
 
 		/**
 		 * @brief	Called by the devices when they're are being destroyed.
@@ -67,12 +67,12 @@ namespace BansheeEngine
 		 *			new device is created. Found/created device is returned, as well as a list of all render windows
 		 *			using that device.
 		 */
-		D3D9Device*	selectDevice(D3D9RenderWindow* renderWindow, Vector<D3D9RenderWindow*>& renderWindowsGroup);
+		D3D9Device*	selectDevice(D3D9RenderWindowCore* renderWindow, Vector<D3D9RenderWindowCore*>& renderWindowsGroup);
 
 		/**
 		 * @brief	Finds the driver the render window belongs to.
 		 */
-		D3D9Driver*	findDriver(D3D9RenderWindow* renderWindow);
+		D3D9Driver*	findDriver(D3D9RenderWindowCore* renderWindow);
 
 		Vector<D3D9Device*> mRenderDevices;
 		D3D9Device*	mActiveDevice;

+ 33 - 14
BansheeD3D9RenderSystem/Include/BsD3D9MultiRenderTexture.h

@@ -5,35 +5,54 @@
 
 namespace BansheeEngine
 {
+	class D3D9MultiRenderTexture;
+
 	/**
 	 * @brief	DirectX 9 implementation of a render texture with multiple color surfaces.
+	 *
+	 * @note	Core thread only.
 	 */
-	class BS_D3D9_EXPORT D3D9MultiRenderTexture : public MultiRenderTexture
+	class BS_D3D9_EXPORT D3D9MultiRenderTextureCore : public MultiRenderTextureCore
 	{
 	public:
-		virtual ~D3D9MultiRenderTexture();
-
-		/**
-		 * @copydoc	MultiRenderTexture::requiresTextureFlipping
-		 */
-		bool requiresTextureFlipping() const { return false; }
-
+		D3D9MultiRenderTextureCore(D3D9MultiRenderTexture* parent, MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc);
+		virtual ~D3D9MultiRenderTextureCore();
+		
 		/**
-		 * @copydoc	MultiRenderTexture::getCustomAttribute
+		 * @copydoc	MultiRenderTextureCore::getCustomAttribute
 		 */
 		void getCustomAttribute(const String& name, void* pData) const;
 
+	protected:
+		friend class D3D9MultiRenderTexture;
+
+		Vector<IDirect3DSurface9*> mDX9ColorSurfaces;
+		IDirect3DSurface9* mDX9DepthStencilSurface;
+	};
+
+	/**
+	 * @brief	DirectX 9 implementation of a render texture with multiple color surfaces.
+	 *
+	 * @note	Sim thread only.
+	 */
+	class BS_D3D9_EXPORT D3D9MultiRenderTexture : public MultiRenderTexture
+	{
+	public:
+		virtual ~D3D9MultiRenderTexture() { }
+
 	protected:
 		friend class D3D9TextureManager;
 
-		D3D9MultiRenderTexture();
+		D3D9MultiRenderTexture() { }
 
 		/**
-		 * @copydoc MultiRenderTexture::initialize_internal().
+		 * @copydoc	MultiRenderTexture::createProperties
 		 */
-		void initialize_internal();
+		virtual RenderTargetProperties* createProperties() const;
 
-		Vector<IDirect3DSurface9*> mDX9ColorSurfaces;
-		IDirect3DSurface9* mDX9DepthStencilSurface;
+		/**
+		 * @copydoc	MultiRenderTexture::createCore
+		 */
+		virtual MultiRenderTextureCore* createCore(MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc);
 	};
 }

+ 1 - 0
BansheeD3D9RenderSystem/Include/BsD3D9Prerequisites.h

@@ -28,6 +28,7 @@ namespace BansheeEngine
 	// Predefine classes
 	class D3D9RenderSystem;
 	class D3D9RenderWindow;
+	class D3D9RenderWindowCore;
 	class D3D9Texture;
 	class D3D9TextureManager;
 	class D3D9Driver;

+ 1 - 1
BansheeD3D9RenderSystem/Include/BsD3D9RenderSystem.h

@@ -219,7 +219,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	Register a newly open window with the render system.
 		 */
-		void registerWindow(RenderWindow& renderWindow);
+		void registerWindow(RenderWindowCore& renderWindow);
 
 	private:
 		friend class D3D9Texture;

+ 37 - 15
BansheeD3D9RenderSystem/Include/BsD3D9RenderTexture.h

@@ -6,21 +6,23 @@
 
 namespace BansheeEngine
 {
+	class D3D9RenderTexture;
+
 	/**
 	 * @brief	DirectX 9 implementation of a render texture.
+	 *
+	 * @note	Core thread only.
 	 */
-	class BS_D3D9_EXPORT D3D9RenderTexture : public RenderTexture, public D3D9Resource
+	class BS_D3D9_EXPORT D3D9RenderTextureCore : public RenderTextureCore, public D3D9Resource
 	{
 	public:
-		virtual ~D3D9RenderTexture();
+		D3D9RenderTextureCore(D3D9RenderTexture* parent, RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+			const RENDER_SURFACE_DESC& depthStencilSurfaceDesc);
 
-		/**
-		 * @copydoc	RenderTexture::requiresTextureFlipping
-		 */
-		virtual bool requiresTextureFlipping() const { return false; }
+		virtual ~D3D9RenderTextureCore();
 
 		/**
-		 * @copydoc	RenderTexture::getCustomAttribute
+		 * @copydoc	RenderTextureCore::getCustomAttribute
 		 */
 		virtual void getCustomAttribute(const String& name, void* pData) const;
 
@@ -45,14 +47,7 @@ namespace BansheeEngine
 		virtual void notifyOnDeviceReset(IDirect3DDevice9* d3d9Device);
 
 	protected:
-		friend class D3D9TextureManager;
-
-		D3D9RenderTexture();
-
-		/**
-		 * @copydoc RenderTexture::initialize_internal().
-		 */
-		void initialize_internal();
+		friend class D3D9RenderTexture;
 
 		/**
 		 * @brief	Initializes the internal color and depth surfaces.
@@ -69,4 +64,31 @@ namespace BansheeEngine
 		IDirect3DSurface9* mDX9DepthStencilSurface;
 		bool mIsBindableToShader;
 	};
+
+	/**
+	* @brief	DirectX 9 implementation of a render texture.
+	*
+	* @note		Sim thread only.
+	*/
+	class BS_D3D9_EXPORT D3D9RenderTexture : public RenderTexture
+	{
+	public:
+		virtual ~D3D9RenderTexture() { }
+
+	protected:
+		friend class D3D9TextureManager;
+
+		D3D9RenderTexture() { }
+
+		/**
+		 * @copydoc	RenderTexture::createProperties
+		 */
+		virtual RenderTargetProperties* createProperties() const;
+
+		/**
+		 * @copydoc	RenderTexture::createCore
+		 */
+		virtual RenderTextureCore* createCore(RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+			const RENDER_SURFACE_DESC& depthStencilSurfaceDesc);
+	};
 }

+ 92 - 64
BansheeD3D9RenderSystem/Include/BsD3D9RenderWindow.h

@@ -6,96 +6,79 @@
 
 namespace BansheeEngine 
 {
+	class D3D9RenderWindow;
+
+	/**
+	 * @brief	Contains various properties that describe a render window.
+	 */
+	class BS_D3D9_EXPORT D3D9RenderWindowProperties : public RenderWindowProperties
+	{
+	public:
+		virtual ~D3D9RenderWindowProperties() { }
+
+	private:
+		friend class D3D9RenderWindowCore;
+		friend class D3D9RenderWindow;
+	};
+
 	/**
 	 * @brief	Render window implementation for Windows.
+	 *
+	 * @note	Core thread only.
 	 */
-	class BS_D3D9_EXPORT D3D9RenderWindow : public RenderWindow
+	class BS_D3D9_EXPORT D3D9RenderWindowCore : public RenderWindowCore
 	{
 	public:
-		~D3D9RenderWindow();
+		D3D9RenderWindowCore(D3D9RenderWindow* parent, RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc, HINSTANCE instance);
+		~D3D9RenderWindowCore();
 		
 		/**
-		 * @copydoc RenderWindow::setFullscreen(UINT32, UINT32, float, UINT32)
+		 * @copydoc RenderWindowCore::setFullscreen(UINT32, UINT32, float, UINT32)
 		 */
 		void setFullscreen(UINT32 width, UINT32 height, float refreshRate = 60.0f, UINT32 monitorIdx = 0);
 
 		/**
-		 * @copydoc RenderWindow::setFullscreen(const VideoMode&)
+		 * @copydoc RenderWindowCore::setFullscreen(const VideoMode&)
 		 */
 		void setFullscreen(const VideoMode& mode);
 
 		/**
-		* @copydoc RenderWindow::setWindowed
+		* @copydoc RenderWindowCore::setWindowed
 		*/
 		void setWindowed(UINT32 width, UINT32 height);
 
 		/**
-		 * @copydoc RenderWindow::setHidden
+		 * @copydoc RenderWindowCore::setHidden
 		 */
 		void setHidden(bool hidden);
 
 		/**
-		 * @copydoc RenderWindow::isActive
-		 */
-		bool isActive() const;
-
-		/**
-		 * @copydoc RenderWindow::isVisible
-		 */
-		bool isVisible() const;
-
-		/**
-		 * @copydoc RenderWindow::isClosed
-		 */
-		bool isClosed() const { return mClosed; }
-
-		/**
-		 * @copydoc RenderWindow::isVSync
-		 */
-		bool isVSync() const { return mVSync; }
-
-		/**
-		 * @copydoc RenderWindow::move
+		 * @copydoc RenderWindowCore::move
 		 */
 		void move(INT32 left, INT32 top);
 
 		/**
-		 * @copydoc RenderWindow::resize
+		 * @copydoc RenderWindowCore::resize
 		 */
 		void resize(UINT32 width, UINT32 height);
 
 		/**
-		 * @copydoc RenderWindow::getCustomAttribute
+		 * @copydoc RenderWindowCore::getCustomAttribute
 		 */
 		void getCustomAttribute(const String& name, void* pData) const;
 
 		/**
-		 * @copydoc RenderWindow::copyContentsToMemory
+		 * @copydoc RenderWindowCore::copyContentsToMemory
 		 */
 		void copyToMemory(PixelData &dst, FrameBuffer buffer);
 
 		/**
-		 * @copydoc RenderWindow::requiresTextureFlipping
-		 */
-		bool requiresTextureFlipping() const { return false; }
-
-		/**
-		 * @copydoc RenderWindow::swapBuffers
+		 * @copydoc RenderWindowCore::swapBuffers
 		 */
 		void swapBuffers();
 
 		/**
-		 * @copydoc RenderWindow::screenToWindowPos
-		 */
-		Vector2I screenToWindowPos(const Vector2I& screenPos) const;
-
-		/**
-		 * @copydoc RenderWindow::windowToScreenPos
-		 */
-		Vector2I windowToScreenPos(const Vector2I& windowPos) const;
-
-		/**
-		 * @copydoc RenderWindow::_windowMovedOrResized
+		 * @copydoc RenderWindowCore::_windowMovedOrResized
 		 */
 		void _windowMovedOrResized();
 
@@ -138,28 +121,15 @@ namespace BansheeEngine
 		 * @brief	Validate the device for this window.
 		 */
 		bool _validateDevice();
-
 		
 	protected:
-		friend class D3D9RenderWindowManager;
-
-		D3D9RenderWindow(const RENDER_WINDOW_DESC& desc, HINSTANCE instance);
+		friend class D3D9RenderWindow;
 
 		/**
 		 * @brief	Updates window coordinates and size from actual values provided by Windows.
 		 */
 		void updateWindowRect();
 
-		/**
-		 * @copydoc RenderWindow::initialize_internal().
-		 */
-		void initialize_internal();
-
-		/**
-		 * @copydoc RenderWindow::destroy_internal().
-		 */
-		void destroy_internal();
-
 		/**
 		 * @brief	Calculates window size based on provided client area size and currently set window style. 
 		 */	
@@ -171,12 +141,10 @@ namespace BansheeEngine
 		D3D9Device* mDevice;
 		bool mDeviceValid;
 		HWND mHWnd;
-		bool mIsExternal;
-		bool mClosed;		
+		bool mIsExternal;		
 		D3DMULTISAMPLE_TYPE	mMultisampleType;
 		DWORD mMultisampleQuality;
 		UINT mDisplayFrequency;
-		bool mVSync;
 		unsigned int mVSyncInterval;		
 		DWORD mStyle;	
 		DWORD mWindowedStyle;
@@ -184,4 +152,64 @@ namespace BansheeEngine
 		bool mIsDepthBuffered;
 		bool mIsChild;
 	};
+
+	/**
+	 * @brief	Render window implementation for Windows.
+	 *
+	 * @note	Sim thread only.
+	 */
+	class BS_D3D9_EXPORT D3D9RenderWindow : public RenderWindow
+	{
+	public:
+		~D3D9RenderWindow() { }
+
+		/**
+		 * @copydoc RenderWindow::screenToWindowPos
+		 */
+		Vector2I screenToWindowPos(const Vector2I& screenPos) const;
+
+		/**
+		 * @copydoc RenderWindow::windowToScreenPos
+		 */
+		Vector2I windowToScreenPos(const Vector2I& windowPos) const;
+
+		/**
+		 * @copydoc RenderWindow::requiresTextureFlipping
+		 */
+		bool requiresTextureFlipping() const { return false; }
+
+		/**
+		 * @copydoc RenderWindow::getCustomAttribute
+		 */
+		void getCustomAttribute(const String& name, void* pData) const;
+
+		/**
+		 * @copydoc	RenderWindow::getCore
+		 */
+		D3D9RenderWindowCore* getCore() const;
+
+	protected:
+		friend class D3D9RenderWindowManager;
+
+		D3D9RenderWindow(HINSTANCE instance);
+
+		/**
+		 * @copydoc	RenderWindow::initialize_internal
+		 */
+		virtual void initialize_internal();
+
+		/**
+		 * @copydoc	RenderWindow::createProperties
+		 */
+		virtual RenderTargetProperties* createProperties() const;
+
+		/**
+		 * @copydoc	RenderWindow::createCore
+		 */
+		virtual RenderWindowCore* createCore(RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc);
+
+	private:
+		HINSTANCE mInstance;
+		HWND mHWnd;
+	};
 }

+ 46 - 43
BansheeD3D9RenderSystem/Source/BsD3D9Device.cpp

@@ -34,7 +34,7 @@ namespace BansheeEngine
 
 	}
 
-	D3D9Device::RenderWindowToResorucesIterator D3D9Device::getRenderWindowIterator(const D3D9RenderWindow* renderWindow)
+	D3D9Device::RenderWindowToResorucesIterator D3D9Device::getRenderWindowIterator(const D3D9RenderWindowCore* renderWindow)
 	{
 		RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.find(renderWindow);
 
@@ -44,7 +44,7 @@ namespace BansheeEngine
 		return it;
 	}
 
-	void D3D9Device::attachRenderWindow(const D3D9RenderWindow* renderWindow)
+	void D3D9Device::attachRenderWindow(const D3D9RenderWindowCore* renderWindow)
 	{
 		RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.find(renderWindow);
 
@@ -61,7 +61,7 @@ namespace BansheeEngine
 		updateRenderWindowsIndices();
 	}
 
-	void D3D9Device::detachRenderWindow(const D3D9RenderWindow* renderWindow)
+	void D3D9Device::detachRenderWindow(const D3D9RenderWindowCore* renderWindow)
 	{
 		RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.find(renderWindow);
 
@@ -175,7 +175,7 @@ namespace BansheeEngine
 		}				
 	}
 
-	bool D3D9Device::acquire(const D3D9RenderWindow* renderWindow)
+	bool D3D9Device::acquire(const D3D9RenderWindowCore* renderWindow)
 	{
 		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
 		
@@ -197,21 +197,21 @@ namespace BansheeEngine
 		renderSystem->notifyOnDeviceLost(this);
 	}	
 
-	IDirect3DSurface9* D3D9Device::getDepthBuffer(const D3D9RenderWindow* renderWindow)
+	IDirect3DSurface9* D3D9Device::getDepthBuffer(const D3D9RenderWindowCore* renderWindow)
 	{
 		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);		
 
 		return it->second->depthBuffer;
 	}
 
-	IDirect3DSurface9* D3D9Device::getBackBuffer(const D3D9RenderWindow* renderWindow)
+	IDirect3DSurface9* D3D9Device::getBackBuffer(const D3D9RenderWindowCore* renderWindow)
 	{
 		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
 	
 		return it->second->backBuffer;		
 	}
 
-	void D3D9Device::setAdapterOrdinalIndex(const D3D9RenderWindow* renderWindow, UINT32 adapterOrdinalInGroupIndex)
+	void D3D9Device::setAdapterOrdinalIndex(const D3D9RenderWindowCore* renderWindow, UINT32 adapterOrdinalInGroupIndex)
 	{
 		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
 
@@ -426,18 +426,18 @@ namespace BansheeEngine
 
 			while (it != mMapRenderWindowToResoruces.end())
 			{
-				const D3D9RenderWindow* renderWindow = it->first;
+				const D3D9RenderWindowCore* renderWindow = it->first;
 				RenderWindowResources* renderWindowResources = it->second;
 
 				// Ask the render window to build it's own parameters.
 				renderWindow->_buildPresentParameters(&renderWindowResources->presentParameters);
 				
 				// Update shared focus window handle.
-				if (renderWindow->isFullScreen() && renderWindowResources->presentParametersIndex == 0 && msSharedFocusWindow == NULL)
+				if (renderWindow->getProperties().isFullScreen() && renderWindowResources->presentParametersIndex == 0 && msSharedFocusWindow == NULL)
 					setSharedWindowHandle(renderWindow->_getWindowHandle());					
 
 				// This is the primary window or a full screen window that is part of multi head device.
-				if (renderWindowResources->presentParametersIndex == 0 || renderWindow->isFullScreen())
+				if (renderWindowResources->presentParametersIndex == 0 || renderWindow->getProperties().isFullScreen())
 				{
 					mPresentationParams[renderWindowResources->presentParametersIndex] = renderWindowResources->presentParameters;
 					mPresentationParamsCount++;
@@ -473,7 +473,7 @@ namespace BansheeEngine
 		{
 			RenderWindowResources* renderWindowResources = resourceData.second;
 
-			if (renderWindowResources->adapterOrdinalInGroupIndex > 0 && resourceData.first->isFullScreen())
+			if (renderWindowResources->adapterOrdinalInGroupIndex > 0 && resourceData.first->getProperties().isFullScreen())
 				return true;
 		}
 
@@ -525,7 +525,7 @@ namespace BansheeEngine
 	void D3D9Device::createD3D9Device()
 	{		
 		// Update focus window.
-		const D3D9RenderWindow* primaryRenderWindow = getPrimaryWindow();
+		const D3D9RenderWindowCore* primaryRenderWindow = getPrimaryWindow();
 
 		// Case we have to share the same focus window.
 		if (msSharedFocusWindow != NULL)
@@ -655,14 +655,14 @@ namespace BansheeEngine
 		renderWindowResources->acquired = false;
 	}
 
-	void D3D9Device::invalidate(const D3D9RenderWindow* renderWindow)
+	void D3D9Device::invalidate(const D3D9RenderWindowCore* renderWindow)
 	{
 		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
 
 		it->second->acquired = false;		
 	}
 
-	bool D3D9Device::validate(D3D9RenderWindow* renderWindow)
+	bool D3D9Device::validate(D3D9RenderWindowCore* renderWindow)
 	{
 		// Validate that the render window should run on this device.
 		if (!validateDisplayMonitor(renderWindow))
@@ -698,7 +698,7 @@ namespace BansheeEngine
 		}
 	}
 
-	bool D3D9Device::validateDeviceState(const D3D9RenderWindow* renderWindow)
+	bool D3D9Device::validateDeviceState(const D3D9RenderWindowCore* renderWindow)
 	{
 		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);		
 		RenderWindowResources* renderWindowResources =  it->second;
@@ -759,31 +759,33 @@ namespace BansheeEngine
 		return true;
 	}
 		
-	void D3D9Device::validateBackBufferSize(const D3D9RenderWindow* renderWindow)
+	void D3D9Device::validateBackBufferSize(const D3D9RenderWindowCore* renderWindow)
 	{
 		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
 		RenderWindowResources*	renderWindowResources = it->second;
 	
+		const RenderWindowProperties& props = renderWindow->getProperties();
+
 		// Case size has been changed.
-		if (renderWindow->getWidth() != renderWindowResources->presentParameters.BackBufferWidth ||
-			renderWindow->getHeight() != renderWindowResources->presentParameters.BackBufferHeight)
+		if (props.getWidth() != renderWindowResources->presentParameters.BackBufferWidth ||
+			props.getHeight() != renderWindowResources->presentParameters.BackBufferHeight)
 		{			
-			if (renderWindow->getWidth() > 0)
-				renderWindowResources->presentParameters.BackBufferWidth = renderWindow->getWidth();
+			if (props.getWidth() > 0)
+				renderWindowResources->presentParameters.BackBufferWidth = props.getWidth();
 
-			if (renderWindow->getHeight() > 0)
-				renderWindowResources->presentParameters.BackBufferHeight = renderWindow->getHeight();
+			if (props.getHeight() > 0)
+				renderWindowResources->presentParameters.BackBufferHeight = props.getHeight();
 
 			invalidate(renderWindow);
 		}				
 	}
 
-	bool D3D9Device::validateDisplayMonitor(D3D9RenderWindow* renderWindow)
+	bool D3D9Device::validateDisplayMonitor(D3D9RenderWindowCore* renderWindow)
 	{
 		// Ignore full screen since it doesn't really move and it is possible 
 		// that it created using multi-head adapter so for a subordinate the
 		// native monitor handle and this device handle will be different.
-		if (renderWindow->isFullScreen())
+		if (renderWindow->getProperties().isFullScreen())
 			return true;
 
 		HMONITOR	hRenderWindowMonitor = NULL;
@@ -813,7 +815,7 @@ namespace BansheeEngine
 		return true;
 	}
 
-	void D3D9Device::present(const D3D9RenderWindow* renderWindow)
+	void D3D9Device::present(const D3D9RenderWindowCore* renderWindow)
 	{		
 		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
 		RenderWindowResources*	renderWindowResources = it->second;				
@@ -856,7 +858,7 @@ namespace BansheeEngine
 	void D3D9Device::acquireRenderWindowResources(RenderWindowToResorucesIterator it)
 	{
 		RenderWindowResources*	renderWindowResources = it->second;
-		const D3D9RenderWindow*	renderWindow = it->first;			
+		const D3D9RenderWindowCore*	renderWindow = it->first;
 		
 		releaseRenderWindowResources(renderWindowResources);
 
@@ -909,8 +911,8 @@ namespace BansheeEngine
 			}
 			else
 			{
-				UINT32 targetWidth  = renderWindow->getWidth();
-				UINT32 targetHeight = renderWindow->getHeight();
+				UINT32 targetWidth  = renderWindow->getProperties().getWidth();
+				UINT32 targetHeight = renderWindow->getProperties().getHeight();
 
 				if (targetWidth == 0)
 					targetWidth = 1;
@@ -942,17 +944,17 @@ namespace BansheeEngine
 		renderWindowResources->acquired = true; 
 	}
 
-	bool D3D9Device::isSwapChainWindow(const D3D9RenderWindow* renderWindow)
+	bool D3D9Device::isSwapChainWindow(const D3D9RenderWindowCore* renderWindow)
 	{
 		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
 		
-		if (it->second->presentParametersIndex == 0 || renderWindow->isFullScreen())			
+		if (it->second->presentParametersIndex == 0 || renderWindow->getProperties().isFullScreen())			
 			return false;
 			
 		return true;
 	}
 
-	const D3D9RenderWindow* D3D9Device::getPrimaryWindow()
+	const D3D9RenderWindowCore* D3D9Device::getPrimaryWindow()
 	{		
 		RenderWindowToResorucesIterator it = mMapRenderWindowToResoruces.begin();
 	
@@ -996,7 +998,7 @@ namespace BansheeEngine
 			UINT32 nextPresParamIndex = 0;
 
 			RenderWindowToResorucesIterator it;
-			const D3D9RenderWindow* deviceFocusWindow = NULL;
+			const D3D9RenderWindowCore* deviceFocusWindow = NULL;
 
 			// In case a d3d9 device exists - try to keep the present parameters order
 			// so that the window that the device is focused on will stay the same and we
@@ -1032,15 +1034,17 @@ namespace BansheeEngine
 		}
 	}
 
-	void D3D9Device::copyContentsToMemory(const D3D9RenderWindow* renderWindow, 
-		PixelData &dst, RenderTarget::FrameBuffer buffer)
+	void D3D9Device::copyContentsToMemory(const D3D9RenderWindowCore* renderWindow,
+		PixelData &dst, RenderTargetCore::FrameBuffer buffer)
 	{
+		const RenderWindowProperties& props = renderWindow->getProperties();
+
 		RenderWindowToResorucesIterator it = getRenderWindowIterator(renderWindow);
 		RenderWindowResources* resources = it->second;
 		bool swapChain = isSwapChainWindow(renderWindow);
 
-		if ((dst.getLeft() < 0) || (dst.getRight() > renderWindow->getWidth()) ||
-			(dst.getTop() < 0) || (dst.getBottom() > renderWindow->getHeight()) ||
+		if ((dst.getLeft() < 0) || (dst.getRight() > props.getWidth()) ||
+			(dst.getTop() < 0) || (dst.getBottom() > props.getHeight()) ||
 			(dst.getFront() != 0) || (dst.getBack() != 1))
 		{
 			BS_EXCEPT(InvalidParametersException, "Invalid box.");
@@ -1053,13 +1057,12 @@ namespace BansheeEngine
 		D3DLOCKED_RECT lockedRect;
 
 
-		if (buffer == RenderTarget::FB_AUTO)
+		if (buffer == RenderTargetCore::FB_AUTO)
 		{
-			//buffer = mIsFullScreen? FB_FRONT : FB_BACK;
-			buffer = RenderTarget::FB_FRONT;
+			buffer = RenderTargetCore::FB_FRONT;
 		}
 
-		if (buffer == RenderTarget::FB_FRONT)
+		if (buffer == RenderTargetCore::FB_FRONT)
 		{
 			D3DDISPLAYMODE dm;
 
@@ -1087,9 +1090,9 @@ namespace BansheeEngine
 				BS_EXCEPT(RenderingAPIException, "Can't get front buffer: TODO PORT NO ERROR"); // TODO PORT - Translate HR to error
 			}
 
-			if(renderWindow->isFullScreen())
+			if (props.isFullScreen())
 			{
-				if ((dst.getLeft() == 0) && (dst.getRight() == renderWindow->getWidth()) && (dst.getTop() == 0) && (dst.getBottom() == renderWindow->getHeight()))
+				if ((dst.getLeft() == 0) && (dst.getRight() == props.getWidth()) && (dst.getTop() == 0) && (dst.getBottom() == props.getHeight()))
 				{
 					hr = pTempSurf->LockRect(&lockedRect, 0, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
 				}
@@ -1199,7 +1202,7 @@ namespace BansheeEngine
 				SAFE_RELEASE(pStretchSurf);
 			}
 
-			if ((dst.getLeft() == 0) && (dst.getRight() == renderWindow->getWidth()) && (dst.getTop() == 0) && (dst.getBottom() == renderWindow->getHeight()))
+			if ((dst.getLeft() == 0) && (dst.getRight() == props.getWidth()) && (dst.getTop() == 0) && (dst.getBottom() == props.getHeight()))
 			{
 				hr = pTempSurf->LockRect(&lockedRect, 0, D3DLOCK_READONLY | D3DLOCK_NOSYSLOCK);
 			}

+ 5 - 5
BansheeD3D9RenderSystem/Source/BsD3D9DeviceManager.cpp

@@ -75,7 +75,7 @@ namespace BansheeEngine
 		return mRenderDevices[index];
 	}
 
-	void D3D9DeviceManager::linkRenderWindow(D3D9RenderWindow* renderWindow)
+	void D3D9DeviceManager::linkRenderWindow(D3D9RenderWindowCore* renderWindow)
 	{		
 		D3D9Device* renderDevice;
 
@@ -84,7 +84,7 @@ namespace BansheeEngine
 		if (renderDevice != nullptr)
 			renderDevice->detachRenderWindow(renderWindow);						
 
-		Vector<D3D9RenderWindow*> renderWindowsGroup;
+		Vector<D3D9RenderWindowCore*> renderWindowsGroup;
 
 		// Select new device for this window.		
 		renderDevice = selectDevice(renderWindow, renderWindowsGroup);
@@ -92,7 +92,7 @@ namespace BansheeEngine
 		// Link the windows group to the new device.
 		for (UINT32 i = 0; i < renderWindowsGroup.size(); ++i)
 		{
-			D3D9RenderWindow* currWindow = renderWindowsGroup[i];
+			D3D9RenderWindowCore* currWindow = renderWindowsGroup[i];
 
 			currWindow->_setDevice(renderDevice);
 			renderDevice->attachRenderWindow(currWindow);
@@ -104,7 +104,7 @@ namespace BansheeEngine
 			setActiveDevice(renderDevice);		
 	}
 
-	D3D9Device* D3D9DeviceManager::selectDevice(D3D9RenderWindow* renderWindow, Vector<D3D9RenderWindow*>& renderWindowsGroup)
+	D3D9Device* D3D9DeviceManager::selectDevice(D3D9RenderWindowCore* renderWindow, Vector<D3D9RenderWindowCore*>& renderWindowsGroup)
 	{
 		D3D9RenderSystem* renderSystem = static_cast<D3D9RenderSystem*>(BansheeEngine::RenderSystem::instancePtr());
 		D3D9Device*	renderDevice = nullptr;	
@@ -165,7 +165,7 @@ namespace BansheeEngine
 		return renderDevice;	
 	}
 
-	D3D9Driver* D3D9DeviceManager::findDriver(D3D9RenderWindow* renderWindow)
+	D3D9Driver* D3D9DeviceManager::findDriver(D3D9RenderWindowCore* renderWindow)
 	{
 		D3D9RenderSystem* renderSystem = static_cast<D3D9RenderSystem*>(BansheeEngine::RenderSystem::instancePtr());		
 		IDirect3D9*	direct3D9 = D3D9RenderSystem::getDirect3D9();				

+ 20 - 17
BansheeD3D9RenderSystem/Source/BsD3D9MultiRenderTexture.cpp

@@ -4,24 +4,14 @@
 
 namespace BansheeEngine
 {
-	D3D9MultiRenderTexture::D3D9MultiRenderTexture()
-		:MultiRenderTexture(), mDX9DepthStencilSurface(nullptr)
-	{
-
-	}
-
-	D3D9MultiRenderTexture::~D3D9MultiRenderTexture()
-	{
-
-	}
-
-	void D3D9MultiRenderTexture::initialize_internal()
+	D3D9MultiRenderTextureCore::D3D9MultiRenderTextureCore(D3D9MultiRenderTexture* parent, MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc)
+		:MultiRenderTextureCore(parent, properties, desc), mDX9DepthStencilSurface(nullptr)
 	{
 		mDX9ColorSurfaces.resize(mColorSurfaces.size());
 
-		for(size_t i = 0; i < mColorSurfaces.size(); i++)
+		for (size_t i = 0; i < mColorSurfaces.size(); i++)
 		{
-			if(mColorSurfaces[i] != nullptr)
+			if (mColorSurfaces[i] != nullptr)
 			{
 				D3D9Texture* d3d9texture = static_cast<D3D9Texture*>(mColorSurfaces[i]->getTexture().get());
 				D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
@@ -34,7 +24,7 @@ namespace BansheeEngine
 			}
 		}
 
-		if(mDepthStencilSurface != nullptr)
+		if (mDepthStencilSurface != nullptr)
 		{
 			D3D9Texture* d3d9DepthStencil = static_cast<D3D9Texture*>(mDepthStencilSurface->getTexture().get());
 			D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
@@ -45,11 +35,14 @@ namespace BansheeEngine
 		{
 			mDX9DepthStencilSurface = nullptr;
 		}
+	}
+
+	D3D9MultiRenderTextureCore::~D3D9MultiRenderTextureCore()
+	{
 
-		MultiRenderTexture::initialize_internal();
 	}
 
-	void D3D9MultiRenderTexture::getCustomAttribute(const String& name, void* pData) const
+	void D3D9MultiRenderTextureCore::getCustomAttribute(const String& name, void* pData) const
 	{
 		if(name == "DDBACKBUFFER")
 		{
@@ -73,4 +66,14 @@ namespace BansheeEngine
 			return;
 		}
 	}
+
+	RenderTargetProperties* D3D9MultiRenderTexture::createProperties() const
+	{
+		return bs_new<MultiRenderTextureProperties>();
+	}
+
+	MultiRenderTextureCore* D3D9MultiRenderTexture::createCore(MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc)
+	{
+		return bs_new<D3D9MultiRenderTextureCore>(this, properties, desc);
+	}
 }

+ 30 - 25
BansheeD3D9RenderSystem/Source/BsD3D9RenderSystem.cpp

@@ -172,11 +172,11 @@ namespace BansheeEngine
 		msD3D9RenderSystem = NULL;
 	}
 
-	void D3D9RenderSystem::registerWindow(RenderWindow& renderWindow)
+	void D3D9RenderSystem::registerWindow(RenderWindowCore& renderWindow)
 	{		
 		THROW_IF_NOT_CORE_THREAD;
 
-		D3D9RenderWindow* d3d9renderWindow = static_cast<D3D9RenderWindow*>(&renderWindow);
+		D3D9RenderWindowCore* d3d9renderWindow = static_cast<D3D9RenderWindowCore*>(&renderWindow);
 
 		String msg;
 
@@ -1025,18 +1025,18 @@ namespace BansheeEngine
 		HRESULT hr;
 
 		// Possibly change device if the target is a window
-		if (target->isWindow())
+		if (target->getCore()->getProperties().isWindow())
 		{
 			D3D9RenderWindow* window = static_cast<D3D9RenderWindow*>(target.get());
-			mDeviceManager->setActiveRenderTargetDevice(window->_getDevice());
-			window->_validateDevice();
+			mDeviceManager->setActiveRenderTargetDevice(window->getCore()->_getDevice());
+			window->getCore()->_validateDevice();
 		}
 
 		// Retrieve render surfaces
 		UINT32 maxRenderTargets = mCurrentCapabilities->getNumMultiRenderTargets();
 		IDirect3DSurface9** pBack = bs_newN<IDirect3DSurface9*, ScratchAlloc>(maxRenderTargets);
 		memset(pBack, 0, sizeof(IDirect3DSurface9*) * maxRenderTargets);
-		target->getCustomAttribute( "DDBACKBUFFER", pBack );
+		target->getCore()->getCustomAttribute("DDBACKBUFFER", pBack);
 		if (!pBack[0])
 		{
 			bs_deleteN<ScratchAlloc>(pBack, maxRenderTargets);
@@ -1046,7 +1046,7 @@ namespace BansheeEngine
 		IDirect3DSurface9* pDepth = NULL;
 
 		if (!pDepth)
-			target->getCustomAttribute( "D3DZBUFFER", &pDepth );
+			target->getCore()->getCustomAttribute("D3DZBUFFER", &pDepth);
 		
 		// Bind render targets
 		for(UINT32 x = 0; x < maxRenderTargets; ++x)
@@ -1083,22 +1083,24 @@ namespace BansheeEngine
 		RenderTargetPtr target = vp.getTarget();
 		setRenderTarget(target);
 
+		const RenderTargetProperties& rtProps = target->getCore()->getProperties();
+
 		setCullingMode( mCullingMode );
 
-		// set viewport dimensions
-		mViewportWidth = vp.getWidth();
-		mViewportHeight = vp.getHeight();
-		mViewportLeft = vp.getX();
-		mViewportTop = vp.getY();
+		// Set viewport dimensions
+		mViewportLeft = (UINT32)(rtProps.getWidth() * vp.getNormalizedX());
+		mViewportTop = (UINT32)(rtProps.getHeight() * vp.getNormalizedY());
+		mViewportWidth = (UINT32)(rtProps.getWidth() * vp.getNormalizedWidth());
+		mViewportHeight = (UINT32)(rtProps.getHeight() * vp.getNormalizedHeight());
 
-		d3dvp.X = vp.getX();
-		d3dvp.Y = vp.getY();
-		d3dvp.Width = vp.getWidth();
-		d3dvp.Height = vp.getHeight();
+		d3dvp.X = mViewportLeft;
+		d3dvp.Y = mViewportTop;
+		d3dvp.Width = mViewportWidth;
+		d3dvp.Height = mViewportHeight;
 		if (target->requiresTextureFlipping())
 		{
 			// Convert "top-left" to "bottom-left"
-			d3dvp.Y = target->getHeight() - d3dvp.Height - d3dvp.Y;
+			d3dvp.Y = rtProps.getHeight() - d3dvp.Height - d3dvp.Y;
 		}
 
 		// Z-values from 0.0 to 1.0 (TODO: standardise with OpenGL)
@@ -1109,7 +1111,7 @@ namespace BansheeEngine
 			BS_EXCEPT(RenderingAPIException, "Failed to set viewport.");
 
 		// Set sRGB write mode
-		setRenderState(D3DRS_SRGBWRITEENABLE, target->isHwGammaEnabled());
+		setRenderState(D3DRS_SRGBWRITEENABLE, rtProps.isHwGammaEnabled());
 	}
 
 	void D3D9RenderSystem::beginFrame()
@@ -1327,7 +1329,8 @@ namespace BansheeEngine
 		if(mActiveRenderTarget == nullptr)
 			return;
 
-		RectI clearRect(0, 0, mActiveRenderTarget->getWidth(), mActiveRenderTarget->getHeight());
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getCore()->getProperties();
+		RectI clearRect(0, 0, rtProps.getWidth(), rtProps.getHeight());
 
 		clearArea(buffers, color, depth, stencil, clearRect);
 	}
@@ -1362,17 +1365,19 @@ namespace BansheeEngine
 			flags |= D3DCLEAR_STENCIL;
 		}
 
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getCore()->getProperties();
+
 		bool clearEntireTarget = clearRect.width == 0 || clearRect.height == 0;
-		clearEntireTarget |= (clearRect.x == 0 && clearRect.y == 0 && clearRect.width == mActiveRenderTarget->getWidth() && clearRect.height == mActiveRenderTarget->getHeight());
+		clearEntireTarget |= (clearRect.x == 0 && clearRect.y == 0 && clearRect.width == rtProps.getWidth() && clearRect.height == rtProps.getHeight());
 
 		if(!clearEntireTarget)
 		{
 			D3DRECT clearD3DRect;
-			clearD3DRect.x1 = (LONG)Math::clamp(clearRect.x, 0, (INT32)mActiveRenderTarget->getWidth() - 1);
-			clearD3DRect.x2 = (LONG)Math::clamp((INT32)clearD3DRect.x1 + clearRect.width, 0, (INT32)mActiveRenderTarget->getWidth() - 1);
+			clearD3DRect.x1 = (LONG)Math::clamp(clearRect.x, 0, (INT32)rtProps.getWidth() - 1);
+			clearD3DRect.x2 = (LONG)Math::clamp((INT32)clearD3DRect.x1 + clearRect.width, 0, (INT32)rtProps.getWidth() - 1);
 
-			clearD3DRect.y1 = (LONG)Math::clamp(clearRect.y, 0, (INT32)mActiveRenderTarget->getHeight() - 1);
-			clearD3DRect.y2 = (LONG)Math::clamp((INT32)clearD3DRect.y1 + clearRect.height, 0, (INT32)mActiveRenderTarget->getHeight() - 1);
+			clearD3DRect.y1 = (LONG)Math::clamp(clearRect.y, 0, (INT32)rtProps.getHeight() - 1);
+			clearD3DRect.y2 = (LONG)Math::clamp((INT32)clearD3DRect.y1 + clearRect.height, 0, (INT32)rtProps.getHeight() - 1);
 
 			HRESULT hr;
 			if(FAILED(hr = getActiveD3D9Device()->Clear(1, &clearD3DRect, flags, color.getAsBGRA(), depth, stencil)))
@@ -1745,7 +1750,7 @@ namespace BansheeEngine
 			D3DFMT_A16B16G16R16F, D3DFMT_R32F, D3DFMT_G32R32F, 
 			D3DFMT_A32B32G32R32F};
 		IDirect3DSurface9* bbSurf;
-		renderWindow->getCustomAttribute("DDBACKBUFFER", &bbSurf);
+		renderWindow->getCore()->getCustomAttribute("DDBACKBUFFER", &bbSurf);
 		D3DSURFACE_DESC bbSurfDesc;
 		bbSurf->GetDesc(&bbSurfDesc);
 

+ 24 - 18
BansheeD3D9RenderSystem/Source/BsD3D9RenderTexture.cpp

@@ -6,25 +6,20 @@
 
 namespace BansheeEngine
 {
-	D3D9RenderTexture::D3D9RenderTexture()
-		:mDX9ColorSurface(nullptr), mDX9DepthStencilSurface(nullptr), mIsBindableToShader(false)
+	D3D9RenderTextureCore::D3D9RenderTextureCore(D3D9RenderTexture* parent, RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+		const RENDER_SURFACE_DESC& depthStencilSurfaceDesc)
+		:RenderTextureCore(parent, properties, colorSurfaceDesc, depthStencilSurfaceDesc), mDX9ColorSurface(nullptr), 
+		mDX9DepthStencilSurface(nullptr), mIsBindableToShader(false)
 	{
-
-	}
-
-	D3D9RenderTexture::~D3D9RenderTexture()
-	{
-
+		initializeSurfaces();
 	}
 
-	void D3D9RenderTexture::initialize_internal()
+	D3D9RenderTextureCore::~D3D9RenderTextureCore()
 	{
-		initializeSurfaces();
 
-		RenderTexture::initialize_internal();
 	}
 
-	void D3D9RenderTexture::initializeSurfaces()
+	void D3D9RenderTextureCore::initializeSurfaces()
 	{
 		D3D9Texture* d3d9texture = static_cast<D3D9Texture*>(mColorSurface->getTexture().get());
 		D3D9PixelBuffer* pixelBuffer = static_cast<D3D9PixelBuffer*>(
@@ -37,14 +32,14 @@ namespace BansheeEngine
 		mDX9DepthStencilSurface = depthStencilBuffer->getSurface(D3D9RenderSystem::getActiveD3D9Device());
 	}
 
-	void D3D9RenderTexture::releaseSurfaces()
+	void D3D9RenderTextureCore::releaseSurfaces()
 	{
 		// All actual releasing happens in the color and depth textures.
 		mDX9ColorSurface = nullptr;
 		mDX9DepthStencilSurface = nullptr;
 	}
 
-	void D3D9RenderTexture::getCustomAttribute(const String& name, void* pData) const
+	void D3D9RenderTextureCore::getCustomAttribute(const String& name, void* pData) const
 	{
 		if(name == "DDBACKBUFFER")
 		{
@@ -66,23 +61,34 @@ namespace BansheeEngine
 		}
 	}
 
-	void D3D9RenderTexture::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
+	void D3D9RenderTextureCore::notifyOnDeviceCreate(IDirect3DDevice9* d3d9Device)
 	{
 		initializeSurfaces();
 	}
 
-	void D3D9RenderTexture::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
+	void D3D9RenderTextureCore::notifyOnDeviceDestroy(IDirect3DDevice9* d3d9Device)
 	{
 		releaseSurfaces();
 	}
 
-	void D3D9RenderTexture::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
+	void D3D9RenderTextureCore::notifyOnDeviceLost(IDirect3DDevice9* d3d9Device)
 	{
 		releaseSurfaces();
 	}
 
-	void D3D9RenderTexture::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
+	void D3D9RenderTextureCore::notifyOnDeviceReset(IDirect3DDevice9* d3d9Device)
 	{
 		initializeSurfaces();
 	}
+
+	RenderTargetProperties* D3D9RenderTexture::createProperties() const
+	{
+		return bs_new<RenderTextureProperties>();
+	}
+
+	RenderTextureCore* D3D9RenderTexture::createCore(RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+		const RENDER_SURFACE_DESC& depthStencilSurfaceDesc)
+	{
+		return bs_new<D3D9RenderTextureCore>(this, properties, colorSurfaceDesc, depthStencilSurfaceDesc);
+	}
 }

+ 209 - 175
BansheeD3D9RenderSystem/Source/BsD3D9RenderWindow.cpp

@@ -12,44 +12,26 @@
 
 namespace BansheeEngine
 {
-	D3D9RenderWindow::D3D9RenderWindow(const RENDER_WINDOW_DESC& desc, HINSTANCE instance)
-		: RenderWindow(desc), mInstance(instance), mIsDepthBuffered(true), mIsChild(false),
-		mStyle(0), mWindowedStyle(0), mWindowedStyleEx(0)
-	{
-		mDevice = NULL;
-		mIsFullScreen = false;		
-		mIsExternal = false;
-		mHWnd = 0;
-		mActive = false;		
-		mClosed = false;
-		mDisplayFrequency = 0;
-		mDeviceValid = false;
-	}
-
-	D3D9RenderWindow::~D3D9RenderWindow()
-	{ }
-
-	void D3D9RenderWindow::initialize_internal()
+	D3D9RenderWindowCore::D3D9RenderWindowCore(D3D9RenderWindow* parent, RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc, HINSTANCE instance)
+		: RenderWindowCore(parent, properties), mInstance(instance), mIsDepthBuffered(true), mIsChild(false),
+		mStyle(0), mWindowedStyle(0), mWindowedStyleEx(0), mDevice(nullptr), mIsExternal(false), mHWnd(0), mDisplayFrequency(0), mDeviceValid(false)
 	{
 		HINSTANCE hInst = mInstance;
 
 		mMultisampleType = D3DMULTISAMPLE_NONE;
 		mMultisampleQuality = 0;
-		mMultisampleCount = mDesc.multisampleCount;
-		mVSync = mDesc.vsync;
-		mVSyncInterval = mDesc.vsyncInterval;
-		mDisplayFrequency = Math::roundToInt(mDesc.videoMode.getRefreshRate());
+		mDisplayFrequency = Math::roundToInt(desc.videoMode.getRefreshRate());
 
 		HWND parentHWnd = 0;
 		HWND externalHandle = 0;
 
 		NameValuePairList::const_iterator opt;
-		opt = mDesc.platformSpecific.find("parentWindowHandle");
-		if(opt != mDesc.platformSpecific.end())
+		opt = desc.platformSpecific.find("parentWindowHandle");
+		if (opt != desc.platformSpecific.end())
 			parentHWnd = (HWND)parseUnsignedInt(opt->second);
 
-		opt = mDesc.platformSpecific.find("externalWindowHandle");
-		if(opt != mDesc.platformSpecific.end())
+		opt = desc.platformSpecific.find("externalWindowHandle");
+		if (opt != desc.platformSpecific.end())
 			externalHandle = (HWND)parseUnsignedInt(opt->second);
 
 		mIsChild = parentHWnd != 0;
@@ -57,21 +39,21 @@ namespace BansheeEngine
 		mWindowedStyle = WS_VISIBLE | WS_CLIPCHILDREN;
 		mWindowedStyleEx = 0;
 
-		if (!mDesc.fullscreen || mIsChild)
+		if (!desc.fullscreen || mIsChild)
 		{
 			if (parentHWnd)
 			{
-				if (mDesc.toolWindow)
+				if (desc.toolWindow)
 					mWindowedStyleEx = WS_EX_TOOLWINDOW;
 				else
 					mWindowedStyle |= WS_CHILD;
 			}
 
-			if (!parentHWnd || mDesc.toolWindow)
+			if (!parentHWnd || desc.toolWindow)
 			{
-				if (mDesc.border == WindowBorder::None)
+				if (desc.border == WindowBorder::None)
 					mWindowedStyle |= WS_POPUP;
-				else if (mDesc.border == WindowBorder::Fixed)
+				else if (desc.border == WindowBorder::Fixed)
 					mWindowedStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
 					WS_SYSMENU | WS_MINIMIZEBOX;
 				else
@@ -79,6 +61,7 @@ namespace BansheeEngine
 			}
 		}
 
+		D3D9RenderWindowProperties* props = static_cast<D3D9RenderWindowProperties*>(mProperties);
 		if (!externalHandle)
 		{
 			MONITORINFO monitorInfo;
@@ -89,7 +72,7 @@ namespace BansheeEngine
 			UINT32 numOutputs = videoModeInfo.getNumOutputs();
 			if (numOutputs > 0)
 			{
-				UINT32 actualMonitorIdx = std::min(mDesc.videoMode.getOutputIdx(), numOutputs - 1);
+				UINT32 actualMonitorIdx = std::min(desc.videoMode.getOutputIdx(), numOutputs - 1);
 				const D3D9VideoOutputInfo& outputInfo = static_cast<const D3D9VideoOutputInfo&>(videoModeInfo.getOutputInfo(actualMonitorIdx));
 				hMonitor = outputInfo.getMonitorHandle();
 			}
@@ -100,8 +83,8 @@ namespace BansheeEngine
 				POINT windowAnchorPoint;
 
 				// Fill in anchor point.
-				windowAnchorPoint.x = mDesc.left;
-				windowAnchorPoint.y = mDesc.top;
+				windowAnchorPoint.x = desc.left;
+				windowAnchorPoint.y = desc.top;
 
 				// Get the nearest monitor to this window.
 				hMonitor = MonitorFromPoint(windowAnchorPoint, MONITOR_DEFAULTTOPRIMARY);
@@ -113,21 +96,21 @@ namespace BansheeEngine
 			GetMonitorInfo(hMonitor, &monitorInfo);
 
 			unsigned int winWidth, winHeight;
-			winWidth = mDesc.videoMode.getWidth();
-			winHeight = mDesc.videoMode.getHeight();
+			winWidth = desc.videoMode.getWidth();
+			winHeight = desc.videoMode.getHeight();
 
-			UINT32 left = mDesc.left;
-			UINT32 top = mDesc.top;
+			UINT32 left = desc.left;
+			UINT32 top = desc.top;
 
 			// No specified top left -> Center the window in the middle of the monitor
 			if (left == -1 || top == -1)
-			{				
-				int screenw = monitorInfo.rcWork.right  - monitorInfo.rcWork.left;
+			{
+				int screenw = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
 				int screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
 
 				// clamp window dimensions to screen size
-				int outerw = (int(winWidth) < screenw)? int(winWidth) : screenw;
-				int outerh = (int(winHeight) < screenh)? int(winHeight) : screenh;
+				int outerw = (int(winWidth) < screenw) ? int(winWidth) : screenw;
+				int outerh = (int(winHeight) < screenh) ? int(winHeight) : screenh;
 
 				if (left == -1)
 					left = monitorInfo.rcWork.left + (screenw - outerw) / 2;
@@ -145,47 +128,47 @@ namespace BansheeEngine
 				top += monitorInfo.rcWork.top;
 			}
 
-			mWidth = mDesc.videoMode.getWidth();
-			mHeight =  mDesc.videoMode.getHeight();
-			mTop = top;
-			mLeft = left;
+			props->mWidth = desc.videoMode.getWidth();
+			props->mHeight = desc.videoMode.getHeight();
+			props->mTop = top;
+			props->mLeft = left;
 
 			DWORD dwStyle = 0;
 			DWORD dwStyleEx = 0;
-			if (mDesc.fullscreen && !mIsChild)
+			if (desc.fullscreen && !mIsChild)
 			{
 				dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_POPUP;
-				mTop = monitorInfo.rcMonitor.top;
-				mLeft = monitorInfo.rcMonitor.left;		
+				props->mTop = monitorInfo.rcMonitor.top;
+				props->mLeft = monitorInfo.rcMonitor.left;
 			}
 			else
 			{
 				dwStyle = mWindowedStyle;
 				dwStyleEx = mWindowedStyleEx;
 
-				getAdjustedWindowSize(mDesc.videoMode.getWidth(), mDesc.videoMode.getHeight(), dwStyle, &winWidth, &winHeight);
+				getAdjustedWindowSize(desc.videoMode.getWidth(), desc.videoMode.getHeight(), dwStyle, &winWidth, &winHeight);
 
-				if (!mDesc.outerDimensions)
+				if (!desc.outerDimensions)
 				{
 					// Calculate window dimensions required
 					// to get the requested client area
-					SetRect(&rc, 0, 0, mWidth, mHeight);
+					SetRect(&rc, 0, 0, props->mWidth, props->mHeight);
 					AdjustWindowRect(&rc, dwStyle, false);
-					mWidth = rc.right - rc.left;
-					mHeight = rc.bottom - rc.top;
+					props->mWidth = rc.right - rc.left;
+					props->mHeight = rc.bottom - rc.top;
 
 					// Clamp window rect to the nearest display monitor.
-					if (mLeft < monitorInfo.rcWork.left)
-						mLeft = monitorInfo.rcWork.left;		
+					if (props->mLeft < monitorInfo.rcWork.left)
+						props->mLeft = monitorInfo.rcWork.left;
 
-					if (mTop < monitorInfo.rcWork.top)					
-						mTop = monitorInfo.rcWork.top;					
+					if (props->mTop < monitorInfo.rcWork.top)
+						props->mTop = monitorInfo.rcWork.top;
 
-					if (static_cast<int>(winWidth) > monitorInfo.rcWork.right - mLeft)					
-						winWidth = monitorInfo.rcWork.right - mLeft;	
+					if (static_cast<int>(winWidth) > monitorInfo.rcWork.right - props->mLeft)
+						winWidth = monitorInfo.rcWork.right - props->mLeft;
 
-					if (static_cast<int>(winHeight) > monitorInfo.rcWork.bottom - mTop)					
-						winHeight = monitorInfo.rcWork.bottom - mTop;										
+					if (static_cast<int>(winHeight) > monitorInfo.rcWork.bottom - props->mTop)
+						winHeight = monitorInfo.rcWork.bottom - props->mTop;
 				}
 			}
 
@@ -199,8 +182,8 @@ namespace BansheeEngine
 			// Create our main window
 			// Pass pointer to self
 			mIsExternal = false;
-			mHWnd = CreateWindowEx(dwStyleEx, "D3D9Wnd", mDesc.title.c_str(), dwStyle,
-				mLeft, mTop, winWidth, winHeight, parentHWnd, 0, hInst, this);
+			mHWnd = CreateWindowEx(dwStyleEx, "D3D9Wnd", desc.title.c_str(), dwStyle,
+				props->mLeft, props->mTop, winWidth, winHeight, parentHWnd, 0, hInst, this);
 			mStyle = dwStyle;
 		}
 		else
@@ -211,33 +194,29 @@ namespace BansheeEngine
 
 		RECT rc;
 		GetWindowRect(mHWnd, &rc);
-		mTop = rc.top;
-		mLeft = rc.left;
+		props->mTop = rc.top;
+		props->mLeft = rc.left;
 
 		GetClientRect(mHWnd, &rc);
-		mWidth = rc.right;
-		mHeight = rc.bottom;
-
-		mName = mDesc.title;
-		mIsDepthBuffered = mDesc.depthBuffer;
-		mIsFullScreen = mDesc.fullscreen && !mIsChild;
-		mColorDepth = 32;
+		props->mWidth = rc.right;
+		props->mHeight = rc.bottom;
 
-		mActive = true;
-		mClosed = false;
+		props->mName = desc.title;
+		mIsDepthBuffered = desc.depthBuffer;
+		props->mIsFullScreen = desc.fullscreen && !mIsChild;
+		props->mColorDepth = 32;
+		props->mActive = true;
 
 		D3D9RenderSystem* rs = static_cast<D3D9RenderSystem*>(RenderSystem::instancePtr());
 		rs->registerWindow(*this);
-
-		RenderWindow::initialize_internal();
 	}
 
-	void D3D9RenderWindow::destroy_internal()
+	D3D9RenderWindowCore::~D3D9RenderWindowCore()
 	{
-		if (mDevice != NULL)
+		if (mDevice != nullptr)
 		{
 			mDevice->detachRenderWindow(this);
-			mDevice = NULL;
+			mDevice = nullptr;
 		}
 
 		if (mHWnd && !mIsExternal)
@@ -246,13 +225,14 @@ namespace BansheeEngine
 		}
 
 		mHWnd = 0;
-		mActive = false;
-		mClosed = true;
 
-		RenderWindow::destroy_internal();
+		D3D9RenderWindowProperties* props = static_cast<D3D9RenderWindowProperties*>(mProperties);
+		props->mActive = false;
+
+		markCoreDirty();
 	}
 
-	void D3D9RenderWindow::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
+	void D3D9RenderWindowCore::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -267,13 +247,14 @@ namespace BansheeEngine
 		UINT32 actualMonitorIdx = std::min(monitorIdx, numOutputs - 1);
 		const D3D9VideoOutputInfo& outputInfo = static_cast<const D3D9VideoOutputInfo&>(videoModeInfo.getOutputInfo(actualMonitorIdx));
 
-		bool oldFullscreen = mIsFullScreen;
+		D3D9RenderWindowProperties* props = static_cast<D3D9RenderWindowProperties*>(mProperties);
+		bool oldFullscreen = props->mIsFullScreen;
 
-		mWidth = width;
-		mHeight = height;
+		props->mWidth = width;
+		props->mHeight = height;
 		mDisplayFrequency = Math::roundToInt(refreshRate);
 
-		mIsFullScreen = true;
+		props->mIsFullScreen = true;
 
 		HMONITOR hMonitor = outputInfo.getMonitorHandle();
 		MONITORINFO monitorInfo;
@@ -282,35 +263,39 @@ namespace BansheeEngine
 		monitorInfo.cbSize = sizeof(MONITORINFO);
 		GetMonitorInfo(hMonitor, &monitorInfo);
 
-		mTop = monitorInfo.rcMonitor.top;
-		mLeft = monitorInfo.rcMonitor.left;
+		props->mTop = monitorInfo.rcMonitor.top;
+		props->mLeft = monitorInfo.rcMonitor.left;
 
 		// Invalidate device, which resets it
 		mDevice->invalidate(this);
 		mDevice->acquire();
+
+		markCoreDirty();
 	}
 
-	void D3D9RenderWindow::setFullscreen(const VideoMode& mode)
+	void D3D9RenderWindowCore::setFullscreen(const VideoMode& mode)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		setFullscreen(mode.getWidth(), mode.getHeight(), mode.getRefreshRate(), mode.getOutputIdx());
 	}
 
-	void D3D9RenderWindow::setWindowed(UINT32 width, UINT32 height)
+	void D3D9RenderWindowCore::setWindowed(UINT32 width, UINT32 height)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if (!mIsFullScreen)
+		D3D9RenderWindowProperties* props = static_cast<D3D9RenderWindowProperties*>(mProperties);
+
+		if (!props->mIsFullScreen)
 			return;
 
-		mIsFullScreen = false;
+		props->mIsFullScreen = false;
 		mStyle = mWindowedStyle;
-		mWidth = width;
-		mHeight = height;
+		props->mWidth = width;
+		props->mHeight = height;
 
 		unsigned int winWidth, winHeight;
-		getAdjustedWindowSize(mWidth, mHeight, mStyle, &winWidth, &winHeight);
+		getAdjustedWindowSize(props->mWidth, props->mHeight, mStyle, &winWidth, &winHeight);
 
 		// Deal with centering when switching down to smaller resolution
 		HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
@@ -332,13 +317,17 @@ namespace BansheeEngine
 
 		mDevice->invalidate(this);
 		mDevice->acquire();
+
+		markCoreDirty();
 	}
 
-	void D3D9RenderWindow::setHidden(bool hidden)
+	void D3D9RenderWindowCore::setHidden(bool hidden)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		mHidden = hidden;
+		D3D9RenderWindowProperties* props = static_cast<D3D9RenderWindowProperties*>(mProperties);
+
+		props->mHidden = hidden;
 		if (!mIsExternal)
 		{
 			if (hidden)
@@ -346,53 +335,48 @@ namespace BansheeEngine
 			else
 				ShowWindow(mHWnd, SW_SHOWNORMAL);
 		}
-	}
-
-	bool D3D9RenderWindow::isActive() const
-	{
-		if (isFullScreen())
-			return isVisible();
-
-		return mActive && isVisible();
-	}
 
-	bool D3D9RenderWindow::isVisible() const
-	{
-		return (mHWnd && !IsIconic(mHWnd));
+		markCoreDirty();
 	}
 
-	void D3D9RenderWindow::move(INT32 top, INT32 left)
+	void D3D9RenderWindowCore::move(INT32 top, INT32 left)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if (mHWnd && !mIsFullScreen)
+		D3D9RenderWindowProperties* props = static_cast<D3D9RenderWindowProperties*>(mProperties);
+
+		if (mHWnd && !props->mIsFullScreen)
 		{
-			mLeft = left;
-			mTop = top;
+			props->mLeft = left;
+			props->mTop = top;
 
-			SetWindowPos(mHWnd, 0, top, left, 0, 0,
-				SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+			SetWindowPos(mHWnd, 0, top, left, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+			markCoreDirty();
 		}
 	}
 
-	void D3D9RenderWindow::resize(UINT32 width, UINT32 height)
+	void D3D9RenderWindowCore::resize(UINT32 width, UINT32 height)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if (mHWnd && !mIsFullScreen)
+		D3D9RenderWindowProperties* props = static_cast<D3D9RenderWindowProperties*>(mProperties);
+
+		if (mHWnd && !props->mIsFullScreen)
 		{
-			mWidth = width;
-			mHeight = height;
+			props->mWidth = width;
+			props->mHeight = height;
 
 			unsigned int winWidth, winHeight;
 			getAdjustedWindowSize(width, height, mStyle, &winWidth, &winHeight);
 
 			SetWindowPos(mHWnd, 0, 0, 0, winWidth, winHeight,
 				SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+
+			markCoreDirty();
 		}
 	}
 
-	void D3D9RenderWindow::getCustomAttribute( const String& name, void* pData ) const
+	void D3D9RenderWindowCore::getCustomAttribute(const String& name, void* pData) const
 	{
 		// Valid attributes and their equivalent native functions:
 		// D3DDEVICE			: getD3DDevice
@@ -437,7 +421,7 @@ namespace BansheeEngine
 		}
 	}
 
-	void D3D9RenderWindow::swapBuffers()
+	void D3D9RenderWindowCore::swapBuffers()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -445,34 +429,14 @@ namespace BansheeEngine
 			mDevice->present(this);		
 	}
 
-	Vector2I D3D9RenderWindow::screenToWindowPos(const Vector2I& screenPos) const
-	{
-		POINT pos;
-		pos.x = screenPos.x;
-		pos.y = screenPos.y;
-
-		ScreenToClient(mHWnd, &pos);
-		return Vector2I(pos.x, pos.y);
-	}
-
-	Vector2I D3D9RenderWindow::windowToScreenPos(const Vector2I& windowPos) const
-	{
-		POINT pos;
-		pos.x = windowPos.x;
-		pos.y = windowPos.y;
-
-		ClientToScreen(mHWnd, &pos);
-		return Vector2I(pos.x, pos.y);
-	}
-
-	void D3D9RenderWindow::copyToMemory(PixelData &dst, FrameBuffer buffer)
+	void D3D9RenderWindowCore::copyToMemory(PixelData &dst, FrameBuffer buffer)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		mDevice->copyContentsToMemory(this, dst, buffer);
 	}
 
-	void D3D9RenderWindow::_windowMovedOrResized()
+	void D3D9RenderWindowCore::_windowMovedOrResized()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -481,14 +445,14 @@ namespace BansheeEngine
 	
 		updateWindowRect();
 
-		RenderWindow::_windowMovedOrResized();
+		RenderWindowCore::_windowMovedOrResized();
 	}
 
 	/************************************************************************/
 	/* 						D3D9 IMPLEMENTATION SPECIFIC                    */
 	/************************************************************************/
 
-	void D3D9RenderWindow::getAdjustedWindowSize(UINT32 clientWidth, UINT32 clientHeight,
+	void D3D9RenderWindowCore::getAdjustedWindowSize(UINT32 clientWidth, UINT32 clientHeight,
 		DWORD style, UINT32* winWidth, UINT32* winHeight)
 	{
 		RECT rc;
@@ -514,7 +478,7 @@ namespace BansheeEngine
 			*winHeight = maxH;
 	}
 	
-	void D3D9RenderWindow::_buildPresentParameters(D3DPRESENT_PARAMETERS* presentParams) const
+	void D3D9RenderWindowCore::_buildPresentParameters(D3DPRESENT_PARAMETERS* presentParams) const
 	{			
 		IDirect3D9* pD3D = D3D9RenderSystem::getDirect3D9();
 		D3DDEVTYPE devType = D3DDEVTYPE_HAL;
@@ -523,14 +487,14 @@ namespace BansheeEngine
 			devType = mDevice->getDeviceType();		
 	
 		ZeroMemory( presentParams, sizeof(D3DPRESENT_PARAMETERS) );
-		presentParams->Windowed = !mIsFullScreen;
+		presentParams->Windowed = !getProperties().isFullScreen();
 		presentParams->SwapEffect = D3DSWAPEFFECT_DISCARD;
 		presentParams->BackBufferCount = 1;
 		presentParams->EnableAutoDepthStencil = mIsDepthBuffered;
 		presentParams->hDeviceWindow = mHWnd;
-		presentParams->BackBufferWidth = mWidth;
-		presentParams->BackBufferHeight	= mHeight;
-		presentParams->FullScreen_RefreshRateInHz = mIsFullScreen ? mDisplayFrequency : 0;
+		presentParams->BackBufferWidth = getProperties().getWidth();
+		presentParams->BackBufferHeight	= getProperties().getHeight();
+		presentParams->FullScreen_RefreshRateInHz = getProperties().isFullScreen() ? mDisplayFrequency : 0;
 		
 		if (presentParams->BackBufferWidth == 0)		
 			presentParams->BackBufferWidth = 1;					
@@ -538,9 +502,9 @@ namespace BansheeEngine
 		if (presentParams->BackBufferHeight == 0)	
 			presentParams->BackBufferHeight = 1;					
 
-		if (mVSync)
+		if (getProperties().getVSync())
 		{
-			if (mIsFullScreen)
+			if (getProperties().isFullScreen())
 			{
 				switch(mVSyncInterval)
 				{
@@ -612,76 +576,146 @@ namespace BansheeEngine
 		D3DMULTISAMPLE_TYPE multisampleType;
 		DWORD multisampleQuality;
 
-		rs->determineMultisampleSettings(mDevice->getD3D9Device(), mMultisampleCount, mMultisampleHint, 
-			presentParams->BackBufferFormat, mIsFullScreen, &multisampleType, &multisampleQuality);
+		rs->determineMultisampleSettings(mDevice->getD3D9Device(), getProperties().getMultisampleCount(), getProperties().getMultisampleHint(), 
+			presentParams->BackBufferFormat, getProperties().isFullScreen(), &multisampleType, &multisampleQuality);
 
 		presentParams->MultiSampleType = multisampleType;
 		presentParams->MultiSampleQuality = (multisampleQuality == 0) ? 0 : multisampleQuality;
 	}
 
-	IDirect3DDevice9* D3D9RenderWindow::_getD3D9Device() const
+	IDirect3DDevice9* D3D9RenderWindowCore::_getD3D9Device() const
 	{
 		return mDevice->getD3D9Device();
 	}
 
-	IDirect3DSurface9* D3D9RenderWindow::_getRenderSurface() const 
+	IDirect3DSurface9* D3D9RenderWindowCore::_getRenderSurface() const
 	{
 		return mDevice->getBackBuffer(this);
 	}
 
-	D3D9Device* D3D9RenderWindow::_getDevice() const
+	D3D9Device* D3D9RenderWindowCore::_getDevice() const
 	{
 		return mDevice;
 	}
 
-	void D3D9RenderWindow::_setDevice(D3D9Device* device)
+	void D3D9RenderWindowCore::_setDevice(D3D9Device* device)
 	{
 		mDevice = device;
 		mDeviceValid = false;
 	}
 
-	bool D3D9RenderWindow::_isDepthBuffered() const
+	bool D3D9RenderWindowCore::_isDepthBuffered() const
 	{
 		return mIsDepthBuffered;
 	}
 
-	void D3D9RenderWindow::updateWindowRect()
+	void D3D9RenderWindowCore::updateWindowRect()
 	{
 		RECT rc;
 		BOOL result;
 
+		D3D9RenderWindowProperties* props = static_cast<D3D9RenderWindowProperties*>(mProperties);
+
 		// Update top left parameters
 		result = GetWindowRect(mHWnd, &rc);
 		if (result == FALSE)
 		{
-			mTop = 0;
-			mLeft = 0;
-			mWidth = 0;
-			mHeight = 0;
+			props->mTop = 0;
+			props->mLeft = 0;
+			props->mWidth = 0;
+			props->mHeight = 0;
+
+			markCoreDirty();
 			return;
 		}
 		
-		mTop = rc.top;
-		mLeft = rc.left;
+		props->mTop = rc.top;
+		props->mLeft = rc.left;
 
 		// Width and height represent drawable area only
 		result = GetClientRect(mHWnd, &rc);
 		if (result == FALSE)
 		{
-			mTop = 0;
-			mLeft = 0;
-			mWidth = 0;
-			mHeight = 0;
+			props->mTop = 0;
+			props->mLeft = 0;
+			props->mWidth = 0;
+			props->mHeight = 0;
+
+			markCoreDirty();
 			return;
 		}
 
-		mWidth  = rc.right - rc.left;
-		mHeight = rc.bottom - rc.top;	
+		props->mWidth = rc.right - rc.left;
+		props->mHeight = rc.bottom - rc.top;
+
+		markCoreDirty();
 	}
 
-	bool D3D9RenderWindow::_validateDevice()
+	bool D3D9RenderWindowCore::_validateDevice()
 	{
 		mDeviceValid = mDevice->validate(this);
 		return mDeviceValid;
 	}
+
+	D3D9RenderWindow::D3D9RenderWindow(HINSTANCE instance)
+		:mInstance(instance), mHWnd(0)
+	{
+
+	}
+
+	void D3D9RenderWindow::getCustomAttribute(const String& name, void* pData) const
+	{
+		THROW_IF_CORE_THREAD;
+
+		if (name == "WINDOW")
+		{
+			HWND *pWnd = (HWND*)pData;
+			*pWnd = mHWnd;
+			return;
+		}
+
+		RenderWindow::getCustomAttribute(name, pData);
+	}
+
+	Vector2I D3D9RenderWindow::screenToWindowPos(const Vector2I& screenPos) const
+	{
+		POINT pos;
+		pos.x = screenPos.x;
+		pos.y = screenPos.y;
+
+		ScreenToClient(mHWnd, &pos);
+		return Vector2I(pos.x, pos.y);
+	}
+
+	Vector2I D3D9RenderWindow::windowToScreenPos(const Vector2I& windowPos) const
+	{
+		POINT pos;
+		pos.x = windowPos.x;
+		pos.y = windowPos.y;
+
+		ClientToScreen(mHWnd, &pos);
+		return Vector2I(pos.x, pos.y);
+	}
+
+	void D3D9RenderWindow::initialize_internal()
+	{
+		RenderWindow::initialize_internal();
+
+		mCore->getCustomAttribute("WINDOW", (void*)&mHWnd);
+	}
+
+	D3D9RenderWindowCore* D3D9RenderWindow::getCore() const
+	{
+		return static_cast<D3D9RenderWindowCore*>(mCore);
+	}
+
+	RenderTargetProperties* D3D9RenderWindow::createProperties() const
+	{
+		return bs_new<RenderWindowProperties>();
+	}
+
+	RenderWindowCore* D3D9RenderWindow::createCore(RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc)
+	{
+		return bs_new<D3D9RenderWindowCore>(this, properties, desc, mInstance);
+	}
 }

+ 1 - 1
BansheeD3D9RenderSystem/Source/BsD3D9RenderWindowManager.cpp

@@ -20,7 +20,7 @@ namespace BansheeEngine
 			desc.platformSpecific["parentWindowHandle"] = toString((UINT64)hWnd);
 		}
 
-		D3D9RenderWindow* window = new (bs_alloc<D3D9RenderWindow, PoolAlloc>()) D3D9RenderWindow(desc, mRenderSystem->getInstanceHandle());
+		D3D9RenderWindow* window = new (bs_alloc<D3D9RenderWindow, PoolAlloc>()) D3D9RenderWindow(mRenderSystem->getInstanceHandle());
 
 		return RenderWindowPtr(window, &CoreObject::_deleteDelayed<D3D9RenderWindow, PoolAlloc>);
 	}

+ 4 - 4
BansheeEditor/Source/BsEditorWindowBase.cpp

@@ -91,21 +91,21 @@ namespace BansheeEngine
 
 	INT32 EditorWindowBase::getLeft() const
 	{
-		return mRenderWindow->getLeft();
+		return mRenderWindow->getProperties().getLeft();
 	}
 
 	INT32 EditorWindowBase::getTop() const
 	{
-		return mRenderWindow->getTop();
+		return mRenderWindow->getProperties().getTop();
 	}
 
 	UINT32 EditorWindowBase::getWidth() const
 	{
-		return (UINT32) mRenderWindow->getWidth();
+		return (UINT32)mRenderWindow->getProperties().getWidth();
 	}
 
 	UINT32 EditorWindowBase::getHeight() const
 	{
-		return (UINT32) mRenderWindow->getHeight();
+		return (UINT32)mRenderWindow->getProperties().getHeight();
 	}
 }

+ 1 - 1
BansheeEditor/Source/BsGUIResourceTreeView.cpp

@@ -449,7 +449,7 @@ namespace BansheeEngine
 	{
 		GUITreeView::_changeParentWidget(widget);
 
-		if (widget != nullptr && widget->getTarget()->getTarget()->isWindow())
+		if (widget != nullptr && widget->getTarget()->getTarget()->getProperties().isWindow())
 		{
 			RenderWindow* parentWindow = static_cast<RenderWindow*>(widget->getTarget()->getTarget().get());
 			setDropTarget(parentWindow, _getOffset().x, _getOffset().y, _getWidth(), _getHeight());

+ 1 - 1
BansheeEditor/Source/BsGUIWindowFrameWidget.cpp

@@ -47,7 +47,7 @@ namespace BansheeEngine
 
 	void WindowFrameWidget::ownerWindowFocusChanged()
 	{
-		mWindowFrame->setFocused(mParentWindow->hasFocus());
+		mWindowFrame->setFocused(mParentWindow->getProperties().hasFocus());
 
 		GUIWidget::ownerWindowFocusChanged();
 	}

+ 2 - 1
BansheeEditor/Source/BsSceneEditorWidget.cpp

@@ -12,6 +12,7 @@
 #include "BsSceneCameraController.h"
 #include "BsCamera.h"
 #include "BsGUIRenderTexture.h"
+#include "BsCoreThread.h"
 
 namespace BansheeEngine
 {
@@ -49,7 +50,7 @@ namespace BansheeEngine
 			mSceneRenderTarget->destroy();
 
 		mSceneRenderTarget = RenderTexture::create(TEX_TYPE_2D, width, height);
-		mSceneRenderTarget->setPriority(1);
+		gCoreAccessor().setPriority(mSceneRenderTarget, 1);
 
 		if (mCamera == nullptr)
 		{

+ 1 - 1
BansheeEditorExec/BsEditorExec.cpp

@@ -11,7 +11,7 @@ int CALLBACK WinMain(
 	_In_  int nCmdShow
 	)
 {
-	EditorApplication::startUp(RenderSystemPlugin::DX11);
+	EditorApplication::startUp(RenderSystemPlugin::OpenGL);
 	EditorApplication::instance().runMainLoop();
 	EditorApplication::shutDown();
 

+ 3 - 2
BansheeEngine/Source/BsGUIManager.cpp

@@ -1416,6 +1416,7 @@ namespace BansheeEngine
 		// so that mInputBridge map allows us to search through it - we don't access anything unless the target is bridged
 		// (in which case we know it is a RenderTexture)
 		const RenderTexture* renderTexture = static_cast<const RenderTexture*>(widget.getTarget()->getTarget().get());
+		const RenderTargetProperties& rtProps = renderTexture->getProperties();
 
 		auto iterFind = mInputBridge.find(renderTexture);
 		if(iterFind != mInputBridge.end()) // Widget input is bridged, which means we need to transform the coordinates
@@ -1431,8 +1432,8 @@ namespace BansheeEngine
 			float x = vecLocalPos.x - (float)bridgeBounds.x;
 			float y = vecLocalPos.y - (float)bridgeBounds.y;
 
-			float scaleX = renderTexture->getWidth() / (float)bridgeBounds.width;
-			float scaleY = renderTexture->getHeight() / (float)bridgeBounds.height;
+			float scaleX = rtProps.getWidth() / (float)bridgeBounds.width;
+			float scaleY = rtProps.getHeight() / (float)bridgeBounds.height;
 
 			return Vector2I(Math::roundToInt(x * scaleX), Math::roundToInt(y * scaleY));
 		}

+ 5 - 4
BansheeEngine/Source/BsGUIViewport.cpp

@@ -84,11 +84,12 @@ namespace BansheeEngine
 
 		ViewportPtr viewport = mCamera->getViewport();
 		RenderTargetPtr renderTarget = viewport->getTarget();
+		const RenderTargetProperties& rtProps = renderTarget->getProperties();
 
-		float x = mOffset.x / (float)renderTarget->getWidth();
-		float y = mOffset.y / (float)renderTarget->getHeight();
-		float width = mWidth / (float)renderTarget->getWidth();
-		float height = mHeight / (float)renderTarget->getHeight();
+		float x = mOffset.x / (float)rtProps.getWidth();
+		float y = mOffset.y / (float)rtProps.getHeight();
+		float width = mWidth / (float)rtProps.getWidth();
+		float height = mHeight / (float)rtProps.getHeight();
 
 		viewport->setArea(x, y, width, height);
 	}

+ 33 - 13
BansheeGLRenderSystem/Include/BsGLMultiRenderTexture.h

@@ -6,38 +6,58 @@
 
 namespace BansheeEngine
 {
+	class GLMultiRenderTexture;
+
 	/**
 	 * @brief	OpenGL implementation of a render texture with multiple color surfaces.
+	 *
+	 * @note	Core thread only.
 	 */
-	class BS_RSGL_EXPORT GLMultiRenderTexture : public MultiRenderTexture
+	class BS_RSGL_EXPORT GLMultiRenderTextureCore : public MultiRenderTextureCore
 	{
 	public:
-		virtual ~GLMultiRenderTexture();
+		GLMultiRenderTextureCore(GLMultiRenderTexture* parent, MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc);
+		virtual ~GLMultiRenderTextureCore();
 
 		/**
-		 * @copydoc MultiRenderTexture::requiresTextureFlipping
+		 * @copydoc MultiRenderTextureCore::getCustomAttribute
 		 */
-		bool requiresTextureFlipping() const { return true; }
+		void getCustomAttribute(const String& name, void* pData) const;
+	protected:
+		friend class GLTextureManager;
+
+	private:
+		GLFrameBufferObject* mFB;
+	};
+
+	/**
+	 * @brief	OpenGL implementation of a render texture with multiple color surfaces.
+	 *
+	 * @note	Sim thread only.
+	 */
+	class BS_RSGL_EXPORT GLMultiRenderTexture : public MultiRenderTexture
+	{
+	public:
+		virtual ~GLMultiRenderTexture() { }
 
 		/**
-		 * @copydoc MultiRenderTexture::getCustomAttribute
+		 * @copydoc	MultiRenderTexture::requiresTextureFlipping
 		 */
-		void getCustomAttribute(const String& name, void* pData) const;
+		bool requiresTextureFlipping() const { return true; }
+
 	protected:
 		friend class GLTextureManager;
 
-		GLMultiRenderTexture();
+		GLMultiRenderTexture() { }
 
 		/**
-		 * @copydoc MultiRenderTexture::initialize_internal
+		 * @copydoc	MultiRenderTexture::createProperties
 		 */
-		void initialize_internal();
+		virtual RenderTargetProperties* createProperties() const;
 
 		/**
-		 * @copydoc MultiRenderTexture::destroy_internal
+		 * @copydoc	MultiRenderTexture::createCore
 		 */
-		void destroy_internal();
-	private:
-		GLFrameBufferObject* mFB;
+		virtual MultiRenderTextureCore* createCore(MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc);
 	};
 }

+ 36 - 14
BansheeGLRenderSystem/Include/BsGLRenderTexture.h

@@ -9,41 +9,63 @@
 
 namespace BansheeEngine 
 {  
+	class GLRenderTexture;
+
 	/**
 	 * @brief	OpenGL implementation of a render texture.
+	 *
+	 * @note	Core thread only.
 	 */
-    class BS_RSGL_EXPORT GLRenderTexture: public RenderTexture
+    class BS_RSGL_EXPORT GLRenderTextureCore : public RenderTextureCore
     {
 	public:
-		virtual ~GLRenderTexture();
+		GLRenderTextureCore(GLRenderTexture* parent, RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+			const RENDER_SURFACE_DESC& depthStencilSurfaceDesc);
 
-		/**
-		 * @copydoc	RenderTexture::requiresTextureFlipping
-		 */
-		bool requiresTextureFlipping() const { return true; }
+		virtual ~GLRenderTextureCore();
 
 		/**
-		 * @copydoc	RenderTexture::getCustomAttribute
+		 * @copydoc	RenderTextureCore::getCustomAttribute
 		 */
 		virtual void getCustomAttribute(const String& name, void* pData) const;
 
+	protected:
+		friend class GLRenderTexture;
+
+		GLFrameBufferObject* mFB;
+    };
+
+	/**
+	 * @brief	OpenGL implementation of a render texture.
+	 *
+	 * @note	Sim thread only.
+	 */
+	class BS_RSGL_EXPORT GLRenderTexture : public RenderTexture
+	{
+	public:
+		virtual ~GLRenderTexture() { }
+
 	protected:
 		friend class GLTextureManager;
 
-		GLRenderTexture();
+		GLRenderTexture() { }
 
 		/**
-		 * @copydoc RenderTexture::initialize_internal
+		 * @copydoc	RenderTexture::requiresTextureFlipping
 		 */
-		void initialize_internal();
+		bool requiresTextureFlipping() const { return true; }
 
 		/**
-		 * @copydoc RenderTexture::destroy_internal
+		 * @copydoc	RenderTexture::createProperties
 		 */
-		void destroy_internal();
+		virtual RenderTargetProperties* createProperties() const;
 
-		GLFrameBufferObject* mFB;
-    };
+		/**
+		 * @copydoc	RenderTexture::createCore
+		 */
+		virtual RenderTextureCore* createCore(RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+			const RENDER_SURFACE_DESC& depthStencilSurfaceDesc);
+	};
 
     /**
      * @brief	Manager that handles valid render texture formats.

+ 1 - 1
BansheeGLRenderSystem/Include/BsGLVertexArrayObjectManager.h

@@ -72,7 +72,7 @@ namespace BansheeEngine
 		/**
 		 * @brief	Called when a vertex buffer containing the provided VAO is destroyed.
 		 */
-		void notifyBufferDestroyed(const GLVertexArrayObject& vao);
+		void notifyBufferDestroyed(GLVertexArrayObject vao);
 	private:
 		typedef UnorderedSet<GLVertexArrayObject, GLVertexArrayObject::Hash, GLVertexArrayObject::Equal> VAOMap;
 

+ 0 - 1
BansheeGLRenderSystem/Include/BsWin32VideoModeInfo.h

@@ -24,7 +24,6 @@ namespace BansheeEngine
 	{
 	public:
 		Win32VideoOutputInfo(HMONITOR monitorHandle, UINT32 outputIdx);
-		~Win32VideoOutputInfo();
 
 		/**
 		 * @brief	Gets a Win32 handle to the monitor referenced by this object.

+ 87 - 53
BansheeGLRenderSystem/Include/BsWin32Window.h

@@ -5,68 +5,123 @@
 
 namespace BansheeEngine 
 {
+	class Win32Window;
+
+	/**
+	 * @brief	Contains various properties that describe a render window.
+	 */
+	class BS_RSGL_EXPORT Win32RenderWindowProperties : public RenderWindowProperties
+	{
+	public:
+		virtual ~Win32RenderWindowProperties() { }
+
+	private:
+		friend class Win32WindowCore;
+		friend class Win32Window;
+	};
+
 	/**
 	 * @brief	Render window implementation for Windows.
+	 *
+	 * @note	Core thread only.
 	 */
-    class BS_RSGL_EXPORT Win32Window : public RenderWindow
+    class BS_RSGL_EXPORT Win32WindowCore : public RenderWindowCore
     {
     public:
-        ~Win32Window();
+		Win32WindowCore(Win32Window* parent, RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc, Win32GLSupport &glsupport);
+		~Win32WindowCore();
 
 		/**
-		 * @copydoc RenderWindow::setFullscreen(UINT32, UINT32, float, UINT32)
+		 * @copydoc RenderWindowCore::setFullscreen(UINT32, UINT32, float, UINT32)
 		 */
 		void setFullscreen(UINT32 width, UINT32 height, float refreshRate = 60.0f, UINT32 monitorIdx = 0);
 
 		/**
-		 * @copydoc RenderWindow::setFullscreen(const VideoMode&)
+		 * @copydoc RenderWindowCore::setFullscreen(const VideoMode&)
 		 */
 		void setFullscreen(const VideoMode& mode);
 
 		/**
-		 * @copydoc RenderWindow::setWindowed
+		 * @copydoc RenderWindowCore::setWindowed
 		 */
 		void setWindowed(UINT32 width, UINT32 height);
 
 		/**
-		 * @copydoc RenderWindow::setHidden
+		 * @copydoc RenderWindowCore::setHidden
 		 */
 		void setHidden(bool hidden);
 
 		/**
-		 * @copydoc RenderWindow::isActive
+		 * @copydoc RenderWindowCore::move
 		 */
-		bool isActive() const;
+		void move(INT32 left, INT32 top);
 
 		/**
-		 * @copydoc RenderWindow::isVisible
+		 * @copydoc RenderWindowCore::resize
 		 */
-		bool isVisible() const;
+		void resize(UINT32 width, UINT32 height);
 
 		/**
-		 * @copydoc RenderWindow::isClosed
+		 * @copydoc RenderWindowCore::copyContentsToMemory
 		 */
-		bool isClosed() const;
+		void copyToMemory(PixelData &dst, FrameBuffer buffer);
 
 		/**
-		 * @copydoc RenderWindow::move
+		 * @copydoc RenderWindowCore::swapBuffers
 		 */
-		void move(INT32 left, INT32 top);
+		void swapBuffers();
 
 		/**
-		 * @copydoc RenderWindow::resize
+		 * @copydoc RenderWindowCore::getCustomAttribute
 		 */
-		void resize(UINT32 width, UINT32 height);
+		void getCustomAttribute(const String& name, void* pData) const;
 
 		/**
-		 * @copydoc RenderWindow::copyContentsToMemory
+		 * @copydoc RenderWindowCore::setActive
 		 */
-		void copyToMemory(PixelData &dst, FrameBuffer buffer);
+		virtual void setActive(bool state);
 
 		/**
-		 * @copydoc RenderWindow::swapBuffers
+		 * @copydoc RenderWindowCore::_windowMovedOrResized
 		 */
-		void swapBuffers();
+		void _windowMovedOrResized();
+
+		/**
+		 * @brief	Returns handle to device context associated with the window.
+		 */
+		HDC _getHDC() const { return mHDC; }
+
+	protected:
+		friend class Win32GLSupport;
+
+		/**
+		 * @brief	Calculates window size based on provided client area size and currently set window style. 
+		 */
+		void getAdjustedWindowSize(UINT32 clientWidth, UINT32 clientHeight, UINT32* winWidth, UINT32* winHeight);
+
+	protected:
+		Win32GLSupport &mGLSupport;
+		HWND mHWnd;
+		HDC	mHDC;
+		DWORD mWindowedStyle;
+		DWORD mWindowedStyleEx;
+		bool mIsExternal;
+		bool mIsChild;
+		char* mDeviceName;
+		bool mIsExternalGLControl;
+		int mDisplayFrequency;
+		Win32Context *mContext;
+    };
+
+	/**
+	 * @brief	Render window implementation for Windows.
+	 *
+	 * @note	Sim thread only.
+	 */
+	class BS_RSGL_EXPORT Win32Window : public RenderWindow
+	{
+	public:
+		~Win32Window() { }
 
 		/**
 		 * @copydoc RenderWindow::requiresTextureFlipping
@@ -89,54 +144,33 @@ namespace BansheeEngine
 		void getCustomAttribute(const String& name, void* pData) const;
 
 		/**
-		 * @copydoc RenderWindow::setActive
+		 * @copydoc	RenderWindow::getCore
 		 */
-		virtual void setActive(bool state);
-
-		/**
-		 * @copydoc RenderWindow::_windowMovedOrResized
-		 */
-		void _windowMovedOrResized();
-
-		/**
-		 * @brief	Returns handle to device context associated with the window.
-		 */
-		HDC _getHDC() const { return mHDC; }
+		Win32WindowCore* getCore() const;
 
 	protected:
 		friend class GLRenderWindowManager;
 		friend class Win32GLSupport;
 
-		Win32Window(const RENDER_WINDOW_DESC& desc, Win32GLSupport &glsupport);
+		Win32Window(Win32GLSupport& glsupport);
 
 		/**
-		 * @copydoc RenderWindow::initialize_internal().
+		 * @copydoc	RenderWindow::initialize_internal
 		 */
-		void initialize_internal();
+		virtual void initialize_internal();
 
 		/**
-		 * @copydoc RenderWindow::destroy_internal().
+		 * @copydoc	RenderWindow::createProperties
 		 */
-		void destroy_internal();
+		virtual RenderTargetProperties* createProperties() const;
 
 		/**
-		 * @brief	Calculates window size based on provided client area size and currently set window style. 
+		 * @copydoc	RenderWindow::createCore
 		 */
-		void getAdjustedWindowSize(UINT32 clientWidth, UINT32 clientHeight, UINT32* winWidth, UINT32* winHeight);
+		virtual RenderWindowCore* createCore(RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc);
 
-	protected:
-		Win32GLSupport &mGLSupport;
+	private:
+		Win32GLSupport& mGLSupport;
 		HWND mHWnd;
-		HDC	mHDC;
-		DWORD mWindowedStyle;
-		DWORD mWindowedStyleEx;
-		bool mIsExternal;
-		bool mIsChild;
-		char* mDeviceName;
-		bool mIsExternalGLControl;
-		bool mSizing;
-		bool mClosed;
-		int mDisplayFrequency;
-		Win32Context *mContext;
-    };
+	};
 }

+ 24 - 28
BansheeGLRenderSystem/Source/BsGLMultiRenderTexture.cpp

@@ -3,35 +3,25 @@
 
 namespace BansheeEngine
 {
-	GLMultiRenderTexture::GLMultiRenderTexture()
-		:MultiRenderTexture(), mFB(nullptr)
+	GLMultiRenderTextureCore::GLMultiRenderTextureCore(GLMultiRenderTexture* parent, MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc)
+		:MultiRenderTextureCore(parent, properties, desc), mFB(nullptr)
 	{
-
-	}
-
-	GLMultiRenderTexture::~GLMultiRenderTexture()
-	{
-
-	}
-
-	void GLMultiRenderTexture::initialize_internal()
-	{
-		if(mFB != nullptr)
+		if (mFB != nullptr)
 			bs_delete(mFB);
 
 		mFB = bs_new<GLFrameBufferObject, PoolAlloc>();
 
-		for(size_t i = 0; i < mColorSurfaces.size(); i++)
+		for (size_t i = 0; i < mColorSurfaces.size(); i++)
 		{
-			if(mColorSurfaces[i] != nullptr)
+			if (mColorSurfaces[i] != nullptr)
 			{
 				GLTexture* glColorSurface = static_cast<GLTexture*>(mColorSurfaces[i]->getTexture().get());
-				GLPixelBufferPtr colorBuffer = 
-					glColorSurface->getBuffer(mColorSurfaces[i]->getDesc().firstArraySlice, 
+				GLPixelBufferPtr colorBuffer =
+					glColorSurface->getBuffer(mColorSurfaces[i]->getDesc().firstArraySlice,
 					mColorSurfaces[i]->getDesc().mostDetailMip);
 
 				GLSurfaceDesc surfaceDesc;
-				surfaceDesc.numSamples = mMultisampleCount;
+				surfaceDesc.numSamples = getProperties().getMultisampleCount();
 				surfaceDesc.zoffset = 0;
 				surfaceDesc.buffer = colorBuffer;
 
@@ -43,11 +33,11 @@ namespace BansheeEngine
 			}
 		}
 
-		if(mDepthStencilSurface != nullptr)
+		if (mDepthStencilSurface != nullptr)
 		{
 			GLTexture* glDepthStencilSurface = static_cast<GLTexture*>(mDepthStencilSurface->getTexture().get());
-			GLPixelBufferPtr depthStencilBuffer = 
-				glDepthStencilSurface->getBuffer(mDepthStencilSurface->getDesc().firstArraySlice, 
+			GLPixelBufferPtr depthStencilBuffer =
+				glDepthStencilSurface->getBuffer(mDepthStencilSurface->getDesc().firstArraySlice,
 				mDepthStencilSurface->getDesc().mostDetailMip);
 
 			mFB->bindDepthStencil(depthStencilBuffer);
@@ -56,19 +46,15 @@ namespace BansheeEngine
 		{
 			mFB->unbindDepthStencil();
 		}
-
-		MultiRenderTexture::initialize_internal();
 	}
 
-	void GLMultiRenderTexture::destroy_internal()
+	GLMultiRenderTextureCore::~GLMultiRenderTextureCore()
 	{
-		if(mFB != nullptr)
+		if (mFB != nullptr)
 			bs_delete(mFB);
-
-		MultiRenderTexture::destroy_internal();
 	}
 
-	void GLMultiRenderTexture::getCustomAttribute(const String& name, void* pData) const
+	void GLMultiRenderTextureCore::getCustomAttribute(const String& name, void* pData) const
 	{
 		if(name=="FBO")
 		{
@@ -79,4 +65,14 @@ namespace BansheeEngine
 			*static_cast<GLuint*>(pData) = mFB->getGLFBOID();
 		}
 	}
+
+	RenderTargetProperties* GLMultiRenderTexture::createProperties() const
+	{
+		return bs_new<MultiRenderTextureProperties>();
+	}
+
+	MultiRenderTextureCore* GLMultiRenderTexture::createCore(MultiRenderTextureProperties* properties, const MULTI_RENDER_TEXTURE_DESC& desc)
+	{
+		return bs_new<GLMultiRenderTextureCore>(this, properties, desc);
+	}
 }

+ 21 - 16
BansheeGLRenderSystem/Source/BsGLRenderSystem.cpp

@@ -116,7 +116,7 @@ namespace BansheeEngine
 		      
 		// Get the context from the window and finish initialization
 		GLContext *context = nullptr;
-		primaryWindow->getCustomAttribute("GLCONTEXT", &context);
+		primaryWindow->getCore()->getCustomAttribute("GLCONTEXT", &context);
 
 		// Set main and current context
 		mMainContext = context;
@@ -159,8 +159,6 @@ namespace BansheeEngine
 	{
 		RenderSystem::destroy_internal();
 
-		GLVertexArrayObjectManager::shutDown();
-
 		// Deleting the GLSL program factory
 		if (mGLSLProgramFactory)
 		{
@@ -190,6 +188,7 @@ namespace BansheeEngine
 		QueryManager::shutDown();
 		RenderWindowManager::shutDown();
 		RenderStateManager::shutDown();
+		GLVertexArrayObjectManager::shutDown(); // Note: Needs to be after QueryManager shutdown as some resources might be waiting for queries to complete
 
 		mGLInitialised = false;
 
@@ -530,16 +529,18 @@ namespace BansheeEngine
 		target = vp.getTarget();
 		setRenderTarget(target);
 
+		const RenderTargetProperties& rtProps = target->getCore()->getProperties();
+
 		// Calculate the "lower-left" corner of the viewport
-		mViewportWidth = vp.getWidth();
-		mViewportHeight = vp.getHeight();
-		mViewportLeft = vp.getX();
-		mViewportTop = vp.getY();
+		mViewportLeft = (UINT32)(rtProps.getWidth() * vp.getNormalizedX());
+		mViewportTop = (UINT32)(rtProps.getHeight() * vp.getNormalizedY());
+		mViewportWidth = (UINT32)(rtProps.getWidth() * vp.getNormalizedWidth());
+		mViewportHeight = (UINT32)(rtProps.getHeight() * vp.getNormalizedHeight());
 
 		if (!target->requiresTextureFlipping())
 		{
 			// Convert "upper-left" corner to "lower-left"
-			mViewportTop = target->getHeight() - mViewportHeight - mViewportTop;
+			mViewportTop = target->getCore()->getProperties().getHeight() - mViewportHeight - mViewportTop;
 		}
 
 		glViewport(mViewportLeft, mViewportTop, mViewportWidth, mViewportHeight);
@@ -556,14 +557,14 @@ namespace BansheeEngine
 
 		// Switch context if different from current one
 		GLContext *newContext = 0;
-		target->getCustomAttribute("GLCONTEXT", &newContext);
+		target->getCore()->getCustomAttribute("GLCONTEXT", &newContext);
 		if(newContext && mCurrentContext != newContext) 
 		{
 			switchContext(newContext);
 		}
 
 		GLFrameBufferObject *fbo = 0;
-		target->getCustomAttribute("FBO", &fbo);
+		target->getCore()->getCustomAttribute("FBO", &fbo);
 		if(fbo)
 			fbo->bind();
 		else
@@ -573,7 +574,7 @@ namespace BansheeEngine
 		if (GLEW_EXT_framebuffer_sRGB)
 		{
 			// Enable / disable sRGB states
-			if (target->isHwGammaEnabled())
+			if (target->getCore()->getProperties().isHwGammaEnabled())
 			{
 				glEnable(GL_FRAMEBUFFER_SRGB_EXT);
 
@@ -667,8 +668,8 @@ namespace BansheeEngine
 
 		// Find the correct type to render
 		GLint primType = getGLDrawMode();
-		beginDraw();
 
+		beginDraw();
 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 
 			static_cast<GLIndexBuffer*>(mBoundIndexBuffer.get())->getGLBufferId());
 
@@ -676,7 +677,6 @@ namespace BansheeEngine
 		glDrawElementsBaseVertex(primType, indexCount, indexType, (GLvoid*)(mBoundIndexBuffer->getIndexSize() * startIndex), vertexOffset);
 
 		endDraw();
-
 		UINT32 primCount = vertexCountToPrimCount(mCurrentDrawOperation, vertexCount);
 
 		BS_INC_RENDER_STAT(NumDrawCalls);
@@ -701,7 +701,8 @@ namespace BansheeEngine
 		if(mActiveRenderTarget == nullptr)
 			return;
 
-		RectI clearRect(0, 0, mActiveRenderTarget->getWidth(), mActiveRenderTarget->getHeight());
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getCore()->getProperties();
+		RectI clearRect(0, 0, rtProps.getWidth(), rtProps.getHeight());
 
 		clearArea(buffers, color, depth, stencil, clearRect);
 	}
@@ -766,8 +767,10 @@ namespace BansheeEngine
 			glDisable(GL_SCISSOR_TEST);
 		}
 
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getCore()->getProperties();
+
 		bool clearEntireTarget = clearRect.width == 0 || clearRect.height == 0;
-		clearEntireTarget |= (clearRect.x == 0 && clearRect.y == 0 && clearRect.width == mActiveRenderTarget->getWidth() && clearRect.height == mActiveRenderTarget->getHeight());
+		clearEntireTarget |= (clearRect.x == 0 && clearRect.y == 0 && clearRect.width == rtProps.getWidth() && clearRect.height == rtProps.getHeight());
 
 		if(!clearEntireTarget)
 		{
@@ -994,10 +997,12 @@ namespace BansheeEngine
 
 	void GLRenderSystem::setScissorTestEnable(bool enable)
 	{
+		const RenderTargetProperties& rtProps = mActiveRenderTarget->getCore()->getProperties();
+
 		// If request texture flipping, use "upper-left", otherwise use "lower-left"
 		bool flipping = mActiveRenderTarget->requiresTextureFlipping();
 		//  GL measures from the bottom, not the top
-		UINT32 targetHeight = mActiveRenderTarget->getHeight();
+		UINT32 targetHeight = rtProps.getHeight();
 		// Calculate the "lower-left" corner of the viewport
 		GLsizei x = 0, y = 0, w = 0, h = 0;
 

+ 23 - 25
BansheeGLRenderSystem/Source/BsGLRenderTexture.cpp

@@ -23,34 +23,17 @@ namespace BansheeEngine
 
 #define DEPTHFORMAT_COUNT (sizeof(depthFormats)/sizeof(GLenum))
 
-
-	GLRenderTexture::GLRenderTexture()
-		:mFB(nullptr)
-	{
-	}
-
-	GLRenderTexture::~GLRenderTexture()
-	{
-
-	}
-
-	void GLRenderTexture::destroy_internal()
-	{
-		if(mFB != nullptr)
-			bs_delete<PoolAlloc>(mFB);
-
-		RenderTexture::destroy_internal();
-	}
-
-	void GLRenderTexture::initialize_internal()
+	GLRenderTextureCore::GLRenderTextureCore(GLRenderTexture* parent, RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+		const RENDER_SURFACE_DESC& depthStencilSurfaceDesc)
+		:RenderTextureCore(parent, properties, colorSurfaceDesc, depthStencilSurfaceDesc), mFB(nullptr)
 	{
-		if(mFB != nullptr)
+		if (mFB != nullptr)
 			bs_delete<PoolAlloc>(mFB);
 
 		mFB = bs_new<GLFrameBufferObject, PoolAlloc>();
 
 		GLSurfaceDesc surfaceDesc;
-		surfaceDesc.numSamples = mMultisampleCount;
+		surfaceDesc.numSamples = properties->getMultisampleCount();
 		surfaceDesc.zoffset = 0;
 
 		GLTexture* glTexture = static_cast<GLTexture*>(mColorSurface->getTexture().get());
@@ -59,15 +42,19 @@ namespace BansheeEngine
 		mFB->bindSurface(0, surfaceDesc);
 
 		GLTexture* glDepthStencilTexture = static_cast<GLTexture*>(mDepthStencilSurface->getTexture().get());
-		GLPixelBufferPtr depthStencilBuffer = 
+		GLPixelBufferPtr depthStencilBuffer =
 			glDepthStencilTexture->getBuffer(mDepthStencilSurface->getFirstArraySlice(), mDepthStencilSurface->getMostDetailedMip());
 
 		mFB->bindDepthStencil(depthStencilBuffer);
+	}
 
-		RenderTexture::initialize_internal();
+	GLRenderTextureCore::~GLRenderTextureCore()
+	{
+		if (mFB != nullptr)
+			bs_delete<PoolAlloc>(mFB);
 	}
 
-	void GLRenderTexture::getCustomAttribute(const String& name, void* pData) const
+	void GLRenderTextureCore::getCustomAttribute(const String& name, void* pData) const
 	{
 		if(name=="FBO")
 		{
@@ -79,6 +66,17 @@ namespace BansheeEngine
 		}
 	}
 
+	RenderTargetProperties* GLRenderTexture::createProperties() const
+	{
+		return bs_new<RenderTextureProperties>();
+	}
+
+	RenderTextureCore* GLRenderTexture::createCore(RenderTextureProperties* properties, const RENDER_SURFACE_DESC& colorSurfaceDesc,
+		const RENDER_SURFACE_DESC& depthStencilSurfaceDesc)
+	{
+		return bs_new<GLRenderTextureCore>(this, properties, colorSurfaceDesc, depthStencilSurfaceDesc);
+	}
+
 	GLRTTManager::GLRTTManager()
     {
 		detectFBOFormats();

+ 24 - 11
BansheeGLRenderSystem/Source/BsGLVertexArrayObjectManager.cpp

@@ -77,27 +77,39 @@ namespace BansheeEngine
 	const GLVertexArrayObject& GLVertexArrayObjectManager::getVAO(const GLSLGpuProgramPtr& vertexProgram,
 		const VertexDeclarationPtr& vertexDecl, const Vector<VertexBufferPtr>& boundBuffers)
 	{
+		UINT16 maxStreamIdx = 0;
+		const VertexDeclaration::VertexElementList& decl = vertexDecl->getElements();
+		for (auto& elem : decl)
+			maxStreamIdx = std::max(maxStreamIdx, elem.getStreamIdx());
+
+		UINT32 numStreams = maxStreamIdx + 1;
 		UINT32 numUsedBuffers = 0;
-		INT32* streamToSeqIdx = stackAllocN<INT32>((UINT32)boundBuffers.size());
+		INT32* streamToSeqIdx = stackAllocN<INT32>(numStreams);
 		GLVertexBuffer** usedBuffers = stackAllocN<GLVertexBuffer*>((UINT32)boundBuffers.size());
 		
-		const VertexDeclaration::VertexElementList& decl = vertexDecl->getElements();
+		memset(usedBuffers, 0, (UINT32)boundBuffers.size() * sizeof(GLVertexBuffer*));
+
+		for (UINT32 i = 0; i < numStreams; i++)
+			streamToSeqIdx[i] = -1;
+
 		for (auto& elem : decl)
 		{
 			UINT16 streamIdx = elem.getStreamIdx();
 			if (streamIdx >= (UINT32)boundBuffers.size())
-			{
-				streamToSeqIdx[streamIdx] = -1;
 				continue;
-			}
+
+			if (streamToSeqIdx[streamIdx] != -1) // Already visited
+				continue;
 
 			VertexBufferPtr vertexBuffer = boundBuffers[streamIdx];
+			streamToSeqIdx[streamIdx] = (INT32)numUsedBuffers;
 
-			if (vertexBuffer == nullptr)
-				continue; // Skip unbound elements
+			if (vertexBuffer != nullptr)
+				usedBuffers[numUsedBuffers] = static_cast<GLVertexBuffer*>(vertexBuffer.get()); 
+			else
+				usedBuffers[numUsedBuffers] = nullptr;
 
-			streamToSeqIdx[streamIdx] = (INT32)numUsedBuffers;
-			usedBuffers[numUsedBuffers++] = static_cast<GLVertexBuffer*>(vertexBuffer.get());
+			numUsedBuffers++;
 		}
 		
 		GLVertexArrayObject wantedVAO(0, vertexProgram->getInternalID(), usedBuffers, numUsedBuffers);
@@ -167,7 +179,7 @@ namespace BansheeEngine
 			glEnableVertexAttribArray(attribLocation);
 		}
 
-		wantedVAO.mAttachedBuffers = (GLVertexBuffer**)bs_alloc<GLVertexBuffer*>(numUsedBuffers);
+		wantedVAO.mAttachedBuffers = (GLVertexBuffer**)bs_alloc(numUsedBuffers * sizeof(GLVertexBuffer*));
 		for (UINT32 i = 0; i < numUsedBuffers; i++)
 		{
 			wantedVAO.mAttachedBuffers[i] = usedBuffers[i];
@@ -183,7 +195,8 @@ namespace BansheeEngine
 		return *iter.first;
 	}
 
-	void GLVertexArrayObjectManager::notifyBufferDestroyed(const GLVertexArrayObject& vao)
+	// Note: This must receieve a copy and not a ref because original will be destroyed
+	void GLVertexArrayObjectManager::notifyBufferDestroyed(GLVertexArrayObject vao)
 	{
 		mVAObjects.erase(vao);
 

+ 3 - 3
BansheeGLRenderSystem/Source/BsWin32GLSupport.cpp

@@ -31,11 +31,11 @@ namespace BansheeEngine
 		if(parentWindow != nullptr)
 		{
 			HWND hWnd;
-			parentWindow->getCustomAttribute("WINDOW", &hWnd);
+			parentWindow->getCore()->getCustomAttribute("WINDOW", &hWnd);
 			desc.platformSpecific["parentWindowHandle"] = toString((UINT64)hWnd);
 		}
 
-		Win32Window* window = new (bs_alloc<Win32Window, PoolAlloc>()) Win32Window(desc, *this);
+		Win32Window* window = new (bs_alloc<Win32Window, PoolAlloc>()) Win32Window(*this);
 		
 		if(!mInitialWindow)
 			mInitialWindow = window;
@@ -65,7 +65,7 @@ namespace BansheeEngine
 		if(_wglGetExtensionsString == nullptr)
 			return;
 
-		const char *wgl_extensions = _wglGetExtensionsString(mInitialWindow->_getHDC());
+		const char *wgl_extensions = _wglGetExtensionsString(mInitialWindow->getCore()->_getHDC());
 
 		// Parse them, and add them to the main list
 		StringStream ext;

+ 0 - 5
BansheeGLRenderSystem/Source/BsWin32VideoModeInfo.cpp

@@ -98,11 +98,6 @@ namespace BansheeEngine
 		mDesktopVideoMode = desktopVideoMode;
 	}
 
-	Win32VideoOutputInfo::~Win32VideoOutputInfo()
-	{
-		CloseHandle(mMonitorHandle);
-	}
-
 	Win32VideoMode::Win32VideoMode(UINT32 width, UINT32 height, float refreshRate, UINT32 outputIdx)
 		:VideoMode(width, height, refreshRate, outputIdx)
 	{ }

+ 213 - 183
BansheeGLRenderSystem/Source/BsWin32Window.cpp

@@ -19,26 +19,9 @@ namespace BansheeEngine
 {
 	#define _MAX_CLASS_NAME_ 128
 
-	Win32Window::Win32Window(const RENDER_WINDOW_DESC& desc, Win32GLSupport &glsupport)
-		:RenderWindow(desc), mGLSupport(glsupport), mContext(0), mWindowedStyle(0), mWindowedStyleEx(0)
-	{
-		mIsFullScreen = false;
-		mHWnd = 0;
-		mIsExternal = false;
-		mIsExternalGLControl = false;
-		mSizing = false;
-		mClosed = false;
-		mDisplayFrequency = 0;
-		mActive = false;
-		mDeviceName = NULL;
-	}
-
-	Win32Window::~Win32Window()
-	{
-
-	}
-
-	void Win32Window::initialize_internal()
+	Win32WindowCore::Win32WindowCore(Win32Window* parentWnd, RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc, Win32GLSupport& glsupport)
+		:RenderWindowCore(parentWnd, properties), mGLSupport(glsupport), mContext(0), mWindowedStyle(0), mWindowedStyleEx(0), mHWnd(0), mIsExternal(false),
+		mIsExternalGLControl(false), mDisplayFrequency(0), mDeviceName(nullptr)
 	{
 #ifdef BS_STATIC_LIB
 		HINSTANCE hInst = GetModuleHandle(NULL);
@@ -46,19 +29,20 @@ namespace BansheeEngine
 		HINSTANCE hInst = GetModuleHandle(MODULE_NAME.c_str());
 #endif
 
+		Win32RenderWindowProperties* props = static_cast<Win32RenderWindowProperties*>(mProperties);
+
 		mHWnd = 0;
-		mName = mDesc.title;
-		mIsFullScreen = mDesc.fullscreen;
-		mClosed = false;
+		props->mName = desc.title;
+		props->mIsFullScreen = desc.fullscreen;
 		mIsChild = false;
-		mDisplayFrequency = Math::roundToInt(mDesc.videoMode.getRefreshRate());
-		mColorDepth = 32;
+		mDisplayFrequency = Math::roundToInt(desc.videoMode.getRefreshRate());
+		props->mColorDepth = 32;
 		HWND parent = 0;
 
 		NameValuePairList::const_iterator opt;
-		NameValuePairList::const_iterator end = mDesc.platformSpecific.end();
+		NameValuePairList::const_iterator end = desc.platformSpecific.end();
 
-		if ((opt = mDesc.platformSpecific.find("externalWindowHandle")) != end)
+		if ((opt = desc.platformSpecific.find("externalWindowHandle")) != end)
 		{
 			mHWnd = (HWND)parseUnsignedInt(opt->second);
 			if (mHWnd)
@@ -66,22 +50,22 @@ namespace BansheeEngine
 				mIsExternal = true;
 			}
 
-			if ((opt = mDesc.platformSpecific.find("externalGLControl")) != end) {
+			if ((opt = desc.platformSpecific.find("externalGLControl")) != end) {
 				mIsExternalGLControl = parseBool(opt->second);
 			}
 		}
 
 		HGLRC glrc = 0;
-		if ((opt = mDesc.platformSpecific.find("externalGLContext")) != end)
+		if ((opt = desc.platformSpecific.find("externalGLContext")) != end)
 		{
 			glrc = (HGLRC)parseUnsignedLong(opt->second);
 		}
 
-		if ((opt = mDesc.platformSpecific.find("parentWindowHandle")) != end)
+		if ((opt = desc.platformSpecific.find("parentWindowHandle")) != end)
 		{
 			parent = (HWND)parseUnsignedInt(opt->second);
 			mIsChild = true;
-			mIsFullScreen = false;
+			props->mIsFullScreen = false;
 		}
 
 		HMONITOR hMonitor = NULL;
@@ -89,36 +73,36 @@ namespace BansheeEngine
 		UINT32 numOutputs = videoModeInfo.getNumOutputs();
 		if (numOutputs > 0)
 		{
-			UINT32 actualMonitorIdx = std::min(mDesc.videoMode.getOutputIdx(), numOutputs - 1);
+			UINT32 actualMonitorIdx = std::min(desc.videoMode.getOutputIdx(), numOutputs - 1);
 			const Win32VideoOutputInfo& outputInfo = static_cast<const Win32VideoOutputInfo&>(videoModeInfo.getOutputInfo(actualMonitorIdx));
 			hMonitor = outputInfo.getMonitorHandle();
 		}
 
-		if (!mIsFullScreen)
+		if (!props->mIsFullScreen)
 		{
 			// Make sure we don't exceed desktop color depth
-			if ((int)mColorDepth > GetDeviceCaps(GetDC(0), BITSPIXEL))
-				mColorDepth = GetDeviceCaps(GetDC(0), BITSPIXEL);
+			if ((int)props->mColorDepth > GetDeviceCaps(GetDC(0), BITSPIXEL))
+				props->mColorDepth = GetDeviceCaps(GetDC(0), BITSPIXEL);
 		}
 
 		mWindowedStyle = WS_VISIBLE | WS_CLIPCHILDREN;
 		mWindowedStyleEx = 0;
 
-		if (!mIsFullScreen)
+		if (!props->mIsFullScreen)
 		{
 			if (parent)
 			{
-				if (mDesc.toolWindow)
+				if (desc.toolWindow)
 					mWindowedStyleEx = WS_EX_TOOLWINDOW;
 				else
 					mWindowedStyle |= WS_CHILD;
 			}
 
-			if (!parent || mDesc.toolWindow)
+			if (!parent || desc.toolWindow)
 			{
-				if (mDesc.border == WindowBorder::None)
+				if (desc.border == WindowBorder::None)
 					mWindowedStyle |= WS_POPUP;
-				else if (mDesc.border == WindowBorder::Fixed)
+				else if (desc.border == WindowBorder::Fixed)
 					mWindowedStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
 					WS_SYSMENU | WS_MINIMIZEBOX;
 				else
@@ -136,8 +120,8 @@ namespace BansheeEngine
 				POINT windowAnchorPoint;
 
 				// Fill in anchor point.
-				windowAnchorPoint.x = mDesc.left;
-				windowAnchorPoint.y = mDesc.top;
+				windowAnchorPoint.x = desc.left;
+				windowAnchorPoint.y = desc.top;
 
 				// Get the nearest monitor to this window.
 				hMonitor = MonitorFromPoint(windowAnchorPoint, MONITOR_DEFAULTTONEAREST);
@@ -155,21 +139,21 @@ namespace BansheeEngine
 
 			strcpy_s(mDeviceName, devNameLen + 1, monitorInfoEx.szDevice);
 
-			UINT32 left = mDesc.left;
-			UINT32 top = mDesc.top;
+			UINT32 left = desc.left;
+			UINT32 top = desc.top;
 
 			// No specified top left -> Center the window in the middle of the monitor
 			if (left == -1 || top == -1)
-			{				
-				int screenw = monitorInfoEx.rcWork.right  - monitorInfoEx.rcWork.left;
+			{
+				int screenw = monitorInfoEx.rcWork.right - monitorInfoEx.rcWork.left;
 				int screenh = monitorInfoEx.rcWork.bottom - monitorInfoEx.rcWork.top;
 
 				unsigned int winWidth, winHeight;
-				getAdjustedWindowSize(mDesc.videoMode.getWidth(), mDesc.videoMode.getHeight(), &winWidth, &winHeight);
+				getAdjustedWindowSize(desc.videoMode.getWidth(), desc.videoMode.getHeight(), &winWidth, &winHeight);
 
 				// clamp window dimensions to screen size
-				int outerw = (int(winWidth) < screenw)? int(winWidth) : screenw;
-				int outerh = (int(winHeight) < screenh)? int(winHeight) : screenh;
+				int outerw = (int(winWidth) < screenw) ? int(winWidth) : screenw;
+				int outerh = (int(winHeight) < screenh) ? int(winHeight) : screenh;
 
 				if (left == -1)
 					left = monitorInfoEx.rcWork.left + (screenw - outerw) / 2;
@@ -187,49 +171,49 @@ namespace BansheeEngine
 				top += monitorInfoEx.rcWork.top;
 			}
 
-			mWidth = mDesc.videoMode.getWidth();
-			mHeight = mDesc.videoMode.getHeight();
-			mTop = top;
-			mLeft = left;
+			props->mWidth = desc.videoMode.getWidth();
+			props->mHeight = desc.videoMode.getHeight();
+			props->mTop = top;
+			props->mLeft = left;
 
 			DWORD dwStyle = 0;
 			DWORD dwStyleEx = 0;
-			if (mIsFullScreen)
+			if (props->mIsFullScreen)
 			{
 				dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_POPUP;
-				mTop = monitorInfoEx.rcMonitor.top;
-				mLeft = monitorInfoEx.rcMonitor.left;											
+				props->mTop = monitorInfoEx.rcMonitor.top;
+				props->mLeft = monitorInfoEx.rcMonitor.left;
 			}
 			else
-			{			
+			{
 				dwStyle = mWindowedStyle;
 				dwStyleEx = mWindowedStyleEx;
 
 				int screenw = GetSystemMetrics(SM_CXSCREEN);
 				int screenh = GetSystemMetrics(SM_CYSCREEN);
 
-				if (!mDesc.outerDimensions)
+				if (!desc.outerDimensions)
 				{
 					// Calculate window dimensions required
 					// to get the requested client area
-					SetRect(&rc, 0, 0, mWidth, mHeight);
+					SetRect(&rc, 0, 0, props->mWidth, props->mHeight);
 					AdjustWindowRect(&rc, dwStyle, false);
-					mWidth = rc.right - rc.left;
-					mHeight = rc.bottom - rc.top;
+					props->mWidth = rc.right - rc.left;
+					props->mHeight = rc.bottom - rc.top;
 
 					// Clamp window rect to the nearest display monitor.
-					if (mLeft < monitorInfoEx.rcWork.left)
-						mLeft = monitorInfoEx.rcWork.left;		
+					if (props->mLeft < monitorInfoEx.rcWork.left)
+						props->mLeft = monitorInfoEx.rcWork.left;
 
-					if (mTop < monitorInfoEx.rcWork.top)					
-						mTop = monitorInfoEx.rcWork.top;					
+					if (props->mTop < monitorInfoEx.rcWork.top)
+						props->mTop = monitorInfoEx.rcWork.top;
 
-					if ((int)mWidth > monitorInfoEx.rcWork.right - mLeft)					
-						mWidth = monitorInfoEx.rcWork.right - mLeft;	
+					if ((int)props->mWidth > monitorInfoEx.rcWork.right - props->mLeft)
+						props->mWidth = monitorInfoEx.rcWork.right - props->mLeft;
 
-					if ((int)mHeight > monitorInfoEx.rcWork.bottom - mTop)					
-						mHeight = monitorInfoEx.rcWork.bottom - mTop;		
-				}			
+					if ((int)props->mHeight > monitorInfoEx.rcWork.bottom - props->mTop)
+						props->mHeight = monitorInfoEx.rcWork.bottom - props->mTop;
+				}
 			}
 
 			// register class and create window
@@ -238,15 +222,15 @@ namespace BansheeEngine
 				(HBRUSH)GetStockObject(BLACK_BRUSH), NULL, "GLWindow" };
 			RegisterClass(&wc);
 
-			if (mIsFullScreen)
+			if (props->mIsFullScreen)
 			{
 				DEVMODE displayDeviceMode;
 
 				memset(&displayDeviceMode, 0, sizeof(displayDeviceMode));
 				displayDeviceMode.dmSize = sizeof(DEVMODE);
-				displayDeviceMode.dmBitsPerPel = mColorDepth;
-				displayDeviceMode.dmPelsWidth = mWidth;
-				displayDeviceMode.dmPelsHeight = mHeight;
+				displayDeviceMode.dmBitsPerPel = props->mColorDepth;
+				displayDeviceMode.dmPelsWidth = props->mWidth;
+				displayDeviceMode.dmPelsHeight = props->mHeight;
 				displayDeviceMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
 
 				if (mDisplayFrequency)
@@ -267,50 +251,50 @@ namespace BansheeEngine
 			}
 
 			// Pass pointer to self as WM_CREATE parameter
-			mHWnd = CreateWindowEx(dwStyleEx, "GLWindow", mDesc.title.c_str(),
-				dwStyle, mLeft, mTop, mWidth, mHeight, parent, 0, hInst, this);		
+			mHWnd = CreateWindowEx(dwStyleEx, "GLWindow", desc.title.c_str(),
+				dwStyle, props->mLeft, props->mTop, props->mWidth, props->mHeight, parent, 0, hInst, this);
 		}
 
 		RECT rc;
 
 		GetWindowRect(mHWnd, &rc);
-		mTop = rc.top;
-		mLeft = rc.left;
+		props->mTop = rc.top;
+		props->mLeft = rc.left;
 
 		GetClientRect(mHWnd, &rc);
-		mWidth = rc.right;
-		mHeight = rc.bottom;
+		props->mWidth = rc.right;
+		props->mHeight = rc.bottom;
 
 		mHDC = GetDC(mHWnd);
 
 		if (!mIsExternalGLControl)
 		{
-			int testMultisample = mMultisampleCount;
-			bool testHwGamma = mDesc.gamma;
-			bool formatOk = mGLSupport.selectPixelFormat(mHDC, mColorDepth, testMultisample, testHwGamma);
+			int testMultisample = props->mMultisampleCount;
+			bool testHwGamma = desc.gamma;
+			bool formatOk = mGLSupport.selectPixelFormat(mHDC, props->mColorDepth, testMultisample, testHwGamma);
 			if (!formatOk)
 			{
-				if (mMultisampleCount > 0)
+				if (props->mMultisampleCount > 0)
 				{
 					// Try without multisampling
 					testMultisample = 0;
-					formatOk = mGLSupport.selectPixelFormat(mHDC, mColorDepth, testMultisample, testHwGamma);
+					formatOk = mGLSupport.selectPixelFormat(mHDC, props->mColorDepth, testMultisample, testHwGamma);
 				}
 
-				if (!formatOk && mDesc.gamma)
+				if (!formatOk && desc.gamma)
 				{
 					// Try without sRGB
 					testHwGamma = false;
-					testMultisample = mMultisampleCount;
-					formatOk = mGLSupport.selectPixelFormat(mHDC, mColorDepth, testMultisample, testHwGamma);
+					testMultisample = props->mMultisampleCount;
+					formatOk = mGLSupport.selectPixelFormat(mHDC, props->mColorDepth, testMultisample, testHwGamma);
 				}
 
-				if (!formatOk && mDesc.gamma && (mMultisampleCount > 0))
+				if (!formatOk && desc.gamma && (props->mMultisampleCount > 0))
 				{
 					// Try without both
 					testHwGamma = false;
 					testMultisample = 0;
-					formatOk = mGLSupport.selectPixelFormat(mHDC, mColorDepth, testMultisample, testHwGamma);
+					formatOk = mGLSupport.selectPixelFormat(mHDC, props->mColorDepth, testMultisample, testHwGamma);
 				}
 
 				if (!formatOk)
@@ -320,27 +304,27 @@ namespace BansheeEngine
 
 			// Record what gamma option we used in the end
 			// this will control enabling of sRGB state flags when used
-			mHwGamma = testHwGamma;
-			mMultisampleCount = testMultisample;
+			props->mHwGamma = testHwGamma;
+			props->mMultisampleCount = testMultisample;
 		}
-		
-		mActive = true;
-		mContext = mGLSupport.createContext(mHDC, glrc);
 
-		RenderWindow::initialize_internal();
+		props->mActive = true;
+		mContext = mGLSupport.createContext(mHDC, glrc);
 	}
 
-	void Win32Window::destroy_internal()
+	Win32WindowCore::~Win32WindowCore()
 	{
 		if (!mHWnd)
 			return;
 
+		Win32RenderWindowProperties* props = static_cast<Win32RenderWindowProperties*>(mProperties);
+
 		// Unregister and destroy GLContext
 		bs_delete(mContext);
 
 		if (!mIsExternal)
 		{
-			if (mIsFullScreen)
+			if (props->mIsFullScreen)
 				ChangeDisplaySettingsEx(mDeviceName, NULL, NULL, 0, NULL);
 			DestroyWindow(mHWnd);
 		}
@@ -350,8 +334,7 @@ namespace BansheeEngine
 			ReleaseDC(mHWnd, mHDC);
 		}
 
-		mActive = false;
-		mClosed = true;
+		props->mActive = false;
 		mHDC = 0; // no release thanks to CS_OWNDC wndclass style
 		mHWnd = 0;
 
@@ -361,10 +344,10 @@ namespace BansheeEngine
 			mDeviceName = NULL;
 		}
 
-		RenderWindow::destroy_internal();
+		markCoreDirty();
 	}
 
-	void Win32Window::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
+	void Win32WindowCore::setFullscreen(UINT32 width, UINT32 height, float refreshRate, UINT32 monitorIdx)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -376,19 +359,21 @@ namespace BansheeEngine
 		if (numOutputs == 0)
 			return;
 
+		Win32RenderWindowProperties* props = static_cast<Win32RenderWindowProperties*>(mProperties);
+
 		UINT32 actualMonitorIdx = std::min(monitorIdx, numOutputs - 1);
 		const Win32VideoOutputInfo& outputInfo = static_cast<const Win32VideoOutputInfo&>(videoModeInfo.getOutputInfo(actualMonitorIdx));
 
-		bool oldFullscreen = mIsFullScreen;
+		bool oldFullscreen = props->mIsFullScreen;
 
 		mDisplayFrequency = Math::roundToInt(refreshRate);
-		mIsFullScreen = true;
+		props->mIsFullScreen = true;
 
 		DEVMODE displayDeviceMode;
 
 		memset(&displayDeviceMode, 0, sizeof(displayDeviceMode));
 		displayDeviceMode.dmSize = sizeof(DEVMODE);
-		displayDeviceMode.dmBitsPerPel = mColorDepth;
+		displayDeviceMode.dmBitsPerPel = props->mColorDepth;
 		displayDeviceMode.dmPelsWidth = width;
 		displayDeviceMode.dmPelsHeight = height;
 		displayDeviceMode.dmDisplayFrequency = mDisplayFrequency;
@@ -406,38 +391,42 @@ namespace BansheeEngine
 			BS_EXCEPT(RenderingAPIException, "ChangeDisplaySettings failed");
 		}
 
-		mTop = monitorInfo.rcMonitor.top;
-		mLeft = monitorInfo.rcMonitor.left;
-		mWidth = width;
-		mHeight = height;
+		props->mTop = monitorInfo.rcMonitor.top;
+		props->mLeft = monitorInfo.rcMonitor.left;
+		props->mWidth = width;
+		props->mHeight = height;
+
+		SetWindowPos(mHWnd, HWND_TOP, props->mLeft, props->mTop, width, height, SWP_NOACTIVATE);
 
-		SetWindowPos(mHWnd, HWND_TOP, mLeft, mTop, width, height, SWP_NOACTIVATE);
+		markCoreDirty();
 	}
 
-	void Win32Window::setFullscreen(const VideoMode& mode)
+	void Win32WindowCore::setFullscreen(const VideoMode& mode)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
 		setFullscreen(mode.getWidth(), mode.getHeight(), mode.getRefreshRate(), mode.getOutputIdx());
 	}
 
-	void Win32Window::setWindowed(UINT32 width, UINT32 height)
+	void Win32WindowCore::setWindowed(UINT32 width, UINT32 height)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if (!mIsFullScreen)
+		Win32RenderWindowProperties* props = static_cast<Win32RenderWindowProperties*>(mProperties);
+
+		if (!props->mIsFullScreen)
 			return;
 
-		mIsFullScreen = false;
-		mWidth = width;
-		mHeight = height;
+		props->mIsFullScreen = false;
+		props->mWidth = width;
+		props->mHeight = height;
 
 		// Drop out of fullscreen
 		ChangeDisplaySettingsEx(mDeviceName, NULL, NULL, 0, NULL);
 
 		// Calculate overall dimensions for requested client area
 		UINT32 winWidth, winHeight;
-		getAdjustedWindowSize(mWidth, mHeight, &winWidth, &winHeight);
+		getAdjustedWindowSize(props->mWidth, props->mHeight, &winWidth, &winHeight);
 
 		// Deal with centering when switching down to smaller resolution
 		HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
@@ -458,48 +447,36 @@ namespace BansheeEngine
 			SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOACTIVATE);
 
 		_windowMovedOrResized();
-	}
-
-	bool Win32Window::isActive(void) const
-	{
-		if (isFullScreen())
-			return isVisible();
-
-		return mActive && isVisible();
-	}
 
-	bool Win32Window::isVisible() const
-	{
-		return (mHWnd && !IsIconic(mHWnd));
-	}
-
-	bool Win32Window::isClosed() const
-	{
-		return mClosed;
+		markCoreDirty();
 	}
 
-	void Win32Window::move(INT32 left, INT32 top)
+	void Win32WindowCore::move(INT32 left, INT32 top)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if (mHWnd && !mIsFullScreen)
+		Win32RenderWindowProperties* props = static_cast<Win32RenderWindowProperties*>(mProperties);
+		if (mHWnd && !props->mIsFullScreen)
 		{
-			mLeft = left;
-			mTop = top;
+			props->mLeft = left;
+			props->mTop = top;
 
 			SetWindowPos(mHWnd, 0, left, top, 0, 0,
 				SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+
+			markCoreDirty();
 		}
 	}
 
-	void Win32Window::resize(UINT32 width, UINT32 height)
+	void Win32WindowCore::resize(UINT32 width, UINT32 height)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if (mHWnd && !mIsFullScreen)
+		Win32RenderWindowProperties* props = static_cast<Win32RenderWindowProperties*>(mProperties);
+		if (mHWnd && !props->mIsFullScreen)
 		{
-			mWidth = width;
-			mHeight = height;
+			props->mWidth = width;
+			props->mHeight = height;
 
 			RECT rc = { 0, 0, width, height };
 			AdjustWindowRect(&rc, GetWindowLong(mHWnd, GWL_STYLE), false);
@@ -507,10 +484,12 @@ namespace BansheeEngine
 			height = rc.bottom - rc.top;
 			SetWindowPos(mHWnd, 0, 0, 0, width, height,
 				SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
+
+			markCoreDirty();
 		}
 	}
 
-	void Win32Window::swapBuffers()
+	void Win32WindowCore::swapBuffers()
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -519,12 +498,12 @@ namespace BansheeEngine
 		}
 	}
 
-	void Win32Window::copyToMemory(PixelData &dst, FrameBuffer buffer)
+	void Win32WindowCore::copyToMemory(PixelData &dst, FrameBuffer buffer)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		if ((dst.getLeft() < 0) || (dst.getRight() > mWidth) ||
-			(dst.getTop() < 0) || (dst.getBottom() > mHeight) ||
+		if ((dst.getLeft() < 0) || (dst.getRight() > getProperties().getWidth()) ||
+			(dst.getTop() < 0) || (dst.getBottom() > getProperties().getHeight()) ||
 			(dst.getFront() != 0) || (dst.getBack() != 1))
 		{
 			BS_EXCEPT(InvalidParametersException, "Invalid box.");
@@ -532,7 +511,7 @@ namespace BansheeEngine
 
 		if (buffer == FB_AUTO)
 		{
-			buffer = mIsFullScreen? FB_FRONT : FB_BACK;
+			buffer = getProperties().isFullScreen() ? FB_FRONT : FB_BACK;
 		}
 
 		GLenum format = BansheeEngine::GLPixelUtil::getGLOriginFormat(dst.getFormat());
@@ -573,27 +552,7 @@ namespace BansheeEngine
 		}
 	}
 
-	Vector2I Win32Window::screenToWindowPos(const Vector2I& screenPos) const
-	{
-		POINT pos;
-		pos.x = screenPos.x;
-		pos.y = screenPos.y;
-
-		ScreenToClient(mHWnd, &pos);
-		return Vector2I(pos.x, pos.y);
-	}
-
-	Vector2I Win32Window::windowToScreenPos(const Vector2I& windowPos) const
-	{
-		POINT pos;
-		pos.x = windowPos.x;
-		pos.y = windowPos.y;
-
-		ClientToScreen(mHWnd, &pos);
-		return Vector2I(pos.x, pos.y);
-	}	
-
-	void Win32Window::getCustomAttribute(const String& name, void* pData) const
+	void Win32WindowCore::getCustomAttribute(const String& name, void* pData) const
 	{
 		if(name == "GLCONTEXT") 
 		{
@@ -608,7 +567,7 @@ namespace BansheeEngine
 		} 
 	}
 
-	void Win32Window::setActive(bool state)
+	void Win32WindowCore::setActive(bool state)
 	{	
 		THROW_IF_NOT_CORE_THREAD;
 
@@ -627,9 +586,10 @@ namespace BansheeEngine
 			}						
 		}
 		
-		mActive = state;
+		Win32RenderWindowProperties* props = static_cast<Win32RenderWindowProperties*>(mProperties);
+		props->mActive = state;
 
-		if( mIsFullScreen )
+		if(props->mIsFullScreen)
 		{
 			if( state == false )
 			{	//Restore Desktop
@@ -644,9 +604,9 @@ namespace BansheeEngine
 
 				memset(&displayDeviceMode, 0, sizeof(displayDeviceMode));
 				displayDeviceMode.dmSize = sizeof(DEVMODE);
-				displayDeviceMode.dmBitsPerPel = mColorDepth;
-				displayDeviceMode.dmPelsWidth = mWidth;
-				displayDeviceMode.dmPelsHeight = mHeight;
+				displayDeviceMode.dmBitsPerPel = props->mColorDepth;
+				displayDeviceMode.dmPelsWidth = props->mWidth;
+				displayDeviceMode.dmPelsHeight = props->mHeight;
 				displayDeviceMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
 				if (mDisplayFrequency)
 				{
@@ -656,13 +616,16 @@ namespace BansheeEngine
 				ChangeDisplaySettingsEx(mDeviceName, &displayDeviceMode, NULL, CDS_FULLSCREEN, NULL);
 			}
 		}
+
+		markCoreDirty();
 	}
 
-	void Win32Window::setHidden(bool hidden)
+	void Win32WindowCore::setHidden(bool hidden)
 	{
 		THROW_IF_NOT_CORE_THREAD;
 
-		mHidden = hidden;
+		Win32RenderWindowProperties* props = static_cast<Win32RenderWindowProperties*>(mProperties);
+		props->mHidden = hidden;
 		if (!mIsExternal)
 		{
 			if (hidden)
@@ -670,27 +633,32 @@ namespace BansheeEngine
 			else
 				ShowWindow(mHWnd, SW_SHOWNORMAL);
 		}
+
+		markCoreDirty();
 	}
 
-	void Win32Window::_windowMovedOrResized()
+	void Win32WindowCore::_windowMovedOrResized()
 	{
 		if (!mHWnd || IsIconic(mHWnd))
 			return;
 
 		RECT rc;
 
+		Win32RenderWindowProperties* props = static_cast<Win32RenderWindowProperties*>(mProperties);
 		GetWindowRect(mHWnd, &rc);
-		mTop = rc.top;
-		mLeft = rc.left;
+		props->mTop = rc.top;
+		props->mLeft = rc.left;
 
 		GetClientRect(mHWnd, &rc);
-		mWidth = rc.right - rc.left;
-		mHeight = rc.bottom - rc.top;
+		props->mWidth = rc.right - rc.left;
+		props->mHeight = rc.bottom - rc.top;
 
-		RenderWindow::_windowMovedOrResized();
+		markCoreDirty();
+
+		RenderWindowCore::_windowMovedOrResized();
 	}
 
-	void Win32Window::getAdjustedWindowSize(UINT32 clientWidth, UINT32 clientHeight, UINT32* winWidth, UINT32* winHeight)
+	void Win32WindowCore::getAdjustedWindowSize(UINT32 clientWidth, UINT32 clientHeight, UINT32* winWidth, UINT32* winHeight)
 	{
 		RECT rc;
 		SetRect(&rc, 0, 0, clientWidth, clientHeight);
@@ -717,4 +685,66 @@ namespace BansheeEngine
 		if (*winHeight > (UINT32)maxH)
 			*winHeight = maxH;
 	}
+
+	Win32Window::Win32Window(Win32GLSupport &glsupport)
+		:mGLSupport(glsupport)
+	{
+
+	}
+
+	void Win32Window::getCustomAttribute(const String& name, void* pData) const
+	{
+		THROW_IF_CORE_THREAD;
+
+		if (name == "WINDOW")
+		{
+			HWND *pWnd = (HWND*)pData;
+			*pWnd = mHWnd;
+			return;
+		}
+
+		RenderWindow::getCustomAttribute(name, pData);
+	}
+
+	Vector2I Win32Window::screenToWindowPos(const Vector2I& screenPos) const
+	{
+		POINT pos;
+		pos.x = screenPos.x;
+		pos.y = screenPos.y;
+
+		ScreenToClient(mHWnd, &pos);
+		return Vector2I(pos.x, pos.y);
+	}
+
+	Vector2I Win32Window::windowToScreenPos(const Vector2I& windowPos) const
+	{
+		POINT pos;
+		pos.x = windowPos.x;
+		pos.y = windowPos.y;
+
+		ClientToScreen(mHWnd, &pos);
+		return Vector2I(pos.x, pos.y);
+	}
+
+	Win32WindowCore* Win32Window::getCore() const
+	{
+		return static_cast<Win32WindowCore*>(mCore);
+	}
+
+	void Win32Window::initialize_internal()
+	{
+		RenderWindow::initialize_internal();
+
+		mCore->getCustomAttribute("WINDOW", (void*)&mHWnd);
+	}
+
+	RenderTargetProperties* Win32Window::createProperties() const
+	{
+		return bs_new<RenderWindowProperties>();
+	}
+
+	RenderWindowCore* Win32Window::createCore(RenderWindowProperties* properties, const RENDER_WINDOW_DESC& desc)
+	{
+		return bs_new<Win32WindowCore>(this, properties, desc, mGLSupport);
+	}
 }

+ 2 - 1
BansheeRenderer/Source/BsBansheeRenderer.cpp

@@ -140,7 +140,8 @@ namespace BansheeEngine
 
 		// Sort everything based on priority
 		auto cameraComparer = [&](const CameraProxyPtr& a, const CameraProxyPtr& b) { return a->priority > b->priority; };
-		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b) { return a.target->getPriority() > b.target->getPriority(); };
+		auto renderTargetInfoComparer = [&](const RenderTargetData& a, const RenderTargetData& b) 
+		{ return a.target->getCore()->getProperties().getPriority() > b.target->getCore()->getProperties().getPriority(); };
 		std::sort(begin(mRenderTargets), end(mRenderTargets), renderTargetInfoComparer);
 
 		for (auto& camerasPerTarget : mRenderTargets)

+ 6 - 0
BansheeUtility/Include/BsThreadPool.h

@@ -76,6 +76,12 @@ namespace BansheeEngine
 		 */
 		UINT32 getId() const;
 
+		/**
+		 * @brief	Blocks the current thread until this thread completes.
+		 *			Returns immediately if the thread is idle.
+		 */
+		void blockUntilComplete();
+
 		/**
 		 * @brief	Called when the thread is first created.
 		 */

+ 18 - 6
BansheeUtility/Source/BsThreadPool.cpp

@@ -89,18 +89,20 @@ namespace BansheeEngine
 			std::function<void()> worker = nullptr;
 
 			{
-				BS_LOCK_MUTEX_NAMED(mMutex, lock);
+				{
+					BS_LOCK_MUTEX_NAMED(mMutex, lock);
+
+					while (!mThreadReady)
+						BS_THREAD_WAIT(mReadyCond, mMutex, lock);
 
-				while(!mThreadReady)
-					BS_THREAD_WAIT(mReadyCond, mMutex, lock);
+					worker = mWorkerMethod;
+				}
 
-				if(mWorkerMethod == nullptr)
+				if (worker == nullptr)
 				{
 					onThreadEnded(mName);
 					return;
 				}
-
-				worker = mWorkerMethod;
 			}
 
 			worker();
@@ -120,6 +122,8 @@ namespace BansheeEngine
 
 	void PooledThread::destroy()
 	{
+		blockUntilComplete();
+
 		{
 			BS_LOCK_MUTEX(mMutex);
 			mWorkerMethod = nullptr;
@@ -131,6 +135,14 @@ namespace BansheeEngine
 		BS_THREAD_DESTROY(mThread);
 	}
 
+	void PooledThread::blockUntilComplete()
+	{
+		BS_LOCK_MUTEX_NAMED(mMutex, lock);
+
+		while (!mIdle)
+			BS_THREAD_WAIT(mWorkerEndedCond, mMutex, lock);
+	}
+
 	bool PooledThread::isIdle()
 	{
 		BS_LOCK_MUTEX(mMutex);

+ 19 - 23
SceneView.txt

@@ -13,6 +13,18 @@ TODO - Think about:
 ----------------------------------------------------------------------
 Handles
 
+ - Make a few different base handle types:
+   - Slider 1D (e.g. for movement using an arrow cap)
+   - Slider 2D (e.g. for movement in 2D using a plane render)
+   - Similar for scale/rotation handles  (see Unity for its implementations of those)
+
+Handles should have colliders which will be queries whenever user input is detected in scene view
+If any handle is hit the input will not proceed further (e.g. no picking will be done) and that handle control
+will become active.
+
+Base handle types should just be positioned in space and then return value every frame as user moves them.
+ - This way they can also easily be used from C# for custom user-made stuff
+
 TODO - Think about this
 See for inspiration: http://docs.unity3d.com/ScriptReference/Handles.html
 
@@ -81,32 +93,16 @@ Need to allow the user to specify custom gizmos.
 -----------------------------------------------------------------------
 RenderTarget (and in turn, Viewport) make data available to sim thread, even though that data can be arbitrarily modified from the core thread
 
-Create a separate set of classes: RenderTargetCore, RenderTextureCore, RenderWindowCore.
- - They would not be core objects but would be used exclusively on the core thread
- - Majority of the current classes would go into those new classes
+TODO:
+ - Fix invalid height
+ - Test DX9 and OpenGL
+ - getProperties on non-core should just make a copy of core for now to check if everything works
+ - Remove the debug stuff in RenderTarget when done testing
 
-Current RenderTarget/RenderTexture/RenderWindow would stay and be useable on sim thread but not meant for core thread use.
- - Internally it would store the *Core versions of the objects
 
 Whenever a core object gets changed it should notify a RenderTargetManager, which will on beginning of every frame update
 non-core version with valid data.
+ - Make sure core dirty properties are updated before render window manager events are triggered
 
 Viewport should return a ViewportProxy for use on core thread (instead of a clone as it has now)
- - The proxy will reference the *Core version of render target
-
-IMPLEMENTATION:
- - Create RenderTargetCore, RenderTextureCore, RenderWindowCore files
- - Start copying (don't modify original files) code from original files and modify them for core use
- - Find any references of render targets on the core thread and make sure it uses those core objects instead
- - Add getCoreImplementation() that returns the core version from "normal" objects
-
-
-Stuff that needs to be synchronized:
- mIsFullscreen
- mWidth
- mHeight
- mHidden
- mTop
- mLeft
- mHasFocus
- (more? check)
+ - The proxy will reference the *Core version of render target