瀏覽代碼

remove separate GUI thread
+ this fixes OGL
- has some issues(f.e. hero movement)

AlexVinS 11 年之前
父節點
當前提交
41a0319985
共有 5 個文件被更改,包括 138 次插入128 次删除
  1. 95 80
      client/CMT.cpp
  2. 12 30
      client/gui/CGuiHandler.cpp
  3. 2 1
      client/gui/CGuiHandler.h
  4. 28 6
      client/gui/SDL_Extensions.cpp
  5. 1 11
      client/gui/SDL_Extensions.h

+ 95 - 80
client/CMT.cpp

@@ -74,14 +74,13 @@ int preferredDriverIndex = -1;
 SDL_Window * mainWindow = nullptr;
 SDL_Renderer * mainRenderer = nullptr;
 SDL_Texture * screenTexture = nullptr;
+
 #endif // VCMI_SDL1
 
 SDL_Surface *screen = nullptr, //main screen surface
 	*screen2 = nullptr,//and hlp surface (used to store not-active interfaces layer)
 	*screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
 	
-static boost::thread *mainGUIThread;
-
 std::queue<SDL_Event> events;
 boost::mutex eventsM;
 
@@ -95,7 +94,7 @@ void processCommand(const std::string &message);
 static void setScreenRes(int w, int h, int bpp, bool fullscreen, bool resetVideo=true);
 void dispose();
 void playIntro();
-static void listenForEvents();
+static void mainLoop();
 //void requestChangingResolution();
 void startGame(StartInfo * options, CConnection *serv = nullptr);
 void endGame();
@@ -458,8 +457,7 @@ int main(int argc, char** argv)
 
 	if(!gNoGUI)
 	{
-		mainGUIThread = new boost::thread(&CGuiHandler::run, &GH);
-		listenForEvents();
+		mainLoop();
 	}
 	else
 	{
@@ -822,7 +820,7 @@ static bool checkVideoMode(int monitorIndex, int w, int h, int& bpp, bool fullsc
 #ifndef VCMI_SDL1
 static bool recreateWindow(int w, int h, int bpp, bool fullscreen)
 {
-	// VCMI will only work with 2, 3 or 4 bytes per pixel	
+	// VCMI will only work with 2 or 4 bytes per pixel	
 	vstd::amax(bpp, 16);
 	vstd::amin(bpp, 32);
 	if(bpp>16)
@@ -905,6 +903,8 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen)
 	logGlobal->infoStream() << "Created renderer " << info.name;	
 	
 	SDL_RenderSetLogicalSize(mainRenderer, w, h);
+	
+	SDL_RenderSetViewport(mainRenderer, nullptr);
 
 
 	
@@ -1082,83 +1082,97 @@ static void fullScreenChanged()
 	GH.totalRedraw();
 }
 
-static void listenForEvents()
+static void handleEvent(SDL_Event & ev)
 {
-	SettingsListener resChanged = settings.listen["video"]["fullscreen"];
-	resChanged([](const JsonNode &newState){  CGuiHandler::pushSDLEvent(SDL_USEREVENT, FULLSCREEN_TOGGLED); });
+	if((ev.type==SDL_QUIT) ||(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
+	{
+		handleQuit();	
+		return;
+	}
 
-	while(1) //main SDL events loop
+	#ifdef VCMI_SDL1
+	//FIXME: this should work even in pregame
+	else if(LOCPLINT && ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
+	#else
+	else if(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
+	#endif // VCMI_SDL1		
 	{
-		SDL_Event ev;
-		
-		int ret = SDL_WaitEvent(&ev);
-		if (ret == 0 || (ev.type==SDL_QUIT) ||
-			(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
-		{
-			handleQuit();
-			continue;
-		}
-		#ifdef VCMI_SDL1
-		//FIXME: this should work even in pregame
-		else if(LOCPLINT && ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
-		#else
-		else if(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
-		#endif // VCMI_SDL1		
-		{
-			Settings full = settings.write["video"]["fullscreen"];
-			full->Bool() = !full->Bool();
-			continue;
-		}
-		else if(ev.type == SDL_USEREVENT)
+		Settings full = settings.write["video"]["fullscreen"];
+		full->Bool() = !full->Bool();
+		return;
+	}
+	else if(ev.type == SDL_USEREVENT)
+	{
+		switch(ev.user.code)
 		{
-			switch(ev.user.code)
+		case RETURN_TO_MAIN_MENU:
 			{
-			case RETURN_TO_MAIN_MENU:
-				{
-                    endGame();
-                    GH.curInt = CGPreGame::create();;
-                    GH.defActionsDef = 63;
-				}
-				break;
-			case STOP_CLIENT:
-				client->endGame(false);
-				break;
-			case RESTART_GAME:
-				{
-					StartInfo si = *client->getStartInfo(true);
-					endGame();
-					startGame(&si);
-				}
-				break;
-			case PREPARE_RESTART_CAMPAIGN:
-				{
-					auto si = reinterpret_cast<StartInfo *>(ev.user.data1);
-					endGame();
-					startGame(si);
-				}
-				break;
-			case RETURN_TO_MENU_LOAD:
 				endGame();
-				CGPreGame::create();
+				GH.curInt = CGPreGame::create();;
 				GH.defActionsDef = 63;
-				CGP->update();
-				CGP->menu->switchToTab(vstd::find_pos(CGP->menu->menuNameToEntry, "load"));
-				GH.curInt = CGP;
-				break;
-			case FULLSCREEN_TOGGLED:
-				fullScreenChanged();
-				break;
-			default:
-                logGlobal->errorStream() << "Error: unknown user event. Code " << ev.user.code;
-				assert(0);
 			}
-
-			continue;
+			break;
+		case STOP_CLIENT:
+			client->endGame(false);
+			break;
+		case RESTART_GAME:
+			{
+				StartInfo si = *client->getStartInfo(true);
+				endGame();
+				startGame(&si);
+			}
+			break;
+		case PREPARE_RESTART_CAMPAIGN:
+			{
+				auto si = reinterpret_cast<StartInfo *>(ev.user.data1);
+				endGame();
+				startGame(si);
+			}
+			break;
+		case RETURN_TO_MENU_LOAD:
+			endGame();
+			CGPreGame::create();
+			GH.defActionsDef = 63;
+			CGP->update();
+			CGP->menu->switchToTab(vstd::find_pos(CGP->menu->menuNameToEntry, "load"));
+			GH.curInt = CGP;
+			break;
+		case FULLSCREEN_TOGGLED:
+			fullScreenChanged();
+			break;
+		default:
+			logGlobal->errorStream() << "Error: unknown user event. Code " << ev.user.code;		
+			break;	
 		}
+
+		return;
+	}
+	{
+		boost::unique_lock<boost::mutex> lock(eventsM);
+		events.push(ev);
+	}	
+	
+}
+
+
+static void mainLoop()
+{
+	SettingsListener resChanged = settings.listen["video"]["fullscreen"];
+	resChanged([](const JsonNode &newState){  CGuiHandler::pushSDLEvent(SDL_USEREVENT, FULLSCREEN_TOGGLED); });
+
+	GH.mainFPSmng->init();
+
+	while(1) //main SDL events loop
+	{
+		SDL_Event ev;
+		
+		while(1 == SDL_PollEvent(&ev))
 		{
-			boost::unique_lock<boost::mutex> lock(eventsM);
-			events.push(ev);
+			handleEvent(ev);
 		}
+		
+		GH.renderFrame();
+
 	}
 }
 
@@ -1208,15 +1222,16 @@ void handleQuit()
 {
 	auto quitApplication = []()
 	{
-		if(client) client->endGame();
+		if(client)
+			endGame();
 
-		if(mainGUIThread)
-		{
-			GH.terminate = true;
-			if(mainGUIThread->get_id() != boost::this_thread::get_id()) mainGUIThread->join();
-			delete mainGUIThread;
-			mainGUIThread = nullptr;
-		}
+//		if(mainGUIThread)
+//		{
+//			GH.terminate = true;
+//			if(mainGUIThread->get_id() != boost::this_thread::get_id()) mainGUIThread->join();
+//			delete mainGUIThread;
+//			mainGUIThread = nullptr;
+//		}
 		delete console;
 		console = nullptr;
 		boost::this_thread::sleep(boost::posix_time::milliseconds(750));

+ 12 - 30
client/gui/CGuiHandler.cpp

@@ -410,43 +410,25 @@ void CGuiHandler::fakeMouseMove()
 	handleMouseMotion(&evnt);
 }
 
-void CGuiHandler::run()
+void CGuiHandler::renderFrame()
 {
-	setThreadName("CGuiHandler::run");
-	inGuiThread.reset(new bool(true));
-	try
-	{		
-		if(settings["video"]["fullscreen"].Bool())
-			CCS->curh->centerCursor();
-
-		mainFPSmng->init(); // resets internal clock, needed for FPS manager
-		while(!terminate)
-		{
-			{
-				//boost::unique_lock<boost::recursive_mutex> lock(*CPlayerInterface::pim);			
-				if(curInt)
-					curInt->update(); // calls a update and drawing process of the loaded game interface object at the moment
+	if(!terminate)
+	{
+		if(curInt)
+			curInt->update(); // calls a update and drawing process of the loaded game interface object at the moment
 
 #ifndef	 VCMI_SDL1
+		if(0 != SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr))
+			logGlobal->errorStream() << __FUNCTION__ << " SDL_RenderCopy " << SDL_GetError();
 
-				SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 0);
-				SDL_RenderClear(mainRenderer);
-				SDL_RenderCopy(mainRenderer, screenTexture, NULL, NULL);
-
-				SDL_RenderPresent(mainRenderer);				
-
+		SDL_RenderPresent(mainRenderer);				
 #endif			
-			}
-			mainFPSmng->framerateDelay(); // holds a constant FPS
-		}
-	}
-	catch(const std::exception & e)
-	{
-        logGlobal->errorStream() << "Error: " << e.what();
-		exit(EXIT_FAILURE);
-	}
+		
+		mainFPSmng->framerateDelay(); // holds a constant FPS
+	}	
 }
 
+
 CGuiHandler::CGuiHandler()
 :lastClick(-500, -500)
 {

+ 2 - 1
client/gui/CGuiHandler.h

@@ -80,7 +80,8 @@ public:
 
 	CGuiHandler();
 	~CGuiHandler();
-	void run(); // holds the main loop for the whole program after initialization and manages the update/rendering system
+	
+	void renderFrame();
 
 	void totalRedraw(); //forces total redraw (using showAll), sets a flag, method gets called at the end of the rendering
 	void simpleRedraw(); //update only top interface and draw background from buffer, sets a flag, method gets called at the end of the rendering

+ 28 - 6
client/gui/SDL_Extensions.cpp

@@ -14,6 +14,21 @@ const SDL_Color Colors::WHITE = { 255, 243, 222, 0 };
 const SDL_Color Colors::METALLIC_GOLD = { 173, 142, 66, 0 };
 const SDL_Color Colors::GREEN = { 0, 255, 0, 0 };
 
+#if (SDL_MAJOR_VERSION == 2)
+void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h)
+{
+	Rect rect(x,y,w,h);
+	if(0 !=SDL_UpdateTexture(screenTexture, &rect, surface->pixels, surface->pitch))
+		logGlobal->errorStream() << __FUNCTION__ << "SDL_UpdateTexture " << SDL_GetError();
+
+	SDL_RenderClear(mainRenderer);
+	if(0 != SDL_RenderCopy(mainRenderer, screenTexture, NULL, NULL))
+		logGlobal->errorStream() << __FUNCTION__ << "SDL_RenderCopy " <<  SDL_GetError();
+	SDL_RenderPresent(mainRenderer);	
+	
+}
+#endif // VCMI_SDL1
+
 SDL_Surface * CSDL_Ext::newSurface(int w, int h, SDL_Surface * mod) //creates new surface, with flags/format same as in surface given
 {
 	SDL_Surface * ret = SDL_CreateRGBSurface(mod->flags,w,h,mod->format->BitsPerPixel,mod->format->Rmask,mod->format->Gmask,mod->format->Bmask,mod->format->Amask);
@@ -490,12 +505,19 @@ Uint32 CSDL_Ext::colorToUint32(const SDL_Color * color)
 
 void CSDL_Ext::update(SDL_Surface * what)
 {
-//	#ifdef VCMI_SDL1
-//	if(what)
-		SDL_UpdateRect(what, 0, 0, what->w, what->h);
-//	#else
-//		SDL_UpdateTexture(screenTexture, NULL, what->pixels, what->pitch);
-//	#endif
+	#ifdef VCMI_SDL1
+	if(what)
+		SDL_UpdateRect(what, 0, 0, what->w, what->h);	
+	#else
+	Rect rect(0,0,what->w,what->h);
+	if(!what)
+		return;
+	if(0 !=SDL_UpdateTexture(screenTexture, &rect, what->pixels, what->pitch))
+		logGlobal->errorStream() << __FUNCTION__ << "SDL_UpdateTexture " << SDL_GetError();		
+	#endif // VCMI_SDL1
+
+		
+	
 }
 void CSDL_Ext::drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const int3 &color)
 {

+ 1 - 11
client/gui/SDL_Extensions.h

@@ -52,17 +52,7 @@ inline void SDL_WarpMouse(int x, int y)
 	SDL_WarpMouseInWindow(mainWindow,x,y);
 }
 
-inline void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h)
-{
-	Rect rect(x,y,w,h);
-	SDL_UpdateTexture(screenTexture, &rect, surface->pixels, surface->pitch);
-
-	SDL_RenderClear(mainRenderer);
-	SDL_RenderCopy(mainRenderer, screenTexture, NULL, NULL);
-
-	SDL_RenderPresent(mainRenderer);	
-	
-}
+void SDL_UpdateRect(SDL_Surface *surface, int x, int y, int w, int h);
 #endif
 
 inline bool isCtrlKeyDown()