opencl/source/openclwrapper.cxx          |    5 +++
 sc/inc/calcconfig.hxx                    |   11 +++++++
 sc/inc/recursionhelper.hxx               |    4 ++
 sc/qa/unit/copy_paste_test.cxx           |    2 -
 sc/source/core/data/formulacell.cxx      |   45 +++++++++++++++++++++++++++----
 sc/source/core/opencl/formulagroupcl.cxx |    3 ++
 sc/source/core/tool/calcconfig.cxx       |   37 +++++++++++++++++++++++++
 sc/source/core/tool/recursionhelper.cxx  |   15 ++++++++++
 sc/source/ui/unoobj/docuno.cxx           |    4 ++
 9 files changed, 119 insertions(+), 7 deletions(-)

New commits:
commit 12c95935f265b484c0a2fa13470085710729c903
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Fri Oct 12 11:34:20 2018 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Wed Nov 14 16:09:16 2018 +0100

    $SC_FORCE_CALCULATION to force Calc use opencl/threads for everything
    
    So that e.g. unit tests can be easily run with OpenCL forced. This forces
    even single cells to be evaluated using the forced method (many correctness
    tests are just a single cell which normally would not be used for grouped
    calculation).
    
    Change-Id: If5c6e77a6e0d8696d5416d760cf5e47b8acf3d27
    Reviewed-on: https://gerrit.libreoffice.org/63188
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>

diff --git a/opencl/source/openclwrapper.cxx b/opencl/source/openclwrapper.cxx
index 4383930ec0d4..436906340c53 100644
--- a/opencl/source/openclwrapper.cxx
+++ b/opencl/source/openclwrapper.cxx
@@ -761,6 +761,11 @@ void findDeviceInfoFromDeviceId(cl_device_id aDeviceId, 
size_t& rDeviceId, size_
 
 bool canUseOpenCL()
 {
+    if( const char* env = getenv( "SC_FORCE_CALCULATION" ))
+    {
+        if( strcmp( env, "opencl" ) == 0 )
+            return true;
+    }
     return !getenv("SAL_DISABLE_OPENCL") && 
officecfg::Office::Common::Misc::UseOpenCL::get();
 }
 
diff --git a/sc/inc/calcconfig.hxx b/sc/inc/calcconfig.hxx
index 2f840f9abdcb..ee99b0c10592 100644
--- a/sc/inc/calcconfig.hxx
+++ b/sc/inc/calcconfig.hxx
@@ -27,6 +27,16 @@ enum ScRecalcOptions
     RECALC_ASK,
 };
 
+// Env.var. SC_FORCE_CALCULATION can be used to force all calculation
+// to be done using OpenCL or group threading (even for single cells).
+enum ForceCalculationType
+{
+    ForceCalculationNone, // do not force anything
+    ForceCalculationCore, // "core", use only non-threaded normal code
+    ForceCalculationOpenCL, // "opencl", force OpenCL
+    ForceCalculationThreads // "threads", force threaded code
+};
+
 /**
  * Configuration options for formula interpreter.
  */
@@ -47,6 +57,7 @@ struct SC_DLLPUBLIC ScCalcConfig
 
     static bool isOpenCLEnabled();
     static bool isThreadingEnabled();
+    static ForceCalculationType getForceCalculationType();
 
     bool mbOpenCLSubsetOnly:1;
     bool mbOpenCLAutoSelect:1;
diff --git a/sc/inc/recursionhelper.hxx b/sc/inc/recursionhelper.hxx
index 23422d7c2a71..d91ee0cfbe58 100644
--- a/sc/inc/recursionhelper.hxx
+++ b/sc/inc/recursionhelper.hxx
@@ -59,6 +59,7 @@ class ScRecursionHelper
     bool                                bDoingRecursion;
     bool                                bInIterationReturn;
     bool                                bConverging;
+    std::vector< ScFormulaCell* >       aTemporaryGroupCells;
 
     void Init();
     void ResetIteration();
@@ -107,6 +108,9 @@ public:
     bool PushFormulaGroup(ScFormulaCell* pCell);
     void PopFormulaGroup();
     bool AnyParentFGInCycle();
+
+    void AddTemporaryGroupCell(ScFormulaCell* cell);
+    void CleanTemporaryGroupCells();
 };
 
 /** A class to wrap ScRecursionHelper::PushFormulaGroup(),
diff --git a/sc/qa/unit/copy_paste_test.cxx b/sc/qa/unit/copy_paste_test.cxx
index e2a8b51a030a..742005df7e26 100644
--- a/sc/qa/unit/copy_paste_test.cxx
+++ b/sc/qa/unit/copy_paste_test.cxx
@@ -207,7 +207,7 @@ void ScCopyPasteTest::testTdf84411()
     CPPUNIT_ASSERT(pModel != nullptr);
     bool bOpenCLState = ScCalcConfig::isOpenCLEnabled();
     pModel->enableOpenCL(false);
-    CPPUNIT_ASSERT(!ScCalcConfig::isOpenCLEnabled());
+    CPPUNIT_ASSERT(!ScCalcConfig::isOpenCLEnabled() || 
ScCalcConfig::getForceCalculationType() == ForceCalculationOpenCL);
     pModel->enableAutomaticCalculation(true);
 
 
diff --git a/sc/source/core/data/formulacell.cxx 
b/sc/source/core/data/formulacell.cxx
index 7b0f9e47b3fe..8d16fdf0d352 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -1483,12 +1483,43 @@ public:
         }
     }
 };
-}
+
+// Forced calculation: OpenCL and threads require formula groups, so force 
even single cells to be a "group".
+// Remove the group again at the end, since there are some places throughout 
the code
+// that do not handle well groups with just 1 cell. Remove the groups only 
when the recursion level
+// reaches 0 again (groups contain some info such as disabling threading 
because of cycles, so removing
+// a group immediately would remove the info), for this reason affected cells 
are stored in the recursion
+// helper.
+struct TemporaryCellGroupMaker
+{
+    TemporaryCellGroupMaker( ScFormulaCell* cell, bool enable )
+        : mCell( cell )
+        , mEnabled( enable )
+    {
+        if( mEnabled && mCell->GetCellGroup() == nullptr )
+        {
+            mCell->CreateCellGroup( 1, false );
+            mCell->GetDocument()->GetRecursionHelper().AddTemporaryGroupCell( 
mCell );
+        }
+    }
+    ~TemporaryCellGroupMaker()
+    {
+        if( mEnabled )
+            
mCell->GetDocument()->GetRecursionHelper().CleanTemporaryGroupCells();
+    }
+    ScFormulaCell* mCell;
+    const bool mEnabled;
+};
+
+} // namespace
 
 void ScFormulaCell::Interpret()
 {
     ScRecursionHelper& rRecursionHelper = pDocument->GetRecursionHelper();
 
+    static ForceCalculationType forceType = 
ScCalcConfig::getForceCalculationType();
+    TemporaryCellGroupMaker cellGroupMaker( this, forceType != 
ForceCalculationNone && forceType != ForceCalculationCore );
+
     ScFormulaCell* pTopCell = mxGroup ? mxGroup->mpTopCell : this;
 
     if (pTopCell->mbSeenInPath && rRecursionHelper.GetDepComputeLevel())
@@ -4473,9 +4504,12 @@ bool ScFormulaCell::InterpretFormulaGroup()
         return false;
     }
 
-    // To temporarily use threading for sc unit tests regardless of the size 
of the formula group,
-    // add the condition !std::getenv("LO_TESTNAME") below (with &&)
-    if (GetWeight() < 
ScInterpreter::GetGlobalConfig().mnOpenCLMinimumFormulaGroupSize)
+    // Use SC_TEST_CALCULATION=opencl/threads to force calculation e.g. for 
unittests
+    static ForceCalculationType forceType = 
ScCalcConfig::getForceCalculationType();
+    if (forceType == ForceCalculationCore
+        || ( GetWeight() < 
ScInterpreter::GetGlobalConfig().mnOpenCLMinimumFormulaGroupSize
+            && forceType != ForceCalculationOpenCL
+            && forceType != ForceCalculationThreads))
     {
         mxGroup->meCalcState = sc::GroupCalcDisabled;
         aScope.addGroupSizeThresholdMessage(*this);
@@ -4802,7 +4836,8 @@ bool 
ScFormulaCell::InterpretFormulaGroupOpenCL(sc::FormulaLogger::GroupScope& a
         if (pInterpreter == nullptr ||
             !pInterpreter->interpret(*pDocument, xGroup->mpTopCell->aPos, 
xGroup, aCode))
         {
-            SAL_INFO("sc.opencl", "interpreting group " << mxGroup << " (state 
" << static_cast<int>(mxGroup->meCalcState) << ") failed, disabling");
+            SAL_INFO("sc.opencl", "interpreting group " << 
mxGroup->mpTopCell->aPos
+                << " (state " << static_cast<int>(mxGroup->meCalcState) << ") 
failed, disabling");
             mxGroup->meCalcState = sc::GroupCalcDisabled;
 
             // Undo the hack above
diff --git a/sc/source/core/opencl/formulagroupcl.cxx 
b/sc/source/core/opencl/formulagroupcl.cxx
index a0c7a098c579..7df68fc77fab 100644
--- a/sc/source/core/opencl/formulagroupcl.cxx
+++ b/sc/source/core/opencl/formulagroupcl.cxx
@@ -3843,6 +3843,9 @@ bool FormulaGroupInterpreterOpenCL::interpret( 
ScDocument& rDoc,
 
     genRPNTokens(rDoc, rTopPos, rCode);
 
+    if( rCode.GetCodeLen() == 0 )
+        return false;
+
     CLInterpreterContext aCxt = createCLInterpreterContext(maCalcConfig, 
xGroup, rCode);
     if (!aCxt.isValid())
         return false;
diff --git a/sc/source/core/tool/calcconfig.cxx 
b/sc/source/core/tool/calcconfig.cxx
index 4a1f5d3d3c27..784bd4690df0 100644
--- a/sc/source/core/tool/calcconfig.cxx
+++ b/sc/source/core/tool/calcconfig.cxx
@@ -43,10 +43,44 @@ static rtl::Reference<ConfigurationListener> const & 
getFormulaCalculationListen
     return xListener;
 }
 
+static ForceCalculationType forceCalculationTypeInit()
+{
+    const char* env = getenv( "SC_FORCE_CALCULATION" );
+    if( env != nullptr )
+    {
+        if( strcmp( env, "opencl" ) == 0 )
+        {
+            SAL_INFO("sc.core.formulagroup", "Forcing calculations to use 
OpenCL");
+            return ForceCalculationOpenCL;
+        }
+        if( strcmp( env, "threads" ) == 0 )
+        {
+            SAL_INFO("sc.core.formulagroup", "Forcing calculations to use 
threads");
+            return ForceCalculationThreads;
+        }
+        if( strcmp( env, "core" ) == 0 )
+        {
+            SAL_INFO("sc.core.formulagroup", "Forcing calculations to use 
core");
+            return ForceCalculationCore;
+        }
+        SAL_WARN("sc.core.formulagroup", "Unrecognized value of 
SC_TEST_CALCULATION");
+    }
+    return ForceCalculationNone;
+}
+
+ForceCalculationType ScCalcConfig::getForceCalculationType()
+{
+    static const ForceCalculationType type = forceCalculationTypeInit();
+    return type;
+}
+
 bool ScCalcConfig::isOpenCLEnabled()
 {
     if (utl::ConfigManager::IsFuzzing())
         return false;
+    static ForceCalculationType force = getForceCalculationType();
+    if( force != ForceCalculationNone )
+        return force == ForceCalculationOpenCL;
     static comphelper::ConfigurationListenerProperty<bool> 
gOpenCLEnabled(getMiscListener(), "UseOpenCL");
     return gOpenCLEnabled.get();
 }
@@ -55,6 +89,9 @@ bool ScCalcConfig::isThreadingEnabled()
 {
     if (utl::ConfigManager::IsFuzzing())
         return false;
+    static ForceCalculationType force = getForceCalculationType();
+    if( force != ForceCalculationNone )
+        return force == ForceCalculationThreads;
     static comphelper::ConfigurationListenerProperty<bool> 
gThreadingEnabled(getFormulaCalculationListener(), 
"UseThreadedCalculationForFormulaGroups");
     return gThreadingEnabled.get();
 }
diff --git a/sc/source/core/tool/recursionhelper.cxx 
b/sc/source/core/tool/recursionhelper.cxx
index dd5be99c7155..1375048759e8 100644
--- a/sc/source/core/tool/recursionhelper.cxx
+++ b/sc/source/core/tool/recursionhelper.cxx
@@ -157,6 +157,21 @@ bool ScRecursionHelper::AnyParentFGInCycle()
     return false;
 }
 
+void ScRecursionHelper::AddTemporaryGroupCell(ScFormulaCell* cell)
+{
+    aTemporaryGroupCells.push_back( cell );
+}
+
+void ScRecursionHelper::CleanTemporaryGroupCells()
+{
+    if( GetRecursionCount() == 0 )
+    {
+        for( ScFormulaCell* cell : aTemporaryGroupCells )
+            cell->SetCellGroup( nullptr );
+        aTemporaryGroupCells.clear();
+    }
+}
+
 
ScFormulaGroupCycleCheckGuard::ScFormulaGroupCycleCheckGuard(ScRecursionHelper& 
rRecursionHelper, ScFormulaCell* pCell) :
     mrRecHelper(rRecursionHelper)
 {
diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx
index 22d75e24c58c..3c6baec93899 100644
--- a/sc/source/ui/unoobj/docuno.cxx
+++ b/sc/source/ui/unoobj/docuno.cxx
@@ -3125,13 +3125,15 @@ void ScModelObj::HandleCalculateEvents()
 
 sal_Bool ScModelObj::isOpenCLEnabled()
 {
-    return officecfg::Office::Common::Misc::UseOpenCL::get();
+    return ScCalcConfig::isOpenCLEnabled();
 }
 
 void ScModelObj::enableOpenCL(sal_Bool bEnable)
 {
     if (ScCalcConfig::isOpenCLEnabled() == static_cast<bool>(bEnable))
         return;
+    if (ScCalcConfig::getForceCalculationType() != ForceCalculationNone)
+        return;
 
     std::shared_ptr<comphelper::ConfigurationChanges> 
batch(comphelper::ConfigurationChanges::create());
     officecfg::Office::Common::Misc::UseOpenCL::set(bEnable, batch);
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to