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.
pull/2/merge
HW 13 years ago
parent a07ea2f8b8
commit d96666f4b1

@ -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

@ -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

Loading…
Cancel
Save