[Libreoffice-commits] core.git: 5 commits - include/o3tl include/vcl o3tl/CppunitTest_o3tl_tests.mk o3tl/qa scp2/source vcl/inc vcl/opengl vcl/unx
Tomaž Vajngerl
tomaz.vajngerl at collabora.co.uk
Fri Jul 24 03:15:55 PDT 2015
include/o3tl/lru_map.hxx | 141 ++++++++++++++++++
include/vcl/salnativewidgets.hxx | 42 +++++
o3tl/CppunitTest_o3tl_tests.mk | 1
o3tl/qa/test-lru_map.cxx | 239 +++++++++++++++++++++++++++++++
scp2/source/ooo/directory_ooo.scp | 5
scp2/source/ooo/file_extra_ooo.scp | 7
scp2/source/ooo/module_ooo.scp | 1
vcl/inc/opengl/x11/gdiimpl.hxx | 11 +
vcl/inc/unx/salgdi.h | 6
vcl/inc/unx/x11/x11gdiimpl.h | 6
vcl/opengl/x11/gdiimpl.cxx | 95 ++++++++++--
vcl/unx/generic/gdi/gdiimpl.cxx | 11 +
vcl/unx/generic/gdi/gdiimpl.hxx | 5
vcl/unx/generic/gdi/salgdi2.cxx | 15 +
vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx | 23 +-
15 files changed, 587 insertions(+), 21 deletions(-)
New commits:
commit 6c853a986444294dd937cd570a4dc0a31943e432
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date: Fri Jul 24 16:54:44 2015 +0900
Add "styles" template folder + content to installation
Change-Id: Ibb674e17eedfc325d3e335aa074391ad7b2b2aa2
diff --git a/scp2/source/ooo/directory_ooo.scp b/scp2/source/ooo/directory_ooo.scp
index 1337098..0f76c94 100644
--- a/scp2/source/ooo/directory_ooo.scp
+++ b/scp2/source/ooo/directory_ooo.scp
@@ -588,6 +588,11 @@ Directory gid_Dir_Template_Common_Presnt
DosName = "presnt";
End
+Directory gid_Dir_Template_Common_Styles
+ ParentID = gid_Dir_Template_Common;
+ DosName = "styles";
+End
+
Directory gid_Brand_Dir_Program_Services
#if defined MACOSX
ParentID = gid_Brand_Dir_Share;
diff --git a/scp2/source/ooo/file_extra_ooo.scp b/scp2/source/ooo/file_extra_ooo.scp
index c2cc985..f56c028 100644
--- a/scp2/source/ooo/file_extra_ooo.scp
+++ b/scp2/source/ooo/file_extra_ooo.scp
@@ -192,6 +192,13 @@ File gid_File_Extra_Tplpresnt
Name = "extras_tplpresnt.filelist";
End
+File gid_File_Extra_Tpl_styles
+ Dir = FILELIST_DIR;
+ TXT_FILE_BODY;
+ Styles = (FILELIST);
+ Name = "extras_tpl_styles.filelist";
+End
+
File gid_File_Extra_Tplpersonal
Dir = FILELIST_DIR;
TXT_FILE_BODY;
diff --git a/scp2/source/ooo/module_ooo.scp b/scp2/source/ooo/module_ooo.scp
index 50066d3..9acfbe8 100644
--- a/scp2/source/ooo/module_ooo.scp
+++ b/scp2/source/ooo/module_ooo.scp
@@ -80,6 +80,7 @@ Module gid_Module_Root
gid_File_Extra_Tplofficorr,
gid_File_Extra_Tploffimisc,
gid_File_Extra_Tplpresnt,
+ gid_File_Extra_Tpl_styles,
gid_File_Extra_Tplpersonal,
gid_File_Extra_Tplwizbitmap,
gid_File_Extra_Tplwizletter,
commit 1c28c59f927361ef85c8aea8b575d274c532a34d
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date: Fri Jul 24 16:08:01 2015 +0900
opengl: don't cache checkboxes for now
Change-Id: I67d0dcb48d1843587abbc1dc0f7da1f8057b281e
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 2114419..bf5e6f6 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -238,8 +238,15 @@ bool X11OpenGLSalGraphicsImpl::RenderAndCacheNativeControl(X11Pixmap* pPixmap, X
{
std::unique_ptr<TextureCombo> pCombo(new TextureCombo);
bool bResult = RenderPixmap(pPixmap, pMask, nX, nY, *pCombo);
+ if (!bResult)
+ return false;
+
+ if (aControlCacheKey.mnType == CTRL_CHECKBOX)
+ return true;
+
ControlCachePair pair(aControlCacheKey, std::move(pCombo));
gTextureCache.insert(std::move(pair));
+
return bResult;
}
commit 3bc00eca4acf9dfc3b2834077cee552f32c8f107
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date: Fri Jul 24 14:19:35 2015 +0900
Use LRU map for caching of native widgets
Change-Id: Ia0423dac5309aabc5e81357cf4f67b5ee14bab31
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 3890b64..2114419 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -25,6 +25,8 @@
#include <vcl/opengl/OpenGLContext.hxx>
#include <vcl/opengl/OpenGLHelper.hxx>
+#include <o3tl/lru_map.hxx>
+
X11OpenGLSalGraphicsImpl::X11OpenGLSalGraphicsImpl( X11SalGraphics& rParent ):
OpenGLSalGraphicsImpl(rParent,rParent.GetGeometryProvider()),
mrParent(rParent)
@@ -117,9 +119,10 @@ struct TextureCombo
std::unique_ptr<OpenGLTexture> mpMask;
};
-typedef std::unordered_map<ControlCacheKey, std::unique_ptr<TextureCombo>, ControlCacheHashFunction> ControlCacheType;
+typedef typename std::pair<ControlCacheKey, std::unique_ptr<TextureCombo>> ControlCachePair;
+typedef o3tl::lru_map<ControlCacheKey, std::unique_ptr<TextureCombo>, ControlCacheHashFunction> ControlCacheType;
-ControlCacheType gTextureCache;
+ControlCacheType gTextureCache(200);
bool X11OpenGLSalGraphicsImpl::RenderPixmap(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY, TextureCombo& rCombo)
{
@@ -235,7 +238,8 @@ bool X11OpenGLSalGraphicsImpl::RenderAndCacheNativeControl(X11Pixmap* pPixmap, X
{
std::unique_ptr<TextureCombo> pCombo(new TextureCombo);
bool bResult = RenderPixmap(pPixmap, pMask, nX, nY, *pCombo);
- gTextureCache[aControlCacheKey] = std::move(pCombo);
+ ControlCachePair pair(aControlCacheKey, std::move(pCombo));
+ gTextureCache.insert(std::move(pair));
return bResult;
}
commit 80a92134806a876287818530eb61c6bb536a05f9
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date: Fri Jul 24 13:39:22 2015 +0900
LRU map (cache) implementation to o3tl + tests
Change-Id: I6b1a39918e6c8c67712be2c8e9907266dcfefedb
diff --git a/include/o3tl/lru_map.hxx b/include/o3tl/lru_map.hxx
new file mode 100644
index 0000000..6d3b725
--- /dev/null
+++ b/include/o3tl/lru_map.hxx
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#ifndef INCLUDED_O3TL_LRU_MAP_HXX
+#define INCLUDED_O3TL_LRU_MAP_HXX
+
+#include <list>
+#include <unordered_map>
+
+namespace o3tl
+{
+
+/** LRU map
+ *
+ * Similar to unordered_map (it actually uses it) with additionaly functionality
+ * which removes the entries that have been "least recently used" when the size
+ * hits the specified capacity.
+ *
+ * It only implements the minimal methods needed and the implementation is NOT
+ * thread safe.
+ *
+ * The implementation is as simple as possible but it still uses O(1) complexity
+ * for most of the operations with a combination unordered map and linked list.
+ *
+ **/
+template<typename Key, typename Value, class KeyHash = std::hash<Key>>
+class lru_map SAL_FINAL
+{
+private:
+ typedef typename std::pair<Key, Value> key_value_pair_t;
+ typedef std::list<key_value_pair_t> list_t;
+ typedef typename list_t::iterator list_iterator_t;
+ typedef typename list_t::const_iterator list_const_iterator_t;
+
+ typedef std::unordered_map<Key, list_iterator_t, KeyHash> map_t;
+ typedef typename map_t::iterator map_iterator_t;
+ typedef typename map_t::const_iterator map_const_iterator_t;
+
+ list_t mLruList;
+ map_t mLruMap;
+ const size_t mMaxSize;
+
+ inline void checkLRU()
+ {
+ if (mLruMap.size() > mMaxSize)
+ {
+ // remove from map
+ mLruMap.erase(mLruList.back().first);
+ // remove from list
+ mLruList.pop_back();
+ }
+ }
+public:
+ typedef list_iterator_t iterator;
+ typedef list_const_iterator_t const_iterator;
+
+ lru_map(size_t nMaxSize)
+ : mMaxSize(nMaxSize)
+ {}
+
+ void insert(key_value_pair_t& rPair)
+ {
+ map_iterator_t iterator = mLruMap.find(rPair.first);
+
+ if (iterator == mLruMap.end()) // doesn't exist -> add to queue and map
+ {
+ // add to front of the list
+ mLruList.push_front(rPair);
+ // add the list position (iterator) to the map
+ mLruMap[rPair.first] = mLruList.begin();
+ checkLRU();
+ }
+ else // already exists -> replace value
+ {
+ // replace value
+ iterator->second->second = rPair.second;
+ // bring to front of the lru list
+ mLruList.splice(mLruList.begin(), mLruList, iterator->second);
+ }
+ }
+
+ void insert(key_value_pair_t&& rPair)
+ {
+ map_iterator_t iterator = mLruMap.find(rPair.first);
+
+ if (iterator == mLruMap.end()) // doesn't exist -> add to list and map
+ {
+ // add to front of the list
+ mLruList.push_front(std::move(rPair));
+ // add the list position (iterator) to the map
+ mLruMap[rPair.first] = mLruList.begin();
+ checkLRU();
+ }
+ else // already exists -> replace value
+ {
+ // replace value
+ iterator->second->second = std::move(rPair.second);
+ // push to back of the lru list
+ mLruList.splice(mLruList.begin(), mLruList, iterator->second);
+ }
+ }
+
+ const list_const_iterator_t find(const Key& key)
+ {
+ const map_iterator_t iterator = mLruMap.find(key);
+ if (iterator == mLruMap.cend()) // can't find entry for the key
+ {
+ // return empty iterator
+ return mLruList.cend();
+ }
+ else
+ {
+ // push to back of the lru list
+ mLruList.splice(mLruList.begin(), mLruList, iterator->second);
+ return iterator->second;
+ }
+ }
+
+ const list_const_iterator_t end() const
+ {
+ return mLruList.end();
+ }
+
+ size_t size() const
+ {
+ return mLruList.size();
+ }
+};
+
+}
+
+#endif /* INCLUDED_O3TL_LRU_MAP_HXX */
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/o3tl/CppunitTest_o3tl_tests.mk b/o3tl/CppunitTest_o3tl_tests.mk
index 66f2951..c8f8f6b 100644
--- a/o3tl/CppunitTest_o3tl_tests.mk
+++ b/o3tl/CppunitTest_o3tl_tests.mk
@@ -33,6 +33,7 @@ $(eval $(call gb_CppunitTest_add_exception_objects,o3tl_tests,\
o3tl/qa/test-vector_pool \
o3tl/qa/test-sorted_vector \
o3tl/qa/test-typed_flags \
+ o3tl/qa/test-lru_map \
))
# vim: set noet sw=4:
diff --git a/o3tl/qa/test-lru_map.cxx b/o3tl/qa/test-lru_map.cxx
new file mode 100644
index 0000000..d9428e3
--- /dev/null
+++ b/o3tl/qa/test-lru_map.cxx
@@ -0,0 +1,239 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <sal/types.h>
+#include "cppunit/TestAssert.h"
+#include "cppunit/TestFixture.h"
+#include "cppunit/extensions/HelperMacros.h"
+
+#include <o3tl/lru_map.hxx>
+
+#include <boost/functional/hash.hpp>
+
+using namespace ::o3tl;
+
+class lru_map_test : public CppUnit::TestFixture
+{
+public:
+ void testBaseUsage();
+ void testReplaceKey();
+ void testReplaceValue();
+ void testLruRemoval();
+ void testCustomHash();
+
+ CPPUNIT_TEST_SUITE(lru_map_test);
+ CPPUNIT_TEST(testBaseUsage);
+ CPPUNIT_TEST(testReplaceKey);
+ CPPUNIT_TEST(testReplaceValue);
+ CPPUNIT_TEST(testLruRemoval);
+ CPPUNIT_TEST(testCustomHash);
+ CPPUNIT_TEST_SUITE_END();
+};
+
+void lru_map_test::testBaseUsage()
+{
+ o3tl::lru_map<int, int> lru(10);
+ lru.insert(std::make_pair<int, int>(1, 1));
+
+ std::pair<int, int> pair;
+ for (int i = 2; i < 7; i++)
+ {
+ pair.first = pair.second = i;
+ lru.insert(pair);
+ }
+
+ CPPUNIT_ASSERT_EQUAL(size_t(6), lru.size());
+
+ o3tl::lru_map<int, int>::const_iterator it;
+
+ it = lru.find(2);
+ CPPUNIT_ASSERT(it != lru.end());
+ CPPUNIT_ASSERT_EQUAL(2, it->second);
+
+ it = lru.find(5);
+ CPPUNIT_ASSERT(it != lru.end());
+ CPPUNIT_ASSERT_EQUAL(5, it->second);
+
+ it = lru.find(0);
+ CPPUNIT_ASSERT(it == lru.end());
+}
+
+void lru_map_test::testReplaceValue()
+{
+ o3tl::lru_map<int, int> lru(2);
+ // check if map is empty
+ CPPUNIT_ASSERT_EQUAL(size_t(0), lru.size());
+
+ // check if inserting entry with with same key replaces the value
+
+ // inserting new entry
+ lru.insert(std::make_pair<int, int>(1, 2));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());
+ CPPUNIT_ASSERT_EQUAL(2, lru.find(1)->second);
+
+ // inserting new entry with key that alreay exists
+ lru.insert(std::make_pair<int, int>(1, 4));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());
+ CPPUNIT_ASSERT_EQUAL(4, lru.find(1)->second);
+
+ // inserting new entry
+ lru.insert(std::make_pair<int, int>(2, 200));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
+ CPPUNIT_ASSERT_EQUAL(4, lru.find(1)->second);
+ CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);
+
+ // check if insert with same key, moves the entry back of the lru queu
+
+ // inserting new entry with key that alreay exists
+ lru.insert(std::make_pair<int, int>(1, 6));
+ // inserting new entry, lru removed
+ lru.insert(std::make_pair<int, int>(3, 300));
+
+ CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
+ CPPUNIT_ASSERT_EQUAL(6, lru.find(1)->second);
+ CPPUNIT_ASSERT_EQUAL(300, lru.find(3)->second);
+
+}
+
+void lru_map_test::testReplaceKey()
+{
+ o3tl::lru_map<int, int> lru(2);
+
+ // inserting new entry
+ lru.insert(std::make_pair<int, int>(1, 100));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());
+ CPPUNIT_ASSERT_EQUAL(100, lru.find(1)->second);
+ CPPUNIT_ASSERT(lru.find(2) == lru.end());
+ CPPUNIT_ASSERT(lru.find(3) == lru.end());
+
+ // inserting new entry
+ lru.insert(std::make_pair<int, int>(2, 200));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
+ CPPUNIT_ASSERT_EQUAL(100, lru.find(1)->second);
+ CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);
+ CPPUNIT_ASSERT(lru.find(3) == lru.end());
+
+ // inserting new entry, lru entry is removed
+ lru.insert(std::make_pair<int, int>(3, 300));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
+ CPPUNIT_ASSERT(lru.find(1) == lru.end());
+ CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);
+ CPPUNIT_ASSERT_EQUAL(300, lru.find(3)->second);
+
+ // inserting new entry, lru entry is removed
+ std::pair<int, int> pair(4, 400);
+ lru.insert(pair);
+ CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
+ CPPUNIT_ASSERT(lru.find(1) == lru.end());
+ CPPUNIT_ASSERT(lru.find(2) == lru.end());
+ CPPUNIT_ASSERT_EQUAL(300, lru.find(3)->second);
+ CPPUNIT_ASSERT_EQUAL(400, lru.find(4)->second);
+}
+
+void lru_map_test::testLruRemoval()
+{
+ o3tl::lru_map<int, int> lru(5);
+ CPPUNIT_ASSERT_EQUAL(size_t(0), lru.size());
+
+ // fill up..
+ lru.insert(std::make_pair<int, int>(1, 100));
+ lru.insert(std::make_pair<int, int>(2, 200));
+ lru.insert(std::make_pair<int, int>(3, 300));
+ lru.insert(std::make_pair<int, int>(4, 400));
+ lru.insert(std::make_pair<int, int>(5, 500));
+ CPPUNIT_ASSERT_EQUAL(size_t(5), lru.size());
+ CPPUNIT_ASSERT_EQUAL(100, lru.find(1)->second);
+ CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);
+ CPPUNIT_ASSERT_EQUAL(300, lru.find(3)->second);
+ CPPUNIT_ASSERT_EQUAL(400, lru.find(4)->second);
+ CPPUNIT_ASSERT_EQUAL(500, lru.find(5)->second);
+
+ // add one more entry - lru entry should be removed
+ lru.insert(std::make_pair<int, int>(6, 600));
+
+ CPPUNIT_ASSERT_EQUAL(size_t(5), lru.size());
+ CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);
+ CPPUNIT_ASSERT_EQUAL(300, lru.find(3)->second);
+ CPPUNIT_ASSERT_EQUAL(400, lru.find(4)->second);
+ CPPUNIT_ASSERT_EQUAL(500, lru.find(5)->second);
+ CPPUNIT_ASSERT_EQUAL(600, lru.find(6)->second);
+
+ // access the lru entry to put it at the back of the lru queue
+ lru.find(2);
+ // add new entry - lru entry should be removed
+ lru.insert(std::make_pair<int, int>(7, 700));
+
+ CPPUNIT_ASSERT_EQUAL(size_t(5), lru.size());
+ CPPUNIT_ASSERT_EQUAL(200, lru.find(2)->second);
+ CPPUNIT_ASSERT_EQUAL(400, lru.find(4)->second);
+ CPPUNIT_ASSERT_EQUAL(500, lru.find(5)->second);
+ CPPUNIT_ASSERT_EQUAL(600, lru.find(6)->second);
+ CPPUNIT_ASSERT_EQUAL(700, lru.find(7)->second);
+}
+
+struct TestClassKey
+{
+ int mA;
+ int mB;
+
+ TestClassKey(int a, int b)
+ : mA(a)
+ , mB(b)
+ {}
+
+ bool operator==(TestClassKey const& aOther) const
+ {
+ return mA == aOther.mA
+ && mB == aOther.mB;
+ }
+};
+
+struct TestClassKeyHashFunction
+{
+ std::size_t operator()(TestClassKey const& aKey) const
+ {
+ std::size_t seed = 0;
+ boost::hash_combine(seed, aKey.mA);
+ boost::hash_combine(seed, aKey.mB);
+ return seed;
+ }
+};
+
+void lru_map_test::testCustomHash()
+{
+ // check lru_map with custom hash function
+ o3tl::lru_map<TestClassKey, int, TestClassKeyHashFunction> lru(2);
+ CPPUNIT_ASSERT_EQUAL(size_t(0), lru.size());
+
+ lru.insert(std::make_pair<TestClassKey, int>(TestClassKey(1,1), 2));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());
+
+ lru.insert(std::make_pair<TestClassKey, int>(TestClassKey(1,1), 7));
+ CPPUNIT_ASSERT_EQUAL(size_t(1), lru.size());
+
+ lru.insert(std::make_pair<TestClassKey, int>(TestClassKey(1,2), 9));
+ CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
+
+ CPPUNIT_ASSERT(lru.end() == lru.find(TestClassKey(0,0))); // non existent
+ CPPUNIT_ASSERT_EQUAL(7, lru.find(TestClassKey(1,1))->second);
+ CPPUNIT_ASSERT_EQUAL(9, lru.find(TestClassKey(1,2))->second);
+
+ lru.insert(std::make_pair<TestClassKey, int>(TestClassKey(2,1), 13));
+
+ CPPUNIT_ASSERT_EQUAL(size_t(2), lru.size());
+
+ CPPUNIT_ASSERT(lru.end() == lru.find(TestClassKey(1,1)));
+ CPPUNIT_ASSERT_EQUAL(9, lru.find(TestClassKey(1,2))->second);
+ CPPUNIT_ASSERT_EQUAL(13, lru.find(TestClassKey(2,1))->second);
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(lru_map_test);
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
commit 450727fdffa4a0dc3b2d4e635a5c1bc0411b3c36
Author: Tomaž Vajngerl <tomaz.vajngerl at collabora.co.uk>
Date: Thu Jul 23 19:15:20 2015 +0900
tdf#92018 cache native controls for X11 OpenGL backend (for now)
Change-Id: I85c7cc01113bc4ac810c450a6460059463cc8e03
diff --git a/include/vcl/salnativewidgets.hxx b/include/vcl/salnativewidgets.hxx
index 5177efe..8118b29 100644
--- a/include/vcl/salnativewidgets.hxx
+++ b/include/vcl/salnativewidgets.hxx
@@ -25,6 +25,8 @@
#include <tools/gen.hxx>
#include <o3tl/typed_flags_set.hxx>
+#include <boost/functional/hash.hpp>
+
/* Control Types:
*
* Specify the overall, whole control
@@ -254,6 +256,46 @@ namespace o3tl
template<> struct typed_flags<ControlState> : is_typed_flags<ControlState, 0xc007f> {};
}
+class ControlCacheKey
+{
+public:
+ ControlType mnType;
+ ControlPart mnPart;
+ ControlState mnState;
+ Size maSize;
+
+ ControlCacheKey(ControlType nType, ControlPart nPart, ControlState nState, const Size& rSize)
+ : mnType(nType)
+ , mnPart(nPart)
+ , mnState(nState)
+ , maSize(rSize)
+ {}
+
+ bool operator==(ControlCacheKey const& aOther) const
+ {
+ return mnType == aOther.mnType
+ && mnPart == aOther.mnPart
+ && mnState == aOther.mnState
+ && maSize.Width() == aOther.maSize.Width()
+ && maSize.Height() == aOther.maSize.Height();
+ }
+};
+
+struct ControlCacheHashFunction
+{
+ std::size_t operator()(ControlCacheKey const& aCache) const
+ {
+ std::size_t seed = 0;
+ boost::hash_combine(seed, aCache.mnType);
+ boost::hash_combine(seed, aCache.mnPart);
+ boost::hash_combine(seed, aCache.mnState);
+ boost::hash_combine(seed, aCache.maSize.Width());
+ boost::hash_combine(seed, aCache.maSize.Height());
+ return seed;
+ }
+};
+
+
/* ButtonValue:
*
* Identifies the tri-state value options
diff --git a/vcl/inc/opengl/x11/gdiimpl.hxx b/vcl/inc/opengl/x11/gdiimpl.hxx
index feb3961..9e2ece3 100644
--- a/vcl/inc/opengl/x11/gdiimpl.hxx
+++ b/vcl/inc/opengl/x11/gdiimpl.hxx
@@ -16,6 +16,8 @@
#include "unx/x11/x11gdiimpl.h"
#include "openglgdiimpl.hxx"
+class TextureCombo;
+
class VCL_PLUGIN_PUBLIC X11OpenGLSalGraphicsImpl : public OpenGLSalGraphicsImpl, public X11GraphicsImpl
{
private:
@@ -29,6 +31,8 @@ protected:
virtual OpenGLContext* CreateWinContext() SAL_OVERRIDE;
virtual bool UseContext( OpenGLContext* pContext ) SAL_OVERRIDE;
+ bool RenderPixmap(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY, TextureCombo& rCombo);
+
public:
// implementation of X11GraphicsImpl
@@ -37,7 +41,12 @@ public:
virtual void Init() SAL_OVERRIDE;
bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
- bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) SAL_OVERRIDE;
+ bool RenderPixmapToScreen(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY) SAL_OVERRIDE;
+
+ bool RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& aControlCacheKey) SAL_OVERRIDE;
+ bool TryRenderCachedNativeControl(ControlCacheKey& rControlCacheKey,
+ int nX, int nY) SAL_OVERRIDE;
};
#endif // INCLUDED_VCL_INC_OPENGL_X11_GDIIMPL_HXX
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 99fe40d..3e80153 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -267,6 +267,12 @@ public:
virtual void BeginPaint() SAL_OVERRIDE;
virtual void EndPaint() SAL_OVERRIDE;
+ bool TryRenderCachedNativeControl(ControlCacheKey& aControlCacheKey,
+ int nX, int nY);
+
+ bool RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& aControlCacheKey);
+
// fill a pixmap from a screen region
bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY );
diff --git a/vcl/inc/unx/x11/x11gdiimpl.h b/vcl/inc/unx/x11/x11gdiimpl.h
index 22859c3..c504364 100644
--- a/vcl/inc/unx/x11/x11gdiimpl.h
+++ b/vcl/inc/unx/x11/x11gdiimpl.h
@@ -12,6 +12,8 @@
#include "unx/pixmap.hxx"
+class ControlCacheKey;
+
class X11GraphicsImpl
{
public:
@@ -19,6 +21,10 @@ public:
virtual bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) = 0;
virtual bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) = 0;
+
+ virtual bool TryRenderCachedNativeControl(ControlCacheKey& rControlCacheKey, int nX, int nY) = 0;
+ virtual bool RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& aControlCacheKey) = 0;
};
#endif // INCLUDED_VCL_INC_UNX_X11_X11GDIIMPL_HXX
diff --git a/vcl/opengl/x11/gdiimpl.cxx b/vcl/opengl/x11/gdiimpl.cxx
index 1d453da..3890b64 100644
--- a/vcl/opengl/x11/gdiimpl.cxx
+++ b/vcl/opengl/x11/gdiimpl.cxx
@@ -111,18 +111,28 @@ bool X11OpenGLSalGraphicsImpl::FillPixmapFromScreen( X11Pixmap* pPixmap, int nX,
return true;
}
-bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY )
+struct TextureCombo
+{
+ std::unique_ptr<OpenGLTexture> mpTexture;
+ std::unique_ptr<OpenGLTexture> mpMask;
+};
+
+typedef std::unordered_map<ControlCacheKey, std::unique_ptr<TextureCombo>, ControlCacheHashFunction> ControlCacheType;
+
+ControlCacheType gTextureCache;
+
+bool X11OpenGLSalGraphicsImpl::RenderPixmap(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY, TextureCombo& rCombo)
{
- const int aAttribs[] = {
+ const int aAttribs[] =
+ {
GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT,
GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGBA_EXT,
None
};
+
Display* pDisplay = mrParent.GetXDisplay();
bool bInverted;
- SAL_INFO( "vcl.opengl", "RenderPixmapToScreen (" << nX << " " << nY << ")" );
-
const long nWidth = pPixmap->GetWidth();
const long nHeight = pPixmap->GetHeight();
SalTwoRect aPosAry(0, 0, nWidth, nHeight, nX, nY, nWidth, nHeight);
@@ -145,27 +155,28 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixm
//TODO: lfrb: glXGetProc to get the functions
- OpenGLTexture aTexture( pPixmap->GetWidth(), pPixmap->GetHeight(), false );
+ rCombo.mpTexture.reset(new OpenGLTexture(pPixmap->GetWidth(), pPixmap->GetHeight(), false));
+
glActiveTexture( GL_TEXTURE0 );
- aTexture.Bind();
+ rCombo.mpTexture->Bind();
glXBindTexImageEXT( pDisplay, pGlxPixmap, GLX_FRONT_LEFT_EXT, NULL );
- aTexture.Unbind();
+ rCombo.mpTexture->Unbind();
if( pMask != NULL && pGlxMask )
{
- OpenGLTexture aMaskTexture( pMask->GetWidth(), pMask->GetHeight(), false );
- aMaskTexture.Bind();
+ rCombo.mpMask.reset(new OpenGLTexture(pPixmap->GetWidth(), pPixmap->GetHeight(), false));
+ rCombo.mpMask->Bind();
glXBindTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT, NULL );
- aMaskTexture.Unbind();
+ rCombo.mpMask->Unbind();
- DrawTextureDiff( aTexture, aMaskTexture, aPosAry, bInverted );
+ DrawTextureDiff(*rCombo.mpTexture, *rCombo.mpMask, aPosAry, bInverted);
glXReleaseTexImageEXT( pDisplay, pGlxMask, GLX_FRONT_LEFT_EXT );
glXDestroyPixmap( pDisplay, pGlxMask );
}
else
{
- DrawTexture( aTexture, aPosAry, bInverted );
+ DrawTexture(*rCombo.mpTexture, aPosAry, bInverted);
}
CHECK_GL_ERROR();
@@ -176,7 +187,56 @@ bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixm
PostDraw();
CHECK_GL_ERROR();
+
return true;
}
+bool X11OpenGLSalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY )
+{
+ SAL_INFO( "vcl.opengl", "RenderPixmapToScreen (" << nX << " " << nY << ")" );
+
+ TextureCombo aCombo;
+ return RenderPixmap(pPixmap, pMask, nX, nY, aCombo);
+}
+
+bool X11OpenGLSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey& rControlCacheKey, int nX, int nY)
+{
+ static bool gbCacheEnabled = !getenv("SAL_WITHOUT_WIDGET_CACHE");
+
+ if (!gbCacheEnabled)
+ return false;
+
+ ControlCacheType::const_iterator iterator = gTextureCache.find(rControlCacheKey);
+
+ if (iterator == gTextureCache.end())
+ return false;
+
+ const std::unique_ptr<TextureCombo>& pCombo = iterator->second;
+
+ PreDraw();
+
+ OpenGLTexture& rTexture = *pCombo->mpTexture;
+
+ SalTwoRect aPosAry(0, 0, rTexture.GetWidth(), rTexture.GetHeight(),
+ nX, nY, rTexture.GetWidth(), rTexture.GetHeight());
+
+ if (pCombo->mpMask)
+ DrawTextureDiff(rTexture, *pCombo->mpMask, aPosAry, true);
+ else
+ DrawTexture(rTexture, aPosAry, true);
+
+ PostDraw();
+
+ return true;
+}
+
+bool X11OpenGLSalGraphicsImpl::RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& aControlCacheKey)
+{
+ std::unique_ptr<TextureCombo> pCombo(new TextureCombo);
+ bool bResult = RenderPixmap(pPixmap, pMask, nX, nY, *pCombo);
+ gTextureCache[aControlCacheKey] = std::move(pCombo);
+ return bResult;
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx
index 7a2beb1..d350d01 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -212,6 +212,17 @@ bool X11SalGraphicsImpl::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* /*
return true;
}
+bool X11SalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey& /*rControlCacheKey*/, int /*nX*/, int /*nY*/)
+{
+ return false;
+}
+
+bool X11SalGraphicsImpl::RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& /*rControlCacheKey*/)
+{
+ return RenderPixmapToScreen(pPixmap, pMask, nX, nY);
+}
+
XID X11SalGraphicsImpl::GetXRenderPicture()
{
XRenderPeer& rRenderPeer = XRenderPeer::GetInstance();
diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx
index f5df99c..3059dc4 100644
--- a/vcl/unx/generic/gdi/gdiimpl.hxx
+++ b/vcl/unx/generic/gdi/gdiimpl.hxx
@@ -279,6 +279,11 @@ public:
void Init() SAL_OVERRIDE;
bool FillPixmapFromScreen( X11Pixmap* pPixmap, int nX, int nY ) SAL_OVERRIDE;
bool RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY ) SAL_OVERRIDE;
+
+ virtual bool TryRenderCachedNativeControl(ControlCacheKey& rControlCacheKey,
+ int nX, int nY) SAL_OVERRIDE;
+ virtual bool RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& aControlCacheKey) SAL_OVERRIDE;
};
#endif
diff --git a/vcl/unx/generic/gdi/salgdi2.cxx b/vcl/unx/generic/gdi/salgdi2.cxx
index b98d9b6..629cf88 100644
--- a/vcl/unx/generic/gdi/salgdi2.cxx
+++ b/vcl/unx/generic/gdi/salgdi2.cxx
@@ -89,6 +89,21 @@ bool X11SalGraphics::RenderPixmapToScreen( X11Pixmap* pPixmap, X11Pixmap* pMask,
return rImpl.RenderPixmapToScreen( pPixmap, pMask, nX, nY );
}
+bool X11SalGraphics::TryRenderCachedNativeControl(ControlCacheKey& rControlCacheKey, int nX, int nY)
+{
+ SAL_INFO( "vcl", "TryRenderCachedNativeControl" );
+ X11GraphicsImpl& rImpl = dynamic_cast<X11GraphicsImpl&>(*mxImpl.get());
+ return rImpl.TryRenderCachedNativeControl(rControlCacheKey, nX, nY);
+}
+
+bool X11SalGraphics::RenderAndCacheNativeControl(X11Pixmap* pPixmap, X11Pixmap* pMask, int nX, int nY,
+ ControlCacheKey& rControlCacheKey)
+{
+ SAL_INFO( "vcl", "RenderAndCachePixmap" );
+ X11GraphicsImpl& rImpl = dynamic_cast<X11GraphicsImpl&>(*mxImpl.get());
+ return rImpl.RenderAndCacheNativeControl(pPixmap, pMask, nX, nY, rControlCacheKey);
+}
+
extern "C"
{
static Bool GraphicsExposePredicate( Display*, XEvent* pEvent, XPointer pFrameWindow )
diff --git a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
index 9da1bfa..6a07683 100644
--- a/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
+++ b/vcl/unx/gtk/gdi/salnativewidgets-gtk.cxx
@@ -896,12 +896,23 @@ bool GtkSalGraphics::drawNativeControl(ControlType nType, ControlPart nPart,
if( aClipRegion.IsNull() )
aClipRegion = aCtrlRect;
+ Rectangle aPixmapRect;
+
+ // make pixmap a little larger since some themes draw decoration
+ // outside the rectangle, see e.g. checkbox
+ aPixmapRect = Rectangle(Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ),
+ Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) );
+
+ ControlCacheKey aControlCacheKey(nType, nPart, nState, aPixmapRect.GetSize());
+ if (TryRenderCachedNativeControl(aControlCacheKey, aPixmapRect.Left(), aPixmapRect.Top()))
+ return true;
+
clipList aClip;
int nPasses = 0;
GdkDrawable* gdkDrawable[2];
std::unique_ptr<GdkX11Pixmap> xPixmap;
std::unique_ptr<GdkX11Pixmap> xMask;
- Rectangle aPixmapRect;
+
if ((bNeedPixmapPaint || (nState & ControlState::DOUBLEBUFFERING))
&& nType != CTRL_SCROLLBAR
&& nType != CTRL_SPINBOX
@@ -911,11 +922,6 @@ bool GtkSalGraphics::drawNativeControl(ControlType nType, ControlPart nPart,
&& ! (nType == CTRL_TOOLBAR && (nPart == PART_THUMB_HORZ || nPart == PART_THUMB_VERT) )
)
{
- // make pixmap a little larger since some themes draw decoration
- // outside the rectangle, see e.g. checkbox
- aPixmapRect = Rectangle( Point( aCtrlRect.Left()-1, aCtrlRect.Top()-1 ),
- Size( aCtrlRect.GetWidth()+2, aCtrlRect.GetHeight()+2) );
-
if( bNeedTwoPasses )
{
xPixmap.reset( NWGetPixmapFromScreen( aPixmapRect, BG_WHITE ) );
@@ -969,7 +975,9 @@ bool GtkSalGraphics::drawNativeControl(ControlType nType, ControlPart nPart,
}
if( xPixmap )
- returnVal = NWRenderPixmapToScreen( xPixmap.get(), xMask.get(), aPixmapRect) && returnVal;
+ returnVal = returnVal && RenderAndCacheNativeControl(xPixmap.get(), xMask.get(),
+ aPixmapRect.Left(), aPixmapRect.Top(),
+ aControlCacheKey);
return returnVal;
}
@@ -4250,7 +4258,6 @@ GdkX11Pixmap* GtkSalGraphics::NWGetPixmapFromScreen( Rectangle srcRect, int nBgC
{
GdkX11Pixmap* pPixmap;
int nDepth = vcl_sal::getSalDisplay(GetGenericData())->GetVisual( m_nXScreen ).GetDepth();
-;
pPixmap = new GdkX11Pixmap( srcRect.GetWidth(), srcRect.GetHeight(), nDepth );
More information about the Libreoffice-commits
mailing list