Closed Bug 829752 Opened 7 years ago Closed 6 years ago

Make 2D Canvas faster on Android

Categories

(Core :: Canvas: 2D, defect)

All
Android
defect
Not set

Tracking

()

RESOLVED FIXED

People

(Reporter: blassey, Assigned: snorp)

References

(Depends on 1 open bug, Blocks 1 open bug)

Details

(Keywords: meta)

No description provided.
Depends on: 829747
I'm thinking we're comparing ourselves to Chrome on Android here (which handily beats us in a number of games I've tried) - so plan of action is to determine what operations, roughly, are slow, run profiles, and see what there is we can do to fix this.

Hopefully there are things we can do to improve performance without going the whole hog of implementing a GL-accelerated canvas. I would expect one thing, for example, would be to use a SurfaceTexture to avoid the texture upload cost (possibly?) - either way, let's see what the numbers are first.
Assignee: nobody → chrislord.net
Status: NEW → ASSIGNED
Async canvas updates will definitely improve performance, adding as a dependency.
Depends on: 829747
It's actually unlikely that it will; canvas 2d is single-buffered by design/spec (e.g. the preserveDrawingBuffer: true case in webgl).  We would either have to copy the contents to a second buffer to be able to send it over async, or need to block on compositing so we can keep reusing the same buffer.

As an aside, I'd really like to add preserveDrawingBuffer: false as an option to canvas, since most apps (especially games) will render the entire thing anyway.
(In reply to Vladimir Vukicevic [:vlad] [:vladv] from comment #4)
> It's actually unlikely that it will; canvas 2d is single-buffered by
> design/spec (e.g. the preserveDrawingBuffer: true case in webgl).  We would
> either have to copy the contents to a second buffer to be able to send it
> over async, or need to block on compositing so we can keep reusing the same
> buffer.
> 
> As an aside, I'd really like to add preserveDrawingBuffer: false as an
> option to canvas, since most apps (especially games) will render the entire
> thing anyway.

ah damn, my mistake then :/ If the swap has to be sync, could we speed this up using EGLImage and map the buffer to a texture? (snorp, is this possible?)
You mean without sending over the buffer contents over IPC?  Do we do that?
(In reply to Vladimir Vukicevic [:vlad] [:vladv] from comment #6)
> You mean without sending over the buffer contents over IPC?  Do we do that?

snorp's informed me that you can't preserve the buffer with EGLImage, so this idea is a non-starter :(
(In reply to Chris Lord [:cwiiis] from comment #7)
> (In reply to Vladimir Vukicevic [:vlad] [:vladv] from comment #6)
> > You mean without sending over the buffer contents over IPC?  Do we do that?
> 
> snorp's informed me that you can't preserve the buffer with EGLImage, so
> this idea is a non-starter :(

Oh, my bad, this was SurfaceTexture.

So my half-baked idea was that we'd map a buffer via gralloc, draw into that and use EGLImage to copy it to a texture on swap - I'm assuming that because the buffer is already in graphics memory, the copy should be quick (or it has some kind of copy-on-write facility?)
(In reply to Chris Lord [:cwiiis] from comment #8)
> (In reply to Chris Lord [:cwiiis] from comment #7)
> > (In reply to Vladimir Vukicevic [:vlad] [:vladv] from comment #6)
> > > You mean without sending over the buffer contents over IPC?  Do we do that?
> > 
> > snorp's informed me that you can't preserve the buffer with EGLImage, so
> > this idea is a non-starter :(
> 
> Oh, my bad, this was SurfaceTexture.
> 
> So my half-baked idea was that we'd map a buffer via gralloc, draw into that
> and use EGLImage to copy it to a texture on swap - I'm assuming that because
> the buffer is already in graphics memory, the copy should be quick (or it
> has some kind of copy-on-write facility?)

The main showstopper with anything here is that we can't reliably use GraphicBuffer on Android. Otherwise, something along those lines seems doable. With skia-gl we would get whatever magical improvements that gives us, but we could also use the streaming GL buffer stuff. We have to copy the framebuffers since preserveDrawing=true, but presumably doing this in GL is faster than memcpy()?
I wonder if we could async swap a locked read-only surface to the compositor similar to how we do in tiles. If the first drawing call to the canvas is a fillRect then we don't copy back from the read-only surface.
It should be no slower than a memcpy(), which is likely going to be better than lockstep sync with the compositor thread especially on multi-core devices.
Depends on: 843224
Assignee: chrislord.net → snorp
SkiaGL largely solved this issue, though work is of course still ongoing.
Status: ASSIGNED → RESOLVED
Closed: 6 years ago
Resolution: --- → FIXED
You need to log in before you can comment on or make changes to this bug.