-
Notifications
You must be signed in to change notification settings - Fork 105
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
[feat] SDL2: update parts of window like a real device #626
Conversation
This commit first renders the full updated blitbuffer to a temporary texture. Subsequently it renders the updated rectangle from the temporary texture onto the final texture, which has up to that point retained all of the old pixel info. That final texture, of which only the one rectangular area was updated, is then rendered to the window. Without this, there are cases where a full screen (or at least bigger) refresh is required that will not be obvious without first testing on a real device. See koreader/koreader#3804 Also fixes `EMULATE_READER_FLASH`, which was accidentally broken in 981bd40
Working fine. One small observation:
Before this, over slow ssh, I saw a single paint from top to bottom: so top menu was drawn first. I'm just wondering if the fact that I didn't see 2 painting before is may be one being cancelled by the 2nd by X11 or SDL - or them being combined. So, no real problem, just saying in case that behaviour talks to you that just put eyes on this code :) |
Note that you should've always been able to see it with something like I think I've made things slightly slower with my workaround. I do see the effect you mention, at least when maximized. It's hard to tell, but with manual stopwatch timing I get ~30 ms for before and ~40 ms for after on fullscreen HD to open the menu. Which certainly makes intuitive sense with the overhead of creating an extra texture and all that. Since SDL isn't just for debugging that means this might need a slight rethink. On the other hand, since no one uses Ubuntu Phone anymore anyway it might not matter for the moment? Before
After
I'm actually slightly surprised to see SDL_SetRenderTarget taking the bulk of the CPU time. Get this in now and improve later or let it sit until I have time to experiment? |
OK, I see the 2 steps with
I don't mind the little extra slowness. The fact that we see multiple small stuff happening makes it feel less slow actually :) So, go ahead. (btw, i'll soon be off for a week, so please don't wait for my comments - you can go on building that koreader desktop app while I have my back turned :). |
I don't think slower is part of a desktop app. :-p (And this particular setup is definitely wholly for the emulator.) Before you go, do you have any opinion on hotkeys to trigger some refresh debug output during runtime? (Similar to that flash thing.) I got some ideas while playing with this. |
No particular opinion, but no pb with having hotkeys for debugging. |
Yeah, so Callgrind says (or at least strongly implies) LuaJIT is just getting the important bit wrong for some reason and that SDL_UpdateTexture is responsible as made much more sense really. But good news! I found a much better solution. It changes much less, it looks like this and it performs very well: function framebuffer:_render(bb, x, y, w, h)
w, x = BB.checkBounds(w or bb:getWidth(), x or 0, 0, bb:getWidth(), 0xFFFF)
h, y = BB.checkBounds(h or bb:getHeight(), y or 0, 0, bb:getHeight(), 0xFFFF)
x, y, w, h = bb:getPhysicalRect(x, y, w, h)
local ffi = require("ffi")
local cdata = ffi.C.malloc(w * h * 4)
local mem = ffi.cast("char*", cdata)
local offset_counter = 0
for from_top = y, y+h-1 do
local offset = 4 * w * offset_counter
offset_counter = offset_counter + 1
for from_left = x, x+w-1 do
local c = bb:getPixel(from_left, from_top):getColorRGB32()
mem[offset] = c.r
mem[offset + 1] = c.g
mem[offset + 2] = c.b
mem[offset + 3] = 0xFF
offset = offset + 4
end
end
local rect = SDL.rect(x, y, w, h)
if bb:getInverse() == 1 then
self.invert_bb:invertblitFrom(bb)
SDL.SDL.SDL_UpdateTexture(temp_texture, nil, self.invert_bb.data, self.invert_bb.pitch)
else
SDL.SDL.SDL_UpdateTexture(SDL.texture, rect, mem, 4*w)
end
ffi.C.free(cdata)
SDL.SDL.SDL_RenderClear(SDL.renderer)
SDL.SDL.SDL_RenderCopy(SDL.renderer, SDL.texture, nil, nil)
SDL.SDL.SDL_RenderPresent(SDL.renderer)
end On a side note, I just came across https://github.com/torch/sdl2-ffi/blob/50659fbeca83d667240b197298a0462c7ec0ad21/cdefs.lua#L2293 which looks like it makes for easier c/p (because ready-made). |
Now the profile looks like this (i.e., that free should obviously be post-render):
Edit: output after moving the ffi.C.free to the bottom:
It's looking like a performance increase, neat. :-) |
ffi/framebuffer_SDL2_0.lua
Outdated
|
||
local rect = SDL.rect(x, y, w, h) | ||
-- lazy solution: ideally it'd be a texture of exactly | ||
-- the right size with SDL.createTexture(w, h) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes a bigger difference for performance than I thought, too.
886a849
to
d41d9ce
Compare
ffi/framebuffer_SDL2_0.lua
Outdated
else | ||
SDL.SDL.SDL_UpdateTexture(SDL.texture, nil, bb.data, bb.pitch) | ||
-- @TODO also use this on Android? | ||
cdata = ffi.C.malloc(w * h * 4) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe some kind of BB:getRect(angle)?
koreader/koreader-base#626 This commit uses a viewport to draw only a subset of the blitbuffer onto the rectangle to be updated in the SDL texture. Without this, there are cases where a full screen (or at least bigger) refresh is required that will not be obvious without first testing on a real device. See koreader#3804 Also fixes `EMULATE_READER_FLASH`, which was accidentally broken in koreader/koreader-base@981bd40 Also includes: [fix] SDL2: apply night mode on window resize (koreader/koreader-base#627)
…3812) koreader/koreader-base#626 This commit uses a viewport to draw only a subset of the blitbuffer onto the rectangle to be updated in the SDL texture. Without this, there are cases where a full screen (or at least bigger) refresh is required that will not be obvious without first testing on a real device. See #3804 Also fixes `EMULATE_READER_FLASH`, which was accidentally broken in koreader/koreader-base@981bd40 Also includes: [fix] SDL2: apply night mode on window resize (koreader/koreader-base#627)
Embarrassingly, I recently introduced two (!) regressions in rotation handling. 1. The new blitbuffer created when resizing didn't take rotation into account. Cf. koreader#614 2. The feature to emulate E Ink refresh didn't properly distinguish between BB rectangles and "physical" SDL rectangles. Cf. koreader#626 Reported by @poire-z in koreader/koreader#3812 (comment)
Embarrassingly, I recently introduced two (!) regressions in rotation handling. 1. The new blitbuffer created when resizing didn't take rotation into account. Cf. koreader#614 2. The feature to emulate E Ink refresh didn't properly distinguish between BB rectangles and "physical" SDL rectangles. Cf. koreader#626 Reported by @poire-z in koreader/koreader#3812 (comment)
Embarrassingly, I recently introduced two (!) regressions in rotation handling. 1. The new blitbuffer created when resizing didn't take rotation into account. Cf. #614 2. The feature to emulate E Ink refresh didn't properly distinguish between BB rectangles and "physical" SDL rectangles. Cf. #626 Reported by @poire-z in koreader/koreader#3812 (comment)
This commit first renders the full updated blitbuffer to a temporary texture.
Subsequently it renders the updated rectangle from the temporary texture onto
the final texture, which has up to that point retained all of the old pixel
info. That final texture, of which only the one rectangular area was updated,
is then rendered to the window.
Without this, there are cases where a full screen (or at least bigger) refresh
is required that will not be obvious without first testing on a real device.
See koreader/koreader#3804
Also fixes
EMULATE_READER_FLASH
, which was accidentally broken in 981bd40