Kaydet (Commit) a7f12df9 authored tarafından Pranav Kant's avatar Pranav Kant Kaydeden (comit) Miklos Vajna

Use thread pool for LOK call: paintTile()

Change-Id: I45e94248013277affa11e91439fbc16995b8ed8e
üst e032b644
......@@ -135,16 +135,6 @@ enum
PROP_CAN_ZOOM_OUT
};
enum
{
LOK_LOAD_DOC,
LOK_POST_COMMAND,
LOK_SET_EDIT,
LOK_SET_PARTMODE,
LOK_SET_PART,
LOK_POST_KEY
};
static guint doc_view_signals[LAST_SIGNAL] = { 0 };
static void lok_doc_view_initable_iface_init (GInitableIface *iface);
......@@ -161,7 +151,7 @@ G_DEFINE_TYPE_WITH_CODE (LOKDocView, lok_doc_view, GTK_TYPE_DRAWING_AREA,
#pragma GCC diagnostic pop
#endif
static GThreadPool* lokThreadPool;
GThreadPool* lokThreadPool;
/// Helper struct used to pass the data from soffice thread -> main thread.
struct CallbackData
......@@ -176,50 +166,6 @@ struct CallbackData
m_pDocView(pDocView) {}
};
/**
A struct that we use to store the data about the LOK call.
Object of this type is passed with all the LOK calls,
so that they can be idenitified. Additionally, it also contains
the data that LOK call needs.
*/
struct LOEvent
{
/// To identify the type of LOK call
int m_nType;
const gchar* m_pCommand;
const gchar* m_pArguments;
gchar* m_pPath;
gboolean m_bEdit;
int m_nPartMode;
int m_nPart;
int m_nKeyEvent;
int m_nCharCode;
int m_nKeyCode;
/// Constructor to easily instantiate an object for LOK call of `type' type.
LOEvent(int type)
: m_nType(type) {}
LOEvent(int type, const gchar* pCommand, const gchar* pArguments)
: m_nType(type),
m_pCommand(pCommand),
m_pArguments(pArguments) {}
LOEvent(int type, const gchar* pPath)
: m_nType(type)
{
m_pPath = g_strdup(pPath);
}
LOEvent(int type, int nKeyEvent, int nCharCode, int nKeyCode)
: m_nType(type),
m_nKeyEvent(nKeyEvent),
m_nCharCode(nCharCode),
m_nKeyCode(nKeyCode) {}
};
static void
payloadToSize(const char* pPayload, long& rWidth, long& rHeight)
{
......@@ -529,10 +475,12 @@ setTilesInvalid (LOKDocView* pDocView, const GdkRectangle& rRectangle)
aStart.y = aRectanglePixels.x / nTileSizePixels;
aEnd.x = (aRectanglePixels.y + aRectanglePixels.height + nTileSizePixels) / nTileSizePixels;
aEnd.y = (aRectanglePixels.x + aRectanglePixels.width + nTileSizePixels) / nTileSizePixels;
GTask* task = g_task_new(pDocView, NULL, NULL, NULL);
for (int i = aStart.x; i < aEnd.x; i++)
for (int j = aStart.y; j < aEnd.y; j++)
priv->m_aTileBuffer.setInvalid(i, j, priv->m_fZoom);
priv->m_aTileBuffer.setInvalid(i, j, priv->m_fZoom, task);
g_object_unref(task);
}
static gboolean
......@@ -753,13 +701,6 @@ renderGraphicHandle(LOKDocView* pDocView,
}
}
static void
renderDocumentCallback(GObject* source_object, GAsyncResult*, gpointer)
{
LOKDocView* pDocView = LOK_DOC_VIEW(source_object);
gtk_widget_queue_draw(GTK_WIDGET(pDocView));
}
static gboolean
renderDocument(LOKDocView* pDocView, cairo_t* pCairo)
{
......@@ -808,14 +749,14 @@ renderDocument(LOKDocView* pDocView, cairo_t* pCairo)
if (bPaint)
{
GTask* task = g_task_new(pDocView, NULL, renderDocumentCallback, NULL);
GTask* task = g_task_new(pDocView, NULL, NULL, NULL);
Tile& currentTile = priv->m_aTileBuffer.getTile(nRow, nColumn, priv->m_fZoom, task);
GdkPixbuf* pPixBuf = currentTile.getBuffer();
gdk_cairo_set_source_pixbuf (pCairo, pPixBuf,
twipToPixel(aTileRectangleTwips.x, priv->m_fZoom),
twipToPixel(aTileRectangleTwips.y, priv->m_fZoom));
cairo_paint(pCairo);
g_object_unref(task);
}
}
}
......@@ -1211,6 +1152,52 @@ lok_doc_view_post_command_in_thread (gpointer data)
priv->m_pDocument->pClass->postUnoCommand(priv->m_pDocument, pLOEvent->m_pCommand, pLOEvent->m_pArguments);
}
static void
paintTileInThread (gpointer data)
{
GTask* task = G_TASK(data);
LOKDocView* pDocView = LOK_DOC_VIEW(g_task_get_source_object(task));
LOKDocViewPrivate *priv = static_cast<LOKDocViewPrivate*>(lok_doc_view_get_instance_private (pDocView));
LOEvent* pLOEvent = static_cast<LOEvent*>(g_task_get_task_data(task));
TileBuffer& buffer = priv->m_aTileBuffer;
int index = pLOEvent->m_nX * buffer.m_nWidth + pLOEvent->m_nY;
if (buffer.m_mTiles.find(index) != buffer.m_mTiles.end() &&
buffer.m_mTiles[index].valid)
return;
GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, nTileSizePixels, nTileSizePixels);
if (!pPixBuf)
{
g_info ("Error allocating memory to pixbuf");
return;
}
unsigned char* pBuffer = gdk_pixbuf_get_pixels(pPixBuf);
GdkRectangle aTileRectangle;
aTileRectangle.x = pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom) * pLOEvent->m_nY;
aTileRectangle.y = pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom) * pLOEvent->m_nX;
g_test_timer_start();
priv->m_pDocument->pClass->paintTile(priv->m_pDocument,
pBuffer,
nTileSizePixels, nTileSizePixels,
aTileRectangle.x, aTileRectangle.y,
pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom),
pixelToTwip(nTileSizePixels, pLOEvent->m_fZoom));
double elapsedTime = g_test_timer_elapsed();
g_info ("Rendered (%d, %d) in %f seconds",
pLOEvent->m_nX,
pLOEvent->m_nY,
elapsedTime);
//create a mapping for it
buffer.m_mTiles[index].setPixbuf(pPixBuf);
buffer.m_mTiles[index].valid = true;
gtk_widget_queue_draw(GTK_WIDGET(pDocView));
}
static void
lokThreadFunc(gpointer data, gpointer /*user_data*/)
{
......@@ -1237,6 +1224,9 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/)
case LOK_POST_KEY:
postKeyEventInThread(task);
break;
case LOK_PAINT_TILE:
paintTileInThread(task);
break;
}
g_object_unref(task);
......
......@@ -13,6 +13,8 @@
#define g_info(...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, __VA_ARGS__)
#endif
extern GThreadPool* lokThreadPool;
/* ------------------
Utility functions
------------------
......@@ -27,42 +29,6 @@ float twipToPixel(float fInput, float zoom)
return fInput / 1440.0f * DPI * zoom;
}
static void getTileFunc(GTask*, gpointer, gpointer task_data, GCancellable*)
{
GdkPixbuf* pPixBuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, nTileSizePixels, nTileSizePixels);
GetTileCallbackData* pCallback = static_cast<GetTileCallbackData*>(task_data);
TileBuffer* buffer = pCallback->m_pBuffer;
int index = pCallback->m_nX * buffer->m_nWidth + pCallback->m_nY;
if (!pPixBuf)
{
g_info ("Error allocating memory to pixbuf");
return;
}
unsigned char* pBuffer = gdk_pixbuf_get_pixels(pPixBuf);
GdkRectangle aTileRectangle;
aTileRectangle.x = pixelToTwip(nTileSizePixels, pCallback->m_fZoom) * pCallback->m_nY;
aTileRectangle.y = pixelToTwip(nTileSizePixels, pCallback->m_fZoom) * pCallback->m_nX;
g_test_timer_start();
buffer->m_pLOKDocument->pClass->paintTile(buffer->m_pLOKDocument,
pBuffer,
nTileSizePixels, nTileSizePixels,
aTileRectangle.x, aTileRectangle.y,
pixelToTwip(nTileSizePixels, pCallback->m_fZoom),
pixelToTwip(nTileSizePixels, pCallback->m_fZoom));
double elapsedTime = g_test_timer_elapsed();
g_info ("Rendered (%d, %d) in %f seconds",
pCallback->m_nX,
pCallback->m_nY,
elapsedTime);
//create a mapping for it
buffer->m_mTiles[index].setPixbuf(pPixBuf);
buffer->m_mTiles[index].valid = true;
}
/* ----------------------------
Tile class member functions
----------------------------
......@@ -96,17 +62,17 @@ void TileBuffer::resetAllTiles()
}
}
void TileBuffer::setInvalid(int x, int y, float fZoom)
void TileBuffer::setInvalid(int x, int y, float fZoom, GTask* task)
{
int index = x * m_nWidth + y;
g_info("Setting tile invalid (%d, %d)", x, y);
if (m_mTiles.find(index) != m_mTiles.end())
{
m_mTiles[index].valid = false;
GTask* task = g_task_new(this, NULL, NULL, NULL);
GetTileCallbackData* pCallback = new GetTileCallbackData(x, y, fZoom, this);
g_task_set_task_data(task, pCallback, g_free);
g_task_run_in_thread(task, getTileFunc);
LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE, x, y, fZoom);
g_task_set_task_data(task, pLOEvent, g_free);
g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL);
}
}
......@@ -116,17 +82,16 @@ Tile& TileBuffer::getTile(int x, int y, float aZoom, GTask* task)
if (m_mTiles.find(index) != m_mTiles.end() && !m_mTiles[index].valid)
{
GetTileCallbackData* pCallback = new GetTileCallbackData(x, y, aZoom, this);
g_task_set_task_data(task, pCallback, g_free);
g_task_run_in_thread(task, getTileFunc);
LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE, x, y, aZoom);
g_task_set_task_data(task, pLOEvent, g_free);
g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL);
return m_mTiles[index];
}
else if(m_mTiles.find(index) == m_mTiles.end())
{
GetTileCallbackData* pCallback = new GetTileCallbackData(x, y, aZoom, this);
g_task_set_task_data(task, pCallback, g_free);
g_info ("running in thread new tile");
g_task_run_in_thread(task, getTileFunc);
LOEvent* pLOEvent = new LOEvent(LOK_PAINT_TILE, x, y, aZoom);
g_task_set_task_data(task, pLOEvent, g_free);
g_thread_pool_push(lokThreadPool, g_object_ref(task), NULL);
return m_DummyTile;
}
......
......@@ -107,7 +107,7 @@ class TileBuffer
@return the tile at the mentioned position (x, y)
*/
Tile& getTile(int x, int y, float aZoom, GTask*);
Tile& getTile(int x, int y, float aZoom, GTask* task);
/// Destroys all the tiles in the tile buffer; also frees the memory allocated
/// for all the Tile objects.
void resetAllTiles();
......@@ -118,8 +118,7 @@ class TileBuffer
@param x the position of tile along x-axis
@param y the position of tile along y-axis
*/
void setInvalid(int x, int y, float zoom);
void setInvalid(int x, int y, float zoom, GTask* task);
/// Contains the reference to the LOK Document that this tile buffer is for.
LibreOfficeKitDocument *m_pLOKDocument;
......@@ -131,26 +130,70 @@ class TileBuffer
Tile m_DummyTile;
};
enum
{
LOK_LOAD_DOC,
LOK_POST_COMMAND,
LOK_SET_EDIT,
LOK_SET_PARTMODE,
LOK_SET_PART,
LOK_POST_KEY,
LOK_PAINT_TILE
};
/**
Helper struct used to pass the data from main thread to spawned threads.
Spawned threads are responsible for calling paintTile, and store the result
in tile buffer.
A struct that we use to store the data about the LOK call.
Object of this type is passed with all the LOK calls,
so that they can be idenitified. Additionally, it also contains
the data that LOK call needs.
*/
struct GetTileCallbackData
struct LOEvent
{
/// To identify the type of LOK call
int m_nType;
const gchar* m_pCommand;
const gchar* m_pArguments;
gchar* m_pPath;
gboolean m_bEdit;
int m_nPartMode;
int m_nPart;
int m_nKeyEvent;
int m_nCharCode;
int m_nKeyCode;
int m_nX;
int m_nY;
float m_fZoom;
TileBuffer* m_pBuffer;
GetTileCallbackData(int x, int y, float zoom, TileBuffer* buffer)
: m_nX(x),
/// Constructor to easily instantiate an object for LOK call of `type' type.
LOEvent(int type)
: m_nType(type) {}
LOEvent(int type, const gchar* pCommand, const gchar* pArguments)
: m_nType(type),
m_pCommand(pCommand),
m_pArguments(pArguments) {}
LOEvent(int type, const gchar* pPath)
: m_nType(type)
{
m_pPath = g_strdup(pPath);
}
LOEvent(int type, int nKeyEvent, int nCharCode, int nKeyCode)
: m_nType(type),
m_nKeyEvent(nKeyEvent),
m_nCharCode(nCharCode),
m_nKeyCode(nKeyCode) {}
LOEvent(int type, int x, int y, float zoom)
: m_nType(type),
m_nX(x),
m_nY(y),
m_fZoom(zoom),
m_pBuffer(buffer) { }
m_fZoom(zoom) {}
};
#endif // INCLUDED_TILEBUFFER_HXX
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment