Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit cf035350 authored by Dmitry Kazakov's avatar Dmitry Kazakov

Test for rectangular artifacts on transparency masks

The problem itself is not solved yet. Only a test that
can reproduce it in a stable way is implemented.

The only things that I know right now is:

1) The problem is related to multithreading. It doesn't
   appear when the number of threads is limited to 1.

2) Artifacts appear only after clearing the transparency
   paint device.

3) Artifacts are neither present in the transparency mask
   paint device, nor in the projection of its parent layer.

4) Artifacts appear in the final image projection, right
   when the async merger calls layer->projectionPlane()->
   ->apply().

5) Changing dirtyRect in KisToolUtils::clearImage() to the
   entire image bounds doesn't help much.


CCBUG:395273
parent 377da7a9
......@@ -115,6 +115,11 @@ krita_add_broken_unit_test(
TEST_NAME krita-ui-FreehandStrokeBenchmark
LINK_LIBRARIES kritaui kritaimage Qt5::Test)
krita_add_broken_unit_test(
KisPaintOnTransparencyMaskTest.cpp ${CMAKE_SOURCE_DIR}/sdk/tests/stroke_testing_utils.cpp
TEST_NAME krita-ui-KisPaintOnTransparencyMaskTest
LINK_LIBRARIES kritaui kritaimage Qt5::Test)
krita_add_broken_unit_test(
fill_processing_visitor_test.cpp ${CMAKE_SOURCE_DIR}/sdk/tests/stroke_testing_utils.cpp
TEST_NAME krita-ui-FillProcessingVisitorTest
......
#include "KisPaintOnTransparencyMaskTest.h"
#include <QTest>
#include <KoCompositeOpRegistry.h>
#include <KoColor.h>
#include "stroke_testing_utils.h"
#include "strokes/freehand_stroke.h"
#include "strokes/KisFreehandStrokeInfo.h"
#include "kis_resources_snapshot.h"
#include "kis_image.h"
#include <brushengine/kis_paint_information.h>
#include "kis_transparency_mask.h"
#include "kis_paint_device_debug_utils.h"
#include "kis_tool_utils.h"
#include "kis_sequential_iterator.h"
class PaintOnTransparencyMaskTester : public utils::StrokeTester
{
public:
PaintOnTransparencyMaskTester(const QString &presetFilename)
: StrokeTester("freehand_benchmark", QSize(5000, 5000), presetFilename)
{
setBaseFuzziness(3);
}
protected:
using utils::StrokeTester::initImage;
void initImage(KisImageWSP image, KisNodeSP activeNode) override {
activeNode->paintDevice()->fill(QRect(0,0,1024,1024), KoColor(Qt::red, image->colorSpace()));
m_mask = new KisTransparencyMask();
m_mask->setSelection(new KisSelection());
m_mask->paintDevice()->clear();
image->addNode(m_mask, activeNode);
image->setWorkingThreadsLimit(8);
}
using utils::StrokeTester::modifyResourceManager;
void modifyResourceManager(KoCanvasResourceManager *manager,
KisImageWSP image) {
KoColor color(Qt::red, image->colorSpace());
color.setOpacity(0.5);
QVariant i;
i.setValue(color);
manager->setResource(KoCanvasResourceManager::ForegroundColor, i);
}
KisStrokeStrategy* createStroke(KisResourcesSnapshotSP resources,
KisImageWSP image) override {
Q_UNUSED(image);
resources->setCurrentNode(m_mask);
KisFreehandStrokeInfo *strokeInfo = new KisFreehandStrokeInfo();
QScopedPointer<FreehandStrokeStrategy> stroke(
new FreehandStrokeStrategy(resources, strokeInfo, kundo2_noi18n("Freehand Stroke")));
return stroke.take();
}
void addPaintingJobs(KisImageWSP image,
KisResourcesSnapshotSP resources) override
{
addPaintingJobs(image, resources, 0);
}
void addPaintingJobs(KisImageWSP image, KisResourcesSnapshotSP resources, int iteration) override {
Q_UNUSED(iteration);
Q_UNUSED(resources);
KisPaintInformation pi1;
KisPaintInformation pi2;
pi1 = KisPaintInformation(QPointF(100, 100), 1.0);
pi2 = KisPaintInformation(QPointF(800, 800), 1.0);
QScopedPointer<KisStrokeJobData> data(
new FreehandStrokeStrategy::Data(0, pi1, pi2));
image->addJob(strokeId(), data.take());
image->addJob(strokeId(), new FreehandStrokeStrategy::UpdateData(true));
}
void checkDeviceIsEmpty(KisPaintDeviceSP dev, const QString &name)
{
const KoColorSpace *cs = dev->colorSpace();
KisSequentialConstIterator it(dev, QRect(0,0,1024,1024));
while (it.nextPixel()) {
if (cs->opacityU8(it.rawDataConst()) > 0) {
KIS_DUMP_DEVICE_2(dev, QRect(0,0,1024,1024), "image", "dd");
qFatal(QString("failed: %1").arg(name).toLatin1().data());
}
}
}
void beforeCheckingResult(KisImageWSP image, KisNodeSP activeNode) {
ENTER_FUNCTION() << ppVar(image) << ppVar(activeNode);
KisToolUtils::clearImage(image, activeNode, 0);
image->waitForDone();
checkDeviceIsEmpty(m_mask->paintDevice(), "mask");
checkDeviceIsEmpty(m_mask->parent()->projection(), "projection");
checkDeviceIsEmpty(image->projection(), "image");
}
private:
KisMaskSP m_mask;
};
#include <KoResourcePaths.h>
void KisPaintOnTransparencyMaskTest::initTestCase()
{
KoResourcePaths::addResourceType("kis_brushes", "data", FILES_DATA_DIR);
}
void KisPaintOnTransparencyMaskTest::test()
{
for (int i = 0; i < 1000; i++) {
PaintOnTransparencyMaskTester tester("testing_wet_circle.kpp");
tester.testSimpleStrokeNoVerification();
}
}
QTEST_MAIN(KisPaintOnTransparencyMaskTest)
#ifndef KISPAINTONTRANSPARENCYMASKTEST_H
#define KISPAINTONTRANSPARENCYMASKTEST_H
#include <QtTest>
class KisPaintOnTransparencyMaskTest : public QObject
{
Q_OBJECT
private Q_SLOTS:
void initTestCase();
void test();
};
#endif // KISPAINTONTRANSPARENCYMASKTEST_H
......@@ -183,6 +183,11 @@ void utils::StrokeTester::benchmark()
doStroke(false, false, false, false);
}
void utils::StrokeTester::testSimpleStrokeNoVerification()
{
doStroke(false, false, true, false);
}
void utils::StrokeTester::testOneStroke(bool cancelled,
bool indirectPainting,
bool externalLayer,
......
......@@ -46,6 +46,7 @@ namespace utils {
void testSimpleStroke();
void test();
void benchmark();
void testSimpleStrokeNoVerification();
void setNumIterations(int value);
void setBaseFuzziness(int value);
......
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