From 1fd01c14fd8a072b6a972d19c714d695e074ce55 Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Sat, 18 Jan 2020 14:55:26 +0100 Subject: [PATCH] Execution policy (multithreading) --- PdfForQtLib/sources/pdfcolorspaces.cpp | 3 +- PdfForQtLib/sources/pdfcompiler.cpp | 3 +- PdfForQtLib/sources/pdfdocumentreader.cpp | 7 +- PdfForQtLib/sources/pdfexecutionpolicy.cpp | 92 ++++++++++++++++ PdfForQtLib/sources/pdfexecutionpolicy.h | 103 ++++++++++++++++++ .../sources/pdfpagecontentprocessor.cpp | 5 +- PdfForQtLib/sources/pdfpattern.cpp | 15 +-- PdfForQtLib/sources/pdftextlayout.cpp | 7 +- .../pdfdocumentpropertiesdialog.cpp | 3 +- PdfForQtViewer/pdfviewermainwindow.cpp | 2 + PdfForQtViewer/pdfviewersettings.cpp | 5 +- PdfForQtViewer/pdfviewersettings.h | 4 + PdfForQtViewer/pdfviewersettingsdialog.cpp | 9 ++ PdfForQtViewer/pdfviewersettingsdialog.ui | 42 ++++--- 14 files changed, 266 insertions(+), 34 deletions(-) create mode 100644 PdfForQtLib/sources/pdfexecutionpolicy.cpp create mode 100644 PdfForQtLib/sources/pdfexecutionpolicy.h diff --git a/PdfForQtLib/sources/pdfcolorspaces.cpp b/PdfForQtLib/sources/pdfcolorspaces.cpp index b79e251..d7d1d87 100644 --- a/PdfForQtLib/sources/pdfcolorspaces.cpp +++ b/PdfForQtLib/sources/pdfcolorspaces.cpp @@ -22,6 +22,7 @@ #include "pdfutils.h" #include "pdfpattern.h" #include "pdfcms.h" +#include "pdfexecutionpolicy.h" #include @@ -222,7 +223,7 @@ QImage PDFAbstractColorSpace::getImage(const PDFImageData& imageData, }; auto range = PDFIntegerRange(0, imageHeight); - std::for_each(std::execution::parallel_policy(), range.begin(), range.end(), transformPixelLine); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, range.begin(), range.end(), transformPixelLine); if (exception) { diff --git a/PdfForQtLib/sources/pdfcompiler.cpp b/PdfForQtLib/sources/pdfcompiler.cpp index cf8f6dd..7e8afa8 100644 --- a/PdfForQtLib/sources/pdfcompiler.cpp +++ b/PdfForQtLib/sources/pdfcompiler.cpp @@ -19,6 +19,7 @@ #include "pdfcms.h" #include "pdfdrawspacecontroller.h" #include "pdfprogress.h" +#include "pdfexecutionpolicy.h" #include @@ -411,7 +412,7 @@ void PDFAsynchronousTextLayoutCompiler::makeTextLayout() }; auto pageRange = PDFIntegerRange(0, catalog->getPageCount()); - std::for_each(std::execution::parallel_policy(), pageRange.begin(), pageRange.end(), generateTextLayout); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Page, pageRange.begin(), pageRange.end(), generateTextLayout); return result; }; diff --git a/PdfForQtLib/sources/pdfdocumentreader.cpp b/PdfForQtLib/sources/pdfdocumentreader.cpp index b0b1cbf..4600e1f 100644 --- a/PdfForQtLib/sources/pdfdocumentreader.cpp +++ b/PdfForQtLib/sources/pdfdocumentreader.cpp @@ -22,6 +22,7 @@ #include "pdfexception.h" #include "pdfparser.h" #include "pdfstreamfilters.h" +#include "pdfexecutionpolicy.h" #include @@ -270,7 +271,7 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer) // Now, we are ready to scan all objects progressStart(occupiedEntries.size(), PDFTranslationContext::tr("Reading contents of document...")); - std::for_each(std::execution::parallel_policy(), occupiedEntries.cbegin(), occupiedEntries.cend(), processEntry); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Unknown, occupiedEntries.cbegin(), occupiedEntries.cend(), processEntry); progressFinish(); if (m_result != Result::OK) @@ -370,7 +371,7 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer) }; progressStart(occupiedEntries.size(), PDFTranslationContext::tr("Decrypting encrypted contents of document...")); - std::for_each(std::execution::parallel_policy(), occupiedEntries.cbegin(), occupiedEntries.cend(), decryptEntry); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Unknown, occupiedEntries.cbegin(), occupiedEntries.cend(), decryptEntry); progressFinish(); } @@ -478,7 +479,7 @@ PDFDocument PDFDocumentReader::readFromBuffer(const QByteArray& buffer) }; // Now, we are ready to scan all object streams - std::for_each(std::execution::parallel_policy(), objectStreams.cbegin(), objectStreams.cend(), processObjectStream); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Unknown, objectStreams.cbegin(), objectStreams.cend(), processObjectStream); PDFObjectStorage storage(std::move(objects), PDFObject(xrefTable.getTrailerDictionary()), std::move(securityHandler)); return PDFDocument(std::move(storage), m_version); diff --git a/PdfForQtLib/sources/pdfexecutionpolicy.cpp b/PdfForQtLib/sources/pdfexecutionpolicy.cpp new file mode 100644 index 0000000..f18b30d --- /dev/null +++ b/PdfForQtLib/sources/pdfexecutionpolicy.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2020 Jakub Melka +// +// This file is part of PdfForQt. +// +// PdfForQt is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// PdfForQt is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with PDFForQt. If not, see . + + +#include "pdfexecutionpolicy.h" + +#include + +namespace pdf +{ + +struct PDFExecutionPolicyHolder +{ + PDFExecutionPolicy policy; +} s_execution_policy; + +void PDFExecutionPolicy::setStrategy(Strategy strategy) +{ + s_execution_policy.policy.m_strategy.store(strategy, std::memory_order_relaxed); +} + +bool PDFExecutionPolicy::isParallelizing(Scope scope) +{ + const Strategy strategy = s_execution_policy.policy.m_strategy.load(std::memory_order_relaxed); + switch (strategy) + { + case Strategy::SingleThreaded: + return false; + + case Strategy::PageMultithreaded: + { + switch (scope) + { + case Scope::Page: + case Scope::Unknown: + return true; // We are parallelizing pages... + + case Scope::Content: + { + // Jakub Melka: this is a bit complicated. We must count number of content streams + // being processed and if it is large enough, then do not parallelize. + const size_t threadLimit = s_execution_policy.policy.m_threadLimit.load(std::memory_order_relaxed); + const size_t contentStreamsCount = s_execution_policy.policy.m_contentStreamsCount.load(std::memory_order_seq_cst); + return contentStreamsCount < threadLimit; + } + } + + break; + } + + case Strategy::AlwaysMultithreaded: + return true; + } + + // It should never go here... + Q_ASSERT(false); + return false; +} + +void PDFExecutionPolicy::startProcessingContentStream() +{ + ++s_execution_policy.policy.m_contentStreamsCount; +} + +void PDFExecutionPolicy::endProcessingContentStream() +{ + --s_execution_policy.policy.m_contentStreamsCount; +} + +PDFExecutionPolicy::PDFExecutionPolicy() : + m_contentStreamsCount(0), + m_threadLimit(QThread::idealThreadCount()), + m_strategy(Strategy::PageMultithreaded) +{ + +} + +} // namespace pdf diff --git a/PdfForQtLib/sources/pdfexecutionpolicy.h b/PdfForQtLib/sources/pdfexecutionpolicy.h new file mode 100644 index 0000000..1f43c63 --- /dev/null +++ b/PdfForQtLib/sources/pdfexecutionpolicy.h @@ -0,0 +1,103 @@ +// Copyright (C) 2020 Jakub Melka +// +// This file is part of PdfForQt. +// +// PdfForQt is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// PdfForQt is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with PDFForQt. If not, see . + +#ifndef PDFEXECUTIONPOLICY_H +#define PDFEXECUTIONPOLICY_H + +#include "pdfglobal.h" + +#include +#include + +namespace pdf +{ +struct PDFExecutionPolicyHolder; + +/// Defines thread execution policy based on settings and actual number of page content +/// streams being processed. It can regulate number of threads executed at each +/// point, where execution policy is used. +class PDFFORQTLIBSHARED_EXPORT PDFExecutionPolicy +{ +public: + + enum class Scope + { + Page, ///< Used, when we are processing page objects + Content, ///< Used, when we are processing objects from page content streams + Unknown ///< Unknown scope, usually tries to parallelize + }; + + enum class Strategy + { + SingleThreaded, + PageMultithreaded, + AlwaysMultithreaded + }; + + /// Sets multithreading strategy + /// \param strategy Strategy + static void setStrategy(Strategy strategy); + + /// Determines, if we should parallelize for scope + /// \param scope Scope for which we want to determine exectution policy + static bool isParallelizing(Scope scope); + + template + static void execute(Scope scope, ForwardIt first, ForwardIt last, UnaryFunction f) + { + if (isParallelizing(scope)) + { + std::for_each(std::execution::parallel_policy(), first, last, f); + } + else + { + std::for_each(std::execution::sequenced_policy(), first, last, f); + } + } + + template + static void sort(Scope scope, ForwardIt first, ForwardIt last, Comparator f) + { + if (isParallelizing(scope)) + { + std::sort(std::execution::parallel_policy(), first, last, f); + } + else + { + std::sort(std::execution::sequenced_policy(), first, last, f); + } + } + + /// Starts processing content stream + static void startProcessingContentStream(); + + /// Ends processing content stream + static void endProcessingContentStream(); + +private: + friend struct PDFExecutionPolicyHolder; + + explicit PDFExecutionPolicy(); + + std::atomic m_contentStreamsCount; + std::atomic m_threadLimit; + std::atomic m_strategy; +}; + +} // namespace pdf + +#endif // PDFEXECUTIONPOLICY_H diff --git a/PdfForQtLib/sources/pdfpagecontentprocessor.cpp b/PdfForQtLib/sources/pdfpagecontentprocessor.cpp index ddd58a4..c9aa8b3 100644 --- a/PdfForQtLib/sources/pdfpagecontentprocessor.cpp +++ b/PdfForQtLib/sources/pdfpagecontentprocessor.cpp @@ -20,6 +20,7 @@ #include "pdfexception.h" #include "pdfimage.h" #include "pdfpattern.h" +#include "pdfexecutionpolicy.h" #include @@ -209,6 +210,8 @@ PDFPageContentProcessor::PDFPageContentProcessor(const PDFPage* page, Q_ASSERT(page); Q_ASSERT(document); + PDFExecutionPolicy::startProcessingContentStream(); + QPainterPath pageRectPath; pageRectPath.addRect(m_page->getRotatedMediaBox()); m_pageBoundingRectDeviceSpace = pagePointToDevicePointMatrix.map(pageRectPath).boundingRect(); @@ -218,7 +221,7 @@ PDFPageContentProcessor::PDFPageContentProcessor(const PDFPage* page, PDFPageContentProcessor::~PDFPageContentProcessor() { - + PDFExecutionPolicy::endProcessingContentStream(); } QList PDFPageContentProcessor::processContents() diff --git a/PdfForQtLib/sources/pdfpattern.cpp b/PdfForQtLib/sources/pdfpattern.cpp index 1178440..59e1a79 100644 --- a/PdfForQtLib/sources/pdfpattern.cpp +++ b/PdfForQtLib/sources/pdfpattern.cpp @@ -20,6 +20,7 @@ #include "pdfexception.h" #include "pdfutils.h" #include "pdfcolorspaces.h" +#include "pdfexecutionpolicy.h" #include @@ -618,7 +619,7 @@ PDFMesh PDFFunctionShading::createMesh(const PDFMeshQualitySettings& settings, c } }; - std::for_each(std::execution::parallel_policy(), indices.cbegin(), indices.cend(), setColor); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, indices.cbegin(), indices.cend(), setColor); if (!functionError) { @@ -664,7 +665,7 @@ PDFMesh PDFFunctionShading::createMesh(const PDFMeshQualitySettings& settings, c } } }; - std::for_each(std::execution::parallel_policy(), indices.cbegin(), indices.cend(), validateMesh); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, indices.cbegin(), indices.cend(), validateMesh); if (!isMeshOK && resolution != settings.minimalMeshResolution) { continue; @@ -750,7 +751,7 @@ PDFMesh PDFFunctionShading::createMesh(const PDFMeshQualitySettings& settings, c triangles[triangleIndex1] = triangle1; triangles[triangleIndex2] = triangle2; }; - std::for_each(std::execution::parallel_policy(), indices.cbegin(), indices.cend(), generateTriangle); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, indices.cbegin(), indices.cend(), generateTriangle); mesh.setTriangles(qMove(triangles)); if (!functionError) @@ -1475,7 +1476,7 @@ PDFMesh PDFFreeFormGouradTriangleShading::createMesh(const PDFMeshQualitySetting }; PDFIntegerRange indices(size_t(0), vertexCount); - std::for_each(std::execution::parallel_policy(), indices.begin(), indices.end(), readVertex); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, indices.begin(), indices.end(), readVertex); mesh.setVertices(qMove(meshVertices)); vertices.front().flags = 0; @@ -1624,7 +1625,7 @@ PDFMesh PDFLatticeFormGouradTriangleShading::createMesh(const PDFMeshQualitySett }; PDFIntegerRange indices(size_t(0), vertexCount); - std::for_each(std::execution::parallel_policy(), indices.begin(), indices.end(), readVertex); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, indices.begin(), indices.end(), readVertex); mesh.setVertices(qMove(meshVertices)); auto getVertexIndex = [columnCount](size_t row, size_t column) -> size_t @@ -2253,7 +2254,7 @@ void PDFTensorProductPatchShadingBase::fillMesh(PDFMesh& mesh, PDFReal previousCurvature = maximalCurvature; while (previousCurvature < curvature && !maximalCurvature.compare_exchange_weak(previousCurvature, curvature)) { } }; - std::for_each(std::execution::parallel_policy(), range.begin(), range.end(), updateCurvature); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, range.begin(), range.end(), updateCurvature); auto getColorForUV = [&](PDFReal u, PDFReal v) { @@ -2364,7 +2365,7 @@ void PDFTensorProductPatchShadingBase::fillMesh(PDFMesh& mesh, QPointF rightCenter = right.getCenter(); return std::pair(leftCenter.y(), leftCenter.x()) < std::pair(rightCenter.y(), rightCenter.x()); }; - std::sort(std::execution::parallel_policy(), finishedTriangles.begin(), finishedTriangles.end(), comparator); + PDFExecutionPolicy::sort(PDFExecutionPolicy::Scope::Content, finishedTriangles.begin(), finishedTriangles.end(), comparator); std::vector vertices; std::vector triangles; diff --git a/PdfForQtLib/sources/pdftextlayout.cpp b/PdfForQtLib/sources/pdftextlayout.cpp index d2a68ed..b6960f5 100644 --- a/PdfForQtLib/sources/pdftextlayout.cpp +++ b/PdfForQtLib/sources/pdftextlayout.cpp @@ -17,6 +17,7 @@ #include "pdftextlayout.h" #include "pdfutils.h" +#include "pdfexecutionpolicy.h" #include @@ -456,7 +457,7 @@ void PDFTextLayout::performDoLayout(PDFReal angle) }; auto range = PDFIntegerRange(0, characterCount); - std::for_each(std::execution::parallel_policy(), range.begin(), range.end(), findNearestCharacters); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, range.begin(), range.end(), findNearestCharacters); // Step 3) - detect lines PDFUnionFindAlgorithm textLinesUF(characterCount); @@ -847,7 +848,7 @@ PDFFindResults PDFTextLayoutStorage::find(const QString& text, Qt::CaseSensitivi }; auto range = PDFIntegerRange(0, m_offsets.size()); - std::for_each(std::execution::parallel_policy(), range.begin(), range.end(), findImpl); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Page, range.begin(), range.end(), findImpl); std::sort(results.begin(), results.end()); return results; @@ -876,7 +877,7 @@ PDFFindResults PDFTextLayoutStorage::find(const QRegularExpression& expression, }; auto range = PDFIntegerRange(0, m_offsets.size()); - std::for_each(std::execution::parallel_policy(), range.begin(), range.end(), findImpl); + PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Page, range.begin(), range.end(), findImpl); std::sort(results.begin(), results.end()); return results; diff --git a/PdfForQtViewer/pdfdocumentpropertiesdialog.cpp b/PdfForQtViewer/pdfdocumentpropertiesdialog.cpp index 389ca17..84d2542 100644 --- a/PdfForQtViewer/pdfdocumentpropertiesdialog.cpp +++ b/PdfForQtViewer/pdfdocumentpropertiesdialog.cpp @@ -23,6 +23,7 @@ #include "pdffont.h" #include "pdfutils.h" #include "pdfexception.h" +#include "pdfexecutionpolicy.h" #include #include @@ -369,7 +370,7 @@ void PDFDocumentPropertiesDialog::initializeFonts(const pdf::PDFDocument* docume }; pdf::PDFIntegerRange indices(pdf::PDFInteger(0), pageCount); - std::for_each(std::execution::parallel_policy(), indices.begin(), indices.end(), processPage); + pdf::PDFExecutionPolicy::execute(pdf::PDFExecutionPolicy::Scope::Page, indices.begin(), indices.end(), processPage); }; m_future = QtConcurrent::run(createFontInfo); connect(&m_futureWatcher, &QFutureWatcher::finished, this, &PDFDocumentPropertiesDialog::onFontsFinished); diff --git a/PdfForQtViewer/pdfviewermainwindow.cpp b/PdfForQtViewer/pdfviewermainwindow.cpp index fc9f9e8..17ed13b 100644 --- a/PdfForQtViewer/pdfviewermainwindow.cpp +++ b/PdfForQtViewer/pdfviewermainwindow.cpp @@ -34,6 +34,7 @@ #include "pdfitemmodels.h" #include "pdfutils.h" #include "pdfsendmail.h" +#include "pdfexecutionpolicy.h" #include #include @@ -776,6 +777,7 @@ void PDFViewerMainWindow::onViewerSettingsChanged() m_pdfWidget->getDrawWidgetProxy()->setPreferredMeshResolutionRatio(m_settings->getPreferredMeshResolutionRatio()); m_pdfWidget->getDrawWidgetProxy()->setMinimalMeshResolutionRatio(m_settings->getMinimalMeshResolutionRatio()); m_pdfWidget->getDrawWidgetProxy()->setColorTolerance(m_settings->getColorTolerance()); + pdf::PDFExecutionPolicy::setStrategy(m_settings->getMultithreadingStrategy()); updateRenderingOptionActions(); } diff --git a/PdfForQtViewer/pdfviewersettings.cpp b/PdfForQtViewer/pdfviewersettings.cpp index 80b6858..c02c2ae 100644 --- a/PdfForQtViewer/pdfviewersettings.cpp +++ b/PdfForQtViewer/pdfviewersettings.cpp @@ -53,6 +53,7 @@ void PDFViewerSettings::readSettings(QSettings& settings, const pdf::PDFCMSSetti m_settings.m_instancedFontCacheLimit = settings.value("instancedFontCacheLimit", defaultSettings.m_instancedFontCacheLimit).toInt(); m_settings.m_allowLaunchApplications = settings.value("allowLaunchApplications", defaultSettings.m_allowLaunchApplications).toBool(); m_settings.m_allowLaunchURI = settings.value("allowLaunchURI", defaultSettings.m_allowLaunchURI).toBool(); + m_settings.m_multithreadingStrategy = static_cast(settings.value("mutlithreadingStrategy", static_cast(defaultSettings.m_multithreadingStrategy)).toInt()); settings.endGroup(); settings.beginGroup("ColorManagementSystemSettings"); @@ -89,6 +90,7 @@ void PDFViewerSettings::writeSettings(QSettings& settings) settings.setValue("instancedFontCacheLimit", m_settings.m_instancedFontCacheLimit); settings.setValue("allowLaunchApplications", m_settings.m_allowLaunchApplications); settings.setValue("allowLaunchURI", m_settings.m_allowLaunchURI); + settings.setValue("mutlithreadingStrategy", static_cast(m_settings.m_multithreadingStrategy)); settings.endGroup(); settings.beginGroup("ColorManagementSystemSettings"); @@ -202,7 +204,8 @@ PDFViewerSettings::Settings::Settings() : m_compiledPageCacheLimit(128 * 1024), m_thumbnailsCacheLimit(PIXMAP_CACHE_LIMIT), m_fontCacheLimit(pdf::DEFAULT_FONT_CACHE_LIMIT), - m_instancedFontCacheLimit(pdf::DEFAULT_REALIZED_FONT_CACHE_LIMIT) + m_instancedFontCacheLimit(pdf::DEFAULT_REALIZED_FONT_CACHE_LIMIT), + m_multithreadingStrategy(pdf::PDFExecutionPolicy::Strategy::PageMultithreaded) { } diff --git a/PdfForQtViewer/pdfviewersettings.h b/PdfForQtViewer/pdfviewersettings.h index 6bf9485..f4331de 100644 --- a/PdfForQtViewer/pdfviewersettings.h +++ b/PdfForQtViewer/pdfviewersettings.h @@ -20,6 +20,7 @@ #include "pdfrenderer.h" #include "pdfcms.h" +#include "pdfexecutionpolicy.h" #include @@ -55,6 +56,7 @@ public: pdf::PDFReal m_colorTolerance; bool m_allowLaunchApplications; bool m_allowLaunchURI; + pdf::PDFExecutionPolicy::Strategy m_multithreadingStrategy = pdf::PDFExecutionPolicy::Strategy::PageMultithreaded; // Cache settings int m_compiledPageCacheLimit; @@ -101,6 +103,8 @@ public: const pdf::PDFCMSSettings& getColorManagementSystemSettings() const { return m_colorManagementSystemSettings; } void setColorManagementSystemSettings(const pdf::PDFCMSSettings& settings) { m_colorManagementSystemSettings = settings; } + pdf::PDFExecutionPolicy::Strategy getMultithreadingStrategy() const { return m_settings.m_multithreadingStrategy; } + signals: void settingsChanged(); diff --git a/PdfForQtViewer/pdfviewersettingsdialog.cpp b/PdfForQtViewer/pdfviewersettingsdialog.cpp index 0c210d8..d033805 100644 --- a/PdfForQtViewer/pdfviewersettingsdialog.cpp +++ b/PdfForQtViewer/pdfviewersettingsdialog.cpp @@ -59,6 +59,10 @@ PDFViewerSettingsDialog::PDFViewerSettingsDialog(const PDFViewerSettings::Settin ui->multisampleAntialiasingSamplesCountComboBox->addItem(QString::number(i), i); } + ui->multithreadingComboBox->addItem(tr("Single thread"), static_cast(pdf::PDFExecutionPolicy::Strategy::SingleThreaded)); + ui->multithreadingComboBox->addItem(tr("Multithreading (load balanced)"), static_cast(pdf::PDFExecutionPolicy::Strategy::PageMultithreaded)); + ui->multithreadingComboBox->addItem(tr("Multithreading (maximum threads)"), static_cast(pdf::PDFExecutionPolicy::Strategy::AlwaysMultithreaded)); + // Load CMS data ui->cmsTypeComboBox->addItem(pdf::PDFCMSManager::getSystemName(pdf::PDFCMSSettings::System::Generic), int(pdf::PDFCMSSettings::System::Generic)); ui->cmsTypeComboBox->addItem(pdf::PDFCMSManager::getSystemName(pdf::PDFCMSSettings::System::LittleCMS2), int(pdf::PDFCMSSettings::System::LittleCMS2)); @@ -200,6 +204,7 @@ void PDFViewerSettingsDialog::loadData() ui->multisampleAntialiasingSamplesCountComboBox->setCurrentIndex(-1); } ui->prefetchPagesCheckBox->setChecked(m_settings.m_prefetchPages); + ui->multithreadingComboBox->setCurrentIndex(ui->multithreadingComboBox->findData(static_cast(m_settings.m_multithreadingStrategy))); // Rendering ui->antialiasingCheckBox->setChecked(m_settings.m_features.testFlag(pdf::PDFRenderer::Antialiasing)); @@ -397,6 +402,10 @@ void PDFViewerSettingsDialog::saveData() { m_cmsSettings.profileDirectory = ui->cmsProfileDirectoryEdit->text(); } + else if (sender == ui->multithreadingComboBox) + { + m_settings.m_multithreadingStrategy = static_cast(ui->multithreadingComboBox->currentData().toInt()); + } loadData(); } diff --git a/PdfForQtViewer/pdfviewersettingsdialog.ui b/PdfForQtViewer/pdfviewersettingsdialog.ui index 1efd82c..780da87 100644 --- a/PdfForQtViewer/pdfviewersettingsdialog.ui +++ b/PdfForQtViewer/pdfviewersettingsdialog.ui @@ -26,7 +26,7 @@ - 5 + 0 @@ -57,6 +57,9 @@ + + + @@ -64,6 +67,16 @@ + + + + + + + Prefetch pages + + + @@ -71,11 +84,12 @@ - - - - - + + + + Enable + + @@ -84,26 +98,22 @@ - - + + - Prefetch pages + Multithreading strategy - - - - Enable - - + + - <html><head/><body><p>Select rendering method according to your needs. <span style=" font-weight:600;">Software rendering</span> is much slower than hardware accelerated rendering using <span style=" font-weight:600;">OpenGL rendering</span>, but it works when OpenGL is not available at your platform. OpenGL rendering is selected as default and is recommended.</p><p>OpenGL rendering uses<span style=" font-weight:600;"> multisample antialiasing (MSAA)</span>, which provides good quality antialiasing. You can turn this feature on or off, but without antialiasing, bad quality image can occur. Samples count affect how much samples per pixel are considered to determine pixel color. It can be a value 1, 2, 4, 8, and 16. Most modern GPUs support at least value 8. Lower this value, if your GPU doesn't support the desired sample count.</p><p><span style=" font-weight:600;">Prefetch pages </span>prefetches (pre-renders) pages next to currently viewed pages, to avoid flickering during scrolling. Prefetched pages are stored in the page cache.</p></body></html> + <html><head/><body><p>Select rendering method according to your needs. <span style=" font-weight:600;">Software rendering</span> is much slower than hardware accelerated rendering using <span style=" font-weight:600;">OpenGL rendering</span>, but it works when OpenGL is not available at your platform. OpenGL rendering is selected as default and is recommended.</p><p>OpenGL rendering uses<span style=" font-weight:600;"> multisample antialiasing (MSAA)</span>, which provides good quality antialiasing. You can turn this feature on or off, but without antialiasing, bad quality image can occur. Samples count affect how much samples per pixel are considered to determine pixel color. It can be a value 1, 2, 4, 8, and 16. Most modern GPUs support at least value 8. Lower this value, if your GPU doesn't support the desired sample count.</p><p><span style=" font-weight:600;">Prefetch pages </span>prefetches (pre-renders) pages next to currently viewed pages, to avoid flickering during scrolling. Prefetched pages are stored in the page cache.</p><p><span style=" font-weight:600;">Multithreading strategy </span>defines how program will use CPU cores. Engine can use multiple cores. Strategy defines, how engine will use these cores. <span style=" font-weight:600;">Single thread</span> strategy uses only one CPU core for rendering page, and for some operations, they aren't parallelized, at the cost of more time needed for operation to be finished. But still, each page will use its own thread to be compiled/drawn. On the other side, there are two multithreading strategies, former is load balanced, latter uses maximum threads. Load balanced strategy tries to optimize number of threads to fit CPU cores, while maximum threads strategy will spawn as much threads as possible to process operations, which can be sometimes unoptimal.</p></body></html> true