-
Notifications
You must be signed in to change notification settings - Fork 104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
BlitBuffer: Make sure we *never* update a color reference #1309
Conversation
Tested (as of 0e87556) on my Kobo:
So, the SW dithering causes same issues with both C/!C blitting. Oh, but no issue if, in ImageViewer, I pinch to zoom and make the image smaller than the ImageViewer area ! Only when Scale or Original size (both make the images touch the top/bottomborders - with initially white stripes on left/right - these white stripes becomes black or grey on each further refreshes). |
Same dithering code on both sides, with the grid now aligned the exact same way. (And, remember, I'm testing this on an H2O, which technically uses an older SoC than your Glo HD ;)). And it's plain C/LuaFFI byte-by-byte, so, no alignment constraints. It's just that a dithered image is extremely prone to ghosting and weird eInk shenanigans. IIRC, ImageViewer now defers scaling to MuPDF, so, stuff should be sane on that front, I think? Nice to know that this did fix a crash/hang, though ^^. |
The dither code is way over my head - but something I don't get: what are x and y in there: koreader-base/ffi/blitbuffer.lua Lines 230 to 247 in d980ec9
They seem to be coordinates of the input pixel we get the original color from as v. |
Yep, hence "ordered" dither and the grid pattern (as opposed to error diffusion algorithms which do push error into surrounding pixels). |
No issue with local function dither_o8x8(x, y, v)
+ if true then return v end
-- Constants: No issue if I put this line at the end of the function (to still have the computation done). So I guess our code is fine, and it's indeed down the hardware that things get bad because of the patterns of color values :/ |
local function dither_o8x8(x, y, v)
if x < 10 or y < 10 then return v end
if x > 1061 or y > 1437 then return v end
[...]
Scratch that... what limited the issues was having my Kobo plugged into USB (so I could do these edits and quickly test)... Plugged in/charging : no issue (even without the above hack) |
Huh. Might affect the voltages applied by the waveform? Gremlins! FWIW, makes no difference on my end (and neither does toggling Wi-Fi, which is extra-funky on the H2O because of the whole DVFS thingy). |
Now, why the hell are the *source* colors off when scaling w/ the Lua blitter?
we call it, we always store the result in a new object. Because the color we pass around is mostly *always* a reference, so updating that with a different pixel-format is obviously a recipe for disaster... In fact, I'm not quite sure why this hasn't blown un in fun and interesting ways before...
They don't matter her, but they do in C because AND has lower priority than MUL
e.g., Assume getPixel returns a const Color? *, while getPixel returns a Color? *
In the vast majority if cases, in blitbuffer, when we're passed a
Color?
object, it's a direct reference (e.g.,Color8 &
) to the buffer itself. As such, if we update it, we're writing to the buffer.This is obviously a terrible idea (except in the cases where we actually want to write to the buffer ^^), and shit starts getting really scary when you remember that we most often do that via the
getColor?
methods, which do pixel-format conversions. Ouch.I'm mildly amazed this has never blown up anywhere in fun and interesting ways before, but, this was at least exposed by @poire-z's testcase in koreader/koreader#5916 (comment)
ImageViewer starts by showing the image full-screen, then a tap scales it in order to show the buttons. Something was modifying the buffer in-between those two states, which meant that the scaled buffer was slightly off. This was made more obvious when dithering enters the fray, as this generated a different, more obvious dither pattern.
Also, compute the dither diffusion based on the source coordinates, not the target's. (Much like the C blitter).
This doesn't happen with the C blitter, because, there, the distinction between what's a pointer/ref and what's a value is much clearer in plain C. (Also, the compiler would shout at you very sternly when this kind of thing happens and involves type-punning. Also,
const
exists in C ^^).This change is