History of the World�of Chrome Graphics
PART I
A super biased, compositor-centric
retrospective from enne@
Goals of this talk
Ancient History (2008)
No GPU process: only browser and renderer processes.
No compositor. No shaders. No command buffer.
Everything software rastered on demand.
(Windows only)
Historical diagram outlining how ancient Chromites got content on screen
RenderWidget’s
PaintAggregator
(1) Invalidate
(2) DoDeferredUpdate
(3) Aggregate invalidations
(4) Raster aggregate areas via Blink paint
To bitmaps
(5) Send bitmaps to Browser via transport dibs
WebKit
Renderer process
Browser process
HWND
Shared memory
Accelerated Compositing (2009)
3D CSS is the first trigger to go into “accelerated compositing” mode.
Once any renderer content is drawn on screen with the GPU then suddenly:
GPU process mode switch
GPU process spin-up was optional and on demand.
Browser would create an HWND for the accelerated content that was a child of the non-accelerated content so that the two modes could coexist.
Entire accelerated path could turn off whenever, even mid-paint.
Other accelerated compositing reasons
WebGL (2009)
Expose OpenGL to Javascript.
Swiftshader for blacklisted cards.
o3d successor.
Canvas (2010)
Implementation initially in Blink.
Eventually switched to Skia and Ganesh.
Small canvas optimizations.
Scrolling is slow (part 1, tiling)
Problem: Scrolling the root layer used shift and blit. Lots of raster work, even when nothing changed but scroll offset.
Solution: tile the root layer to re-use raster work.
Why 256x256 tiles? http://bugs.webkit.org/show_bug.cgi?id=49947#c6
Scrolling is slow (part 2, threading, 2011)
Problem: Scrolling is still slow. Problem viewed as WebKit main thread jank.
Solution: Add a more responsive thread to handle input.
Infamous “impl” suffix, aka blame nduca@
See: https://bugs.webkit.org/show_bug.cgi?id=55013#c5
James Robinson 2011-02-24 11:50:23 PST
(In reply to comment #4)��> Is there any reason you call the new class CCLayerImpl instead of plain CCLayer ?�> ��Nat pointed out that it makes more sense to name the interface we exposed to the rest of WebKit CCLayer and have CCLayerImpl be the compositor's internal implementation. IOW GraphicsLayerChromium will have a set of CCLayers and set properties on them, etc, and only the compositor internals will ever have knowledge of CCLayerImpl.�
The awkward dance of early compositor thread implementations
Ancient scheduler code that somehow fits entirely on one slide
CCSchedulerStateMachine::Action CCSchedulerStateMachine::nextAction(bool insideVSyncTick) const
{
switch (m_commitState) {
case COMMIT_STATE_IDLE:
if (m_needsRedraw && insideVSyncTick)
return ACTION_DRAW;
if (m_needsCommit)
return ACTION_BEGIN_FRAME;
return ACTION_NONE;
case COMMIT_STATE_FRAME_IN_PROGRESS:
if (m_needsRedraw && insideVSyncTick)
return ACTION_DRAW;
return ACTION_NONE;
case COMMIT_STATE_UPDATING_RESOURCES:
if (m_needsRedraw && insideVSyncTick)
return ACTION_DRAW;
if (!m_updatedThisFrame)
return ACTION_UPDATE_MORE_RESOURCES;
return ACTION_NONE;
case COMMIT_STATE_READY_TO_COMMIT:
return ACTION_COMMIT;
}
}
void CCSchedulerStateMachine::updateState(Action action)
{
switch (action) {
case ACTION_NONE:
return;
case ACTION_BEGIN_FRAME:
m_commitState = COMMIT_STATE_FRAME_IN_PROGRESS;
m_needsCommit = false;
return;
case ACTION_UPDATE_MORE_RESOURCES:
m_updatedThisFrame = true;
return;
case ACTION_COMMIT:
m_commitState = COMMIT_STATE_IDLE;
m_needsRedraw = true;
return;
case ACTION_DRAW:
m_updatedThisFrame = false;
m_needsRedraw = false;
return;
}
}
Compositor thread timeline (2011-2015)
2013
2012
2011
2014
2015
Finally shipped on Mac
Try to ship on Mac
Ship on Windows
Browser compositor briefly is threaded
Make browser never threaded
Start! 🏁
Scrollbars update on thread
Universal accelerated scrolling
Start work on non-root accelerated scrolling
Quads (early 2012)
Problem: Drawing code littered through layer classes. Hard to add new drawing modes, like software raster.
Solution: Draw into an abstraction (quads and shared quad states).
Feature grab bag interlude~ 🎶
Edge antialiasing (2011): extend quads in screen space for soft edges
Occlusion tracker (2012): only at draw time, opaqueness hard to detect
Accelerated Filters (2012): use Ganesh in cc::GLRenderer for filter chains
Übercompositor (2012-2013)
Problem: Renderer draws into an gl texture. Compositing that texture with the rest of the ui is an unneeded copy. ChromeOS devices often bandwidth bound.
Solution: Send quads to a browser compositor; composite “once”.
Aura (2011-2013)
aka “views compositor”
Project GTFO (2011-2013)
Context: remember that all of this work in the compositor is being done inside of third_party/WebKit/Source/WebCore/platform/graphics/chromium
Problems:�(1) Aura wants to back views with cc::Layers�(2) WebKit reviewer policy super stringent
Solution: move the compositor out of Blink via abstractions
Force compositing mode (2012-2014)
Compositor still has three modes:
This sounds simple, but took a surprising amount of calendar time to roll out.
Impl-side painting (2012-2015)
Problem: Scrolling is now smooth, but quickly run out of prepainted content. Scrolling checkerboards somehow not super exciting to users.
Solution: Move rasterization from main thread to the compositor thread
Additional problems: image decodes, assumptions about scales at record time
Impl-side painting (2012-2015)
Layer Squashing (2013-2014)
Problem: Layers are expensive. Many sites create too many layers!
Solution: Squash more PaintLayers together into a single composited layer.
1
2
3
A
Animated
1
1
2
2
3
3
root
R
PaintLayer tree
before squashing
A
R
PaintLayer tree
after squashing
Surfaces (2014)
Browser compositor
Renderer compositor
OOPIF compositor
Display compositor
Renderer compositor
OOPIF compositor
Browser compositor
Ganesh Rasterization (2013-2017?)
Ganesh has been used for a long time in Chrome for various things:
Synchronous Ganesh Raster (v1)
Impl Thread
Commit
PrepareTiles
Raster
NotifyReadyToActivate
Activate
BeginImplFrameDeadline
DrawAndSwap
Renderer Thread
BeginImplFrame
BeginMainFrame
Commit
diagram by vmiura@
Threaded Ganesh Raster (v2)
Worker Thread
Impl Thread
Commit
PrepareTiles
NotifyReadyToActivate
Activate
BeginImplFrameDeadline
DrawAndSwap
BeginImplFrame
Draw
TaskGraphRunner
RasterTask
RasterTask
...
diagram by vmiura@
THE END
(for now)
Other things currently in flight:
Conclusions