6281bd6eb1b194d08d67dfc1703d48d86235285b
[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 void CoordinatedGraphicsScene::didChangeScrollPosition(const FloatPoint& position)
236 {
237     m_pendingRenderedContentsScrollPosition = position;
238 }
239
240 #if USE(GRAPHICS_SURFACE)
241 void CoordinatedGraphicsScene::createCanvas(CoordinatedLayerID id, const IntSize&, PassRefPtr<GraphicsSurface> surface)
242 {
243     ASSERT(m_textureMapper);
244     GraphicsLayer* layer = layerByID(id);
245     ASSERT(!m_surfaceBackingStores.contains(id));
246
247     RefPtr<TextureMapperSurfaceBackingStore> canvasBackingStore(TextureMapperSurfaceBackingStore::create());
248     m_surfaceBackingStores.set(id, canvasBackingStore);
249
250     canvasBackingStore->setGraphicsSurface(surface);
251     layer->setContentsToMedia(canvasBackingStore.get());
252 }
253
254 void CoordinatedGraphicsScene::syncCanvas(CoordinatedLayerID id, uint32_t frontBuffer)
255 {
256     ASSERT(m_textureMapper);
257     ASSERT(m_surfaceBackingStores.contains(id));
258
259     SurfaceBackingStoreMap::iterator it = m_surfaceBackingStores.find(id);
260     RefPtr<TextureMapperSurfaceBackingStore> canvasBackingStore = it->value;
261
262     canvasBackingStore->swapBuffersIfNeeded(frontBuffer);
263 }
264
265 void CoordinatedGraphicsScene::destroyCanvas(CoordinatedLayerID id)
266 {
267     ASSERT(m_textureMapper);
268     GraphicsLayer* layer = layerByID(id);
269     ASSERT(m_surfaceBackingStores.contains(id));
270
271     m_surfaceBackingStores.remove(id);
272     layer->setContentsToMedia(0);
273 }
274 #endif
275
276 void CoordinatedGraphicsScene::setLayerRepaintCount(CoordinatedLayerID id, int value)
277 {
278     GraphicsLayer* layer = layerByID(id);
279     toGraphicsLayerTextureMapper(layer)->setRepaintCount(value);
280 }
281
282 void CoordinatedGraphicsScene::setLayerChildren(CoordinatedLayerID id, const Vector<CoordinatedLayerID>& childIDs)
283 {
284     GraphicsLayer* layer = layerByID(id);
285     Vector<GraphicsLayer*> children;
286
287     for (size_t i = 0; i < childIDs.size(); ++i) {
288         CoordinatedLayerID childID = childIDs[i];
289         GraphicsLayer* child = layerByID(childID);
290         children.append(child);
291     }
292     layer->setChildren(children);
293 }
294
295 #if ENABLE(CSS_FILTERS)
296 void CoordinatedGraphicsScene::setLayerFilters(CoordinatedLayerID id, const FilterOperations& filters)
297 {
298     GraphicsLayer* layer = layerByID(id);
299
300 #if ENABLE(CSS_SHADERS)
301     injectCachedCustomFilterPrograms(filters);
302 #endif
303     layer->setFilters(filters);
304 }
305 #endif
306
307 #if ENABLE(CSS_SHADERS)
308 void CoordinatedGraphicsScene::injectCachedCustomFilterPrograms(const FilterOperations& filters) const
309 {
310     for (size_t i = 0; i < filters.size(); ++i) {
311         FilterOperation* operation = filters.operations().at(i).get();
312         if (operation->getOperationType() != FilterOperation::CUSTOM)
313             continue;
314
315         CoordinatedCustomFilterOperation* customOperation = static_cast<CoordinatedCustomFilterOperation*>(operation);
316         ASSERT(!customOperation->program());
317         CustomFilterProgramMap::const_iterator iter = m_customFilterPrograms.find(customOperation->programID());
318         ASSERT(iter != m_customFilterPrograms.end());
319         customOperation->setProgram(iter->value.get());
320     }
321 }
322
323 void CoordinatedGraphicsScene::createCustomFilterProgram(int id, const CustomFilterProgramInfo& programInfo)
324 {
325     ASSERT(!m_customFilterPrograms.contains(id));
326     m_customFilterPrograms.set(id, CoordinatedCustomFilterProgram::create(programInfo.vertexShaderString(), programInfo.fragmentShaderString(), programInfo.programType(), programInfo.mixSettings(), programInfo.meshType()));
327 }
328
329 void CoordinatedGraphicsScene::removeCustomFilterProgram(int id)
330 {
331     CustomFilterProgramMap::iterator iter = m_customFilterPrograms.find(id);
332     ASSERT(iter != m_customFilterPrograms.end());
333     if (m_textureMapper)
334         m_textureMapper->removeCachedCustomFilterProgram(iter->value.get());
335     m_customFilterPrograms.remove(iter);
336 }
337 #endif // ENABLE(CSS_SHADERS)
338
339 void CoordinatedGraphicsScene::setLayerState(CoordinatedLayerID id, const CoordinatedLayerInfo& layerInfo)
340 {
341     ASSERT(m_rootLayerID != InvalidCoordinatedLayerID);
342     GraphicsLayer* layer = layerByID(id);
343
344     layer->setReplicatedByLayer(getLayerByIDIfExists(layerInfo.replica));
345     layer->setMaskLayer(getLayerByIDIfExists(layerInfo.mask));
346
347     layer->setAnchorPoint(layerInfo.anchorPoint);
348     layer->setPosition(layerInfo.pos);
349     layer->setSize(layerInfo.size);
350
351     layer->setTransform(layerInfo.transform);
352     layer->setChildrenTransform(layerInfo.childrenTransform);
353     layer->setBackfaceVisibility(layerInfo.backfaceVisible);
354     layer->setContentsOpaque(layerInfo.contentsOpaque);
355     layer->setContentsRect(layerInfo.contentsRect);
356     layer->setContentsToSolidColor(layerInfo.solidColor);
357     layer->setDrawsContent(layerInfo.drawsContent);
358     layer->setContentsVisible(layerInfo.contentsVisible);
359     toGraphicsLayerTextureMapper(layer)->setFixedToViewport(layerInfo.fixedToViewport);
360     layer->setShowDebugBorder(layerInfo.showDebugBorders);
361     layer->setDebugBorder(layerInfo.debugBorderColor, layerInfo.debugBorderWidth);
362     layer->setShowRepaintCounter(layerInfo.showRepaintCounter);
363
364     if (layerInfo.fixedToViewport)
365         m_fixedLayers.add(id, layer);
366     else
367         m_fixedLayers.remove(id);
368
369     assignImageBackingToLayer(layer, layerInfo.imageID);
370     prepareContentBackingStore(layer);
371
372     // Never make the root layer clip.
373     layer->setMasksToBounds(layerInfo.isRootLayer ? false : layerInfo.masksToBounds);
374     layer->setOpacity(layerInfo.opacity);
375     layer->setPreserves3D(layerInfo.preserves3D);
376 }
377
378 GraphicsLayer* CoordinatedGraphicsScene::getLayerByIDIfExists(CoordinatedLayerID id)
379 {
380     return (id != InvalidCoordinatedLayerID) ? layerByID(id) : 0;
381 }
382
383 void CoordinatedGraphicsScene::createLayers(const Vector<CoordinatedLayerID>& ids)
384 {
385     for (size_t index = 0; index < ids.size(); ++index)
386         createLayer(ids[index]);
387 }
388
389 void CoordinatedGraphicsScene::createLayer(CoordinatedLayerID id)
390 {
391     OwnPtr<GraphicsLayer> newLayer = GraphicsLayer::create(0 /* factory */, this);
392     toGraphicsLayerTextureMapper(newLayer.get())->setHasOwnBackingStore(false);
393     m_layers.add(id, newLayer.release());
394 }
395
396 void CoordinatedGraphicsScene::deleteLayers(const Vector<CoordinatedLayerID>& layerIDs)
397 {
398     for (size_t index = 0; index < layerIDs.size(); ++index)
399         deleteLayer(layerIDs[index]);
400 }
401
402 void CoordinatedGraphicsScene::deleteLayer(CoordinatedLayerID layerID)
403 {
404     OwnPtr<GraphicsLayer> layer = m_layers.take(layerID);
405     ASSERT(layer);
406
407     m_backingStores.remove(layer.get());
408     m_fixedLayers.remove(layerID);
409 #if USE(GRAPHICS_SURFACE)
410     m_surfaceBackingStores.remove(layerID);
411 #endif
412 }
413
414 void CoordinatedGraphicsScene::setRootLayerID(CoordinatedLayerID layerID)
415 {
416     ASSERT(layerID != InvalidCoordinatedLayerID);
417     ASSERT(m_rootLayerID == InvalidCoordinatedLayerID);
418
419     m_rootLayerID = layerID;
420
421     GraphicsLayer* layer = layerByID(layerID);
422     ASSERT(m_rootLayer->children().isEmpty());
423     m_rootLayer->addChild(layer);
424 }
425
426 void CoordinatedGraphicsScene::prepareContentBackingStore(GraphicsLayer* graphicsLayer)
427 {
428     if (!layerShouldHaveBackingStore(graphicsLayer)) {
429         removeBackingStoreIfNeeded(graphicsLayer);
430         return;
431     }
432
433     createBackingStoreIfNeeded(graphicsLayer);
434 }
435
436 void CoordinatedGraphicsScene::createBackingStoreIfNeeded(GraphicsLayer* graphicsLayer)
437 {
438     if (m_backingStores.contains(graphicsLayer))
439         return;
440
441     RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create());
442     backingStore->setSize(graphicsLayer->size());
443     m_backingStores.add(graphicsLayer, backingStore);
444     toGraphicsLayerTextureMapper(graphicsLayer)->setBackingStore(backingStore);
445 }
446
447 void CoordinatedGraphicsScene::removeBackingStoreIfNeeded(GraphicsLayer* graphicsLayer)
448 {
449     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.take(graphicsLayer);
450     if (!backingStore)
451         return;
452
453     toGraphicsLayerTextureMapper(graphicsLayer)->setBackingStore(0);
454 }
455
456 void CoordinatedGraphicsScene::resetBackingStoreSizeToLayerSize(GraphicsLayer* graphicsLayer)
457 {
458     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(graphicsLayer);
459     ASSERT(backingStore);
460     backingStore->setSize(graphicsLayer->size());
461 }
462
463 void CoordinatedGraphicsScene::createTile(CoordinatedLayerID layerID, uint32_t tileID, float scale)
464 {
465     GraphicsLayer* layer = layerByID(layerID);
466     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
467     ASSERT(backingStore);
468     backingStore->createTile(tileID, scale);
469     resetBackingStoreSizeToLayerSize(layer);
470 }
471
472 void CoordinatedGraphicsScene::removeTile(CoordinatedLayerID layerID, uint32_t tileID)
473 {
474     GraphicsLayer* layer = layerByID(layerID);
475     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
476     if (!backingStore)
477         return;
478
479     backingStore->removeTile(tileID);
480     resetBackingStoreSizeToLayerSize(layer);
481     m_backingStoresWithPendingBuffers.add(backingStore);
482 }
483
484 void CoordinatedGraphicsScene::updateTile(CoordinatedLayerID layerID, uint32_t tileID, const TileUpdate& update)
485 {
486     GraphicsLayer* layer = layerByID(layerID);
487     RefPtr<CoordinatedBackingStore> backingStore = m_backingStores.get(layer);
488     ASSERT(backingStore);
489
490     SurfaceMap::iterator it = m_surfaces.find(update.atlasID);
491     ASSERT(it != m_surfaces.end());
492
493     backingStore->updateTile(tileID, update.sourceRect, update.tileRect, it->value, update.offset);
494     resetBackingStoreSizeToLayerSize(layer);
495     m_backingStoresWithPendingBuffers.add(backingStore);
496 }
497
498 void CoordinatedGraphicsScene::createUpdateAtlas(uint32_t atlasID, PassRefPtr<CoordinatedSurface> surface)
499 {
500     ASSERT(!m_surfaces.contains(atlasID));
501     m_surfaces.add(atlasID, surface);
502 }
503
504 void CoordinatedGraphicsScene::removeUpdateAtlas(uint32_t atlasID)
505 {
506     ASSERT(m_surfaces.contains(atlasID));
507     m_surfaces.remove(atlasID);
508 }
509
510 void CoordinatedGraphicsScene::createImageBacking(CoordinatedImageBackingID imageID)
511 {
512     ASSERT(!m_imageBackings.contains(imageID));
513     RefPtr<CoordinatedBackingStore> backingStore(CoordinatedBackingStore::create());
514     m_imageBackings.add(imageID, backingStore.release());
515 }
516
517 void CoordinatedGraphicsScene::updateImageBacking(CoordinatedImageBackingID imageID, PassRefPtr<CoordinatedSurface> surface)
518 {
519     ASSERT(m_imageBackings.contains(imageID));
520     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
521     RefPtr<CoordinatedBackingStore> backingStore = it->value;
522
523     // CoordinatedImageBacking is realized to CoordinatedBackingStore with only one tile in UI Process.
524     backingStore->createTile(1 /* id */, 1 /* scale */);
525     IntRect rect(IntPoint::zero(), surface->size());
526     // See CoordinatedGraphicsLayer::shouldDirectlyCompositeImage()
527     ASSERT(2000 >= std::max(rect.width(), rect.height()));
528     backingStore->setSize(rect.size());
529     backingStore->updateTile(1 /* id */, rect, rect, surface, rect.location());
530
531     m_backingStoresWithPendingBuffers.add(backingStore);
532 }
533
534 void CoordinatedGraphicsScene::clearImageBackingContents(CoordinatedImageBackingID imageID)
535 {
536     ASSERT(m_imageBackings.contains(imageID));
537     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
538     RefPtr<CoordinatedBackingStore> backingStore = it->value;
539     backingStore->removeAllTiles();
540     m_backingStoresWithPendingBuffers.add(backingStore);
541 }
542
543 void CoordinatedGraphicsScene::removeImageBacking(CoordinatedImageBackingID imageID)
544 {
545     ASSERT(m_imageBackings.contains(imageID));
546
547     // We don't want TextureMapperLayer refers a dangling pointer.
548     m_releasedImageBackings.append(m_imageBackings.take(imageID));
549 }
550
551 void CoordinatedGraphicsScene::assignImageBackingToLayer(GraphicsLayer* layer, CoordinatedImageBackingID imageID)
552 {
553     if (imageID == InvalidCoordinatedImageBackingID) {
554         layer->setContentsToMedia(0);
555         return;
556     }
557     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
558     ASSERT(it != m_imageBackings.end());
559     layer->setContentsToMedia(it->value.get());
560 }
561
562 void CoordinatedGraphicsScene::removeReleasedImageBackingsIfNeeded()
563 {
564     m_releasedImageBackings.clear();
565 }
566
567 void CoordinatedGraphicsScene::commitPendingBackingStoreOperations()
568 {
569     HashSet<RefPtr<CoordinatedBackingStore> >::iterator end = m_backingStoresWithPendingBuffers.end();
570     for (HashSet<RefPtr<CoordinatedBackingStore> >::iterator it = m_backingStoresWithPendingBuffers.begin(); it != end; ++it)
571         (*it)->commitTileOperations(m_textureMapper.get());
572
573     m_backingStoresWithPendingBuffers.clear();
574 }
575
576 void CoordinatedGraphicsScene::flushLayerChanges()
577 {
578     m_renderedContentsScrollPosition = m_pendingRenderedContentsScrollPosition;
579
580     // Since the frame has now been rendered, we can safely unlock the animations until the next layout.
581     setAnimationsLocked(false);
582
583     m_rootLayer->flushCompositingState(FloatRect());
584     commitPendingBackingStoreOperations();
585     removeReleasedImageBackingsIfNeeded();
586
587     // The pending tiles state is on its way for the screen, tell the web process to render the next one.
588     dispatchOnMainThread(bind(&CoordinatedGraphicsScene::renderNextFrame, this));
589 }
590
591 void CoordinatedGraphicsScene::renderNextFrame()
592 {
593     if (m_client)
594         m_client->renderNextFrame();
595 }
596
597 void CoordinatedGraphicsScene::ensureRootLayer()
598 {
599     if (m_rootLayer)
600         return;
601
602     m_rootLayer = GraphicsLayer::create(0 /* factory */, this);
603     m_rootLayer->setMasksToBounds(false);
604     m_rootLayer->setDrawsContent(false);
605     m_rootLayer->setAnchorPoint(FloatPoint3D(0, 0, 0));
606
607     // The root layer should not have zero size, or it would be optimized out.
608     m_rootLayer->setSize(FloatSize(1.0, 1.0));
609
610     ASSERT(m_textureMapper);
611     toTextureMapperLayer(m_rootLayer.get())->setTextureMapper(m_textureMapper.get());
612 }
613
614 void CoordinatedGraphicsScene::syncRemoteContent()
615 {
616     // We enqueue messages and execute them during paint, as they require an active GL context.
617     ensureRootLayer();
618
619     Vector<Function<void()> > renderQueue;
620     bool calledOnMainThread = WTF::isMainThread();
621     if (!calledOnMainThread)
622         m_renderQueueMutex.lock();
623     renderQueue.swap(m_renderQueue);
624     if (!calledOnMainThread)
625         m_renderQueueMutex.unlock();
626
627     for (size_t i = 0; i < renderQueue.size(); ++i)
628         renderQueue[i]();
629 }
630
631 void CoordinatedGraphicsScene::purgeGLResources()
632 {
633     m_imageBackings.clear();
634     m_releasedImageBackings.clear();
635 #if USE(GRAPHICS_SURFACE)
636     m_surfaceBackingStores.clear();
637 #endif
638     m_surfaces.clear();
639
640     m_rootLayer.clear();
641     m_rootLayerID = InvalidCoordinatedLayerID;
642     m_layers.clear();
643     m_fixedLayers.clear();
644     m_textureMapper.clear();
645     m_backingStores.clear();
646     m_backingStoresWithPendingBuffers.clear();
647
648     setActive(false);
649     dispatchOnMainThread(bind(&CoordinatedGraphicsScene::purgeBackingStores, this));
650 }
651
652 void CoordinatedGraphicsScene::purgeBackingStores()
653 {
654     if (m_client)
655         m_client->purgeBackingStores();
656 }
657
658 void CoordinatedGraphicsScene::setLayerAnimations(CoordinatedLayerID id, const GraphicsLayerAnimations& animations)
659 {
660     GraphicsLayerTextureMapper* layer = toGraphicsLayerTextureMapper(layerByID(id));
661 #if ENABLE(CSS_SHADERS)
662     for (size_t i = 0; i < animations.animations().size(); ++i) {
663         const KeyframeValueList& keyframes = animations.animations().at(i).keyframes();
664         if (keyframes.property() != AnimatedPropertyWebkitFilter)
665             continue;
666         for (size_t j = 0; j < keyframes.size(); ++j) {
667             const FilterAnimationValue* filterValue = static_cast<const FilterAnimationValue*>(keyframes.at(i));
668             injectCachedCustomFilterPrograms(*filterValue->value());
669         }
670     }
671 #endif
672     layer->setAnimations(animations);
673 }
674
675 void CoordinatedGraphicsScene::setAnimationsLocked(bool locked)
676 {
677     m_animationsLocked = locked;
678 }
679
680 void CoordinatedGraphicsScene::detach()
681 {
682     ASSERT(isMainThread());
683     m_client = 0;
684 }
685
686 void CoordinatedGraphicsScene::appendUpdate(const Function<void()>& function)
687 {
688     if (!m_isActive)
689         return;
690
691     ASSERT(isMainThread());
692     MutexLocker locker(m_renderQueueMutex);
693     m_renderQueue.append(function);
694 }
695
696 void CoordinatedGraphicsScene::setActive(bool active)
697 {
698     if (m_isActive == active)
699         return;
700
701     // Have to clear render queue in both cases.
702     // If there are some updates in queue during activation then those updates are from previous instance of paint node
703     // and cannot be applied to the newly created instance.
704     m_renderQueue.clear();
705     m_isActive = active;
706     if (m_isActive)
707         dispatchOnMainThread(bind(&CoordinatedGraphicsScene::renderNextFrame, this));
708 }
709
710 void CoordinatedGraphicsScene::setBackgroundColor(const Color& color)
711 {
712     m_backgroundColor = color;
713 }
714
715 void CoordinatedGraphicsScene::updateFPS(const FloatPoint& location, const TransformationMatrix& matrix)
716 {
717     m_frameCount++;
718     double delta = WTF::currentTime() - m_fpsTimestamp;
719     if (delta >= m_fpsInterval) {
720         m_lastFPS = int(m_frameCount / delta);
721         m_frameCount = 0;
722         m_fpsTimestamp += delta;
723     }
724
725     // FIXME: drawRepaintCounter() should save a texture and re-use whenever possible.
726     m_textureMapper->drawRepaintCounter(m_lastFPS, Color::black, location, matrix);
727 }
728
729 } // namespace WebCore
730
731 #endif // USE(COORDINATED_GRAPHICS)