@ -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 = { }