From d59a3e217e6e3196471f838695810210f0fc938f Mon Sep 17 00:00:00 2001 From: ezdiy Date: Tue, 22 Sep 2020 22:04:37 +0200 Subject: [PATCH] Pocketbook: Implement HW screen rotation, bring in PB specific kludges from linuxfb (#6684) * Uses bunch of new plumbing in base to configure screen rotations in hardware (koreader normally does this via blit buffer rotations, except for android). * Some PB specific kludges that used to pollute core/framebuffer_linux are brought into PBs frontend driver. --- base | 2 +- frontend/device/generic/device.lua | 17 ++++----- frontend/device/gesturedetector.lua | 9 ++--- frontend/device/pocketbook/device.lua | 50 +++++++++++++++++++-------- frontend/ui/uimanager.lua | 2 ++ spec/unit/gesturedetector_spec.lua | 2 +- 6 files changed, 54 insertions(+), 28 deletions(-) diff --git a/base b/base index 009227741..2ef312502 160000 --- a/base +++ b/base @@ -1 +1 @@ -Subproject commit 00922774168ba8cab225d337f1bbeb15d2799d8d +Subproject commit 2ef312502979bd8b5b7606cf15d4aa6b8eaa8259 diff --git a/frontend/device/generic/device.lua b/frontend/device/generic/device.lua index a65bd9296..eee25aad3 100644 --- a/frontend/device/generic/device.lua +++ b/frontend/device/generic/device.lua @@ -80,17 +80,18 @@ local Device = { -- some devices have part of their screen covered by the bezel viewport = nil, - -- enforce portrait orientation on display, no matter how configured at - -- startup + -- enforce portrait orientation of display when FB defaults to landscape isAlwaysPortrait = no, + -- On some devices (eg newer pocketbook) we can force HW rotation on the fly (before each update) + -- The value here is table of 4 elements mapping the sensible linux constants to whatever + -- nonsense the device actually has. Canonically it should be { 0, 1, 2, 3 } if the device + -- matches FB_ROTATE_* constants. + -- See https://github.com/koreader/koreader-base/blob/master/ffi/framebuffer.lua for full template + -- of the table expected. + usingForcedRotation = nil, -- needs full screen refresh when resumed from screensaver? needsScreenRefreshAfterResume = yes, - -- set to yes on devices whose framebuffer reports 8bit per pixel, - -- but is actually a color eInk screen with 24bit per pixel. - -- The refresh is still based on bytes. (This solves issue #4193.) - has3BytesWideFrameBuffer = no, - -- set to yes on devices that support over-the-air incremental updates. hasOTAUpdates = no, @@ -392,8 +393,8 @@ end prepare for application shutdown --]] function Device:exit() - require("ffi/input"):closeAll() self.screen:close() + require("ffi/input"):closeAll() end function Device:retrieveNetworkInfo() diff --git a/frontend/device/gesturedetector.lua b/frontend/device/gesturedetector.lua index 757fd17d4..e9339fb12 100644 --- a/frontend/device/gesturedetector.lua +++ b/frontend/device/gesturedetector.lua @@ -601,7 +601,7 @@ function GestureDetector:handlePan(tev) local pan_ev_multiswipe = pan_ev -- store a copy of pan_ev without rotation adjustment -- for multiswipe calculations when rotated - if self.screen.cur_rotation_mode > self.screen.ORIENTATION_PORTRAIT then + if self.screen:getTouchRotation() > self.screen.ORIENTATION_PORTRAIT then pan_ev_multiswipe = util.tableDeepCopy(pan_ev) end if msd_direction ~= msd_direction_prev then @@ -787,7 +787,8 @@ end @return adjusted gesture. --]] function GestureDetector:adjustGesCoordinate(ges) - if self.screen.cur_rotation_mode == self.screen.ORIENTATION_LANDSCAPE then + local mode = self.screen:getTouchRotation() + if mode == self.screen.ORIENTATION_LANDSCAPE then -- in landscape mode rotated 90 if ges.pos then ges.pos.x, ges.pos.y = (self.screen:getWidth() - ges.pos.y), (ges.pos.x) @@ -814,7 +815,7 @@ function GestureDetector:adjustGesCoordinate(ges) ges.direction = "horizontal" end end - elseif self.screen.cur_rotation_mode == self.screen.ORIENTATION_LANDSCAPE_ROTATED then + elseif mode == self.screen.ORIENTATION_LANDSCAPE_ROTATED then -- in landscape mode rotated 270 if ges.pos then ges.pos.x, ges.pos.y = (ges.pos.y), (self.screen:getHeight() - ges.pos.x) @@ -841,7 +842,7 @@ function GestureDetector:adjustGesCoordinate(ges) ges.direction = "horizontal" end end - elseif self.screen.cur_rotation_mode == self.screen.ORIENTATION_PORTRAIT_ROTATED then + elseif mode == self.screen.ORIENTATION_PORTRAIT_ROTATED then -- in portrait mode rotated 180 if ges.pos then ges.pos.x, ges.pos.y = (self.screen:getWidth() - ges.pos.x), (self.screen:getHeight() - ges.pos.y) diff --git a/frontend/device/pocketbook/device.lua b/frontend/device/pocketbook/device.lua index c80baba2d..edeec1aa6 100644 --- a/frontend/device/pocketbook/device.lua +++ b/frontend/device/pocketbook/device.lua @@ -39,6 +39,10 @@ local PocketBook = Generic:new{ -- Apparently, HW inversion is a pipedream on PB (#6669) canHWInvert = no, + + -- Private per-model kludges + _fb_init = function() end, + _model_init = function() end, } -- Make sure the C BB cannot be used on devices with a 24bpp fb @@ -75,7 +79,13 @@ function PocketBook:init() -- Blacklist the C BB before the first BB require... self:blacklistCBB() - self.screen = require("ffi/framebuffer_mxcfb"):new{device = self, debug = logger.dbg} + self.screen = require("ffi/framebuffer_mxcfb"):new { + device = self, + debug = logger.dbg, + is_always_portrait = self.isAlwaysPortrait(), + forced_rotation = self.usingForcedRotation, + fbinfoOverride = self._fb_init, + } self.powerd = require("device/pocketbook/powerd"):new{device = self} -- Whenever we lose focus, but also get suspended for real (we can't reliably tell atm), @@ -143,12 +153,7 @@ function PocketBook:init() end end) - -- fix rotation for Color Lux device - if PocketBook:getDeviceModel() == "PocketBook Color Lux" then - self.screen.blitbuffer_rotation_mode = self.screen.ORIENTATION_PORTRAIT - self.screen.native_rotation_mode = self.screen.ORIENTATION_PORTRAIT - end - + self._model_init() self.input.open() self:setAutoStandby(true) Generic.init(self) @@ -265,6 +270,14 @@ function PocketBook:getDeviceModel() return ffi.string(inkview.GetDeviceModel()) end +-- Pocketbook HW rotation modes start from landsape, CCW +local landscape_ccw = { + 1, 0, 3, 2, -- PORTRAIT, LANDSCAPE, PORTRAIT_180, LANDSCAPE_180 + every_paint = true, -- inkview will try to steal the rot mode frequently + restore = false, -- no need, because everything using inkview forces 3 on focus + default = nil, -- usually 3 +} + -- PocketBook Mini (515) local PocketBook515 = PocketBook:new{ model = "PB515", @@ -377,7 +390,7 @@ local PocketBook627 = PocketBook:new{ local PocketBook628 = PocketBook:new{ model = "PBTouchLux5", display_dpi = 212, - isAlwaysPortrait = yes, + usingForcedRotation = landscape_ccw, hasNaturalLight = yes, } @@ -399,7 +412,7 @@ local PocketBook631 = PocketBook:new{ local PocketBook632 = PocketBook:new{ model = "PBTouchHDPlus", display_dpi = 300, - isAlwaysPortrait = yes, + usingForcedRotation = landscape_ccw, hasNaturalLight = yes, } @@ -409,7 +422,7 @@ local PocketBook633 = PocketBook:new{ display_dpi = 300, hasColorScreen = yes, canUseCBB = no, -- 24bpp - isAlwaysPortrait = yes, + usingForcedRotation = landscape_ccw, } -- PocketBook Aqua (640) @@ -434,7 +447,7 @@ local PocketBook650 = PocketBook:new{ local PocketBook740 = PocketBook:new{ model = "PBInkPad3", display_dpi = 300, - isAlwaysPortrait = yes, + usingForcedRotation = landscape_ccw, hasNaturalLight = yes, } @@ -442,7 +455,7 @@ local PocketBook740 = PocketBook:new{ local PocketBook740_2 = PocketBook:new{ model = "PBInkPad3Pro", display_dpi = 300, - isAlwaysPortrait = yes, + usingForcedRotation = landscape_ccw, hasNaturalLight = yes, } @@ -451,9 +464,18 @@ local PocketBookColorLux = PocketBook:new{ model = "PBColorLux", display_dpi = 125, hasColorScreen = yes, - has3BytesWideFrameBuffer = yes, canUseCBB = no, -- 24bpp } +function PocketBookColorLux:_model_init() + self.screen.blitbuffer_rotation_mode = self.screen.ORIENTATION_PORTRAIT + self.screen.native_rotation_mode = self.screen.ORIENTATION_PORTRAIT +end +function PocketBookColorLux._fb_init(fb,finfo,vinfo) + -- Pocketbook Color Lux reports bits_per_pixel = 8, but actually uses an RGB24 framebuffer + vinfo.bits_per_pixel = 24 + vinfo.xres = vinfo.xres / 3 + fb.refresh_pixel_size = 3 +end -- PocketBook InkPad / InkPad 2 (840) local PocketBook840 = PocketBook:new{ @@ -465,7 +487,7 @@ local PocketBook840 = PocketBook:new{ local PocketBook1040 = PocketBook:new{ model = "PB1040", display_dpi = 227, - isAlwaysPortrait = yes, + usingForcedRotation = landscape_ccw, hasNaturalLight = yes, } diff --git a/frontend/ui/uimanager.lua b/frontend/ui/uimanager.lua index a6375b108..04b8b2d1b 100644 --- a/frontend/ui/uimanager.lua +++ b/frontend/ui/uimanager.lua @@ -1062,6 +1062,7 @@ function UIManager:_repaint() -- pass hint to widget that we got when setting widget dirty -- the widget can use this to decide which parts should be refreshed logger.dbg("painting widget:", widget.widget.name or widget.widget.id or tostring(widget)) + Screen:beforePaint() widget.widget:paintTo(Screen.bb, widget.x, widget.y, self._dirty[widget.widget]) -- and remove from list after painting @@ -1133,6 +1134,7 @@ function UIManager:_repaint() refresh.region.w, refresh.region.h, refresh.dither) end + Screen:afterPaint() self._refresh_stack = {} self.refresh_counted = false end diff --git a/spec/unit/gesturedetector_spec.lua b/spec/unit/gesturedetector_spec.lua index 548a113a7..e51523145 100644 --- a/spec/unit/gesturedetector_spec.lua +++ b/spec/unit/gesturedetector_spec.lua @@ -18,7 +18,7 @@ describe("gesturedetector module", function() ORIENTATION_PORTRAIT_ROTATED = 2, ORIENTATION_LANDSCAPE_ROTATED = 3, } - GestureDetector.screen.cur_rotation_mode = rotation_mode + GestureDetector.screen.getTouchRotation = function() return rotation_mode end return GestureDetector:adjustGesCoordinate(ges).direction end