From d96666f4b18accead94dc9a6908196087a3329d4 Mon Sep 17 00:00:00 2001 From: HW Date: Sun, 20 Nov 2011 22:36:31 +0100 Subject: [PATCH] new cache organization in preparation for more complex tile data in order to use the tile cache for variable zoomed tiles, we need more flexibility. thus, now cache tiles are hashed (well, in fact it's a concatenation) of their metadata. also, we close pages right after opening them - there was no re-use before and now we have opening and closing at one place. this should also make it easier for the garbage collector. --- reader.lua | 47 ++++++++++++------------- tilecache.lua | 95 ++++++++++++++++++++++----------------------------- 2 files changed, 63 insertions(+), 79 deletions(-) diff --git a/reader.lua b/reader.lua index 2866025f7..139a2c4a7 100755 --- a/reader.lua +++ b/reader.lua @@ -51,6 +51,7 @@ rcount = 5 rcountmax = 5 globalzoom = -1 +globalgamma = -1.0 if optarg["d"] == "k3" then -- for now, the only difference is the additional input device @@ -66,6 +67,10 @@ else input.open("/dev/input/event1") end +if optarg["G"] ~= nil then + globalgamma = optarg["G"] +end + doc = pdf.openDocument(ARGV[optind], optarg["p"] or "") print("pdf has "..doc:getPages().." pages.") @@ -73,12 +78,11 @@ print("pdf has "..doc:getPages().." pages.") fb = einkfb.open("/dev/fb0") width, height = fb:getSize() -init_tilecache() - nulldc = pdf.newDC() -function setzoom(cacheslot) - local pwidth, pheight = cache[cacheslot].page:getSize(nulldc) +function setzoom(page, cacheslot) + local dc = pdf.newDC() + local pwidth, pheight = page:getSize(nulldc) -- default zoom: fit to page local zoom = width / pwidth @@ -90,18 +94,19 @@ function setzoom(cacheslot) offset_y = 0 end - cache[cacheslot].dc:setZoom(zoom) - cache[cacheslot].dc:setOffset(offset_x, offset_y) + dc:setZoom(zoom) + dc:setOffset(offset_x, offset_y) -- set gamma here, we don't have any other good place for this right now: - if optarg["G"] then - print("gamma correction: "..optarg["G"]) - cache[cacheslot].dc:setGamma(optarg["G"]) + if globalgamma ~= -1.0 then + print("gamma correction: "..globalgamma) + dc:setGamma(globalgamma) end + return dc end function show(no) - local slot = draworcache(no) + local slot = draworcache(no,globalzoom,0,0,width,height,globalgamma) fb:blitFullFrom(cache[slot].bb) if rcount == rcountmax then print("full refresh") @@ -123,22 +128,18 @@ function goto(no) show(no) if no < doc:getPages() then -- always pre-cache next page - draworcache(no+1) + draworcache(no+1,globalzoom,0,0,width,height,globalgamma) end end function modify_gamma(offset) - local slot = slot_visible - local gamma = cache[slot].dc:getGamma(); - if gamma == -1 then - gamma = 1 + if globalgamma == -1 then + globalgamma = 1 end - local no = cache[slot].no - print("modify_gamma "..no.." slot="..slot.." gamma="..gamma.." offset="..offset) - gamma = gamma + offset; - optarg["G"] = gamma; -- for next page - freecache() - goto(no) + print("modify_gamma, gamma="..globalgamma.." offset="..offset) + globalgamma = globalgamma + offset; + clearcache() + goto(pageno) end function mainloop() @@ -147,13 +148,9 @@ function mainloop() if ev.type == EV_KEY and ev.value == EVENT_VALUE_KEY_PRESS then local secs, usecs = util.gettime() if ev.code == KEY_PAGEUP then - print(cache) goto(pageno + 1) - print(cache) elseif ev.code == KEY_PAGEDOWN then - print(cache) goto(pageno - 1) - print(cache) elseif ev.code == KEY_BACK then return elseif ev.code == KEY_UP then diff --git a/tilecache.lua b/tilecache.lua index 31c9e1040..8aa7657a3 100755 --- a/tilecache.lua +++ b/tilecache.lua @@ -1,64 +1,51 @@ --[[ a cache for rendered tiles ]]-- - -function init_tilecache() - cache = { - { age = 0, no = 0, bb = blitbuffer.new(width, height), dc = pdf.newDC(), page = nil }, - { age = 0, no = 0, bb = blitbuffer.new(width, height), dc = pdf.newDC(), page = nil }, - { age = 0, no = 0, bb = blitbuffer.new(width, height), dc = pdf.newDC(), page = nil } - } -end -function freecache() - for i = 1, #cache do - if cache[i].page ~= nil then - print("freeing slot="..i.." oldpage="..cache[i].no) - cache[i].page:close() - cache[i].page = nil - end - end -end -function checkcache(no) - for i = 1, #cache do - if cache[i].no == no and cache[i].page ~= nil then - print("cache hit: slot="..i.." page="..no) - return i - end +cache_max_memsize = 1024*1024*5 -- 5MB tile cache +cache_current_memsize = 0 +cache = {} +cache_max_age = 20 +function cacheclaim(size) + if(size > cache_max_memsize) then + error("too much memory claimed") + return false end - print("cache miss") - return nil -end -function cacheslot() - freeslot = nil - while freeslot == nil do - for i = 1, #cache do - if cache[i].age > 0 then - print("aging slot="..i) - cache[i].age = cache[i].age - 1 + repeat + for k, v in pairs(cache) do + if v.age > 0 then + print("aging slot="..k) + v.age = v.age - 1 else - if cache[i].page ~= nil then - print("freeing slot="..i.." oldpage="..cache[i].no) - cache[i].page:close() - cache[i].page = nil - end - freeslot = i + cache_current_memsize = cache_current_memsize - v.size + cache[k] = nil + break -- out of for loop end end - end - print("returning free slot="..freeslot) - return freeslot + until cache_current_memsize + size <= cache_max_memsize + cache_current_memsize = cache_current_memsize + size + print("cleaned cache to fit new tile (size="..size..")") + return true end - -function draworcache(no) - local slot = checkcache(no) - if slot == nil then - slot = cacheslot() - cache[slot].no = no - cache[slot].age = #cache - cache[slot].page = doc:openPage(no) - setzoom(slot) - print("drawing page="..no.." to slot="..slot) - cache[slot].page:draw(cache[slot].dc, cache[slot].bb, 0, 0) +function draworcache(no, zoom, offset_x, offset_y, width, height, gamma) + local hash = cachehash(no, zoom, offset_x, offset_y, width, height, gamma) + if cache[hash] == nil then + cacheclaim(width * height / 2); + cache[hash] = { + age = cache_max_age, + size = width * height / 2, + bb = blitbuffer.new(width, height) + } + print("drawing page="..no.." to slot="..hash) + local page = doc:openPage(no) + local dc = setzoom(page, hash) + page:draw(dc, cache[hash].bb, 0, 0) + page:close() end - return slot + return hash +end +function cachehash(no, zoom, offset_x, offset_y, width, height, gamma) + return no..'_'..zoom..'_'..offset_x..','..offset_y..'-'..width..'x'..height..'_'..gamma; +end +function clearcache() + cache = {} end