1 of 28

History of the World�of Chrome Graphics

PART I

A super biased, compositor-centric

retrospective from enne@

2 of 28

Goals of this talk

  • Survey of graphics features across time
  • Understand Chesterton’s fences
  • Learn important Chrome GPU facts like “ugh gosh why is everything named Impl” and “why are we stuck with 256x256 tiles??”

3 of 28

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)

4 of 28

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

5 of 28

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:

  • All renderer content needs to be drawn with GPU
  • Overlapping content needs to be detected (thus RenderLayerCompositor)
  • OpenGL needs to be executed safely (thus GPU process)
  • OpenGL needs to get to GPU process (thus command buffer)
  • OpenGL is slow on Windows (hence ANGLE)

6 of 28

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.

7 of 28

Other accelerated compositing reasons

WebGL (2009)

Expose OpenGL to Javascript.

Swiftshader for blacklisted cards.

o3d successor.

Video (2010)

Previous video decode all software.

Pink video bug: https://crbug.com/57741

Canvas (2010)

Implementation initially in Blink.

Eventually switched to Skia and Ganesh.

Small canvas optimizations.

8 of 28

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

9 of 28

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.

10 of 28

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.�

11 of 28

The awkward dance of early compositor thread implementations

12 of 28

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;

}

}

13 of 28

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

14 of 28

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).

15 of 28

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

16 of 28

Ü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”.

17 of 28

Aura (2011-2013)

aka “views compositor”

18 of 28

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

19 of 28

Force compositing mode (2012-2014)

Compositor still has three modes:

  1. Legacy software (remember that diagram, many slides ago? Still there!)
  2. Hardware compositing (using gl for final draw)
  3. Software compositing (still have layers, but using SoftwareRenderer)

This sounds simple, but took a surprising amount of calendar time to roll out.

20 of 28

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

21 of 28

Impl-side painting (2012-2015)

22 of 28

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

23 of 28

Surfaces (2014)

Browser compositor

Renderer compositor

OOPIF compositor

Display compositor

Renderer compositor

OOPIF compositor

Browser compositor

24 of 28

Ganesh Rasterization (2013-2017?)

Ganesh has been used for a long time in Chrome for various things:

  • accelerated canvas
  • composited filters
  • main thread ganesh rasterization, pre compositor thread (!!!)

25 of 28

Synchronous Ganesh Raster (v1)

Impl Thread

Commit

PrepareTiles

Raster

NotifyReadyToActivate

Activate

BeginImplFrameDeadline

DrawAndSwap

Renderer Thread

BeginImplFrame

BeginMainFrame

Commit

diagram by vmiura@

26 of 28

Threaded Ganesh Raster (v2)

Worker Thread

Impl Thread

Commit

PrepareTiles

NotifyReadyToActivate

Activate

BeginImplFrameDeadline

DrawAndSwap

BeginImplFrame

Draw

TaskGraphRunner

RasterTask

RasterTask

...

diagram by vmiura@

27 of 28

THE END

(for now)

Other things currently in flight:

  • MUS
  • slimming paint v2, v3, v4
  • color correctness
  • custom display lists
  • image checkering
  • WebGL next
  • cc::SkiaRenderer
  • Vulkan
  • VR
  • &c &c &c

28 of 28

Conclusions

  1. We are always already working on accelerated path rendering.
  2. Pick your numerical constants well the first time.
  3. Major graphics features take a hella long time to ship everywhere.
  4. Chrome graphics makes terrible cases ok and great cases...also just ok.
  5. Everything starts out simple but is often complicated for a reason. :C