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

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