Masterwork From Distant Lands
ActivePublic

Authored by dkazakov on Aug 11 2017, 9:55 AM.
diff --git a/libs/image/CMakeLists.txt b/libs/image/CMakeLists.txt
index ab42e38..6537852 100644
--- a/libs/image/CMakeLists.txt
+++ b/libs/image/CMakeLists.txt
@@ -45,6 +45,7 @@ set(kritaimage_LIB_SRCS
tiles3/kis_hline_iterator.cpp
tiles3/kis_vline_iterator.cpp
tiles3/kis_random_accessor.cc
+ tiles3/KisTiledDataManagerExtentCache.cpp
tiles3/swap/kis_abstract_compression.cpp
tiles3/swap/kis_lzf_compression.cpp
tiles3/swap/kis_abstract_tile_compressor.cpp
diff --git a/libs/image/tiles3/KisTiledDataManagerExtentCache.cpp b/libs/image/tiles3/KisTiledDataManagerExtentCache.cpp
index 5c13499..6c4d7d6 100644
--- a/libs/image/tiles3/KisTiledDataManagerExtentCache.cpp
+++ b/libs/image/tiles3/KisTiledDataManagerExtentCache.cpp
@@ -18,8 +18,14 @@
#include "KisTiledDataManagerExtentCache.h"
-KisTiledDataManagerExtentCache::KisTiledDataManagerExtentCache()
-{
+#include "kis_tiled_data_manager.h"
+KisTiledDataManagerExtentCache::KisTiledDataManagerExtentCache(KisTiledDataManager *dm)
+ : m_dataManager(dm)
+{
}
+QRect KisTiledDataManagerExtentCache::calculateNewValue() const
+{
+ return m_dataManager->calculateExtentInternal();
+}
diff --git a/libs/image/tiles3/KisTiledDataManagerExtentCache.h b/libs/image/tiles3/KisTiledDataManagerExtentCache.h
index 0faa49e..f318556 100644
--- a/libs/image/tiles3/KisTiledDataManagerExtentCache.h
+++ b/libs/image/tiles3/KisTiledDataManagerExtentCache.h
@@ -19,11 +19,21 @@
#ifndef KISTILEDDATAMANAGEREXTENTCACHE_H
#define KISTILEDDATAMANAGEREXTENTCACHE_H
+#include <QRect>
+#include "kis_lock_free_cache.h"
-class KisTiledDataManagerExtentCache
+class KisTiledDataManager;
+
+class KisTiledDataManagerExtentCache : public KisLockFreeCache<QRect>
{
public:
- KisTiledDataManagerExtentCache();
+ KisTiledDataManagerExtentCache(KisTiledDataManager *dm);
+
+protected:
+ QRect calculateNewValue() const override;
+
+private:
+ KisTiledDataManager *m_dataManager;
};
#endif // KISTILEDDATAMANAGEREXTENTCACHE_H
diff --git a/libs/image/tiles3/kis_tiled_data_manager.cc b/libs/image/tiles3/kis_tiled_data_manager.cc
index 8bcf684..88171cf 100644
--- a/libs/image/tiles3/kis_tiled_data_manager.cc
+++ b/libs/image/tiles3/kis_tiled_data_manager.cc
@@ -44,6 +44,7 @@
KisTiledDataManager::KisTiledDataManager(quint32 pixelSize,
const quint8 *defaultPixel)
+ : m_extentCache(this)
{
/* See comment in destructor for details */
m_mementoManager = new KisMementoManager();
@@ -60,7 +61,8 @@ KisTiledDataManager::KisTiledDataManager(quint32 pixelSize,
}
KisTiledDataManager::KisTiledDataManager(const KisTiledDataManager &dm)
- : KisShared()
+ : KisShared(),
+ m_extentCache(this)
{
/* See comment in destructor for details */
@@ -280,8 +282,6 @@ wrongString:
void KisTiledDataManager::purge(const QRect& area)
{
- QWriteLocker locker(&m_lock);
-
QList<KisTileSP> tilesToDelete;
{
const qint32 tileDataSize = KisTileData::HEIGHT * KisTileData::WIDTH * pixelSize();
@@ -309,7 +309,7 @@ void KisTiledDataManager::purge(const QRect& area)
m_hashTable->deleteTile(tile);
}
- recalculateExtent();
+ m_extentCache.invalidate();
}
quint8* KisTiledDataManager::duplicatePixel(qint32 num, const quint8 *pixel)
@@ -327,8 +327,6 @@ quint8* KisTiledDataManager::duplicatePixel(qint32 num, const quint8 *pixel)
void KisTiledDataManager::clear(QRect clearRect, const quint8 *clearPixel)
{
- QWriteLocker locker(&m_lock);
-
if (clearPixel == 0)
clearPixel = m_defaultPixel;
@@ -348,7 +346,7 @@ void KisTiledDataManager::clear(QRect clearRect, const quint8 *clearPixel)
}
if (pixelBytesAreDefault) {
- clearRect &= extentImpl();
+ clearRect &= extent();
}
qint32 firstColumn = xToCol(clearRect.left());
@@ -385,12 +383,12 @@ void KisTiledDataManager::clear(QRect clearRect, const quint8 *clearPixel)
if (clearTileRect == tileRect) {
// Clear whole tile
m_hashTable->deleteTile(column, row);
- needsRecalculateExtent = true;
if (!pixelBytesAreDefault) {
KisTileSP clearedTile = KisTileSP(new KisTile(column, row, td, m_mementoManager));
m_hashTable->addTile(clearedTile);
- updateExtent(column, row);
+ } else {
+ needsRecalculateExtent = true;
}
} else {
const qint32 lineSize = clearTileRect.width() * pixelSize;
@@ -420,7 +418,7 @@ void KisTiledDataManager::clear(QRect clearRect, const quint8 *clearPixel)
}
if (needsRecalculateExtent) {
- recalculateExtent();
+ m_extentCache.invalidate();
}
if (td) td->release();
@@ -464,6 +462,8 @@ void KisTiledDataManager::bitBltImpl(KisTiledDataManager *srcDM, const QRect &re
if (rect.isEmpty()) return;
+ bool needsRecalculateExtent = false;
+
const qint32 pixelSize = this->pixelSize();
const quint32 rowStride = KisTileData::WIDTH * pixelSize;
@@ -495,7 +495,7 @@ void KisTiledDataManager::bitBltImpl(KisTiledDataManager *srcDM, const QRect &re
srcTile->unlock();
m_hashTable->addTile(clonedTile);
- updateExtent(column, row);
+ needsRecalculateExtent = true;
} else {
const qint32 lineSize = cloneTileRect.width() * pixelSize;
qint32 rowsRemaining = cloneTileRect.height();
@@ -520,6 +520,10 @@ void KisTiledDataManager::bitBltImpl(KisTiledDataManager *srcDM, const QRect &re
}
}
}
+
+ if (needsRecalculateExtent) {
+ m_extentCache.invalidate();
+ }
}
template<bool useOldSrcData>
@@ -556,9 +560,10 @@ void KisTiledDataManager::bitBltRoughImpl(KisTiledDataManager *srcDM, const QRec
srcTile->unlock();
m_hashTable->addTile(clonedTile);
- updateExtent(column, row);
}
}
+
+ m_extentCache.invalidate();
}
void KisTiledDataManager::bitBlt(KisTiledDataManager *srcDM, const QRect &rect)
@@ -595,8 +600,6 @@ void KisTiledDataManager::setExtent(QRect newRect)
// that is handled by the autoextending automatically
if (newRect.contains(oldRect)) return;
- QWriteLocker locker(&m_lock);
-
KisTileSP tile;
QRect tileRect;
{
@@ -636,46 +639,37 @@ void KisTiledDataManager::setExtent(QRect newRect)
}
}
- recalculateExtent();
+ m_extentCache.invalidate();
}
-void KisTiledDataManager::recalculateExtent()
+QRect KisTiledDataManager::calculateExtentInternal() const
{
- m_extentMinX = qint32_MAX;
- m_extentMinY = qint32_MAX;
- m_extentMaxX = qint32_MIN;
- m_extentMaxY = qint32_MIN;
+ int extentMinX = qint32_MAX;
+ int extentMinY = qint32_MAX;
+ int extentMaxX = qint32_MIN;
+ int extentMaxY = qint32_MIN;
KisTileHashTableConstIterator iter(m_hashTable);
KisTileSP tile;
while ((tile = iter.tile())) {
- updateExtent(tile->col(), tile->row());
- iter.next();
- }
-}
+ const qint32 tileMinX = tile->col() * KisTileData::WIDTH;
+ const qint32 tileMinY = tile->row() * KisTileData::HEIGHT;
+ const qint32 tileMaxX = tileMinX + KisTileData::WIDTH - 1;
+ const qint32 tileMaxY = tileMinY + KisTileData::HEIGHT - 1;
-void KisTiledDataManager::updateExtent(qint32 col, qint32 row)
-{
- const qint32 tileMinX = col * KisTileData::WIDTH;
- const qint32 tileMinY = row * KisTileData::HEIGHT;
- const qint32 tileMaxX = tileMinX + KisTileData::WIDTH - 1;
- const qint32 tileMaxY = tileMinY + KisTileData::HEIGHT - 1;
+ extentMinX = qMin(extentMinX, tileMinX);
+ extentMaxX = qMax(extentMaxX, tileMaxX);
+ extentMinY = qMin(extentMinY, tileMinY);
+ extentMaxY = qMax(extentMaxY, tileMaxY);
- m_extentMinX = qMin(m_extentMinX, tileMinX);
- m_extentMaxX = qMax(m_extentMaxX, tileMaxX);
- m_extentMinY = qMin(m_extentMinY, tileMinY);
- m_extentMaxY = qMax(m_extentMaxY, tileMaxY);
-}
+ iter.next();
+ }
-QRect KisTiledDataManager::extentImpl() const
-{
- qint32 x = m_extentMinX;
- qint32 y = m_extentMinY;
- qint32 w = (m_extentMaxX >= m_extentMinX) ? m_extentMaxX - m_extentMinX + 1 : 0;
- qint32 h = (m_extentMaxY >= m_extentMinY) ? m_extentMaxY - m_extentMinY + 1 : 0;
+ const qint32 w = qMax(extentMaxX - extentMinX + 1, 0);
+ const qint32 h = qMax(extentMaxY - extentMinY + 1, 0);
- return QRect(x, y, w, h);
+ return QRect(extentMinX, extentMinY, w, h);
}
void KisTiledDataManager::extent(qint32 &x, qint32 &y, qint32 &w, qint32 &h) const
@@ -686,8 +680,7 @@ void KisTiledDataManager::extent(qint32 &x, qint32 &y, qint32 &w, qint32 &h) con
QRect KisTiledDataManager::extent() const
{
- QReadLocker locker(&m_lock);
- return extentImpl();
+ return m_extentCache.getValue();
}
QRegion KisTiledDataManager::region() const
diff --git a/libs/image/tiles3/kis_tiled_data_manager.h b/libs/image/tiles3/kis_tiled_data_manager.h
index 25f9dd8..be0c1ea 100644
--- a/libs/image/tiles3/kis_tiled_data_manager.h
+++ b/libs/image/tiles3/kis_tiled_data_manager.h
@@ -32,6 +32,7 @@
#include "kis_tile_hash_table.h"
#include "kis_memento_manager.h"
#include "kis_memento.h"
+#include "KisTiledDataManagerExtentCache.h"
class KisTiledDataManager;
@@ -109,8 +110,9 @@ public:
if (writable) {
bool newTile;
KisTileSP tile = m_hashTable->getTileLazy(col, row, newTile);
- if (newTile)
- updateExtent(tile->col(), tile->row());
+ if (newTile) {
+ m_extentCache.invalidate();
+ }
return tile;
} else {
@@ -154,7 +156,7 @@ public:
if(memcmp(m_defaultPixel, defaultPixel, m_pixelSize)) {
setDefaultPixelImpl(defaultPixel);
}
- recalculateExtent();
+ m_extentCache.invalidate();
}
void rollforward(KisMementoSP memento) {
commit();
@@ -165,7 +167,7 @@ public:
if(memcmp(m_defaultPixel, defaultPixel, m_pixelSize)) {
setDefaultPixelImpl(defaultPixel);
}
- recalculateExtent();
+ m_extentCache.invalidate();
}
bool hasCurrentMemento() const {
return m_mementoManager->hasCurrentMemento();
@@ -328,6 +330,8 @@ private:
qint32 m_extentMinY;
qint32 m_extentMaxY;
+ KisTiledDataManagerExtentCache m_extentCache;
+
mutable QReadWriteLock m_lock;
private:
@@ -341,15 +345,13 @@ private:
private:
void setDefaultPixelImpl(const quint8 *defPixel);
- QRect extentImpl() const;
-
bool writeTilesHeader(KisPaintDeviceWriter &store, quint32 numTiles);
bool processTilesHeader(QIODevice *stream, quint32 &numTiles);
qint32 divideRoundDown(qint32 x, const qint32 y) const;
- void updateExtent(qint32 col, qint32 row);
- void recalculateExtent();
+ friend class KisTiledDataManagerExtentCache;
+ QRect calculateExtentInternal() const;
quint8* duplicatePixel(qint32 num, const quint8 *pixel);
dkazakov edited the content of this paste. (Show Details)Aug 11 2017, 9:55 AM
dkazakov changed the title of this paste from untitled to Masterwork From Distant Lands.
dkazakov updated the paste's language from autodetect to autodetect.