Krita Source Code Documentation
Loading...
Searching...
No Matches
KisStrokesQueue Class Reference

#include <kis_strokes_queue.h>

+ Inheritance diagram for KisStrokesQueue:

Classes

class  LodNUndoStrokesFacade
 

Public Member Functions

void addJob (KisStrokeId id, KisStrokeJobData *data)
 
void addMutatedJobs (KisStrokeId id, const QVector< KisStrokeJobData * > list) final override
 
qreal balancingRatioOverride () const
 
void cancelForgettableStrokes ()
 
bool cancelStroke (KisStrokeId id)
 
std::pair< StrokesQueueIterator, StrokesQueueIteratorcurrentLodRange ()
 
KUndo2MagicString currentStrokeName () const
 
void debugDumpAllStrokes ()
 
void endStroke (KisStrokeId id)
 
void explicitRegenerateLevelOfDetail ()
 
StrokesQueueIterator findNewLod0Pos ()
 
StrokesQueueIterator findNewLodNPos (KisStrokeSP lodN)
 
void forceResetLodAndCloseCurrentLodRange ()
 
bool hasOpenedStrokes () const
 
bool hasUnfinishedStrokes () const
 
bool isEmpty () const
 
 KisStrokesQueue ()
 
void loadStroke (KisStrokeSP stroke)
 
KisPostExecutionUndoAdapterlodNPostExecutionUndoAdapter () const
 
KisLodPreferences lodPreferences () const override
 
bool needsExclusiveAccess () const
 
void notifyUFOChangedImage ()
 
 Private (KisStrokesQueue *_q)
 
void processQueue (KisUpdaterContext &updaterContext, bool externalJobsPending)
 
void setLod0ToNStrokeStrategyFactory (const KisLodSyncStrokeStrategyFactory &factory)
 
void setLodPreferences (const KisLodPreferences &value)
 
void setPostSyncLod0GUIPlaneRequestForResumeCallback (const std::function< void()> &callback)
 
void setPurgeRedoStateCallback (const std::function< void()> &callback)
 
void setSuspendResumeUpdatesStrokeStrategyFactory (const KisSuspendResumeStrategyPairFactory &factory)
 
bool shouldWrapInSuspendUpdatesStroke ()
 
qint32 sizeMetric () const
 
void startLod0ToNStroke (int levelOfDetail, bool forgettable)
 
KisStrokeId startStroke (KisStrokeStrategy *strokeStrategy)
 
void switchDesiredLevelOfDetail (bool forced)
 
bool tryCancelCurrentStrokeAsync ()
 
void tryClearUndoOnStrokeCompletion (KisStrokeSP finishingStroke)
 
UndoResult tryUndoLastStrokeAsync ()
 
bool wrapAroundModeSupported () const
 
 ~KisStrokesQueue ()
 
- Public Member Functions inherited from Private
 Private (KisCanvas2 *c)
 
- Public Member Functions inherited from KisStrokesQueueMutatedJobInterface
virtual ~KisStrokesQueueMutatedJobInterface ()
 

Public Attributes

qreal balancingRatioOverride
 
bool currentStrokeLoaded
 
int desiredLevelOfDetail
 
KisLodSyncStrokeStrategyFactory lod0ToNStrokeStrategyFactory
 
bool lodNNeedsSynchronization
 
KisPostExecutionUndoAdapter lodNPostExecutionUndoAdapter
 
LodNUndoStrokesFacade lodNStrokesFacade
 
KisSurrogateUndoStore lodNUndoStore
 
KisLodPreferences lodPreferences
 
QMutex mutex
 
bool needsExclusiveAccess
 
int nextDesiredLevelOfDetail
 
int openedStrokesCounter
 
std::function< void()> postSyncLod0GUIPlaneRequestForResume
 
std::function< void()> purgeRedoStateCallback
 
KisStrokesQueueq
 
StrokesQueue strokesQueue
 
KisSuspendResumeStrategyPairFactory suspendResumeUpdatesStrokeStrategyFactory
 
bool wrapAroundModeSupported
 
- Public Attributes inherited from Private
KisCanvas2canvas
 
int displayedFrame
 
int intendedFrame
 

Private Member Functions

bool checkBarrierProperty (bool hasMergeJobs, bool hasStrokeJobs, bool externalJobsPending)
 
bool checkExclusiveProperty (bool hasMergeJobs, bool hasStrokeJobs)
 
bool checkLevelOfDetailProperty (int runningLevelOfDetail)
 
bool checkSequentialProperty (KisUpdaterContextSnapshotEx snapshot, bool externalJobsPending)
 
bool checkStrokeState (bool hasStrokeJobsRunning, int runningLevelOfDetail)
 
bool processOneJob (KisUpdaterContext &updaterContext, bool externalJobsPending)
 
KisStrokeId startLodNUndoStroke (KisStrokeStrategy *strokeStrategy)
 

Private Attributes

Private *const m_d
 

Detailed Description

Definition at line 62 of file kis_strokes_queue.cpp.

Constructor & Destructor Documentation

◆ KisStrokesQueue()

KisStrokesQueue::KisStrokesQueue ( )

Definition at line 114 of file kis_strokes_queue.cpp.

115 : m_d(new Private(this))
116{
117}
Private *const m_d

◆ ~KisStrokesQueue()

KisStrokesQueue::~KisStrokesQueue ( )

Definition at line 119 of file kis_strokes_queue.cpp.

120{
121 Q_FOREACH (KisStrokeSP stroke, m_d->strokesQueue) {
122 stroke->cancelStroke();
123 }
124
125 delete m_d;
126}

References m_d.

Member Function Documentation

◆ addJob()

void KisStrokesQueue::addJob ( KisStrokeId id,
KisStrokeJobData * data )

Definition at line 342 of file kis_strokes_queue.cpp.

343{
344 QMutexLocker locker(&m_d->mutex);
345
346 KisStrokeSP stroke = id.toStrongRef();
348
349 KisStrokeSP buddy = stroke->lodBuddy();
350 if (buddy) {
351 KisStrokeJobData *clonedData =
352 data->createLodClone(buddy->worksOnLevelOfDetail());
353 KIS_ASSERT_RECOVER_RETURN(clonedData);
354
355 buddy->addJob(clonedData);
356 }
357
358 stroke->addJob(data);
359}
virtual KisStrokeJobData * createLodClone(int levelOfDetail)
#define KIS_SAFE_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:128
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75

References KisStrokeJobData::createLodClone(), KIS_ASSERT_RECOVER_RETURN, KIS_SAFE_ASSERT_RECOVER_RETURN, and m_d.

◆ addMutatedJobs()

void KisStrokesQueue::addMutatedJobs ( KisStrokeId id,
const QVector< KisStrokeJobData * > list )
finaloverridevirtual

Implements KisStrokesQueueMutatedJobInterface.

Definition at line 361 of file kis_strokes_queue.cpp.

362{
363 QMutexLocker locker(&m_d->mutex);
364
365 KisStrokeSP stroke = id.toStrongRef();
367
368 stroke->addMutatedJobs(list);
369}

References KIS_SAFE_ASSERT_RECOVER_RETURN, and m_d.

◆ balancingRatioOverride()

qreal KisStrokesQueue::balancingRatioOverride ( ) const

◆ cancelForgettableStrokes()

void KisStrokesQueue::cancelForgettableStrokes ( )

◆ cancelStroke()

bool KisStrokesQueue::cancelStroke ( KisStrokeId id)

Definition at line 386 of file kis_strokes_queue.cpp.

387{
388 QMutexLocker locker(&m_d->mutex);
389
390 KisStrokeSP stroke = id.toStrongRef();
391 if(stroke) {
392 stroke->cancelStroke();
393 m_d->openedStrokesCounter--;
394
395 KisStrokeSP buddy = stroke->lodBuddy();
396 if (buddy) {
397 buddy->cancelStroke();
398 }
399 }
400 return bool(stroke);
401}

References m_d.

◆ checkBarrierProperty()

bool KisStrokesQueue::checkBarrierProperty ( bool hasMergeJobs,
bool hasStrokeJobs,
bool externalJobsPending )
private

◆ checkExclusiveProperty()

bool KisStrokesQueue::checkExclusiveProperty ( bool hasMergeJobs,
bool hasStrokeJobs )
private

Definition at line 867 of file kis_strokes_queue.cpp.

869{
870 Q_UNUSED(hasStrokeJobs);
871
872 if(!m_d->strokesQueue.head()->isExclusive()) return true;
873 return hasMergeJobs == 0;
874}

References m_d.

◆ checkLevelOfDetailProperty()

bool KisStrokesQueue::checkLevelOfDetailProperty ( int runningLevelOfDetail)
private

Definition at line 914 of file kis_strokes_queue.cpp.

915{
916 KisStrokeSP stroke = m_d->strokesQueue.head();
917
918 return runningLevelOfDetail < 0 ||
919 stroke->nextJobLevelOfDetail() == runningLevelOfDetail;
920}

References m_d.

◆ checkSequentialProperty()

bool KisStrokesQueue::checkSequentialProperty ( KisUpdaterContextSnapshotEx snapshot,
bool externalJobsPending )
private

Definition at line 876 of file kis_strokes_queue.cpp.

878{
879 KisStrokeSP stroke = m_d->strokesQueue.head();
880
881 if (snapshot & HasSequentialJob ||
882 snapshot & HasBarrierJob) {
883 return false;
884 }
885
886 KisStrokeJobData::Sequentiality nextSequentiality =
887 stroke->nextJobSequentiality();
888
889 if (nextSequentiality == KisStrokeJobData::UNIQUELY_CONCURRENT &&
890 snapshot & HasUniquelyConcurrentJob) {
891
892 return false;
893 }
894
895 if (nextSequentiality == KisStrokeJobData::SEQUENTIAL &&
896 (snapshot & HasUniquelyConcurrentJob ||
897 snapshot & HasConcurrentJob)) {
898
899 return false;
900 }
901
902 if (nextSequentiality == KisStrokeJobData::BARRIER &&
903 (snapshot & HasUniquelyConcurrentJob ||
904 snapshot & HasConcurrentJob ||
905 snapshot & HasMergeJob ||
906 externalJobsPending)) {
907
908 return false;
909 }
910
911 return true;
912}

References KisStrokeJobData::BARRIER, HasBarrierJob, HasConcurrentJob, HasMergeJob, HasSequentialJob, HasUniquelyConcurrentJob, m_d, KisStrokeJobData::SEQUENTIAL, and KisStrokeJobData::UNIQUELY_CONCURRENT.

◆ checkStrokeState()

bool KisStrokesQueue::checkStrokeState ( bool hasStrokeJobsRunning,
int runningLevelOfDetail )
private

We cannot start/continue a stroke if its LOD differs from the one that is running on CPU

The stroke may be cancelled very fast. In this case it will end up in the state:

!stroke->isInitialized() && stroke->isEnded() && !stroke->hasJobs()

This means that !isInitialised() doesn't imply there are any jobs present.

It might happen that the stroke got initialized, but its job was not started due to some other reasons like exclusivity. Therefore the stroke might end up in loaded, but uninitialized state.

If the stroke has no initialization phase, then it can arrive here unloaded.

If the Lod0 stroke has been cancelled without even being started, it means that the GUI still has LodN tiles active, so we should reread the data from the image to switch GUI tiles into Lod0 mode.

Definition at line 788 of file kis_strokes_queue.cpp.

790{
791 KisStrokeSP stroke = m_d->strokesQueue.head();
792 bool result = false;
793
798 bool hasLodCompatibility = checkLevelOfDetailProperty(runningLevelOfDetail);
799 bool hasJobs = stroke->hasJobs();
800
810 if(!stroke->isInitialized() && hasJobs && hasLodCompatibility) {
816 if (!m_d->currentStrokeLoaded) {
817 m_d->loadStroke(stroke);
818 }
819
820 result = true;
821 }
822 else if(hasJobs && hasLodCompatibility) {
827 if (!m_d->currentStrokeLoaded) {
828 m_d->loadStroke(stroke);
829 }
830
831 result = true;
832 }
833 else if(stroke->isEnded() && !hasJobs && !hasStrokeJobsRunning) {
834 m_d->tryClearUndoOnStrokeCompletion(stroke);
835
836 const bool needsSyncLod0PlaneToGUI =
837 stroke->type() == KisStroke::LOD0 &&
838 stroke->isCancelled();
839
846 if (needsSyncLod0PlaneToGUI &&
847 m_d->postSyncLod0GUIPlaneRequestForResume) {
848 m_d->postSyncLod0GUIPlaneRequestForResume();
849 }
850
851 m_d->strokesQueue.dequeue(); // deleted by shared pointer
852 m_d->needsExclusiveAccess = false;
853 m_d->wrapAroundModeSupported = false;
854 m_d->balancingRatioOverride = -1.0;
855 m_d->currentStrokeLoaded = false;
856
857 m_d->switchDesiredLevelOfDetail(false);
858
859 if(!m_d->strokesQueue.isEmpty()) {
860 result = checkStrokeState(false, runningLevelOfDetail);
861 }
862 }
863
864 return result;
865}
bool checkStrokeState(bool hasStrokeJobsRunning, int runningLevelOfDetail)
bool checkLevelOfDetailProperty(int runningLevelOfDetail)

References checkLevelOfDetailProperty(), checkStrokeState(), KisStroke::LOD0, and m_d.

◆ currentLodRange()

std::pair< StrokesQueueIterator, StrokesQueueIterator > KisStrokesQueue::currentLodRange ( )

◆ currentStrokeName()

KUndo2MagicString KisStrokesQueue::currentStrokeName ( ) const

Definition at line 728 of file kis_strokes_queue.cpp.

729{
730 QMutexLocker locker(&m_d->mutex);
731 if(m_d->strokesQueue.isEmpty()) return KUndo2MagicString();
732
733 return m_d->strokesQueue.head()->name();
734}

References m_d.

◆ debugDumpAllStrokes()

void KisStrokesQueue::debugDumpAllStrokes ( )

Definition at line 692 of file kis_strokes_queue.cpp.

693{
694 QMutexLocker locker(&m_d->mutex);
695
696 qDebug() <<"===";
697 Q_FOREACH (KisStrokeSP stroke, m_d->strokesQueue) {
698 qDebug() << ppVar(stroke->name()) << ppVar(stroke->type()) << ppVar(stroke->numJobs()) << ppVar(stroke->isInitialized()) << ppVar(stroke->isCancelled());
699 }
700 qDebug() <<"===";
701}
#define ppVar(var)
Definition kis_debug.h:155

References m_d, and ppVar.

◆ endStroke()

void KisStrokesQueue::endStroke ( KisStrokeId id)

Definition at line 371 of file kis_strokes_queue.cpp.

372{
373 QMutexLocker locker(&m_d->mutex);
374
375 KisStrokeSP stroke = id.toStrongRef();
377 stroke->endStroke();
378 m_d->openedStrokesCounter--;
379
380 KisStrokeSP buddy = stroke->lodBuddy();
381 if (buddy) {
382 buddy->endStroke();
383 }
384}

References KIS_SAFE_ASSERT_RECOVER_RETURN, and m_d.

◆ explicitRegenerateLevelOfDetail()

void KisStrokesQueue::explicitRegenerateLevelOfDetail ( )

Definition at line 679 of file kis_strokes_queue.cpp.

680{
681 QMutexLocker locker(&m_d->mutex);
682 m_d->switchDesiredLevelOfDetail(true);
683}

References m_d.

◆ findNewLod0Pos()

StrokesQueueIterator KisStrokesQueue::findNewLod0Pos ( )

◆ findNewLodNPos()

StrokesQueueIterator KisStrokesQueue::findNewLodNPos ( KisStrokeSP lodN)

◆ forceResetLodAndCloseCurrentLodRange()

void KisStrokesQueue::forceResetLodAndCloseCurrentLodRange ( )

◆ hasOpenedStrokes()

bool KisStrokesQueue::hasOpenedStrokes ( ) const

Definition at line 736 of file kis_strokes_queue.cpp.

737{
738 QMutexLocker locker(&m_d->mutex);
739 return m_d->openedStrokesCounter;
740}

References m_d.

◆ hasUnfinishedStrokes()

bool KisStrokesQueue::hasUnfinishedStrokes ( ) const

◆ isEmpty()

bool KisStrokesQueue::isEmpty ( ) const

Definition at line 643 of file kis_strokes_queue.cpp.

644{
645 QMutexLocker locker(&m_d->mutex);
646 return m_d->strokesQueue.isEmpty();
647}

References m_d.

◆ loadStroke()

void KisStrokesQueue::loadStroke ( KisStrokeSP stroke)

◆ lodNPostExecutionUndoAdapter()

KisPostExecutionUndoAdapter * KisStrokesQueue::lodNPostExecutionUndoAdapter ( ) const

◆ lodPreferences()

KisLodPreferences KisStrokesQueue::lodPreferences ( ) const
overridevirtual

◆ needsExclusiveAccess()

bool KisStrokesQueue::needsExclusiveAccess ( ) const

◆ notifyUFOChangedImage()

void KisStrokesQueue::notifyUFOChangedImage ( )

Notifies the queue, that someone else (neither strokes nor the queue itself have changed the image. It means that the caches should be regenerated

Definition at line 685 of file kis_strokes_queue.cpp.

686{
687 QMutexLocker locker(&m_d->mutex);
688
689 m_d->forceResetLodAndCloseCurrentLodRange();
690}

References m_d.

◆ Private()

KisStrokesQueue::Private ( KisStrokesQueue * _q)
inline

Definition at line 63 of file kis_strokes_queue.cpp.

64 : q(_q),
KisSurrogateUndoStore lodNUndoStore
KisStrokesQueue * q
KisPostExecutionUndoAdapter lodNPostExecutionUndoAdapter
LodNUndoStrokesFacade lodNStrokesFacade

◆ processOneJob()

bool KisStrokesQueue::processOneJob ( KisUpdaterContext & updaterContext,
bool externalJobsPending )
private

Definition at line 742 of file kis_strokes_queue.cpp.

744{
745 if(m_d->strokesQueue.isEmpty()) return false;
746 bool result = false;
747
748 const int levelOfDetail = updaterContext.currentLevelOfDetail();
749
750 const KisUpdaterContextSnapshotEx snapshot = updaterContext.getContextSnapshotEx();
751
752 const bool hasStrokeJobs = !(snapshot == ContextEmpty ||
753 snapshot == HasMergeJob);
754 const bool hasMergeJobs = snapshot & HasMergeJob;
755
756 if(checkStrokeState(hasStrokeJobs, levelOfDetail) &&
757 checkExclusiveProperty(hasMergeJobs, hasStrokeJobs) &&
758 checkSequentialProperty(snapshot, externalJobsPending)) {
759
760 KisStrokeSP stroke = m_d->strokesQueue.head();
761 updaterContext.addStrokeJob(stroke->popOneJob());
762 result = true;
763 }
764
765 return result;
766}
KisUpdaterContextSnapshotEx getContextSnapshotEx() const
void addStrokeJob(KisStrokeJob *strokeJob)
bool checkExclusiveProperty(bool hasMergeJobs, bool hasStrokeJobs)
bool checkSequentialProperty(KisUpdaterContextSnapshotEx snapshot, bool externalJobsPending)

References KisUpdaterContext::addStrokeJob(), checkExclusiveProperty(), checkSequentialProperty(), checkStrokeState(), ContextEmpty, KisUpdaterContext::currentLevelOfDetail(), KisUpdaterContext::getContextSnapshotEx(), HasMergeJob, and m_d.

◆ processQueue()

void KisStrokesQueue::processQueue ( KisUpdaterContext & updaterContext,
bool externalJobsPending )

Definition at line 589 of file kis_strokes_queue.cpp.

591{
592 updaterContext.lock();
593 m_d->mutex.lock();
594
595 while(updaterContext.hasSpareThread() &&
596 processOneJob(updaterContext,
597 externalJobsPending));
598
599 m_d->mutex.unlock();
600 updaterContext.unlock();
601}
bool processOneJob(KisUpdaterContext &updaterContext, bool externalJobsPending)

References KisUpdaterContext::hasSpareThread(), KisUpdaterContext::lock(), m_d, processOneJob(), and KisUpdaterContext::unlock().

◆ setLod0ToNStrokeStrategyFactory()

void KisStrokesQueue::setLod0ToNStrokeStrategyFactory ( const KisLodSyncStrokeStrategyFactory & factory)

Definition at line 703 of file kis_strokes_queue.cpp.

704{
705 m_d->lod0ToNStrokeStrategyFactory = factory;
706}

References m_d.

◆ setLodPreferences()

void KisStrokesQueue::setLodPreferences ( const KisLodPreferences & value)

Definition at line 629 of file kis_strokes_queue.cpp.

630{
631 QMutexLocker locker(&m_d->mutex);
632
633 m_d->lodPreferences = value;
634
635 if (m_d->lodPreferences.desiredLevelOfDetail() != m_d->nextDesiredLevelOfDetail ||
636 (m_d->lodPreferences.lodPreferred() && m_d->lodNNeedsSynchronization)) {
637
638 m_d->nextDesiredLevelOfDetail = m_d->lodPreferences.desiredLevelOfDetail();
639 m_d->switchDesiredLevelOfDetail(false);
640 }
641}
float value(const T *src, size_t ch)

References m_d, and value().

◆ setPostSyncLod0GUIPlaneRequestForResumeCallback()

void KisStrokesQueue::setPostSyncLod0GUIPlaneRequestForResumeCallback ( const std::function< void()> & callback)

Definition at line 718 of file kis_strokes_queue.cpp.

719{
720 m_d->postSyncLod0GUIPlaneRequestForResume = callback;
721}

References m_d.

◆ setPurgeRedoStateCallback()

void KisStrokesQueue::setPurgeRedoStateCallback ( const std::function< void()> & callback)

Definition at line 713 of file kis_strokes_queue.cpp.

714{
715 m_d->purgeRedoStateCallback = callback;
716}

References m_d.

◆ setSuspendResumeUpdatesStrokeStrategyFactory()

void KisStrokesQueue::setSuspendResumeUpdatesStrokeStrategyFactory ( const KisSuspendResumeStrategyPairFactory & factory)

Definition at line 708 of file kis_strokes_queue.cpp.

709{
710 m_d->suspendResumeUpdatesStrokeStrategyFactory = factory;
711}

References m_d.

◆ shouldWrapInSuspendUpdatesStroke()

bool KisStrokesQueue::shouldWrapInSuspendUpdatesStroke ( )

◆ sizeMetric()

qint32 KisStrokesQueue::sizeMetric ( ) const

Definition at line 649 of file kis_strokes_queue.cpp.

650{
651 QMutexLocker locker(&m_d->mutex);
652 if(m_d->strokesQueue.isEmpty()) return 0;
653
654 // just a rough approximation
655 return qMax(1, m_d->strokesQueue.head()->numJobs()) * m_d->strokesQueue.size();
656}

References m_d.

◆ startLod0ToNStroke()

void KisStrokesQueue::startLod0ToNStroke ( int levelOfDetail,
bool forgettable )

◆ startLodNUndoStroke()

KisStrokeId KisStrokesQueue::startLodNUndoStroke ( KisStrokeStrategy * strokeStrategy)
private

Definition at line 264 of file kis_strokes_queue.cpp.

265{
266 QMutexLocker locker(&m_d->mutex);
267
268 KIS_SAFE_ASSERT_RECOVER_NOOP(!m_d->lodNNeedsSynchronization);
269 KIS_SAFE_ASSERT_RECOVER_NOOP(m_d->desiredLevelOfDetail > 0);
270
271 KisStrokeSP buddy(new KisStroke(strokeStrategy, KisStroke::LODN, m_d->desiredLevelOfDetail));
272 strokeStrategy->setMutatedJobsInterface(this, buddy);
273 m_d->strokesQueue.insert(m_d->findNewLodNPos(buddy), buddy);
274
275 KisStrokeId id(buddy);
276 m_d->openedStrokesCounter++;
277
278 return id;
279}
void setMutatedJobsInterface(KisStrokesQueueMutatedJobInterface *mutatedJobsInterface, KisStrokeId strokeId)
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130

References KIS_SAFE_ASSERT_RECOVER_NOOP, KisStroke::LODN, m_d, and KisStrokeStrategy::setMutatedJobsInterface().

◆ startStroke()

KisStrokeId KisStrokesQueue::startStroke ( KisStrokeStrategy * strokeStrategy)

Definition at line 281 of file kis_strokes_queue.cpp.

282{
283 QMutexLocker locker(&m_d->mutex);
284
285 KisStrokeSP stroke;
286 KisStrokeStrategy* lodBuddyStrategy;
287
288 // we should let forgettable strokes to queue up
289 if (!strokeStrategy->canForgetAboutMe()) {
290 m_d->cancelForgettableStrokes();
291 }
292
293 if (m_d->desiredLevelOfDetail &&
294 (m_d->lodPreferences.lodPreferred() || strokeStrategy->forceLodModeIfPossible()) &&
295 (lodBuddyStrategy =
296 strokeStrategy->createLodClone(m_d->desiredLevelOfDetail))) {
297
298 if (m_d->lodNNeedsSynchronization) {
299 m_d->startLod0ToNStroke(m_d->desiredLevelOfDetail, false);
300 }
301
302 stroke = KisStrokeSP(new KisStroke(strokeStrategy, KisStroke::LOD0, 0));
303
304 KisStrokeSP buddy(new KisStroke(lodBuddyStrategy, KisStroke::LODN, m_d->desiredLevelOfDetail));
305 lodBuddyStrategy->setMutatedJobsInterface(this, buddy);
306 stroke->setLodBuddy(buddy);
307 m_d->strokesQueue.insert(m_d->findNewLodNPos(buddy), buddy);
308
309 if (m_d->shouldWrapInSuspendUpdatesStroke()) {
310
311 KisSuspendResumePair suspendPair;
312 KisSuspendResumePair resumePair;
313 std::tie(suspendPair, resumePair) = m_d->suspendResumeUpdatesStrokeStrategyFactory();
314
315 StrokesQueueIterator it = m_d->findNewLod0Pos();
316
317 it = executeStrokePair(resumePair, m_d->strokesQueue, it, KisStroke::RESUME, 0, this);
318 it = m_d->strokesQueue.insert(it, stroke);
319 it = executeStrokePair(suspendPair, m_d->strokesQueue, it, KisStroke::SUSPEND, 0, this);
320
321 } else {
322 m_d->strokesQueue.insert(m_d->findNewLod0Pos(), stroke);
323 }
324
325 } else {
326 stroke = KisStrokeSP(new KisStroke(strokeStrategy, KisStroke::LEGACY, 0));
327 m_d->strokesQueue.enqueue(stroke);
328 }
329
330 KisStrokeId id(stroke);
331 strokeStrategy->setMutatedJobsInterface(this, id);
332
333 m_d->openedStrokesCounter++;
334
335 if (stroke->type() == KisStroke::LEGACY) {
336 m_d->lodNNeedsSynchronization = true;
337 }
338
339 return id;
340}
bool forceLodModeIfPossible() const
virtual KisStrokeStrategy * createLodClone(int levelOfDetail)
std::pair< KisStrokeStrategy *, QList< KisStrokeJobData * > > KisSuspendResumePair
QQueue< KisStrokeSP >::iterator StrokesQueueIterator
StrokesQueue::iterator executeStrokePair(const StrokePair &pair, StrokesQueue &queue, typename StrokesQueue::iterator it, KisStroke::Type type, int levelOfDetail, KisStrokesQueueMutatedJobInterface *mutatedJobsInterface)
QSharedPointer< KisStroke > KisStrokeSP
Definition kis_types.h:270

References KisStrokeStrategy::canForgetAboutMe(), KisStrokeStrategy::createLodClone(), executeStrokePair(), KisStrokeStrategy::forceLodModeIfPossible(), KisStroke::LEGACY, KisStroke::LOD0, KisStroke::LODN, m_d, KisStroke::RESUME, KisStrokeStrategy::setMutatedJobsInterface(), and KisStroke::SUSPEND.

◆ switchDesiredLevelOfDetail()

void KisStrokesQueue::switchDesiredLevelOfDetail ( bool forced)

◆ tryCancelCurrentStrokeAsync()

bool KisStrokesQueue::tryCancelCurrentStrokeAsync ( )

We cancel only ended strokes. This is done to avoid handling dangling pointers problem (KisStrokeId). The owner of a stroke will cancel the stroke itself if needed.

1) We can cancel only cancellable strokes 2) We can only cancel a continuous set of strokes

Basically, a non-cancellable stroke adds a barrier wall into the strokes queue, preventing cancellation of any strokes that we added into the queue earlier.

If the buddy has already finished, we cannot undo it because it doesn't store any undo data. Therefore we just regenerate the LOD caches.

NOTE: We do not touch the openedStrokesCounter here since we work with closed id's only here

Definition at line 414 of file kis_strokes_queue.cpp.

415{
416 bool anythingCanceled = false;
417
418 QMutexLocker locker(&m_d->mutex);
419
425 if (!m_d->strokesQueue.isEmpty() &&
426 !m_d->hasUnfinishedStrokes()) {
427
436 const auto lastNonCancellableStrokeIt =
437 std::find_if_not(std::make_reverse_iterator(m_d->strokesQueue.end()),
438 std::make_reverse_iterator(m_d->strokesQueue.begin()),
440
441 bool needsLodNSynchronization = false;
442
443 for (auto it = lastNonCancellableStrokeIt.base(); it != m_d->strokesQueue.end(); it++) {
444 KisStrokeSP currentStroke = *it;
445 KIS_ASSERT_RECOVER_NOOP(currentStroke->isEnded());
446 KIS_ASSERT_RECOVER_NOOP(currentStroke->isAsynchronouslyCancellable());
447
448 currentStroke->cancelStroke();
449 anythingCanceled = true;
450
451 // we shouldn't cancel buddies...
452 if (currentStroke->type() == KisStroke::LOD0) {
458 needsLodNSynchronization = true;
459 }
460
461 }
462
463 if (needsLodNSynchronization) {
464 m_d->forceResetLodAndCloseCurrentLodRange();
465 }
466 }
467
473 return anythingCanceled;
474}
bool isAsynchronouslyCancellable() const
#define KIS_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:97

References KisStroke::isAsynchronouslyCancellable(), KIS_ASSERT_RECOVER_NOOP, KisStroke::LOD0, and m_d.

◆ tryClearUndoOnStrokeCompletion()

void KisStrokesQueue::tryClearUndoOnStrokeCompletion ( KisStrokeSP finishingStroke)

◆ tryUndoLastStrokeAsync()

UndoResult KisStrokesQueue::tryUndoLastStrokeAsync ( )

Definition at line 476 of file kis_strokes_queue.cpp.

477{
478 UndoResult result = UNDO_FAIL;
479
480 QMutexLocker locker(&m_d->mutex);
481
482 KisStrokeSP lastStroke;
483 KisStrokeSP lastBuddy;
484 bool buddyFound = false;
485
486 for (auto it = std::make_reverse_iterator(m_d->strokesQueue.constEnd());
487 it != std::make_reverse_iterator(m_d->strokesQueue.constBegin());
488 ++it) {
489
490 if ((*it)->type() == KisStroke::LEGACY) {
491 break;
492 }
493
494 if (!lastStroke && (*it)->type() == KisStroke::LOD0 && !(*it)->isCancelled()) {
495 lastStroke = *it;
496 lastBuddy = lastStroke->lodBuddy();
497
498 KIS_SAFE_ASSERT_RECOVER(lastBuddy) {
499 lastStroke.clear();
500 lastBuddy.clear();
501 break;
502 }
503 }
504
505 KIS_SAFE_ASSERT_RECOVER(!lastStroke || *it == lastBuddy || (*it)->type() != KisStroke::LODN) {
506 lastStroke.clear();
507 lastBuddy.clear();
508 break;
509 }
510
511 if (lastStroke && *it == lastBuddy) {
512 KIS_SAFE_ASSERT_RECOVER(lastBuddy->type() == KisStroke::LODN) {
513 lastStroke.clear();
514 lastBuddy.clear();
515 break;
516 }
517 buddyFound = true;
518 break;
519 }
520 }
521
522 if (!lastStroke) return UNDO_FAIL;
523 if (!lastStroke->isEnded()) return UNDO_FAIL;
524 if (lastStroke->isCancelled()) return UNDO_FAIL;
525
526 KIS_SAFE_ASSERT_RECOVER_NOOP(!buddyFound ||
527 lastStroke->isCancelled() == lastBuddy->isCancelled());
528 KIS_SAFE_ASSERT_RECOVER_NOOP(lastBuddy->isEnded());
529
530 if (!lastStroke->canCancel()) {
531 return UNDO_WAIT;
532 }
533 lastStroke->cancelStroke();
534
535 if (buddyFound && lastBuddy->canCancel()) {
536 lastBuddy->cancelStroke();
537 } else {
538 // TODO: assert that checks that there is no other lodn strokes
539 locker.unlock();
540 m_d->lodNUndoStore.undo();
541 m_d->lodNUndoStore.purgeRedoState();
542 locker.relock();
543 }
544
545 result = UNDO_OK;
546
547 return result;
548}
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126

References KIS_SAFE_ASSERT_RECOVER, KIS_SAFE_ASSERT_RECOVER_NOOP, KisStroke::LEGACY, KisStroke::LOD0, KisStroke::LODN, m_d, UNDO_FAIL, UNDO_OK, and UNDO_WAIT.

◆ wrapAroundModeSupported()

bool KisStrokesQueue::wrapAroundModeSupported ( ) const

Member Data Documentation

◆ balancingRatioOverride

qreal KisStrokesQueue::balancingRatioOverride

Definition at line 81 of file kis_strokes_queue.cpp.

◆ currentStrokeLoaded

bool KisStrokesQueue::currentStrokeLoaded

Definition at line 82 of file kis_strokes_queue.cpp.

◆ desiredLevelOfDetail

int KisStrokesQueue::desiredLevelOfDetail

Definition at line 85 of file kis_strokes_queue.cpp.

◆ lod0ToNStrokeStrategyFactory

KisLodSyncStrokeStrategyFactory KisStrokesQueue::lod0ToNStrokeStrategyFactory

Definition at line 88 of file kis_strokes_queue.cpp.

◆ lodNNeedsSynchronization

bool KisStrokesQueue::lodNNeedsSynchronization

Definition at line 84 of file kis_strokes_queue.cpp.

◆ lodNPostExecutionUndoAdapter

KisPostExecutionUndoAdapter * KisStrokesQueue::lodNPostExecutionUndoAdapter

Definition at line 94 of file kis_strokes_queue.cpp.

◆ lodNStrokesFacade

LodNUndoStrokesFacade KisStrokesQueue::lodNStrokesFacade

Definition at line 93 of file kis_strokes_queue.cpp.

◆ lodNUndoStore

KisSurrogateUndoStore KisStrokesQueue::lodNUndoStore

Definition at line 92 of file kis_strokes_queue.cpp.

◆ lodPreferences

KisLodPreferences KisStrokesQueue::lodPreferences

The desired level of detail might have not been activated due to multi-stage activation process

Definition at line 95 of file kis_strokes_queue.cpp.

◆ m_d

Private* const KisStrokesQueue::m_d
private

Definition at line 93 of file kis_strokes_queue.h.

◆ mutex

QMutex KisStrokesQueue::mutex

Definition at line 87 of file kis_strokes_queue.cpp.

◆ needsExclusiveAccess

bool KisStrokesQueue::needsExclusiveAccess

Definition at line 79 of file kis_strokes_queue.cpp.

◆ nextDesiredLevelOfDetail

int KisStrokesQueue::nextDesiredLevelOfDetail

Definition at line 86 of file kis_strokes_queue.cpp.

◆ openedStrokesCounter

int KisStrokesQueue::openedStrokesCounter

Definition at line 78 of file kis_strokes_queue.cpp.

◆ postSyncLod0GUIPlaneRequestForResume

std::function<void()> KisStrokesQueue::postSyncLod0GUIPlaneRequestForResume

Definition at line 91 of file kis_strokes_queue.cpp.

◆ purgeRedoStateCallback

std::function<void()> KisStrokesQueue::purgeRedoStateCallback

Definition at line 90 of file kis_strokes_queue.cpp.

◆ q

KisStrokesQueue* KisStrokesQueue::q

Definition at line 76 of file kis_strokes_queue.cpp.

◆ strokesQueue

StrokesQueue KisStrokesQueue::strokesQueue

Definition at line 77 of file kis_strokes_queue.cpp.

◆ suspendResumeUpdatesStrokeStrategyFactory

KisSuspendResumeStrategyPairFactory KisStrokesQueue::suspendResumeUpdatesStrokeStrategyFactory

Definition at line 89 of file kis_strokes_queue.cpp.

◆ wrapAroundModeSupported

bool KisStrokesQueue::wrapAroundModeSupported

Definition at line 80 of file kis_strokes_queue.cpp.


The documentation for this class was generated from the following files: