void KisSwappedDataStoreTest::testRandomAccess()
{
    qsrand(10);
    const qint32 pixelSize = 1;
    const quint8 defaultPixel = 128;
    const qint32 NUM_CYCLES = 50000;
    const qint32 NUM_TILES = 10000;

    KisImageConfig config;
    config.setMaxSwapSize(40);
    config.setSwapSlabSize(1);
    config.setSwapWindowSize(1);


    KisSwappedDataStore store;

    QList<KisTileData*> tileDataList;
    for(qint32 i = 0; i < NUM_TILES; i++)
        tileDataList.append(new KisTileData(pixelSize, &defaultPixel, KisTileDataStore::instance()));

    for(qint32 i = 0; i < NUM_CYCLES; i++) {
        if(!(i%5000))
            dbgKrita << i << "of" << NUM_CYCLES;

        qint32 col = qrand() % NUM_TILES;

        KisTileData *td = tileDataList[col];
        processTileData(col, td, store);
    }

    store.debugStatistics();

    for(qint32 i = 0; i < NUM_TILES; i++)
        delete tileDataList[i];
}
Ejemplo n.º 2
0
void KisLowMemoryTests::initTestCase()
{
    // hard limit of 1MiB, no undo in memory, no clones
    KisImageConfig config;
    config.setMemoryHardLimitPercent(1.1 * 100.0 / KisImageConfig::totalRAM());
    config.setMemorySoftLimitPercent(0);
    config.setMemoryPoolLimitPercent(0);
}
KisSwappedDataStore::KisSwappedDataStore()
{
    KisImageConfig config;
    const quint64 maxSwapSize = config.maxSwapSize() * MiB;
    const quint64 swapSlabSize = config.swapSlabSize() * MiB;
    const quint64 swapWindowSize = config.swapWindowSize() * MiB;

    m_allocator = new KisChunkAllocator(swapSlabSize, maxSwapSize);
    m_swapSpace = new KisMemoryWindow(swapWindowSize);

    // FIXME: use a factory after the patch is committed
    m_compressor = new KisTileCompressor2();
}
void KisSwappedDataStoreTest::testRoundTrip()
{
    const qint32 pixelSize = 1;
    const quint8 defaultPixel = 128;
    const qint32 NUM_TILES = 10000;

    KisImageConfig config;
    config.setMaxSwapSize(4);
    config.setSwapSlabSize(1);
    config.setSwapWindowSize(1);


    KisSwappedDataStore store;

    QList<KisTileData*> tileDataList;
    for(qint32 i = 0; i < NUM_TILES; i++)
        tileDataList.append(new KisTileData(pixelSize, &defaultPixel, KisTileDataStore::instance()));

    for(qint32 i = 0; i < NUM_TILES; i++) {
        KisTileData *td = tileDataList[i];
        QVERIFY(memoryIsFilled(defaultPixel, td->data(), TILESIZE));

        memset(td->data(), COLUMN2COLOR(i), TILESIZE);
        QVERIFY(memoryIsFilled(COLUMN2COLOR(i), td->data(), TILESIZE));

        // FIXME: take a lock of the tile data
        store.swapOutTileData(td);
    }

    store.debugStatistics();

    for(qint32 i = 0; i < NUM_TILES; i++) {
        KisTileData *td = tileDataList[i];
        QVERIFY(!td->data());
        // TODO: check num clones

        // FIXME: take a lock of the tile data
        store.swapInTileData(td);
        QVERIFY(memoryIsFilled(COLUMN2COLOR(i), td->data(), TILESIZE));
    }

    store.debugStatistics();

    for(qint32 i = 0; i < NUM_TILES; i++)
        delete tileDataList[i];
}
Ejemplo n.º 5
0
void KisImagePyramid::setImage(KisImageWSP newImage)
{
    if (newImage) {
        m_originalImage = newImage;

        clearPyramid();
        setImageSize(m_originalImage->width(), m_originalImage->height());

        // Get the full image size
        QRect rc = m_originalImage->projection()->exactBounds();

        KisImageConfig config;

        int patchWidth = config.updatePatchWidth();
        int patchHeight = config.updatePatchHeight();

        if (rc.width() * rc.height() <= patchWidth * patchHeight) {
            retrieveImageData(rc);
        }
        else {
            qint32 firstCol = rc.x() / patchWidth;
            qint32 firstRow = rc.y() / patchHeight;

            qint32 lastCol = (rc.x() + rc.width()) / patchWidth;
            qint32 lastRow = (rc.y() + rc.height()) / patchHeight;

            for(qint32 i = firstRow; i <= lastRow; i++) {
                for(qint32 j = firstCol; j <= lastCol; j++) {
                    QRect maxPatchRect(j * patchWidth,
                                       i * patchHeight,
                                       patchWidth, patchHeight);
                    QRect patchRect = rc & maxPatchRect;
                    retrieveImageData(patchRect);
                }
            }

        }
        //TODO: check whether there is needed recalculateCache()
    }
}
Ejemplo n.º 6
0
/**
 * This benchmark runs a series of huge strokes on a canvas with a
 * particular configuration of the swapper/pooler and history
 * management. After the test is done you can visualize the results
 * with the GNU Octave. Please use kis_low_memory_show_report.m file
 * for that.
 */
void KisLowMemoryBenchmark::benchmarkWideArea(const QString presetFileName,
                                              const QRectF &rect, qreal vstep,
                                              int numCycles,
                                              bool createTransaction,
                                              int hardLimitMiB,
                                              int softLimitMiB,
                                              int poolLimitMiB,
                                              int index)
{
    KisPaintOpPresetSP preset = new KisPaintOpPreset(QString(FILES_DATA_DIR) + QDir::separator() + presetFileName);
    LOAD_PRESET_OR_RETURN(preset, presetFileName);


    /**
     * Initialize image and painter
     */
    const KoColorSpace *colorSpace = KoColorSpaceRegistry::instance()->rgb8();
    KisImageSP image = new KisImage(0, HUGE_IMAGE_SIZE, HUGE_IMAGE_SIZE, colorSpace, "stroke sample image", true);
    KisLayerSP layer = new KisPaintLayer(image, "temporary for stroke sample", OPACITY_OPAQUE_U8, colorSpace);
    KisLayerSP layerExtra = new KisPaintLayer(image, "temporary for threading", OPACITY_OPAQUE_U8, colorSpace);

    image->addNode(layer, image->root());
    image->addNode(layerExtra, image->root());

    KisPainter *painter = new KisPainter(layer->paintDevice());

    painter->setPaintColor(KoColor(Qt::black, colorSpace));
    painter->setPaintOpPreset(preset, layer, image);

    /**
     * A simple adapter that will store all the transactions for us
     */
    KisSurrogateUndoAdapter undoAdapter;

    /**
     * Reset configuration to the desired settings
     */
    KisImageConfig config;
    qreal oldHardLimit = config.memoryHardLimitPercent();
    qreal oldSoftLimit = config.memorySoftLimitPercent();
    qreal oldPoolLimit = config.memoryPoolLimitPercent();
    const qreal _MiB = 100.0 / KisImageConfig::totalRAM();

    config.setMemoryHardLimitPercent(hardLimitMiB * _MiB);
    config.setMemorySoftLimitPercent(softLimitMiB * _MiB);
    config.setMemoryPoolLimitPercent(poolLimitMiB * _MiB);

    KisTileDataStore::instance()->testingRereadConfig();

    /**
     * Create an empty the log file
     */
    QString fileName;
    fileName = QString("log_%1_%2_%3_%4_%5.txt")
        .arg(createTransaction)
        .arg(hardLimitMiB)
        .arg(softLimitMiB)
        .arg(poolLimitMiB)
        .arg(index);

    QFile logFile(fileName);
    logFile.open(QFile::WriteOnly | QFile::Truncate);
    QTextStream logStream(&logFile);
    logStream.setFieldWidth(10);
    logStream.setFieldAlignment(QTextStream::AlignRight);

    /**
     * Start painting on the image
     */

    QTime cycleTime;
    QTime lineTime;
    cycleTime.start();
    lineTime.start();

    qreal rectBottom = rect.y() + rect.height();

    for (int i = 0; i < numCycles; i++) {
        cycleTime.restart();

        QLineF line(rect.topLeft(), rect.topLeft() + QPointF(rect.width(), 0));
        if (createTransaction) {
            painter->beginTransaction();
        }

        KisDistanceInformation currentDistance;

        while(line.y1() < rectBottom) {
            lineTime.restart();

            KisPaintInformation pi1(line.p1(), 0.0);
            KisPaintInformation pi2(line.p2(), 1.0);
            painter->paintLine(pi1, pi2, &currentDistance);
            painter->device()->setDirty(painter->takeDirtyRegion());

            logStream << "L 1" << i << lineTime.elapsed()
                      << KisTileDataStore::instance()->numTilesInMemory() * 16
                      << KisTileDataStore::instance()->numTiles() * 16
                      << createTransaction << endl;

            line.translate(0, vstep);
        }

        painter->device()->setDirty(painter->takeDirtyRegion());

        if (createTransaction) {
            painter->endTransaction(&undoAdapter);
        }

        // comment/uncomment to emulate user waiting after the stroke
        QTest::qSleep(1000);

        logStream << "C 2" << i << cycleTime.elapsed()
                  << KisTileDataStore::instance()->numTilesInMemory() * 16
                  << KisTileDataStore::instance()->numTiles() * 16
                  << createTransaction
                  << config.memoryHardLimitPercent() / _MiB
                  << config.memorySoftLimitPercent() / _MiB
                  << config.memoryPoolLimitPercent() / _MiB  << endl;
    }

    config.setMemoryHardLimitPercent(oldHardLimit * _MiB);
    config.setMemorySoftLimitPercent(oldSoftLimit * _MiB);
    config.setMemoryPoolLimitPercent(oldPoolLimit * _MiB);

    delete painter;
}
Ejemplo n.º 7
0
 QSize optimalPatchSize()
 {
     KisImageConfig cfg;
     return QSize(cfg.updatePatchWidth(),
                  cfg.updatePatchHeight());
 }
Ejemplo n.º 8
0
AnimationDocker::AnimationDocker()
    : QDockWidget(i18n("Animation"))
    , m_canvas(0)
    , m_animationWidget(new Ui_WdgAnimation)
    , m_mainWindow(0)
{
    QWidget* mainWidget = new QWidget(this);
    setWidget(mainWidget);

    m_animationWidget->setupUi(mainWidget);


    m_previousFrameAction = new KisAction(i18n("Previous Frame"), m_animationWidget->btnPreviousFrame);
    m_previousFrameAction->setActivationFlags(KisAction::ACTIVE_IMAGE);
    m_animationWidget->btnPreviousFrame->setDefaultAction(m_previousFrameAction);

    m_nextFrameAction = new KisAction(i18n("Next Frame"), m_animationWidget->btnNextFrame);
    m_nextFrameAction->setActivationFlags(KisAction::ACTIVE_IMAGE);
    m_animationWidget->btnNextFrame->setDefaultAction(m_nextFrameAction);

    m_previousKeyFrameAction = new KisAction(i18n("Previous Key Frame"), m_animationWidget->btnPreviousKeyFrame);
    m_previousKeyFrameAction->setActivationFlags(KisAction::ACTIVE_IMAGE);
    m_animationWidget->btnPreviousKeyFrame->setDefaultAction(m_previousKeyFrameAction);

    m_nextKeyFrameAction = new KisAction(i18n("Next Key Frame"), m_animationWidget->btnNextKeyFrame);
    m_nextKeyFrameAction->setActivationFlags(KisAction::ACTIVE_IMAGE);
    m_animationWidget->btnNextKeyFrame->setDefaultAction(m_nextKeyFrameAction);

    m_firstFrameAction = new KisAction(i18n("First Frame"), m_animationWidget->btnFirstFrame);
    m_firstFrameAction->setActivationFlags(KisAction::ACTIVE_IMAGE);
    m_animationWidget->btnFirstFrame->setDefaultAction(m_firstFrameAction);

    m_lastFrameAction = new KisAction(i18n("Last Frame"), m_animationWidget->btnLastFrame);
    m_lastFrameAction->setActivationFlags(KisAction::ACTIVE_IMAGE);
    m_animationWidget->btnLastFrame->setDefaultAction(m_lastFrameAction);

    m_playPauseAction = new KisAction(i18n("Play / Pause"), m_animationWidget->btnPlay);
    m_playPauseAction->setActivationFlags(KisAction::ACTIVE_IMAGE);
    m_animationWidget->btnPlay->setDefaultAction(m_playPauseAction);

    m_addBlankFrameAction = new KisAction(KisAnimationUtils::addFrameActionName, m_animationWidget->btnAddKeyframe);
    m_addBlankFrameAction->setActivationFlags(KisAction::ACTIVE_LAYER);
    m_animationWidget->btnAddKeyframe->setDefaultAction(m_addBlankFrameAction);

    m_addDuplicateFrameAction = new KisAction(KisAnimationUtils::duplicateFrameActionName, m_animationWidget->btnAddDuplicateFrame);
    m_addDuplicateFrameAction->setActivationFlags(KisAction::ACTIVE_LAYER);
    m_animationWidget->btnAddDuplicateFrame->setDefaultAction(m_addDuplicateFrameAction);

    m_deleteKeyframeAction = new KisAction(KisAnimationUtils::removeFrameActionName, m_animationWidget->btnDeleteKeyframe);
    m_deleteKeyframeAction->setActivationFlags(KisAction::ACTIVE_LAYER);
    m_animationWidget->btnDeleteKeyframe->setDefaultAction(m_deleteKeyframeAction);

    {
        KisImageConfig cfg;
        setupActionButton(KisAnimationUtils::lazyFrameCreationActionName,
                          KisAction::ACTIVE_IMAGE,
                          cfg.lazyFrameCreationEnabled(),
                          m_animationWidget->btnLazyFrame,
                          &m_lazyFrameAction);
    }

    {
        KisConfig cfg;
        setupActionButton(KisAnimationUtils::dropFramesActionName,
                          KisAction::ACTIVE_IMAGE,
                          cfg.animationDropFrames(),
                          m_animationWidget->btnDropFrames,
                          &m_dropFramesAction);
    }

    QFont font;
    font.setPointSize(1.7 * font.pointSize());
    font.setBold(true);
    m_animationWidget->intCurrentTime->setFont(font);

    connect(m_previousFrameAction, SIGNAL(triggered()), this, SLOT(slotPreviousFrame()));
    connect(m_nextFrameAction, SIGNAL(triggered()), this, SLOT(slotNextFrame()));

    connect(m_previousKeyFrameAction, SIGNAL(triggered()), this, SLOT(slotPreviousKeyFrame()));
    connect(m_nextKeyFrameAction, SIGNAL(triggered()), this, SLOT(slotNextKeyFrame()));

    connect(m_firstFrameAction, SIGNAL(triggered()), this, SLOT(slotFirstFrame()));
    connect(m_lastFrameAction, SIGNAL(triggered()), this, SLOT(slotLastFrame()));

    connect(m_playPauseAction, SIGNAL(triggered()), this, SLOT(slotPlayPause()));

    connect(m_addBlankFrameAction, SIGNAL(triggered()), this, SLOT(slotAddBlankFrame()));
    connect(m_addDuplicateFrameAction, SIGNAL(triggered()), this, SLOT(slotAddDuplicateFrame()));
    connect(m_deleteKeyframeAction, SIGNAL(triggered()), this, SLOT(slotDeleteKeyframe()));
    connect(m_lazyFrameAction, SIGNAL(toggled(bool)), this, SLOT(slotLazyFrameChanged(bool)));
    connect(m_dropFramesAction, SIGNAL(toggled(bool)), this, SLOT(slotDropFramesChanged(bool)));

    m_animationWidget->btnOnionSkinOptions->setToolTip(i18n("Onion Skins"));
    connect(m_animationWidget->btnOnionSkinOptions, SIGNAL(clicked()), this, SLOT(slotOnionSkinOptions()));

    connect(m_animationWidget->spinFromFrame, SIGNAL(valueChanged(int)), this, SLOT(slotUIRangeChanged()));
    connect(m_animationWidget->spinToFrame, SIGNAL(valueChanged(int)), this, SLOT(slotUIRangeChanged()));
    connect(m_animationWidget->intFramerate, SIGNAL(valueChanged(int)), this, SLOT(slotUIFramerateChanged()));

    connect(m_animationWidget->intCurrentTime, SIGNAL(valueChanged(int)), SLOT(slotTimeSpinBoxChanged()));
}
void KisPrescaledProjection::updateSettings()
{
    KisImageConfig imageConfig;
    m_d->updatePatchSize.setWidth(imageConfig.updatePatchWidth());
    m_d->updatePatchSize.setHeight(imageConfig.updatePatchHeight());
}