Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tfxattributes.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "trenderer.h"
Toshihiro Shimizu 890ddd
#include "tcacheresource.h"
Toshihiro Shimizu 890ddd
#include "tcacheresourcepool.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#include "tpassivecachemanager.h"
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//#define USE_SQLITE_HDPOOL
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
/* PRACTICAL EXPLANATION:
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
The TPassiveCacheManager's purpose is that of storing render results from a
Shinya Kitaoka 120a6e
specified set of fx nodes.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
When an fx is passed to the manager to be cached, a structure of type FxData is
Shinya Kitaoka 120a6e
generated for the fx.
Shinya Kitaoka 120a6e
It is stored inside the manager and ASSOCIATED to the fx through an INDEX key -
Shinya Kitaoka 120a6e
this one being stored
Toshihiro Shimizu 890ddd
inside the fx data.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
In particular, the FxData instances contain a PERSISTANT identifier
Shinya Kitaoka 120a6e
(passiveCacheId) that is saved inside
Shinya Kitaoka 120a6e
the scene data, a flag specifying the cache status of the fx node (like, if it's
Shinya Kitaoka 120a6e
enabled or not), and
Toshihiro Shimizu 890ddd
a description of the schematic dag below the associated fx.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Now, when a resource request is made to the TPassiveCacheManager, it checks the
Shinya Kitaoka 120a6e
FxData about the generating
Shinya Kitaoka 120a6e
fx - if it contains the flag specifying that it must be cached, a resource is
Shinya Kitaoka 120a6e
allocated (if not already
Toshihiro Shimizu 890ddd
present), a reference to it is stored, and finally the resource is returned.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
References to interesting resources are stored in a TABLE container, indexed by
Shinya Kitaoka 120a6e
"rendering context" and
Shinya Kitaoka 120a6e
fx. A rendering context is hereby intended as a SEQUENCE of render processes
Shinya Kitaoka 120a6e
where the next render of the
Toshihiro Shimizu 890ddd
sequence is assumed to REPLACE the previous one.
Shinya Kitaoka 120a6e
We therefore have one context for the swatch viewer, one for File>Preview, one
Shinya Kitaoka 120a6e
for the Preview Fx of each
Shinya Kitaoka 120a6e
fx node, and one context for EACH FRAME of the sceneviewer preview (one frame is
Shinya Kitaoka 120a6e
not supposed to replace
Toshihiro Shimizu 890ddd
another in that case).
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
The table is in practice a map of maps (a kind of 'comb' structure) - where the
Shinya Kitaoka 120a6e
primary map is associated
Shinya Kitaoka 120a6e
by render context and the secondary ones by fx. This mean that we are able to
Shinya Kitaoka 120a6e
address and iterate contexts
Toshihiro Shimizu 890ddd
easier than fxs. Values of the table are set of resources.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
RESOURCES MAINTENANCE POLICY:
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
As resources use a concrete amount of memory for storage, they should be kept in
Shinya Kitaoka 120a6e
the resources table only
Shinya Kitaoka 120a6e
for the time they are supposedly useful to the user. There are 2 ways of dealing
Shinya Kitaoka 120a6e
with this issue.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
1) First, we can track scene changes and eliminate those resources that will no
Shinya Kitaoka 120a6e
longer be accessed due to the
Shinya Kitaoka 120a6e
applied change. This happens, for example, when a level is being drawn, fxs are
Shinya Kitaoka 120a6e
inserted, moved or removed.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Level changes are delivered immediately to the ::invalidateLevel(..) method,
Shinya Kitaoka 120a6e
which removes all resources
Shinya Kitaoka 120a6e
whose name contains the level's name. Unfortunately, this cannot be done at
Shinya Kitaoka 120a6e
frame precision (ie you cannot
Toshihiro Shimizu 890ddd
invalidate a single frame of the level, but ALL the level).
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Xsheet (schematic) changes are tracked through the schematic node description
Shinya Kitaoka 120a6e
stored inside the FxData structure.
Shinya Kitaoka 120a6e
Once one such change happens, all resources update their description - if that
Shinya Kitaoka 120a6e
changes, the associated resources
Toshihiro Shimizu 890ddd
are released.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
The same schematic description is used to track and release resources affected
Shinya Kitaoka 120a6e
by changes on a downstream fx's
Toshihiro Shimizu 890ddd
parameters.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
There are also scene changes that are inherently hard to track or intercept. For
Shinya Kitaoka 120a6e
example, pegbar affines changes,
Shinya Kitaoka 120a6e
fx nodes expressions referencing data not directly connected to the fx, and
Shinya Kitaoka 120a6e
possibly others. These are currently
Toshihiro Shimizu 890ddd
NOT handled by direct tracking.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
2) As there may be resources which escape the resource control by point (1), we
Shinya Kitaoka 120a6e
need some extra control
Toshihiro Shimizu 890ddd
policies. Here they are:
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
We assume that the pool of resources accessed by render processes of a same
Shinya Kitaoka 120a6e
render context should be CONSTANT
Shinya Kitaoka 120a6e
IF NO SCENE CHANGE HAPPENS. In other words, we are guessing that only those
Shinya Kitaoka 120a6e
resources used in the last
Shinya Kitaoka 120a6e
rendering will be used in the next. Resources accessed in a render but NOT in
Shinya Kitaoka 120a6e
the next (of the same context)
Toshihiro Shimizu 890ddd
are released.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
However, it could be that the sequence of render processes from a context is
Shinya Kitaoka 120a6e
halted from a certain moment on.
Shinya Kitaoka 120a6e
In that case, it is a waste to keep the resources accessed by its last render if
Shinya Kitaoka 120a6e
no new render will ever take
Shinya Kitaoka 120a6e
place. We then assume further that a rendering context can be ENABLED or
Shinya Kitaoka 120a6e
DISABLED - when a render context is
Shinya Kitaoka 120a6e
enabled, it will most likely have a next render - and therefore can keep its
Shinya Kitaoka 120a6e
resources in memory.
Toshihiro Shimizu 890ddd
Once a context is DISABLED, it moves the resources to a TEMPORARY context.
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
Resources in the temporary context are those 'on their way for release'. They
Shinya Kitaoka 120a6e
will be KEPT only if the
Shinya Kitaoka 120a6e
next rendering - INDEPENDENTLY FROM THE RENDER CONTEXT - requires them (in this
Shinya Kitaoka 120a6e
case, they will be adopted
Shinya Kitaoka 120a6e
by the new context). This is necessary since context disables typically happen
Shinya Kitaoka 120a6e
when a preview window closes.
Shinya Kitaoka 120a6e
It is not unfrequent that users close the preview window, modify the scene, and
Shinya Kitaoka 120a6e
then restore the preview.
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
CONSIDERATIONS:
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
* The File>Render generates NO CONTEXT - and therefore does NOT PASSIVELY CACHE
Shinya Kitaoka 120a6e
RESOURCES, since it cannot be
Shinya Kitaoka 120a6e
  stated whether it is in the 'enabled' or 'disabled' state. It could be
Shinya Kitaoka 120a6e
considered coherent with what tcomposer
Toshihiro Shimizu 890ddd
  does, by the way...
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
* Our resources maintenance policy ensures that the memory usage should be
Shinya Kitaoka 120a6e
stable over time - that is, no
Toshihiro Shimizu 890ddd
  useless resource is kept in memory.
Shinya Kitaoka 120a6e
  Of course, it is possibly more restrictive than what the user may desire. For
Shinya Kitaoka 120a6e
example, closing 2 preview
Shinya Kitaoka 120a6e
  windows marks their resources for deletion, but only one of the two restored
Shinya Kitaoka 120a6e
previews will keep its
Toshihiro Shimizu 890ddd
  resources intact...
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
//  Local stuff - inlines
Shinya Kitaoka 120a6e
namespace {
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
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//---------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TFx *TPassiveCacheManager::getNotAllowingAncestor(TFx *fx) {
Shinya Kitaoka 120a6e
  // Trace all output ports
Shinya Kitaoka 120a6e
  int outputPortsCount = fx->getOutputConnectionCount();
Shinya Kitaoka 120a6e
  /*if(!outputPortsCount)   //We have no access to TApp here!!
Toshihiro Shimizu 890ddd
{
Shinya Kitaoka 120a6e
//It could be a terminal fx. In that case, pass to the xsheet fx
Shinya Kitaoka 120a6e
FxDag* dag = TApp::instance()->getCurrentXsheet()->getXsheet()->getFxDag();
Shinya Kitaoka 120a6e
if(dag->getTerminalFxs()->containsFx(fx))
Shinya Kitaoka 120a6e
return getNotAllowingAncestor(dag->getXsheetFx());
Shinya Kitaoka 120a6e
}*/
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Now, for common ports
Shinya Kitaoka 120a6e
  for (int i = 0; i < outputPortsCount; ++i) {
Shinya Kitaoka 120a6e
    // Find the output Fx and the port connected to our fx
Shinya Kitaoka 120a6e
    TFxPort *port    = fx->getOutputConnection(i);
Shinya Kitaoka 120a6e
    TRasterFx *outFx = static_cast<trasterfx *="">(port->getOwnerFx());</trasterfx>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int portIdx, portsCount = outFx->getInputPortCount();
Shinya Kitaoka 120a6e
    for (portIdx = 0; portIdx < portsCount; ++portIdx)
Shinya Kitaoka 120a6e
      if (outFx->getInputPort(portIdx) == port) break;
Shinya Kitaoka 120a6e
    assert(portIdx < portsCount);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (!outFx->allowUserCacheOnPort(portIdx)) return outFx;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    TFx *naAncestor = getNotAllowingAncestor(outFx);
Shinya Kitaoka 120a6e
    if (naAncestor) return naAncestor;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  return 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*****************************************************************************************
Toshihiro Shimizu 890ddd
//    Resources Container Definition
Toshihiro Shimizu 890ddd
//*****************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
template <typename colkey,="" rowkey,="" typename="" val=""></typename>
Shinya Kitaoka 120a6e
class Table {
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  typedef typename std::map<colkey, val=""> Row;</colkey,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
private:
Shinya Kitaoka 120a6e
  std::map<rowkey, row=""> m_table;</rowkey,>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  friend class Iterator;
Shinya Kitaoka 120a6e
  friend class ColIterator;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  typedef typename std::map<rowkey, row="">::iterator RowsIterator;</rowkey,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  class Iterator {
Shinya Kitaoka 120a6e
  protected:
Shinya Kitaoka 120a6e
    Table *m_table;
Shinya Kitaoka 120a6e
    RowsIterator m_rowIt;
Shinya Kitaoka 120a6e
    typename Row::iterator m_it;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    friend class Table;
Shinya Kitaoka 120a6e
    Iterator(Table *table) : m_table(table) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    virtual void makeConsistent() {
Shinya Kitaoka 120a6e
      if (m_it == m_rowIt->second.end()) {
Shinya Kitaoka 120a6e
        if (++m_rowIt == m_table->m_table.end()) return;
Shinya Kitaoka 120a6e
        m_it = m_rowIt->second.begin();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  public:
Shinya Kitaoka 120a6e
    const RowKey &row() { return m_rowIt->first; }
Shinya Kitaoka 120a6e
    const ColKey &col() { return m_it->first; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    virtual void operator++() {
Shinya Kitaoka 120a6e
      ++m_it;
Shinya Kitaoka 120a6e
      makeConsistent();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    virtual operator bool() { return m_rowIt != m_table->m_table.end(); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    Val &operator*() { return m_it->second; }
Shinya Kitaoka 120a6e
    Val *operator->() { return &m_it->second; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    bool operator==(const Iterator &it) { return m_it == it.m_it; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    bool operator!=(const Iterator &it) { return !operator==(it); }
Shinya Kitaoka 120a6e
  };
Shinya Kitaoka 120a6e
Shinya Kitaoka d1f6c4
  class ColIterator final : public Iterator {
Shinya Kitaoka 120a6e
    ColKey m_colKey;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    friend class Table;
Shinya Kitaoka 120a6e
    ColIterator(Table *table, const ColKey &c) : Iterator(table), m_colKey(c) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
    void makeConsistent() override {
Shinya Kitaoka 120a6e
      Iterator::m_rowIt = Iterator::m_rowIt;
Shinya Kitaoka 120a6e
      while (Iterator::m_rowIt != Iterator::m_table->m_table.end()) {
Shinya Kitaoka 120a6e
        Iterator::m_it = Iterator::m_rowIt->second.find(m_colKey);
Shinya Kitaoka 120a6e
        if (Iterator::m_it != Iterator::m_rowIt->second.end()) break;
Shinya Kitaoka 120a6e
        ++Iterator::m_rowIt;
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  public:
Shinya Kitaoka 473e70
    void operator++() override {
Shinya Kitaoka 120a6e
      ++Iterator::m_rowIt;
Shinya Kitaoka 120a6e
      makeConsistent();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };
Shinya Kitaoka 120a6e
Shinya Kitaoka d1f6c4
  class RowIterator final : public Iterator {
Shinya Kitaoka 120a6e
    friend class Table;
Shinya Kitaoka 120a6e
    RowIterator(Table *table) : Iterator(table) {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
    void makeConsistent() override {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  public:
Shinya Kitaoka 120a6e
    RowIterator(const RowsIterator rowIt) : Iterator(0) {
Shinya Kitaoka 120a6e
      Iterator::m_rowIt = rowIt;
Shinya Kitaoka 120a6e
      Iterator::m_it    = rowIt->second.begin();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 473e70
    void operator++() override { ++Iterator::m_it; }
Shinya Kitaoka 473e70
    operator bool() override {
Shinya Kitaoka 120a6e
      return Iterator::m_it != Iterator::m_rowIt->second.end();
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  };
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  Table() {}
Shinya Kitaoka 120a6e
  ~Table() {}
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::map<rowkey, row=""> &rows() { return m_table; }</rowkey,>
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Iterator begin() {
Shinya Kitaoka 120a6e
    Iterator result(this);
Shinya Kitaoka 120a6e
    result.m_rowIt = m_table.begin();
Shinya Kitaoka 120a6e
    if (result.m_rowIt != m_table.end())
Shinya Kitaoka 120a6e
      result.m_it = result.m_rowIt->second.begin();
Shinya Kitaoka 120a6e
    return result;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  RowIterator rowBegin(const RowKey &row) {
Shinya Kitaoka 120a6e
    RowIterator result(this);
Shinya Kitaoka 120a6e
    result.m_rowIt = m_table.find(row);
Shinya Kitaoka 120a6e
    if (result.m_rowIt != m_table.end())
Shinya Kitaoka 120a6e
      result.m_it = result.m_rowIt->second.begin();
Shinya Kitaoka 120a6e
    return result;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ColIterator colBegin(const ColKey &col) {
Shinya Kitaoka 120a6e
    ColIterator result(this, col);
Shinya Kitaoka 120a6e
    result.m_rowIt = m_table.begin();
Shinya Kitaoka 120a6e
    result.makeConsistent();
Shinya Kitaoka 120a6e
    return result;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Val &value(const RowKey &r, const ColKey &c) { return m_table[r][c]; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Iterator insert(const RowKey &r, const ColKey &c, const Val &val) {
Shinya Kitaoka 120a6e
    Iterator result(this);
Shinya Kitaoka 120a6e
    result.m_rowIt = m_table.insert(std::make_pair(r, Row())).first;
Shinya Kitaoka 120a6e
    result.m_it = result.m_rowIt->second.insert(std::make_pair(c, val)).first;
Shinya Kitaoka 120a6e
    return result;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Iterator find(const RowKey &r, const ColKey &c) {
Shinya Kitaoka 120a6e
    Iterator result(this);
Shinya Kitaoka 120a6e
    result.m_rowIt = m_table.find(r);
Shinya Kitaoka 120a6e
    if (result.m_rowIt == m_table.end()) return;
Shinya Kitaoka 120a6e
    result.m_it = result.m_rowIt->second.find(c);
Shinya Kitaoka 120a6e
    if (result.m_it == result.m_rowIt->second.end())
Shinya Kitaoka 120a6e
      result.m_rowIt = m_table.end();
Shinya Kitaoka 120a6e
    return result;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Iterator erase(const RowKey &r, const ColKey &c) {
Shinya Kitaoka 120a6e
    Iterator it(find(r, c));
Shinya Kitaoka 120a6e
    return erase(it);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  Iterator erase(const Iterator &it) {
Shinya Kitaoka 120a6e
    Iterator result(it);
Shinya Kitaoka 120a6e
    Row &row = it.m_rowIt->second;
Shinya Kitaoka 120a6e
    ++result.m_it;
Shinya Kitaoka 120a6e
    row.erase(it.m_it);
Shinya Kitaoka 120a6e
    if (result.m_it == row.end() && row.empty()) {
Shinya Kitaoka 120a6e
      result.makeConsistent();
Shinya Kitaoka 120a6e
      m_table.erase(it.m_rowIt);
Shinya Kitaoka 120a6e
      return result;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    result.makeConsistent();
Shinya Kitaoka 120a6e
    return result;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void erase(const ColKey &c) {
Shinya Kitaoka 120a6e
    ColIterator it(colBegin(c));
Shinya Kitaoka 120a6e
    while (it) {
Shinya Kitaoka 120a6e
      RowsIterator rowIt = it.m_rowIt;
Shinya Kitaoka 120a6e
      rowIt->second.erase(it.m_it);
Shinya Kitaoka 120a6e
      ++it;
Shinya Kitaoka 120a6e
      if (rowIt->second.empty()) m_table.erase(rowIt);
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void erase(const RowKey &r) { m_table.erase(r); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  void clear() { m_table.clear(); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
struct LockedResourceP {
Shinya Kitaoka 120a6e
  TCacheResourceP m_resource;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  LockedResourceP(const TCacheResourceP &resource) : m_resource(resource) {
Shinya Kitaoka 120a6e
    m_resource->addLock();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  LockedResourceP(const LockedResourceP &resource)
Shinya Kitaoka 120a6e
      : m_resource(resource.m_resource) {
Shinya Kitaoka 120a6e
    m_resource->addLock();
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ~LockedResourceP() { m_resource->releaseLock(); }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  LockedResourceP &operator=(const LockedResourceP &src) {
Shinya Kitaoka 120a6e
    src.m_resource->addLock();
Shinya Kitaoka 120a6e
    if (m_resource) m_resource->releaseLock();
Shinya Kitaoka 120a6e
    m_resource = src.m_resource;
Shinya Kitaoka 120a6e
    return *this;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  operator bool() const { return m_resource; }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  bool operator<(const LockedResourceP &resource) const {
Shinya Kitaoka 120a6e
    return m_resource < resource.m_resource;
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  TCacheResource *operator->() const { return m_resource.getPointer(); }
Shinya Kitaoka 120a6e
  TCacheResource &operator*() const { return *m_resource.getPointer(); }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
typedef Table<std::string, int,="" std::set<lockedresourcep="">> ResourcesTable;</std::string,>
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//--------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
class TPassiveCacheManager::ResourcesContainer {
Shinya Kitaoka 120a6e
  ResourcesTable m_resources;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
public:
Shinya Kitaoka 120a6e
  ResourcesContainer() {}
Shinya Kitaoka 120a6e
  ~ResourcesContainer() {}
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  ResourcesTable &getTable() { return m_resources; }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*****************************************************************************************
Toshihiro Shimizu 890ddd
//    FxData implementation
Toshihiro Shimizu 890ddd
//*****************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPassiveCacheManager::FxData::FxData()
Shinya Kitaoka 120a6e
    : m_storageFlag(0), m_passiveCacheId(0) {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPassiveCacheManager::FxData::~FxData() {}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*****************************************************************************************
Toshihiro Shimizu 890ddd
//    Manager generator
Toshihiro Shimizu 890ddd
//*****************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//=======================================
Toshihiro Shimizu 890ddd
//    TPassiveCacheManagerGenerator
Toshihiro Shimizu 890ddd
//---------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka d1f6c4
class TPassiveCacheManagerGenerator final
Shinya Kitaoka d1f6c4
    : public TRenderResourceManagerGenerator {
Shinya Kitaoka 473e70
  TRenderResourceManager *operator()(void) override {
Shinya Kitaoka 120a6e
    // return new TPassiveCacheManager;
Shinya Kitaoka 120a6e
    return TPassiveCacheManager::instance();
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
};
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
MANAGER_FILESCOPE_DECLARATION_DEP(TPassiveCacheManager,
Shinya Kitaoka 120a6e
                                  TPassiveCacheManagerGenerator,
Shinya Kitaoka 120a6e
                                  TFxCacheManager::deps())
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//*****************************************************************************************
Toshihiro Shimizu 890ddd
//    Implementation
Toshihiro Shimizu 890ddd
//*****************************************************************************************
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
TPassiveCacheManager::TPassiveCacheManager()
Toshihiro Shimizu 890ddd
#ifdef USE_SQLITE_HDPOOL
Shinya Kitaoka 120a6e
    : m_currStorageFlag(ON_DISK)
Toshihiro Shimizu 890ddd
#else
Shinya Kitaoka 120a6e
    : m_currStorageFlag(IN_MEMORY)
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
    , m_enabled(true)
Shinya Kitaoka 120a6e
    , m_descriptorCallback(0)
Shinya Kitaoka 120a6e
    , m_mutex(QMutex::Recursive)
Shinya Kitaoka 120a6e
    , m_resources(new ResourcesContainer) {
Shinya Kitaoka 120a6e
  reset();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPassiveCacheManager::~TPassiveCacheManager() { delete m_resources; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPassiveCacheManager *TPassiveCacheManager::instance() {
Shinya Kitaoka 120a6e
  static TPassiveCacheManager theInstance;
Shinya Kitaoka 120a6e
  return &theInstance;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::setContextName(unsigned long renderId,
Shinya Kitaoka 120a6e
                                          const std::string &name) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Retrieve the context data if already present
Shinya Kitaoka 120a6e
  std::map<std::string, uchar="">::iterator it = m_contextNames.find(name);</std::string,>
Shinya Kitaoka 120a6e
  if (it == m_contextNames.end())
Shinya Kitaoka 120a6e
    it = m_contextNames.insert(std::make_pair(name, 0)).first;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  it->second = !it->second;
Shinya Kitaoka 120a6e
  m_contextNamesByRenderId.insert(
Shinya Kitaoka 120a6e
      std::make_pair(renderId, name + "%" + std::to_string(it->second)));
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
std::string TPassiveCacheManager::getContextName() {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // First, search the context name
Shinya Kitaoka 120a6e
  std::map<unsigned long,="" std::string="">::iterator it =</unsigned>
Shinya Kitaoka 120a6e
      m_contextNamesByRenderId.find(TRenderer::renderId());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (it == m_contextNamesByRenderId.end()) return "";
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return it->second;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::setEnabled(bool enabled) { m_enabled = enabled; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TPassiveCacheManager::isEnabled() const { return m_enabled; }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::setStorageMode(StorageFlag mode) {
Shinya Kitaoka 120a6e
  m_currStorageFlag = mode;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPassiveCacheManager::StorageFlag TPassiveCacheManager::getStorageMode() const {
Shinya Kitaoka 120a6e
  return m_currStorageFlag;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::setTreeDescriptor(TreeDescriptor callback) {
Shinya Kitaoka 120a6e
  m_descriptorCallback = callback;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TPassiveCacheManager::getNewPassiveCacheId() {
Shinya Kitaoka 120a6e
  return ++m_currentPassiveCacheId;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TPassiveCacheManager::updatePassiveCacheId(int id) {
Shinya Kitaoka 120a6e
  if (m_updatingPassiveCacheIds)
Shinya Kitaoka 120a6e
    m_currentPassiveCacheId = std::max(m_currentPassiveCacheId, id);
Shinya Kitaoka 120a6e
  else
Shinya Kitaoka 120a6e
    id = getNewPassiveCacheId();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return id;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::onSceneLoaded() {
Shinya Kitaoka 120a6e
  m_updatingPassiveCacheIds = false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Initialize the fxs tree description. This was not possible before, as the
Shinya Kitaoka 120a6e
// scene was yet incomplete (in loading state).
Toshihiro Shimizu 890ddd
#ifndef USE_SQLITE_HDPOOL
Shinya Kitaoka 120a6e
  unsigned int count = m_fxDataVector.size();
Shinya Kitaoka 120a6e
  for (unsigned int i = 0; i < count; ++i) {
Shinya Kitaoka 120a6e
    FxData &data = m_fxDataVector[i];
Shinya Kitaoka 120a6e
    (*m_descriptorCallback)(data.m_treeDescription, data.m_fx);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::touchFxData(int &idx) {
Shinya Kitaoka 120a6e
  if (idx >= 0) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_fxDataVector.push_back(FxData());
Shinya Kitaoka 120a6e
  idx = m_fxDataVector.size() - 1;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-----------------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TPassiveCacheManager::declareCached(TFx *fx, int passiveCacheId) {
Shinya Kitaoka 120a6e
  int &idx = fx->getAttributes()->passiveCacheDataIdx();
Shinya Kitaoka 120a6e
  touchFxData(idx);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  FxData &data          = m_fxDataVector[idx];
Shinya Kitaoka 120a6e
  data.m_fx             = fx;
Shinya Kitaoka 120a6e
  data.m_storageFlag    = m_currStorageFlag;
Shinya Kitaoka 120a6e
  data.m_passiveCacheId = updatePassiveCacheId(passiveCacheId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return idx;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::reset() {
Shinya Kitaoka 120a6e
  m_updatingPassiveCacheIds = true;
Shinya Kitaoka 120a6e
  m_currentPassiveCacheId   = 0;
Shinya Kitaoka 120a6e
  m_fxDataVector.clear();
Shinya Kitaoka 120a6e
  m_resources->getTable().clear();
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
bool TPassiveCacheManager::cacheEnabled(TFx *fx) {
Shinya Kitaoka 120a6e
  int idx = fx->getAttributes()->passiveCacheDataIdx();
Shinya Kitaoka 120a6e
  if (idx < 0) return false;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(idx < (int)m_fxDataVector.size());
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return m_fxDataVector[idx].m_storageFlag > 0;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
int TPassiveCacheManager::getPassiveCacheId(TFx *fx) {
Shinya Kitaoka 120a6e
  int idx = fx->getAttributes()->passiveCacheDataIdx();
Shinya Kitaoka 120a6e
  if (idx < 0) return 0;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // This needs not be mutex locked
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  assert(idx < (int)m_fxDataVector.size());
Shinya Kitaoka 120a6e
  return m_fxDataVector[idx].m_passiveCacheId;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
TPassiveCacheManager::StorageFlag TPassiveCacheManager::getStorageMode(
Shinya Kitaoka 120a6e
    TFx *fx) {
Shinya Kitaoka 120a6e
  int idx = fx->getAttributes()->passiveCacheDataIdx();
Shinya Kitaoka 120a6e
  if (idx < 0) return NONE;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  return (StorageFlag)m_fxDataVector[idx].m_storageFlag;
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::enableCache(TFx *fx) {
Shinya Kitaoka 120a6e
  int &idx = fx->getAttributes()->passiveCacheDataIdx();
Shinya Kitaoka 120a6e
  touchFxData(idx);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  FxData &data = m_fxDataVector[idx];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Shinya Kitaoka 120a6e
  DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + " " +
Shinya Kitaoka 120a6e
                  QString("Enable Cache"));
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  StorageFlag flag = getStorageMode();
Shinya Kitaoka 120a6e
  if (flag) {
Shinya Kitaoka 120a6e
    UCHAR &storedFlag = data.m_storageFlag;
Shinya Kitaoka 120a6e
    UCHAR oldFlag     = storedFlag;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    storedFlag |= flag;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (data.m_passiveCacheId == 0)
Shinya Kitaoka 120a6e
      data.m_passiveCacheId = getNewPassiveCacheId();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if ((storedFlag & ON_DISK) && !(oldFlag & ON_DISK)) {
Shinya Kitaoka 120a6e
      ResourcesTable::ColIterator it =
Shinya Kitaoka 120a6e
          m_resources->getTable().colBegin(data.m_passiveCacheId);
Shinya Kitaoka 120a6e
      for (; it; ++it) {
Shinya Kitaoka 120a6e
        std::set<lockedresourcep> &resources = *it;</lockedresourcep>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        std::set<lockedresourcep>::iterator jt;</lockedresourcep>
Shinya Kitaoka 120a6e
        for (jt = resources.begin(); jt != resources.end(); ++jt)
Shinya Kitaoka 120a6e
          (*jt)->enableBackup();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef USE_SQLITE_HDPOOL
Shinya Kitaoka 120a6e
    if ((storedFlag & IN_MEMORY) && !(oldFlag & IN_MEMORY)) {
Shinya Kitaoka 120a6e
      data.m_fx = fx;
Shinya Kitaoka 120a6e
      (*m_descriptorCallback)(data.m_treeDescription, data.m_fx);
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::disableCache(TFx *fx) {
Shinya Kitaoka 120a6e
  int idx = fx->getAttributes()->passiveCacheDataIdx();
Shinya Kitaoka 120a6e
  if (idx < 0) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  FxData &data = m_fxDataVector[idx];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Shinya Kitaoka 120a6e
  DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + " " +
Shinya Kitaoka 120a6e
                  QString("Disable Cache"));
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  StorageFlag flag = getStorageMode();
Shinya Kitaoka 120a6e
  if (flag) {
Shinya Kitaoka 120a6e
    UCHAR &storedFlag = data.m_storageFlag;
Shinya Kitaoka 120a6e
    UCHAR oldFlag     = storedFlag;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    storedFlag &= ~flag;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if ((oldFlag & IN_MEMORY) && !(storedFlag & IN_MEMORY)) {
Shinya Kitaoka 120a6e
      m_resources->getTable().erase(data.m_passiveCacheId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      data.m_fx              = TFxP();
Shinya Kitaoka 120a6e
      data.m_treeDescription = "";
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef USE_SQLITE_HDPOOL
Shinya Kitaoka 120a6e
    if ((oldFlag & ON_DISK) && !(storedFlag & ON_DISK))
Shinya Kitaoka 120a6e
      TCacheResourcePool::instance()->releaseReferences(
Shinya Kitaoka 120a6e
          "P" + QString::number(data.m_passiveCacheId));
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::toggleCache(TFx *fx) {
Shinya Kitaoka 120a6e
  int &idx = fx->getAttributes()->passiveCacheDataIdx();
Shinya Kitaoka 120a6e
  touchFxData(idx);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  FxData &data = m_fxDataVector[idx];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  StorageFlag flag = getStorageMode();
Shinya Kitaoka 120a6e
  if (flag) {
Shinya Kitaoka 120a6e
    UCHAR &storedFlag = data.m_storageFlag;
Shinya Kitaoka 120a6e
    UCHAR oldFlag     = storedFlag;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    storedFlag ^= flag;
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Shinya Kitaoka 120a6e
    DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() + " " +
Shinya Kitaoka 120a6e
                    QString("Toggle Cache (now ") +
Shinya Kitaoka 120a6e
                    ((storedFlag & IN_MEMORY) ? "enabled)" : "disabled)"));
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (data.m_passiveCacheId == 0)
Shinya Kitaoka 120a6e
      data.m_passiveCacheId = getNewPassiveCacheId();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if ((storedFlag & ON_DISK) && !(oldFlag & ON_DISK)) {
Shinya Kitaoka 120a6e
      ResourcesTable::ColIterator it =
Shinya Kitaoka 120a6e
          m_resources->getTable().colBegin(data.m_passiveCacheId);
Shinya Kitaoka 120a6e
      for (; it; ++it) {
Shinya Kitaoka 120a6e
        std::set<lockedresourcep> &resources = *it;</lockedresourcep>
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
        std::set<lockedresourcep>::iterator jt;</lockedresourcep>
Shinya Kitaoka 120a6e
        for (jt = resources.begin(); jt != resources.end(); ++jt)
Shinya Kitaoka 120a6e
          (*jt)->enableBackup();
Shinya Kitaoka 120a6e
      }
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    // Implementa la versione contraria - eliminazione dell'fx nell'hdPool...
Shinya Kitaoka 120a6e
    // Metti anche questo in versione ritardata con flush... Il flush e' da
Shinya Kitaoka 120a6e
    // unificare...
Shinya Kitaoka 120a6e
    // e magari da spostare direttamente nell'hdPool
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if ((oldFlag & IN_MEMORY) && !(storedFlag & IN_MEMORY)) {
Shinya Kitaoka 120a6e
      m_resources->getTable().erase(data.m_passiveCacheId);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
      data.m_fx              = TFxP();
Shinya Kitaoka 120a6e
      data.m_treeDescription = "";
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifndef USE_SQLITE_HDPOOL
Shinya Kitaoka 120a6e
    if ((storedFlag & IN_MEMORY) && !(oldFlag & IN_MEMORY)) {
Shinya Kitaoka 120a6e
      data.m_fx = fx;
Shinya Kitaoka 120a6e
      (*m_descriptorCallback)(data.m_treeDescription, data.m_fx);
Shinya Kitaoka 120a6e
    }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef USE_SQLITE_HDPOOL
Shinya Kitaoka 120a6e
    if ((oldFlag & ON_DISK) && !(storedFlag & ON_DISK))
Shinya Kitaoka 120a6e
      TCacheResourcePool::instance()->releaseReferences(
Shinya Kitaoka 120a6e
          "P" + QString::number(data.m_passiveCacheId));
Toshihiro Shimizu 890ddd
#endif
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::invalidateLevel(const std::string &levelName) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Traverse the managed resources for passed levelName.
Shinya Kitaoka 120a6e
  ResourcesTable &table       = m_resources->getTable();
Shinya Kitaoka 120a6e
  ResourcesTable::Iterator it = table.begin();
Shinya Kitaoka 120a6e
  while (it) {
Shinya Kitaoka 120a6e
    std::set<lockedresourcep> &resources = *it;</lockedresourcep>
Shinya Kitaoka 120a6e
    std::set<lockedresourcep>::iterator jt, kt;</lockedresourcep>
Shinya Kitaoka 120a6e
    for (jt = resources.begin(); jt != resources.end();) {
Shinya Kitaoka 120a6e
      if ((*jt)->getName().find(levelName) != std::string::npos) {
Shinya Kitaoka 120a6e
        kt = jt++;
Shinya Kitaoka 120a6e
        it->erase(kt);
Shinya Kitaoka 120a6e
      } else
Shinya Kitaoka 120a6e
        ++jt;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    if (resources.empty())
Shinya Kitaoka 120a6e
      it = table.erase(it);
Shinya Kitaoka 120a6e
    else
Shinya Kitaoka 120a6e
      ++it;
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef USE_SQLITE_HDPOOL
Shinya Kitaoka 120a6e
  // Store the level name until the invalidation is forced
Shinya Kitaoka 120a6e
  m_invalidatedLevels.insert(levelName);
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::forceInvalidate() {
Toshihiro Shimizu 890ddd
#ifdef USE_SQLITE_HDPOOL
Shinya Kitaoka 120a6e
  TCacheResourcePool *pool = TCacheResourcePool::instance();
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Clear all invalidated levels from the resource pool
Shinya Kitaoka 120a6e
  std::set<std::string>::iterator it;</std::string>
Shinya Kitaoka 120a6e
  for (it = m_invalidatedLevels.begin(); it != m_invalidatedLevels.end(); ++it)
Shinya Kitaoka 120a6e
    pool->clearKeyword(*it);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  m_invalidatedLevels.clear();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Generate the fx's tree description. If it is contained in one of those
Shinya Kitaoka 120a6e
// stored with cached fxs, release their associated resources.
Shinya Kitaoka 120a6e
void TPassiveCacheManager::onFxChanged(const TFxP &fx) {
Toshihiro Shimizu 890ddd
#ifndef USE_SQLITE_HDPOOL
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::string fxTreeDescription;
Shinya Kitaoka 120a6e
  (*m_descriptorCallback)(fxTreeDescription, fx);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  unsigned int count = m_fxDataVector.size();
Shinya Kitaoka 120a6e
  for (unsigned int i = 0; i < count; ++i) {
Shinya Kitaoka 120a6e
    FxData &data = m_fxDataVector[i];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!data.m_fx) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (data.m_treeDescription.find(fxTreeDescription) != std::string::npos)
Shinya Kitaoka 120a6e
      m_resources->getTable().erase(data.m_passiveCacheId);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
// Regenerate the tree descriptions of cached fxs. If the new description does
Shinya Kitaoka 120a6e
// not match the previous one, release the associated resources.
Shinya Kitaoka 120a6e
void TPassiveCacheManager::onXsheetChanged() {
Toshihiro Shimizu 890ddd
#ifndef USE_SQLITE_HDPOOL
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Shinya Kitaoka 120a6e
  DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() +
Shinya Kitaoka 120a6e
                  " XSheet changed");
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  unsigned int count = m_fxDataVector.size();
Shinya Kitaoka 120a6e
  for (unsigned int i = 0; i < count; ++i) {
Shinya Kitaoka 120a6e
    FxData &data = m_fxDataVector[i];
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (!data.m_fx) continue;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    std::string newTreeDescription;
Shinya Kitaoka 120a6e
    (*m_descriptorCallback)(newTreeDescription, data.m_fx);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    if (data.m_treeDescription != newTreeDescription) {
Shinya Kitaoka 120a6e
      m_resources->getTable().erase(data.m_passiveCacheId);
Shinya Kitaoka 120a6e
      data.m_treeDescription = newTreeDescription;
Shinya Kitaoka 120a6e
    }
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::getResource(TCacheResourceP &resource,
Shinya Kitaoka 120a6e
                                       const std::string &alias, const TFxP &fx,
Shinya Kitaoka 120a6e
                                       double frame, const TRenderSettings &rs,
Shinya Kitaoka 120a6e
                                       ResourceDeclaration *resData) {
Shinya Kitaoka 120a6e
  if (!(m_enabled && fx && rs.m_userCachable)) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  StorageFlag flag = getStorageMode(fx.getPointer());
Shinya Kitaoka 120a6e
  if (flag == NONE) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  std::string contextName(getContextName());
Shinya Kitaoka 120a6e
  if (contextName.empty()) return;
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Build a resource if none was passed.
Shinya Kitaoka 120a6e
  if (!resource) resource = TCacheResourceP(alias, true);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef USE_SQLITE_HDPOOL
Shinya Kitaoka 120a6e
  if (flag & ON_DISK) {
Shinya Kitaoka 120a6e
    resource->enableBackup();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
    int passiveCacheId =
Shinya Kitaoka 120a6e
        m_fxDataVector[fx->getAttributes()->passiveCacheDataIdx()]
Shinya Kitaoka 120a6e
            .m_passiveCacheId;
Shinya Kitaoka 120a6e
    TCacheResourcePool::instance()->addReference(
Shinya Kitaoka 120a6e
        resource, "P" + QString::number(passiveCacheId));
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  if (flag & IN_MEMORY) {
Shinya Kitaoka 120a6e
    QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
    int passiveCacheId =
Shinya Kitaoka 120a6e
        m_fxDataVector[fx->getAttributes()->passiveCacheDataIdx()]
Shinya Kitaoka 120a6e
            .m_passiveCacheId;
Shinya Kitaoka 120a6e
    m_resources->getTable().value(contextName, passiveCacheId).insert(resource);
Shinya Kitaoka 120a6e
  }
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::releaseContextNamesWithPrefix(
Shinya Kitaoka 120a6e
    const std::string &prefix) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef DIAGNOSTICS
Shinya Kitaoka 120a6e
  DIAGNOSTICS_STR("#activity.txt | " + QTime::currentTime().toString() +
Shinya Kitaoka 120a6e
                  " Release Context Name (" + QString::fromStdString(prefix) +
Shinya Kitaoka 120a6e
                  ")");
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  // Retrieve the context range
Shinya Kitaoka 120a6e
  std::string prefixPlus1 = prefix;
Shinya Kitaoka 120a6e
  prefixPlus1[prefix.size() - 1]++;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  {
Shinya Kitaoka 120a6e
    std::map<std::string, uchar="">::iterator it, jt;</std::string,>
Shinya Kitaoka 120a6e
    it = m_contextNames.lower_bound(prefix);
Shinya Kitaoka 120a6e
    jt = m_contextNames.lower_bound(prefixPlus1);
Shinya Kitaoka 120a6e
    m_contextNames.erase(it, jt);
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Transfer to temporary
Shinya Kitaoka 120a6e
  ResourcesTable &table = m_resources->getTable();
Shinya Kitaoka 120a6e
  std::map<std::string, resourcestable::row=""> &rows =</std::string,>
Shinya Kitaoka 120a6e
      m_resources->getTable().rows();
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::map<std::string, resourcestable::row="">::iterator it, jt, kt;</std::string,>
Shinya Kitaoka 120a6e
  it = rows.lower_bound(prefix);
Shinya Kitaoka 120a6e
  jt = rows.lower_bound(prefixPlus1);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  std::string temporaryName("T");
Shinya Kitaoka 120a6e
  for (kt = it; kt != jt; ++kt) {
Shinya Kitaoka 120a6e
    ResourcesTable::RowIterator lt(kt);
Shinya Kitaoka 120a6e
    for (; lt; ++lt)
Shinya Kitaoka 120a6e
      table.value(temporaryName, lt.col()).insert(lt->begin(), lt->end());
Shinya Kitaoka 120a6e
  }
Shinya Kitaoka 120a6e
  rows.erase(it, jt == rows.end() ? rows.lower_bound(prefixPlus1) : jt);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::releaseOldResources() {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  // Release all the resources that were stored in the old render instance of
Shinya Kitaoka 120a6e
  // the
Shinya Kitaoka 120a6e
  // context, PLUS those of the temporary container.
Shinya Kitaoka 120a6e
  // Resources that were held by the TPassiveCacheManager::getResource()
Shinya Kitaoka 120a6e
  // procedure
Shinya Kitaoka 120a6e
  // are now duplicated in a proper row of the table - and will not be freed.
Shinya Kitaoka 120a6e
  std::string contextName(getContextName());
Shinya Kitaoka 120a6e
  if (contextName.empty()) return;
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  char &lastChar = contextName[contextName.size() - 1];
Shinya Kitaoka 120a6e
  lastChar       = '0' + !(lastChar - '0');
Shinya Kitaoka 120a6e
Shinya Kitaoka 120a6e
  ResourcesTable &table = m_resources->getTable();
Shinya Kitaoka 120a6e
  table.erase(contextName);
Shinya Kitaoka 120a6e
  table.erase("T");
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::onRenderInstanceStart(unsigned long renderId) {
Shinya Kitaoka 120a6e
  TFxCacheManagerDelegate::onRenderInstanceStart(renderId);
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
#ifdef USE_SQLITE_HDPOOL
Shinya Kitaoka 120a6e
  // Force invalidation of levels before the render starts
Shinya Kitaoka 120a6e
  forceInvalidate();
Toshihiro Shimizu 890ddd
#endif
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::onRenderInstanceEnd(unsigned long renderId) {
Shinya Kitaoka 120a6e
  QMutexLocker locker(&m_mutex);
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
  releaseOldResources();
Shinya Kitaoka 120a6e
  m_contextNamesByRenderId.erase(renderId);
Toshihiro Shimizu 890ddd
}
Toshihiro Shimizu 890ddd
Toshihiro Shimizu 890ddd
//-------------------------------------------------------------------------
Toshihiro Shimizu 890ddd
Shinya Kitaoka 120a6e
void TPassiveCacheManager::onRenderStatusEnd(int renderStatus) {
Shinya Kitaoka 120a6e
  if (renderStatus == TRenderer::TESTRUN) releaseOldResources();
Toshihiro Shimizu 890ddd
}