[graphics/krita] libs: Workaround a deadlock when painting on a vector selection with Instant Preview

Dmitry Kazakov null at kde.org
Tue Oct 27 11:27:31 GMT 2020


Git commit fe6d1d6c4456e57b250aef70662a56d4b4cc2f16 by Dmitry Kazakov.
Committed on 27/10/2020 at 11:27.
Pushed by dkazakov into branch 'master'.

Workaround a deadlock when painting on a vector selection with Instant Preview

Instant Preview is based on running two consequent with different
level of detail, but our vector selection don't support that. More
than that, when starting a paint operation on a vector selection,
it should be flattened into a pixel selection. Which means that in LoD
mode the flattening will happen twice.

Ideally, we should somehow make KisSelection survive flattening in
two separate LoD strokes, but I'm not sure it is really worth the
effort.

The downsides of the patch are:

1) The first painting stroke on a selection based layer or
   mask with vector selection will always be executed without
   instant preview. It affects all mask, generator layers and
   filter layers.

2) The first applicaiton of a filter on such a layer will also
   be slow.

BUG:428260
CC:kimageshop at kde.org

M  +5    -0    libs/image/kis_base_node.cpp
M  +6    -0    libs/image/kis_base_node.h
M  +5    -0    libs/image/kis_mask.cc
M  +2    -0    libs/image/kis_mask.h
M  +5    -0    libs/image/kis_selection_based_layer.cpp
M  +2    -0    libs/image/kis_selection_based_layer.h
M  +1    -0    libs/ui/tool/strokes/freehand_stroke.cpp
M  +1    -0    libs/ui/tool/strokes/kis_filter_stroke_strategy.cpp

https://invent.kde.org/graphics/krita/commit/fe6d1d6c4456e57b250aef70662a56d4b4cc2f16

diff --git a/libs/image/kis_base_node.cpp b/libs/image/kis_base_node.cpp
index bf7a54ace1..d32af9c973 100644
--- a/libs/image/kis_base_node.cpp
+++ b/libs/image/kis_base_node.cpp
@@ -393,6 +393,11 @@ bool KisBaseNode::supportsLodMoves() const
     return m_d->supportsLodMoves;
 }
 
+bool KisBaseNode::supportsLodPainting() const
+{
+    return true;
+}
+
 void KisBaseNode::setImage(KisImageWSP image)
 {
     m_d->image = image;
diff --git a/libs/image/kis_base_node.h b/libs/image/kis_base_node.h
index 6f3825121a..45e9974314 100644
--- a/libs/image/kis_base_node.h
+++ b/libs/image/kis_base_node.h
@@ -490,6 +490,12 @@ public:
      */
     bool supportsLodMoves() const;
 
+    /**
+     * Returns true if the node can be painted via KisPaintDevice. Notable
+     * exceptions are selection-based layers and masks.
+     */
+    virtual bool supportsLodPainting() const;
+
     /**
      * Return the keyframe channels associated with this node
      * @return list of keyframe channels
diff --git a/libs/image/kis_mask.cc b/libs/image/kis_mask.cc
index 94d50e24fb..2d2dc8c7c0 100644
--- a/libs/image/kis_mask.cc
+++ b/libs/image/kis_mask.cc
@@ -485,6 +485,11 @@ void KisMask::testingInitSelection(const QRect &rect, KisLayerSP parentLayer)
     m_d->selection->setParentNode(this);
 }
 
+bool KisMask::supportsLodPainting() const
+{
+    return !m_d->selection || !m_d->selection->hasShapeSelection();
+}
+
 KisKeyframeChannel *KisMask::requestKeyframeChannel(const QString &id)
 {
     if (id == KisKeyframeChannel::Raster.id()) {
diff --git a/libs/image/kis_mask.h b/libs/image/kis_mask.h
index 82ad7e9d71..c7592a628b 100644
--- a/libs/image/kis_mask.h
+++ b/libs/image/kis_mask.h
@@ -191,6 +191,8 @@ public:
 
     void testingInitSelection(const QRect &rect, KisLayerSP parentLayer);
 
+    bool supportsLodPainting() const override;
+
 protected:
     /**
      * Apply the effect the projection using the mask as a selection.
diff --git a/libs/image/kis_selection_based_layer.cpp b/libs/image/kis_selection_based_layer.cpp
index 7a9f8db324..29e9244ab2 100644
--- a/libs/image/kis_selection_based_layer.cpp
+++ b/libs/image/kis_selection_based_layer.cpp
@@ -280,6 +280,11 @@ void KisSelectionBasedLayer::setY(qint32 y)
     }
 }
 
+bool KisSelectionBasedLayer::supportsLodPainting() const
+{
+    return !m_d->selection || !m_d->selection->hasShapeSelection();
+}
+
 KisKeyframeChannel *KisSelectionBasedLayer::requestKeyframeChannel(const QString &id)
 {
     if (id == KisKeyframeChannel::Raster.id()) {
diff --git a/libs/image/kis_selection_based_layer.h b/libs/image/kis_selection_based_layer.h
index a9580e49ef..a68120ac11 100644
--- a/libs/image/kis_selection_based_layer.h
+++ b/libs/image/kis_selection_based_layer.h
@@ -140,6 +140,8 @@ public:
      */
     void setY(qint32 y) override;
 
+    bool supportsLodPainting() const override;
+
 public:
 
     /**
diff --git a/libs/ui/tool/strokes/freehand_stroke.cpp b/libs/ui/tool/strokes/freehand_stroke.cpp
index b498ba90dc..9a795af5e6 100644
--- a/libs/ui/tool/strokes/freehand_stroke.cpp
+++ b/libs/ui/tool/strokes/freehand_stroke.cpp
@@ -336,6 +336,7 @@ void FreehandStrokeStrategy::issueSetDirtySignals()
 KisStrokeStrategy* FreehandStrokeStrategy::createLodClone(int levelOfDetail)
 {
     if (!m_d->resources->presetAllowsLod()) return 0;
+    if (!m_d->resources->currentNode()->supportsLodPainting()) return 0;
 
     FreehandStrokeStrategy *clone = new FreehandStrokeStrategy(*this, levelOfDetail);
     return clone;
diff --git a/libs/ui/tool/strokes/kis_filter_stroke_strategy.cpp b/libs/ui/tool/strokes/kis_filter_stroke_strategy.cpp
index 9d054138e2..4961080209 100644
--- a/libs/ui/tool/strokes/kis_filter_stroke_strategy.cpp
+++ b/libs/ui/tool/strokes/kis_filter_stroke_strategy.cpp
@@ -191,6 +191,7 @@ void KisFilterStrokeStrategy::finishStrokeCallback()
 KisStrokeStrategy* KisFilterStrokeStrategy::createLodClone(int levelOfDetail)
 {
     if (!m_d->filter->supportsLevelOfDetail(m_d->filterConfig.data(), levelOfDetail)) return 0;
+    if (!m_d->node->supportsLodPainting()) return 0;
 
     KisFilterStrokeStrategy *clone = new KisFilterStrokeStrategy(*this, levelOfDetail);
     return clone;


More information about the kimageshop mailing list