mirror of https://github.com/koreader/koreader
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
parent
a07ea2f8b8
commit
d96666f4b1
@ -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
|
||||
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
|
||||
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
|
||||
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
|
||||
end
|
||||
end
|
||||
cache_current_memsize = cache_current_memsize - v.size
|
||||
cache[k] = nil
|
||||
break -- out of for loop
|
||||
end
|
||||
end
|
||||
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, 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
|
||||
print("returning free slot="..freeslot)
|
||||
return freeslot
|
||||
return hash
|
||||
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 cachehash(no, zoom, offset_x, offset_y, width, height, gamma)
|
||||
return no..'_'..zoom..'_'..offset_x..','..offset_y..'-'..width..'x'..height..'_'..gamma;
|
||||
end
|
||||
return slot
|
||||
function clearcache()
|
||||
cache = {}
|
||||
end
|
||||
|
Loading…
Reference in New Issue