Skip to content

Commit

Permalink
[PocketBook] Rejig PB fb setup shenanigans (#783)
Browse files Browse the repository at this point in the history
* Attempt to make sense of PB's various epic fails in terms of framebuffer setup...

This either fixes a lot of weird PB segfaults, or massively breaks PB support \o/.
  • Loading branch information
NiLuJe authored and Frenzie committed Jan 3, 2019
1 parent 18a9b89 commit 59cc501
Showing 1 changed file with 30 additions and 8 deletions.
38 changes: 30 additions & 8 deletions ffi/framebuffer_linux.lua
Expand Up @@ -66,6 +66,12 @@ But under 32bits mode, we got:
The only settings that got changed are `finfo.line_length` and `vinfo.bits_per_pixel`.
`finfo.smem_len` still remains at 10813440.
There's a reason for that: there used to be enough space for a shadow buffer on 16bpp modesets,
and that's no longer the case on 32bpp, since the active buffer now takes twice as much space.
What *is* definitely wrong in this log is yres_virtual in the 32bpp case, it should be much smaller,
so that line_length * yres_virtual == smem_len
AFAICT, this has since been fixed.
--]]
function framebuffer:init()
local finfo = ffi.new("struct fb_fix_screeninfo")
Expand All @@ -87,31 +93,47 @@ function framebuffer:init()
self.fb_size = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8
-- Newer eink framebuffer (Kindle Touch, Paperwhite, Kobo)
elseif ffi.string(finfo.id, 11) == "mxc_epdc_fb" then
-- it seems that finfo.smem_len is unreliable on kobo
-- Figure out the size of the screen in bytes
-- Figure out the size of the active screen buffer in bytes
self.fb_size = vinfo.xres_virtual * vinfo.yres_virtual * vinfo.bits_per_pixel / 8
-- Kobo hasn't updated smem_len when the depth was changed from 16 to 32
-- There's no longer space for a shadow buffer on 32bpp modesets, and yres_virtual may be bogus, so, use smem_len as-is
if vinfo.bits_per_pixel == 32 then
self.fb_size = finfo.smem_len
end
-- PocketBook eink framebuffer seems to have no finfo.id
elseif string.byte(ffi.string(finfo.id, 16), 1, 1) == 0 then
-- We may need to make sure finfo.line_length is 16-bytes aligned ourselves...
-- We may need to make sure finfo.line_length is properly aligned ourselves...
-- NOTE: Technically, the PxP *may* require a scratch space of *up to* 8 extra *pixels* in a line.
-- Here, we're dealing with bytes, so, technically, we should enforce an alignement to:
-- 8px * bpp / 8 which neatly comes down to simply bpp itself ;).
-- That's why xres_virtual is often a few px larger than xres: 8-bytes alignment, for that scratch space.
local line_length = finfo.line_length
finfo.line_length = bit.band(line_length * vinfo.bits_per_pixel / 8 + 15, bit.bnot(15))
-- NOTE: But because everything is terrible, line_length apparently sometimes doesn't take bpp into account on PB,
-- (i.e., it's in pixels instead of being in bytes), which is horribly wrong...
-- So try to fix that...
if finfo.line_length == vinfo.xres_virtual then
-- Make sure xres_virtual is aligned to 8-bytes
vinfo.xres_virtual = bit.band(vinfo.xres_virtual + 7, bit.bnot(7))
-- And now compute the proper line_length
finfo.line_length = (vinfo.xres_virtual * (vinfo.bits_per_pixel / 8))
else
-- As we said initially, ensure it's properly aligned, according to the bitdepth...
finfo.line_length = bit.band(finfo.line_length + (vinfo.bits_per_pixel - 1), bit.bnot(vinfo.bits_per_pixel - 1))
end
-- Now make sure yres_virtual is aligned to 8-bytes, too
vinfo.yres_virtual = bit.band(vinfo.yres_virtual + 7, bit.bnot(7))
-- And we should now have an accurate computation of the active buffer size... Whew!
self.fb_size = finfo.line_length * vinfo.yres_virtual
-- NOTE: If our manually computed value is larger than the reported smem_len, honor smem_len instead (c.f., #4416)
-- Because despite PB's shenanigans, I'm assuming smem_len matches the actual HW bounds,
-- and as such matches the extent of memory we can safely mmap.
-- TL;DR: We can safely mmap a *smaller* memory region than smem_len,
-- (which is usually what all of the fb_size computations that don't use smem_len do here),
-- but we certainly CANNOT mmap a *larger* one!
-- Hell, if PB wasn't so broken, I'd make that an assert!
if self.fb_size > finfo.smem_len then
self.fb_size = finfo.smem_len
-- And that means line_length should *probably* be honored, too...
-- Possibly 8-bytes aligned to make the PxP happy?
finfo.line_length = bit.band(line_length * vinfo.bits_per_pixel / 8 + 7, bit.bnot(7))
-- Here's hoping that it's honoring the PxP requirements properly...
finfo.line_length = line_length
end
else
error("framebuffer model not supported");
Expand Down

0 comments on commit 59cc501

Please sign in to comment.