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
pull/4852/head
NiLuJe 5 years ago committed by GitHub
parent fe3fc78171
commit 7210fb478d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1 +1 @@
Subproject commit 8660dcd10c3a0512ce5144a223e4c4ee34eb0646
Subproject commit 5f5df5c0091642daed49b09fb1b023c3113b66ed

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

Loading…
Cancel
Save