ソースを参照

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

Marko Pintera 11 年 前
コミット
492ad2cac2
68 ファイル変更2375 行追加1424 行削除
  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