From 39887673297c87ea460d16fed152065ff1a134c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Mon, 16 Jun 2008 14:56:48 +0000 Subject: [PATCH] * BitmapHandler thread-safe * multi-threaded loading main graphics --- CThreadHelper.cpp | 35 +++++++++++++++ CThreadHelper.h | 38 +++++++++++++++++ client/CBitmapHandler.cpp | 12 +++++- client/CBitmapHandler.h | 2 +- client/Graphics.cpp | 89 +++++++++++++++++++++------------------ client/Graphics.h | 1 + client/VCMI_client.vcproj | 24 +++++++++++ hch/CLodHandler.cpp | 17 -------- 8 files changed, 156 insertions(+), 62 deletions(-) create mode 100644 CThreadHelper.cpp create mode 100644 CThreadHelper.h diff --git a/CThreadHelper.cpp b/CThreadHelper.cpp new file mode 100644 index 000000000..448f99c37 --- /dev/null +++ b/CThreadHelper.cpp @@ -0,0 +1,35 @@ +#include "CThreadHelper.h" +#include +#include +CThreadHelper::CThreadHelper(std::vector > *Tasks, int Threads) +{ + currentTask = 0; amount = Tasks->size(); + tasks = Tasks; + threads = Threads; +} +void CThreadHelper::run() +{ + boost::thread_group grupa; + for(int i=0;i= amount) + { + rtinm.unlock(); + break; + } + else + { + ++currentTask; + rtinm.unlock(); + (*tasks)[pom](); + } + } +} \ No newline at end of file diff --git a/CThreadHelper.h b/CThreadHelper.h new file mode 100644 index 000000000..61cd9e462 --- /dev/null +++ b/CThreadHelper.h @@ -0,0 +1,38 @@ +#include "global.h" +#include +#include +typedef boost::function Task; + +class CThreadHelper +{ + boost::mutex rtinm; + int currentTask, amount, threads; + std::vector *tasks; + + + void processTasks(); +public: + CThreadHelper(std::vector > *Tasks, int Threads); + void run(); +}; + +template inline void setData(T * data, boost::function func) +{ + *data = func(); +} + + +#define GET_DATA(TYPE,DESTINATION,FUNCTION_TO_GET) \ + (boost::bind(&setData,&DESTINATION,FUNCTION_TO_GET)) +#define GET_SURFACE(SUR_DESTINATION, SUR_NAME) \ + (GET_DATA \ + (SDL_Surface*,SUR_DESTINATION,\ + boost::function(boost::bind(&BitmapHandler::loadBitmap,SUR_NAME,true)))) +#define GET_DEF(DESTINATION, DEF_NAME) \ + (GET_DATA \ + (CDefHandler*,DESTINATION,\ + boost::function(boost::bind(CDefHandler::giveDef,DEF_NAME,(CLodHandler*)NULL)))) +#define GET_DEF_ESS(DESTINATION, DEF_NAME) \ + (GET_DATA \ + (CDefEssential*,DESTINATION,\ + boost::function(boost::bind(CDefHandler::giveDefEss,DEF_NAME,(CLodHandler*)NULL)))) \ No newline at end of file diff --git a/client/CBitmapHandler.cpp b/client/CBitmapHandler.cpp index da5658106..b7b600729 100644 --- a/client/CBitmapHandler.cpp +++ b/client/CBitmapHandler.cpp @@ -5,6 +5,8 @@ #include "../hch/CDefHandler.h" #include "../hch/CLodHandler.h" #include +#include +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; } \ No newline at end of file diff --git a/client/CBitmapHandler.h b/client/CBitmapHandler.h index 368679ae6..53114c138 100644 --- a/client/CBitmapHandler.h +++ b/client/CBitmapHandler.h @@ -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); }; \ No newline at end of file diff --git a/client/Graphics.cpp b/client/Graphics.cpp index 8389644a4..1f491c6ad 100644 --- a/client/Graphics.cpp +++ b/client/Graphics.cpp @@ -8,7 +8,11 @@ #include #include #include +#include #include +#include +#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(44,82)); slotsPos.push_back(std::pair(80,82)); slotsPos.push_back(std::pair(116,82)); @@ -93,45 +92,61 @@ Graphics::Graphics() slotsPos.push_back(std::pair(98,131)); slotsPos.push_back(std::pair(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 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; iourImages.size(); i++) { smallImgs[i-2] = smi->ourImages[i].bitmap; } delete smi; - smi = CDefHandler::giveDef("TWCRPORT.DEF"); - smi->notFreeImgs = true; - for (int i=0; iourImages.size(); i++) + smi2->notFreeImgs = true; + for (int i=0; iourImages.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>path; portraitSmall.push_back(BitmapHandler::loadBitmap(path)); - //if (!heroes[ID]->portraitSmall) - // std::cout<<"Can't read small portrait for "<portraitLarge) - // std::cout<<"Can't read large portrait for "<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 & 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: "< Graphics::*, std::vector > &pr, bool mode); void loadHeroAnim(std::vector & 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); diff --git a/client/VCMI_client.vcproj b/client/VCMI_client.vcproj index c2250a898..ac047bde2 100644 --- a/client/VCMI_client.vcproj +++ b/client/VCMI_client.vcproj @@ -376,6 +376,10 @@ RelativePath="..\hch\CSpellHandler.cpp" > + + @@ -558,6 +562,10 @@ RelativePath="..\hch\CAmbarCendamo.h" > + + @@ -586,6 +594,10 @@ RelativePath=".\CCreatureAnimation.h" > + + @@ -610,6 +622,10 @@ RelativePath="..\hch\CGeneralTextHandler.h" > + + @@ -630,6 +646,10 @@ RelativePath="..\hch\CMusicHandler.h" > + + @@ -658,6 +678,10 @@ RelativePath="..\hch\CSpellHandler.h" > + + diff --git a/hch/CLodHandler.cpp b/hch/CLodHandler.cpp index 7335484b0..4fed56801 100644 --- a/hch/CLodHandler.cpp +++ b/hch/CLodHandler.cpp @@ -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