Blame SOURCES/0275-lokdocview-Don-t-render-tiles-while-tile-buffer-has-.patch

f325b2
From 26a44f8b7e9ce4e5e9a097f5fedc04d4717fd51d Mon Sep 17 00:00:00 2001
f325b2
From: Pranav Kant <pranavk@libreoffice.org>
f325b2
Date: Sun, 1 Nov 2015 17:11:09 +0530
f325b2
Subject: [PATCH 275/398] lokdocview: Don't render tiles while tile buffer has
f325b2
 changed
f325b2
f325b2
This is common when widget gets a zoom request, resulting in a
f325b2
new tile buffer, and the tiles from the old tile buffer are still
f325b2
waiting to be processed in the LOK thread, for old tile buffer. If
f325b2
we allow these useless operations to execute successfully, they
f325b2
would end up writing in new tile buffer giving false results.
f325b2
f325b2
Lets tag every paint tile operations with their respective tile
f325b2
buffer during `task` creation, and then check whether the tile
f325b2
buffer has changed or not before writing to the tile buffer.
f325b2
f325b2
Change-Id: If784341a67ad430bc3415b765137badaad6b97f6
f325b2
Reviewed-on: https://gerrit.libreoffice.org/19726
f325b2
Reviewed-by: Miklos Vajna <vmiklos@collabora.co.uk>
f325b2
Tested-by: Miklos Vajna <vmiklos@collabora.co.uk>
f325b2
(cherry picked from commit 93f98e98e42d75914a3e1d8f85bd3c6328d2e111)
f325b2
---
f325b2
 libreofficekit/source/gtk/lokdocview.cxx | 38 ++++++++++++++++++++++++++++++--
f325b2
 libreofficekit/source/gtk/tilebuffer.cxx |  6 +++++
f325b2
 libreofficekit/source/gtk/tilebuffer.hxx | 15 +++++++++++++
f325b2
 3 files changed, 57 insertions(+), 2 deletions(-)
f325b2
f325b2
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
f325b2
index 9cf78a3f5429..575116f4d028 100644
f325b2
--- a/libreofficekit/source/gtk/lokdocview.cxx
f325b2
+++ b/libreofficekit/source/gtk/lokdocview.cxx
f325b2
@@ -912,7 +912,12 @@ paintTileCallback(GObject* sourceObject, GAsyncResult* res, gpointer userData)
f325b2
     GdkPixbuf* pPixBuf = static_cast<GdkPixbuf*>(paintTileFinish(pDocView, res, &error));
f325b2
     if (error != NULL)
f325b2
     {
f325b2
-        g_warning("Unable to get painted GdkPixbuf: %s", error->message);
f325b2
+        if (error->domain == LOK_TILEBUFFER_ERROR &&
f325b2
+            error->code == LOK_TILEBUFFER_CHANGED)
f325b2
+            g_info("Skipping paint tile request because corresponding"
f325b2
+                   "tile buffer has been destroyed");
f325b2
+        else
f325b2
+            g_warning("Unable to get painted GdkPixbuf: %s", error->message);
f325b2
         g_error_free(error);
f325b2
         return;
f325b2
     }
f325b2
@@ -977,6 +982,7 @@ renderDocument(LOKDocView* pDocView, cairo_t* pCairo)
f325b2
                 pLOEvent->m_nPaintTileX = nRow;
f325b2
                 pLOEvent->m_nPaintTileY = nColumn;
f325b2
                 pLOEvent->m_fPaintTileZoom = priv->m_fZoom;
f325b2
+                pLOEvent->m_pTileBuffer = &*priv->m_pTileBuffer;
f325b2
                 GTask* task = g_task_new(pDocView, NULL, paintTileCallback, pLOEvent);
f325b2
                 g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
f325b2
 
f325b2
@@ -1541,6 +1547,17 @@ paintTileInThread (gpointer data)
f325b2
     LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
f325b2
     LOKDocViewPrivate& priv = getPrivate(pDocView);
f325b2
     LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task));
f325b2
+
f325b2
+    // check if "source" tile buffer is different from "current" tile buffer
f325b2
+    if (pLOEvent->m_pTileBuffer != &*priv->m_pTileBuffer)
f325b2
+    {
f325b2
+        pLOEvent->m_pTileBuffer = nullptr;
f325b2
+        g_task_return_new_error(task,
f325b2
+                                LOK_TILEBUFFER_ERROR,
f325b2
+                                LOK_TILEBUFFER_CHANGED,
f325b2
+                                "TileBuffer has changed");
f325b2
+        return;
f325b2
+    }
f325b2
     std::unique_ptr<TileBuffer>& buffer = priv->m_pTileBuffer;
f325b2
     int index = pLOEvent->m_nPaintTileX * buffer->m_nWidth + pLOEvent->m_nPaintTileY;
f325b2
     if (buffer->m_mTiles.find(index) != buffer->m_mTiles.end() &&
f325b2
@@ -1550,7 +1567,10 @@ paintTileInThread (gpointer data)
f325b2
     GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, nTileSizePixels, nTileSizePixels);
f325b2
     if (!pPixBuf)
f325b2
     {
f325b2
-        g_info ("Error allocating memory to pixbuf");
f325b2
+        g_task_return_new_error(task,
f325b2
+                                LOK_TILEBUFFER_ERROR,
f325b2
+                                LOK_TILEBUFFER_MEMORY,
f325b2
+                                "Error allocating memory to GdkPixbuf");
f325b2
         return;
f325b2
     }
f325b2
 
f325b2
@@ -1574,6 +1594,20 @@ paintTileInThread (gpointer data)
f325b2
                                          pixelToTwip(nTileSizePixels, pLOEvent->m_fPaintTileZoom),
f325b2
                                          pixelToTwip(nTileSizePixels, pLOEvent->m_fPaintTileZoom));
f325b2
 
f325b2
+    // Its likely that while the tilebuffer has changed, one of the paint tile
f325b2
+    // requests has passed the previous check at start of this function, and has
f325b2
+    // rendered the tile already. We want to stop such rendered tiles from being
f325b2
+    // stored in new tile buffer.
f325b2
+    if (pLOEvent->m_pTileBuffer != &*priv->m_pTileBuffer)
f325b2
+    {
f325b2
+        pLOEvent->m_pTileBuffer = nullptr;
f325b2
+        g_task_return_new_error(task,
f325b2
+                                LOK_TILEBUFFER_ERROR,
f325b2
+                                LOK_TILEBUFFER_CHANGED,
f325b2
+                                "TileBuffer has changed");
f325b2
+        return;
f325b2
+    }
f325b2
+
f325b2
     g_task_return_pointer(task, pPixBuf, g_object_unref);
f325b2
 }
f325b2
 
f325b2
diff --git a/libreofficekit/source/gtk/tilebuffer.cxx b/libreofficekit/source/gtk/tilebuffer.cxx
f325b2
index 1158209b2273..32a9534e884c 100644
f325b2
--- a/libreofficekit/source/gtk/tilebuffer.cxx
f325b2
+++ b/libreofficekit/source/gtk/tilebuffer.cxx
f325b2
@@ -121,4 +121,10 @@ void LOEvent::destroy(void* pMemory)
f325b2
     delete pLOEvent;
f325b2
 }
f325b2
 
f325b2
+GQuark
f325b2
+LOKTileBufferErrorQuark(void)
f325b2
+{
f325b2
+    return g_quark_from_static_string("lok-tilebuffer-error");
f325b2
+}
f325b2
+
f325b2
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
f325b2
diff --git a/libreofficekit/source/gtk/tilebuffer.hxx b/libreofficekit/source/gtk/tilebuffer.hxx
f325b2
index 8a8569eeb306..9407257e5fec 100644
f325b2
--- a/libreofficekit/source/gtk/tilebuffer.hxx
f325b2
+++ b/libreofficekit/source/gtk/tilebuffer.hxx
f325b2
@@ -19,6 +19,8 @@
f325b2
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
f325b2
 #include <LibreOfficeKit/LibreOfficeKitGtk.h>
f325b2
 
f325b2
+#define LOK_TILEBUFFER_ERROR (LOKTileBufferErrorQuark())
f325b2
+
f325b2
 // We know that VirtualDevices use a DPI of 96.
f325b2
 const int DPI = 96;
f325b2
 // Lets use a square of side 256 pixels for each tile.
f325b2
@@ -45,6 +47,11 @@ float pixelToTwip(float fInput, float zoom);
f325b2
 float twipToPixel(float fInput, float zoom);
f325b2
 
f325b2
 /**
f325b2
+   Gets GQuark identifying this tile buffer errors
f325b2
+*/
f325b2
+GQuark LOKTileBufferErrorQuark(void);
f325b2
+
f325b2
+/**
f325b2
    This class represents a single tile in the tile buffer.
f325b2
    It encloses a reference to GdkPixBuf containing the pixel data of the tile.
f325b2
 */
f325b2
@@ -155,6 +162,12 @@ enum
f325b2
     LOK_SET_GRAPHIC_SELECTION
f325b2
 };
f325b2
 
f325b2
+enum
f325b2
+{
f325b2
+    LOK_TILEBUFFER_CHANGED,
f325b2
+    LOK_TILEBUFFER_MEMORY
f325b2
+};
f325b2
+
f325b2
 /**
f325b2
    A struct that we use to store the data about the LOK call.
f325b2
 
f325b2
@@ -200,6 +213,7 @@ struct LOEvent
f325b2
     int m_nPaintTileX;
f325b2
     int m_nPaintTileY;
f325b2
     float m_fPaintTileZoom;
f325b2
+    TileBuffer* m_pTileBuffer;
f325b2
     ///@}
f325b2
 
f325b2
     /// @name postMouseEvent parameters
f325b2
@@ -235,6 +249,7 @@ struct LOEvent
f325b2
         , m_nPaintTileX(0)
f325b2
         , m_nPaintTileY(0)
f325b2
         , m_fPaintTileZoom(0)
f325b2
+        , m_pTileBuffer(nullptr)
f325b2
         , m_nPostMouseEventType(0)
f325b2
         , m_nPostMouseEventX(0)
f325b2
         , m_nPostMouseEventY(0)
f325b2
-- 
f325b2
2.12.0
f325b2