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

#include <kis_simple_update_queue.h>

+ Inheritance diagram for KisSimpleUpdateQueue:

Public Member Functions

void addFullRefreshJob (KisNodeSP node, const QRect &rc, const QRect &cropRect, int levelOfDetail)
 
void addFullRefreshJob (KisNodeSP node, const QVector< QRect > &rects, const QRect &cropRect, int levelOfDetail, KisProjectionUpdateFlags flags)
 
void addSpontaneousJob (KisSpontaneousJob *spontaneousJob)
 
void addUpdateJob (KisNodeSP node, const QRect &rc, const QRect &cropRect, int levelOfDetail)
 
void addUpdateJob (KisNodeSP node, const QVector< QRect > &rects, const QRect &cropRect, int levelOfDetail, KisProjectionUpdateFlags flags)
 
bool isEmpty () const
 
 KisSimpleUpdateQueue ()
 
void optimize ()
 
int overrideLevelOfDetail () const
 
void processQueue (KisUpdaterContext &updaterContext)
 
qint32 sizeMetric () const
 
void updateSettings ()
 
virtual ~KisSimpleUpdateQueue ()
 

Protected Member Functions

void addJob (KisNodeSP node, const QVector< QRect > &rects, const QRect &cropRect, int levelOfDetail, KisBaseRectsWalker::UpdateType type, bool dontInvalidateFrames)
 
void collectJobs (KisBaseRectsWalkerSP &baseWalker, QRect baseRect, const qreal maxAlpha)
 
bool joinRects (QRect &baseRect, const QRect &newRect, qreal maxAlpha)
 
bool processOneJob (KisUpdaterContext &updaterContext)
 
bool tryMergeJob (KisNodeSP node, const QRect &rc, const QRect &cropRect, int levelOfDetail, KisBaseRectsWalker::UpdateType type, bool dontInvalidateFrames)
 
bool trySplitJob (KisNodeSP node, const QRect &rc, const QRect &cropRect, int levelOfDetail, KisBaseRectsWalker::UpdateType type, bool dontInvalidateFrames)
 

Protected Attributes

QMutex m_lock
 
qreal m_maxCollectAlpha
 
qreal m_maxMergeAlpha
 
qreal m_maxMergeCollectAlpha
 
int m_overrideLevelOfDetail
 
qint32 m_patchHeight
 
qint32 m_patchWidth
 
KisSpontaneousJobsList m_spontaneousJobsList
 
KisWalkersList m_updatesList
 

Detailed Description

Definition at line 23 of file kis_simple_update_queue.h.

Constructor & Destructor Documentation

◆ KisSimpleUpdateQueue()

KisSimpleUpdateQueue::KisSimpleUpdateQueue ( )

◆ ~KisSimpleUpdateQueue()

KisSimpleUpdateQueue::~KisSimpleUpdateQueue ( )
virtual

Definition at line 50 of file kis_simple_update_queue.cpp.

51{
52 QMutexLocker locker(&m_lock);
53
54 while (!m_spontaneousJobsList.isEmpty()) {
55 delete m_spontaneousJobsList.takeLast();
56 }
57}
KisSpontaneousJobsList m_spontaneousJobsList

References m_lock, and m_spontaneousJobsList.

Member Function Documentation

◆ addFullRefreshJob() [1/2]

void KisSimpleUpdateQueue::addFullRefreshJob ( KisNodeSP node,
const QRect & rc,
const QRect & cropRect,
int levelOfDetail )

Definition at line 178 of file kis_simple_update_queue.cpp.

179{
180 addFullRefreshJob(node, {rc}, cropRect, levelOfDetail, KisProjectionUpdateFlag::None);
181}
void addFullRefreshJob(KisNodeSP node, const QVector< QRect > &rects, const QRect &cropRect, int levelOfDetail, KisProjectionUpdateFlags flags)

References addFullRefreshJob(), and None.

◆ addFullRefreshJob() [2/2]

void KisSimpleUpdateQueue::addFullRefreshJob ( KisNodeSP node,
const QVector< QRect > & rects,
const QRect & cropRect,
int levelOfDetail,
KisProjectionUpdateFlags flags )

Definition at line 161 of file kis_simple_update_queue.cpp.

162{
164 !flags.testFlag(KisProjectionUpdateFlag::NoFilthy) ?
167
168 addJob(node, rects, cropRect, levelOfDetail,
169 type,
171}
void addJob(KisNodeSP node, const QVector< QRect > &rects, const QRect &cropRect, int levelOfDetail, KisBaseRectsWalker::UpdateType type, bool dontInvalidateFrames)

References addJob(), DontInvalidateFrames, KisBaseRectsWalker::FULL_REFRESH, KisBaseRectsWalker::FULL_REFRESH_NO_FILTHY, and NoFilthy.

◆ addJob()

void KisSimpleUpdateQueue::addJob ( KisNodeSP node,
const QVector< QRect > & rects,
const QRect & cropRect,
int levelOfDetail,
KisBaseRectsWalker::UpdateType type,
bool dontInvalidateFrames )
protected

Definition at line 183 of file kis_simple_update_queue.cpp.

188{
190
191 Q_FOREACH (const QRect &rc, rects) {
192 if (rc.isEmpty()) continue;
193
195
196 if(trySplitJob(node, rc, cropRect, levelOfDetail, type, dontInvalidateFrames)) continue;
197 if(tryMergeJob(node, rc, cropRect, levelOfDetail, type, dontInvalidateFrames)) continue;
198
199 if (type == KisBaseRectsWalker::UPDATE) {
200 KisMergeWalker::Flags flags = KisMergeWalker::DEFAULT;
201 if (dontInvalidateFrames) {
203 }
204
205 walker = new KisMergeWalker(cropRect, flags);
206 }
207 else if (type == KisBaseRectsWalker::FULL_REFRESH) {
208 KisFullRefreshWalker::Flags flags = KisFullRefreshWalker::None;
209 if (dontInvalidateFrames) {
211 }
212
213 walker = new KisFullRefreshWalker(cropRect, flags);
214 }
215 else if (type == KisBaseRectsWalker::UPDATE_NO_FILTHY) {
216 KisMergeWalker::Flags flags = KisMergeWalker::NO_FILTHY;
217 if (dontInvalidateFrames) {
219 }
220
221 walker = new KisMergeWalker(cropRect, flags);
222 }
224 KisFullRefreshWalker::Flags flags = KisFullRefreshWalker::NoFilthyMode;
225 if (dontInvalidateFrames) {
227 }
228
230 }
231 /* else if(type == KisBaseRectsWalker::UNSUPPORTED) fatalKrita; */
232
233 walker->collectRects(node, rc);
234 walkers.append(walker);
235 }
236
237 if (!walkers.isEmpty()) {
238 m_lock.lock();
239 m_updatesList.append(walkers);
240 m_lock.unlock();
241 }
242}
void collectRects(KisNodeSP node, const QRect &requestedRect)
bool tryMergeJob(KisNodeSP node, const QRect &rc, const QRect &cropRect, int levelOfDetail, KisBaseRectsWalker::UpdateType type, bool dontInvalidateFrames)
bool trySplitJob(KisNodeSP node, const QRect &rc, const QRect &cropRect, int levelOfDetail, KisBaseRectsWalker::UpdateType type, bool dontInvalidateFrames)

References KisMergeWalker::CLONES_DONT_INVALIDATE_FRAMES, KisRefreshSubtreeWalker::ClonesDontInvalidateFrames, KisBaseRectsWalker::collectRects(), KisMergeWalker::DEFAULT, KisBaseRectsWalker::FULL_REFRESH, KisBaseRectsWalker::FULL_REFRESH_NO_FILTHY, m_lock, m_updatesList, KisMergeWalker::NO_FILTHY, KisBaseRectsWalker::NoFilthyMode, KisBaseRectsWalker::None, tryMergeJob(), trySplitJob(), KisBaseRectsWalker::UPDATE, and KisBaseRectsWalker::UPDATE_NO_FILTHY.

◆ addSpontaneousJob()

void KisSimpleUpdateQueue::addSpontaneousJob ( KisSpontaneousJob * spontaneousJob)

Definition at line 244 of file kis_simple_update_queue.cpp.

245{
246 QMutexLocker locker(&m_lock);
247
248 KisSpontaneousJob *item;
250
251 iter.toBack();
252
253 while(iter.hasPrevious()) {
254 item = iter.previous();
255
256 if (spontaneousJob->overrides(item)) {
257 iter.remove();
258 delete item;
259 }
260 }
261
262 m_spontaneousJobsList.append(spontaneousJob);
263}
virtual bool overrides(const KisSpontaneousJob *otherJob)=0
QMutableListIterator< KisSpontaneousJob * > KisMutableSpontaneousJobsListIterator

References m_lock, m_spontaneousJobsList, and KisSpontaneousJob::overrides().

◆ addUpdateJob() [1/2]

void KisSimpleUpdateQueue::addUpdateJob ( KisNodeSP node,
const QRect & rc,
const QRect & cropRect,
int levelOfDetail )

Definition at line 173 of file kis_simple_update_queue.cpp.

174{
175 addUpdateJob(node, {rc}, cropRect, levelOfDetail, KisProjectionUpdateFlag::None);
176}
void addUpdateJob(KisNodeSP node, const QVector< QRect > &rects, const QRect &cropRect, int levelOfDetail, KisProjectionUpdateFlags flags)

References addUpdateJob(), and None.

◆ addUpdateJob() [2/2]

void KisSimpleUpdateQueue::addUpdateJob ( KisNodeSP node,
const QVector< QRect > & rects,
const QRect & cropRect,
int levelOfDetail,
KisProjectionUpdateFlags flags )

◆ collectJobs()

void KisSimpleUpdateQueue::collectJobs ( KisBaseRectsWalkerSP & baseWalker,
QRect baseRect,
const qreal maxAlpha )
protected

Definition at line 365 of file kis_simple_update_queue.cpp.

368{
371
372 while(iter.hasNext()) {
373 item = iter.next();
374
375 if(item == baseWalker) continue;
376 if(item->type() != baseWalker->type()) continue;
377 if(item->startNode() != baseWalker->startNode()) continue;
378 if(item->clonesDontInvalidateFrames() != baseWalker->clonesDontInvalidateFrames()) continue;
379 if(item->cropRect() != baseWalker->cropRect()) continue;
380 if(item->levelOfDetail() != baseWalker->levelOfDetail()) continue;
381
382 if(joinRects(baseRect, item->requestedRect(), maxAlpha)) {
383 iter.remove();
384 }
385 }
386
387 if(baseWalker->requestedRect() != baseRect) {
388 baseWalker->collectRects(baseWalker->startNode(), baseRect);
389 }
390}
bool clonesDontInvalidateFrames() const
virtual UpdateType type() const =0
KisNodeSP startNode() const
bool joinRects(QRect &baseRect, const QRect &newRect, qreal maxAlpha)
QMutableListIterator< KisBaseRectsWalkerSP > KisMutableWalkersListIterator

References KisBaseRectsWalker::clonesDontInvalidateFrames(), KisBaseRectsWalker::collectRects(), KisBaseRectsWalker::cropRect(), joinRects(), KisBaseRectsWalker::levelOfDetail(), m_updatesList, KisBaseRectsWalker::requestedRect(), KisBaseRectsWalker::startNode(), and KisBaseRectsWalker::type().

◆ isEmpty()

bool KisSimpleUpdateQueue::isEmpty ( ) const

Definition at line 265 of file kis_simple_update_queue.cpp.

266{
267 QMutexLocker locker(&m_lock);
268 return m_updatesList.isEmpty() && m_spontaneousJobsList.isEmpty();
269}

References m_lock, m_spontaneousJobsList, and m_updatesList.

◆ joinRects()

bool KisSimpleUpdateQueue::joinRects ( QRect & baseRect,
const QRect & newRect,
qreal maxAlpha )
protected

Definition at line 392 of file kis_simple_update_queue.cpp.

394{
395 QRect unitedRect = baseRect | newRect;
396 if(unitedRect.width() > m_patchWidth || unitedRect.height() > m_patchHeight)
397 return false;
398
399 bool result = false;
400 qint64 baseWork = qint64(baseRect.width()) * baseRect.height() +
401 qint64(newRect.width()) * newRect.height();
402
403 qint64 newWork = qint64(unitedRect.width()) * unitedRect.height();
404
405 qreal alpha = qreal(newWork) / baseWork;
406
407 if(alpha < maxAlpha) {
408 DEBUG_JOIN(baseRect, newRect, alpha);
409
411 ACCUMULATOR_ADD(baseWork, newWork);
413
414 baseRect = unitedRect;
415 result = true;
416 }
417
418 return result;
419}
#define DECLARE_ACCUMULATOR()
#define ACCUMULATOR_ADD(baseAmount, newAmount)
#define DEBUG_JOIN(baseRect, newRect, alpha)
#define ACCUMULATOR_DEBUG()

References ACCUMULATOR_ADD, ACCUMULATOR_DEBUG, DEBUG_JOIN, DECLARE_ACCUMULATOR, m_patchHeight, and m_patchWidth.

◆ optimize()

void KisSimpleUpdateQueue::optimize ( )

Definition at line 353 of file kis_simple_update_queue.cpp.

354{
355 QMutexLocker locker(&m_lock);
356
357 if(m_updatesList.size() <= 1) return;
358
359 KisBaseRectsWalkerSP baseWalker = m_updatesList.first();
360 QRect baseRect = baseWalker->requestedRect();
361
362 collectJobs(baseWalker, baseRect, m_maxCollectAlpha);
363}
void collectJobs(KisBaseRectsWalkerSP &baseWalker, QRect baseRect, const qreal maxAlpha)

References collectJobs(), m_lock, m_maxCollectAlpha, m_updatesList, and KisBaseRectsWalker::requestedRect().

◆ overrideLevelOfDetail()

int KisSimpleUpdateQueue::overrideLevelOfDetail ( ) const

Definition at line 73 of file kis_simple_update_queue.cpp.

74{
76}

References m_overrideLevelOfDetail.

◆ processOneJob()

bool KisSimpleUpdateQueue::processOneJob ( KisUpdaterContext & updaterContext)
protected

WARNING: Please note that this still doesn't guarantee that the spontaneous jobs are exclusive, since updates and/or strokes can be added after them. The only thing it guarantees that two spontaneous jobs will not be executed in parallel.

Right now it works as it is. Probably will need to be fixed in the future.

Definition at line 88 of file kis_simple_update_queue.cpp.

89{
90 QMutexLocker locker(&m_lock);
91
94 bool jobAdded = false;
95
96 int currentLevelOfDetail = updaterContext.currentLevelOfDetail();
97
98 while(iter.hasNext()) {
99 item = iter.next();
100
101 if ((currentLevelOfDetail < 0 || currentLevelOfDetail == item->levelOfDetail()) &&
102 !item->checksumValid()) {
103
105 item->recalculate(item->requestedRect());
107 }
108
109 if ((currentLevelOfDetail < 0 || currentLevelOfDetail == item->levelOfDetail()) &&
110 updaterContext.isJobAllowed(item)) {
111
112 updaterContext.addMergeJob(item);
113 iter.remove();
114 jobAdded = true;
115 break;
116 }
117 }
118
119 if (jobAdded) return true;
120
121 if (!m_spontaneousJobsList.isEmpty()) {
132 qint32 numMergeJobs;
133 qint32 numStrokeJobs;
134 updaterContext.getJobsSnapshot(numMergeJobs, numStrokeJobs);
135
137 if (!numMergeJobs && !numStrokeJobs &&
138 (currentLevelOfDetail < 0 || currentLevelOfDetail == job->levelOfDetail())) {
139
140 updaterContext.addSpontaneousJob(job);
141 m_spontaneousJobsList.removeFirst();
142 jobAdded = true;
143 }
144 }
145
146 return jobAdded;
147}
void recalculate(const QRect &requestedRect)
void getJobsSnapshot(qint32 &numMergeJobs, qint32 &numStrokeJobs)
bool isJobAllowed(KisBaseRectsWalkerSP walker)
void addMergeJob(KisBaseRectsWalkerSP walker)
void addSpontaneousJob(KisSpontaneousJob *spontaneousJob)

References KisUpdaterContext::addMergeJob(), KisUpdaterContext::addSpontaneousJob(), KisBaseRectsWalker::checksumValid(), KisUpdaterContext::currentLevelOfDetail(), KisUpdaterContext::getJobsSnapshot(), KisUpdaterContext::isJobAllowed(), KisBaseRectsWalker::levelOfDetail(), m_lock, m_overrideLevelOfDetail, m_spontaneousJobsList, m_updatesList, KisBaseRectsWalker::recalculate(), and KisBaseRectsWalker::requestedRect().

◆ processQueue()

void KisSimpleUpdateQueue::processQueue ( KisUpdaterContext & updaterContext)

Definition at line 78 of file kis_simple_update_queue.cpp.

79{
80 updaterContext.lock();
81
82 while(updaterContext.hasSpareThread() &&
83 processOneJob(updaterContext));
84
85 updaterContext.unlock();
86}
bool processOneJob(KisUpdaterContext &updaterContext)

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

◆ sizeMetric()

qint32 KisSimpleUpdateQueue::sizeMetric ( ) const

Definition at line 271 of file kis_simple_update_queue.cpp.

272{
273 QMutexLocker locker(&m_lock);
274 return m_updatesList.size() + m_spontaneousJobsList.size();
275}

References m_lock, m_spontaneousJobsList, and m_updatesList.

◆ tryMergeJob()

bool KisSimpleUpdateQueue::tryMergeJob ( KisNodeSP node,
const QRect & rc,
const QRect & cropRect,
int levelOfDetail,
KisBaseRectsWalker::UpdateType type,
bool dontInvalidateFrames )
protected

We add new jobs to the tail of the list, so it's more probable to find a good candidate here.

Definition at line 311 of file kis_simple_update_queue.cpp.

316{
317 QMutexLocker locker(&m_lock);
318
319 QRect baseRect = rc;
320
321 KisBaseRectsWalkerSP goodCandidate;
324
330 iter.toBack();
331
332 while(iter.hasPrevious()) {
333 item = iter.previous();
334
335 if(item->startNode() != node) continue;
336 if(item->type() != type) continue;
337 if(item->clonesDontInvalidateFrames() != dontInvalidateFrames) continue;
338 if(item->cropRect() != cropRect) continue;
339 if(item->levelOfDetail() != levelOfDetail) continue;
340
341 if(joinRects(baseRect, item->requestedRect(), m_maxMergeAlpha)) {
342 goodCandidate = item;
343 break;
344 }
345 }
346
347 if(goodCandidate)
348 collectJobs(goodCandidate, baseRect, m_maxMergeCollectAlpha);
349
350 return (bool)goodCandidate;
351}
QListIterator< KisBaseRectsWalkerSP > KisWalkersListIterator

References KisBaseRectsWalker::clonesDontInvalidateFrames(), collectJobs(), KisBaseRectsWalker::cropRect(), joinRects(), KisBaseRectsWalker::levelOfDetail(), m_lock, m_maxMergeAlpha, m_maxMergeCollectAlpha, m_updatesList, KisBaseRectsWalker::requestedRect(), KisBaseRectsWalker::startNode(), and KisBaseRectsWalker::type().

◆ trySplitJob()

bool KisSimpleUpdateQueue::trySplitJob ( KisNodeSP node,
const QRect & rc,
const QRect & cropRect,
int levelOfDetail,
KisBaseRectsWalker::UpdateType type,
bool dontInvalidateFrames )
protected

Definition at line 277 of file kis_simple_update_queue.cpp.

282{
283 if(rc.width() <= m_patchWidth || rc.height() <= m_patchHeight)
284 return false;
285
286 // a bit of recursive splitting...
287
288 qint32 firstCol = rc.x() / m_patchWidth;
289 qint32 firstRow = rc.y() / m_patchHeight;
290
291 qint32 lastCol = (rc.x() + rc.width()) / m_patchWidth;
292 qint32 lastRow = (rc.y() + rc.height()) / m_patchHeight;
293
295
296 for(qint32 i = firstRow; i <= lastRow; i++) {
297 for(qint32 j = firstCol; j <= lastCol; j++) {
298 QRect maxPatchRect(j * m_patchWidth, i * m_patchHeight,
300 QRect patchRect = rc & maxPatchRect;
301 splitRects.append(patchRect);
302 }
303 }
304
306 addJob(node, splitRects, cropRect, levelOfDetail, type, dontInvalidateFrames);
307
308 return true;
309}
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
Definition kis_assert.h:130
void splitRects(QVector< QRect >::iterator beginIt, QVector< QRect >::iterator endIt, OutIt resultIt, QVector< QRect > tempBuf[2], int gridSize, RowMergeOp rowMergeOp)

References addJob(), KIS_SAFE_ASSERT_RECOVER_NOOP, m_patchHeight, and m_patchWidth.

◆ updateSettings()

void KisSimpleUpdateQueue::updateSettings ( )

Definition at line 59 of file kis_simple_update_queue.cpp.

60{
61 QMutexLocker locker(&m_lock);
62
63 KisImageConfig config(true);
64
65 m_patchWidth = config.updatePatchWidth();
66 m_patchHeight = config.updatePatchHeight();
67
68 m_maxCollectAlpha = config.maxCollectAlpha();
69 m_maxMergeAlpha = config.maxMergeAlpha();
70 m_maxMergeCollectAlpha = config.maxMergeCollectAlpha();
71}

References m_lock, m_maxCollectAlpha, m_maxMergeAlpha, m_maxMergeCollectAlpha, m_patchHeight, m_patchWidth, KisImageConfig::maxCollectAlpha(), KisImageConfig::maxMergeAlpha(), KisImageConfig::maxMergeCollectAlpha(), KisImageConfig::updatePatchHeight(), and KisImageConfig::updatePatchWidth().

Member Data Documentation

◆ m_lock

QMutex KisSimpleUpdateQueue::m_lock
mutableprotected

Definition at line 66 of file kis_simple_update_queue.h.

◆ m_maxCollectAlpha

qreal KisSimpleUpdateQueue::m_maxCollectAlpha
protected

Maximum coefficient of work while regular optimization()

Definition at line 86 of file kis_simple_update_queue.h.

◆ m_maxMergeAlpha

qreal KisSimpleUpdateQueue::m_maxMergeAlpha
protected

Maximum coefficient of work when to rects are considered similar and are merged in tryMergeJob()

Definition at line 92 of file kis_simple_update_queue.h.

◆ m_maxMergeCollectAlpha

qreal KisSimpleUpdateQueue::m_maxMergeCollectAlpha
protected

The coefficient of work used while collecting phase of tryToMerge()

Definition at line 97 of file kis_simple_update_queue.h.

◆ m_overrideLevelOfDetail

int KisSimpleUpdateQueue::m_overrideLevelOfDetail
protected

Definition at line 99 of file kis_simple_update_queue.h.

◆ m_patchHeight

qint32 KisSimpleUpdateQueue::m_patchHeight
protected

Definition at line 81 of file kis_simple_update_queue.h.

◆ m_patchWidth

qint32 KisSimpleUpdateQueue::m_patchWidth
protected

Parameters of optimization (loaded from a configuration file) Big update areas are split into a set of smaller ones, m_patchWidth and m_patchHeight represent the size of these areas.

Definition at line 80 of file kis_simple_update_queue.h.

◆ m_spontaneousJobsList

KisSpontaneousJobsList KisSimpleUpdateQueue::m_spontaneousJobsList
protected

Definition at line 68 of file kis_simple_update_queue.h.

◆ m_updatesList

KisWalkersList KisSimpleUpdateQueue::m_updatesList
protected

Definition at line 67 of file kis_simple_update_queue.h.


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