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