Accelerated overflow scrolling for Coordinated Graphics.
[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         toGraphicsLayerTextureMapper(layer)->setFixedToViewport(layerState.fixedToViewport);
359         layer->setShowDebugBorder(layerState.showDebugBorders);
360         layer->setShowRepaintCounter(layerState.showRepaintCounter);
361     }
362
363     if (layerState.isScrollableChanged)
364         toGraphicsLayerTextureMapper(layer)->setIsScrollable(layerState.isScrollable);
365
366     if (layerState.committedScrollOffsetChanged)
367         toGraphicsLayerTextureMapper(layer)->didCommitScrollOffset(layerState.committedScrollOffset);
368
369     if (layerState.fixedToViewport)
370         m_fixedLayers.add(id, layer);
371     else
372         m_fixedLayers.remove(id);
373
374     prepareContentBackingStore(layer);
375
376     // Apply Operations.
377     setLayerChildrenIfNeeded(layer, layerState);
378     createTilesIfNeeded(layer, layerState);
379     removeTilesIfNeeded(layer, layerState);
380     updateTilesIfNeeded(layer, layerState);
381 #if ENABLE(CSS_FILTERS)
382     setLayerFiltersIfNeeded(layer, layerState);
383 #endif
384     setLayerAnimationsIfNeeded(layer, layerState);
385 #if USE(GRAPHICS_SURFACE)
386     syncCanvasIfNeeded(layer, layerState);
387 #endif
388     setLayerRepaintCountIfNeeded(layer, layerState);
389 }
390
391 GraphicsLayer* CoordinatedGraphicsScene::getLayerByIDIfExists(CoordinatedLayerID id)
392 {
393     return (id != InvalidCoordinatedLayerID) ? layerByID(id) : 0;
394 }
395
396 void CoordinatedGraphicsScene::createLayers(const Vector<CoordinatedLayerID>& ids)
397 {
398     for (size_t index = 0; index < ids.size(); ++index)
399         createLayer(ids[index]);
400 }
401
402 void CoordinatedGraphicsScene::createLayer(CoordinatedLayerID id)
403 {
404     OwnPtr<GraphicsLayer> newLayer = GraphicsLayer::create(0 /* factory */, this);
405     toGraphicsLayerTextureMapper(newLayer.get())->setHasOwnBackingStore(false);
406     toGraphicsLayerTextureMapper(newLayer.get())->setID(id);
407     toGraphicsLayerTextureMapper(newLayer.get())->setScrollClient(this);
408     m_layers.add(id, newLayer.release());
409 }
410
411 void CoordinatedGraphicsScene::deleteLayers(const Vector<CoordinatedLayerID>& layerIDs)
412 {
413     for (size_t index = 0; index < layerIDs.size(); ++index)
414         deleteLayer(layerIDs[index]);
415 }
416
417 void CoordinatedGraphicsScene::deleteLayer(CoordinatedLayerID layerID)
418 {
419     OwnPtr<GraphicsLayer> layer = m_layers.take(layerID);
420     ASSERT(layer);
421
422     m_backingStores.remove(layer.get());
423     m_fixedLayers.remove(layerID);
424 #if USE(GRAPHICS_SURFACE)
425     m_surfaceBackingStores.remove(layer.get());
426 #endif
427 }
428
429 void CoordinatedGraphicsScene::setRootLayerID(CoordinatedLayerID layerID)
430 {
431     ASSERT(layerID != InvalidCoordinatedLayerID);
432     ASSERT(m_rootLayerID == InvalidCoordinatedLayerID);
433
434     m_rootLayerID = layerID;
435
436     GraphicsLayer* layer = layerByID(layerID);
437     ASSERT(m_rootLayer->children().isEmpty());
438     m_rootLayer->addChild(layer);
439 }
440
441 void CoordinatedGraphicsScene::prepareContentBackingStore(GraphicsLayer* graphicsLayer)
442 {
443     if (!layerShouldHaveBackingStore(graphicsLayer)) {
444         removeBackingStoreIfNeeded(graphicsLayer);
445         return;
446     }
447
448     createBackingStoreIfNeeded(graphicsLayer);
449     resetBackingStoreSizeToLayerSize(graphicsLayer);
450 }
451
452 void CoordinatedGraphicsScene::createBackingStoreIfNeeded(GraphicsLayer* graphicsLayer)
453 {
454     if (m_backingStores.contains(graphicsLayer))
455         return;
456
457     RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create());
458     m_backingStores.add(graphicsLayer, backingStore);
459     toGraphicsLayerTextureMapper(graphicsLayer)->setBackingStore(backingStore);
460 }
461
462 void CoordinatedGraphicsScene::removeBackingStoreIfNeeded(GraphicsLayer* graphicsLayer)
463 {
464     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.take(graphicsLayer);
465     if (!backingStore)
466         return;
467
468     toGraphicsLayerTextureMapper(graphicsLayer)->setBackingStore(0);
469 }
470
471 void CoordinatedGraphicsScene::resetBackingStoreSizeToLayerSize(GraphicsLayer* graphicsLayer)
472 {
473     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(graphicsLayer);
474     ASSERT(backingStore);
475     backingStore->setSize(graphicsLayer->size());
476     m_backingStoresWithPendingBuffers.add(backingStore);
477 }
478
479 void CoordinatedGraphicsScene::createTilesIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
480 {
481     if (state.tilesToCreate.isEmpty())
482         return;
483
484     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
485     ASSERT(backingStore);
486
487     for (size_t i = 0; i < state.tilesToCreate.size(); ++i)
488         backingStore->createTile(state.tilesToCreate[i].tileID, state.tilesToCreate[i].scale);
489 }
490
491 void CoordinatedGraphicsScene::removeTilesIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
492 {
493     if (state.tilesToRemove.isEmpty())
494         return;
495
496     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
497     if (!backingStore)
498         return;
499
500     for (size_t i = 0; i < state.tilesToRemove.size(); ++i)
501         backingStore->removeTile(state.tilesToRemove[i]);
502
503     m_backingStoresWithPendingBuffers.add(backingStore);
504 }
505
506 void CoordinatedGraphicsScene::updateTilesIfNeeded(GraphicsLayer* layer, const CoordinatedGraphicsLayerState& state)
507 {
508     if (state.tilesToUpdate.isEmpty())
509         return;
510
511     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
512     ASSERT(backingStore);
513
514     for (size_t i = 0; i < state.tilesToUpdate.size(); ++i) {
515         const TileUpdateInfo& tileInfo = state.tilesToUpdate[i];
516         const SurfaceUpdateInfo& surfaceUpdateInfo = tileInfo.updateInfo;
517
518         SurfaceMap::iterator surfaceIt = m_surfaces.find(surfaceUpdateInfo.atlasID);
519         ASSERT(surfaceIt != m_surfaces.end());
520
521         backingStore->updateTile(tileInfo.tileID, surfaceUpdateInfo.updateRect, tileInfo.tileRect, surfaceIt->value, surfaceUpdateInfo.surfaceOffset);
522         m_backingStoresWithPendingBuffers.add(backingStore);
523     }
524 }
525
526 void CoordinatedGraphicsScene::createUpdateAtlas(uint32_t atlasID, PassRefPtr<CoordinatedSurface> surface)
527 {
528     ASSERT(!m_surfaces.contains(atlasID));
529     m_surfaces.add(atlasID, surface);
530 }
531
532 void CoordinatedGraphicsScene::removeUpdateAtlas(uint32_t atlasID)
533 {
534     ASSERT(m_surfaces.contains(atlasID));
535     m_surfaces.remove(atlasID);
536 }
537
538 void CoordinatedGraphicsScene::createImageBacking(CoordinatedImageBackingID imageID)
539 {
540     ASSERT(!m_imageBackings.contains(imageID));
541     RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create());
542     m_imageBackings.add(imageID, backingStore.release());
543 }
544
545 void CoordinatedGraphicsScene::updateImageBacking(CoordinatedImageBackingID imageID, PassRefPtr<CoordinatedSurface> surface)
546 {
547     ASSERT(m_imageBackings.contains(imageID));
548     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
549     RefPtr<CoordinatedBackingStore> backingStore = it->value;
550
551     // CoordinatedImageBacking is realized to CoordinatedBackingStore with only one tile in UI Process.
552     backingStore->createTile(1 /* id */, 1 /* scale */);
553     IntRect rect(IntPoint::zero(), surface->size());
554     // See CoordinatedGraphicsLayer::shouldDirectlyCompositeImage()
555     ASSERT(2000 >= std::max(rect.width(), rect.height()));
556     backingStore->setSize(rect.size());
557     backingStore->updateTile(1 /* id */, rect, rect, surface, rect.location());
558
559     m_backingStoresWithPendingBuffers.add(backingStore);
560 }
561
562 void CoordinatedGraphicsScene::clearImageBackingContents(CoordinatedImageBackingID imageID)
563 {
564     ASSERT(m_imageBackings.contains(imageID));
565     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
566     RefPtr<CoordinatedBackingStore> backingStore = it->value;
567     backingStore->removeAllTiles();
568     m_backingStoresWithPendingBuffers.add(backingStore);
569 }
570
571 void CoordinatedGraphicsScene::removeImageBacking(CoordinatedImageBackingID imageID)
572 {
573     ASSERT(m_imageBackings.contains(imageID));
574
575     // We don't want TextureMapperLayer refers a dangling pointer.
576     m_releasedImageBackings.append(m_imageBackings.take(imageID));
577 }
578
579 void CoordinatedGraphicsScene::assignImageBackingToLayer(GraphicsLayer* layer, CoordinatedImageBackingID imageID)
580 {
581 #if USE(GRAPHICS_SURFACE)
582     if (m_surfaceBackingStores.contains(layer))
583         return;
584 #endif
585
586     if (imageID == InvalidCoordinatedImageBackingID) {
587         layer->setContentsToMedia(0);
588         return;
589     }
590     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
591     ASSERT(it != m_imageBackings.end());
592     layer->setContentsToMedia(it->value.get());
593 }
594
595 void CoordinatedGraphicsScene::removeReleasedImageBackingsIfNeeded()
596 {
597     m_releasedImageBackings.clear();
598 }
599
600 void CoordinatedGraphicsScene::commitPendingBackingStoreOperations()
601 {
602     HashSet<RefPtr<CoordinatedBackingStore> >::iterator end = m_backingStoresWithPendingBuffers.end();
603     for (HashSet<RefPtr<CoordinatedBackingStore> >::iterator it = m_backingStoresWithPendingBuffers.begin(); it != end; ++it)
604         (*it)->commitTileOperations(m_textureMapper.get());
605
606     m_backingStoresWithPendingBuffers.clear();
607 }
608
609 void CoordinatedGraphicsScene::commitSceneState(const CoordinatedGraphicsState& state)
610 {
611     m_renderedContentsScrollPosition = state.scrollPosition;
612
613     // Since the frame has now been rendered, we can safely unlock the animations until the next layout.
614     setAnimationsLocked(false);
615
616     if (state.rootCompositingLayer != m_rootLayerID)
617         setRootLayerID(state.rootCompositingLayer);
618
619     if (state.backgroundColor != m_backgroundColor)
620         setBackgroundColor(state.backgroundColor);
621
622     for (size_t i = 0; i < state.imagesToUpdate.size(); ++i)
623         updateImageBacking(state.imagesToUpdate[i].first, state.imagesToUpdate[i].second);
624
625     for (size_t i = 0; i < state.layersToUpdate.size(); ++i)
626         setLayerState(state.layersToUpdate[i].first, state.layersToUpdate[i].second);
627
628     m_rootLayer->flushCompositingState(FloatRect());
629     commitPendingBackingStoreOperations();
630     removeReleasedImageBackingsIfNeeded();
631
632     // The pending tiles state is on its way for the screen, tell the web process to render the next one.
633     dispatchOnMainThread(bind(&CoordinatedGraphicsScene::renderNextFrame, this));
634 }
635
636 void CoordinatedGraphicsScene::renderNextFrame()
637 {
638     if (m_client)
639         m_client->renderNextFrame();
640 }
641
642 void CoordinatedGraphicsScene::ensureRootLayer()
643 {
644     if (m_rootLayer)
645         return;
646
647     m_rootLayer = GraphicsLayer::create(0 /* factory */, this);
648     m_rootLayer->setMasksToBounds(false);
649     m_rootLayer->setDrawsContent(false);
650     m_rootLayer->setAnchorPoint(FloatPoint3D(0, 0, 0));
651
652     // The root layer should not have zero size, or it would be optimized out.
653     m_rootLayer->setSize(FloatSize(1.0, 1.0));
654
655     ASSERT(m_textureMapper);
656     toTextureMapperLayer(m_rootLayer.get())->setTextureMapper(m_textureMapper.get());
657 }
658
659 void CoordinatedGraphicsScene::syncRemoteContent()
660 {
661     // We enqueue messages and execute them during paint, as they require an active GL context.
662     ensureRootLayer();
663
664     Vector<Function<void()> > renderQueue;
665     bool calledOnMainThread = WTF::isMainThread();
666     if (!calledOnMainThread)
667         m_renderQueueMutex.lock();
668     renderQueue.swap(m_renderQueue);
669     if (!calledOnMainThread)
670         m_renderQueueMutex.unlock();
671
672     for (size_t i = 0; i < renderQueue.size(); ++i)
673         renderQueue[i]();
674 }
675
676 void CoordinatedGraphicsScene::purgeGLResources()
677 {
678     m_imageBackings.clear();
679     m_releasedImageBackings.clear();
680 #if USE(GRAPHICS_SURFACE)
681     m_surfaceBackingStores.clear();
682 #endif
683     m_surfaces.clear();
684
685     m_rootLayer.clear();
686     m_rootLayerID = InvalidCoordinatedLayerID;
687     m_layers.clear();
688     m_fixedLayers.clear();
689     m_textureMapper.clear();
690     m_backingStores.clear();
691     m_backingStoresWithPendingBuffers.clear();
692
693     setActive(false);
694     dispatchOnMainThread(bind(&CoordinatedGraphicsScene::purgeBackingStores, this));
695 }
696
697 void CoordinatedGraphicsScene::dispatchCommitScrollOffset(uint32_t layerID, const IntSize& offset)
698 {
699     m_client->commitScrollOffset(layerID, offset);
700 }
701
702 void CoordinatedGraphicsScene::commitScrollOffset(uint32_t layerID, const IntSize& offset)
703 {
704     dispatchOnMainThread(bind(&CoordinatedGraphicsScene::dispatchCommitScrollOffset, this, layerID, offset));
705 }
706
707 void CoordinatedGraphicsScene::purgeBackingStores()
708 {
709     if (m_client)
710         m_client->purgeBackingStores();
711 }
712
713 void CoordinatedGraphicsScene::setLayerAnimationsIfNeeded(GraphicsLayer* graphicsLayer, const CoordinatedGraphicsLayerState& state)
714 {
715     if (!state.animationsChanged)
716         return;
717
718     GraphicsLayerTextureMapper* layer = toGraphicsLayerTextureMapper(graphicsLayer);
719
720 #if ENABLE(CSS_SHADERS)
721     for (size_t i = 0; i < state.animations.animations().size(); ++i) {
722         const KeyframeValueList& keyframes = state.animations.animations().at(i).keyframes();
723         if (keyframes.property() != AnimatedPropertyWebkitFilter)
724             continue;
725         for (size_t j = 0; j < keyframes.size(); ++j) {
726             const FilterAnimationValue* filterValue = static_cast<const FilterAnimationValue*>(keyframes.at(i));
727             injectCachedCustomFilterPrograms(*filterValue->value());
728         }
729     }
730 #endif
731     layer->setAnimations(state.animations);
732 }
733
734 void CoordinatedGraphicsScene::setAnimationsLocked(bool locked)
735 {
736     m_animationsLocked = locked;
737 }
738
739 void CoordinatedGraphicsScene::detach()
740 {
741     ASSERT(isMainThread());
742     m_client = 0;
743 }
744
745 void CoordinatedGraphicsScene::appendUpdate(const Function<void()>& function)
746 {
747     if (!m_isActive)
748         return;
749
750     ASSERT(isMainThread());
751     MutexLocker locker(m_renderQueueMutex);
752     m_renderQueue.append(function);
753 }
754
755 void CoordinatedGraphicsScene::setActive(bool active)
756 {
757     if (m_isActive == active)
758         return;
759
760     // Have to clear render queue in both cases.
761     // If there are some updates in queue during activation then those updates are from previous instance of paint node
762     // and cannot be applied to the newly created instance.
763     m_renderQueue.clear();
764     m_isActive = active;
765     if (m_isActive)
766         dispatchOnMainThread(bind(&CoordinatedGraphicsScene::renderNextFrame, this));
767 }
768
769 void CoordinatedGraphicsScene::setBackgroundColor(const Color& color)
770 {
771     m_backgroundColor = color;
772 }
773
774 TextureMapperLayer* CoordinatedGraphicsScene::findScrollableContentsLayerAt(const FloatPoint& point)
775 {
776     return rootLayer() ? toTextureMapperLayer(rootLayer())->findScrollableContentsLayerAt(point) : 0;
777 }
778
779 } // namespace WebCore
780
781 #endif // USE(COORDINATED_GRAPHICS)