File indexing completed on 2024-04-28 04:21:31

0001 /*
0002  *  SPDX-FileCopyrightText: 2009 Dmitry Kazakov <dimula73@gmail.com>
0003  *
0004  *  SPDX-License-Identifier: GPL-2.0-or-later
0005  */
0006 
0007 #include "kis_filter_selections_benchmark.h"
0008 
0009 #include "kis_painter.h"
0010 
0011 #include <simpletest.h>
0012 #include <testutil.h>
0013 #include "kis_transaction.h"
0014 #include <KoCompositeOpRegistry.h>
0015 #include "kis_datamanager.h"
0016 #include <KisGlobalResourcesInterface.h>
0017 
0018 #define NUM_CYCLES 50
0019 #define WARMUP_CYCLES 2
0020 #define SHOW_WARMUPS  0
0021 
0022 /**
0023  * Our filters don't know anything about applyAlphaU8Mask
0024  * That's why they treat semy-selected pixels badly
0025  *
0026  * If you have a hack in KisFilter - processSpecial(..) method
0027  * that takes into account this alpha mask then activate
0028  * the following define
0029  */
0030 #define USE_GOOD_SELECTIONS 0
0031 
0032 #define USE_UTIME 0
0033 
0034 
0035 #if(USE_UTIME==1)
0036 #include <sys/times.h>
0037 class KisTimeCounter
0038 {
0039 public:
0040     KisTimeCounter() {
0041         m_factor = double(sysconf(_SC_CLK_TCK)) / 1000.0;
0042         restart();
0043     }
0044 
0045     void restart() {
0046         times(&m_startTime);
0047     }
0048 
0049     double elapsed() {
0050         struct tms endTime;
0051         times(&endTime);
0052         return double(endTime.tms_utime - m_startTime.tms_utime) / m_factor;
0053     }
0054 
0055 private:
0056     struct tms m_startTime;
0057     double m_factor;
0058 };
0059 #else /* if(USE_UTIME==0) */
0060 typedef QElapsedTimer KisTimeCounter;
0061 #endif
0062 
0063 void KisFilterSelectionsBenchmark::initSelection()
0064 {
0065     m_selection = new KisSelection();
0066     KisPixelSelectionSP pixelSelection = m_selection->pixelSelection();
0067 
0068 
0069 //67.2% deselected
0070     dbgKrita << "Deselected: 67.2%";
0071     pixelSelection->dataManager()->clear(75, 75, 500, 320, 255);
0072     pixelSelection->dataManager()->clear(100, 100, 50, 50, quint8(0));
0073     pixelSelection->dataManager()->clear(150, 150, 50, 50, quint8(0));
0074     pixelSelection->dataManager()->clear(200, 200, 50, 50, quint8(0));
0075 
0076     pixelSelection->dataManager()->clear(375, 195, 200, 200, quint8(0));
0077     pixelSelection->dataManager()->clear(75, 195, 200, 200, quint8(0));
0078 
0079     pixelSelection->dataManager()->clear(375, 75, 150, 150, quint8(0));
0080 
0081     pixelSelection->dataManager()->clear(205, 105, 50, 50, quint8(128));
0082 
0083 // 94.9% deselected
0084 //    dbgKrita << "Deselected: 94.9%";
0085 //    pixelSelection->dataManager()->clear(75,75,500,320,255);
0086 //    pixelSelection->dataManager()->clear(80,80,490,310,quint8(0));
0087 
0088 
0089 
0090     pixelSelection->convertToQImage(0).save("TEST_FILTER_SELECTION.png");
0091 }
0092 
0093 void KisFilterSelectionsBenchmark::initFilter(const QString &name)
0094 {
0095     m_filter = KisFilterRegistry::instance()->value(name);
0096     Q_ASSERT(m_filter);
0097     m_configuration = m_filter->defaultConfiguration(KisGlobalResourcesInterface::instance());
0098 
0099     dbgKrita << "Filter initialized:" << name;
0100 }
0101 
0102 void KisFilterSelectionsBenchmark::testFilter(const QString &name)
0103 {
0104     blockSignals(true);
0105 
0106     initFilter(name);
0107 
0108     testUsualSelections(WARMUP_CYCLES);
0109     testUsualSelections(NUM_CYCLES);
0110 
0111     testGoodSelections(WARMUP_CYCLES);
0112     testGoodSelections(NUM_CYCLES);
0113 
0114     testNoSelections(WARMUP_CYCLES);
0115     testNoSelections(NUM_CYCLES);
0116 
0117     testBitBltWOSelections(WARMUP_CYCLES);
0118     testBitBltWOSelections(NUM_CYCLES);
0119 
0120     testBitBltSelections(WARMUP_CYCLES);
0121     testBitBltSelections(NUM_CYCLES);
0122 
0123     blockSignals(false);
0124 }
0125 
0126 
0127 void KisFilterSelectionsBenchmark::testAll()
0128 {
0129     initSelection();
0130 
0131     const KoColorSpace *cs = KoColorSpaceRegistry::instance()->rgb8();
0132     QImage image(QString(FILES_DATA_DIR) + '/' + "hakonepa.png");
0133     m_device = new KisPaintDevice(cs);
0134     m_device->convertFromQImage(image, 0, 0, 0);
0135 
0136     testFilter("brightnesscontrast");
0137     testFilter("invert");
0138 //    testFilter("levels");
0139 
0140 }
0141 
0142 void KisFilterSelectionsBenchmark::testUsualSelections(int num)
0143 {
0144     KisPaintDeviceSP projection =
0145         new KisPaintDevice(m_device->colorSpace());
0146 
0147     double avTime;
0148     KisTimeCounter timer;
0149 
0150     QRect filterRect = m_selection->selectedExactRect();
0151 
0152     timer.restart();
0153     for (int i = 0; i < num; i++) {
0154         KisTransaction transac(projection, 0);
0155         m_filter->process(m_device, projection, m_selection, filterRect, m_configuration, 0);
0156     }
0157     avTime = double(timer.elapsed()) / num;
0158 
0159     projection->convertToQImage(0).save("TFS__USUAL_SELECTIONS.png");
0160 
0161     if (num > WARMUP_CYCLES || SHOW_WARMUPS)
0162         dbgKrita << "Selections inside filter:\t\t" << avTime;
0163 }
0164 
0165 void KisFilterSelectionsBenchmark::testNoSelections(int num)
0166 {
0167     KisPaintDeviceSP projection =
0168         new KisPaintDevice(m_device->colorSpace());
0169 
0170     double avTime;
0171     KisTimeCounter timer;
0172 
0173     QRect filterRect = m_selection->selectedExactRect();
0174 
0175     timer.restart();
0176     for (int i = 0; i < num; i++) {
0177         KisTransaction transac(projection, 0);
0178         m_filter->process(m_device, projection, 0, filterRect, m_configuration, 0);
0179     }
0180     avTime = double(timer.elapsed()) / num;
0181 
0182     projection->convertToQImage(0).save("TFS__NO_SELECTIONS.png");
0183 
0184     if (num > WARMUP_CYCLES || SHOW_WARMUPS)
0185         dbgKrita << "No Selections:\t\t\t\t" << avTime;
0186 }
0187 
0188 void KisFilterSelectionsBenchmark::testGoodSelections(int num)
0189 {
0190 #if(USE_GOOD_SELECTIONS==1)
0191     KisPaintDeviceSP projection =
0192         new KisPaintDevice(m_device->colorSpace());
0193 
0194     double avTime;
0195     KisTimeCounter timer;
0196 
0197     QRect filterRect = m_selection->selectedExactRect();
0198     KisConstProcessingInformation src(m_device,  filterRect.topLeft(), m_selection);
0199     KisProcessingInformation dst(projection, filterRect.topLeft(), 0);
0200 
0201     timer.restart();
0202     for (int i = 0; i < num; i++) {
0203         KisTransaction transac(0, projection, 0);
0204         m_filter->processSpecial(src, dst, filterRect.size(), m_configuration, 0);
0205     }
0206     avTime = double(timer.elapsed()) / num;
0207 
0208     projection->convertToQImage(0).save("TFS__GOOD_SELECTIONS.png");
0209 
0210     if (num > WARMUP_CYCLES || SHOW_WARMUPS)
0211         dbgKrita << "Selections with alpha (filter):\t" << avTime;
0212 #else /* if (USE_GOOD_SELECTIONS!=1) */
0213     if (num > WARMUP_CYCLES || SHOW_WARMUPS)
0214         dbgKrita << "Selections with alpha (filter):\t [Disabled]";
0215 #endif
0216 }
0217 
0218 void KisFilterSelectionsBenchmark::testBitBltWOSelections(int num)
0219 {
0220     KisPaintDeviceSP projection =
0221         new KisPaintDevice(m_device->colorSpace());
0222 
0223     double avTime;
0224     KisTimeCounter timer;
0225 
0226     QRect filterRect = m_selection->selectedExactRect();
0227 
0228     timer.restart();
0229     for (int i = 0; i < num; i++) {
0230         KisPaintDeviceSP cacheDevice = new KisPaintDevice(projection->colorSpace());
0231 
0232         KisTransaction transac(cacheDevice, 0);
0233         m_filter->process(m_device, projection, 0, filterRect, m_configuration, 0);
0234 
0235         KisPainter painter(projection);
0236         painter.beginTransaction();
0237         painter.setCompositeOpId(COMPOSITE_ALPHA_DARKEN);
0238         painter.bitBlt(filterRect.topLeft(), cacheDevice, filterRect);
0239         painter.deleteTransaction();
0240     }
0241     avTime = double(timer.elapsed()) / num;
0242 
0243     projection->convertToQImage(0).save("TFS__BITBLT_WO_SELECTIONS.png");
0244 
0245     if (num > WARMUP_CYCLES || SHOW_WARMUPS)
0246         dbgKrita << "bitBlt w/o sel:\t\t\t" << avTime;
0247 }
0248 
0249 void KisFilterSelectionsBenchmark::testBitBltSelections(int num)
0250 {
0251     KisPaintDeviceSP projection =
0252         new KisPaintDevice(m_device->colorSpace());
0253 
0254     double avTime;
0255     KisTimeCounter timer;
0256 
0257     QRect filterRect = m_selection->selectedExactRect();
0258 
0259     timer.restart();
0260     for (int i = 0; i < num; i++) {
0261         KisPaintDeviceSP cacheDevice = new KisPaintDevice(projection->colorSpace());
0262 
0263         KisTransaction transac(cacheDevice, 0);
0264         m_filter->process(m_device, cacheDevice, 0, filterRect, m_configuration, 0);
0265 
0266         KisPainter gc(projection);
0267         gc.beginTransaction();
0268         gc.setCompositeOpId(COMPOSITE_ALPHA_DARKEN);
0269         gc.setSelection(m_selection);
0270         gc.bitBlt(filterRect.topLeft(), cacheDevice, filterRect);
0271         gc.deleteTransaction();
0272     }
0273     avTime = double(timer.elapsed()) / num;
0274 
0275     projection->convertToQImage(0).save("TFS__BITBLT_WITH_SELECTIONS.png");
0276 
0277     if (num > WARMUP_CYCLES || SHOW_WARMUPS)
0278         dbgKrita << "bitBlt with sel:\t\t\t" << avTime;
0279 }
0280 
0281 SIMPLE_TEST_MAIN(KisFilterSelectionsBenchmark)