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
 
bool isIdle () 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 if (!walker->isEmpty()) {
235 walkers.append(walker);
236 }
237 }
238
239 if (!walkers.isEmpty()) {
240 m_lock.lock();
241 m_updatesList.append(walkers);
242 m_lock.unlock();
243 }
244}
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, KisBaseRectsWalker::isEmpty(), 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 246 of file kis_simple_update_queue.cpp.

247{
248 QMutexLocker locker(&m_lock);
249
250 KisSpontaneousJob *item;
252
253 iter.toBack();
254
255 while(iter.hasPrevious()) {
256 item = iter.previous();
257
258 if (spontaneousJob->overrides(item)) {
259 iter.remove();
260 delete item;
261 }
262 }
263
264 m_spontaneousJobsList.append(spontaneousJob);
265}
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 374 of file kis_simple_update_queue.cpp.

377{
380
381 while(iter.hasNext()) {
382 item = iter.next();
383
384 if(item == baseWalker) continue;
385 if(item->type() != baseWalker->type()) continue;
386 if(item->startNode() != baseWalker->startNode()) continue;
387 if(item->clonesDontInvalidateFrames() != baseWalker->clonesDontInvalidateFrames()) continue;
388 if(item->cropRect() != baseWalker->cropRect()) continue;
389 if(item->levelOfDetail() != baseWalker->levelOfDetail()) continue;
390
391 if(joinRects(baseRect, item->requestedRect(), maxAlpha)) {
392 iter.remove();
393 }
394 }
395
396 if(baseWalker->requestedRect() != baseRect) {
397 baseWalker->collectRects(baseWalker->startNode(), baseRect);
398 }
399}
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

Returns true if the update queue is empty, i.e. there are no update or spontaneous jobs pending

Definition at line 267 of file kis_simple_update_queue.cpp.

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

References m_lock, m_spontaneousJobsList, and m_updatesList.

◆ isIdle()

bool KisSimpleUpdateQueue::isIdle ( ) const

Works in the same way as isEmpty(), except that it will not wait on the mutex in case there is any contestion on the queue.

If some other threads are contending on the queue, it will just return false, whatever the state of the queue is.

Definition at line 273 of file kis_simple_update_queue.cpp.

274{
275 std::unique_lock<QMutex> locker(m_lock, std::try_to_lock);
276 if (!locker.owns_lock()) return false;
277 return m_updatesList.isEmpty() && m_spontaneousJobsList.isEmpty();
278}

References m_lock, m_spontaneousJobsList, and m_updatesList.

◆ joinRects()

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

Definition at line 401 of file kis_simple_update_queue.cpp.

403{
404 QRect unitedRect = baseRect | newRect;
405 if(unitedRect.width() > m_patchWidth || unitedRect.height() > m_patchHeight)
406 return false;
407
408 bool result = false;
409 qint64 baseWork = qint64(baseRect.width()) * baseRect.height() +
410 qint64(newRect.width()) * newRect.height();
411
412 qint64 newWork = qint64(unitedRect.width()) * unitedRect.height();
413
414 qreal alpha = qreal(newWork) / baseWork;
415
416 if(alpha < maxAlpha) {
417 DEBUG_JOIN(baseRect, newRect, alpha);
418
420 ACCUMULATOR_ADD(baseWork, newWork);
422
423 baseRect = unitedRect;
424 result = true;
425 }
426
427 return result;
428}
#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 362 of file kis_simple_update_queue.cpp.

363{
364 QMutexLocker locker(&m_lock);
365
366 if(m_updatesList.size() <= 1) return;
367
368 KisBaseRectsWalkerSP baseWalker = m_updatesList.first();
369 QRect baseRect = baseWalker->requestedRect();
370
371 collectJobs(baseWalker, baseRect, m_maxCollectAlpha);
372}
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 280 of file kis_simple_update_queue.cpp.

281{
282 QMutexLocker locker(&m_lock);
283 return m_updatesList.size() + m_spontaneousJobsList.size();
284}

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 320 of file kis_simple_update_queue.cpp.

325{
326 QMutexLocker locker(&m_lock);
327
328 QRect baseRect = rc;
329
330 KisBaseRectsWalkerSP goodCandidate;
333
339 iter.toBack();
340
341 while(iter.hasPrevious()) {
342 item = iter.previous();
343
344 if(item->startNode() != node) continue;
345 if(item->type() != type) continue;
346 if(item->clonesDontInvalidateFrames() != dontInvalidateFrames) continue;
347 if(item->cropRect() != cropRect) continue;
348 if(item->levelOfDetail() != levelOfDetail) continue;
349
350 if(joinRects(baseRect, item->requestedRect(), m_maxMergeAlpha)) {
351 goodCandidate = item;
352 break;
353 }
354 }
355
356 if(goodCandidate)
357 collectJobs(goodCandidate, baseRect, m_maxMergeCollectAlpha);
358
359 return (bool)goodCandidate;
360}
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 286 of file kis_simple_update_queue.cpp.

291{
292 if(rc.width() <= m_patchWidth || rc.height() <= m_patchHeight)
293 return false;
294
295 // a bit of recursive splitting...
296
297 qint32 firstCol = rc.x() / m_patchWidth;
298 qint32 firstRow = rc.y() / m_patchHeight;
299
300 qint32 lastCol = (rc.x() + rc.width()) / m_patchWidth;
301 qint32 lastRow = (rc.y() + rc.height()) / m_patchHeight;
302
304
305 for(qint32 i = firstRow; i <= lastRow; i++) {
306 for(qint32 j = firstCol; j <= lastCol; j++) {
307 QRect maxPatchRect(j * m_patchWidth, i * m_patchHeight,
309 QRect patchRect = rc & maxPatchRect;
310 splitRects.append(patchRect);
311 }
312 }
313
315 addJob(node, splitRects, cropRect, levelOfDetail, type, dontInvalidateFrames);
316
317 return true;
318}
#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 80 of file kis_simple_update_queue.h.

◆ m_maxCollectAlpha

qreal KisSimpleUpdateQueue::m_maxCollectAlpha
protected

Maximum coefficient of work while regular optimization()

Definition at line 100 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 106 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 111 of file kis_simple_update_queue.h.

◆ m_overrideLevelOfDetail

int KisSimpleUpdateQueue::m_overrideLevelOfDetail
protected

Definition at line 113 of file kis_simple_update_queue.h.

◆ m_patchHeight

qint32 KisSimpleUpdateQueue::m_patchHeight
protected

Definition at line 95 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 94 of file kis_simple_update_queue.h.

◆ m_spontaneousJobsList

KisSpontaneousJobsList KisSimpleUpdateQueue::m_spontaneousJobsList
protected

Definition at line 82 of file kis_simple_update_queue.h.

◆ m_updatesList

KisWalkersList KisSimpleUpdateQueue::m_updatesList
protected

Definition at line 81 of file kis_simple_update_queue.h.


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