about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2011-12-30 16:02:22 +0100
committerMagnus Auvinen <magnus.auvinen@gmail.com>2011-12-30 16:02:22 +0100
commit8ffe5826156d07b1feb7fc58bf59a1431e01160f (patch)
treea2a0a536538e725b68741b516e80f3e0a73999c5 /src
parent6e20c32859ee4518f398a12b65586463ddeecaab (diff)
downloadzcatch-8ffe5826156d07b1feb7fc58bf59a1431e01160f.tar.gz
zcatch-8ffe5826156d07b1feb7fc58bf59a1431e01160f.zip
ugly incomplete hack to put the rendering into another thread so we don't have to wait for the flip
Diffstat (limited to 'src')
-rw-r--r--src/base/tl/threading.h78
-rw-r--r--src/engine/client/client.cpp98
-rw-r--r--src/engine/client/client.h6
-rw-r--r--src/game/client/components/menus.cpp3
4 files changed, 177 insertions, 8 deletions
diff --git a/src/base/tl/threading.h b/src/base/tl/threading.h
new file mode 100644
index 00000000..66751ec4
--- /dev/null
+++ b/src/base/tl/threading.h
@@ -0,0 +1,78 @@
+
+#pragma once
+
+#include "../system.h"
+
+inline unsigned atomic_inc(volatile unsigned *pValue)
+{
+	return __sync_fetch_and_add(pValue, 1);
+}
+
+inline unsigned atomic_dec(volatile unsigned *pValue)
+{
+	return __sync_fetch_and_add(pValue, -1);
+}
+
+inline unsigned atomic_compswap(volatile unsigned *pValue, unsigned comperand, unsigned value)
+{
+	return __sync_val_compare_and_swap(pValue, comperand, value);
+}
+
+inline void sync_barrier()
+{
+	__sync_synchronize();
+}
+
+#include <semaphore.h>
+typedef sem_t SEMAPHORE;
+inline void semaphore_init(SEMAPHORE *sem) { sem_init(sem, 0, 0); }
+inline void semaphore_wait(SEMAPHORE *sem) { sem_wait(sem); }
+inline void semaphore_signal(SEMAPHORE *sem) { sem_post(sem); }
+inline void semaphore_destroy(SEMAPHORE *sem) { sem_destroy(sem); }
+
+class semaphore
+{
+	SEMAPHORE sem;
+public:
+	semaphore() { semaphore_init(&sem); }
+	~semaphore() { semaphore_destroy(&sem); }
+	void wait() { semaphore_wait(&sem); }
+	void signal() { semaphore_signal(&sem); }
+};
+
+class lock
+{
+	friend class scope_lock;
+
+	LOCK var;
+
+	void take() { lock_wait(var); }
+	void release() { lock_release(var); }
+
+public:
+	lock()
+	{
+		var = lock_create();
+	}
+
+	~lock()
+	{
+		lock_destroy(var);
+	}
+};
+
+class scope_lock
+{
+	lock *var;
+public:
+	scope_lock(lock *l)
+	{
+		var = l;
+		var->take();
+	}
+
+	~scope_lock()
+	{
+		var->release();
+	}
+};
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp
index 9f43b9ce..4107cd85 100644
--- a/src/engine/client/client.cpp
+++ b/src/engine/client/client.cpp
@@ -7,6 +7,7 @@
 
 #include <base/math.h>
 #include <base/system.h>
+#include <base/tl/threading.h>
 
 #include <engine/client.h>
 #include <engine/config.h>
@@ -1688,17 +1689,27 @@ void CClient::InitInterfaces()
 	m_Friends.Init();
 }
 
-void CClient::Run()
-{
-	int64 ReportTime = time_get();
-	int64 ReportInterval = time_freq()*1;
 
-	m_LocalStartTime = time_get();
-	m_SnapshotParts = 0;
+enum
+{
+	GFXSTATE_ERROR = -1,
+	GFXSTATE_INIT = 0,
+	GFXSTATE_IDLE,
+	GFXSTATE_RENDERING,
+	GFXSTATE_SWAPPING,
+};
 
+void CClient::GraphicsThread()
+{
 	// init graphics
 	if(m_pGraphics->Init() != 0)
+	{
+		m_GfxState = GFXSTATE_ERROR;
+		m_GfxStateSemaphore.signal();
+		m_GfxState = GFXSTATE_ERROR;
 		return;
+	}
+
 
 	// open socket
 	{
@@ -1708,6 +1719,7 @@ void CClient::Run()
 		if(!m_NetClient.Open(BindAddr, 0))
 		{
 			dbg_msg("client", "couldn't start network");
+			m_GfxState = GFXSTATE_ERROR;
 			return;
 		}
 	}
@@ -1722,16 +1734,66 @@ void CClient::Run()
 	MasterServer()->RefreshAddresses(m_NetClient.NetType());
 
 	// init the editor
-	m_pEditor->Init();
+	//m_pEditor->Init();
 
 	// init sound, allowed to fail
 	m_SoundInitFailed = Sound()->Init() != 0;
 
 	// load data
 	if(!LoadData())
+	{
+		m_GfxState = GFXSTATE_ERROR;
 		return;
+	}
 
 	GameClient()->OnInit();
+
+
+	while(1)
+	{
+		// do idle
+		sync_barrier();
+		m_GfxState = GFXSTATE_IDLE;
+		m_GfxStateSemaphore.signal();
+		m_GfxRenderSemaphore.wait();
+		
+		// do render
+		m_GfxState = GFXSTATE_RENDERING;
+		m_GfxStateSemaphore.signal();
+		Render();
+		sync_barrier();
+
+		// do swap
+		m_GfxState = GFXSTATE_SWAPPING;
+		m_GfxStateSemaphore.signal();
+		m_pGraphics->Swap();
+	}
+
+	// do shutdown
+}
+
+void CClient::Run()
+{
+	int64 ReportTime = time_get();
+	int64 ReportInterval = time_freq()*1;
+
+	m_LocalStartTime = time_get();
+	m_SnapshotParts = 0;
+
+	m_GfxState = GFXSTATE_INIT;
+	thread_create(GraphicsThreadProxy, this);
+
+	// wait for gfx to init
+	while(1)
+	{
+		m_GfxStateSemaphore.wait();
+		if(m_GfxState == GFXSTATE_ERROR)
+			return;
+		if(m_GfxState != GFXSTATE_INIT)
+			break;
+	}
+
+
 	char aBuf[256];
 	str_format(aBuf, sizeof(aBuf), "version %s", GameClient()->NetVersion());
 	m_pConsole->Print(IConsole::OUTPUT_LEVEL_STANDARD, "client", aBuf);
@@ -1847,7 +1909,27 @@ void CClient::Run()
 				m_EditorActive = false;
 
 			Update();
+			
+
+			if(m_GfxState == GFXSTATE_IDLE)
+			{
+				// issue new rendering
+				m_GfxRenderSemaphore.signal();
+
+				// wait for gfx to finish rendering
+				while(m_GfxState != GFXSTATE_SWAPPING)
+					m_GfxStateSemaphore.wait();
 
+			}
+
+			/*
+			if(m_pGraphics->AsyncSwapIsDone())
+			{
+				m_pGraphics->BeginScene();
+				Render();
+				m_pGraphics->EndScene();
+			}*/
+			/*
 			if(g_Config.m_DbgStress)
 			{
 				if((m_Frames%10) == 0)
@@ -1860,7 +1942,7 @@ void CClient::Run()
 			{
 				Render();
 				m_pGraphics->Swap();
-			}
+			}*/
 		}
 
 		AutoScreenshot_Cleanup();
diff --git a/src/engine/client/client.h b/src/engine/client/client.h
index 1504a4e4..83553eb4 100644
--- a/src/engine/client/client.h
+++ b/src/engine/client/client.h
@@ -172,6 +172,12 @@ class CClient : public IClient, public CDemoPlayer::IListner
 		class CHostLookup m_VersionServeraddr;
 	} m_VersionInfo;
 
+	semaphore m_GfxRenderSemaphore;
+	semaphore m_GfxStateSemaphore;
+	volatile int m_GfxState;
+	static void GraphicsThreadProxy(void *pThis) { ((CClient*)pThis)->GraphicsThread(); }
+	void GraphicsThread();
+
 public:
 	IEngine *Engine() { return m_pEngine; }
 	IEngineGraphics *Graphics() { return m_pGraphics; }
diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp
index a39139c8..fc1ca2db 100644
--- a/src/game/client/components/menus.cpp
+++ b/src/game/client/components/menus.cpp
@@ -627,6 +627,9 @@ int CMenus::RenderMenubar(CUIRect r)
 
 void CMenus::RenderLoading()
 {
+	// TODO: not supported right now due to separate render thread
+	return;
+
 	static int64 LastLoadRender = 0;
 	float Percent = m_LoadCurrent++/(float)m_LoadTotal;