mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
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:
@@ -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 = {}
|
||||
|
||||
Reference in New Issue
Block a user