summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorTomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>2020-07-01 15:57:15 +0200
committerTomaž Vajngerl <quikee@gmail.com>2020-07-05 23:17:16 +0200
commit8166f340511f49c91deba161f27d9ded11a14e14 (patch)
treec5d074d5c41cf63ee8d70c6f5cb83547b1b4a9eb /vcl
parentb945946135cb302c1805fdf6502e02dbdf52b813 (diff)
add generateStripRanges and use that in StackBlur and ScaleSuper
generateStripRanges divides a range into equally long stripes that is useful for defining scanlines for a thread. This is used in the BitmapFilterStackBlur and BitmapScaleSuperFilter as they are running using a thread pool. Change-Id: Ifb9f70dea3b0233e6aa30ccf20187a2ff58fd5a2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/97725 Tested-by: Jenkins Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
Diffstat (limited to 'vcl')
-rw-r--r--vcl/qa/cppunit/BitmapFilterTest.cxx63
-rw-r--r--vcl/source/bitmap/BitmapFilterStackBlur.cxx49
-rw-r--r--vcl/source/bitmap/BitmapScaleSuperFilter.cxx24
3 files changed, 102 insertions, 34 deletions
diff --git a/vcl/qa/cppunit/BitmapFilterTest.cxx b/vcl/qa/cppunit/BitmapFilterTest.cxx
index dddfaf571dd4..a519da24ed9b 100644
--- a/vcl/qa/cppunit/BitmapFilterTest.cxx
+++ b/vcl/qa/cppunit/BitmapFilterTest.cxx
@@ -38,11 +38,13 @@ public:
void testBlurCorrectness();
void testBasicMorphology();
void testPerformance();
+ void testGenerateStripRanges();
CPPUNIT_TEST_SUITE(BitmapFilterTest);
CPPUNIT_TEST(testBlurCorrectness);
CPPUNIT_TEST(testBasicMorphology);
CPPUNIT_TEST(testPerformance);
+ CPPUNIT_TEST(testGenerateStripRanges);
CPPUNIT_TEST_SUITE_END();
private:
@@ -209,6 +211,67 @@ void BitmapFilterTest::testPerformance()
}
}
+void BitmapFilterTest::testGenerateStripRanges()
+{
+ {
+ constexpr long nFirstIndex = 0;
+ constexpr long nLastIndex = 100;
+ constexpr long nStripSize = 32;
+
+ std::vector<std::tuple<long, long, bool>> aRanges;
+
+ vcl::bitmap::generateStripRanges<nStripSize>(
+ nFirstIndex, nLastIndex, [&](long const nStart, long const nEnd, bool const bLast) {
+ aRanges.emplace_back(nStart, nEnd, bLast);
+ });
+
+ CPPUNIT_ASSERT_EQUAL(size_t(4), aRanges.size());
+
+ CPPUNIT_ASSERT_EQUAL(0L, std::get<0>(aRanges[0]));
+ CPPUNIT_ASSERT_EQUAL(31L, std::get<1>(aRanges[0]));
+ CPPUNIT_ASSERT_EQUAL(false, std::get<2>(aRanges[0]));
+
+ CPPUNIT_ASSERT_EQUAL(32L, std::get<0>(aRanges[1]));
+ CPPUNIT_ASSERT_EQUAL(63L, std::get<1>(aRanges[1]));
+ CPPUNIT_ASSERT_EQUAL(false, std::get<2>(aRanges[1]));
+
+ CPPUNIT_ASSERT_EQUAL(64L, std::get<0>(aRanges[2]));
+ CPPUNIT_ASSERT_EQUAL(95L, std::get<1>(aRanges[2]));
+ CPPUNIT_ASSERT_EQUAL(false, std::get<2>(aRanges[2]));
+
+ CPPUNIT_ASSERT_EQUAL(96L, std::get<0>(aRanges[3]));
+ CPPUNIT_ASSERT_EQUAL(100L, std::get<1>(aRanges[3]));
+ CPPUNIT_ASSERT_EQUAL(true, std::get<2>(aRanges[3]));
+ }
+
+ {
+ constexpr long nFirstIndex = 0;
+ constexpr long nLastIndex = 95;
+ constexpr long nStripSize = 32;
+
+ std::vector<std::tuple<long, long, bool>> aRanges;
+
+ vcl::bitmap::generateStripRanges<nStripSize>(
+ nFirstIndex, nLastIndex, [&](long const nStart, long const nEnd, bool const bLast) {
+ aRanges.emplace_back(nStart, nEnd, bLast);
+ });
+
+ CPPUNIT_ASSERT_EQUAL(size_t(3), aRanges.size());
+
+ CPPUNIT_ASSERT_EQUAL(0L, std::get<0>(aRanges[0]));
+ CPPUNIT_ASSERT_EQUAL(31L, std::get<1>(aRanges[0]));
+ CPPUNIT_ASSERT_EQUAL(false, std::get<2>(aRanges[0]));
+
+ CPPUNIT_ASSERT_EQUAL(32L, std::get<0>(aRanges[1]));
+ CPPUNIT_ASSERT_EQUAL(63L, std::get<1>(aRanges[1]));
+ CPPUNIT_ASSERT_EQUAL(false, std::get<2>(aRanges[1]));
+
+ CPPUNIT_ASSERT_EQUAL(64L, std::get<0>(aRanges[2]));
+ CPPUNIT_ASSERT_EQUAL(95L, std::get<1>(aRanges[2]));
+ CPPUNIT_ASSERT_EQUAL(true, std::get<2>(aRanges[2]));
+ }
+}
+
} // namespace
CPPUNIT_TEST_SUITE_REGISTRATION(BitmapFilterTest);
diff --git a/vcl/source/bitmap/BitmapFilterStackBlur.cxx b/vcl/source/bitmap/BitmapFilterStackBlur.cxx
index 69e7c8b2e3ec..a9e17eee2cd2 100644
--- a/vcl/source/bitmap/BitmapFilterStackBlur.cxx
+++ b/vcl/source/bitmap/BitmapFilterStackBlur.cxx
@@ -469,17 +469,21 @@ void runStackBlur(Bitmap& rBitmap, const long nRadius, const long nComponentWidt
BlurSharedData aSharedData(pReadAccess.get(), pWriteAccess.get(), nRadius,
nComponentWidth, nColorChannels);
+ const long nFirstIndex = 0;
const long nLastIndex = pReadAccess->Height() - 1;
- long nStripStart = 0;
- for (; nStripStart < nLastIndex - nThreadStrip; nStripStart += nThreadStrip)
- {
- long nStripEnd = nStripStart + nThreadStrip - 1;
- auto pTask(std::make_unique<BlurTask>(pTag, pBlurHorizontalFn, aSharedData,
- nStripStart, nStripEnd));
- rShared.pushTask(std::move(pTask));
- }
- // Do the last (or the only) strip in main thread without threading overhead
- pBlurHorizontalFn(aSharedData, nStripStart, nLastIndex);
+
+ vcl::bitmap::generateStripRanges<nThreadStrip>(
+ nFirstIndex, nLastIndex,
+ [&](long const nStart, long const nEnd, bool const bLast) {
+ if (!bLast)
+ {
+ auto pTask(std::make_unique<BlurTask>(pTag, pBlurHorizontalFn,
+ aSharedData, nStart, nEnd));
+ rShared.pushTask(std::move(pTask));
+ }
+ else
+ pBlurHorizontalFn(aSharedData, nStart, nEnd);
+ });
rShared.waitUntilDone(pTag);
}
{
@@ -488,17 +492,22 @@ void runStackBlur(Bitmap& rBitmap, const long nRadius, const long nComponentWidt
BlurSharedData aSharedData(pReadAccess.get(), pWriteAccess.get(), nRadius,
nComponentWidth, nColorChannels);
+ const long nFirstIndex = 0;
const long nLastIndex = pReadAccess->Width() - 1;
- long nStripStart = 0;
- for (; nStripStart < nLastIndex - nThreadStrip; nStripStart += nThreadStrip)
- {
- long nStripEnd = nStripStart + nThreadStrip - 1;
- auto pTask(std::make_unique<BlurTask>(pTag, pBlurVerticalFn, aSharedData,
- nStripStart, nStripEnd));
- rShared.pushTask(std::move(pTask));
- }
- // Do the last (or the only) strip in main thread without threading overhead
- pBlurVerticalFn(aSharedData, nStripStart, nLastIndex);
+
+ vcl::bitmap::generateStripRanges<nThreadStrip>(
+ nFirstIndex, nLastIndex,
+ [&](long const nStart, long const nEnd, bool const bLast) {
+ if (!bLast)
+ {
+ auto pTask(std::make_unique<BlurTask>(pTag, pBlurVerticalFn,
+ aSharedData, nStart, nEnd));
+ rShared.pushTask(std::move(pTask));
+ }
+ else
+ pBlurVerticalFn(aSharedData, nStart, nEnd);
+ });
+
rShared.waitUntilDone(pTag);
}
}
diff --git a/vcl/source/bitmap/BitmapScaleSuperFilter.cxx b/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
index 4b6d8ede851b..42d2897143f0 100644
--- a/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
+++ b/vcl/source/bitmap/BitmapScaleSuperFilter.cxx
@@ -983,21 +983,17 @@ BitmapEx BitmapScaleSuperFilter::execute(BitmapEx const& rBitmap) const
comphelper::ThreadPool &rShared = comphelper::ThreadPool::getSharedOptimalPool();
std::shared_ptr<comphelper::ThreadTaskTag> pTag = comphelper::ThreadPool::createThreadTaskTag();
- long nStripYStart = nStartY;
- long nStripYEnd = nStripYStart + constScaleThreadStrip - 1;
-
- while (nStripYEnd < nEndY)
- {
- std::unique_ptr<ScaleTask> pTask(new ScaleTask(pTag, pScaleRangeFn, aContext, nStripYStart, nStripYEnd));
- rShared.pushTask(std::move(pTask));
- nStripYStart += constScaleThreadStrip;
- nStripYEnd += constScaleThreadStrip;
- }
- if (nStripYStart <= nEndY)
+ vcl::bitmap::generateStripRanges<constScaleThreadStrip>(nStartY, nEndY,
+ [&] (long const nStart, long const nEnd, bool const bLast)
{
- std::unique_ptr<ScaleTask> pTask(new ScaleTask(pTag, pScaleRangeFn, aContext, nStripYStart, nEndY));
- rShared.pushTask(std::move(pTask));
- }
+ if (!bLast)
+ {
+ auto pTask(std::make_unique<ScaleTask>(pTag, pScaleRangeFn, aContext, nStart, nEnd));
+ rShared.pushTask(std::move(pTask));
+ }
+ else
+ pScaleRangeFn(aContext, nStart, nEnd);
+ });
rShared.waitUntilDone(pTag);
SAL_INFO("vcl.gdi", "All threaded scaling tasks complete");
}