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