Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include <string></string>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trenderer.h"
Toshihiro Shimizu 890ddd
#include "tcacheresourcepool.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tfxcachemanager.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Debug
Toshihiro Shimizu 890ddd
//#define DIAGNOSTICS
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "diagnostics.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#define WRITESTACK
Toshihiro Shimizu 890ddd
//#define WRITESUBRECTS
Toshihiro Shimizu 890ddd
//#define WRITEGENERAL
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
QString traduce(const TRectD &rect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return "[" + QString::number(rect.x0) + " " + QString::number(rect.y0) + " " + QString::number(rect.x1) + " " + QString::number(rect.y1) + "]";
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QString traduce(const TTile &tile)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TDimension dim(tile.getRaster()->getSize());
Toshihiro Shimizu 890ddd
	TRectD tileRect(tile.m_pos, TDimensionD(dim.lx, dim.ly));
Toshihiro Shimizu 890ddd
	return traduce(tileRect);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
QString prefixInfo("#info.txt | ");
Toshihiro Shimizu 890ddd
QString prefixWarn("#warning.txt | ");
Toshihiro Shimizu 890ddd
QString prefixErr("#error.txt | ");
Toshihiro Shimizu 890ddd
QString prefixTest("#TestRun.txt | ");
Toshihiro Shimizu 890ddd
QString prefixComp("#Computing.txt | ");
Toshihiro Shimizu 890ddd
QString prefixSubTiles("#SubTiles.txt | ");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif //DIAGNOSTICS
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    Explanation
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*
Toshihiro Shimizu 890ddd
This file contains most of the code that deals with smart caching during a Toonz render process.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
The paradigms on which the 'smart caching' takes place are:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
  - Only calculations resulting in an image positioned in a plane are dealt. These results are
Toshihiro Shimizu 890ddd
    called 'tiles' - and are modeled by a TTile instance.
Toshihiro Shimizu 890ddd
    These images MUST BE wrapped to INTEGER POSITIONS on the reference, and are intended so that
Toshihiro Shimizu 890ddd
    a PIXEL corresponds to a UNIT SQUARE.
Toshihiro Shimizu 890ddd
  - Given one such calculation procedure, it MUST BE SIMULABLE, so that children calculations
Toshihiro Shimizu 890ddd
    are invoked 'faithfully' with respect to the actual calculation.
Toshihiro Shimizu 890ddd
    This is necessary to predict results in advance in force of which we can efficiently store
Toshihiro Shimizu 890ddd
    results in the cache, releasing them when they will no longer be required.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Now, the principal classes dealing with this job are:
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
 - One TFxCacheManager per render instance, used to store predictive informations.
Toshihiro Shimizu 890ddd
 - A set of TFxCacheManagerDelegate per render instance, used to store references to cache resources
Toshihiro Shimizu 890ddd
   and providing reasons for caching results.
Toshihiro Shimizu 890ddd
 - The ResourceBuilder interface class, used by users to access the smart caching ensemble. This class
Toshihiro Shimizu 890ddd
   implements the actual resources build and simulation code.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    Preliminaries
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
//Global variables
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Utility functions
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline QRect toQRect(const TRect &r) { return QRect(r.x0, r.y0, r.getLx(), r.getLy()); }
Toshihiro Shimizu 890ddd
inline TRect toTRect(const QRect &r) { return TRect(r.left(), r.top(), r.right(), r.bottom()); }
Toshihiro Shimizu 890ddd
inline QPoint toQPoint(const TPoint &p) { return QPoint(p.x, p.y); }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
inline bool isEmpty(const TRectD &rect) { return rect.x0 >= rect.x1 || rect.y0 >= rect.y1; }
Toshihiro Shimizu 890ddd
inline void enlargeToI(TRectD &r)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TRectD temp(tfloor(r.x0), tfloor(r.y0), tceil(r.x1), tceil(r.y1));
Toshihiro Shimizu 890ddd
	if (!isEmpty(temp))
Toshihiro Shimizu 890ddd
		r = temp; //Since r could have TConsts::infiniteRectD-like coordinates...
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//Qt's contains actually returns QRegion::intersected... I wonder why...
Toshihiro Shimizu 890ddd
inline bool contains(const QRegion ®ion, const TRect &rect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return QRegion(toQRect(rect)).subtracted(region).isEmpty();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
bool getTilesToBuild(const ResourceData &data, const TRectD &rect,
Toshihiro Shimizu 890ddd
					 std::vector<resourcedeclaration::tiledata *=""> &rectsToCalculate);</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    TFxCacheManager Generator
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TFxCacheManagerGenerator : public TRenderResourceManagerGenerator
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	TFxCacheManagerGenerator() : TRenderResourceManagerGenerator(true) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRenderResourceManager *operator()() { return new TFxCacheManager; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
MANAGER_FILESCOPE_DECLARATION(TFxCacheManager, TFxCacheManagerGenerator);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    TFxCacheManager implementation
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
class TFxCacheManager::Imp
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	typedef std::map<std::string, resourcedeclaration=""> ResourceInstanceDataMap;</std::string,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ResourceInstanceDataMap m_resourcesData;
Toshihiro Shimizu 890ddd
	std::map<resourcedeclaration *,="" resourcedeclaration::rawdata=""> m_rawData;</resourcedeclaration>
Toshihiro Shimizu 890ddd
	int m_renderStatus;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QMutex m_mutex;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Toshihiro Shimizu 890ddd
	void prepareTilesToCalculate(ResourceDeclaration &data);
Toshihiro Shimizu 890ddd
	inline void subdivideIntoSmallerTiles(const TRectD &rect, std::vector<trectd> &tileSet);</trectd>
Toshihiro Shimizu 890ddd
	void recursiveRectSubdivide(
Toshihiro Shimizu 890ddd
		std::vector<resourcedeclaration::tiledata> &results, TRasterFx *fx,</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
		const TRectD &rect, double frame, const TRenderSettings &info,
Toshihiro Shimizu 890ddd
		int dropTol = (std::numeric_limits<int>::max)());</int>
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    Methods implementation
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//========================
Toshihiro Shimizu 890ddd
//    TFxCacheManager
Toshihiro Shimizu 890ddd
//------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFxCacheManager::TFxCacheManager()
Toshihiro Shimizu 890ddd
	: m_imp(new Imp)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFxCacheManager::~TFxCacheManager()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Release all the static-cached images
Toshihiro Shimizu 890ddd
	std::set<std::string>::iterator it;</std::string>
Toshihiro Shimizu 890ddd
	for (it = m_staticCacheIds.begin(); it != m_staticCacheIds.end(); ++it)
Toshihiro Shimizu 890ddd
		TImageCache::instance()->remove(*it);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	delete m_imp;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TFxCacheManager *TFxCacheManager::instance()
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	return static_cast<tfxcachemanager *="">(</tfxcachemanager>
Toshihiro Shimizu 890ddd
		TFxCacheManager::gen()->getManager(TRenderer::renderId()));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCacheManager::add(const std::string &cacheId, TImageP img)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TImageCache::instance()->add(cacheId, img);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
	m_staticCacheIds.insert(cacheId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCacheManager::remove(const std::string &cacheId)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TImageCache::instance()->remove(cacheId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QMutexLocker locker(&m_imp->m_mutex);
Toshihiro Shimizu 890ddd
	m_staticCacheIds.erase(cacheId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCacheManager::install(TFxCacheManagerDelegate *managerDelegate)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	m_delegates.insert(managerDelegate);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/*void TFxCacheManager::install(TFxCacheManagerListener* listener)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  m_listeners.insert(listener);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCacheManager::notifyResourceUpload(const TCacheResourceP& resource, const TRect& rect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  std::set<tfxcachemanagerlistener*>::iterator it;</tfxcachemanagerlistener*>
Toshihiro Shimizu 890ddd
  for(it = m_listeners.begin(); it != m_listeners.end(); ++it)
Toshihiro Shimizu 890ddd
    (*it)->onResourceUpload(resource, rect);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCacheManager::notifyResourceDownload(const TCacheResourceP& resource, const TRect& rect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  std::set<tfxcachemanagerlistener*>::iterator it;</tfxcachemanagerlistener*>
Toshihiro Shimizu 890ddd
  for(it = m_listeners.begin(); it != m_listeners.end(); ++it)
Toshihiro Shimizu 890ddd
    (*it)->onResourceDownload(resource, rect);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCacheManager::notifyPredictedRelease(const TCacheResourceP& resource)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
  std::set<tfxcachemanagerlistener*>::iterator it;</tfxcachemanagerlistener*>
Toshihiro Shimizu 890ddd
  for(it = m_listeners.begin(); it != m_listeners.end(); ++it)
Toshihiro Shimizu 890ddd
    (*it)->onPredictedRelease(resource);
Toshihiro Shimizu 890ddd
}*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    Resources dealing
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCacheManager::declareResource(
Toshihiro Shimizu 890ddd
	const string &alias, const TFxP &fx,
Toshihiro Shimizu 890ddd
	const TRectD &rect, double frame, const TRenderSettings &rs,
Toshihiro Shimizu 890ddd
	bool subtileable)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	Imp::ResourceInstanceDataMap::iterator it;
Toshihiro Shimizu 890ddd
	it = m_imp->m_resourcesData.insert(std::make_pair(alias, ResourceDeclaration())).first;
Toshihiro Shimizu 890ddd
	it->second.m_rawData =
Toshihiro Shimizu 890ddd
		&m_imp->m_rawData.insert(std::make_pair(&it->second, ResourceDeclaration::RawData())).first->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	ResourceDeclaration::RawData &rawData = *it->second.m_rawData;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Assign the sim data
Toshihiro Shimizu 890ddd
	rawData.m_fx = fx;
Toshihiro Shimizu 890ddd
	rawData.m_tiles.push_back(rect);
Toshihiro Shimizu 890ddd
	rawData.m_rs = rs;
Toshihiro Shimizu 890ddd
	rawData.m_frame = frame;
Toshihiro Shimizu 890ddd
	//rawData.m_bbox = bbox;
Toshihiro Shimizu 890ddd
	rawData.m_subtileable = subtileable;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ResourceData TFxCacheManager::getResource(
Toshihiro Shimizu 890ddd
	const string &alias,
Toshihiro Shimizu 890ddd
	const TFxP &fx, double frame, const TRenderSettings &rs)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TCacheResourceP result, temp;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Seek the associated infos
Toshihiro Shimizu 890ddd
	Imp::ResourceInstanceDataMap::iterator jt =
Toshihiro Shimizu 890ddd
		m_imp->m_resourcesData.find(alias);
Toshihiro Shimizu 890ddd
	ResourceDeclaration *decl = (jt == m_imp->m_resourcesData.end()) ? 0 : &jt->second;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Search the resource in cached mode.
Toshihiro Shimizu 890ddd
	//TCacheResourcePool* pool = TCacheResourcePool::instance();
Toshihiro Shimizu 890ddd
	//pool->beginCachedSearch();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Ask every installed delegate if it's managing - or want to manage
Toshihiro Shimizu 890ddd
	//the passed resource specs.
Toshihiro Shimizu 890ddd
	std::set<tfxcachemanagerdelegate *="">::iterator it;</tfxcachemanagerdelegate>
Toshihiro Shimizu 890ddd
	for (it = m_delegates.begin(); it != m_delegates.end(); ++it) {
Toshihiro Shimizu 890ddd
		(*it)->getResource(temp, alias, fx, frame, rs, decl);
Toshihiro Shimizu 890ddd
		if (!result && temp)
Toshihiro Shimizu 890ddd
			result = temp;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//pool->endCachedSearch();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return ResourceData(decl, result);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCacheManager::onRenderStatusStart(int renderStatus)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Store current render status
Toshihiro Shimizu 890ddd
	m_imp->m_renderStatus = renderStatus;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WRITESTACK
Toshihiro Shimizu 890ddd
	if (renderStatus == TRenderer::TESTRUN) {
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_GLOSTRSET("status", "test");
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_GLOSET("testInst", DIAGNOSTICS_GLOGET("compInst") + 1);
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_GLOSTRSET("instVar", QString::number(DIAGNOSTICS_GLOGET("testInst")));
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_GLOSTRSET("testRenderStr", "Render #" + QString::number(DIAGNOSTICS_GLOGET("testInst")) + " | ");
Toshihiro Shimizu 890ddd
	} else if (renderStatus == TRenderer::COMPUTING) {
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_GLOSTRSET("status", "comp");
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_GLOSTRSET("instVar", QString::number(DIAGNOSTICS_GLOGET("compInst")));
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_GLOSTRSET("compRenderStr", "Render #" + QString::number(DIAGNOSTICS_GLOGET("compInst")) + " | ");
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_GLOSET(DIAGNOSTICS_THRSTRGET("stackVar"), 0);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCacheManager::onRenderStatusEnd(int renderStatus)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	if (renderStatus == TRenderer::FIRSTRUN) {
Toshihiro Shimizu 890ddd
		Imp::ResourceInstanceDataMap &resMap = m_imp->m_resourcesData;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		Imp::ResourceInstanceDataMap::iterator it;
Toshihiro Shimizu 890ddd
		for (it = resMap.begin(); it != resMap.end();) {
Toshihiro Shimizu 890ddd
			m_imp->prepareTilesToCalculate(it->second);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//Cannot be done. The resource could still be feasible to caching,
Toshihiro Shimizu 890ddd
			//due to external requests.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//Erase all resource datas which have been declared and prepared only once
Toshihiro Shimizu 890ddd
			/*if(it->second.m_tiles.size() == 1 && it->second.m_simData->m_tiles.size() == 1)
Toshihiro Shimizu 890ddd
      {
Toshihiro Shimizu 890ddd
        it = resMap.erase(it);
Toshihiro Shimizu 890ddd
        continue;
Toshihiro Shimizu 890ddd
      }*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			++it;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	} else if (renderStatus == TRenderer::TESTRUN) {
Toshihiro Shimizu 890ddd
		Imp::ResourceInstanceDataMap &resMap = m_imp->m_resourcesData;
Toshihiro Shimizu 890ddd
		Imp::ResourceInstanceDataMap::iterator it;
Toshihiro Shimizu 890ddd
		for (it = resMap.begin(); it != resMap.end();) {
Toshihiro Shimizu 890ddd
			//Release all resource declarations which are declared to be used only once.
Toshihiro Shimizu 890ddd
			if (it->second.m_tiles.size() == 1 && it->second.m_tiles[0].m_refCount == 1) {
Toshihiro Shimizu 890ddd
				Imp::ResourceInstanceDataMap::iterator jt = it++;
Toshihiro Shimizu 890ddd
				resMap.erase(jt);
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//In any case, release all simulation datas - they are no longer useful.
Toshihiro Shimizu 890ddd
			//An associated cache resource avoids deletion only in case some manager
Toshihiro Shimizu 890ddd
			//retained it.
Toshihiro Shimizu 890ddd
			it->second.m_rawData = 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			++it;
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WRITEGENERAL
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_SET("Declarations used more than once", resMap.size());
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		m_imp->m_rawData.clear();
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
#ifdef WRITEGENERAL
Toshihiro Shimizu 890ddd
	else {
Toshihiro Shimizu 890ddd
		//Print the number of not depleted declarations
Toshihiro Shimizu 890ddd
		Imp::ResourceInstanceDataMap &resMap = m_imp->m_resourcesData;
Toshihiro Shimizu 890ddd
		Imp::ResourceInstanceDataMap::iterator it;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_ADD(prefixErr + "Computing | Declarations survived after Test Run", resMap.size());
Toshihiro Shimizu 890ddd
		if (resMap.size() > 0) {
Toshihiro Shimizu 890ddd
			for (it = resMap.begin(); it != resMap.end(); ++it) {
Toshihiro Shimizu 890ddd
				DIAGNOSTICS_STR(prefixErr + "Survived Declarations | " + QString::fromStdString(it->first).left(40));
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    Tiles to calculate - methods
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCacheManager::Imp::prepareTilesToCalculate(ResourceDeclaration &data)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//First, build the total sum of declared tiles
Toshihiro Shimizu 890ddd
	TRectD sum;
Toshihiro Shimizu 890ddd
	int tilesCount = data.m_rawData->m_tiles.size();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	for (int i = 0; i < tilesCount; ++i)
Toshihiro Shimizu 890ddd
		sum += data.m_rawData->m_tiles[i];
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Intersect the sum with bbox and ensure integer geometry
Toshihiro Shimizu 890ddd
	//sum *= data.m_rawData->m_bbox;
Toshihiro Shimizu 890ddd
	enlargeToI(sum);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!data.m_rawData->m_subtileable) {
Toshihiro Shimizu 890ddd
		data.m_tiles.push_back(sum);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRasterFx *fx = dynamic_cast<trasterfx *="">(data.m_rawData->m_fx.getPointer());</trasterfx>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Now, subdivide the sum
Toshihiro Shimizu 890ddd
	recursiveRectSubdivide(data.m_tiles, fx, sum, data.m_rawData->m_frame, data.m_rawData->m_rs);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//! Calculates at max 4 smaller subrects of passed one. Returns true or false whether the subdivision was
Toshihiro Shimizu 890ddd
//! successfully applied.
Toshihiro Shimizu 890ddd
inline void TFxCacheManager::Imp::subdivideIntoSmallerTiles(
Toshihiro Shimizu 890ddd
	const TRectD &rect, std::vector<trectd> &tileSet)</trectd>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Find the greater rect edge
Toshihiro Shimizu 890ddd
	TRectD subTile1, subTile2;
Toshihiro Shimizu 890ddd
	if (rect.getLx() > rect.getLy()) {
Toshihiro Shimizu 890ddd
		int sep = rect.x0 + tceil(0.5 * rect.getLx());
Toshihiro Shimizu 890ddd
		subTile1 = TRectD(rect.x0, rect.y0, sep, rect.y1);
Toshihiro Shimizu 890ddd
		subTile2 = TRectD(sep, rect.y0, rect.x1, rect.y1);
Toshihiro Shimizu 890ddd
	} else {
Toshihiro Shimizu 890ddd
		int sep = rect.y0 + tceil(0.5 * rect.getLy());
Toshihiro Shimizu 890ddd
		subTile1 = TRectD(rect.x0, rect.y0, rect.x1, sep);
Toshihiro Shimizu 890ddd
		subTile2 = TRectD(rect.x0, sep, rect.x1, rect.y1);
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	tileSet.push_back(subTile1);
Toshihiro Shimizu 890ddd
	tileSet.push_back(subTile2);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void TFxCacheManager::Imp::recursiveRectSubdivide(
Toshihiro Shimizu 890ddd
	std::vector<resourcedeclaration::tiledata> &results,</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
	TRasterFx *fx,
Toshihiro Shimizu 890ddd
	const TRectD &rect,
Toshihiro Shimizu 890ddd
	double frame,
Toshihiro Shimizu 890ddd
	const TRenderSettings &info,
Toshihiro Shimizu 890ddd
	int dropTol)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Here is the subdivision strategy:
Toshihiro Shimizu 890ddd
	//  - First, since cache tiles are newly ALLOCATED, we impose the raster
Toshihiro Shimizu 890ddd
	//    size restriction on them directly
Toshihiro Shimizu 890ddd
	//  - Then, we check that the memory requirement for the fx (max raster size
Toshihiro Shimizu 890ddd
	//    that it will allocate) is little.
Toshihiro Shimizu 890ddd
	//  - As an exception to previous point, if the memory requirement stagnates
Toshihiro Shimizu 890ddd
	//    near the same memory size, quit
Toshihiro Shimizu 890ddd
	//NOTE: Level images pass here, but haven't any fx. So they are currently not subdivided.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Retrieve the memory requirement for this input.
Toshihiro Shimizu 890ddd
	int memReq = fx ? fx->getMemoryRequirement(rect, frame, info) : 0;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//In case memReq < 0, we assume a strong subdivision denial, just as if the usage was
Toshihiro Shimizu 890ddd
	//explicitly set as unsubdividable.
Toshihiro Shimizu 890ddd
	if (memReq < 0) {
Toshihiro Shimizu 890ddd
		results.push_back(rect);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if ((memReq > info.m_maxTileSize && memReq < dropTol) ||
Toshihiro Shimizu 890ddd
		TRasterFx::memorySize(rect, info.m_bpp) > info.m_maxTileSize) {
Toshihiro Shimizu 890ddd
		std::vector<trectd> subTileRects;</trectd>
Toshihiro Shimizu 890ddd
		subdivideIntoSmallerTiles(rect, subTileRects);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		while (!subTileRects.empty()) {
Toshihiro Shimizu 890ddd
			TRectD subTileRect(subTileRects.back());
Toshihiro Shimizu 890ddd
			subTileRects.pop_back();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//Pass subdivision below, with updated drop-tolerance
Toshihiro Shimizu 890ddd
			recursiveRectSubdivide(results, fx, subTileRect, frame, info,
Toshihiro Shimizu 890ddd
								   memReq - (memReq >> 2));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//The newly required memory must be under 3/4 of the previous.
Toshihiro Shimizu 890ddd
			//This is required in order to make it worth subdividing.
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	results.push_back(ResourceDeclaration::TileData(rect));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
//    ResourceBuilder
Toshihiro Shimizu 890ddd
//****************************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
ResourceBuilder::ResourceBuilder(
Toshihiro Shimizu 890ddd
	const std::string &resourceName,
Toshihiro Shimizu 890ddd
	const TFxP &fx, double frame, const TRenderSettings &rs)
Toshihiro Shimizu 890ddd
	: m_cacheManager(TFxCacheManager::instance()), m_data(m_cacheManager->getResource(resourceName, fx, frame, rs))
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
#ifdef WRITESTACK
Toshihiro Shimizu 890ddd
	DIAGNOSTICS_THRSET("frame", frame);
Toshihiro Shimizu 890ddd
	DIAGNOSTICS_THRSTRSET("frameStr", "Frame " + QString::number(frame).rightJustified(4, ' ') + " | ");
Toshihiro Shimizu 890ddd
	DIAGNOSTICS_THRSTRSET("stackVar",
Toshihiro Shimizu 890ddd
						  DIAGNOSTICS_GLOSTRGET("status") + "sv" + DIAGNOSTICS_GLOSTRGET("instVar") + "fr" + QString::number(frame));
Toshihiro Shimizu 890ddd
	DIAGNOSTICS_THRSTRSET("ResourceName", QString::fromStdString(resourceName).left(35));
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ResourceBuilder::declareResource(
Toshihiro Shimizu 890ddd
	const string &alias, const TFxP &fx,
Toshihiro Shimizu 890ddd
	const TRectD &rect, double frame, const TRenderSettings &rs,
Toshihiro Shimizu 890ddd
	bool subtileable)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	TFxCacheManager::instance()->declareResource(
Toshihiro Shimizu 890ddd
		alias, fx, rect, frame, rs, subtileable);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
namespace
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
// Retrieves all interesting tiles with respect to the build procedure.
Toshihiro Shimizu 890ddd
// Explicitly, this refers to tiles intersecting the required rect, that are either
Toshihiro Shimizu 890ddd
// not in the resource, or supposed to be not.
Toshihiro Shimizu 890ddd
// Returns true if the required tile is contained in the sum of the predicted ones
Toshihiro Shimizu 890ddd
// (which should definitely happen if the predictive step is coherent with the
Toshihiro Shimizu 890ddd
// computation one).
Toshihiro Shimizu 890ddd
bool getTilesToBuild(
Toshihiro Shimizu 890ddd
	const ResourceData &data, const TRectD &rect, std::vector<resourcedeclaration::tiledata *=""> &rectsToCalculate)</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	assert(data.first);  //The declaration must DEFINITELY be present
Toshihiro Shimizu 890ddd
	assert(data.second); //The resource should be present here
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Now, fill in with all prepared rects which intersect input rect and are not
Toshihiro Shimizu 890ddd
	//already in the resource
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<resourcedeclaration::tiledata> &preparedRects =</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
		data.first->m_tiles;
Toshihiro Shimizu 890ddd
	std::vector<resourcedeclaration::tiledata>::iterator jt;</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	TRectD sum;
Toshihiro Shimizu 890ddd
	for (jt = preparedRects.begin(); jt != preparedRects.end(); ++jt) {
Toshihiro Shimizu 890ddd
		sum += jt->m_rect;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!(isEmpty(rect * jt->m_rect) || jt->m_calculated))
Toshihiro Shimizu 890ddd
			rectsToCalculate.push_back(&(*jt));
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	return sum.contains(rect);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
} // namespace
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ResourceBuilder::simBuild(const TRectD &rect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
	//Retrieve the render status
Toshihiro Shimizu 890ddd
	int renderStatus = m_cacheManager->m_imp->m_renderStatus;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//In the initial precomputing stage, just retrieve all the declarations without efforts.
Toshihiro Shimizu 890ddd
	if (renderStatus == TRenderer::FIRSTRUN) {
Toshihiro Shimizu 890ddd
		simCompute(rect);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Perform the test run
Toshihiro Shimizu 890ddd
	if (renderStatus == TRenderer::TESTRUN) {
Toshihiro Shimizu 890ddd
		if (!(m_data.first && m_data.second))
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WRITESTACK
Toshihiro Shimizu 890ddd
		QString resName(DIAGNOSTICS_THRSTRGET("ResourceName"));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		QString renderStr(DIAGNOSTICS_GLOSTRGET("testRenderStr"));
Toshihiro Shimizu 890ddd
		QString frameStr(DIAGNOSTICS_THRSTRGET("frameStr"));
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_NUMBEREDSTRSET(prefixTest + renderStr + frameStr,
Toshihiro Shimizu 890ddd
								   DIAGNOSTICS_THRSTRGET("stackVar"), DIAGNOSTICS_STACKGET("parentResource") + " " + resName,
Toshihiro Shimizu 890ddd
								   ::traduce(rect), 4);
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_PUSHAUTO("parentResource",
Toshihiro Shimizu 890ddd
							 QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), bla);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Retrieve the tiles to build
Toshihiro Shimizu 890ddd
		std::vector<resourcedeclaration::tiledata> &tiles = m_data.first->m_tiles;</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//For every tile intersecting rect
Toshihiro Shimizu 890ddd
		std::vector<resourcedeclaration::tiledata>::iterator it;</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
		for (it = tiles.begin(); it != tiles.end(); ++it) {
Toshihiro Shimizu 890ddd
			ResourceDeclaration::TileData &tileData = *it;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (!isEmpty(tileData.m_rect * rect)) {
Toshihiro Shimizu 890ddd
				//If the tile ref count == 0, assume that this tile has not yet been simComputed.
Toshihiro Shimizu 890ddd
				//Do so, then; further, add 1 to the number of predicted actively accessed tiles.
Toshihiro Shimizu 890ddd
				if (tileData.m_refCount == 0) {
Toshihiro Shimizu 890ddd
#ifdef WRITESUBRECTS
Toshihiro Shimizu 890ddd
					DIAGNOSTICS_NUMBEREDSTRSET(prefixTest + renderStr + frameStr,
Toshihiro Shimizu 890ddd
											   DIAGNOSTICS_THRSTRGET("stackVar"), DIAGNOSTICS_STACKGET("parentResource") + "   " + resName,
Toshihiro Shimizu 890ddd
											   ::traduce(tileData.m_rect), 4);
Toshihiro Shimizu 890ddd
					DIAGNOSTICS_PUSHAUTO("parentResource",
Toshihiro Shimizu 890ddd
										 QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), bla2);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					simCompute(tileData.m_rect);
Toshihiro Shimizu 890ddd
					++m_data.first->m_tilesCount;
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//Add a reference to this tile
Toshihiro Shimizu 890ddd
				++tileData.m_refCount;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (m_data.second) {
Toshihiro Shimizu 890ddd
					QMutexLocker locker(m_data.second->getMutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					TRect tileRectI(
Toshihiro Shimizu 890ddd
						tileData.m_rect.x0, tileData.m_rect.y0,
Toshihiro Shimizu 890ddd
						tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					m_data.second->addRef2(tileRectI);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//In this case, the simulation is used to declare that this rect will NOT be calculated.
Toshihiro Shimizu 890ddd
	//So, this is the behaviour: 1 refCount is depleted by all cells intersecting the rect
Toshihiro Shimizu 890ddd
	// - if the refCount is still >0, then another request will occur that will make the
Toshihiro Shimizu 890ddd
	//tile calculated. If it is == 0, and the tile has not yet been calculated, then the tile
Toshihiro Shimizu 890ddd
	//will supposedly be NO MORE calculated, so the simCompute has to be launched on that tile, too.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (renderStatus == TRenderer::COMPUTING) {
Toshihiro Shimizu 890ddd
		if (!(m_data.first && m_data.second))
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		QMutexLocker locker(m_data.second->getMutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Retrieve the tiles to build
Toshihiro Shimizu 890ddd
		std::vector<resourcedeclaration::tiledata> &tiles = m_data.first->m_tiles;</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Please note that the request should definitely be fitting the predicted results,
Toshihiro Shimizu 890ddd
		//since the original rect which generated these simCompute calls must have been fitting.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//For every tile to build
Toshihiro Shimizu 890ddd
		std::vector<resourcedeclaration::tiledata>::iterator it;</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
		for (it = tiles.begin(); it != tiles.end(); ++it) {
Toshihiro Shimizu 890ddd
			ResourceDeclaration::TileData &tileData = *it;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (!isEmpty(tileData.m_rect * rect)) {
Toshihiro Shimizu 890ddd
				if (tileData.m_refCount <= 0)
Toshihiro Shimizu 890ddd
					continue;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (--tileData.m_refCount == 0 && !tileData.m_calculated) {
Toshihiro Shimizu 890ddd
					--m_data.first->m_tilesCount;
Toshihiro Shimizu 890ddd
					simCompute(tileData.m_rect);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				if (m_data.second) {
Toshihiro Shimizu 890ddd
					TRect tileRectI(
Toshihiro Shimizu 890ddd
						tileData.m_rect.x0, tileData.m_rect.y0,
Toshihiro Shimizu 890ddd
						tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					m_data.second->release2(tileRectI);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
void ResourceBuilder::build(const TRectD &tileRect)
Toshihiro Shimizu 890ddd
{
Toshihiro Shimizu 890ddd
#ifdef WRITESTACK
Toshihiro Shimizu 890ddd
	QString resName(DIAGNOSTICS_THRSTRGET("ResourceName"));
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	QString renderStr(DIAGNOSTICS_GLOSTRGET("compRenderStr"));
Toshihiro Shimizu 890ddd
	QString frameStr(DIAGNOSTICS_THRSTRGET("frameStr"));
Toshihiro Shimizu 890ddd
	DIAGNOSTICS_NUMBEREDSTRSET(prefixComp + renderStr + frameStr,
Toshihiro Shimizu 890ddd
							   DIAGNOSTICS_THRSTRGET("stackVar"), DIAGNOSTICS_STACKGET("parentResource") + " " + resName,
Toshihiro Shimizu 890ddd
							   ::traduce(tileRect), 4);
Toshihiro Shimizu 890ddd
	DIAGNOSTICS_PUSHAUTO("parentResource",
Toshihiro Shimizu 890ddd
						 QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), bla);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//If there is no resource, just compute the tile directly.
Toshihiro Shimizu 890ddd
	if (!m_data.second) {
Toshihiro Shimizu 890ddd
#ifdef WRITEGENERAL
Toshihiro Shimizu 890ddd
		if (m_data.first)
Toshihiro Shimizu 890ddd
			if (m_data.first->m_tilesCount > 0)
Toshihiro Shimizu 890ddd
				DIAGNOSTICS_ADD(prefixErr + "Computing | No-resource build, active decl, tilesCount > 0", 1);
Toshihiro Shimizu 890ddd
			else
Toshihiro Shimizu 890ddd
				DIAGNOSTICS_ADD(prefixErr + "Computing | No-resource build, active decl, tilesCount <= 0", 1);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//assert(!m_data.first);  //Should have been erased before the COMPUTING run.
Toshihiro Shimizu 890ddd
		compute(tileRect);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Since this function must be thread-safe, use the appropriate synchronization tool.
Toshihiro Shimizu 890ddd
	QMutexLocker locker(m_data.second->getMutex());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Without declaration, you can just deal with the required tile.
Toshihiro Shimizu 890ddd
	if (!(m_data.first && m_data.first->m_tilesCount > 0)) {
Toshihiro Shimizu 890ddd
#ifdef WRITEGENERAL
Toshihiro Shimizu 890ddd
		if (!m_data.first)
Toshihiro Shimizu 890ddd
			DIAGNOSTICS_ADD("#error.txt | Resources without declaration", 1);
Toshihiro Shimizu 890ddd
		else
Toshihiro Shimizu 890ddd
			DIAGNOSTICS_ADD("#error.txt | Resources with declaration, tilesCount <=0", 1);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (download(m_data.second))
Toshihiro Shimizu 890ddd
			return;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		compute(tileRect);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//Since there is an associated resource, the calculated content is supposedly
Toshihiro Shimizu 890ddd
		//an interesting one. Upload it.
Toshihiro Shimizu 890ddd
		upload(m_data.second);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Now, both the declaration and the resource exist.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Retrieve the predicted tile that must be built in place of tile.
Toshihiro Shimizu 890ddd
	TDimension dim(tileRect.getLx(), tileRect.getLy());
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	std::vector<resourcedeclaration::tiledata *=""> tiles;</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
	bool fittingPrediction = getTilesToBuild(m_data, tileRect, tiles);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	if (!fittingPrediction) {
Toshihiro Shimizu 890ddd
#ifdef WRITEGENERAL
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_ADD(prefixErr + "Computing | Not fitting tiles", 1);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//If the required tile is not fitting the prediction, we assume it is a
Toshihiro Shimizu 890ddd
		//full un-predicted one - so no reference count will be updated (this would comply
Toshihiro Shimizu 890ddd
		//with the simCompute() method, in case we assume that mis-predicted
Toshihiro Shimizu 890ddd
		//computes are always prudently built IN EXCESS).
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		//For now, just calculate it and stop.
Toshihiro Shimizu 890ddd
		locker.unlock();
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		compute(tileRect);
Toshihiro Shimizu 890ddd
		return;
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//If necessary, calculate something
Toshihiro Shimizu 890ddd
	if (tiles.size() > 0) {
Toshihiro Shimizu 890ddd
		//For every tile to build
Toshihiro Shimizu 890ddd
		std::vector<resourcedeclaration::tiledata *="">::iterator it;</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
		for (it = tiles.begin(); it != tiles.end(); ++it) {
Toshihiro Shimizu 890ddd
			ResourceDeclaration::TileData &tileData = **it;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//If the tile can be downloaded from the resource, it's because it has actually
Toshihiro Shimizu 890ddd
			//been calculated by another render process - either a concurrent one, or any
Toshihiro Shimizu 890ddd
			//which has written this resource part on disk storage.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			//Since reference counts built in the simCompute assume that tiles downloaded
Toshihiro Shimizu 890ddd
			//from the resource have been calculated in THIS very render process,
Toshihiro Shimizu 890ddd
			//therefore having tileData.m_calculated == true, in this case
Toshihiro Shimizu 890ddd
			//heir refCounts must be updated since no computing will happen on them
Toshihiro Shimizu 890ddd
			//due to the predicted node builds of this resource.
Toshihiro Shimizu 890ddd
			TRect tileRectI(
Toshihiro Shimizu 890ddd
				tileData.m_rect.x0, tileData.m_rect.y0,
Toshihiro Shimizu 890ddd
				tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (m_data.second->canDownloadAll(tileRectI)) {
Toshihiro Shimizu 890ddd
				if (!tileData.m_calculated && tileData.m_refCount > 0) {
Toshihiro Shimizu 890ddd
					/*#ifdef WRITESTACK
Toshihiro Shimizu 890ddd
          QString renderStr(DIAGNOSTICS_GLOSTRGET("compRenderStr"));
Toshihiro Shimizu 890ddd
          QString frameStr(DIAGNOSTICS_THRSTRGET("frameStr"));
Toshihiro Shimizu 890ddd
          DIAGNOSTICS_NUMBEREDSTRSET(prefixComp + renderStr + frameStr,
Toshihiro Shimizu 890ddd
            DIAGNOSTICS_THRSTRGET("stackVar"), "$ > " + resName,
Toshihiro Shimizu 890ddd
            ::traduce(tileData.m_rect), 4);
Toshihiro Shimizu 890ddd
#endif*/
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
					//Deplete children refsCount - rely on the simulated procedure
Toshihiro Shimizu 890ddd
					simCompute(tileData.m_rect);
Toshihiro Shimizu 890ddd
				}
Toshihiro Shimizu 890ddd
			} else {
Toshihiro Shimizu 890ddd
#ifdef WRITESUBRECTS
Toshihiro Shimizu 890ddd
				DIAGNOSTICS_NUMBEREDSTRSET(prefixComp + renderStr + frameStr,
Toshihiro Shimizu 890ddd
										   DIAGNOSTICS_THRSTRGET("stackVar"), DIAGNOSTICS_STACKGET("parentResource") + "   " + resName,
Toshihiro Shimizu 890ddd
										   ::traduce(tileData.m_rect), 4);
Toshihiro Shimizu 890ddd
				DIAGNOSTICS_PUSHAUTO("parentResource",
Toshihiro Shimizu 890ddd
									 QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))), bla2);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//Compute the tile to be calculated
Toshihiro Shimizu 890ddd
				compute(tileData.m_rect);
Toshihiro Shimizu 890ddd
				if (tileData.m_refCount > 0)
Toshihiro Shimizu 890ddd
					tileData.m_calculated = true;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				//Upload the tile into the resource - do so even if the tile
Toshihiro Shimizu 890ddd
				//was unpredicted. In this case, we rely on the resource refCount to
Toshihiro Shimizu 890ddd
				//provide the deallocations... Should be so?
Toshihiro Shimizu 890ddd
				upload(m_data.second);
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Finally, download the built resource in the required tile
Toshihiro Shimizu 890ddd
	bool ret = download(m_data.second);
Toshihiro Shimizu 890ddd
	assert(ret);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef WRITESTACK
Toshihiro Shimizu 890ddd
	if (!ret)
Toshihiro Shimizu 890ddd
		DIAGNOSTICS_STRSET(prefixErr + "Download falliti | " +
Toshihiro Shimizu 890ddd
							   DIAGNOSTICS_GLOSTRGET("compRenderStr") + DIAGNOSTICS_THRSTRGET("frameStr") +
Toshihiro Shimizu 890ddd
							   QString::number(DIAGNOSTICS_GLOGET(DIAGNOSTICS_THRSTRGET("stackVar"))),
Toshihiro Shimizu 890ddd
						   "CROP #" + QString::number(DIAGNOSTICS_GLOGET("crStack")));
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//Deplete a usage for all tiles intersecting the downloaded one. Fully depleted
Toshihiro Shimizu 890ddd
	//tiles become unpredicted from now on.
Toshihiro Shimizu 890ddd
	std::vector<resourcedeclaration::tiledata> &resTiles = m_data.first->m_tiles;</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
	std::vector<resourcedeclaration::tiledata>::iterator it;</resourcedeclaration::tiledata>
Toshihiro Shimizu 890ddd
	for (it = resTiles.begin(); it != resTiles.end(); ++it) {
Toshihiro Shimizu 890ddd
		ResourceDeclaration::TileData &tileData = *it;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
		if (!isEmpty(tileData.m_rect * tileRect)) {
Toshihiro Shimizu 890ddd
			if (tileData.m_refCount <= 0) {
Toshihiro Shimizu 890ddd
#ifdef WRITEGENERAL
Toshihiro Shimizu 890ddd
				DIAGNOSTICS_ADD(prefixErr + "Computing | Over-used subtiles", 1);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
				continue;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			if (--tileData.m_refCount == 0) {
Toshihiro Shimizu 890ddd
				tileData.m_calculated = false;
Toshihiro Shimizu 890ddd
				--m_data.first->m_tilesCount;
Toshihiro Shimizu 890ddd
			}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			TRect tileRectI(
Toshihiro Shimizu 890ddd
				tileData.m_rect.x0, tileData.m_rect.y0,
Toshihiro Shimizu 890ddd
				tileData.m_rect.x1 - 1, tileData.m_rect.y1 - 1);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
			m_data.second->release2(tileRectI);
Toshihiro Shimizu 890ddd
		}
Toshihiro Shimizu 890ddd
	}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
	//If the declaration has been completely used up, destroy it.
Toshihiro Shimizu 890ddd
	//NOTE: Keeping the declarations is useful for diagnostic purposes. The following code
Toshihiro Shimizu 890ddd
	//could be reactivated - but declarations tend to be lightweight now...
Toshihiro Shimizu 890ddd
	//NOTE: If re-enabled, competing mutexes must be set where the resourcesData map is used...
Toshihiro Shimizu 890ddd
	/*if(m_data.first->m_tilesCount <= 0)
Toshihiro Shimizu 890ddd
  {
Toshihiro Shimizu 890ddd
    QMutexLocker locker(&m_cacheManager->m_imp->m_mutex);
Toshihiro Shimizu 890ddd
    m_cacheManager->m_imp->m_resourcesData.erase(m_data.second->getName());
Toshihiro Shimizu 890ddd
  }*/
Toshihiro Shimizu 890ddd
}