[Libreoffice-commits] core.git: include/vcl vcl/qa vcl/source
Tomaž Vajngerl (via logerrit)
logerrit at kemper.freedesktop.org
Sun Jul 5 21:17:58 UTC 2020
include/vcl/BitmapFilter.hxx | 28 ++++++++++++
vcl/qa/cppunit/BitmapFilterTest.cxx | 63 +++++++++++++++++++++++++++
vcl/source/bitmap/BitmapFilterStackBlur.cxx | 49 ++++++++++++---------
vcl/source/bitmap/BitmapScaleSuperFilter.cxx | 24 ++++------
4 files changed, 130 insertions(+), 34 deletions(-)
New commits:
commit 8166f340511f49c91deba161f27d9ded11a14e14
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
AuthorDate: Wed Jul 1 15:57:15 2020 +0200
Commit: Tomaž Vajngerl <quikee at gmail.com>
CommitDate: Sun Jul 5 23:17:16 2020 +0200
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 at gmail.com>
diff --git a/include/vcl/BitmapFilter.hxx b/include/vcl/BitmapFilter.hxx
index 19599d06316f..0521ded42357 100644
--- a/include/vcl/BitmapFilter.hxx
+++ b/include/vcl/BitmapFilter.hxx
@@ -12,8 +12,36 @@
#define INCLUDED_VCL_BITMAPFILTER_HXX
#include <vcl/bitmapex.hxx>
+#include <functional>
+
class Animation;
+namespace vcl::bitmap
+{
+// Generates strip ranges and run the input function with the start and
+// end as parameters. The additional parameter bLast denotes if the
+// iteration is teh last one.
+//
+// Example:
+// first = 0, last = 100, STRIP_SIZE = 32
+// this will generate:
+// [0, 31, false], [32, 63, false], [64, 95, false], [96, 100, true]
+template <int STRIP_SIZE>
+void generateStripRanges(
+ long nFirst, long nLast,
+ std::function<void(long const nStart, long const nEnd, bool const bLast)> aFunction)
+{
+ long nStart = nFirst;
+ for (; nStart < nLast - STRIP_SIZE; nStart += STRIP_SIZE)
+ {
+ long nEnd = nStart + STRIP_SIZE - 1;
+ aFunction(nStart, nEnd, false);
+ }
+ aFunction(nStart, nLast, true);
+}
+
+} // end vcl::bitmap
+
class VCL_DLLPUBLIC BitmapFilter
{
public:
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");
}
More information about the Libreoffice-commits
mailing list