diff options
author | Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk> | 2020-07-01 15:57:15 +0200 |
---|---|---|
committer | Tomaž Vajngerl <quikee@gmail.com> | 2020-07-05 23:17:16 +0200 |
commit | 8166f340511f49c91deba161f27d9ded11a14e14 (patch) | |
tree | c5d074d5c41cf63ee8d70c6f5cb83547b1b4a9eb /vcl | |
parent | b945946135cb302c1805fdf6502e02dbdf52b813 (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.cxx | 63 | ||||
-rw-r--r-- | vcl/source/bitmap/BitmapFilterStackBlur.cxx | 49 | ||||
-rw-r--r-- | vcl/source/bitmap/BitmapScaleSuperFilter.cxx | 24 |
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"); } |