loolwsd/LOOLKit.cpp | 4 ++ loolwsd/MessageQueue.cpp | 74 ++++++++++++++++++++++++++++++++++++++++------- loolwsd/MessageQueue.hpp | 4 +- loolwsd/TileDesc.hpp | 42 ++++++++++++++++++++++++++ 4 files changed, 113 insertions(+), 11 deletions(-)
New commits: commit e9f37433d7aafb0ac91e240cc4adab758036508f Author: Ashod Nakashian <ashod.nakash...@collabora.co.uk> Date: Thu Sep 15 08:40:26 2016 -0400 loolwsd: combine tiles before rendering to reduce latency Change-Id: I5af2d2a9ddf3b5a3db5bc5f0835687d7cae5b17c Reviewed-on: https://gerrit.libreoffice.org/29115 Reviewed-by: Ashod Nakashian <ashnak...@gmail.com> Tested-by: Ashod Nakashian <ashnak...@gmail.com> diff --git a/loolwsd/LOOLKit.cpp b/loolwsd/LOOLKit.cpp index a04945c..3b4e39b 100644 --- a/loolwsd/LOOLKit.cpp +++ b/loolwsd/LOOLKit.cpp @@ -1279,6 +1279,10 @@ private: { pThis->renderCombinedTiles(tokens, pThis->_ws); } + else + { + Log::error("Unexpected tile request: [" + message + "]."); + } } } catch (const std::exception& exc) diff --git a/loolwsd/MessageQueue.cpp b/loolwsd/MessageQueue.cpp index 0660d2b..16946e2 100644 --- a/loolwsd/MessageQueue.cpp +++ b/loolwsd/MessageQueue.cpp @@ -48,6 +48,8 @@ void MessageQueue::remove_if(const std::function<bool(const Payload&)>& pred) void MessageQueue::put_impl(const Payload& value) { + const auto msg = std::string(value.data(), value.size()); + Log::trace() << "Pushing into MQ [" << msg << "]" << Log::end; _queue.push_back(value); } @@ -73,6 +75,8 @@ void BasicTileQueue::put_impl(const Payload& value) const auto msg = std::string(&value[0], value.size()); if (msg == "canceltiles") { + Log::error("Unexpected canceltiles!"); + // remove all the existing tiles from the queue _queue.erase(std::remove_if(_queue.begin(), _queue.end(), [](const Payload& v) @@ -104,16 +108,6 @@ void TileQueue::put_impl(const Payload& value) { const auto newMsg = msg.substr(0, msg.find(" ver")); - // TODO: implement a real re-ordering here, so that the tiles closest to - // the cursor are returned first. - // * we will want to put just a general "tile" message to the queue - // * add a std::set that handles the tiles - // * change the get_impl() to decide which tile is the correct one to - // be returned - // * we will also need to be informed about the position of the cursor - // so that get_impl() returns optimal results - // - // For now: just don't put duplicates into the queue for (size_t i = 0; i < _queue.size(); ++i) { auto& it = _queue[i]; @@ -201,4 +195,64 @@ bool TileQueue::priority(const std::string& tileMsg) return false; } +MessageQueue::Payload TileQueue::get_impl() +{ + std::vector<TileDesc> tiles; + const auto front = _queue.front(); + _queue.pop_front(); + + auto msg = std::string(front.data(), front.size()); + Log::trace() << "MessageQueue Get, Size: " << _queue.size() << ", Front: " << msg << Log::end; + + if (msg.compare(0, 5, "tile ") != 0 || msg.find("id=") != std::string::npos) + { + // Don't combine non-tiles or tiles with id. + Log::trace() << "MessageQueue res: " << msg << Log::end; + return front; + } + + tiles.emplace_back(TileDesc::parse(msg)); + + // Combine as many tiles as possible with the top one. + for (size_t i = 0; i < _queue.size(); ) + { + auto& it = _queue[i]; + msg = std::string(it.data(), it.size()); + if (msg.compare(0, 5, "tile ") != 0 || + msg.find("id=") != std::string::npos) + { + // Don't combine non-tiles or tiles with id. + continue; + } + + auto tile2 = TileDesc::parse(msg); + bool found = false; + Log::trace() << "combining?: " << msg << Log::end; + + // Check if adjacent tiles. + for (auto& tile : tiles) + { + if (tile.isAdjacent(tile2)) + { + tiles.emplace_back(tile2); + _queue.erase(_queue.begin() + i); + found = true; + break; + } + } + + i += !found; + } + + if (tiles.size() == 1) + { + msg = tiles[0].serialize("tile"); + return Payload(msg.data(), msg.data() + msg.size()); + } + + auto tileCombined = TileCombined::create(tiles).serialize("tilecombine"); + Log::trace() << "MessageQueue res: " << tileCombined << Log::end; + return Payload(tileCombined.data(), tileCombined.data() + tileCombined.size()); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/loolwsd/MessageQueue.hpp b/loolwsd/MessageQueue.hpp index f1b14b2..4d1efba 100644 --- a/loolwsd/MessageQueue.hpp +++ b/loolwsd/MessageQueue.hpp @@ -58,7 +58,7 @@ protected: bool wait_impl() const; - Payload get_impl(); + virtual Payload get_impl(); void clear_impl(); @@ -124,6 +124,8 @@ public: protected: virtual void put_impl(const Payload& value) override; + virtual Payload get_impl() override; + private: /// Bring the underlying tile (if any) to the top. diff --git a/loolwsd/TileDesc.hpp b/loolwsd/TileDesc.hpp index 0258645..20ac257 100644 --- a/loolwsd/TileDesc.hpp +++ b/loolwsd/TileDesc.hpp @@ -10,6 +10,7 @@ #ifndef INCLUDED_TILEDESC_HPP #define INCLUDED_TILEDESC_HPP +#include <cassert> #include <map> #include <sstream> #include <string> @@ -60,6 +61,7 @@ public: void setVersion(const int ver) { _ver = ver; } int getImgSize() const { return _imgSize; } void setImgSize(const int imgSize) { _imgSize = imgSize; } + bool intersectsWithRect(int x, int y, int w, int h) const { return x + w >= getTilePosX() && @@ -68,6 +70,26 @@ public: y <= getTilePosY() + getTileHeight(); } + bool intersects(const TileDesc& other) const + { + return intersectsWithRect(other.getTilePosX(), other.getTilePosY(), + other.getTileWidth(), other.getTileHeight()); + } + + bool isAdjacent(const TileDesc& other) const + { + if (other.getPart() != getPart() || + other.getWidth() != getWidth() || + other.getHeight() != getHeight() || + other.getTileWidth() != getTileWidth() || + other.getTileHeight() != getTileHeight()) + { + return false; + } + + return intersects(other); + } + /// Serialize this instance into a string. /// Optionally prepend a prefix. std::string serialize(const std::string& prefix = "") const @@ -334,6 +356,26 @@ public: return parse(tokens); } + static + TileCombined create(const std::vector<TileDesc>& tiles) + { + assert(!tiles.empty()); + + std::ostringstream xs; + std::ostringstream ys; + int ver = -1; + + for (auto& tile : tiles) + { + xs << tile.getTilePosX() << ','; + ys << tile.getTilePosY() << ','; + ver = std::max(tile.getVersion(), ver); + } + + return TileCombined(tiles[0].getPart(), tiles[0].getWidth(), tiles[0].getHeight(), + xs.str(), ys.str(), tiles[0].getTileWidth(), tiles[0].getTileHeight(), ver, "", -1); + } + private: std::vector<TileDesc> _tiles; int _part; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits