1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <graphic/Manager.hxx>
21 #include <impgraph.hxx>
22 #include <sal/log.hxx>
24 #include <officecfg/Office/Common.hxx>
25 #include <unotools/configmgr.hxx>
35 void setupConfigurationValuesIfPossible(sal_Int64
& rMemoryLimit
,
36 std::chrono::seconds
& rAllowedIdleTime
, bool& bSwapEnabled
)
38 if (utl::ConfigManager::IsFuzzing())
43 using officecfg::Office::Common::Cache
;
45 rMemoryLimit
= Cache::GraphicManager::GraphicMemoryLimit::get();
47 = std::chrono::seconds(Cache::GraphicManager::GraphicAllowedIdleTime::get());
48 bSwapEnabled
= Cache::GraphicManager::GraphicSwappingEnabled::get();
56 Manager
& Manager::get()
58 static Manager gStaticManager
;
59 return gStaticManager
;
63 : mnAllowedIdleTime(10)
65 , mnMemoryLimit(300000000)
67 , maSwapOutTimer("graphic::Manager maSwapOutTimer")
69 setupConfigurationValuesIfPossible(mnMemoryLimit
, mnAllowedIdleTime
, mbSwapEnabled
);
73 maSwapOutTimer
.SetInvokeHandler(LINK(this, Manager
, SwapOutTimerHandler
));
74 maSwapOutTimer
.SetTimeout(10000);
75 maSwapOutTimer
.SetDebugName("graphic::Manager maSwapOutTimer");
76 maSwapOutTimer
.Start();
80 void Manager::reduceGraphicMemory()
85 std::scoped_lock
<std::recursive_mutex
> aGuard(maMutex
);
87 for (ImpGraphic
* pEachImpGraphic
: m_pImpGraphicList
)
89 if (mnUsedSize
< mnMemoryLimit
* 0.7)
92 sal_Int64 nCurrentGraphicSize
= getGraphicSizeBytes(pEachImpGraphic
);
93 if (!pEachImpGraphic
->ImplIsSwapOut() && nCurrentGraphicSize
> 1000000)
95 if (!pEachImpGraphic
->mpContext
)
97 auto aCurrent
= std::chrono::high_resolution_clock::now();
98 auto aDeltaTime
= aCurrent
- pEachImpGraphic
->maLastUsed
;
99 auto aSeconds
= std::chrono::duration_cast
<std::chrono::seconds
>(aDeltaTime
);
101 if (aSeconds
> mnAllowedIdleTime
)
102 pEachImpGraphic
->ImplSwapOut();
108 sal_Int64
Manager::getGraphicSizeBytes(const ImpGraphic
* pImpGraphic
)
110 if (!pImpGraphic
->isAvailable())
112 return pImpGraphic
->ImplGetSizeBytes();
115 IMPL_LINK(Manager
, SwapOutTimerHandler
, Timer
*, pTimer
, void)
117 std::scoped_lock
<std::recursive_mutex
> aGuard(maMutex
);
120 reduceGraphicMemory();
124 void Manager::registerGraphic(const std::shared_ptr
<ImpGraphic
>& pImpGraphic
,
125 OUString
const& /*rsContext*/)
127 std::scoped_lock
<std::recursive_mutex
> aGuard(maMutex
);
129 // make some space first
130 if (mnUsedSize
> mnMemoryLimit
)
131 reduceGraphicMemory();
133 // Insert and update the used size (bytes)
134 mnUsedSize
+= getGraphicSizeBytes(pImpGraphic
.get());
135 m_pImpGraphicList
.insert(pImpGraphic
.get());
137 // calculate size of the graphic set
138 sal_Int64 calculatedSize
= 0;
139 for (ImpGraphic
* pEachImpGraphic
: m_pImpGraphicList
)
141 if (!pEachImpGraphic
->ImplIsSwapOut())
143 calculatedSize
+= getGraphicSizeBytes(pEachImpGraphic
);
147 if (calculatedSize
!= mnUsedSize
)
149 SAL_INFO_IF(calculatedSize
!= mnUsedSize
, "vcl.gdi",
150 "Calculated size mismatch. Variable size is '"
151 << mnUsedSize
<< "' but calculated size is '" << calculatedSize
<< "'");
152 mnUsedSize
= calculatedSize
;
156 void Manager::unregisterGraphic(ImpGraphic
* pImpGraphic
)
158 std::scoped_lock
<std::recursive_mutex
> aGuard(maMutex
);
160 mnUsedSize
-= getGraphicSizeBytes(pImpGraphic
);
161 m_pImpGraphicList
.erase(pImpGraphic
);
164 std::shared_ptr
<ImpGraphic
> Manager::copy(std::shared_ptr
<ImpGraphic
> const& rImpGraphicPtr
)
166 auto pReturn
= std::make_shared
<ImpGraphic
>(*rImpGraphicPtr
);
167 registerGraphic(pReturn
, "Copy");
171 std::shared_ptr
<ImpGraphic
> Manager::newInstance()
173 auto pReturn
= std::make_shared
<ImpGraphic
>();
174 registerGraphic(pReturn
, "Empty");
178 std::shared_ptr
<ImpGraphic
> Manager::newInstance(const Bitmap
& rBitmap
)
180 auto pReturn
= std::make_shared
<ImpGraphic
>(rBitmap
);
181 registerGraphic(pReturn
, "Bitmap");
185 std::shared_ptr
<ImpGraphic
> Manager::newInstance(const BitmapEx
& rBitmapEx
)
187 auto pReturn
= std::make_shared
<ImpGraphic
>(rBitmapEx
);
188 registerGraphic(pReturn
, "BitmapEx");
192 std::shared_ptr
<ImpGraphic
> Manager::newInstance(const Animation
& rAnimation
)
194 auto pReturn
= std::make_shared
<ImpGraphic
>(rAnimation
);
195 registerGraphic(pReturn
, "Animation");
199 std::shared_ptr
<ImpGraphic
> Manager::newInstance(const VectorGraphicDataPtr
& rVectorGraphicDataPtr
)
201 auto pReturn
= std::make_shared
<ImpGraphic
>(rVectorGraphicDataPtr
);
202 registerGraphic(pReturn
, "VectorGraphic");
206 std::shared_ptr
<ImpGraphic
> Manager::newInstance(const GDIMetaFile
& rMetaFile
)
208 auto pReturn
= std::make_shared
<ImpGraphic
>(rMetaFile
);
209 registerGraphic(pReturn
, "Metafile");
213 std::shared_ptr
<ImpGraphic
> Manager::newInstance(const GraphicExternalLink
& rGraphicLink
)
215 auto pReturn
= std::make_shared
<ImpGraphic
>(rGraphicLink
);
216 registerGraphic(pReturn
, "GraphicExternalLink");
220 void Manager::swappedIn(const ImpGraphic
* pImpGraphic
)
222 std::scoped_lock
<std::recursive_mutex
> aGuard(maMutex
);
224 mnUsedSize
+= getGraphicSizeBytes(pImpGraphic
);
227 void Manager::swappedOut(const ImpGraphic
* pImpGraphic
)
229 std::scoped_lock
<std::recursive_mutex
> aGuard(maMutex
);
231 mnUsedSize
-= getGraphicSizeBytes(pImpGraphic
);
234 void Manager::changeExisting(const ImpGraphic
* pImpGraphic
, sal_Int64 nOldSizeBytes
)
236 std::scoped_lock
<std::recursive_mutex
> aGuard(maMutex
);
238 mnUsedSize
-= nOldSizeBytes
;
239 mnUsedSize
+= getGraphicSizeBytes(pImpGraphic
);
242 } // end vcl::graphic
244 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */