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

Reply via email to