mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
* BitmapHandler thread-safe
* multi-threaded loading main graphics
This commit is contained in:
parent
d5b0bdcf9e
commit
3988767329
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");
|
||||
while(!ifs.eof())
|
||||
{
|
||||
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())
|
||||
{
|
||||
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 */
|
||||
|
Loading…
Reference in New Issue
Block a user