0b217ec908b93e7d42dbc4d6d960e1fd31302678
[WebKit-https.git] / Source / WebCore / platform / graphics / texmap / coordinated / 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
25 #include "CoordinatedGraphicsScene.h"
26
27 #include "CoordinatedBackingStore.h"
28 #include "TextureMapper.h"
29 #include "TextureMapperBackingStore.h"
30 #include "TextureMapperGL.h"
31 #include "TextureMapperLayer.h"
32 #include <wtf/Atomics.h>
33 #include <wtf/MainThread.h>
34
35 namespace WebCore {
36
37 void CoordinatedGraphicsScene::dispatchOnMainThread(std::function<void()> function)
38 {
39     if (isMainThread())
40         function();
41     else
42         callOnMainThread(std::move(function));
43 }
44
45 static bool layerShouldHaveBackingStore(TextureMapperLayer* layer)
46 {
47     return layer->drawsContent() && layer->contentsAreVisible() && !layer->size().isEmpty();
48 }
49
50 CoordinatedGraphicsScene::CoordinatedGraphicsScene(CoordinatedGraphicsSceneClient* client)
51     : m_client(client)
52     , m_isActive(false)
53     , m_rootLayerID(InvalidCoordinatedLayerID)
54     , m_backgroundColor(Color::white)
55     , m_setDrawsBackground(false)
56 {
57     ASSERT(isMainThread());
58 }
59
60 CoordinatedGraphicsScene::~CoordinatedGraphicsScene()
61 {
62 }
63
64 void CoordinatedGraphicsScene::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect, TextureMapper::PaintFlags PaintFlags)
65 {
66     if (!m_textureMapper) {
67         m_textureMapper = TextureMapper::create(TextureMapper::OpenGLMode);
68         static_cast<TextureMapperGL*>(m_textureMapper.get())->setEnableEdgeDistanceAntialiasing(true);
69     }
70
71     ASSERT(m_textureMapper->accelerationMode() == TextureMapper::OpenGLMode);
72     syncRemoteContent();
73
74     adjustPositionForFixedLayers();
75     TextureMapperLayer* currentRootLayer = rootLayer();
76     if (!currentRootLayer)
77         return;
78
79     currentRootLayer->setTextureMapper(m_textureMapper.get());
80     currentRootLayer->applyAnimationsRecursively();
81     m_textureMapper->beginPainting(PaintFlags);
82     m_textureMapper->beginClip(TransformationMatrix(), clipRect);
83
84     if (m_setDrawsBackground) {
85         RGBA32 rgba = makeRGBA32FromFloats(m_backgroundColor.red(),
86             m_backgroundColor.green(), m_backgroundColor.blue(),
87             m_backgroundColor.alpha() * opacity);
88         m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), Color(rgba));
89     }
90
91     if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != matrix) {
92         currentRootLayer->setOpacity(opacity);
93         currentRootLayer->setTransform(matrix);
94     }
95
96     currentRootLayer->paint();
97     m_fpsCounter.updateFPSAndDisplay(m_textureMapper.get(), clipRect.location(), matrix);
98     m_textureMapper->endClip();
99     m_textureMapper->endPainting();
100
101     if (currentRootLayer->descendantsOrSelfHaveRunningAnimations()) {
102         RefPtr<CoordinatedGraphicsScene> protector(this);
103         dispatchOnMainThread([=] {
104             protector->updateViewport();
105         });
106     }
107 }
108
109 void CoordinatedGraphicsScene::paintToGraphicsContext(PlatformGraphicsContext* platformContext)
110 {
111     if (!m_textureMapper)
112         m_textureMapper = TextureMapper::create();
113     ASSERT(m_textureMapper->accelerationMode() == TextureMapper::SoftwareMode);
114     syncRemoteContent();
115     TextureMapperLayer* layer = rootLayer();
116
117     if (!layer)
118         return;
119
120     GraphicsContext graphicsContext(platformContext);
121     m_textureMapper->setGraphicsContext(&graphicsContext);
122     m_textureMapper->beginPainting();
123
124     IntRect clipRect = graphicsContext.clipBounds();
125     if (m_setDrawsBackground)
126         m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), m_backgroundColor);
127
128     layer->paint();
129     m_fpsCounter.updateFPSAndDisplay(m_textureMapper.get(), clipRect.location());
130     m_textureMapper->endPainting();
131     m_textureMapper->setGraphicsContext(0);
132 }
133
134 void CoordinatedGraphicsScene::setScrollPosition(const FloatPoint& scrollPosition)
135 {
136     m_scrollPosition = scrollPosition;
137 }
138
139 void CoordinatedGraphicsScene::updateViewport()
140 {
141     ASSERT(isMainThread());
142     if (m_client)
143         m_client->updateViewport();
144 }
145
146 void CoordinatedGraphicsScene::adjustPositionForFixedLayers()
147 {
148     if (m_fixedLayers.isEmpty())
149         return;
150
151     // Fixed layer positions are updated by the web process when we update the visible contents rect / scroll position.
152     // If we want those layers to follow accurately the viewport when we move between the web process updates, we have to offset
153     // them by the delta between the current position and the position of the viewport used for the last layout.
154     FloatSize delta = m_scrollPosition - m_renderedContentsScrollPosition;
155
156     LayerRawPtrMap::iterator end = m_fixedLayers.end();
157     for (LayerRawPtrMap::iterator it = m_fixedLayers.begin(); it != end; ++it)
158         it->value->setScrollPositionDeltaIfNeeded(delta);
159 }
160
161 #if USE(GRAPHICS_SURFACE)
162 void CoordinatedGraphicsScene::createCanvasIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
163 {
164     if (!state.canvasToken.isValid())
165         return;
166
167     RefPtr<TextureMapperSurfaceBackingStore> canvasBackingStore(TextureMapperSurfaceBackingStore::create());
168     m_surfaceBackingStores.set(layer, canvasBackingStore);
169     canvasBackingStore->setGraphicsSurface(GraphicsSurface::create(state.canvasSize, state.canvasSurfaceFlags, state.canvasToken));
170     layer->setContentsLayer(canvasBackingStore.get());
171 }
172
173 void CoordinatedGraphicsScene::syncCanvasIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
174 {
175     ASSERT(m_textureMapper);
176
177     if (state.canvasChanged) {
178         destroyCanvasIfNeeded(layer, state);
179         createCanvasIfNeeded(layer, state);
180     }
181
182     if (state.canvasShouldSwapBuffers) {
183         ASSERT(m_surfaceBackingStores.contains(layer));
184         SurfaceBackingStoreMap::iterator it = m_surfaceBackingStores.find(layer);
185         RefPtr<TextureMapperSurfaceBackingStore> canvasBackingStore = it->value;
186         canvasBackingStore->swapBuffersIfNeeded(state.canvasFrontBuffer);
187     }
188 }
189
190 void CoordinatedGraphicsScene::destroyCanvasIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
191 {
192     if (state.canvasToken.isValid())
193         return;
194
195     m_surfaceBackingStores.remove(layer);
196     layer->setContentsLayer(0);
197 }
198 #endif
199
200 void CoordinatedGraphicsScene::setLayerRepaintCountIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
201 {
202     if (!layer->isShowingRepaintCounter() || !state.repaintCountChanged)
203         return;
204
205     layer->setRepaintCount(state.repaintCount);
206 }
207
208 void CoordinatedGraphicsScene::setLayerChildrenIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
209 {
210     if (!state.childrenChanged)
211         return;
212
213     Vector<TextureMapperLayer*> children;
214
215     for (size_t i = 0; i < state.children.size(); ++i) {
216         CoordinatedLayerID childID = state.children[i];
217         TextureMapperLayer* child = layerByID(childID);
218         children.append(child);
219     }
220     layer->setChildren(children);
221 }
222
223 #if ENABLE(CSS_FILTERS)
224 void CoordinatedGraphicsScene::setLayerFiltersIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
225 {
226     if (!state.filtersChanged)
227         return;
228
229     layer->setFilters(state.filters);
230 }
231 #endif
232
233 void CoordinatedGraphicsScene::setLayerState(CoordinatedLayerID id, const CoordinatedGraphicsLayerState& layerState)
234 {
235     ASSERT(m_rootLayerID != InvalidCoordinatedLayerID);
236     TextureMapperLayer* layer = layerByID(id);
237
238     if (layerState.positionChanged)
239         layer->setPosition(layerState.pos);
240
241     if (layerState.anchorPointChanged)
242         layer->setAnchorPoint(layerState.anchorPoint);
243
244     if (layerState.sizeChanged)
245         layer->setSize(layerState.size);
246
247     if (layerState.transformChanged)
248         layer->setTransform(layerState.transform);
249
250     if (layerState.childrenTransformChanged)
251         layer->setChildrenTransform(layerState.childrenTransform);
252
253     if (layerState.contentsRectChanged)
254         layer->setContentsRect(layerState.contentsRect);
255
256     if (layerState.contentsTilingChanged) {
257         layer->setContentsTilePhase(layerState.contentsTilePhase);
258         layer->setContentsTileSize(layerState.contentsTileSize);
259     }
260
261     if (layerState.opacityChanged)
262         layer->setOpacity(layerState.opacity);
263
264     if (layerState.solidColorChanged)
265         layer->setSolidColor(layerState.solidColor);
266
267     if (layerState.debugBorderColorChanged || layerState.debugBorderWidthChanged)
268         layer->setDebugVisuals(layerState.showDebugBorders, layerState.debugBorderColor, layerState.debugBorderWidth, layerState.showRepaintCounter);
269
270     if (layerState.replicaChanged)
271         layer->setReplicaLayer(getLayerByIDIfExists(layerState.replica));
272
273     if (layerState.maskChanged)
274         layer->setMaskLayer(getLayerByIDIfExists(layerState.mask));
275
276     if (layerState.imageChanged)
277         assignImageBackingToLayer(layer, layerState.imageID);
278
279     if (layerState.flagsChanged) {
280         layer->setContentsOpaque(layerState.contentsOpaque);
281         layer->setDrawsContent(layerState.drawsContent);
282         layer->setContentsVisible(layerState.contentsVisible);
283         layer->setBackfaceVisibility(layerState.backfaceVisible);
284
285         // Never clip the root layer.
286         layer->setMasksToBounds(id == m_rootLayerID ? false : layerState.masksToBounds);
287         layer->setPreserves3D(layerState.preserves3D);
288
289         bool fixedToViewportChanged = layer->fixedToViewport() != layerState.fixedToViewport;
290         layer->setFixedToViewport(layerState.fixedToViewport);
291         if (fixedToViewportChanged) {
292             if (layerState.fixedToViewport)
293                 m_fixedLayers.add(id, layer);
294             else
295                 m_fixedLayers.remove(id);
296         }
297
298         layer->setIsScrollable(layerState.isScrollable);
299     }
300
301     if (layerState.committedScrollOffsetChanged)
302         layer->didCommitScrollOffset(layerState.committedScrollOffset);
303
304     prepareContentBackingStore(layer);
305
306     // Apply Operations.
307     setLayerChildrenIfNeeded(layer, layerState);
308     createTilesIfNeeded(layer, layerState);
309     removeTilesIfNeeded(layer, layerState);
310     updateTilesIfNeeded(layer, layerState);
311 #if ENABLE(CSS_FILTERS)
312     setLayerFiltersIfNeeded(layer, layerState);
313 #endif
314     setLayerAnimationsIfNeeded(layer, layerState);
315 #if USE(GRAPHICS_SURFACE)
316     syncCanvasIfNeeded(layer, layerState);
317 #endif
318     setLayerRepaintCountIfNeeded(layer, layerState);
319 }
320
321 TextureMapperLayer* CoordinatedGraphicsScene::getLayerByIDIfExists(CoordinatedLayerID id)
322 {
323     return (id != InvalidCoordinatedLayerID) ? layerByID(id) : 0;
324 }
325
326 void CoordinatedGraphicsScene::createLayers(const Vector<CoordinatedLayerID>& ids)
327 {
328     for (size_t index = 0; index < ids.size(); ++index)
329         createLayer(ids[index]);
330 }
331
332 void CoordinatedGraphicsScene::createLayer(CoordinatedLayerID id)
333 {
334     std::unique_ptr<TextureMapperLayer> newLayer = std::make_unique<TextureMapperLayer>();
335     newLayer->setID(id);
336     newLayer->setScrollClient(this);
337     m_layers.add(id, std::move(newLayer));
338 }
339
340 void CoordinatedGraphicsScene::deleteLayers(const Vector<CoordinatedLayerID>& layerIDs)
341 {
342     for (size_t index = 0; index < layerIDs.size(); ++index)
343         deleteLayer(layerIDs[index]);
344 }
345
346 void CoordinatedGraphicsScene::deleteLayer(CoordinatedLayerID layerID)
347 {
348     std::unique_ptr<TextureMapperLayer> layer = m_layers.take(layerID);
349     ASSERT(layer);
350
351     m_backingStores.remove(layer.get());
352     m_fixedLayers.remove(layerID);
353 #if USE(GRAPHICS_SURFACE)
354     m_surfaceBackingStores.remove(layer.get());
355 #endif
356 }
357
358 void CoordinatedGraphicsScene::setRootLayerID(CoordinatedLayerID layerID)
359 {
360     ASSERT(layerID != InvalidCoordinatedLayerID);
361     ASSERT(m_rootLayerID == InvalidCoordinatedLayerID);
362
363     m_rootLayerID = layerID;
364
365     TextureMapperLayer* layer = layerByID(layerID);
366     ASSERT(m_rootLayer->children().isEmpty());
367     m_rootLayer->addChild(layer);
368 }
369
370 void CoordinatedGraphicsScene::prepareContentBackingStore(TextureMapperLayer* layer)
371 {
372     if (!layerShouldHaveBackingStore(layer)) {
373         removeBackingStoreIfNeeded(layer);
374         return;
375     }
376
377     createBackingStoreIfNeeded(layer);
378     resetBackingStoreSizeToLayerSize(layer);
379 }
380
381 void CoordinatedGraphicsScene::createBackingStoreIfNeeded(TextureMapperLayer* layer)
382 {
383     if (m_backingStores.contains(layer))
384         return;
385
386     RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create());
387     m_backingStores.add(layer, backingStore);
388     layer->setBackingStore(backingStore);
389 }
390
391 void CoordinatedGraphicsScene::removeBackingStoreIfNeeded(TextureMapperLayer* layer)
392 {
393     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.take(layer);
394     if (!backingStore)
395         return;
396
397     layer->setBackingStore(0);
398 }
399
400 void CoordinatedGraphicsScene::resetBackingStoreSizeToLayerSize(TextureMapperLayer* layer)
401 {
402     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
403     ASSERT(backingStore);
404     backingStore->setSize(layer->size());
405     m_backingStoresWithPendingBuffers.add(backingStore);
406 }
407
408 void CoordinatedGraphicsScene::createTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
409 {
410     if (state.tilesToCreate.isEmpty())
411         return;
412
413     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
414     ASSERT(backingStore);
415
416     for (size_t i = 0; i < state.tilesToCreate.size(); ++i)
417         backingStore->createTile(state.tilesToCreate[i].tileID, state.tilesToCreate[i].scale);
418 }
419
420 void CoordinatedGraphicsScene::removeTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
421 {
422     if (state.tilesToRemove.isEmpty())
423         return;
424
425     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
426     if (!backingStore)
427         return;
428
429     for (size_t i = 0; i < state.tilesToRemove.size(); ++i)
430         backingStore->removeTile(state.tilesToRemove[i]);
431
432     m_backingStoresWithPendingBuffers.add(backingStore);
433 }
434
435 void CoordinatedGraphicsScene::updateTilesIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
436 {
437     if (state.tilesToUpdate.isEmpty())
438         return;
439
440     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
441     ASSERT(backingStore);
442
443     for (size_t i = 0; i < state.tilesToUpdate.size(); ++i) {
444         const TileUpdateInfo& tileInfo = state.tilesToUpdate[i];
445         const SurfaceUpdateInfo& surfaceUpdateInfo = tileInfo.updateInfo;
446
447         SurfaceMap::iterator surfaceIt = m_surfaces.find(surfaceUpdateInfo.atlasID);
448         ASSERT(surfaceIt != m_surfaces.end());
449
450         backingStore->updateTile(tileInfo.tileID, surfaceUpdateInfo.updateRect, tileInfo.tileRect, surfaceIt->value, surfaceUpdateInfo.surfaceOffset);
451         m_backingStoresWithPendingBuffers.add(backingStore);
452     }
453 }
454
455 void CoordinatedGraphicsScene::syncUpdateAtlases(const CoordinatedGraphicsState& state)
456 {
457     for (size_t i = 0; i < state.updateAtlasesToCreate.size(); ++i)
458         createUpdateAtlas(state.updateAtlasesToCreate[i].first, state.updateAtlasesToCreate[i].second);
459
460     for (size_t i = 0; i < state.updateAtlasesToRemove.size(); ++i)
461         removeUpdateAtlas(state.updateAtlasesToRemove[i]);
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 (size_t i = 0; i < state.imagesToRemove.size(); ++i)
479         removeImageBacking(state.imagesToRemove[i]);
480
481     for (size_t i = 0; i < state.imagesToCreate.size(); ++i)
482         createImageBacking(state.imagesToCreate[i]);
483
484     for (size_t i = 0; i < state.imagesToUpdate.size(); ++i)
485         updateImageBacking(state.imagesToUpdate[i].first, state.imagesToUpdate[i].second);
486
487     for (size_t i = 0; i < state.imagesToClear.size(); ++i)
488         clearImageBackingContents(state.imagesToClear[i]);
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     HashSet<RefPtr<CoordinatedBackingStore> >::iterator end = m_backingStoresWithPendingBuffers.end();
557     for (HashSet<RefPtr<CoordinatedBackingStore> >::iterator it = m_backingStoresWithPendingBuffers.begin(); it != end; ++it)
558         (*it)->commitTileOperations(m_textureMapper.get());
559
560     m_backingStoresWithPendingBuffers.clear();
561 }
562
563 void CoordinatedGraphicsScene::commitSceneState(const CoordinatedGraphicsState& state)
564 {
565     m_renderedContentsScrollPosition = state.scrollPosition;
566
567     createLayers(state.layersToCreate);
568     deleteLayers(state.layersToRemove);
569
570     if (state.rootCompositingLayer != m_rootLayerID)
571         setRootLayerID(state.rootCompositingLayer);
572
573     syncImageBackings(state);
574     syncUpdateAtlases(state);
575
576     for (size_t i = 0; i < state.layersToUpdate.size(); ++i)
577         setLayerState(state.layersToUpdate[i].first, state.layersToUpdate[i].second);
578
579     commitPendingBackingStoreOperations();
580     removeReleasedImageBackingsIfNeeded();
581
582     // The pending tiles state is on its way for the screen, tell the web process to render the next one.
583     RefPtr<CoordinatedGraphicsScene> protector(this);
584     dispatchOnMainThread([=] {
585         protector->renderNextFrame();
586     });
587 }
588
589 void CoordinatedGraphicsScene::renderNextFrame()
590 {
591     if (m_client)
592         m_client->renderNextFrame();
593 }
594
595 void CoordinatedGraphicsScene::ensureRootLayer()
596 {
597     if (m_rootLayer)
598         return;
599
600     m_rootLayer = std::make_unique<TextureMapperLayer>();
601     m_rootLayer->setMasksToBounds(false);
602     m_rootLayer->setDrawsContent(false);
603     m_rootLayer->setAnchorPoint(FloatPoint3D(0, 0, 0));
604
605     // The root layer should not have zero size, or it would be optimized out.
606     m_rootLayer->setSize(FloatSize(1.0, 1.0));
607
608     ASSERT(m_textureMapper);
609     m_rootLayer->setTextureMapper(m_textureMapper.get());
610 }
611
612 void CoordinatedGraphicsScene::syncRemoteContent()
613 {
614     // We enqueue messages and execute them during paint, as they require an active GL context.
615     ensureRootLayer();
616
617     Vector<std::function<void()>> renderQueue;
618     bool calledOnMainThread = WTF::isMainThread();
619     if (!calledOnMainThread)
620         m_renderQueueMutex.lock();
621     renderQueue = std::move(m_renderQueue);
622     if (!calledOnMainThread)
623         m_renderQueueMutex.unlock();
624
625     for (auto& function : renderQueue)
626         function();
627 }
628
629 void CoordinatedGraphicsScene::purgeGLResources()
630 {
631     m_imageBackings.clear();
632     m_releasedImageBackings.clear();
633 #if USE(GRAPHICS_SURFACE)
634     m_surfaceBackingStores.clear();
635 #endif
636     m_surfaces.clear();
637
638     m_rootLayer = nullptr;
639     m_rootLayerID = InvalidCoordinatedLayerID;
640     m_layers.clear();
641     m_fixedLayers.clear();
642     m_textureMapper.clear();
643     m_backingStores.clear();
644     m_backingStoresWithPendingBuffers.clear();
645
646     setActive(false);
647
648     RefPtr<CoordinatedGraphicsScene> protector(this);
649     dispatchOnMainThread([=] {
650         protector->purgeBackingStores();
651     });
652 }
653
654 void CoordinatedGraphicsScene::dispatchCommitScrollOffset(uint32_t layerID, const IntSize& offset)
655 {
656     m_client->commitScrollOffset(layerID, offset);
657 }
658
659 void CoordinatedGraphicsScene::commitScrollOffset(uint32_t layerID, const IntSize& offset)
660 {
661     RefPtr<CoordinatedGraphicsScene> protector(this);
662     dispatchOnMainThread([=] {
663         protector->dispatchCommitScrollOffset(layerID, offset);
664     });
665 }
666
667 void CoordinatedGraphicsScene::purgeBackingStores()
668 {
669     if (m_client)
670         m_client->purgeBackingStores();
671 }
672
673 void CoordinatedGraphicsScene::setLayerAnimationsIfNeeded(TextureMapperLayer* layer, const CoordinatedGraphicsLayerState& state)
674 {
675     if (!state.animationsChanged)
676         return;
677
678     layer->setAnimations(state.animations);
679 }
680
681 void CoordinatedGraphicsScene::detach()
682 {
683     ASSERT(isMainThread());
684     m_renderQueue.clear();
685     m_client = 0;
686 }
687
688 void CoordinatedGraphicsScene::appendUpdate(std::function<void()> function)
689 {
690     if (!m_isActive)
691         return;
692
693     ASSERT(isMainThread());
694     MutexLocker locker(m_renderQueueMutex);
695     m_renderQueue.append(std::move(function));
696 }
697
698 void CoordinatedGraphicsScene::setActive(bool active)
699 {
700     if (m_isActive == active)
701         return;
702
703     // Have to clear render queue in both cases.
704     // If there are some updates in queue during activation then those updates are from previous instance of paint node
705     // and cannot be applied to the newly created instance.
706     m_renderQueue.clear();
707     m_isActive = active;
708     if (m_isActive) {
709         RefPtr<CoordinatedGraphicsScene> protector(this);
710         dispatchOnMainThread([=] {
711             protector->renderNextFrame();
712         });
713     }
714 }
715
716 void CoordinatedGraphicsScene::setBackgroundColor(const Color& color)
717 {
718     m_backgroundColor = color;
719 }
720
721 TextureMapperLayer* CoordinatedGraphicsScene::findScrollableContentsLayerAt(const FloatPoint& point)
722 {
723     return rootLayer() ? rootLayer()->findScrollableContentsLayerAt(point) : 0;
724 }
725
726 } // namespace WebCore
727
728 #endif // USE(COORDINATED_GRAPHICS)