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]; }
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]; }
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() } }
/** * 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, ¤tDistance); 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; }
QSize optimalPatchSize() { KisImageConfig cfg; return QSize(cfg.updatePatchWidth(), cfg.updatePatchHeight()); }
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()); }