summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2013-06-14 09:24:37 -0700
committerRobin Watts <robin.watts@artifex.com>2013-06-14 21:25:01 +0100
commitf9574246ead2457963ede0c6d65e208ad6943258 (patch)
treed85069efadf5a6b5b78403eda57b0adabb7a45e0
parent9a1898c42152dfac560bb9d291e43f7dc0fd40ac (diff)
downloadmupdf-f9574246ead2457963ede0c6d65e208ad6943258.tar.xz
Addition of locking cache for display list in winRT library
-rw-r--r--winrt/mupdf_cpp/MainPage.xaml.cpp24
-rw-r--r--winrt/mupdfwinrt/Cache.cpp112
-rw-r--r--winrt/mupdfwinrt/Cache.h37
-rw-r--r--winrt/mupdfwinrt/muctx.cpp62
-rw-r--r--winrt/mupdfwinrt/muctx.h12
-rw-r--r--winrt/mupdfwinrt/mudocument.cpp22
-rw-r--r--winrt/mupdfwinrt/mudocument.h2
-rw-r--r--winrt/mupdfwinrt/mupdfwinrt.vcxproj2
-rw-r--r--winrt/mupdfwinrt/mupdfwinrt.vcxproj.filters2
9 files changed, 199 insertions, 76 deletions
diff --git a/winrt/mupdf_cpp/MainPage.xaml.cpp b/winrt/mupdf_cpp/MainPage.xaml.cpp
index e700a444..4c1095bf 100644
--- a/winrt/mupdf_cpp/MainPage.xaml.cpp
+++ b/winrt/mupdf_cpp/MainPage.xaml.cpp
@@ -642,7 +642,7 @@ void mupdf_cpp::MainPage::InitialRender()
Point ras_size = ComputePageSize(spatial_info, k);
auto render_task =
- create_task(mu_doc->RenderPageAsync(k, ras_size.X, ras_size.Y, false));
+ create_task(mu_doc->RenderPageAsync(k, ras_size.X, ras_size.Y, true));
render_task.then([this, k, ras_size] (InMemoryRandomAccessStream^ ras)
{
@@ -689,7 +689,7 @@ void mupdf_cpp::MainPage::RenderRange(int curr_page)
{
Point ras_size = ComputePageSize(spatial_info, k);
auto render_task =
- create_task(mu_doc->RenderPageAsync(k, ras_size.X, ras_size.Y, false));
+ create_task(mu_doc->RenderPageAsync(k, ras_size.X, ras_size.Y, true));
render_task.then([this, k, ras_size] (InMemoryRandomAccessStream^ ras)
{
@@ -750,7 +750,7 @@ void mupdf_cpp::MainPage::Slider_ValueChanged(Platform::Object^ sender, Windows:
spatial_info_t spatial_info = InitSpatial(1);
Point ras_size = ComputePageSize(spatial_info, newValue);
auto render_task =
- create_task(mu_doc->RenderPageAsync(newValue, ras_size.X, ras_size.Y, false));
+ create_task(mu_doc->RenderPageAsync(newValue, ras_size.X, ras_size.Y, true));
render_task.then([this, newValue, ras_size] (InMemoryRandomAccessStream^ ras)
{
@@ -1345,20 +1345,12 @@ void mupdf_cpp::MainPage::ScrollChanged(Platform::Object^ sender,
Point ras_size = ComputePageSize(spatial_info, page);
/* Go ahead and create display list if we dont have one for this page */
- auto ui = task_continuation_context::use_current();
- auto display_task = create_task(mu_doc->CreateDisplayList(page));
- display_task.then([this, page, ras_size, ui] (int code)
+ auto render_task =
+ create_task(mu_doc->RenderPageAsync(page, ras_size.X, ras_size.Y, true));
+ render_task.then([this, page, ras_size] (InMemoryRandomAccessStream^ ras)
{
- if (code == S_ISOK)
- {
- auto render_task =
- create_task(mu_doc->RenderPageAsync(page, ras_size.X, ras_size.Y, true));
- render_task.then([this, page, ras_size] (InMemoryRandomAccessStream^ ras)
- {
- ReplaceImage(page, ras, ras_size);
- }, ui);
- }
- });
+ ReplaceImage(page, ras, ras_size);
+ }, task_continuation_context::use_current());
}
}
diff --git a/winrt/mupdfwinrt/Cache.cpp b/winrt/mupdfwinrt/Cache.cpp
new file mode 100644
index 00000000..e1e68241
--- /dev/null
+++ b/winrt/mupdfwinrt/Cache.cpp
@@ -0,0 +1,112 @@
+#include "pch.h"
+#include "Cache.h"
+
+Cache::Cache(void)
+{
+ this->size = 0;
+ this->head = NULL;
+ this->tail = NULL;
+}
+
+Cache::~Cache(void)
+{
+}
+
+void Cache::Empty(fz_context *mu_ctx)
+{
+ cache_entry_t *curr_entry = this->head;
+
+ while (curr_entry != NULL)
+ {
+ cache_entry_t *old_entry = curr_entry;
+ curr_entry = old_entry->next;
+ fz_drop_display_list(mu_ctx, old_entry->dlist);
+ delete old_entry;
+ }
+ this->size = 0;
+ this->head = NULL;
+ this->tail = NULL;
+}
+
+void Cache::AddEntry(int value, fz_display_list *dlist, fz_context *mu_ctx)
+{
+ std::lock_guard<std::mutex> lock(cache_lock);
+
+ /* If full, then delete the tail */
+ if (size >= MAX_DISPLAY_CACHE_SIZE)
+ {
+ cache_entry_t *curr_entry = this->tail;
+ cache_entry_t *prev_entry = curr_entry->prev;
+
+ if (prev_entry != NULL)
+ prev_entry->next = NULL;
+ else
+ head = NULL;
+
+ tail = prev_entry;
+
+ /* Decrement the caches rc of this list */
+ fz_drop_display_list(mu_ctx, curr_entry->dlist);
+ delete curr_entry;
+ size--;
+ }
+
+ /* Make a new entry and stick at head */
+ cache_entry_t *new_entry = new cache_entry_t;
+
+ new_entry->dlist = dlist;
+ new_entry->index = value;
+ new_entry->prev = NULL;
+ if (head == NULL)
+ {
+ new_entry->next = NULL;
+ head = new_entry;
+ tail = new_entry;
+ }
+ else
+ {
+ new_entry->next = head;
+ head->prev = new_entry;
+ head = new_entry;
+ }
+ size++;
+ /* We are going to use this item now */
+ fz_keep_display_list(mu_ctx, new_entry->dlist);
+}
+
+fz_display_list* Cache::UseEntry(int value, fz_context *mu_ctx)
+{
+ std::lock_guard<std::mutex> lock(cache_lock);
+ cache_entry_t *curr_entry = this->head;
+
+ while (curr_entry != NULL)
+ {
+ if (curr_entry->index == value)
+ break;
+ curr_entry = curr_entry->next;
+ }
+ if (curr_entry != NULL)
+ {
+ fz_keep_display_list(mu_ctx, curr_entry->dlist);
+ /* Move this to the front */
+ if (curr_entry != head)
+ {
+ cache_entry_t *prev_entry = curr_entry->prev;
+ cache_entry_t *next_entry = curr_entry->next;
+ prev_entry->next = next_entry;
+
+ if (next_entry != NULL)
+ next_entry->prev = prev_entry;
+ else
+ tail = prev_entry;
+
+ curr_entry->prev = NULL;
+ curr_entry->next = head;
+ head->prev = curr_entry;
+ head = curr_entry;
+ }
+ return curr_entry->dlist;
+ }
+ else
+ return NULL;
+}
diff --git a/winrt/mupdfwinrt/Cache.h b/winrt/mupdfwinrt/Cache.h
new file mode 100644
index 00000000..f8dd8ecb
--- /dev/null
+++ b/winrt/mupdfwinrt/Cache.h
@@ -0,0 +1,37 @@
+#pragma once
+
+#include <mutex>
+extern "C" {
+ #include "fitz.h"
+ #include "fitz-internal.h"
+ #include "muxps.h"
+ #include "mupdf.h"
+}
+
+#define MAX_DISPLAY_CACHE_SIZE 3
+
+typedef struct cache_entry_s cache_entry_t;
+
+struct cache_entry_s
+{
+ fz_display_list *dlist;
+ cache_entry_t *next;
+ cache_entry_t *prev;
+ int index;
+};
+
+class Cache
+{
+private:
+ int size;
+ cache_entry_t *head;
+ cache_entry_t *tail;
+ std::mutex cache_lock;
+
+public:
+ Cache(void);
+ ~Cache(void);
+ fz_display_list* UseEntry(int value, fz_context *mu_ctx);
+ void AddEntry(int value, fz_display_list *dlist, fz_context *mu_ctx);
+ void Empty(fz_context *mu_ctx);
+};
diff --git a/winrt/mupdfwinrt/muctx.cpp b/winrt/mupdfwinrt/muctx.cpp
index 40849fb9..5db701aa 100644
--- a/winrt/mupdfwinrt/muctx.cpp
+++ b/winrt/mupdfwinrt/muctx.cpp
@@ -131,11 +131,10 @@ status_t muctx::InitializeContext()
/* Initializer */
muctx::muctx(void)
{
- this->mu_ctx = NULL;
- this->mu_doc = NULL;
- this->mu_outline = NULL;
- this->mu_dlist = NULL;
- this->dlist_pagenum = -1;
+ mu_ctx = NULL;
+ mu_doc = NULL;
+ mu_outline = NULL;
+ display_list_cache = new Cache();
}
/* Destructor */
@@ -143,14 +142,14 @@ muctx::~muctx(void)
{
fz_free_outline(mu_ctx, mu_outline);
fz_close_document(mu_doc);
- fz_free_display_list(mu_ctx, mu_dlist);
+ display_list_cache->Empty(mu_ctx);
fz_free_context(mu_ctx);
- this->mu_ctx = NULL;
- this->mu_doc = NULL;
- this->mu_outline = NULL;
- this->mu_dlist = NULL;
- this->dlist_pagenum = -1;
+ mu_ctx = NULL;
+ mu_doc = NULL;
+ mu_outline = NULL;
+ delete display_list_cache;
+ display_list_cache = NULL;
}
/* Set up the stream access */
@@ -406,7 +405,7 @@ int muctx::GetLinks(int page_num, sh_vector_link links_vec)
return num_links;
}
-status_t muctx::CreateDisplayList(int page_num)
+fz_display_list * muctx::CreateDisplayList(int page_num)
{
fz_context *ctx_clone = NULL;
fz_device *dev = NULL;
@@ -414,20 +413,24 @@ status_t muctx::CreateDisplayList(int page_num)
ctx_clone = fz_clone_context(mu_ctx);
+ /* First see if we have this one in the cache */
+ fz_display_list *dlist = display_list_cache->UseEntry(page_num, ctx_clone);
+ if (dlist != NULL)
+ return dlist;
+
+ /* Apparently not, lets go ahead and create and add to cache */
fz_var(dev);
fz_var(page);
fz_try(ctx_clone)
{
page = fz_load_page(mu_doc, page_num);
- /* Free current list if we have one */
- if (mu_dlist != NULL)
- fz_free_display_list(ctx_clone, mu_dlist);
-
/* Create a new list */
- mu_dlist = fz_new_display_list(ctx_clone);
- dev = fz_new_list_device(ctx_clone, mu_dlist);
+ dlist = fz_new_display_list(ctx_clone);
+ dev = fz_new_list_device(ctx_clone, dlist);
fz_run_page_contents(mu_doc, page, dev, &fz_identity, NULL);
+ /* Add it to the cache and set that it is in use */
+ display_list_cache->AddEntry(page_num, dlist, ctx_clone);
}
fz_always(ctx_clone)
{
@@ -437,16 +440,9 @@ status_t muctx::CreateDisplayList(int page_num)
fz_catch(ctx_clone)
{
fz_free_context(ctx_clone);
- dlist_pagenum = -1;
- return E_FAILURE;
+ return NULL;
}
- dlist_pagenum = page_num;
- return S_ISOK;
-}
-
-int muctx::GetDisplayListPage(void)
-{
- return dlist_pagenum;
+ return dlist;
}
/* Render page_num to size width by height into bmp_data buffer */
@@ -459,15 +455,18 @@ status_t muctx::RenderPage(int page_num, int width, int height,
fz_matrix ctm, *pctm = &ctm;
Point page_size;
fz_context *ctx_clone = NULL;
+ fz_display_list *dlist = NULL;
- if (mu_dlist == NULL && use_dlist)
- return E_FAILURE;
+ if (use_dlist)
+ if ((dlist = CreateDisplayList(page_num)) == NULL)
+ return E_FAILURE;
ctx_clone = fz_clone_context(mu_ctx);
fz_var(dev);
fz_var(pix);
fz_var(page);
+
fz_try(ctx_clone)
{
page = fz_load_page(mu_doc, page_num);
@@ -482,7 +481,7 @@ status_t muctx::RenderPage(int page_num, int width, int height,
fz_clear_pixmap_with_value(ctx_clone, pix, 255);
dev = fz_new_draw_device(ctx_clone, pix);
if (use_dlist)
- fz_run_display_list(mu_dlist, dev, pctm, NULL, NULL);
+ fz_run_display_list(dlist, dev, pctm, NULL, NULL);
else
fz_run_page(mu_doc, page, dev, pctm, NULL);
}
@@ -491,6 +490,9 @@ status_t muctx::RenderPage(int page_num, int width, int height,
fz_free_device(dev);
fz_drop_pixmap(ctx_clone, pix);
fz_free_page(mu_doc, page);
+ if (use_dlist)
+ fz_drop_display_list(ctx_clone, dlist);
+
}
fz_catch(ctx_clone)
{
diff --git a/winrt/mupdfwinrt/muctx.h b/winrt/mupdfwinrt/muctx.h
index d22009a0..7c984b91 100644
--- a/winrt/mupdfwinrt/muctx.h
+++ b/winrt/mupdfwinrt/muctx.h
@@ -6,6 +6,7 @@
#include <windows.h>
#include <mutex>
#include "utils.h"
+#include "Cache.h"
extern "C" {
#include "fitz.h"
@@ -80,12 +81,12 @@ private:
fz_locks_context mu_locks;
fz_context *mu_ctx;
fz_document *mu_doc;
- fz_display_list *mu_dlist;
- int dlist_pagenum;
fz_outline *mu_outline;
fz_rect mu_hit_bbox[MAX_SEARCH];
void FlattenOutline(fz_outline *outline, int level,
- sh_vector_content contents_vec);
+ sh_vector_content contents_vec);
+ Cache *display_list_cache;
+ fz_display_list* CreateDisplayList(int page_num);
public:
muctx(void);
@@ -94,9 +95,8 @@ public:
status_t InitializeStream(IRandomAccessStream^ readStream, char *ext);
int GetPageCount();
status_t InitializeContext();
- status_t RenderPage(int page_num, int width, int height, unsigned char *bmp_data, bool use_dlist);
- status_t CreateDisplayList(int page_num);
- int GetDisplayListPage(void);
+ status_t RenderPage(int page_num, int width, int height, unsigned char *bmp_data,
+ bool use_dlist);
Point MeasurePage(int page_num);
Point MeasurePage(fz_page *page);
int GetLinks(int page_num, sh_vector_link links_vec);
diff --git a/winrt/mupdfwinrt/mudocument.cpp b/winrt/mupdfwinrt/mudocument.cpp
index 8688d520..b33be118 100644
--- a/winrt/mupdfwinrt/mudocument.cpp
+++ b/winrt/mupdfwinrt/mudocument.cpp
@@ -162,28 +162,6 @@ Windows::Foundation::IAsyncOperationWithProgress<int, double>^
});
}
-/* Create the display list for this page */
-Windows::Foundation::IAsyncOperation<int>^ mudocument::CreateDisplayList(int page_num)
-{
- return create_async([this, page_num](cancellation_token ct) -> int
- {
- if (mu_object.GetDisplayListPage() == page_num)
- return S_ISOK;
- std::lock_guard<std::mutex> lock(mutex_lock);
- status_t code = mu_object.CreateDisplayList(page_num);
- if (code != S_ISOK)
- {
- throw ref new FailureException("Display List Creation Failed");
- }
- return code;
- });
-}
-
-int mudocument::GetDisplayListPage(void)
-{
- return mu_object.GetDisplayListPage();
-}
-
/* Pack the page into a bmp stream */
Windows::Foundation::IAsyncOperation<InMemoryRandomAccessStream^>^
mudocument::RenderPageAsync(int page_num, int width, int height, bool use_dlist)
diff --git a/winrt/mupdfwinrt/mudocument.h b/winrt/mupdfwinrt/mudocument.h
index d90d2c9a..c4bc0b4e 100644
--- a/winrt/mupdfwinrt/mudocument.h
+++ b/winrt/mupdfwinrt/mudocument.h
@@ -36,7 +36,6 @@ namespace mupdfwinrt
Windows::Foundation::IAsyncOperation<int>^ OpenFileAsync(StorageFile^ file);
int GetNumPages(void);
Point GetPageSize(int page_num);
- Windows::Foundation::IAsyncOperation<int>^ mudocument::CreateDisplayList(int page_num);
Windows::Foundation::IAsyncOperation<InMemoryRandomAccessStream^>^
RenderPageAsync(int page_num, int width, int height, bool use_dlist);
Windows::Foundation::IAsyncOperationWithProgress<int, double>^
@@ -48,7 +47,6 @@ namespace mupdfwinrt
int ComputeContents(void);
ContentItem^ GetContent(int k);
int ComputeLinks(int page_num);
- int GetDisplayListPage(void);
Links^ GetLink(int k);
bool RequiresPassword();
bool ApplyPassword(String^ password);
diff --git a/winrt/mupdfwinrt/mupdfwinrt.vcxproj b/winrt/mupdfwinrt/mupdfwinrt.vcxproj
index 2b63addb..2510491a 100644
--- a/winrt/mupdfwinrt/mupdfwinrt.vcxproj
+++ b/winrt/mupdfwinrt/mupdfwinrt.vcxproj
@@ -217,6 +217,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+ <ClInclude Include="Cache.h" />
<ClInclude Include="Links.h" />
<ClInclude Include="ContentItem.h" />
<ClInclude Include="muctx.h" />
@@ -225,6 +226,7 @@
<ClInclude Include="utils.h" />
</ItemGroup>
<ItemGroup>
+ <ClCompile Include="Cache.cpp" />
<ClCompile Include="Links.cpp" />
<ClCompile Include="ContentItem.cpp" />
<ClCompile Include="muctx.cpp" />
diff --git a/winrt/mupdfwinrt/mupdfwinrt.vcxproj.filters b/winrt/mupdfwinrt/mupdfwinrt.vcxproj.filters
index 23e52055..5c98d5ba 100644
--- a/winrt/mupdfwinrt/mupdfwinrt.vcxproj.filters
+++ b/winrt/mupdfwinrt/mupdfwinrt.vcxproj.filters
@@ -13,6 +13,7 @@
<ClCompile Include="Links.cpp" />
<ClCompile Include="ContentItem.cpp" />
<ClCompile Include="utils.cpp" />
+ <ClCompile Include="Cache.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
@@ -21,5 +22,6 @@
<ClInclude Include="Links.h" />
<ClInclude Include="utils.h" />
<ClInclude Include="ContentItem.h" />
+ <ClInclude Include="Cache.h" />
</ItemGroup>
</Project> \ No newline at end of file