mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	* BitmapHandler thread-safe
* multi-threaded loading main graphics
This commit is contained in:
		
							
								
								
									
										35
									
								
								CThreadHelper.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								CThreadHelper.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| #include "CThreadHelper.h" | ||||
| #include <boost/thread.hpp> | ||||
| #include <boost/bind.hpp> | ||||
| CThreadHelper::CThreadHelper(std::vector<boost::function<void()> > *Tasks, int Threads) | ||||
| { | ||||
| 	currentTask = 0; amount = Tasks->size(); | ||||
| 	tasks = Tasks; | ||||
| 	threads = Threads; | ||||
| } | ||||
| void CThreadHelper::run() | ||||
| { | ||||
| 	boost::thread_group grupa; | ||||
| 	for(int i=0;i<threads;i++) | ||||
| 		grupa.create_thread(boost::bind(&CThreadHelper::processTasks,this)); | ||||
| 	grupa.join_all(); | ||||
| } | ||||
| void CThreadHelper::processTasks() | ||||
| { | ||||
| 	int pom; | ||||
| 	while(true) | ||||
| 	{ | ||||
| 		rtinm.lock(); | ||||
| 		if((pom=currentTask) >= amount) | ||||
| 		{ | ||||
| 			rtinm.unlock(); | ||||
| 			break; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			++currentTask; | ||||
| 			rtinm.unlock(); | ||||
| 			(*tasks)[pom](); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										38
									
								
								CThreadHelper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								CThreadHelper.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| #include "global.h" | ||||
| #include <boost/function.hpp> | ||||
| #include <boost/thread.hpp> | ||||
| typedef boost::function<void()> Task; | ||||
|  | ||||
| class CThreadHelper | ||||
| { | ||||
| 	boost::mutex rtinm; | ||||
| 	int currentTask, amount, threads; | ||||
| 	std::vector<Task> *tasks; | ||||
|  | ||||
|  | ||||
| 	void processTasks(); | ||||
| public: | ||||
| 	CThreadHelper(std::vector<boost::function<void()> > *Tasks, int Threads); | ||||
| 	void run(); | ||||
| }; | ||||
|  | ||||
| template <typename T> inline void setData(T * data, boost::function<T()> func) | ||||
| { | ||||
| 	*data = func(); | ||||
| } | ||||
|  | ||||
|  | ||||
| #define GET_DATA(TYPE,DESTINATION,FUNCTION_TO_GET) \ | ||||
| 	(boost::bind(&setData<TYPE>,&DESTINATION,FUNCTION_TO_GET)) | ||||
| #define GET_SURFACE(SUR_DESTINATION, SUR_NAME) \ | ||||
| 	(GET_DATA \ | ||||
| 		(SDL_Surface*,SUR_DESTINATION,\ | ||||
| 		boost::function<SDL_Surface*()>(boost::bind(&BitmapHandler::loadBitmap,SUR_NAME,true)))) | ||||
| #define GET_DEF(DESTINATION, DEF_NAME) \ | ||||
| 	(GET_DATA \ | ||||
| 		(CDefHandler*,DESTINATION,\ | ||||
| 		boost::function<CDefHandler*()>(boost::bind(CDefHandler::giveDef,DEF_NAME,(CLodHandler*)NULL)))) | ||||
| #define GET_DEF_ESS(DESTINATION, DEF_NAME) \ | ||||
| 	(GET_DATA \ | ||||
| 		(CDefEssential*,DESTINATION,\ | ||||
| 		boost::function<CDefEssential*()>(boost::bind(CDefHandler::giveDefEss,DEF_NAME,(CLodHandler*)NULL)))) | ||||
| @@ -5,6 +5,8 @@ | ||||
| #include "../hch/CDefHandler.h" | ||||
| #include "../hch/CLodHandler.h" | ||||
| #include <sstream> | ||||
| #include <boost/thread.hpp> | ||||
| boost::mutex bitmap_handler_mx; | ||||
| int readNormalNr (int pos, int bytCon, unsigned char * str); | ||||
| CLodHandler * BitmapHandler::bitmaph = NULL; | ||||
| void BMPHeader::print(std::ostream & out) | ||||
| @@ -253,7 +255,7 @@ SDL_Surface * CPCXConv::getSurface() | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| SDL_Surface * BitmapHandler::loadBitmap(std::string fname) | ||||
| SDL_Surface * BitmapHandler::loadBitmap(std::string fname, bool setKey) | ||||
| { | ||||
| 	if(!fname.size()) | ||||
| 		return NULL; | ||||
| @@ -309,16 +311,19 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	bitmap_handler_mx.lock(); | ||||
| 	fseek(bitmaph->FLOD, e->offset, 0); | ||||
| 	if (e->size==0) //file is not compressed | ||||
| 	{ | ||||
| 		pcx = new unsigned char[e->realSize]; | ||||
| 		fread((char*)pcx, 1, e->realSize, bitmaph->FLOD); | ||||
| 		bitmap_handler_mx.unlock(); | ||||
| 	} | ||||
| 	else  | ||||
| 	{ | ||||
| 		unsigned char * pcd = new unsigned char[e->size]; | ||||
| 		fread((char*)pcd, 1, e->size, bitmaph->FLOD); | ||||
| 		bitmap_handler_mx.unlock(); | ||||
| 		int res=bitmaph->infs2(pcd,e->size,e->realSize,pcx); | ||||
| 		if(res!=0) | ||||
| 		{ | ||||
| @@ -328,5 +333,8 @@ SDL_Surface * BitmapHandler::loadBitmap(std::string fname) | ||||
| 	} | ||||
| 	CPCXConv cp; | ||||
| 	cp.openPCX((char*)pcx,e->realSize); | ||||
| 	return cp.getSurface(); | ||||
| 	SDL_Surface * ret = cp.getSurface(); | ||||
| 	if(setKey) | ||||
| 		SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255)); | ||||
| 	return ret; | ||||
| } | ||||
| @@ -35,5 +35,5 @@ public: | ||||
| namespace BitmapHandler | ||||
| { | ||||
| 	extern CLodHandler *bitmaph; | ||||
| 	SDL_Surface * loadBitmap(std::string fname); | ||||
| 	SDL_Surface * loadBitmap(std::string fname, bool setKey=false); | ||||
| }; | ||||
| @@ -8,7 +8,11 @@ | ||||
| #include <sstream> | ||||
| #include <iomanip> | ||||
| #include <boost/thread.hpp> | ||||
| #include <boost/function.hpp> | ||||
| #include <boost/bind.hpp> | ||||
| #include <boost/assign/std/vector.hpp> | ||||
| #include "../CThreadHelper.h" | ||||
| using namespace boost::assign; | ||||
| using namespace CSDL_Ext; | ||||
| Graphics * graphics = NULL; | ||||
| SDL_Surface * Graphics::drawPrimarySkill(const CGHeroInstance *curh, SDL_Surface *ret, int from, int to) | ||||
| @@ -80,11 +84,6 @@ SDL_Surface * Graphics::drawTownInfoWin(const CGTownInstance * curh) | ||||
| } | ||||
| Graphics::Graphics() | ||||
| { | ||||
| 	artDefs = CDefHandler::giveDef("ARTIFACT.DEF"); | ||||
| 	hInfo = BitmapHandler::loadBitmap("HEROQVBK.bmp"); | ||||
| 	SDL_SetColorKey(hInfo,SDL_SRCCOLORKEY,SDL_MapRGB(hInfo->format,0,255,255)); | ||||
| 	tInfo = BitmapHandler::loadBitmap("TOWNQVBK.bmp"); | ||||
| 	SDL_SetColorKey(tInfo,SDL_SRCCOLORKEY,SDL_MapRGB(tInfo->format,0,255,255)); | ||||
| 	slotsPos.push_back(std::pair<int,int>(44,82)); | ||||
| 	slotsPos.push_back(std::pair<int,int>(80,82)); | ||||
| 	slotsPos.push_back(std::pair<int,int>(116,82)); | ||||
| @@ -93,45 +92,61 @@ Graphics::Graphics() | ||||
| 	slotsPos.push_back(std::pair<int,int>(98,131)); | ||||
| 	slotsPos.push_back(std::pair<int,int>(134,131)); | ||||
|  | ||||
| 	luck22 = CDefHandler::giveDefEss("ILCK22.DEF"); | ||||
| 	luck30 = CDefHandler::giveDefEss("ILCK30.DEF"); | ||||
| 	luck42 = CDefHandler::giveDefEss("ILCK42.DEF"); | ||||
| 	luck82 = CDefHandler::giveDefEss("ILCK82.DEF"); | ||||
| 	morale22 = CDefHandler::giveDefEss("IMRL22.DEF"); | ||||
| 	morale30 = CDefHandler::giveDefEss("IMRL30.DEF"); | ||||
| 	morale42 = CDefHandler::giveDefEss("IMRL42.DEF"); | ||||
| 	morale82 = CDefHandler::giveDefEss("IMRL82.DEF"); | ||||
| 	halls = CDefHandler::giveDefEss("ITMTLS.DEF"); | ||||
| 	forts = CDefHandler::giveDefEss("ITMCLS.DEF"); | ||||
| 	bigTownPic =  CDefHandler::giveDefEss("ITPT.DEF"); | ||||
| 	std::ifstream ifs; | ||||
| 	ifs.open("config/cr_bgs.txt");  | ||||
| 	CDefHandler *smi, *smi2; | ||||
|  | ||||
| 	std::vector<Task> tasks; //preparing list of graphics to load | ||||
| 	tasks += boost::bind(&Graphics::loadHeroFlags,this); | ||||
| 	tasks += boost::bind(&Graphics::loadHeroPortraits,this); | ||||
| 	tasks += GET_SURFACE(hInfo,"HEROQVBK.bmp"); | ||||
| 	tasks += GET_SURFACE(tInfo,"TOWNQVBK.bmp"); | ||||
| 	tasks += GET_DEF(artDefs,"ARTIFACT.DEF"); | ||||
| 	tasks += GET_DEF_ESS(forts,"ITMCLS.DEF"); | ||||
| 	tasks += GET_DEF_ESS(luck22,"ILCK22.DEF"); | ||||
| 	tasks += GET_DEF_ESS(luck30,"ILCK30.DEF"); | ||||
| 	tasks += GET_DEF_ESS(luck42,"ILCK42.DEF"); | ||||
| 	tasks += GET_DEF_ESS(luck82,"ILCK82.DEF"); | ||||
| 	tasks += GET_DEF_ESS(morale22,"IMRL22.DEF"); | ||||
| 	tasks += GET_DEF_ESS(morale30,"IMRL30.DEF"); | ||||
| 	tasks += GET_DEF_ESS(morale42,"IMRL42.DEF"); | ||||
| 	tasks += GET_DEF_ESS(morale82,"IMRL82.DEF"); | ||||
| 	tasks += GET_DEF_ESS(halls,"ITMTLS.DEF"); | ||||
| 	tasks += GET_DEF_ESS(bigTownPic,"ITPT.DEF"); | ||||
| 	tasks += GET_DEF(pskillsb,"PSKILL.DEF"); | ||||
| 	tasks += GET_DEF(resources,"RESOUR82.DEF"); | ||||
| 	tasks += GET_DEF(un44,"UN44.DEF"); | ||||
| 	tasks += GET_DEF(smallIcons,"ITPA.DEF"); | ||||
| 	tasks += GET_DEF(resources32,"RESOURCE.DEF"); | ||||
| 	tasks += GET_DEF(smi,"CPRSMALL.DEF"); | ||||
| 	tasks += GET_DEF(smi2,"TWCRPORT.DEF"); | ||||
|  | ||||
| 	std::ifstream ifs("config/cr_bgs.txt");  | ||||
| 	int id; | ||||
| 	std::string name; | ||||
| 	while(!ifs.eof()) | ||||
| 	{ | ||||
| 		int id; | ||||
| 		std::string name; | ||||
| 		ifs >> id >> name; | ||||
| 		backgrounds[id]=BitmapHandler::loadBitmap(name); | ||||
| 		tasks += GET_SURFACE(backgrounds[id],name); | ||||
| 	} | ||||
| 	ifs.close(); | ||||
| 	ifs.clear(); | ||||
|  | ||||
| 	//loading 32x32px imgs | ||||
| 	CDefHandler *smi = CDefHandler::giveDef("CPRSMALL.DEF"); | ||||
| 	CThreadHelper th(&tasks,max(1,boost::thread::hardware_concurrency())); | ||||
| 	th.run(); | ||||
|  | ||||
| 	//handling 32x32px imgs | ||||
| 	smi->notFreeImgs = true; | ||||
| 	for (int i=0; i<smi->ourImages.size(); i++) | ||||
| 	{ | ||||
| 		smallImgs[i-2] = smi->ourImages[i].bitmap; | ||||
| 	} | ||||
| 	delete smi; | ||||
| 	smi = CDefHandler::giveDef("TWCRPORT.DEF"); | ||||
| 	smi->notFreeImgs = true; | ||||
| 	for (int i=0; i<smi->ourImages.size(); i++) | ||||
| 	smi2->notFreeImgs = true; | ||||
| 	for (int i=0; i<smi2->ourImages.size(); i++) | ||||
| 	{ | ||||
| 		bigImgs[i-2] = smi->ourImages[i].bitmap; | ||||
| 		bigImgs[i-2] = smi2->ourImages[i].bitmap; | ||||
| 	} | ||||
| 	delete smi; | ||||
|  | ||||
| 	delete smi2; | ||||
| } | ||||
| void Graphics::loadHeroPortraits() | ||||
| {	 | ||||
| 	std::ifstream of("config/portrety.txt"); | ||||
| 	for (int j=0;j<HEROES_QUANTITY;j++) | ||||
| 	{ | ||||
| @@ -140,8 +155,6 @@ Graphics::Graphics() | ||||
| 		std::string path; | ||||
| 		of>>path; | ||||
| 		portraitSmall.push_back(BitmapHandler::loadBitmap(path)); | ||||
| 		//if (!heroes[ID]->portraitSmall) | ||||
| 		//	std::cout<<"Can't read small portrait for "<<ID<<" ("<<path<<")\n"; | ||||
| 		for(int ff=0; ff<path.size(); ++ff) //size letter is usually third one, but there are exceptions an it should fix the problem | ||||
| 		{ | ||||
| 			if(path[ff]=='S') | ||||
| @@ -151,18 +164,10 @@ Graphics::Graphics() | ||||
| 			} | ||||
| 		} | ||||
| 		portraitLarge.push_back(BitmapHandler::loadBitmap(path)); | ||||
| 		//if (!heroes[ID]->portraitLarge) | ||||
| 		//	std::cout<<"Can't read large portrait for "<<ID<<" ("<<path<<")\n";	 | ||||
| 		SDL_SetColorKey(portraitLarge[portraitLarge.size()-1],SDL_SRCCOLORKEY,SDL_MapRGB(portraitLarge[portraitLarge.size()-1]->format,0,255,255)); | ||||
|  | ||||
| 	} | ||||
| 	of.close(); | ||||
| 	pskillsb = CDefHandler::giveDef("PSKILL.DEF"); | ||||
| 	resources = CDefHandler::giveDef("RESOUR82.DEF"); | ||||
| 	un44 = CDefHandler::giveDef("UN44.DEF"); | ||||
| 	smallIcons = CDefHandler::giveDef("ITPA.DEF"); | ||||
| 	resources32 = CDefHandler::giveDef("RESOURCE.DEF"); | ||||
| 	loadHeroFlags(); | ||||
| } | ||||
| void Graphics::loadHeroAnim(std::vector<CDefHandler **> & anims) | ||||
| { | ||||
| @@ -377,7 +382,7 @@ void Graphics::loadHeroFlags() | ||||
| 	grupa.create_thread(boost::bind(&Graphics::loadHeroFlags,this,boost::ref(pr[1]),false)); | ||||
| 	grupa.create_thread(boost::bind(&Graphics::loadHeroFlags,this,boost::ref(pr[0]),false)); | ||||
| 	grupa.join_all(); | ||||
| 	std::cout << "Flagi: "<<th.getDif()<<std::endl; | ||||
| 	std::cout << "Loading and transforming heroes' flags: "<<th.getDif()<<std::endl; | ||||
| } | ||||
| SDL_Surface * Graphics::getPic(int ID, bool fort, bool builded) | ||||
| { | ||||
|   | ||||
| @@ -34,6 +34,7 @@ public: | ||||
| 	void loadHeroFlags(); | ||||
| 	void loadHeroFlags(std::pair<std::vector<CDefHandler *> Graphics::*, std::vector<const char *> > &pr, bool mode); | ||||
| 	void loadHeroAnim(std::vector<CDefHandler **> & anims); | ||||
| 	void loadHeroPortraits(); | ||||
| 	SDL_Surface * drawHeroInfoWin(const CGHeroInstance * curh); | ||||
| 	SDL_Surface * drawPrimarySkill(const CGHeroInstance *curh, SDL_Surface *ret, int from=0, int to=PRIMARY_SKILLS); | ||||
| 	SDL_Surface * drawTownInfoWin(const CGTownInstance * curh); | ||||
|   | ||||
| @@ -376,6 +376,10 @@ | ||||
| 				RelativePath="..\hch\CSpellHandler.cpp" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\CThreadHelper.cpp" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath=".\Graphics.cpp" | ||||
| 				> | ||||
| @@ -558,6 +562,10 @@ | ||||
| 				RelativePath="..\hch\CAmbarCendamo.h" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\hch\CArtHandler.h" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\CBattleInterface.h" | ||||
| 				> | ||||
| @@ -586,6 +594,10 @@ | ||||
| 				RelativePath=".\CCreatureAnimation.h" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\hch\CCreatureHandler.h" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\CCursorHandler.h" | ||||
| 				> | ||||
| @@ -610,6 +622,10 @@ | ||||
| 				RelativePath="..\hch\CGeneralTextHandler.h" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\hch\CHeroHandler.h" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\CHeroWindow.h" | ||||
| 				> | ||||
| @@ -630,6 +646,10 @@ | ||||
| 				RelativePath="..\hch\CMusicHandler.h" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\hch\CObjectHandler.h" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\CPathfinder.h" | ||||
| 				> | ||||
| @@ -658,6 +678,10 @@ | ||||
| 				RelativePath="..\hch\CSpellHandler.h" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\CThreadHelper.h" | ||||
| 				> | ||||
| 			</File> | ||||
| 			<File | ||||
| 				RelativePath="..\global.h" | ||||
| 				> | ||||
|   | ||||
| @@ -176,12 +176,6 @@ DLL_EXPORT int CLodHandler::infs2(unsigned char * in, int size, int realSize, un | ||||
| 		} | ||||
| 		++chunkNumber; | ||||
| 		strm.avail_in = readBytes; | ||||
| 		//strm.avail_in = fread(inx, 1, NLoadHandlerHelp::fCHUNK, source); | ||||
| 		/*if (in.bad()) | ||||
| 		{ | ||||
| 			(void)inflateEnd(&strm); | ||||
| 			return Z_ERRNO; | ||||
| 		}*/ | ||||
| 		if (strm.avail_in == 0) | ||||
| 			break; | ||||
| 		strm.next_in = inx; | ||||
| @@ -203,22 +197,11 @@ DLL_EXPORT int CLodHandler::infs2(unsigned char * in, int size, int realSize, un | ||||
| 					return ret; | ||||
| 			} | ||||
| 			have = NLoadHandlerHelp::fCHUNK - strm.avail_out; | ||||
| 			/*if (fwrite(out, 1, have, dest) != have || ferror(dest)) | ||||
| 			{ | ||||
| 				(void)inflateEnd(&strm); | ||||
| 				return Z_ERRNO; | ||||
| 			}*/ | ||||
| 			//out.write((char*)outx, have); | ||||
| 			for(int oo=0; oo<have; ++oo) | ||||
| 			{ | ||||
| 				out[latPosOut] = outx[oo]; | ||||
| 				++latPosOut; | ||||
| 			} | ||||
| 			/*if(out.bad()) | ||||
| 			{ | ||||
| 				(void)inflateEnd(&strm); | ||||
| 				return Z_ERRNO; | ||||
| 			}*/ | ||||
| 		} while (strm.avail_out == 0); | ||||
|  | ||||
| 		/* done when inflate() says it's done */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user