Commit 0617bb06 authored by Dmitry Kazakov's avatar Dmitry Kazakov
Browse files

Fix random artifacts when undoing brush strokes

It looks like making indirect painting merge multithreaded
revealed a very old race condition in the tiles data manager.
The extent of the memento should be calculated in a synchronous
way.

BUG:453243
parent b3eb2eaf
Pipeline #202769 canceled with stage
in 25 minutes and 38 seconds
......@@ -85,16 +85,27 @@ public:
private:
friend class KisMementoManager;
inline void updateExtent(qint32 col, qint32 row) {
inline void updateExtent(qint32 col, qint32 row, QMutex *currentMementoExtentLock) {
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;
m_extentMinX = qMin(m_extentMinX, tileMinX);
m_extentMaxX = qMax(m_extentMaxX, tileMaxX);
m_extentMinY = qMin(m_extentMinY, tileMinY);
m_extentMaxY = qMax(m_extentMaxY, tileMaxY);
{
/**
* HACK ALERT: the lock is stored in the memento
* manager to avoid too many locks to be created.
* Anyway, a memento manager can have only one
* "current memento". And it would not be nice to
* do KisTileData::WIDTH/HEIGHT multiplication
* under the lock held.
*/
QMutexLocker l(currentMementoExtentLock);
m_extentMinX = qMin(m_extentMinX, tileMinX);
m_extentMaxX = qMax(m_extentMaxX, tileMaxX);
m_extentMinY = qMin(m_extentMinY, tileMinY);
m_extentMaxY = qMax(m_extentMaxY, tileMaxY);
}
}
private:
......
......@@ -123,8 +123,9 @@ void KisMementoManager::registerTileChange(KisTile *tile)
mi->changeTile(tile);
m_index.addTile(mi);
if(namedTransactionInProgress())
m_currentMemento->updateExtent(mi->col(), mi->row());
if(namedTransactionInProgress()) {
m_currentMemento->updateExtent(mi->col(), mi->row(), &m_currentMementoExtentLock);
}
}
else {
mi->reset();
......@@ -149,8 +150,9 @@ void KisMementoManager::registerTileDeleted(KisTile *tile)
m_index.addTile(mi);
if(namedTransactionInProgress())
m_currentMemento->updateExtent(mi->col(), mi->row());
if(namedTransactionInProgress()) {
m_currentMemento->updateExtent(mi->col(), mi->row(), &m_currentMementoExtentLock);
}
}
else {
mi->reset();
......
......@@ -147,6 +147,7 @@ protected:
* It is the "name" of current named transaction
*/
KisMementoSP m_currentMemento;
QMutex m_currentMementoExtentLock;
/**
* The flag that blocks registration of changes on tiles.
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment