Browse Source

WIP: Linux port
- Fixing OpenGL usage with multiple windows

Marko Pintera 8 years ago
parent
commit
78f89c68ac

+ 1 - 1
Source/BansheeGLRenderAPI/BsGLContext.h

@@ -20,7 +20,7 @@ namespace bs { namespace ct
         virtual ~GLContext();
 
 		/**	Activates the rendering context (all subsequent rendering commands will be executed on it). */
-        virtual void setCurrent() = 0;
+        virtual void setCurrent(const RenderWindow& window) = 0;
 
 		/**	Deactivates the rendering context. Normally called just before setCurrent is called on another context. */
         virtual void endCurrent() = 0;

+ 25 - 9
Source/BansheeGLRenderAPI/BsGLRenderAPI.cpp

@@ -123,7 +123,7 @@ namespace bs { namespace ct
 
 		// Set primary context as active
 		if (mCurrentContext)
-			mCurrentContext->setCurrent();
+			mCurrentContext->setCurrent(*primaryWindow);
 
 		checkForErrors();
 
@@ -809,14 +809,16 @@ namespace bs { namespace ct
 			THROW_IF_NOT_CORE_THREAD;
 
 			// Switch context if different from current one
-			if (target != nullptr)
+			if (target != nullptr && target->getProperties().isWindow)
 			{
+				RenderWindow* window = static_cast<RenderWindow*>(target.get());
+
 				SPtr<GLContext> newContext;
 				target->getCustomAttribute("GLCONTEXT", &newContext);
 				if (newContext && mCurrentContext != newContext)
-				{
-					switchContext(newContext);
-				}
+					switchContext(newContext, *window);
+				else
+					mCurrentContext->setCurrent(*window);
 			}
 
 			// This must happen after context switch to ensure previous context is still alive
@@ -1162,6 +1164,20 @@ namespace bs { namespace ct
 	void GLRenderAPI::swapBuffers(const SPtr<RenderTarget>& target, UINT32 syncMask)
 	{
 		THROW_IF_NOT_CORE_THREAD;
+
+		// Switch context if different from current one
+		if(!target->getProperties().isWindow)
+			return;
+
+		RenderWindow* window = static_cast<RenderWindow*>(target.get());
+
+		SPtr<GLContext> newContext;
+		target->getCustomAttribute("GLCONTEXT", &newContext);
+		if (newContext && mCurrentContext != newContext)
+			switchContext(newContext, *window);
+		else
+			mCurrentContext->setCurrent(*window);
+
 		target->swapBuffers();
 	
 		BS_INC_RENDER_STAT(NumPresents);
@@ -2086,7 +2102,7 @@ namespace bs { namespace ct
 		TextureManager::startUp<GLTextureManager>(std::ref(*mGLSupport));
 	}
 
-	void GLRenderAPI::switchContext(const SPtr<GLContext>& context)
+	void GLRenderAPI::switchContext(const SPtr<GLContext>& context, const RenderWindow& window)
 	{
 		// Unbind GPU programs and rebind to new context later, because
 		// scene manager treat render system as ONE 'context' ONLY, and it
@@ -2098,11 +2114,11 @@ namespace bs { namespace ct
 			mCurrentContext->endCurrent();
 
 		mCurrentContext = context;
-		mCurrentContext->setCurrent();
+		mCurrentContext->setCurrent(window);
 
 		// Must reset depth/colour write mask to according with user desired, otherwise,
-		// clearFrameBuffer would be wrong because the value we are recorded may be
-		// difference with the really state stored in GL context.
+		// clearFrameBuffer would be wrong because the value we recorded may be
+		// different from the real state stored in GL context.
 		glDepthMask(mDepthWrite);
 		glColorMask(mColorWrite[0], mColorWrite[1], mColorWrite[2], mColorWrite[3]);
 		glStencilMask(mStencilWriteMask);

+ 2 - 2
Source/BansheeGLRenderAPI/BsGLRenderAPI.h

@@ -114,7 +114,7 @@ namespace bs { namespace ct
 		bool _isContextInitialized() const { return mGLInitialised; }
 
 		/**	Returns main context. Caller must ensure the context has been initialized. */
-		SPtr<GLContext> getMainContext() const { return mMainContext; } 
+		SPtr<GLContext> _getMainContext() const { return mMainContext; }
 
 		/**	Returns a support object you may use for creating */
 		GLSupport* getGLSupport() const { return mGLSupport; }
@@ -169,7 +169,7 @@ namespace bs { namespace ct
 		 * Switch the currently used OpenGL context. You will need to re-bind any previously bound values manually
 		 * (for example textures, gpu programs and such).
 		 */
-		void switchContext(const SPtr<GLContext>& context);
+		void switchContext(const SPtr<GLContext>& context, const RenderWindow& window);
 
 		/************************************************************************/
 		/* 								Sampler states                     		*/

+ 19 - 17
Source/BansheeGLRenderAPI/Linux/BsLinuxContext.cpp

@@ -6,15 +6,15 @@
 
 namespace bs { namespace ct
 {
-		typedef int(*ErrorHandlerProc)(::Display*, XErrorEvent*);
-		int contextErrorHandler(::Display* display, XErrorEvent* error)
-		{
-			// Do nothing
-			return 0;
-		}
+	typedef int(*ErrorHandlerProc)(::Display*, XErrorEvent*);
+	int contextErrorHandler(::Display* display, XErrorEvent* error)
+	{
+		// Do nothing
+		return 0;
+	}
 
-		LinuxContext::LinuxContext(::Display* display, XVisualInfo& visualInfo)
-		: mDisplay(display), mContext(0)
+	LinuxContext::LinuxContext(::Display* display, XVisualInfo& visualInfo)
+	: mDisplay(display), mCurrentWindow(0), mContext(0)
 	{
 		LinuxPlatform::lockX();
 
@@ -53,13 +53,13 @@ namespace bs { namespace ct
 			if(windowConfig)
 			{
 				int32_t attributes[] =
-						{
-								GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
-								GLX_CONTEXT_MINOR_VERSION_ARB, 5,
-								0, 0, // Core profile
-								0, 0, // Debug flags
-								0 // Terminator
-						};
+				{
+					GLX_CONTEXT_MAJOR_VERSION_ARB, 4,
+					GLX_CONTEXT_MINOR_VERSION_ARB, 5,
+					0, 0, // Core profile
+					0, 0, // Debug flags
+					0 // Terminator
+				};
 
 				if(extGLX_ARB_create_context_profile)
 				{
@@ -97,10 +97,12 @@ namespace bs { namespace ct
 		releaseContext();
 	}
 
-	void LinuxContext::setCurrent()
+	void LinuxContext::setCurrent(const RenderWindow& window)
 	{
+		window.getCustomAttribute("WINDOW", &mCurrentWindow);
+
 		LinuxPlatform::lockX();
-		glXMakeCurrent(mDisplay, LinuxPlatform::getMainXWindow(), mContext);
+		glXMakeCurrent(mDisplay, mCurrentWindow, mContext);
 		LinuxPlatform::unlockX();
 	}
 

+ 2 - 1
Source/BansheeGLRenderAPI/Linux/BsLinuxContext.h

@@ -25,7 +25,7 @@ namespace bs { namespace ct
 		virtual ~LinuxContext();
 
 		/** @copydoc GLContext::setCurrent */
-		void setCurrent() override;
+		void setCurrent(const RenderWindow& window) override;
 
 		/** @copydoc GLContext::endCurrent */
 		void endCurrent() override;
@@ -35,6 +35,7 @@ namespace bs { namespace ct
 
 	protected:
 		::Display* mDisplay;
+		::Window mCurrentWindow;
 		GLXContext mContext;
 	};
 

+ 1 - 3
Source/BansheeGLRenderAPI/Linux/BsLinuxGLSupport.cpp

@@ -164,9 +164,7 @@ namespace bs { namespace ct
 			return bs_shared_ptr_new<LinuxContext>(x11display, visualInfo);
 		else
 		{
-			SPtr<GLContext> context = rapi->getMainContext();
-			context->setCurrent();
-
+			SPtr<GLContext> context = rapi->_getMainContext();
 			return std::static_pointer_cast<LinuxContext>(context);
 		}
 	}

+ 1 - 1
Source/BansheeGLRenderAPI/Win32/BsWin32Context.cpp

@@ -20,7 +20,7 @@ namespace bs { namespace ct
 			releaseContext();
 	}
 
-	void Win32Context::setCurrent()
+	void Win32Context::setCurrent(const RenderWindow& window)
 	{
 		wglMakeCurrent(mHDC, mGlrc);
 	}

+ 12 - 12
Source/BansheeGLRenderAPI/Win32/BsWin32Context.h

@@ -12,31 +12,31 @@ namespace bs { namespace ct
 	 */
 
 	/**	Windows specific implementation of an OpenGL context. */
-    class Win32Context : public GLContext
-    {
-    public:
+	class Win32Context : public GLContext
+	{
+	public:
 		/**
 		 * Constructs a new context from a Windows device context and OpenGL rendering context. Optionally you may specify
 		 * that the context isn't owned by us (might be created by some external library), in which case it will not be
 		 * automatically released.
 		 */
-        Win32Context(HDC hdc, HGLRC glrc, bool ownsContext);
-        virtual ~Win32Context();
+		Win32Context(HDC hdc, HGLRC glrc, bool ownsContext);
+		virtual ~Win32Context();
 
-        /** @copydoc GLContext::setCurrent */
-        void setCurrent() override;
+		/** @copydoc GLContext::setCurrent */
+		void setCurrent(const RenderWindow& window) override;
 
-        /** @copydoc GLContext::endCurrent */
+		/** @copydoc GLContext::endCurrent */
 		void endCurrent() override;
 
-        /** @copydoc GLContext::releaseContext  */
+		/** @copydoc GLContext::releaseContext  */
 		void releaseContext() override;
 
 	protected:
-        HDC     mHDC;
-        HGLRC   mGlrc;
+		HDC     mHDC;
+		HGLRC   mGlrc;
 		bool	mOwnsContext;
-    };
+	};
 
 	/** @} */
 }}

+ 3 - 3
Source/BansheeGLRenderAPI/Win32/BsWin32GLSupport.cpp

@@ -87,12 +87,12 @@ namespace bs { namespace ct
 
 	SPtr<Win32Context> Win32GLSupport::createContext(HDC hdc, HGLRC externalGlrc)
 	{
-		GLRenderAPI* rs = static_cast<GLRenderAPI*>(RenderAPI::instancePtr());
+		GLRenderAPI* rapi = static_cast<GLRenderAPI*>(RenderAPI::instancePtr());
 
 		// If RenderAPI has initialized a context use that, otherwise we create our own
 		HGLRC glrc = externalGlrc;
 		bool createdNew = false;
-		if (!rs->_isContextInitialized())
+		if (!rapi->_isContextInitialized())
 		{
 			if (externalGlrc == 0)
 			{
@@ -127,7 +127,7 @@ namespace bs { namespace ct
 		}
 		else
 		{
-			rs->getMainContext()->setCurrent();
+			rapi->_getMainContext()->setCurrent();
 			glrc = wglGetCurrentContext();
 		}
 

+ 2 - 2
Source/BansheeGLRenderAPI/Win32/BsWin32RenderWindow.cpp

@@ -84,13 +84,13 @@ namespace bs
 
 	namespace ct
 	{
-		Win32RenderWindow::Win32RenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId, Win32GLSupport& glsupport)
+	Win32RenderWindow::Win32RenderWindow(const RENDER_WINDOW_DESC& desc, UINT32 windowId, Win32GLSupport& glsupport)
 		: RenderWindow(desc, windowId), mWindow(nullptr), mGLSupport(glsupport), mHDC(nullptr), mIsChild(false)
 		, mDeviceName(nullptr), mDisplayFrequency(0), mShowOnSwap(false), mContext(nullptr), mProperties(desc)
 		, mSyncedProperties(desc)
 	{ }
 
-		Win32RenderWindow::~Win32RenderWindow()
+	Win32RenderWindow::~Win32RenderWindow()
 	{ 
 		RenderWindowProperties& props = mProperties;