loolwsd/DocumentBroker.cpp | 29 +++++++++++++--- loolwsd/LOOLKit.cpp | 39 ++++++++++++++++++++-- loolwsd/MessageQueue.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++--- loolwsd/MessageQueue.hpp | 50 ++++++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 14 deletions(-)
New commits: commit 72c1988bc922ba7e5c9d072a2e16c62243a06bea Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Wed Sep 14 18:18:08 2016 -0400 loolwsd: only prioritize tile messages and not tilecombine Change-Id: Ia292e5b499dd4409dc3a672e4d5360c868d6c71f (cherry picked from commit c01629ab2a52f6f4243df458b0505f231e392c49) diff --git a/loolwsd/MessageQueue.cpp b/loolwsd/MessageQueue.cpp index 756e568..0660d2b 100644 --- a/loolwsd/MessageQueue.cpp +++ b/loolwsd/MessageQueue.cpp @@ -158,6 +158,11 @@ void TileQueue::reprioritize(const CursorPosition& cursorPosition) { auto& it = _queue[i]; const std::string msg(it.data(), it.size()); + if (msg.compare(0, 5, "tile ") != 0) + { + continue; + } + auto tile = TileDesc::parse(msg); //FIXME: Expensive, avoid. if (tile.intersectsWithRect(cursorPosition.X, cursorPosition.Y, cursorPosition.Width, cursorPosition.Height)) @@ -178,6 +183,11 @@ void TileQueue::reprioritize(const CursorPosition& cursorPosition) bool TileQueue::priority(const std::string& tileMsg) { + if (tileMsg.compare(0, 5, "tile ") != 0) + { + return false; + } + auto tile = TileDesc::parse(tileMsg); //FIXME: Expensive, avoid. for (auto& pair : _cursorPositions) commit 20428860cc7e3caa2d165df746dffc7443611031 Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Wed Sep 14 18:02:03 2016 -0400 loolwsd: remove cursor of unloading views Change-Id: I4281a5aa101f034007aa227bb18b14eeba806ea0 (cherry picked from commit ad6d77cd3b4ccaeb1da16f100fb3bc3ac4d4c947) diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp index 387a0d5..583b173 100644 --- a/loolwsd/LOOLKit.cpp +++ b/loolwsd/LOOLKit.cpp @@ -940,6 +940,7 @@ private: // Broadcast the demise and removal of session. notifyOtherSessions(sessionId, "remview: " + std::to_string(session.getViewId())); + _tileQueue->removeCursorPosition(session.getViewId()); if (_loKitDocument == nullptr) { commit bbcde1d091ba51beaae37402a10b757d41fc8e49 Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Sun Sep 11 13:18:22 2016 -0400 loolwsd: queue -> tileQueue Change-Id: If61de6807fa7f52a703fe45948df911fe162f69a (cherry picked from commit 2db1db06c75fd67bbc73ba86707f89ee7e4f24c6) diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp index 2207e7d..387a0d5 100644 --- a/loolwsd/LOOLKit.cpp +++ b/loolwsd/LOOLKit.cpp @@ -398,14 +398,14 @@ public: const std::string& jailId, const std::string& docKey, const std::string& url, - std::shared_ptr<TileQueue> queue, + std::shared_ptr<TileQueue> tileQueue, const std::shared_ptr<WebSocket>& ws) : _multiView(std::getenv("LOK_VIEW_CALLBACK")), _loKit(loKit), _jailId(jailId), _docKey(docKey), _url(url), - _queue(std::move(queue)), + _tileQueue(std::move(tileQueue)), _ws(ws), _docPassword(""), _haveDocPassword(false), @@ -419,6 +419,7 @@ public: Log::info("Document ctor for url [" + _url + "] on child [" + _jailId + "] LOK_VIEW_CALLBACK=" + std::to_string(_multiView) + "."); assert(_loKit && _loKit->get()); + _callbackThread.start(*this); } @@ -1230,7 +1231,7 @@ private: { while (true) { - const auto input = pThis->_queue->get(); + const auto input = pThis->_tileQueue->get(); const std::string message(input.data(), input.size()); StringTokenizer tokens(message, " ", StringTokenizer::TOK_IGNORE_EMPTY | StringTokenizer::TOK_TRIM); @@ -1269,7 +1270,7 @@ private: std::string _renderOpts; std::shared_ptr<lok::Document> _loKitDocument; - std::shared_ptr<TileQueue> _queue; + std::shared_ptr<TileQueue> _tileQueue; std::shared_ptr<WebSocket> _ws; // Document password provided commit 2bcbdf3362433d3472e2c2ce6666172b5b52875f Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Wed Sep 14 17:42:50 2016 -0400 loolwsd: tile prioritization per view cursor Change-Id: I1410b64982ac2db04e5a47d744a95b8d2eab5f7e (cherry picked from commit ece87da287433d665a175e92a576f00c639695a2) diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp index 73ade5b..2207e7d 100644 --- a/loolwsd/LOOLKit.cpp +++ b/loolwsd/LOOLKit.cpp @@ -813,6 +813,35 @@ private: std::unique_lock<std::mutex> lock(pDescr->Doc->_mutex); + if (nType == LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR || + nType == LOK_CALLBACK_CELL_CURSOR) + { + Poco::StringTokenizer tokens(payload, ",", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); + auto cursorX = std::stoi(tokens[0]); + auto cursorY = std::stoi(tokens[1]); + auto cursorWidth = std::stoi(tokens[2]); + auto cursorHeight = std::stoi(tokens[3]); + + pDescr->Doc->_tileQueue->updateCursorPosition(0, 0, cursorX, cursorY, cursorWidth, cursorHeight); + } + else if (nType == LOK_CALLBACK_INVALIDATE_VIEW_CURSOR || + nType == LOK_CALLBACK_CELL_VIEW_CURSOR) + { + Poco::JSON::Parser parser; + const auto result = parser.parse(payload); + const auto& command = result.extract<Poco::JSON::Object::Ptr>(); + auto viewId = command->get("viewId").toString(); + auto part = command->get("part").toString(); + auto text = command->get("rectangle").toString(); + Poco::StringTokenizer tokens(text, ",", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); + auto cursorX = std::stoi(tokens[0]); + auto cursorY = std::stoi(tokens[1]); + auto cursorWidth = std::stoi(tokens[2]); + auto cursorHeight = std::stoi(tokens[3]); + + pDescr->Doc->_tileQueue->updateCursorPosition(std::stoi(viewId), std::stoi(part), cursorX, cursorY, cursorWidth, cursorHeight); + } + // Forward to the same view only. // Demultiplexing is done by Core. // TODO: replace with a map to be faster. diff --git a/loolwsd/MessageQueue.cpp b/loolwsd/MessageQueue.cpp index 027051e..756e568 100644 --- a/loolwsd/MessageQueue.cpp +++ b/loolwsd/MessageQueue.cpp @@ -11,6 +11,7 @@ #include <algorithm> +#include <TileDesc.hpp> #include <Log.hpp> MessageQueue::~MessageQueue() @@ -95,9 +96,10 @@ void BasicTileQueue::put_impl(const Payload& value) void TileQueue::put_impl(const Payload& value) { + const auto msg = std::string(value.data(), value.size()); + Log::trace() << "Putting [" << msg << "]" << Log::end; if (!_queue.empty()) { - const auto msg = std::string(value.data(), value.size()); if (msg.compare(0, 4, "tile") == 0 || msg.compare(0, 10, "tilecombine") == 0) { const auto newMsg = msg.substr(0, msg.find(" ver")); @@ -117,18 +119,76 @@ void TileQueue::put_impl(const Payload& value) auto& it = _queue[i]; const std::string old(it.data(), it.size()); const auto oldMsg = old.substr(0, old.find(" ver")); - Log::error(std::to_string(i) + ": " + oldMsg); + Log::trace() << "TileQueue #" << i << ": " << oldMsg << Log::end; if (newMsg == oldMsg) { - Log::trace() << "Replacing duplicate tile: " << oldMsg << " -> " << newMsg << Log::end; + Log::debug() << "Replacing duplicate tile: " << oldMsg << " -> " << newMsg << Log::end; _queue[i] = value; + + if (priority(msg)) + { + // Bump to top. + Log::debug() << "And bumping tile to top: " << msg << Log::end; + _queue.erase(_queue.begin() + i); + _queue.push_front(value); + } + return; } } } } - BasicTileQueue::put_impl(value); + if (priority(msg)) + { + Log::debug() << "Priority tile [" << msg << "]" << Log::end; + _queue.push_front(value); + } + else + { + BasicTileQueue::put_impl(value); + } +} + +/// Bring the underlying tile (if any) to the top. +/// There should be only one overlapping tile at most. +void TileQueue::reprioritize(const CursorPosition& cursorPosition) +{ + for (size_t i = 0; i < _queue.size(); ++i) + { + auto& it = _queue[i]; + const std::string msg(it.data(), it.size()); + auto tile = TileDesc::parse(msg); //FIXME: Expensive, avoid. + + if (tile.intersectsWithRect(cursorPosition.X, cursorPosition.Y, cursorPosition.Width, cursorPosition.Height)) + { + if (i != 0) + { + // Bump to top. + Log::trace() << "Bumping tile to top: " << msg << Log::end; + const Payload payload = it; + _queue.erase(_queue.begin() + i); + _queue.push_front(payload); + } + + return; + } + } +} + +bool TileQueue::priority(const std::string& tileMsg) +{ + auto tile = TileDesc::parse(tileMsg); //FIXME: Expensive, avoid. + + for (auto& pair : _cursorPositions) + { + if (tile.intersectsWithRect(pair.second.X, pair.second.Y, pair.second.Width, pair.second.Height)) + { + return true; + } + } + + return false; } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/loolwsd/MessageQueue.hpp b/loolwsd/MessageQueue.hpp index 8330f0f..f1b14b2 100644 --- a/loolwsd/MessageQueue.hpp +++ b/loolwsd/MessageQueue.hpp @@ -11,8 +11,9 @@ #define INCLUDED_MESSAGEQUEUE_HPP #include <condition_variable> -#include <mutex> #include <deque> +#include <map> +#include <mutex> #include <vector> /** Thread-safe message queue (FIFO). @@ -85,8 +86,55 @@ that the ones closest to the cursor position are returned first. */ class TileQueue : public BasicTileQueue { +private: + + class CursorPosition + { + public: + int Part; + int X; + int Y; + int Width; + int Height; + }; + +public: + + void updateCursorPosition(int viewId, int part, int x, int y, int width, int height) + { + auto cursorPosition = CursorPosition({part, x, y, width, height}); + auto it = _cursorPositions.find(viewId); + if (it != _cursorPositions.end()) + { + it->second = cursorPosition; + } + else + { + _cursorPositions[viewId] = cursorPosition; + } + + reprioritize(cursorPosition); + } + + void removeCursorPosition(int viewId) + { + _cursorPositions.erase(viewId); + } + protected: virtual void put_impl(const Payload& value) override; + +private: + + /// Bring the underlying tile (if any) to the top. + /// There should be only one overlapping tile at most. + void reprioritize(const CursorPosition& cursorPosition); + + /// Check if the given tile msg underlies a cursor. + bool priority(const std::string& tileMsg); + +private: + std::map<int, CursorPosition> _cursorPositions; }; #endif commit 0108579f1da47a304650b5e43b0b046a3229735a Author: Michael Meeks <mich...@linux.site> Date: Wed Sep 14 22:15:43 2016 +0100 Revert "loolwsd: don't combine tiles by row to allow for better culling" This breaks combine-tiles very significantly, viewing images in documents with this appears to show each tile scaling and rendering individually. This reverts commit 99d0ee2ac111e7199626f6c17fb7ce723dac9126. (cherry picked from commit 787ee1d2d2719f4fed161dd66eb7d3e21c512bd3) diff --git a/loolwsd/DocumentBroker.cpp b/loolwsd/DocumentBroker.cpp index fe73d63..043218f 100644 --- a/loolwsd/DocumentBroker.cpp +++ b/loolwsd/DocumentBroker.cpp @@ -532,7 +532,8 @@ void DocumentBroker::handleTileCombinedRequest(TileCombined& tileCombined, Log::trace() << "TileCombined request for " << tileCombined.serialize() << Log::end; // Satisfy as many tiles from the cache. - std::vector<TileDesc> tiles; + // The rest, group by rows. + std::map<int, std::vector<TileDesc>> rows; for (auto& tile : tileCombined.getTiles()) { std::unique_ptr<std::fstream> cachedTile = _tileCache->lookupTile(tile); @@ -586,16 +587,34 @@ void DocumentBroker::handleTileCombinedRequest(TileCombined& tileCombined, } } - tiles.push_back(tile); + const auto tilePosY = tile.getTilePosY(); + auto it = rows.lower_bound(tilePosY); + if (it != rows.end()) + { + it->second.emplace_back(tile); + } + else + { + rows.emplace_hint(it, tilePosY, std::vector<TileDesc>({ tile })); + } } - for (auto& tile : tiles) + if (rows.empty()) { - const auto tileMsg = tile.serialize("tile "); + // Done. + return; + } + + auto& tiles = tileCombined.getTiles(); + for (auto& row : rows) + { + tiles = row.second; + const auto tileMsg = tileCombined.serialize(); Log::debug() << "TileCombined residual request for " << tileMsg << Log::end; // Forward to child to render. - _childProcess->getWebSocket()->sendFrame(tileMsg.data(), tileMsg.size()); + const std::string request = "tilecombine " + tileMsg; + _childProcess->getWebSocket()->sendFrame(request.data(), request.size()); } } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits