Coordinated Graphics: remove the DidChangeScrollPosition message.
[WebKit-https.git] / Source / WebKit2 / WebProcess / WebPage / CoordinatedGraphics / CoordinatedLayerTreeHost.cpp
1 /*
2  * Copyright (C) 2011 Apple Inc. All rights reserved.
3  * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4  * Copyright (C) 2012 Company 100, Inc.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
17  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
18  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
19  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
25  * THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "config.h"
29
30 #if USE(COORDINATED_GRAPHICS)
31 #include "CoordinatedLayerTreeHost.h"
32
33 #include "CoordinatedGraphicsArgumentCoders.h"
34 #include "CoordinatedLayerTreeHostProxyMessages.h"
35 #include "DrawingAreaImpl.h"
36 #include "GraphicsContext.h"
37 #include "WebCoordinatedSurface.h"
38 #include "WebCoreArgumentCoders.h"
39 #include "WebPage.h"
40 #include "WebPageProxyMessages.h"
41 #include <WebCore/Frame.h>
42 #include <WebCore/FrameView.h>
43 #include <WebCore/GraphicsSurface.h>
44 #include <WebCore/Page.h>
45 #include <WebCore/RenderLayer.h>
46 #include <WebCore/RenderLayerBacking.h>
47 #include <WebCore/RenderLayerCompositor.h>
48 #include <WebCore/RenderView.h>
49 #include <WebCore/Settings.h>
50 #include <WebCore/SurfaceUpdateInfo.h>
51 #include <WebCore/TextureMapperPlatformLayer.h>
52 #include <wtf/TemporaryChange.h>
53
54 #if ENABLE(CSS_SHADERS)
55 #include "CustomFilterValidatedProgram.h"
56 #include "ValidatedCustomFilterOperation.h"
57 #endif
58
59 using namespace WebCore;
60
61 namespace WebKit {
62
63 PassRefPtr<CoordinatedLayerTreeHost> CoordinatedLayerTreeHost::create(WebPage* webPage)
64 {
65     return adoptRef(new CoordinatedLayerTreeHost(webPage));
66 }
67
68 CoordinatedLayerTreeHost::~CoordinatedLayerTreeHost()
69 {
70 #if ENABLE(CSS_SHADERS)
71     disconnectCustomFilterPrograms();
72 #endif
73     purgeBackingStores();
74
75     HashSet<WebCore::CoordinatedGraphicsLayer*>::iterator end = m_registeredLayers.end();
76     for (HashSet<WebCore::CoordinatedGraphicsLayer*>::iterator it = m_registeredLayers.begin(); it != end; ++it)
77         (*it)->setCoordinator(0);
78 }
79
80 CoordinatedLayerTreeHost::CoordinatedLayerTreeHost(WebPage* webPage)
81     : LayerTreeHost(webPage)
82     , m_notifyAfterScheduledLayerFlush(false)
83     , m_isValid(true)
84     , m_isPurging(false)
85     , m_isFlushingLayerChanges(false)
86     , m_waitingForUIProcess(true)
87     , m_isSuspended(false)
88     , m_shouldSyncFrame(false)
89     , m_didInitializeRootCompositingLayer(false)
90     , m_layerFlushTimer(this, &CoordinatedLayerTreeHost::layerFlushTimerFired)
91     , m_releaseInactiveAtlasesTimer(this, &CoordinatedLayerTreeHost::releaseInactiveAtlasesTimerFired)
92     , m_layerFlushSchedulingEnabled(true)
93     , m_forceRepaintAsyncCallbackID(0)
94     , m_animationsLocked(false)
95 {
96     // Create a root layer.
97     m_rootLayer = GraphicsLayer::create(this, this);
98     CoordinatedGraphicsLayer* coordinatedRootLayer = toCoordinatedGraphicsLayer(m_rootLayer.get());
99     coordinatedRootLayer->setRootLayer(true);
100 #ifndef NDEBUG
101     m_rootLayer->setName("CoordinatedLayerTreeHost root layer");
102 #endif
103     m_rootLayer->setDrawsContent(false);
104     m_rootLayer->setSize(m_webPage->size());
105     m_layerTreeContext.coordinatedLayerID = toCoordinatedGraphicsLayer(coordinatedRootLayer)->id();
106
107     m_nonCompositedContentLayer = GraphicsLayer::create(this, this);
108 #ifndef NDEBUG
109     m_nonCompositedContentLayer->setName("CoordinatedLayerTreeHost non-composited content");
110 #endif
111     m_nonCompositedContentLayer->setDrawsContent(true);
112     m_nonCompositedContentLayer->setSize(m_webPage->size());
113
114     m_nonCompositedContentLayer->setShowDebugBorder(m_webPage->corePage()->settings()->showDebugBorders());
115     m_nonCompositedContentLayer->setShowRepaintCounter(m_webPage->corePage()->settings()->showRepaintCounter());
116
117     m_rootLayer->addChild(m_nonCompositedContentLayer.get());
118
119     CoordinatedSurface::setFactory(createCoordinatedSurface);
120
121     if (m_webPage->hasPageOverlay())
122         createPageOverlayLayer();
123
124     scheduleLayerFlush();
125 }
126
127 void CoordinatedLayerTreeHost::setLayerFlushSchedulingEnabled(bool layerFlushingEnabled)
128 {
129     if (m_layerFlushSchedulingEnabled == layerFlushingEnabled)
130         return;
131
132     m_layerFlushSchedulingEnabled = layerFlushingEnabled;
133
134     if (m_layerFlushSchedulingEnabled) {
135         scheduleLayerFlush();
136         return;
137     }
138
139     cancelPendingLayerFlush();
140 }
141
142 void CoordinatedLayerTreeHost::scheduleLayerFlush()
143 {
144     if (!m_layerFlushSchedulingEnabled)
145         return;
146
147     if (!m_layerFlushTimer.isActive())
148         m_layerFlushTimer.startOneShot(0);
149 }
150
151 void CoordinatedLayerTreeHost::cancelPendingLayerFlush()
152 {
153     m_layerFlushTimer.stop();
154 }
155
156 void CoordinatedLayerTreeHost::setShouldNotifyAfterNextScheduledLayerFlush(bool notifyAfterScheduledLayerFlush)
157 {
158     m_notifyAfterScheduledLayerFlush = notifyAfterScheduledLayerFlush;
159 }
160
161 void CoordinatedLayerTreeHost::setRootCompositingLayer(WebCore::GraphicsLayer* graphicsLayer)
162 {
163     m_nonCompositedContentLayer->removeAllChildren();
164     m_nonCompositedContentLayer->setContentsOpaque(m_webPage->drawsBackground() && !m_webPage->drawsTransparentBackground());
165
166     // Add the accelerated layer tree hierarchy.
167     if (graphicsLayer)
168         m_nonCompositedContentLayer->addChild(graphicsLayer);
169 }
170
171 void CoordinatedLayerTreeHost::invalidate()
172 {
173     cancelPendingLayerFlush();
174
175     ASSERT(m_isValid);
176     m_rootLayer = nullptr;
177     m_isValid = false;
178 }
179
180 void CoordinatedLayerTreeHost::setNonCompositedContentsNeedDisplay(const WebCore::IntRect& rect)
181 {
182     m_nonCompositedContentLayer->setNeedsDisplayInRect(rect);
183     if (m_pageOverlayLayer)
184         m_pageOverlayLayer->setNeedsDisplayInRect(rect);
185
186     scheduleLayerFlush();
187 }
188
189 void CoordinatedLayerTreeHost::scrollNonCompositedContents(const WebCore::IntRect& scrollRect, const WebCore::IntSize& /* scrollOffset */)
190 {
191     setNonCompositedContentsNeedDisplay(scrollRect);
192 }
193
194 void CoordinatedLayerTreeHost::forceRepaint()
195 {
196     // This is necessary for running layout tests. Since in this case we are not waiting for a UIProcess to reply nicely.
197     // Instead we are just triggering forceRepaint. But we still want to have the scripted animation callbacks being executed.
198     syncDisplayState();
199
200     // We need to schedule another flush, otherwise the forced paint might cancel a later expected flush.
201     // This is aligned with LayerTreeHostCA.
202     scheduleLayerFlush();
203     flushPendingLayerChanges();
204 }
205
206 bool CoordinatedLayerTreeHost::forceRepaintAsync(uint64_t callbackID)
207 {
208     // We expect the UI process to not require a new repaint until the previous one has finished.
209     ASSERT(!m_forceRepaintAsyncCallbackID);
210     m_forceRepaintAsyncCallbackID = callbackID;
211     scheduleLayerFlush();
212     return true;
213 }
214
215 void CoordinatedLayerTreeHost::sizeDidChange(const WebCore::IntSize& newSize)
216 {
217     if (m_rootLayer->size() == newSize)
218         return;
219
220     m_rootLayer->setSize(newSize);
221
222     // If the newSize exposes new areas of the non-composited content a setNeedsDisplay is needed
223     // for those newly exposed areas.
224     FloatSize oldSize = m_nonCompositedContentLayer->size();
225     m_nonCompositedContentLayer->setSize(newSize);
226
227     if (newSize.width() > oldSize.width()) {
228         float height = std::min(static_cast<float>(newSize.height()), oldSize.height());
229         m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(oldSize.width(), 0, newSize.width() - oldSize.width(), height));
230     }
231
232     if (newSize.height() > oldSize.height())
233         m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(0, oldSize.height(), newSize.width(), newSize.height() - oldSize.height()));
234
235     if (m_pageOverlayLayer)
236         m_pageOverlayLayer->setSize(newSize);
237
238     scheduleLayerFlush();
239 }
240
241 void CoordinatedLayerTreeHost::didInstallPageOverlay()
242 {
243     createPageOverlayLayer();
244     scheduleLayerFlush();
245 }
246
247 void CoordinatedLayerTreeHost::didUninstallPageOverlay()
248 {
249     destroyPageOverlayLayer();
250     scheduleLayerFlush();
251 }
252
253 void CoordinatedLayerTreeHost::setPageOverlayNeedsDisplay(const WebCore::IntRect& rect)
254 {
255     ASSERT(m_pageOverlayLayer);
256     m_pageOverlayLayer->setNeedsDisplayInRect(rect);
257     scheduleLayerFlush();
258 }
259
260 void CoordinatedLayerTreeHost::setPageOverlayOpacity(float value)
261 {
262     ASSERT(m_pageOverlayLayer);
263     m_pageOverlayLayer->setOpacity(value);
264     scheduleLayerFlush();
265 }
266
267 bool CoordinatedLayerTreeHost::flushPendingLayerChanges()
268 {
269     if (m_waitingForUIProcess)
270         return false;
271
272     TemporaryChange<bool> protector(m_isFlushingLayerChanges, true);
273
274     createCompositingLayers();
275
276     initializeRootCompositingLayerIfNeeded();
277
278     m_rootLayer->flushCompositingStateForThisLayerOnly();
279     m_nonCompositedContentLayer->flushCompositingStateForThisLayerOnly();
280     if (m_pageOverlayLayer)
281         m_pageOverlayLayer->flushCompositingStateForThisLayerOnly();
282
283     bool didSync = m_webPage->corePage()->mainFrame()->view()->flushCompositingStateIncludingSubframes();
284
285     flushPendingImageBackingChanges();
286
287     deleteCompositingLayers();
288
289     if (m_shouldSyncFrame) {
290         didSync = true;
291
292         IntSize contentsSize = roundedIntSize(m_nonCompositedContentLayer->size());
293         IntRect coveredRect = toCoordinatedGraphicsLayer(m_nonCompositedContentLayer.get())->coverRect();
294         m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::DidRenderFrame(m_visibleContentsRect.location(), contentsSize, coveredRect));
295         m_waitingForUIProcess = true;
296         m_shouldSyncFrame = false;
297     } else
298         unlockAnimations();
299
300     if (m_forceRepaintAsyncCallbackID) {
301         m_webPage->send(Messages::WebPageProxy::VoidCallback(m_forceRepaintAsyncCallbackID));
302         m_forceRepaintAsyncCallbackID = 0;
303     }
304
305     return didSync;
306 }
307
308 void CoordinatedLayerTreeHost::createCompositingLayers()
309 {
310     if (m_layersToCreate.isEmpty())
311         return;
312
313     // If a layer gets created and deleted in the same cycle, we can simply remove it from m_layersToCreate and m_layersToDelete.
314     for (int i = m_layersToCreate.size() - 1; i >= 0; --i) {
315         size_t index = m_layersToDelete.find(m_layersToCreate[i]);
316         if (index != notFound) {
317             m_layersToCreate.remove(i);
318             m_layersToDelete.remove(index);
319         }
320     }
321
322     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::CreateCompositingLayers(m_layersToCreate));
323     m_layersToCreate.clear();
324     m_shouldSyncFrame = true;
325 }
326
327 void CoordinatedLayerTreeHost::deleteCompositingLayers()
328 {
329     if (m_layersToDelete.isEmpty())
330         return;
331
332     if (m_isPurging) {
333         m_layersToDelete.clear();
334         return;
335     }
336
337     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::DeleteCompositingLayers(m_layersToDelete));
338     m_layersToDelete.clear();
339     m_shouldSyncFrame = true;
340 }
341
342 void CoordinatedLayerTreeHost::initializeRootCompositingLayerIfNeeded()
343 {
344     if (m_didInitializeRootCompositingLayer)
345         return;
346
347     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SetRootCompositingLayer(toCoordinatedGraphicsLayer(m_rootLayer.get())->id()));
348     m_didInitializeRootCompositingLayer = true;
349     m_shouldSyncFrame = true;
350 }
351
352 void CoordinatedLayerTreeHost::syncLayerState(CoordinatedLayerID id, const CoordinatedLayerInfo& info)
353 {
354     m_shouldSyncFrame = true;
355     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SetCompositingLayerState(id, info));
356 }
357
358 void CoordinatedLayerTreeHost::syncLayerChildren(CoordinatedLayerID id, const Vector<CoordinatedLayerID>& children)
359 {
360     m_shouldSyncFrame = true;
361     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SetCompositingLayerChildren(id, children));
362 }
363
364 #if USE(GRAPHICS_SURFACE)
365 void CoordinatedLayerTreeHost::createCanvas(CoordinatedLayerID id, PlatformLayer* canvasPlatformLayer)
366 {
367     m_shouldSyncFrame = true;
368     GraphicsSurfaceToken token = canvasPlatformLayer->graphicsSurfaceToken();
369     IntSize canvasSize = canvasPlatformLayer->platformLayerSize();
370     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::CreateCanvas(id, canvasSize, token));
371 }
372
373 void CoordinatedLayerTreeHost::syncCanvas(CoordinatedLayerID id, PlatformLayer* canvasPlatformLayer)
374 {
375     m_shouldSyncFrame = true;
376     uint32_t frontBuffer = canvasPlatformLayer->copyToGraphicsSurface();
377     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SyncCanvas(id, frontBuffer));
378 }
379
380 void CoordinatedLayerTreeHost::destroyCanvas(CoordinatedLayerID id)
381 {
382     if (m_isPurging)
383         return;
384
385     m_shouldSyncFrame = true;
386     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::DestroyCanvas(id));
387 }
388 #endif
389
390 void CoordinatedLayerTreeHost::setLayerRepaintCount(CoordinatedLayerID id, int value)
391 {
392     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SetLayerRepaintCount(id, value));
393 }
394
395 #if ENABLE(CSS_FILTERS)
396 void CoordinatedLayerTreeHost::syncLayerFilters(CoordinatedLayerID id, const FilterOperations& filters)
397 {
398     m_shouldSyncFrame = true;
399 #if ENABLE(CSS_SHADERS)
400     checkCustomFilterProgramProxies(filters);
401 #endif
402     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SetCompositingLayerFilters(id, filters));
403 }
404 #endif
405
406 #if ENABLE(CSS_SHADERS)
407 void CoordinatedLayerTreeHost::checkCustomFilterProgramProxies(const FilterOperations& filters)
408 {
409     // We need to create the WebCustomFilterProgramProxy objects before we get to serialize the
410     // custom filters to the other process. That's because WebCustomFilterProgramProxy needs
411     // to link back to the coordinator, so that we can send a message to the UI process when
412     // the program is not needed anymore.
413     // Note that the serialization will only happen at a later time in ArgumentCoder<WebCore::FilterOperations>::encode.
414     // At that point the program will only be serialized once. All the other times it will only use the ID of the program.
415     for (size_t i = 0; i < filters.size(); ++i) {
416         const FilterOperation* operation = filters.at(i);
417         if (operation->getOperationType() != FilterOperation::VALIDATED_CUSTOM)
418             continue;
419         const ValidatedCustomFilterOperation* customOperation = static_cast<const ValidatedCustomFilterOperation*>(operation);
420         ASSERT(customOperation->validatedProgram()->isInitialized());
421         TextureMapperPlatformCompiledProgram* program = customOperation->validatedProgram()->platformCompiledProgram();
422
423         RefPtr<WebCustomFilterProgramProxy> customFilterProgramProxy;
424         if (program->client())
425             customFilterProgramProxy = static_cast<WebCustomFilterProgramProxy*>(program->client());
426         else {
427             customFilterProgramProxy = WebCustomFilterProgramProxy::create();
428             program->setClient(customFilterProgramProxy);
429         }
430
431         if (!customFilterProgramProxy->client()) {
432             customFilterProgramProxy->setClient(this);
433             m_customFilterPrograms.add(customFilterProgramProxy.get());
434             m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::CreateCustomFilterProgram(customFilterProgramProxy->id(), customOperation->validatedProgram()->validatedProgramInfo()));
435         } else {
436             // If the client was not disconnected then this coordinator must be the client for it.
437             ASSERT(customFilterProgramProxy->client() == this);
438         }
439     }
440 }
441
442 void CoordinatedLayerTreeHost::removeCustomFilterProgramProxy(WebCustomFilterProgramProxy* customFilterProgramProxy)
443 {
444     // At this time the shader is not needed anymore, so we remove it from our set and
445     // send a message to the other process to delete it.
446     m_customFilterPrograms.remove(customFilterProgramProxy);
447     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::RemoveCustomFilterProgram(customFilterProgramProxy->id()));
448 }
449
450 void CoordinatedLayerTreeHost::disconnectCustomFilterPrograms()
451 {
452     // Make sure that WebCore will not call into this coordinator anymore.
453     HashSet<WebCustomFilterProgramProxy*>::iterator iter = m_customFilterPrograms.begin();
454     for (; iter != m_customFilterPrograms.end(); ++iter)
455         (*iter)->setClient(0);
456 }
457 #endif
458
459 void CoordinatedLayerTreeHost::detachLayer(CoordinatedGraphicsLayer* layer)
460 {
461     m_registeredLayers.remove(layer);
462     m_layersToDelete.append(layer->id());
463     scheduleLayerFlush();
464 }
465
466 void CoordinatedLayerTreeHost::lockAnimations()
467 {
468     m_animationsLocked = true;
469     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SetAnimationsLocked(true));
470 }
471
472 void CoordinatedLayerTreeHost::unlockAnimations()
473 {
474     if (!m_animationsLocked)
475         return;
476
477     m_animationsLocked = false;
478     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SetAnimationsLocked(false));
479 }
480
481 void CoordinatedLayerTreeHost::performScheduledLayerFlush()
482 {
483     if (m_isSuspended || m_waitingForUIProcess)
484         return;
485
486     // We lock the animations while performing layout, to avoid flickers caused by animations continuing in the UI process while
487     // the web process layout wants to cancel them.
488     lockAnimations();
489     syncDisplayState();
490
491     // We can unlock the animations before flushing if there are no visible changes, for example if there are content updates
492     // in a layer with opacity 0.
493     bool canUnlockBeforeFlush = !m_isValid || !toCoordinatedGraphicsLayer(m_rootLayer.get())->hasPendingVisibleChanges();
494     if (canUnlockBeforeFlush)
495         unlockAnimations();
496
497     if (!m_isValid)
498         return;
499
500     if (flushPendingLayerChanges())
501         didPerformScheduledLayerFlush();
502 }
503
504 void CoordinatedLayerTreeHost::syncDisplayState()
505 {
506 #if ENABLE(REQUEST_ANIMATION_FRAME) && !USE(REQUEST_ANIMATION_FRAME_TIMER) && !USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
507     // Make sure that any previously registered animation callbacks are being executed before we flush the layers.
508     m_webPage->corePage()->mainFrame()->view()->serviceScriptedAnimations(convertSecondsToDOMTimeStamp(currentTime()));
509 #endif
510
511     m_webPage->layoutIfNeeded();
512 }
513
514 void CoordinatedLayerTreeHost::didPerformScheduledLayerFlush()
515 {
516     if (m_notifyAfterScheduledLayerFlush) {
517         static_cast<DrawingAreaImpl*>(m_webPage->drawingArea())->layerHostDidFlushLayers();
518         m_notifyAfterScheduledLayerFlush = false;
519     }
520 }
521
522 void CoordinatedLayerTreeHost::layerFlushTimerFired(Timer<CoordinatedLayerTreeHost>*)
523 {
524     performScheduledLayerFlush();
525 }
526
527 void CoordinatedLayerTreeHost::createPageOverlayLayer()
528 {
529     ASSERT(!m_pageOverlayLayer);
530
531     m_pageOverlayLayer = GraphicsLayer::create(this, this);
532 #ifndef NDEBUG
533     m_pageOverlayLayer->setName("CoordinatedLayerTreeHost page overlay content");
534 #endif
535
536     m_pageOverlayLayer->setDrawsContent(true);
537     m_pageOverlayLayer->setSize(m_webPage->size());
538
539     m_rootLayer->addChild(m_pageOverlayLayer.get());
540 }
541
542 void CoordinatedLayerTreeHost::destroyPageOverlayLayer()
543 {
544     ASSERT(m_pageOverlayLayer);
545     m_pageOverlayLayer->removeFromParent();
546     m_pageOverlayLayer = nullptr;
547 }
548
549 PassRefPtr<CoordinatedImageBacking> CoordinatedLayerTreeHost::createImageBackingIfNeeded(Image* image)
550 {
551     CoordinatedImageBackingID imageID = CoordinatedImageBacking::getCoordinatedImageBackingID(image);
552     ImageBackingMap::iterator it = m_imageBackings.find(imageID);
553     RefPtr<CoordinatedImageBacking> imageBacking;
554     if (it == m_imageBackings.end()) {
555         imageBacking = CoordinatedImageBacking::create(this, image);
556         m_imageBackings.add(imageID, imageBacking);
557     } else
558         imageBacking = it->value;
559
560     return imageBacking;
561 }
562
563 void CoordinatedLayerTreeHost::createImageBacking(CoordinatedImageBackingID imageID)
564 {
565     m_shouldSyncFrame = true;
566     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::CreateImageBacking(imageID));
567 }
568
569 bool CoordinatedLayerTreeHost::updateImageBacking(CoordinatedImageBackingID imageID, PassRefPtr<CoordinatedSurface> coordinatedSurface)
570 {
571     m_shouldSyncFrame = true;
572     WebCoordinatedSurface* webCoordinatedSurface = static_cast<WebCoordinatedSurface*>(coordinatedSurface.get());
573     WebCoordinatedSurface::Handle handle;
574     if (!webCoordinatedSurface->createHandle(handle))
575         return false;
576     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::UpdateImageBacking(imageID, handle));
577     return true;
578 }
579
580 void CoordinatedLayerTreeHost::clearImageBackingContents(CoordinatedImageBackingID imageID)
581 {
582     m_shouldSyncFrame = true;
583     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::ClearImageBackingContents(imageID));
584 }
585
586 void CoordinatedLayerTreeHost::removeImageBacking(CoordinatedImageBackingID imageID)
587 {
588     if (m_isPurging)
589         return;
590
591     ASSERT(m_imageBackings.contains(imageID));
592     m_shouldSyncFrame = true;
593     m_imageBackings.remove(imageID);
594     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::RemoveImageBacking(imageID));
595 }
596
597 void CoordinatedLayerTreeHost::flushPendingImageBackingChanges()
598 {
599     ImageBackingMap::iterator end = m_imageBackings.end();
600     for (ImageBackingMap::iterator iter = m_imageBackings.begin(); iter != end; ++iter)
601         iter->value->update();
602 }
603
604 void CoordinatedLayerTreeHost::notifyAnimationStarted(const WebCore::GraphicsLayer*, double /* time */)
605 {
606 }
607
608 void CoordinatedLayerTreeHost::notifyFlushRequired(const WebCore::GraphicsLayer*)
609 {
610     scheduleLayerFlush();
611 }
612
613 void CoordinatedLayerTreeHost::paintContents(const WebCore::GraphicsLayer* graphicsLayer, WebCore::GraphicsContext& graphicsContext, WebCore::GraphicsLayerPaintingPhase, const WebCore::IntRect& clipRect)
614 {
615     if (graphicsLayer == m_nonCompositedContentLayer) {
616         m_webPage->drawRect(graphicsContext, clipRect);
617         return;
618     }
619
620     if (graphicsLayer == m_pageOverlayLayer) {
621         // Overlays contain transparent contents and won't clear the context as part of their rendering, so we do it here.
622         graphicsContext.clearRect(clipRect);
623         m_webPage->drawPageOverlay(graphicsContext, clipRect);
624         return;
625     }
626 }
627
628 PassOwnPtr<GraphicsLayer> CoordinatedLayerTreeHost::createGraphicsLayer(GraphicsLayerClient* client)
629 {
630     CoordinatedGraphicsLayer* layer = new CoordinatedGraphicsLayer(client);
631     layer->setCoordinator(this);
632     m_registeredLayers.add(layer);
633     m_layersToCreate.append(layer->id());
634     layer->setNeedsVisibleRectAdjustment();
635     scheduleLayerFlush();
636     return adoptPtr(layer);
637 }
638
639 PassRefPtr<CoordinatedSurface> CoordinatedLayerTreeHost::createCoordinatedSurface(const IntSize& size, CoordinatedSurface::Flags flags)
640 {
641     return WebCoordinatedSurface::create(size, flags);
642 }
643
644 float CoordinatedLayerTreeHost::deviceScaleFactor() const
645 {
646     return m_webPage->deviceScaleFactor();
647 }
648
649 float CoordinatedLayerTreeHost::pageScaleFactor() const
650 {
651     return m_webPage->pageScaleFactor();
652 }
653
654 bool LayerTreeHost::supportsAcceleratedCompositing()
655 {
656     return true;
657 }
658
659 void CoordinatedLayerTreeHost::createTile(CoordinatedLayerID layerID, uint32_t tileID, const WebCore::SurfaceUpdateInfo& updateInfo, const WebCore::IntRect& tileRect)
660 {
661     m_shouldSyncFrame = true;
662     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::CreateTileForLayer(layerID, tileID, tileRect, updateInfo));
663 }
664
665 void CoordinatedLayerTreeHost::updateTile(CoordinatedLayerID layerID, uint32_t tileID, const WebCore::SurfaceUpdateInfo& updateInfo, const WebCore::IntRect& tileRect)
666 {
667     m_shouldSyncFrame = true;
668     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::UpdateTileForLayer(layerID, tileID, tileRect, updateInfo));
669 }
670
671 void CoordinatedLayerTreeHost::removeTile(CoordinatedLayerID layerID, uint32_t tileID)
672 {
673     if (m_isPurging)
674         return;
675     m_shouldSyncFrame = true;
676     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::RemoveTileForLayer(layerID, tileID));
677 }
678
679 bool CoordinatedLayerTreeHost::createUpdateAtlas(uint32_t atlasID, PassRefPtr<CoordinatedSurface> coordinatedSurface)
680 {
681     WebCoordinatedSurface* webCoordinatedSurface = static_cast<WebCoordinatedSurface*>(coordinatedSurface.get());
682     WebCoordinatedSurface::Handle handle;
683     if (!webCoordinatedSurface->createHandle(handle))
684         return false;
685     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::CreateUpdateAtlas(atlasID, handle));
686     return true;
687 }
688
689 void CoordinatedLayerTreeHost::removeUpdateAtlas(uint32_t atlasID)
690 {
691     if (m_isPurging)
692         return;
693     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::RemoveUpdateAtlas(atlasID));
694 }
695
696 WebCore::FloatRect CoordinatedLayerTreeHost::visibleContentsRect() const
697 {
698     return m_visibleContentsRect;
699 }
700
701
702 void CoordinatedLayerTreeHost::setLayerAnimations(CoordinatedLayerID layerID, const GraphicsLayerAnimations& animations)
703 {
704     m_shouldSyncFrame = true;
705     GraphicsLayerAnimations activeAnimations = animations.getActiveAnimations();
706 #if ENABLE(CSS_SHADERS)
707     for (size_t i = 0; i < activeAnimations.animations().size(); ++i) {
708         const KeyframeValueList& keyframes = animations.animations().at(i).keyframes();
709         if (keyframes.property() != AnimatedPropertyWebkitFilter)
710             continue;
711         for (size_t j = 0; j < keyframes.size(); ++j) {
712             const FilterAnimationValue* filterValue = static_cast<const FilterAnimationValue*>(keyframes.at(i));
713             checkCustomFilterProgramProxies(*filterValue->value());
714         }
715     }
716 #endif
717     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SetLayerAnimations(layerID, activeAnimations));
718 }
719
720 void CoordinatedLayerTreeHost::setVisibleContentsRect(const FloatRect& rect, const FloatPoint& trajectoryVector)
721 {
722     // A zero trajectoryVector indicates that tiles all around the viewport are requested.
723     toCoordinatedGraphicsLayer(m_nonCompositedContentLayer.get())->setVisibleContentRectTrajectoryVector(trajectoryVector);
724
725     bool contentsRectDidChange = rect != m_visibleContentsRect;
726     if (contentsRectDidChange) {
727         m_visibleContentsRect = rect;
728
729         HashSet<WebCore::CoordinatedGraphicsLayer*>::iterator end = m_registeredLayers.end();
730         for (HashSet<WebCore::CoordinatedGraphicsLayer*>::iterator it = m_registeredLayers.begin(); it != end; ++it) {
731             (*it)->setNeedsVisibleRectAdjustment();
732         }
733     }
734
735     scheduleLayerFlush();
736     if (m_webPage->useFixedLayout()) {
737         // Round the rect instead of enclosing it to make sure that its size stays
738         // the same while panning. This can have nasty effects on layout.
739         m_webPage->setFixedVisibleContentRect(roundedIntRect(rect));
740     }
741 }
742
743 void CoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged()
744 {
745     m_rootLayer->deviceOrPageScaleFactorChanged();
746     m_nonCompositedContentLayer->deviceOrPageScaleFactorChanged();
747     if (m_pageOverlayLayer)
748         m_pageOverlayLayer->deviceOrPageScaleFactorChanged();
749 }
750
751 GraphicsLayerFactory* CoordinatedLayerTreeHost::graphicsLayerFactory()
752 {
753     return this;
754 }
755
756 #if ENABLE(REQUEST_ANIMATION_FRAME)
757 void CoordinatedLayerTreeHost::scheduleAnimation()
758 {
759     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::RequestAnimationFrame());
760 }
761
762 void CoordinatedLayerTreeHost::animationFrameReady()
763 {
764     scheduleLayerFlush();
765 }
766 #endif
767
768 void CoordinatedLayerTreeHost::renderNextFrame()
769 {
770     m_waitingForUIProcess = false;
771     scheduleLayerFlush();
772     for (unsigned i = 0; i < m_updateAtlases.size(); ++i)
773         m_updateAtlases[i]->didSwapBuffers();
774 }
775
776 void CoordinatedLayerTreeHost::purgeBackingStores()
777 {
778     TemporaryChange<bool> purgingToggle(m_isPurging, true);
779
780     HashSet<WebCore::CoordinatedGraphicsLayer*>::iterator end = m_registeredLayers.end();
781     for (HashSet<WebCore::CoordinatedGraphicsLayer*>::iterator it = m_registeredLayers.begin(); it != end; ++it)
782         (*it)->purgeBackingStores();
783
784     m_imageBackings.clear();
785     m_updateAtlases.clear();
786 }
787
788 PassOwnPtr<GraphicsContext> CoordinatedLayerTreeHost::beginContentUpdate(const IntSize& size, CoordinatedSurface::Flags flags, uint32_t& atlasID, IntPoint& offset)
789 {
790     OwnPtr<GraphicsContext> graphicsContext;
791     for (unsigned i = 0; i < m_updateAtlases.size(); ++i) {
792         UpdateAtlas* atlas = m_updateAtlases[i].get();
793         if (atlas->supportsAlpha() == (flags & CoordinatedSurface::SupportsAlpha)) {
794             // This will return null if there is no available buffer space.
795             graphicsContext = atlas->beginPaintingOnAvailableBuffer(atlasID, size, offset);
796             if (graphicsContext)
797                 return graphicsContext.release();
798         }
799     }
800
801     static const int ScratchBufferDimension = 1024; // Should be a power of two.
802     m_updateAtlases.append(adoptPtr(new UpdateAtlas(this, ScratchBufferDimension, flags)));
803     scheduleReleaseInactiveAtlases();
804     return m_updateAtlases.last()->beginPaintingOnAvailableBuffer(atlasID, size, offset);
805 }
806
807 const double ReleaseInactiveAtlasesTimerInterval = 0.5;
808
809 void CoordinatedLayerTreeHost::scheduleReleaseInactiveAtlases()
810 {
811     if (!m_releaseInactiveAtlasesTimer.isActive())
812         m_releaseInactiveAtlasesTimer.startRepeating(ReleaseInactiveAtlasesTimerInterval);
813 }
814
815 void CoordinatedLayerTreeHost::releaseInactiveAtlasesTimerFired(Timer<CoordinatedLayerTreeHost>*)
816 {
817     // We always want to keep one atlas for non-composited content.
818     OwnPtr<UpdateAtlas> atlasToKeepAnyway;
819     bool foundActiveAtlasForNonCompositedContent = false;
820     for (int i = m_updateAtlases.size() - 1;  i >= 0; --i) {
821         UpdateAtlas* atlas = m_updateAtlases[i].get();
822         if (!atlas->isInUse())
823             atlas->addTimeInactive(ReleaseInactiveAtlasesTimerInterval);
824         bool usableForNonCompositedContent = !atlas->supportsAlpha();
825         if (atlas->isInactive()) {
826             if (!foundActiveAtlasForNonCompositedContent && !atlasToKeepAnyway && usableForNonCompositedContent)
827                 atlasToKeepAnyway = m_updateAtlases[i].release();
828             m_updateAtlases.remove(i);
829         } else if (usableForNonCompositedContent)
830             foundActiveAtlasForNonCompositedContent = true;
831     }
832
833     if (!foundActiveAtlasForNonCompositedContent && atlasToKeepAnyway)
834         m_updateAtlases.append(atlasToKeepAnyway.release());
835
836     if (m_updateAtlases.size() <= 1)
837         m_releaseInactiveAtlasesTimer.stop();
838 }
839
840 void CoordinatedLayerTreeHost::setBackgroundColor(const WebCore::Color& color)
841 {
842     m_webPage->send(Messages::CoordinatedLayerTreeHostProxy::SetBackgroundColor(color));
843 }
844
845 } // namespace WebKit
846 #endif // USE(COORDINATED_GRAPHICS)