Commit 56b7bbc9 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Optimize Fill Layers to not regenerate stuff when not needed

With this patch one can use Fill Layer as an overlay for
colored draft lines. Painting works almost at the same speed
as painting on a normal layer.

Such usecase was suggested by David Revoy at Krita Sprint 2018

To Deevad: it would be nice to have a short video about that :)

CC:kimageshop@kde.org
parent 6e023a11
......@@ -44,6 +44,8 @@ struct Q_DECL_HIDDEN KisGeneratorLayer::Private
}
KisThreadSafeSignalCompressor updateSignalCompressor;
QRect preparedRect;
KisFilterConfigurationSP preparedForFilter;
};
......@@ -72,6 +74,7 @@ KisGeneratorLayer::~KisGeneratorLayer()
void KisGeneratorLayer::setFilter(KisFilterConfigurationSP filterConfig)
{
KisSelectionBasedLayer::setFilter(filterConfig);
m_d->preparedRect = QRect();
update();
}
......@@ -93,32 +96,43 @@ void KisGeneratorLayer::slotDelayedStaticUpdate()
void KisGeneratorLayer::update()
{
KisImageSP image = this->image().toStrongRef();
const QRect updateRect = extent() | image->bounds();
KisFilterConfigurationSP filterConfig = filter();
KIS_SAFE_ASSERT_RECOVER_RETURN(filterConfig);
if (!filterConfig) {
warnImage << "BUG: No Filter configuration in KisGeneratorLayer";
return;
if (filterConfig != m_d->preparedForFilter) {
resetCache();
}
const QRegion processRegion(QRegion(updateRect) - m_d->preparedRect);
if (processRegion.isEmpty()) return;
KisGeneratorSP f = KisGeneratorRegistry::instance()->value(filterConfig->name());
if (!f) return;
KIS_SAFE_ASSERT_RECOVER_RETURN(f);
QRect processRect = exactBounds();
KisPaintDeviceSP originalDevice = original();
resetCache();
QVector<QRect> dirtyRegion;
KisPaintDeviceSP originalDevice = original();
Q_FOREACH (const QRect &rc, processRegion) {
KisProcessingInformation dstCfg(originalDevice,
rc.topLeft(),
KisSelectionSP());
f->generate(dstCfg, rc.size(), filterConfig.data());
KisProcessingInformation dstCfg(originalDevice,
processRect.topLeft(),
KisSelectionSP());
dirtyRegion << rc;
f->generate(dstCfg, processRect.size(), filterConfig.data());
}
m_d->preparedRect = updateRect;
m_d->preparedForFilter = filterConfig;
// HACK ALERT!!!
// this avoids cyclic loop with KisRecalculateGeneratorLayerJob::run()
KisSelectionBasedLayer::setDirty(QVector<QRect>() << extent());
KisSelectionBasedLayer::setDirty(dirtyRegion);
}
bool KisGeneratorLayer::accept(KisNodeVisitor & v)
......@@ -150,12 +164,21 @@ KisBaseNode::PropertyList KisGeneratorLayer::sectionModelProperties() const
void KisGeneratorLayer::setX(qint32 x)
{
KisSelectionBasedLayer::setX(x);
m_d->preparedRect = QRect();
m_d->updateSignalCompressor.start();
}
void KisGeneratorLayer::setY(qint32 y)
{
KisSelectionBasedLayer::setY(y);
m_d->preparedRect = QRect();
m_d->updateSignalCompressor.start();
}
void KisGeneratorLayer::resetCache()
{
KisSelectionBasedLayer::resetCache();
m_d->preparedRect = QRect();
m_d->updateSignalCompressor.start();
}
......
......@@ -72,6 +72,8 @@ public:
void setX(qint32 x) override;
void setY(qint32 y) override;
void resetCache() override;
private Q_SLOTS:
void slotDelayedStaticUpdate();
......
......@@ -73,7 +73,7 @@ public:
* resets cached projection of lower layer to a new device
* @return void
*/
void resetCache();
virtual void resetCache();
/**
* for KisLayer::setDirty(const QRegion&)
......
Markdown is supported
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