Fix partial HW dithered refreshes sometimes appearing to shift refreshed content (#6267)

* Fix HW dithered partial refreshes sometimes behaving as if the refreshed
content had moved a few pixels to the side...

Probably a kernel issue with the alignment fixup in the EPDC?

* Get rid of the legacy coordinates fixup

It shouldn't be necessary anymore.
And I'd rather fix the root cause, anyway.

* Bump base

(https://github.com/koreader/koreader-base/pull/1116)

* Missed a few DIVs in #6224
This commit is contained in:
NiLuJe
2020-06-14 02:21:41 +02:00
committed by GitHub
parent d6e87a111a
commit b23af97914
15 changed files with 58 additions and 21 deletions

View File

@@ -962,6 +962,21 @@ function UIManager:_refresh(mode, region, dither)
table.insert(self._refresh_stack, {mode = mode, region = region, dither = dither})
end
-- A couple helper functions to compute aligned values...
-- c.f., <linux/kernel.h> & ffi/framebuffer_linux.lua
local function ALIGN_DOWN(x, a)
-- x & ~(a-1)
local mask = a - 1
return bit.band(x, bit.bnot(mask))
end
local function ALIGN_UP(x, a)
-- (x + (a-1)) & ~(a-1)
local mask = a - 1
return bit.band(x + mask, bit.bnot(mask))
end
--- Repaints dirty widgets.
function UIManager:_repaint()
-- flag in which we will record if we did any repaints at all
@@ -1031,12 +1046,34 @@ function UIManager:_repaint()
refresh.dither = nil
end
dbg:v("triggering refresh", refresh)
-- NOTE: We overshoot by 1px to account for potential off-by-ones.
-- This may not strictly be needed anymore, and is blatantly unneeded for full-screen updates,
-- but checkBounds & getPhysicalRect will sanitize that in mxc_update @ ffi/framebuffer_mxcfb ;).
-- NOTE: If we're requesting hardware dithering on a partial update, make sure the rectangle is using
-- coordinates aligned to the previous multiple of 8, and dimensions aligned to the next multiple of 8.
-- Otherwise, some unlucky coordinates will play badly with the PxP's own alignment constraints,
-- leading to a refresh where content appears to have moved a few pixels to the side...
-- (Sidebar: this is probably a kernel issue, the EPDC driver is responsible for the alignment fixup,
-- c.f., epdc_process_update @ drivers/video/fbdev/mxc/mxc_epdc_v2_fb.c on a Kobo Mk. 7 kernel...).
if refresh.dither then
-- NOTE: Make sure the coordinates are positive, first! Otherwise, we'd gladly align further down below 0,
-- which would skew the rectangle's position/dimension after checkBounds...
local x_fixup = 0
if refresh.region.x > 0 then
local x_orig = refresh.region.x
refresh.region.x = ALIGN_DOWN(x_orig, 8)
x_fixup = x_orig - refresh.region.x
end
local y_fixup = 0
if refresh.region.y > 0 then
local y_orig = refresh.region.y
refresh.region.y = ALIGN_DOWN(y_orig, 8)
y_fixup = y_orig - refresh.region.y
end
-- And also make sure we won't be inadvertently cropping our rectangle in case of severe alignment fixups...
refresh.region.w = ALIGN_UP(refresh.region.w + (x_fixup * 2), 8)
refresh.region.h = ALIGN_UP(refresh.region.h + (y_fixup * 2), 8)
end
Screen[refresh_methods[refresh.mode]](Screen,
refresh.region.x - 1, refresh.region.y - 1,
refresh.region.w + 2, refresh.region.h + 2,
refresh.region.x, refresh.region.y,
refresh.region.w, refresh.region.h,
refresh.dither)
end
self._refresh_stack = {}