diff options
author | Michael Vrhel <michael.vrhel@artifex.com> | 2013-06-14 09:24:37 -0700 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2013-06-14 21:25:01 +0100 |
commit | f9574246ead2457963ede0c6d65e208ad6943258 (patch) | |
tree | d85069efadf5a6b5b78403eda57b0adabb7a45e0 /winrt | |
parent | 9a1898c42152dfac560bb9d291e43f7dc0fd40ac (diff) | |
download | mupdf-f9574246ead2457963ede0c6d65e208ad6943258.tar.xz |
Addition of locking cache for display list in winRT library
Diffstat (limited to 'winrt')
-rw-r--r-- | winrt/mupdf_cpp/MainPage.xaml.cpp | 24 | ||||
-rw-r--r-- | winrt/mupdfwinrt/Cache.cpp | 112 | ||||
-rw-r--r-- | winrt/mupdfwinrt/Cache.h | 37 | ||||
-rw-r--r-- | winrt/mupdfwinrt/muctx.cpp | 62 | ||||
-rw-r--r-- | winrt/mupdfwinrt/muctx.h | 12 | ||||
-rw-r--r-- | winrt/mupdfwinrt/mudocument.cpp | 22 | ||||
-rw-r--r-- | winrt/mupdfwinrt/mudocument.h | 2 | ||||
-rw-r--r-- | winrt/mupdfwinrt/mupdfwinrt.vcxproj | 2 | ||||
-rw-r--r-- | winrt/mupdfwinrt/mupdfwinrt.vcxproj.filters | 2 |
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 |