[EFL][Qt] REGRESSION(r144787): A fixed element lags when scrolling and wheeling.
[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 "GraphicsLayerTextureMapper.h"
29 #include "TextureMapper.h"
30 #include "TextureMapperBackingStore.h"
31 #include "TextureMapperGL.h"
32 #include "TextureMapperLayer.h"
33 #include <OpenGLShims.h>
34 #include <wtf/Atomics.h>
35 #include <wtf/MainThread.h>
36
37 #if ENABLE(CSS_SHADERS)
38 #include "CoordinatedCustomFilterOperation.h"
39 #include "CoordinatedCustomFilterProgram.h"
40 #include "CustomFilterProgram.h"
41 #include "CustomFilterProgramInfo.h"
42 #endif
43
44 namespace WebCore {
45
46 void CoordinatedGraphicsScene::dispatchOnMainThread(const Function<void()>& function)
47 {
48     if (isMainThread())
49         function();
50     else
51         callOnMainThread(function);
52 }
53
54 static bool layerShouldHaveBackingStore(GraphicsLayer* 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_animationsLocked(false)
64 #if ENABLE(REQUEST_ANIMATION_FRAME)
65     , m_animationFrameRequested(false)
66 #endif
67     , m_backgroundColor(Color::white)
68     , m_setDrawsBackground(false)
69 {
70     ASSERT(isMainThread());
71 }
72
73 CoordinatedGraphicsScene::~CoordinatedGraphicsScene()
74 {
75 }
76
77 void CoordinatedGraphicsScene::paintToCurrentGLContext(const TransformationMatrix& matrix, float opacity, const FloatRect& clipRect, TextureMapper::PaintFlags PaintFlags)
78 {
79     if (!m_textureMapper) {
80         m_textureMapper = TextureMapper::create(TextureMapper::OpenGLMode);
81         static_cast<TextureMapperGL*>(m_textureMapper.get())->setEnableEdgeDistanceAntialiasing(true);
82     }
83
84     ASSERT(m_textureMapper->accelerationMode() == TextureMapper::OpenGLMode);
85     syncRemoteContent();
86
87     adjustPositionForFixedLayers();
88     GraphicsLayer* currentRootLayer = rootLayer();
89     if (!currentRootLayer)
90         return;
91
92     TextureMapperLayer* layer = toTextureMapperLayer(currentRootLayer);
93
94     if (!layer)
95         return;
96
97     layer->setTextureMapper(m_textureMapper.get());
98     if (!m_animationsLocked)
99         layer->applyAnimationsRecursively();
100     m_textureMapper->beginPainting(PaintFlags);
101     m_textureMapper->beginClip(TransformationMatrix(), clipRect);
102
103     if (m_setDrawsBackground) {
104         RGBA32 rgba = makeRGBA32FromFloats(m_backgroundColor.red(),
105             m_backgroundColor.green(), m_backgroundColor.blue(),
106             m_backgroundColor.alpha() * opacity);
107         m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), Color(rgba));
108     }
109
110     if (currentRootLayer->opacity() != opacity || currentRootLayer->transform() != matrix) {
111         currentRootLayer->setOpacity(opacity);
112         currentRootLayer->setTransform(matrix);
113         currentRootLayer->flushCompositingStateForThisLayerOnly();
114     }
115
116     layer->paint();
117     m_fpsCounter.updateFPSAndDisplay(m_textureMapper.get(), clipRect.location(), matrix);
118     m_textureMapper->endClip();
119     m_textureMapper->endPainting();
120
121     if (layer->descendantsOrSelfHaveRunningAnimations())
122         dispatchOnMainThread(bind(&CoordinatedGraphicsScene::updateViewport, this));
123
124 #if ENABLE(REQUEST_ANIMATION_FRAME)
125     if (m_animationFrameRequested) {
126         m_animationFrameRequested = false;
127         dispatchOnMainThread(bind(&CoordinatedGraphicsScene::animationFrameReady, this));
128     }
129 #endif
130 }
131
132 #if ENABLE(REQUEST_ANIMATION_FRAME)
133 void CoordinatedGraphicsScene::animationFrameReady()
134 {
135     ASSERT(isMainThread());
136     if (m_client)
137         m_client->animationFrameReady();
138 }
139
140 void CoordinatedGraphicsScene::requestAnimationFrame()
141 {
142     m_animationFrameRequested = true;
143 }
144 #endif
145
146 void CoordinatedGraphicsScene::paintToGraphicsContext(PlatformGraphicsContext* platformContext)
147 {
148     if (!m_textureMapper)
149         m_textureMapper = TextureMapper::create();
150     ASSERT(m_textureMapper->accelerationMode() == TextureMapper::SoftwareMode);
151     syncRemoteContent();
152     TextureMapperLayer* layer = toTextureMapperLayer(rootLayer());
153
154     if (!layer)
155         return;
156
157     GraphicsContext graphicsContext(platformContext);
158     m_textureMapper->setGraphicsContext(&graphicsContext);
159     m_textureMapper->beginPainting();
160
161     IntRect clipRect = graphicsContext.clipBounds();
162     if (m_setDrawsBackground)
163         m_textureMapper->drawSolidColor(clipRect, TransformationMatrix(), m_backgroundColor);
164
165     layer->paint();
166     m_fpsCounter.updateFPSAndDisplay(m_textureMapper.get(), clipRect.location());
167     m_textureMapper->endPainting();
168     m_textureMapper->setGraphicsContext(0);
169 }
170
171 void CoordinatedGraphicsScene::setScrollPosition(const FloatPoint& scrollPosition)
172 {
173     m_scrollPosition = scrollPosition;
174 }
175
176 void CoordinatedGraphicsScene::updateViewport()
177 {
178     ASSERT(isMainThread());
179     if (m_client)
180         m_client->updateViewport();
181 }
182
183 void CoordinatedGraphicsScene::adjustPositionForFixedLayers()
184 {
185     if (m_fixedLayers.isEmpty())
186         return;
187
188     // Fixed layer positions are updated by the web process when we update the visible contents rect / scroll position.
189     // If we want those layers to follow accurately the viewport when we move between the web process updates, we have to offset
190     // them by the delta between the current position and the position of the viewport used for the last layout.
191     FloatSize delta = m_scrollPosition - m_renderedContentsScrollPosition;
192
193     LayerRawPtrMap::iterator end = m_fixedLayers.end();
194     for (LayerRawPtrMap::iterator it = m_fixedLayers.begin(); it != end; ++it)
195         toTextureMapperLayer(it->value)->setScrollPositionDeltaIfNeeded(delta);
196 }
197
198 #if USE(GRAPHICS_SURFACE)
199 void CoordinatedGraphicsScene::createCanvasIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
200 {
201     if (!state.canvasToken.isValid())
202         return;
203
204     RefPtr<TextureMapperSurfaceBackingStore> canvasBackingStore(TextureMapperSurfaceBackingStore::create());
205     m_surfaceBackingStores.set(layer, canvasBackingStore);
206
207     GraphicsSurface::Flags surfaceFlags = GraphicsSurface::SupportsTextureTarget | GraphicsSurface::SupportsSharing;
208     canvasBackingStore->setGraphicsSurface(GraphicsSurface::create(state.canvasSize, surfaceFlags, state.canvasToken));
209     layer->setContentsToMedia(canvasBackingStore.get());
210 }
211
212 void CoordinatedGraphicsScene::syncCanvasIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
213 {
214     ASSERT(m_textureMapper);
215
216     if (state.canvasChanged) {
217         destroyCanvasIfNeeded(layer, state);
218         createCanvasIfNeeded(layer, state);
219     }
220
221     if (state.canvasShouldSwapBuffers) {
222         ASSERT(m_surfaceBackingStores.contains(layer));
223         SurfaceBackingStoreMap::iterator it = m_surfaceBackingStores.find(layer);
224         RefPtr<TextureMapperSurfaceBackingStore> canvasBackingStore = it->value;
225         canvasBackingStore->swapBuffersIfNeeded(state.canvasFrontBuffer);
226     }
227 }
228
229 void CoordinatedGraphicsScene::destroyCanvasIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
230 {
231     if (state.canvasToken.isValid())
232         return;
233
234     m_surfaceBackingStores.remove(layer);
235     layer->setContentsToMedia(0);
236 }
237 #endif
238
239 void CoordinatedGraphicsScene::setLayerRepaintCountIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
240 {
241     if (!layer->isShowingRepaintCounter() || !state.repaintCountChanged)
242         return;
243
244     toGraphicsLayerTextureMapper(layer)->setRepaintCount(state.repaintCount);
245 }
246
247 void CoordinatedGraphicsScene::setLayerChildrenIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
248 {
249     if (!state.childrenChanged)
250         return;
251
252     Vector<GraphicsLayer*> children;
253
254     for (size_t i = 0; i < state.children.size(); ++i) {
255         CoordinatedLayerID childID = state.children[i];
256         GraphicsLayer* child = layerByID(childID);
257         children.append(child);
258     }
259     layer->setChildren(children);
260 }
261
262 #if ENABLE(CSS_FILTERS)
263 void CoordinatedGraphicsScene::setLayerFiltersIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
264 {
265     if (!state.filtersChanged)
266         return;
267
268 #if ENABLE(CSS_SHADERS)
269     injectCachedCustomFilterPrograms(state.filters);
270 #endif
271     layer->setFilters(state.filters);
272 }
273 #endif
274
275 #if ENABLE(CSS_SHADERS)
276 void CoordinatedGraphicsScene::injectCachedCustomFilterPrograms(const FilterOperations& filters) const
277 {
278     for (size_t i = 0; i < filters.size(); ++i) {
279         FilterOperation* operation = filters.operations().at(i).get();
280         if (operation->getOperationType() != FilterOperation::CUSTOM)
281             continue;
282
283         CoordinatedCustomFilterOperation* customOperation = static_cast<CoordinatedCustomFilterOperation*>(operation);
284         ASSERT(!customOperation->program());
285         CustomFilterProgramMap::const_iterator iter = m_customFilterPrograms.find(customOperation->programID());
286         ASSERT(iter != m_customFilterPrograms.end());
287         customOperation->setProgram(iter->value.get());
288     }
289 }
290
291 void CoordinatedGraphicsScene::createCustomFilterProgram(int id, const CustomFilterProgramInfo& programInfo)
292 {
293     ASSERT(!m_customFilterPrograms.contains(id));
294     m_customFilterPrograms.set(id, CoordinatedCustomFilterProgram::create(programInfo.vertexShaderString(), programInfo.fragmentShaderString(), programInfo.programType(), programInfo.mixSettings(), programInfo.meshType()));
295 }
296
297 void CoordinatedGraphicsScene::removeCustomFilterProgram(int id)
298 {
299     CustomFilterProgramMap::iterator iter = m_customFilterPrograms.find(id);
300     ASSERT(iter != m_customFilterPrograms.end());
301     if (m_textureMapper)
302         m_textureMapper->removeCachedCustomFilterProgram(iter->value.get());
303     m_customFilterPrograms.remove(iter);
304 }
305 #endif // ENABLE(CSS_SHADERS)
306
307 void CoordinatedGraphicsScene::setLayerState(CoordinatedLayerID id, const CoordinatedGraphicsLayerState& layerState)
308 {
309     ASSERT(m_rootLayerID != InvalidCoordinatedLayerID);
310     GraphicsLayer* layer = layerByID(id);
311
312     if (layerState.positionChanged)
313         layer->setPosition(layerState.pos);
314
315     if (layerState.anchorPointChanged)
316         layer->setAnchorPoint(layerState.anchorPoint);
317
318     if (layerState.sizeChanged)
319         layer->setSize(layerState.size);
320
321     if (layerState.transformChanged)
322         layer->setTransform(layerState.transform);
323
324     if (layerState.childrenTransformChanged)
325         layer->setChildrenTransform(layerState.childrenTransform);
326
327     if (layerState.contentsRectChanged)
328         layer->setContentsRect(layerState.contentsRect);
329
330     if (layerState.opacityChanged)
331         layer->setOpacity(layerState.opacity);
332
333     if (layerState.solidColorChanged)
334         layer->setContentsToSolidColor(layerState.solidColor);
335
336     if (layerState.debugBorderColorChanged || layerState.debugBorderWidthChanged)
337         layer->setDebugBorder(layerState.debugBorderColor, layerState.debugBorderWidth);
338
339     if (layerState.replicaChanged)
340         layer->setReplicatedByLayer(getLayerByIDIfExists(layerState.replica));
341
342     if (layerState.maskChanged)
343         layer->setMaskLayer(getLayerByIDIfExists(layerState.mask));
344
345     if (layerState.imageChanged)
346         assignImageBackingToLayer(layer, layerState.imageID);
347
348     if (layerState.flagsChanged) {
349         layer->setContentsOpaque(layerState.contentsOpaque);
350         layer->setDrawsContent(layerState.drawsContent);
351         layer->setContentsVisible(layerState.contentsVisible);
352         layer->setBackfaceVisibility(layerState.backfaceVisible);
353
354         // Never clip the root layer.
355         layer->setMasksToBounds(layerState.isRootLayer ? false : layerState.masksToBounds);
356         layer->setPreserves3D(layerState.preserves3D);
357
358         bool fixedToViewportChanged = toGraphicsLayerTextureMapper(layer)->fixedToViewport() != layerState.fixedToViewport;
359         toGraphicsLayerTextureMapper(layer)->setFixedToViewport(layerState.fixedToViewport);
360         if (fixedToViewportChanged) {
361             if (layerState.fixedToViewport)
362                 m_fixedLayers.add(id, layer);
363             else
364                 m_fixedLayers.remove(id);
365         }
366
367         layer->setShowDebugBorder(layerState.showDebugBorders);
368         layer->setShowRepaintCounter(layerState.showRepaintCounter);
369
370         toGraphicsLayerTextureMapper(layer)->setIsScrollable(layerState.isScrollable);
371     }
372
373     if (layerState.committedScrollOffsetChanged)
374         toGraphicsLayerTextureMapper(layer)->didCommitScrollOffset(layerState.committedScrollOffset);
375
376     prepareContentBackingStore(layer);
377
378     // Apply Operations.
379     setLayerChildrenIfNeeded(layer, layerState);
380     createTilesIfNeeded(layer, layerState);
381     removeTilesIfNeeded(layer, layerState);
382     updateTilesIfNeeded(layer, layerState);
383 #if ENABLE(CSS_FILTERS)
384     setLayerFiltersIfNeeded(layer, layerState);
385 #endif
386     setLayerAnimationsIfNeeded(layer, layerState);
387 #if USE(GRAPHICS_SURFACE)
388     syncCanvasIfNeeded(layer, layerState);
389 #endif
390     setLayerRepaintCountIfNeeded(layer, layerState);
391 }
392
393 GraphicsLayer* CoordinatedGraphicsScene::getLayerByIDIfExists(CoordinatedLayerID id)
394 {
395     return (id != InvalidCoordinatedLayerID) ? layerByID(id) : 0;
396 }
397
398 void CoordinatedGraphicsScene::createLayers(const Vector<CoordinatedLayerID>& ids)
399 {
400     for (size_t index = 0; index < ids.size(); ++index)
401         createLayer(ids[index]);
402 }
403
404 void CoordinatedGraphicsScene::createLayer(CoordinatedLayerID id)
405 {
406     OwnPtr<GraphicsLayer> newLayer = GraphicsLayer::create(0 /* factory */, this);
407     toGraphicsLayerTextureMapper(newLayer.get())->setHasOwnBackingStore(false);
408     toGraphicsLayerTextureMapper(newLayer.get())->setID(id);
409     toGraphicsLayerTextureMapper(newLayer.get())->setScrollClient(this);
410     m_layers.add(id, newLayer.release());
411 }
412
413 void CoordinatedGraphicsScene::deleteLayers(const Vector<CoordinatedLayerID>& layerIDs)
414 {
415     for (size_t index = 0; index < layerIDs.size(); ++index)
416         deleteLayer(layerIDs[index]);
417 }
418
419 void CoordinatedGraphicsScene::deleteLayer(CoordinatedLayerID layerID)
420 {
421     OwnPtr<GraphicsLayer> layer = m_layers.take(layerID);
422     ASSERT(layer);
423
424     m_backingStores.remove(layer.get());
425     m_fixedLayers.remove(layerID);
426 #if USE(GRAPHICS_SURFACE)
427     m_surfaceBackingStores.remove(layer.get());
428 #endif
429 }
430
431 void CoordinatedGraphicsScene::setRootLayerID(CoordinatedLayerID layerID)
432 {
433     ASSERT(layerID != InvalidCoordinatedLayerID);
434     ASSERT(m_rootLayerID == InvalidCoordinatedLayerID);
435
436     m_rootLayerID = layerID;
437
438     GraphicsLayer* layer = layerByID(layerID);
439     ASSERT(m_rootLayer->children().isEmpty());
440     m_rootLayer->addChild(layer);
441 }
442
443 void CoordinatedGraphicsScene::prepareContentBackingStore(GraphicsLayer* graphicsLayer)
444 {
445     if (!layerShouldHaveBackingStore(graphicsLayer)) {
446         removeBackingStoreIfNeeded(graphicsLayer);
447         return;
448     }
449
450     createBackingStoreIfNeeded(graphicsLayer);
451     resetBackingStoreSizeToLayerSize(graphicsLayer);
452 }
453
454 void CoordinatedGraphicsScene::createBackingStoreIfNeeded(GraphicsLayer* graphicsLayer)
455 {
456     if (m_backingStores.contains(graphicsLayer))
457         return;
458
459     RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create());
460     m_backingStores.add(graphicsLayer, backingStore);
461     toGraphicsLayerTextureMapper(graphicsLayer)->setBackingStore(backingStore);
462 }
463
464 void CoordinatedGraphicsScene::removeBackingStoreIfNeeded(GraphicsLayer* graphicsLayer)
465 {
466     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.take(graphicsLayer);
467     if (!backingStore)
468         return;
469
470     toGraphicsLayerTextureMapper(graphicsLayer)->setBackingStore(0);
471 }
472
473 void CoordinatedGraphicsScene::resetBackingStoreSizeToLayerSize(GraphicsLayer* graphicsLayer)
474 {
475     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(graphicsLayer);
476     ASSERT(backingStore);
477     backingStore->setSize(graphicsLayer->size());
478     m_backingStoresWithPendingBuffers.add(backingStore);
479 }
480
481 void CoordinatedGraphicsScene::createTilesIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
482 {
483     if (state.tilesToCreate.isEmpty())
484         return;
485
486     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
487     ASSERT(backingStore);
488
489     for (size_t i = 0; i < state.tilesToCreate.size(); ++i)
490         backingStore->createTile(state.tilesToCreate[i].tileID, state.tilesToCreate[i].scale);
491 }
492
493 void CoordinatedGraphicsScene::removeTilesIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
494 {
495     if (state.tilesToRemove.isEmpty())
496         return;
497
498     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
499     if (!backingStore)
500         return;
501
502     for (size_t i = 0; i < state.tilesToRemove.size(); ++i)
503         backingStore->removeTile(state.tilesToRemove[i]);
504
505     m_backingStoresWithPendingBuffers.add(backingStore);
506 }
507
508 void CoordinatedGraphicsScene::updateTilesIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
509 {
510     if (state.tilesToUpdate.isEmpty())
511         return;
512
513     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
514     ASSERT(backingStore);
515
516     for (size_t i = 0; i < state.tilesToUpdate.size(); ++i) {
517         const TileUpdateInfo& tileInfo = state.tilesToUpdate[i];
518         const SurfaceUpdateInfo& surfaceUpdateInfo = tileInfo.updateInfo;
519
520         SurfaceMap::iterator surfaceIt = m_surfaces.find(surfaceUpdateInfo.atlasID);
521         ASSERT(surfaceIt != m_surfaces.end());
522
523         backingStore->updateTile(tileInfo.tileID, surfaceUpdateInfo.updateRect, tileInfo.tileRect, surfaceIt->value, surfaceUpdateInfo.surfaceOffset);
524         m_backingStoresWithPendingBuffers.add(backingStore);
525     }
526 }
527
528 void CoordinatedGraphicsScene::createUpdateAtlas(uint32_t atlasID, PassRefPtr<CoordinatedSurface> surface)
529 {
530     ASSERT(!m_surfaces.contains(atlasID));
531     m_surfaces.add(atlasID, surface);
532 }
533
534 void CoordinatedGraphicsScene::removeUpdateAtlas(uint32_t atlasID)
535 {
536     ASSERT(m_surfaces.contains(atlasID));
537     m_surfaces.remove(atlasID);
538 }
539
540 void CoordinatedGraphicsScene::createImageBacking(CoordinatedImageBackingID imageID)
541 {
542     ASSERT(!m_imageBackings.contains(imageID));
543     RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create());
544     m_imageBackings.add(imageID, backingStore.release());
545 }
546
547 void CoordinatedGraphicsScene::updateImageBacking(CoordinatedImageBackingID imageID, PassRefPtr<CoordinatedSurface> surface)
548 {
549     ASSERT(m_imageBackings.contains(imageID));
550     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
551     RefPtr<CoordinatedBackingStore> backingStore = it->value;
552
553     // CoordinatedImageBacking is realized to CoordinatedBackingStore with only one tile in UI Process.
554     backingStore->createTile(1 /* id */, 1 /* scale */);
555     IntRect rect(IntPoint::zero(), surface->size());
556     // See CoordinatedGraphicsLayer::shouldDirectlyCompositeImage()
557     ASSERT(2000 >= std::max(rect.width(), rect.height()));
558     backingStore->setSize(rect.size());
559     backingStore->updateTile(1 /* id */, rect, rect, surface, rect.location());
560
561     m_backingStoresWithPendingBuffers.add(backingStore);
562 }
563
564 void CoordinatedGraphicsScene::clearImageBackingContents(CoordinatedImageBackingID imageID)
565 {
566     ASSERT(m_imageBackings.contains(imageID));
567     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
568     RefPtr<CoordinatedBackingStore> backingStore = it->value;
569     backingStore->removeAllTiles();
570     m_backingStoresWithPendingBuffers.add(backingStore);
571 }
572
573 void CoordinatedGraphicsScene::removeImageBacking(CoordinatedImageBackingID imageID)
574 {
575     ASSERT(m_imageBackings.contains(imageID));
576
577     // We don't want TextureMapperLayer refers a dangling pointer.
578     m_releasedImageBackings.append(m_imageBackings.take(imageID));
579 }
580
581 void CoordinatedGraphicsScene::assignImageBackingToLayer(GraphicsLayer* layer, CoordinatedImageBackingID imageID)
582 {
583 #if USE(GRAPHICS_SURFACE)
584     if (m_surfaceBackingStores.contains(layer))
585         return;
586 #endif
587
588     if (imageID == InvalidCoordinatedImageBackingID) {
589         layer->setContentsToMedia(0);
590         return;
591     }
592     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
593     ASSERT(it != m_imageBackings.end());
594     layer->setContentsToMedia(it->value.get());
595 }
596
597 void CoordinatedGraphicsScene::removeReleasedImageBackingsIfNeeded()
598 {
599     m_releasedImageBackings.clear();
600 }
601
602 void CoordinatedGraphicsScene::commitPendingBackingStoreOperations()
603 {
604     HashSet<RefPtr<CoordinatedBackingStore> >::iterator end = m_backingStoresWithPendingBuffers.end();
605     for (HashSet<RefPtr<CoordinatedBackingStore> >::iterator it = m_backingStoresWithPendingBuffers.begin(); it != end; ++it)
606         (*it)->commitTileOperations(m_textureMapper.get());
607
608     m_backingStoresWithPendingBuffers.clear();
609 }
610
611 void CoordinatedGraphicsScene::commitSceneState(const CoordinatedGraphicsState& state)
612 {
613     m_renderedContentsScrollPosition = state.scrollPosition;
614
615     // Since the frame has now been rendered, we can safely unlock the animations until the next layout.
616     setAnimationsLocked(false);
617
618     if (state.rootCompositingLayer != m_rootLayerID)
619         setRootLayerID(state.rootCompositingLayer);
620
621     if (state.backgroundColor != m_backgroundColor)
622         setBackgroundColor(state.backgroundColor);
623
624     for (size_t i = 0; i < state.imagesToUpdate.size(); ++i)
625         updateImageBacking(state.imagesToUpdate[i].first, state.imagesToUpdate[i].second);
626
627     for (size_t i = 0; i < state.layersToUpdate.size(); ++i)
628         setLayerState(state.layersToUpdate[i].first, state.layersToUpdate[i].second);
629
630     m_rootLayer->flushCompositingState(FloatRect());
631     commitPendingBackingStoreOperations();
632     removeReleasedImageBackingsIfNeeded();
633
634     // The pending tiles state is on its way for the screen, tell the web process to render the next one.
635     dispatchOnMainThread(bind(&CoordinatedGraphicsScene::renderNextFrame, this));
636 }
637
638 void CoordinatedGraphicsScene::renderNextFrame()
639 {
640     if (m_client)
641         m_client->renderNextFrame();
642 }
643
644 void CoordinatedGraphicsScene::ensureRootLayer()
645 {
646     if (m_rootLayer)
647         return;
648
649     m_rootLayer = GraphicsLayer::create(0 /* factory */, this);
650     m_rootLayer->setMasksToBounds(false);
651     m_rootLayer->setDrawsContent(false);
652     m_rootLayer->setAnchorPoint(FloatPoint3D(0, 0, 0));
653
654     // The root layer should not have zero size, or it would be optimized out.
655     m_rootLayer->setSize(FloatSize(1.0, 1.0));
656
657     ASSERT(m_textureMapper);
658     toTextureMapperLayer(m_rootLayer.get())->setTextureMapper(m_textureMapper.get());
659 }
660
661 void CoordinatedGraphicsScene::syncRemoteContent()
662 {
663     // We enqueue messages and execute them during paint, as they require an active GL context.
664     ensureRootLayer();
665
666     Vector<Function<void()> > renderQueue;
667     bool calledOnMainThread = WTF::isMainThread();
668     if (!calledOnMainThread)
669         m_renderQueueMutex.lock();
670     renderQueue.swap(m_renderQueue);
671     if (!calledOnMainThread)
672         m_renderQueueMutex.unlock();
673
674     for (size_t i = 0; i < renderQueue.size(); ++i)
675         renderQueue[i]();
676 }
677
678 void CoordinatedGraphicsScene::purgeGLResources()
679 {
680     m_imageBackings.clear();
681     m_releasedImageBackings.clear();
682 #if USE(GRAPHICS_SURFACE)
683     m_surfaceBackingStores.clear();
684 #endif
685     m_surfaces.clear();
686
687     m_rootLayer.clear();
688     m_rootLayerID = InvalidCoordinatedLayerID;
689     m_layers.clear();
690     m_fixedLayers.clear();
691     m_textureMapper.clear();
692     m_backingStores.clear();
693     m_backingStoresWithPendingBuffers.clear();
694
695     setActive(false);
696     dispatchOnMainThread(bind(&CoordinatedGraphicsScene::purgeBackingStores, this));
697 }
698
699 void CoordinatedGraphicsScene::dispatchCommitScrollOffset(uint32_t layerID, const IntSize& offset)
700 {
701     m_client->commitScrollOffset(layerID, offset);
702 }
703
704 void CoordinatedGraphicsScene::commitScrollOffset(uint32_t layerID, const IntSize& offset)
705 {
706     dispatchOnMainThread(bind(&CoordinatedGraphicsScene::dispatchCommitScrollOffset, this, layerID, offset));
707 }
708
709 void CoordinatedGraphicsScene::purgeBackingStores()
710 {
711     if (m_client)
712         m_client->purgeBackingStores();
713 }
714
715 void CoordinatedGraphicsScene::setLayerAnimationsIfNeeded(GraphicsLayer* graphicsLayer, const CoordinatedGraphicsLayerState& state)
716 {
717     if (!state.animationsChanged)
718         return;
719
720     GraphicsLayerTextureMapper* layer = toGraphicsLayerTextureMapper(graphicsLayer);
721
722 #if ENABLE(CSS_SHADERS)
723     for (size_t i = 0; i < state.animations.animations().size(); ++i) {
724         const KeyframeValueList& keyframes = state.animations.animations().at(i).keyframes();
725         if (keyframes.property() != AnimatedPropertyWebkitFilter)
726             continue;
727         for (size_t j = 0; j < keyframes.size(); ++j) {
728             const FilterAnimationValue* filterValue = static_cast<const FilterAnimationValue*>(keyframes.at(i));
729             injectCachedCustomFilterPrograms(*filterValue->value());
730         }
731     }
732 #endif
733     layer->setAnimations(state.animations);
734 }
735
736 void CoordinatedGraphicsScene::setAnimationsLocked(bool locked)
737 {
738     m_animationsLocked = locked;
739 }
740
741 void CoordinatedGraphicsScene::detach()
742 {
743     ASSERT(isMainThread());
744     m_client = 0;
745 }
746
747 void CoordinatedGraphicsScene::appendUpdate(const Function<void()>& function)
748 {
749     if (!m_isActive)
750         return;
751
752     ASSERT(isMainThread());
753     MutexLocker locker(m_renderQueueMutex);
754     m_renderQueue.append(function);
755 }
756
757 void CoordinatedGraphicsScene::setActive(bool active)
758 {
759     if (m_isActive == active)
760         return;
761
762     // Have to clear render queue in both cases.
763     // If there are some updates in queue during activation then those updates are from previous instance of paint node
764     // and cannot be applied to the newly created instance.
765     m_renderQueue.clear();
766     m_isActive = active;
767     if (m_isActive)
768         dispatchOnMainThread(bind(&CoordinatedGraphicsScene::renderNextFrame, this));
769 }
770
771 void CoordinatedGraphicsScene::setBackgroundColor(const Color& color)
772 {
773     m_backgroundColor = color;
774 }
775
776 TextureMapperLayer* CoordinatedGraphicsScene::findScrollableContentsLayerAt(const FloatPoint& point)
777 {
778     return rootLayer() ? toTextureMapperLayer(rootLayer())->findScrollableContentsLayerAt(point) : 0;
779 }
780
781 } // namespace WebCore
782
783 #endif // USE(COORDINATED_GRAPHICS)