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