Unreviewed, roll out http://trac.webkit.org/changeset/187972.
[WebKit-https.git] / Source / WebKit2 / Shared / CoordinatedGraphics / CoordinatedGraphicsScene.cpp
1 /*
2     Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies)
3     Copyright (C) 2012 Company 100, Inc.
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Library General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Library General Public License for more details.
14
15     You should have received a copy of the GNU Library General Public License
16     along with this library; see the file COPYING.LIB.  If not, write to
17     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18     Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22
23 #if USE(COORDINATED_GRAPHICS)
24 #include "CoordinatedGraphicsScene.h"
25
26 #include "CoordinatedBackingStore.h"
27 #include <WebCore/TextureMapper.h>
28 #include <WebCore/TextureMapperBackingStore.h>
29 #include <WebCore/TextureMapperGL.h>
30 #include <WebCore/TextureMapperLayer.h>
31 #include <wtf/Atomics.h>
32 #include <wtf/MainThread.h>
33
34 using namespace WebCore;
35
36 namespace WebKit {
37
38 void CoordinatedGraphicsScene::dispatchOnMainThread(std::function<void()> function)
39 {
40     if (isMainThread())
41         function();
42     else
43         callOnMainThread(WTF::move(function));
44 }
45
46 void CoordinatedGraphicsScene::dispatchOnClientRunLoop(std::function<void()> function)
47 {
48     if (&m_clientRunLoop == &RunLoop::current())
49         function();
50     else
51         m_clientRunLoop.dispatch(WTF::move(function));
52 }
53
54 static bool layerShouldHaveBackingStore(TextureMapperLayer* layer)
55 {
56     return layer->drawsContent() && layer->contentsAreVisible() && !layer->size().isEmpty();
57 }
58
59 CoordinatedGraphicsScene::CoordinatedGraphicsScene(CoordinatedGraphicsSceneClient* client)
60     : m_client(client)
61     , m_isActive(false)
62     , m_rootLayerID(InvalidCoordinatedLayerID)
63     , m_viewBackgroundColor(Color::white)
64     , m_clientRunLoop(RunLoop::current())
65 {
66 }
67
68 CoordinatedGraphicsScene::~CoordinatedGraphicsScene()
69 {
70 }
71
72 void CoordinatedGraphicsScene::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect, const Color& backgroundColor, bool drawsBackground, const FloatPoint& contentPosition, TextureMapper::PaintFlags PaintFlags)
73 {
74     if (!m_textureMapper) {
75         m_textureMapper = TextureMapper::create();
76         static_cast<TextureMapperGL*>(m_textureMapper.get())->setEnableEdgeDistanceAntialiasing(true);
77     }
78
79     syncRemoteContent();
80
81     adjustPositionForFixedLayers(contentPosition);
82     TextureMapperLayer* currentRootLayer = rootLayer();
83     if (!currentRootLayer)
84         return;
85
86     currentRootLayer->setTextureMapper(m_textureMapper.get());
87     currentRootLayer->applyAnimationsRecursively();
88     m_textureMapper->beginPainting(PaintFlags);
89     m_textureMapper->beginClip(TransformationMatrix(), clipRect);
90
91     if (drawsBackground) {
92         RGBA32 rgba = makeRGBA32FromFloats(backgroundColor.red(),
93             backgroundColor.green(), backgroundColor.blue(),
94             backgroundColor.alpha() * opacity);
95         m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), Color(rgba));
96     } else {
97         GraphicsContext3D* context = static_cast<TextureMapperGL*>(m_textureMapper.get())->graphicsContext3D();
98         context->clearColor(m_viewBackgroundColor.red() / 255.0f, m_viewBackgroundColor.green() / 255.0f, m_viewBackgroundColor.blue() / 255.0f, m_viewBackgroundColor.alpha() / 255.0f);
99         context->clear(GraphicsContext3D::COLOR_BUFFER_BIT);
100     }
101
102     if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != matrix) {
103         currentRootLayer->setOpacity(opacity);
104         currentRootLayer->setTransform(matrix);
105     }
106
107     currentRootLayer->paint();
108     m_fpsCounter.updateFPSAndDisplay(m_textureMapper.get(), clipRect.location(), matrix);
109     m_textureMapper->endClip();
110     m_textureMapper->endPainting();
111
112     if (currentRootLayer->descendantsOrSelfHaveRunningAnimations()) {
113         RefPtr<CoordinatedGraphicsScene> protector(this);
114         dispatchOnClientRunLoop([=] {
115             protector->updateViewport();
116         });
117     }
118 }
119
120 void CoordinatedGraphicsScene::paintToGraphicsContext(PlatformGraphicsContext* platformContext, const Color& backgroundColor, bool drawsBackground)
121 {
122     if (!m_textureMapper)
123         m_textureMapper = TextureMapper::create();
124     syncRemoteContent();
125     TextureMapperLayer* layer = rootLayer();
126
127     if (!layer)
128         return;
129
130     GraphicsContext graphicsContext(platformContext);
131     m_textureMapper->setGraphicsContext(&graphicsContext);
132     m_textureMapper->beginPainting();
133
134     IntRect clipRect = graphicsContext.clipBounds();
135     if (drawsBackground)
136         m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), backgroundColor);
137     else
138         m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), m_viewBackgroundColor);
139
140     layer->paint();
141     m_fpsCounter.updateFPSAndDisplay(m_textureMapper.get(), clipRect.location());
142     m_textureMapper->endPainting();
143     m_textureMapper->setGraphicsContext(0);
144 }
145
146 void CoordinatedGraphicsScene::updateViewport()
147 {
148     ASSERT(&m_clientRunLoop == &RunLoop::current());
149     if (m_client)
150         m_client->updateViewport();
151 }
152
153 void CoordinatedGraphicsScene::adjustPositionForFixedLayers(const FloatPoint& contentPosition)
154 {
155     if (m_fixedLayers.isEmpty())
156         return;
157
158     // Fixed layer positions are updated by the web process when we update the visible contents rect / scroll position.
159     // If we want those layers to follow accurately the viewport when we move between the web process updates, we have to offset
160     // them by the delta between the current position and the position of the viewport used for the last layout.
161     FloatSize delta = contentPosition - m_renderedContentsScrollPosition;
162
163     for (auto& fixedLayer : m_fixedLayers.values())
164         fixedLayer->setScrollPositionDeltaIfNeeded(delta);
165 }
166
167 #if USE(GRAPHICS_SURFACE)
168 void CoordinatedGraphicsScene::createPlatformLayerIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
169 {
170     if (!state.platformLayerToken.isValid())
171         return;
172
173     RefPtr<TextureMapperSurfaceBackingStore> platformLayerBackingStore(TextureMapperSurfaceBackingStore::create());
174     m_surfaceBackingStores.set(layer, platformLayerBackingStore);
175     platformLayerBackingStore->setGraphicsSurface(GraphicsSurface::create(state.platformLayerSize, state.platformLayerSurfaceFlags, state.platformLayerToken));
176     layer->setContentsLayer(platformLayerBackingStore.get());
177 }
178
179 void CoordinatedGraphicsScene::syncPlatformLayerIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
180 {
181     ASSERT(m_textureMapper);
182
183     if (state.platformLayerChanged) {
184         destroyPlatformLayerIfNeeded(layer, state);
185         createPlatformLayerIfNeeded(layer, state);
186     }
187
188     if (state.platformLayerShouldSwapBuffers) {
189         ASSERT(m_surfaceBackingStores.contains(layer));
190         SurfaceBackingStoreMap::iterator it = m_surfaceBackingStores.find(layer);
191         RefPtr<TextureMapperSurfaceBackingStore> platformLayerBackingStore = it->value;
192         platformLayerBackingStore->swapBuffersIfNeeded(state.platformLayerFrontBuffer);
193     }
194 }
195
196 void CoordinatedGraphicsScene::destroyPlatformLayerIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
197 {
198     if (state.platformLayerToken.isValid())
199         return;
200
201     m_surfaceBackingStores.remove(layer);
202     layer->setContentsLayer(0);
203 }
204 #endif
205
206 void CoordinatedGraphicsScene::setLayerRepaintCountIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
207 {
208     if (!layer->isShowingRepaintCounter() || !state.repaintCountChanged)
209         return;
210
211     layer->setRepaintCount(state.repaintCount);
212 }
213
214 void CoordinatedGraphicsScene::setLayerChildrenIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
215 {
216     if (!state.childrenChanged)
217         return;
218
219     Vector<TextureMapperLayer*> children;
220
221     for (auto& child : state.children) {
222         TextureMapperLayer* childLayer = layerByID(child);
223         children.append(childLayer);
224     }
225     layer->setChildren(children);
226 }
227
228 void CoordinatedGraphicsScene::setLayerFiltersIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
229 {
230     if (!state.filtersChanged)
231         return;
232
233     layer->setFilters(state.filters);
234 }
235
236 void CoordinatedGraphicsScene::setLayerState(CoordinatedLayerID id, const CoordinatedGraphicsLayerState& layerState)
237 {
238     ASSERT(m_rootLayerID != InvalidCoordinatedLayerID);
239     TextureMapperLayer* layer = layerByID(id);
240
241     if (layerState.positionChanged)
242         layer->setPosition(layerState.pos);
243
244     if (layerState.anchorPointChanged)
245         layer->setAnchorPoint(layerState.anchorPoint);
246
247     if (layerState.sizeChanged)
248         layer->setSize(layerState.size);
249
250     if (layerState.transformChanged)
251         layer->setTransform(layerState.transform);
252
253     if (layerState.childrenTransformChanged)
254         layer->setChildrenTransform(layerState.childrenTransform);
255
256     if (layerState.contentsRectChanged)
257         layer->setContentsRect(layerState.contentsRect);
258
259     if (layerState.contentsTilingChanged) {
260         layer->setContentsTilePhase(layerState.contentsTilePhase);
261         layer->setContentsTileSize(layerState.contentsTileSize);
262     }
263
264     if (layerState.opacityChanged)
265         layer->setOpacity(layerState.opacity);
266
267     if (layerState.solidColorChanged)
268         layer->setSolidColor(layerState.solidColor);
269
270     if (layerState.debugBorderColorChanged || layerState.debugBorderWidthChanged)
271         layer->setDebugVisuals(layerState.showDebugBorders, layerState.debugBorderColor, layerState.debugBorderWidth, layerState.showRepaintCounter);
272
273     if (layerState.replicaChanged)
274         layer->setReplicaLayer(getLayerByIDIfExists(layerState.replica));
275
276     if (layerState.maskChanged)
277         layer->setMaskLayer(getLayerByIDIfExists(layerState.mask));
278
279     if (layerState.imageChanged)
280         assignImageBackingToLayer(layer, layerState.imageID);
281
282     if (layerState.flagsChanged) {
283         layer->setContentsOpaque(layerState.contentsOpaque);
284         layer->setDrawsContent(layerState.drawsContent);
285         layer->setContentsVisible(layerState.contentsVisible);
286         layer->setBackfaceVisibility(layerState.backfaceVisible);
287
288         // Never clip the root layer.
289         layer->setMasksToBounds(id == m_rootLayerID ? false : layerState.masksToBounds);
290         layer->setPreserves3D(layerState.preserves3D);
291
292         bool fixedToViewportChanged = layer->fixedToViewport() != layerState.fixedToViewport;
293         layer->setFixedToViewport(layerState.fixedToViewport);
294         if (fixedToViewportChanged) {
295             if (layerState.fixedToViewport)
296                 m_fixedLayers.add(id, layer);
297             else
298                 m_fixedLayers.remove(id);
299         }
300
301         layer->setIsScrollable(layerState.isScrollable);
302     }
303
304     if (layerState.committedScrollOffsetChanged)
305         layer->didCommitScrollOffset(layerState.committedScrollOffset);
306
307     prepareContentBackingStore(layer);
308
309     // Apply Operations.
310     setLayerChildrenIfNeeded(layer, layerState);
311     createTilesIfNeeded(layer, layerState);
312     removeTilesIfNeeded(layer, layerState);
313     updateTilesIfNeeded(layer, layerState);
314     setLayerFiltersIfNeeded(layer, layerState);
315     setLayerAnimationsIfNeeded(layer, layerState);
316 #if USE(GRAPHICS_SURFACE)
317     syncPlatformLayerIfNeeded(layer, layerState);
318 #endif
319     setLayerRepaintCountIfNeeded(layer, layerState);
320 }
321
322 TextureMapperLayer* CoordinatedGraphicsScene::getLayerByIDIfExists(CoordinatedLayerID id)
323 {
324     return (id != InvalidCoordinatedLayerID) ? layerByID(id) : 0;
325 }
326
327 void CoordinatedGraphicsScene::createLayers(const Vector<CoordinatedLayerID>& layerIDs)
328 {
329     for (auto& layerID : layerIDs)
330         createLayer(layerID);
331 }
332
333 void CoordinatedGraphicsScene::createLayer(CoordinatedLayerID id)
334 {
335     std::unique_ptr<TextureMapperLayer> newLayer = std::make_unique<TextureMapperLayer>();
336     newLayer->setID(id);
337     newLayer->setScrollClient(this);
338     m_layers.add(id, WTF::move(newLayer));
339 }
340
341 void CoordinatedGraphicsScene::deleteLayers(const Vector<CoordinatedLayerID>& layerIDs)
342 {
343     for (auto& layerID : layerIDs)
344         deleteLayer(layerID);
345 }
346
347 void CoordinatedGraphicsScene::deleteLayer(CoordinatedLayerID layerID)
348 {
349     std::unique_ptr<TextureMapperLayer> layer = m_layers.take(layerID);
350     ASSERT(layer);
351
352     m_backingStores.remove(layer.get());
353     m_fixedLayers.remove(layerID);
354 #if USE(GRAPHICS_SURFACE)
355     m_surfaceBackingStores.remove(layer.get());
356 #endif
357 }
358
359 void CoordinatedGraphicsScene::setRootLayerID(CoordinatedLayerID layerID)
360 {
361     ASSERT(layerID != InvalidCoordinatedLayerID);
362     ASSERT(m_rootLayerID == InvalidCoordinatedLayerID);
363
364     m_rootLayerID = layerID;
365
366     TextureMapperLayer* layer = layerByID(layerID);
367     ASSERT(m_rootLayer->children().isEmpty());
368     m_rootLayer->addChild(layer);
369 }
370
371 void CoordinatedGraphicsScene::prepareContentBackingStore(TextureMapperLayer* layer)
372 {
373     if (!layerShouldHaveBackingStore(layer)) {
374         removeBackingStoreIfNeeded(layer);
375         return;
376     }
377
378     createBackingStoreIfNeeded(layer);
379     resetBackingStoreSizeToLayerSize(layer);
380 }
381
382 void CoordinatedGraphicsScene::createBackingStoreIfNeeded(TextureMapperLayer* layer)
383 {
384     if (m_backingStores.contains(layer))
385         return;
386
387     RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create());
388     m_backingStores.add(layer, backingStore);
389     layer->setBackingStore(backingStore);
390 }
391
392 void CoordinatedGraphicsScene::removeBackingStoreIfNeeded(TextureMapperLayer* layer)
393 {
394     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.take(layer);
395     if (!backingStore)
396         return;
397
398     layer->setBackingStore(0);
399 }
400
401 void CoordinatedGraphicsScene::resetBackingStoreSizeToLayerSize(TextureMapperLayer* layer)
402 {
403     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
404     ASSERT(backingStore);
405     backingStore->setSize(layer->size());
406     m_backingStoresWithPendingBuffers.add(backingStore);
407 }
408
409 void CoordinatedGraphicsScene::createTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
410 {
411     if (state.tilesToCreate.isEmpty())
412         return;
413
414     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
415     ASSERT(backingStore);
416
417     for (auto& tile : state.tilesToCreate)
418         backingStore->createTile(tile.tileID, tile.scale);
419 }
420
421 void CoordinatedGraphicsScene::removeTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
422 {
423     if (state.tilesToRemove.isEmpty())
424         return;
425
426     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
427     if (!backingStore)
428         return;
429
430     for (auto& tile : state.tilesToRemove)
431         backingStore->removeTile(tile);
432
433     m_backingStoresWithPendingBuffers.add(backingStore);
434 }
435
436 void CoordinatedGraphicsScene::updateTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
437 {
438     if (state.tilesToUpdate.isEmpty())
439         return;
440
441     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
442     ASSERT(backingStore);
443
444     for (auto& tile : state.tilesToUpdate) {
445         const SurfaceUpdateInfo& surfaceUpdateInfo = tile.updateInfo;
446
447         SurfaceMap::iterator surfaceIt = m_surfaces.find(surfaceUpdateInfo.atlasID);
448         ASSERT(surfaceIt != m_surfaces.end());
449
450         backingStore->updateTile(tile.tileID, surfaceUpdateInfo.updateRect, tile.tileRect, surfaceIt->value, surfaceUpdateInfo.surfaceOffset);
451         m_backingStoresWithPendingBuffers.add(backingStore);
452     }
453 }
454
455 void CoordinatedGraphicsScene::syncUpdateAtlases(const CoordinatedGraphicsState& state)
456 {
457     for (auto& atlas : state.updateAtlasesToCreate)
458         createUpdateAtlas(atlas.first, atlas.second);
459
460     for (auto& atlas : state.updateAtlasesToRemove)
461         removeUpdateAtlas(atlas);
462 }
463
464 void CoordinatedGraphicsScene::createUpdateAtlas(uint32_t atlasID, PassRefPtr<CoordinatedSurface> surface)
465 {
466     ASSERT(!m_surfaces.contains(atlasID));
467     m_surfaces.add(atlasID, surface);
468 }
469
470 void CoordinatedGraphicsScene::removeUpdateAtlas(uint32_t atlasID)
471 {
472     ASSERT(m_surfaces.contains(atlasID));
473     m_surfaces.remove(atlasID);
474 }
475
476 void CoordinatedGraphicsScene::syncImageBackings(const CoordinatedGraphicsState& state)
477 {
478     for (auto& image : state.imagesToRemove)
479         removeImageBacking(image);
480
481     for (auto& image : state.imagesToCreate)
482         createImageBacking(image);
483
484     for (auto& image : state.imagesToUpdate)
485         updateImageBacking(image.first, image.second);
486
487     for (auto& image : state.imagesToClear)
488         clearImageBackingContents(image);
489 }
490
491 void CoordinatedGraphicsScene::createImageBacking(CoordinatedImageBackingID imageID)
492 {
493     ASSERT(!m_imageBackings.contains(imageID));
494     RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create());
495     m_imageBackings.add(imageID, backingStore.release());
496 }
497
498 void CoordinatedGraphicsScene::updateImageBacking(CoordinatedImageBackingID imageID, PassRefPtr<CoordinatedSurface> surface)
499 {
500     ASSERT(m_imageBackings.contains(imageID));
501     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
502     RefPtr<CoordinatedBackingStore> backingStore = it->value;
503
504     // CoordinatedImageBacking is realized to CoordinatedBackingStore with only one tile in UI Process.
505     backingStore->createTile(1 /* id */, 1 /* scale */);
506     IntRect rect(IntPoint::zero(), surface->size());
507     // See CoordinatedGraphicsLayer::shouldDirectlyCompositeImage()
508     ASSERT(2000 >= std::max(rect.width(), rect.height()));
509     backingStore->setSize(rect.size());
510     backingStore->updateTile(1 /* id */, rect, rect, surface, rect.location());
511
512     m_backingStoresWithPendingBuffers.add(backingStore);
513 }
514
515 void CoordinatedGraphicsScene::clearImageBackingContents(CoordinatedImageBackingID imageID)
516 {
517     ASSERT(m_imageBackings.contains(imageID));
518     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
519     RefPtr<CoordinatedBackingStore> backingStore = it->value;
520     backingStore->removeAllTiles();
521     m_backingStoresWithPendingBuffers.add(backingStore);
522 }
523
524 void CoordinatedGraphicsScene::removeImageBacking(CoordinatedImageBackingID imageID)
525 {
526     ASSERT(m_imageBackings.contains(imageID));
527
528     // We don't want TextureMapperLayer refers a dangling pointer.
529     m_releasedImageBackings.append(m_imageBackings.take(imageID));
530 }
531
532 void CoordinatedGraphicsScene::assignImageBackingToLayer(TextureMapperLayer* layer, CoordinatedImageBackingID imageID)
533 {
534 #if USE(GRAPHICS_SURFACE)
535     if (m_surfaceBackingStores.contains(layer))
536         return;
537 #endif
538
539     if (imageID == InvalidCoordinatedImageBackingID) {
540         layer->setContentsLayer(0);
541         return;
542     }
543
544     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
545     ASSERT(it != m_imageBackings.end());
546     layer->setContentsLayer(it->value.get());
547 }
548
549 void CoordinatedGraphicsScene::removeReleasedImageBackingsIfNeeded()
550 {
551     m_releasedImageBackings.clear();
552 }
553
554 void CoordinatedGraphicsScene::commitPendingBackingStoreOperations()
555 {
556     for (auto& backingStore : m_backingStoresWithPendingBuffers)
557         backingStore->commitTileOperations(m_textureMapper.get());
558
559     m_backingStoresWithPendingBuffers.clear();
560 }
561
562 void CoordinatedGraphicsScene::commitSceneState(const CoordinatedGraphicsState& state)
563 {
564     m_renderedContentsScrollPosition = state.scrollPosition;
565
566     createLayers(state.layersToCreate);
567     deleteLayers(state.layersToRemove);
568
569     if (state.rootCompositingLayer != m_rootLayerID)
570         setRootLayerID(state.rootCompositingLayer);
571
572     syncImageBackings(state);
573     syncUpdateAtlases(state);
574
575     for (auto& layer : state.layersToUpdate)
576         setLayerState(layer.first, layer.second);
577
578     commitPendingBackingStoreOperations();
579     removeReleasedImageBackingsIfNeeded();
580
581     // The pending tiles state is on its way for the screen, tell the web process to render the next one.
582     RefPtr<CoordinatedGraphicsScene> protector(this);
583     dispatchOnMainThread([=] {
584         protector->renderNextFrame();
585     });
586 }
587
588 void CoordinatedGraphicsScene::renderNextFrame()
589 {
590     if (m_client)
591         m_client->renderNextFrame();
592 }
593
594 void CoordinatedGraphicsScene::ensureRootLayer()
595 {
596     if (m_rootLayer)
597         return;
598
599     m_rootLayer = std::make_unique<TextureMapperLayer>();
600     m_rootLayer->setMasksToBounds(false);
601     m_rootLayer->setDrawsContent(false);
602     m_rootLayer->setAnchorPoint(FloatPoint3D(0, 0, 0));
603
604     // The root layer should not have zero size, or it would be optimized out.
605     m_rootLayer->setSize(FloatSize(1.0, 1.0));
606
607     ASSERT(m_textureMapper);
608     m_rootLayer->setTextureMapper(m_textureMapper.get());
609 }
610
611 void CoordinatedGraphicsScene::syncRemoteContent()
612 {
613     // We enqueue messages and execute them during paint, as they require an active GL context.
614     ensureRootLayer();
615
616     Vector<std::function<void()>> renderQueue;
617     bool calledOnMainThread = WTF::isMainThread();
618     if (!calledOnMainThread)
619         m_renderQueueMutex.lock();
620     renderQueue = WTF::move(m_renderQueue);
621     if (!calledOnMainThread)
622         m_renderQueueMutex.unlock();
623
624     for (auto& function : renderQueue)
625         function();
626 }
627
628 void CoordinatedGraphicsScene::purgeGLResources()
629 {
630     m_imageBackings.clear();
631     m_releasedImageBackings.clear();
632 #if USE(GRAPHICS_SURFACE)
633     m_surfaceBackingStores.clear();
634 #endif
635     m_surfaces.clear();
636
637     m_rootLayer = nullptr;
638     m_rootLayerID = InvalidCoordinatedLayerID;
639     m_layers.clear();
640     m_fixedLayers.clear();
641     m_textureMapper = nullptr;
642     m_backingStores.clear();
643     m_backingStoresWithPendingBuffers.clear();
644
645     setActive(false);
646
647     RefPtr<CoordinatedGraphicsScene> protector(this);
648     dispatchOnMainThread([=] {
649         protector->purgeBackingStores();
650     });
651 }
652
653 void CoordinatedGraphicsScene::dispatchCommitScrollOffset(uint32_t layerID, const IntSize& offset)
654 {
655     m_client->commitScrollOffset(layerID, offset);
656 }
657
658 void CoordinatedGraphicsScene::commitScrollOffset(uint32_t layerID, const IntSize& offset)
659 {
660     RefPtr<CoordinatedGraphicsScene> protector(this);
661     dispatchOnMainThread([=] {
662         protector->dispatchCommitScrollOffset(layerID, offset);
663     });
664 }
665
666 void CoordinatedGraphicsScene::purgeBackingStores()
667 {
668     if (m_client)
669         m_client->purgeBackingStores();
670 }
671
672 void CoordinatedGraphicsScene::setLayerAnimationsIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
673 {
674     if (!state.animationsChanged)
675         return;
676
677     layer->setAnimations(state.animations);
678 }
679
680 void CoordinatedGraphicsScene::detach()
681 {
682     ASSERT(isMainThread());
683     m_renderQueue.clear();
684     m_client = 0;
685 }
686
687 void CoordinatedGraphicsScene::appendUpdate(std::function<void()> function)
688 {
689     if (!m_isActive)
690         return;
691
692     ASSERT(isMainThread());
693     MutexLocker locker(m_renderQueueMutex);
694     m_renderQueue.append(WTF::move(function));
695 }
696
697 void CoordinatedGraphicsScene::setActive(bool active)
698 {
699     if (m_isActive == active)
700         return;
701
702     // Have to clear render queue in both cases.
703     // If there are some updates in queue during activation then those updates are from previous instance of paint node
704     // and cannot be applied to the newly created instance.
705     m_renderQueue.clear();
706     m_isActive = active;
707     if (m_isActive) {
708         RefPtr<CoordinatedGraphicsScene> protector(this);
709         dispatchOnMainThread([=] {
710             protector->renderNextFrame();
711         });
712     }
713 }
714
715 TextureMapperLayer* CoordinatedGraphicsScene::findScrollableContentsLayerAt(const FloatPoint& point)
716 {
717     return rootLayer() ? rootLayer()->findScrollableContentsLayerAt(point) : 0;
718 }
719
720 } // namespace WebKit
721
722 #endif // USE(COORDINATED_GRAPHICS)