mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
Faster blitting @ BB8/BBRGB32 when no processing is needed (#4847)
* Pickup the eponymous blitting performance tweaks from koreader/koreader-base#878 * Cleanup BitOpts usage (require & cache) * Unify oddness checks (MOD -> AND) * Enforce the native Portrait orientation on Kobo (except @ 16bpp, i.e., KSM w/ 8bpp swap disabled), to allow for faster blitting when unrotted. * Switch CRe BB to 32BPP on color screens * Minor cleanups
This commit is contained in:
2
base
2
base
Submodule base updated: 8660dcd10c...5f5df5c009
@@ -1,3 +1,4 @@
|
||||
local bit = require("bit")
|
||||
local Blitbuffer = require("ffi/blitbuffer")
|
||||
local ConfirmBox = require("ui/widget/confirmbox")
|
||||
local Device = require("device")
|
||||
@@ -11,6 +12,8 @@ local Input = Device.input
|
||||
local Screen = Device.screen
|
||||
local T = require("ffi/util").template
|
||||
|
||||
local band = bit.band
|
||||
|
||||
--[[
|
||||
Rolling is just like paging in page-based documents except that
|
||||
sometimes (in scroll mode) there is no concept of page number to indicate
|
||||
@@ -789,12 +792,12 @@ function ReaderRolling:_gotoPage(new_page, free_first_page)
|
||||
if self.ui.document:getVisiblePageCount() > 1 and not free_first_page then
|
||||
-- Ensure we always have the first of the two pages odd
|
||||
if self.odd_or_even_first_page == 1 then -- odd
|
||||
if new_page % 2 == 0 then
|
||||
if band(new_page, 1) == 0 then
|
||||
-- requested page will be shown as the right page
|
||||
new_page = new_page - 1
|
||||
end
|
||||
elseif self.odd_or_even_first_page == 2 then -- (or 'even' if requested)
|
||||
if new_page % 2 == 1 then
|
||||
if band(new_page, 1) == 1 then
|
||||
-- requested page will be shown as the right page
|
||||
new_page = new_page - 1
|
||||
end
|
||||
|
||||
@@ -219,7 +219,7 @@ function Device:onPowerEvent(ev)
|
||||
G_reader_settings:readSetting("screensaver_type") == "random_image" or
|
||||
G_reader_settings:readSetting("screensaver_type") == "image_file" then
|
||||
if not G_reader_settings:isTrue("screensaver_no_background") then
|
||||
self.screen:clear(self.screen:getScreenWidth(), self.screen:getScreenHeight())
|
||||
self.screen:clear()
|
||||
end
|
||||
self.screen:refreshFull()
|
||||
end
|
||||
|
||||
@@ -359,18 +359,20 @@ function CreDocument:drawCurrentView(target, x, y, rect, pos)
|
||||
end
|
||||
if not self.buffer then
|
||||
-- Note about color rendering:
|
||||
-- If we use TYPE_BBRGB32 (and LVColorDrawBuf drawBuf(..., 32) in cre.cpp),
|
||||
-- we get inverted Red and Blue in the blitbuffer (could be that
|
||||
-- crengine/src/lvdrawbuf.cpp treats our 32bits not as RGBA).
|
||||
-- But it is all fine if we use TYPE_BBRGB16.
|
||||
self.buffer = Blitbuffer.new(rect.w, rect.h, self.render_color and Blitbuffer.TYPE_BBRGB16 or nil)
|
||||
-- We use TYPE_BBRGB32 (and LVColorDrawBuf drawBuf(..., 32) in cre.cpp),
|
||||
-- to match the screen's BB type, allowing us to take shortcuts when blitting.
|
||||
self.buffer = Blitbuffer.new(rect.w, rect.h, self.render_color and Blitbuffer.TYPE_BBRGB32 or nil)
|
||||
end
|
||||
-- TODO: self.buffer could be re-used when no page/layout/highlights
|
||||
-- change has been made, to avoid having crengine redraw the exact
|
||||
-- same buffer.
|
||||
-- And it could only change when some other methods from here are called
|
||||
--local start_clock = os.clock()
|
||||
self._drawn_images_count, self._drawn_images_surface_ratio = self._document:drawCurrentPage(self.buffer, self.render_color)
|
||||
--print(string.format("CreDocument:drawCurrentView: Rendering took %9.3f ms", (os.clock() - start_clock) * 1000))
|
||||
--start_clock = os.clock()
|
||||
target:blitFrom(self.buffer, x, y, 0, 0, rect.w, rect.h)
|
||||
--print(string.format("CreDocument:drawCurrentView: Blitting took %9.3f ms", (os.clock() - start_clock) * 1000))
|
||||
end
|
||||
|
||||
function CreDocument:drawCurrentViewByPos(target, x, y, rect, pos)
|
||||
|
||||
@@ -134,6 +134,7 @@ function Document:fastDigest(docsettings)
|
||||
local result = docsettings:readSetting("partial_md5_checksum")
|
||||
if not result then
|
||||
logger.dbg("computing and storing partial_md5_checksum")
|
||||
local bit = require("bit")
|
||||
local md5 = require("ffi/MD5")
|
||||
local lshift = bit.lshift
|
||||
local step, size = 1024, 1024
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
Simple math helper functions
|
||||
]]
|
||||
|
||||
local bit = require("bit")
|
||||
|
||||
local Math = {}
|
||||
|
||||
local band = bit.band
|
||||
|
||||
function Math.roundAwayFromZero(num)
|
||||
if num > 0 then
|
||||
return math.ceil(num)
|
||||
@@ -17,7 +21,7 @@ function Math.round(num)
|
||||
end
|
||||
|
||||
function Math.oddEven(number)
|
||||
if number % 2 == 1 then
|
||||
if band(number, 1) == 1 then
|
||||
return "odd"
|
||||
else
|
||||
return "even"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
--- A set of functions to extend math.random and math.randomseed.
|
||||
|
||||
local bit = require("bit")
|
||||
local random = {}
|
||||
|
||||
--- Uses current time as seed to randomize.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
Text rendering module.
|
||||
]]
|
||||
|
||||
local bit = require("bit")
|
||||
local Font = require("ui/font")
|
||||
local Cache = require("cache")
|
||||
local CacheItem = require("cacheitem")
|
||||
@@ -9,6 +10,10 @@ local BlitBuffer = require("ffi/blitbuffer")
|
||||
local Device = require("device")
|
||||
local logger = require("logger")
|
||||
|
||||
local band = bit.band
|
||||
local bor = bit.bor
|
||||
local lshift = bit.lshift
|
||||
|
||||
if Device.should_restrict_JIT then
|
||||
require("jit").off(true, true)
|
||||
end
|
||||
@@ -31,23 +36,23 @@ local function utf8Chars(input_text)
|
||||
local function read_next_glyph(input, pos)
|
||||
if string.len(input) < pos then return nil end
|
||||
local value = string.byte(input, pos)
|
||||
if bit.band(value, 0x80) == 0 then
|
||||
if band(value, 0x80) == 0 then
|
||||
-- TODO: check valid ranges
|
||||
return pos+1, value, string.sub(input, pos, pos)
|
||||
elseif bit.band(value, 0xC0) == 0x80 -- invalid, continuation
|
||||
or bit.band(value, 0xF8) == 0xF8 -- 5-or-more byte sequence, illegal due to RFC3629
|
||||
elseif band(value, 0xC0) == 0x80 -- invalid, continuation
|
||||
or band(value, 0xF8) == 0xF8 -- 5-or-more byte sequence, illegal due to RFC3629
|
||||
then
|
||||
return pos+1, 0xFFFD, "\xFF\xFD"
|
||||
else
|
||||
local glyph, bytes_left
|
||||
if bit.band(value, 0xE0) == 0xC0 then
|
||||
glyph = bit.band(value, 0x1F)
|
||||
if band(value, 0xE0) == 0xC0 then
|
||||
glyph = band(value, 0x1F)
|
||||
bytes_left = 1
|
||||
elseif bit.band(value, 0xF0) == 0xE0 then
|
||||
glyph = bit.band(value, 0x0F)
|
||||
elseif band(value, 0xF0) == 0xE0 then
|
||||
glyph = band(value, 0x0F)
|
||||
bytes_left = 2
|
||||
elseif bit.band(value, 0xF8) == 0xF0 then
|
||||
glyph = bit.band(value, 0x07)
|
||||
elseif band(value, 0xF8) == 0xF0 then
|
||||
glyph = band(value, 0x07)
|
||||
bytes_left = 3
|
||||
else
|
||||
return pos+1, 0xFFFD, "\xFF\xFD"
|
||||
@@ -57,8 +62,8 @@ local function utf8Chars(input_text)
|
||||
end
|
||||
for i = pos+1, pos + bytes_left do
|
||||
value = string.byte(input, i)
|
||||
if bit.band(value, 0xC0) == 0x80 then
|
||||
glyph = bit.bor(bit.lshift(glyph, 6), bit.band(value, 0x3F))
|
||||
if band(value, 0xC0) == 0x80 then
|
||||
glyph = bor(lshift(glyph, 6), band(value, 0x3F))
|
||||
else
|
||||
-- invalid UTF8 continuation - don't be greedy, just skip
|
||||
-- the initial char of the sequence.
|
||||
|
||||
@@ -168,7 +168,7 @@ function ImageWidget:_loadfile()
|
||||
-- cache this image
|
||||
logger.dbg("cache", hash)
|
||||
cache = ImageCacheItem:new{ bb = self._bb }
|
||||
cache.size = cache.bb.pitch * cache.bb.h * cache.bb:getBpp() / 8
|
||||
cache.size = cache.bb.pitch * cache.bb.h * cache.bb:getBytesPerPixel()
|
||||
ImageCache:insert(hash, cache)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,6 +30,7 @@ Example:
|
||||
|
||||
]]
|
||||
|
||||
local bit = require("bit")
|
||||
local Blitbuffer = require("ffi/blitbuffer")
|
||||
local CenterContainer = require("ui/widget/container/centercontainer")
|
||||
local Device = require("device")
|
||||
@@ -57,6 +58,8 @@ local _ = require("gettext")
|
||||
local T = require("ffi/util").template
|
||||
local Screen = Device.screen
|
||||
|
||||
local band = bit.band
|
||||
|
||||
local function obtainIP()
|
||||
-- TODO: check for DHCP result
|
||||
local info = InfoMessage:new{text = _("Obtaining IP address…")}
|
||||
@@ -386,7 +389,7 @@ function NetworkSetting:init()
|
||||
function(l, r) return l.signal_quality > r.signal_quality end)
|
||||
for idx, network in ipairs(self.network_list) do
|
||||
local bg
|
||||
if idx % 2 == 0 then
|
||||
if band(idx, 1) == 0 then
|
||||
bg = gray_bg
|
||||
else
|
||||
bg = Blitbuffer.COLOR_WHITE
|
||||
|
||||
@@ -135,19 +135,10 @@ if [ -z "${INTERFACE}" ]; then
|
||||
fi
|
||||
# end of value check of PLATFORM
|
||||
|
||||
# If we're on a Forma, make sure we start in an orientation we know how to handle (i.e., Portrait, buttons on the Right)
|
||||
# Because NTX likes mounting panels in weird native rotations, this is actually FB_ROTATE_CCW (3).
|
||||
# And because shit gets even weirder, we have to echo 1 to get 3 (because the kernel inverts Landscape FB constants, and 3 ^ 2 = 1).
|
||||
if [ "${PRODUCT}" = "frost" ]; then
|
||||
# NOTE: We enforce this *everywhere*, because KSM is currently emulating a bogus pickel rotation (UR (0), instead of CCW (3)),
|
||||
# and current kernels are surreptitiously broken when UR @ 8bpp (especially as far as A2 handling is concerned)...
|
||||
ORIG_FB_ROTA="$(cat /sys/class/graphics/fb0/rotate)"
|
||||
# Don't do anything if we're already in the right orientation.
|
||||
if [ "${ORIG_FB_ROTA}" -ne "3" ]; then
|
||||
echo 1 >/sys/class/graphics/fb0/rotate
|
||||
fi
|
||||
fi
|
||||
# NOTE: We don't have to restore anything on exit, nickel's startup process will take care of everything (pickel -> nickel).
|
||||
# We'll want to ensure Portrait rotation to allow us to use faster blitting codepaths @ 8bpp,
|
||||
# so remember the current one before fbdepth does its thing.
|
||||
ORIG_FB_ROTA="$(cat /sys/class/graphics/fb0/rotate)"
|
||||
echo "Original fb rotation is set @ ${ORIG_FB_ROTA}" >>crash.log 2>&1
|
||||
|
||||
# In the same vein, swap to 8bpp,
|
||||
# because 16bpp is the worst idea in the history of time, as RGB565 is generally a PITA without hardware blitting,
|
||||
@@ -175,14 +166,21 @@ ko_do_fbdepth() {
|
||||
if grep -q '\["dev_startup_no_fbdepth"\] = true' 'settings.reader.lua' 2>/dev/null; then
|
||||
# Swap back to the original bitdepth (in case this was a restart)
|
||||
if [ -n "${ORIG_FB_BPP}" ]; then
|
||||
echo "Making sure we're using the original fb bitdepth @ ${ORIG_FB_BPP}bpp" >>crash.log 2>&1
|
||||
./fbdepth -d "${ORIG_FB_BPP}" >>crash.log 2>&1
|
||||
# Unless we're a Forma, don't even bother to swap rotation if the fb is @ 16bpp, because RGB565 is terrible anyways,
|
||||
# so there's no faster codepath to achieve, and running in Portrait @ 16bpp might actually be broken on some setups...
|
||||
if [ "${ORIG_FB_BPP}" -eq "16" ] && [ "${PRODUCT}" != "frost" ]; then
|
||||
echo "Making sure we're using the original fb bitdepth @ ${ORIG_FB_BPP}bpp & rotation @ ${ORIG_FB_ROTA}" >>crash.log 2>&1
|
||||
./fbdepth -d "${ORIG_FB_BPP}" -r "${ORIG_FB_ROTA}" >>crash.log 2>&1
|
||||
else
|
||||
echo "Making sure we're using the original fb bitdepth @ ${ORIG_FB_BPP}bpp, and that rotation is set to Portrait" >>crash.log 2>&1
|
||||
./fbdepth -d "${ORIG_FB_BPP}" -r -1 >>crash.log 2>&1
|
||||
fi
|
||||
fi
|
||||
else
|
||||
# Swap to 8bpp if things looke sane
|
||||
if [ -n "${ORIG_FB_BPP}" ]; then
|
||||
echo "Switching fb bitdepth to 8bpp" >>crash.log 2>&1
|
||||
./fbdepth -d 8 >>crash.log 2>&1
|
||||
echo "Switching fb bitdepth to 8bpp & rotation to Portrait" >>crash.log 2>&1
|
||||
./fbdepth -d 8 -r -1 >>crash.log 2>&1
|
||||
fi
|
||||
fi
|
||||
}
|
||||
@@ -210,18 +208,13 @@ while [ $RETURN_VALUE -eq 85 ]; do
|
||||
done
|
||||
|
||||
# Restore original fb bitdepth if need be...
|
||||
# Since we also (almost) always enforce Portrait, we also have to restore the original rotation no matter what ;).
|
||||
if [ -n "${ORIG_FB_BPP}" ]; then
|
||||
echo "Restoring original fb bitdepth @ ${ORIG_FB_BPP}bpp" >>crash.log 2>&1
|
||||
./fbdepth -d "${ORIG_FB_BPP}" >>crash.log 2>&1
|
||||
fi
|
||||
|
||||
# Restore original fb rotation on the Forma, for KSM
|
||||
if [ "${PRODUCT}" = "frost" ]; then
|
||||
# Only needed for KSM, pickel -> Nickel will restore its own rota properly
|
||||
if [ "${FROM_NICKEL}" != "true" ]; then
|
||||
# The Forma kernel inverts odd rotation constants, counteract that, à la Plato, because one-liner ;p.
|
||||
echo "$(((4 - ORIG_FB_ROTA) % 4))" >/sys/class/graphics/fb0/rotate
|
||||
fi
|
||||
echo "Restoring original fb bitdepth @ ${ORIG_FB_BPP}bpp & rotation @ ${ORIG_FB_ROTA}" >>crash.log 2>&1
|
||||
./fbdepth -d "${ORIG_FB_BPP}" -r "${ORIG_FB_ROTA}" >>crash.log 2>&1
|
||||
else
|
||||
echo "Restoring original fb rotation @ ${ORIG_FB_ROTA}" >>crash.log 2>&1
|
||||
./fbdepth -r "${ORIG_FB_ROTA}" >>crash.log 2>&1
|
||||
fi
|
||||
|
||||
# Restore original CPUFreq governor if need be...
|
||||
|
||||
@@ -269,6 +269,7 @@ function ReaderStatistics:partialMd5(file)
|
||||
if file == nil then
|
||||
return nil
|
||||
end
|
||||
local bit = require("bit")
|
||||
local md5 = require("ffi/MD5")
|
||||
local lshift = bit.lshift
|
||||
local step, size = 1024, 1024
|
||||
|
||||
Reference in New Issue
Block a user