[CoordGraphics] Avoid painting backing stores for zero-opacity layers
[WebKit.git] / Source / WebCore / platform / graphics / texmap / coordinated / CoordinatedGraphicsLayer.cpp
1 /*
2  Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3  Copyright (C) 2010 Apple Inc. All rights reserved.
4  Copyright (C) 2012 Company 100, Inc.
5  Copyright (C) 2012 Intel Corporation. All rights reserved.
6  Copyright (C) 2017 Sony Interactive Entertainment Inc.
7
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Library General Public
10  License as published by the Free Software Foundation; either
11  version 2 of the License, or (at your option) any later version.
12
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  Library General Public License for more details.
17
18  You should have received a copy of the GNU Library General Public License
19  along with this library; see the file COPYING.LIB.  If not, write to
20  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  Boston, MA 02110-1301, USA.
22  */
23
24 #include "config.h"
25 #include "CoordinatedGraphicsLayer.h"
26
27 #if USE(COORDINATED_GRAPHICS)
28
29 #include "FloatQuad.h"
30 #include "GraphicsContext.h"
31 #include "GraphicsLayer.h"
32 #include "GraphicsLayerFactory.h"
33 #include "NicosiaBackingStoreTextureMapperImpl.h"
34 #include "NicosiaCompositionLayerTextureMapperImpl.h"
35 #include "NicosiaContentLayerTextureMapperImpl.h"
36 #include "NicosiaImageBackingTextureMapperImpl.h"
37 #include "NicosiaPaintingContext.h"
38 #include "NicosiaPaintingEngine.h"
39 #include "ScrollableArea.h"
40 #include "TextureMapperPlatformLayerProxyProvider.h"
41 #include "TiledBackingStore.h"
42 #ifndef NDEBUG
43 #include <wtf/SetForScope.h>
44 #endif
45 #include <wtf/text/CString.h>
46
47 #if USE(GLIB_EVENT_LOOP)
48 #include <wtf/glib/RunLoopSourcePriority.h>
49 #endif
50
51 namespace WebCore {
52
53 Ref<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client, Type layerType)
54 {
55     if (!factory)
56         return adoptRef(*new CoordinatedGraphicsLayer(layerType, client));
57
58     return factory->createGraphicsLayer(layerType, client);
59 }
60
61 void CoordinatedGraphicsLayer::notifyFlushRequired()
62 {
63     if (!m_coordinator)
64         return;
65
66     if (m_coordinator->isFlushingLayerChanges())
67         return;
68
69     client().notifyFlushRequired(this);
70 }
71
72 void CoordinatedGraphicsLayer::didChangeAnimations()
73 {
74     m_nicosia.delta.animationsChanged = true;
75     notifyFlushRequired();
76 }
77
78 void CoordinatedGraphicsLayer::didChangeChildren()
79 {
80     m_nicosia.delta.childrenChanged = true;
81     notifyFlushRequired();
82 }
83
84 void CoordinatedGraphicsLayer::didChangeFilters()
85 {
86     m_nicosia.delta.filtersChanged = true;
87     notifyFlushRequired();
88 }
89
90 void CoordinatedGraphicsLayer::didUpdateTileBuffers()
91 {
92     if (!isShowingRepaintCounter())
93         return;
94
95     auto repaintCount = incrementRepaintCount();
96     m_nicosia.repaintCounter.count = repaintCount;
97     m_nicosia.delta.repaintCounterChanged = true;
98 }
99
100 void CoordinatedGraphicsLayer::setShouldUpdateVisibleRect()
101 {
102     m_shouldUpdateVisibleRect = true;
103     for (auto& child : children())
104         downcast<CoordinatedGraphicsLayer>(child.get()).setShouldUpdateVisibleRect();
105     if (replicaLayer())
106         downcast<CoordinatedGraphicsLayer>(*replicaLayer()).setShouldUpdateVisibleRect();
107 }
108
109 void CoordinatedGraphicsLayer::didChangeGeometry(FlushNotification flushNotification)
110 {
111     if (flushNotification == FlushNotification::Required)
112         notifyFlushRequired();
113     setShouldUpdateVisibleRect();
114 }
115
116 CoordinatedGraphicsLayer::CoordinatedGraphicsLayer(Type layerType, GraphicsLayerClient& client)
117     : GraphicsLayer(layerType, client)
118 #ifndef NDEBUG
119     , m_isPurging(false)
120 #endif
121     , m_shouldUpdateVisibleRect(true)
122     , m_movingVisibleRect(false)
123     , m_pendingContentsScaleAdjustment(false)
124     , m_pendingVisibleRectAdjustment(false)
125     , m_shouldUpdatePlatformLayer(false)
126     , m_coordinator(0)
127     , m_compositedNativeImagePtr(0)
128     , m_animationStartedTimer(*this, &CoordinatedGraphicsLayer::animationStartedTimerFired)
129     , m_requestPendingTileCreationTimer(RunLoop::main(), this, &CoordinatedGraphicsLayer::requestPendingTileCreationTimerFired)
130 {
131     static Nicosia::PlatformLayer::LayerID nextLayerID = 1;
132     m_id = nextLayerID++;
133
134     m_nicosia.layer = Nicosia::CompositionLayer::create(m_id,
135         Nicosia::CompositionLayerTextureMapperImpl::createFactory());
136
137     // Enforce a complete flush on the first occasion.
138     m_nicosia.delta.value = UINT_MAX;
139
140 #if USE(GLIB_EVENT_LOOP)
141     m_requestPendingTileCreationTimer.setPriority(RunLoopSourcePriority::LayerFlushTimer);
142 #endif
143 }
144
145 CoordinatedGraphicsLayer::~CoordinatedGraphicsLayer()
146 {
147     if (m_coordinator) {
148         purgeBackingStores();
149         m_coordinator->detachLayer(this);
150     }
151     ASSERT(!m_nicosia.imageBacking);
152     ASSERT(!m_nicosia.backingStore);
153     if (m_animatedBackingStoreHost)
154         m_animatedBackingStoreHost->layerWillBeDestroyed();
155     willBeDestroyed();
156 }
157
158 bool CoordinatedGraphicsLayer::isCoordinatedGraphicsLayer() const
159 {
160     return true;
161 }
162
163 Nicosia::PlatformLayer::LayerID CoordinatedGraphicsLayer::id() const
164 {
165     return m_id;
166 }
167
168 auto CoordinatedGraphicsLayer::primaryLayerID() const -> PlatformLayerID
169 {
170     return id();
171 }
172
173 bool CoordinatedGraphicsLayer::setChildren(Vector<Ref<GraphicsLayer>>&& children)
174 {
175     bool ok = GraphicsLayer::setChildren(WTFMove(children));
176     if (!ok)
177         return false;
178     didChangeChildren();
179     return true;
180 }
181
182 void CoordinatedGraphicsLayer::addChild(Ref<GraphicsLayer>&& layer)
183 {
184     GraphicsLayer* rawLayer = layer.ptr();
185     GraphicsLayer::addChild(WTFMove(layer));
186     downcast<CoordinatedGraphicsLayer>(*rawLayer).setCoordinatorIncludingSubLayersIfNeeded(m_coordinator);
187     didChangeChildren();
188 }
189
190 void CoordinatedGraphicsLayer::addChildAtIndex(Ref<GraphicsLayer>&& layer, int index)
191 {
192     GraphicsLayer* rawLayer = layer.ptr();
193     GraphicsLayer::addChildAtIndex(WTFMove(layer), index);
194     downcast<CoordinatedGraphicsLayer>(*rawLayer).setCoordinatorIncludingSubLayersIfNeeded(m_coordinator);
195     didChangeChildren();
196 }
197
198 void CoordinatedGraphicsLayer::addChildAbove(Ref<GraphicsLayer>&& layer, GraphicsLayer* sibling)
199 {
200     GraphicsLayer* rawLayer = layer.ptr();
201     GraphicsLayer::addChildAbove(WTFMove(layer), sibling);
202     downcast<CoordinatedGraphicsLayer>(*rawLayer).setCoordinatorIncludingSubLayersIfNeeded(m_coordinator);
203     didChangeChildren();
204 }
205
206 void CoordinatedGraphicsLayer::addChildBelow(Ref<GraphicsLayer>&& layer, GraphicsLayer* sibling)
207 {
208     GraphicsLayer* rawLayer = layer.ptr();
209     GraphicsLayer::addChildBelow(WTFMove(layer), sibling);
210     downcast<CoordinatedGraphicsLayer>(*rawLayer).setCoordinatorIncludingSubLayersIfNeeded(m_coordinator);
211     didChangeChildren();
212 }
213
214 bool CoordinatedGraphicsLayer::replaceChild(GraphicsLayer* oldChild, Ref<GraphicsLayer>&& newChild)
215 {
216     GraphicsLayer* rawLayer = newChild.ptr();
217     bool ok = GraphicsLayer::replaceChild(oldChild, WTFMove(newChild));
218     if (!ok)
219         return false;
220     downcast<CoordinatedGraphicsLayer>(*rawLayer).setCoordinatorIncludingSubLayersIfNeeded(m_coordinator);
221     didChangeChildren();
222     return true;
223 }
224
225 void CoordinatedGraphicsLayer::removeFromParent()
226 {
227     if (CoordinatedGraphicsLayer* parentLayer = downcast<CoordinatedGraphicsLayer>(parent()))
228         parentLayer->didChangeChildren();
229     GraphicsLayer::removeFromParent();
230 }
231
232 void CoordinatedGraphicsLayer::setPosition(const FloatPoint& p)
233 {
234     if (position() == p)
235         return;
236
237     GraphicsLayer::setPosition(p);
238     m_nicosia.delta.positionChanged = true;
239     didChangeGeometry();
240 }
241
242 void CoordinatedGraphicsLayer::syncPosition(const FloatPoint& p)
243 {
244     if (position() == p)
245         return;
246
247     GraphicsLayer::syncPosition(p);
248     m_nicosia.delta.positionChanged = true;
249     didChangeGeometry(FlushNotification::NotRequired);
250 }
251
252 void CoordinatedGraphicsLayer::setAnchorPoint(const FloatPoint3D& p)
253 {
254     if (anchorPoint() == p)
255         return;
256
257     GraphicsLayer::setAnchorPoint(p);
258     m_nicosia.delta.anchorPointChanged = true;
259     didChangeGeometry();
260 }
261
262 void CoordinatedGraphicsLayer::setSize(const FloatSize& size)
263 {
264     if (this->size() == size)
265         return;
266
267     GraphicsLayer::setSize(size);
268     m_nicosia.delta.sizeChanged = true;
269
270     if (maskLayer())
271         maskLayer()->setSize(size);
272     didChangeGeometry();
273 }
274
275 void CoordinatedGraphicsLayer::setBoundsOrigin(const FloatPoint& boundsOrigin)
276 {
277     if (this->boundsOrigin() == boundsOrigin)
278         return;
279
280     GraphicsLayer::setBoundsOrigin(boundsOrigin);
281     m_nicosia.delta.boundsOriginChanged = true;
282     didChangeGeometry();
283 }
284
285 void CoordinatedGraphicsLayer::syncBoundsOrigin(const FloatPoint& boundsOrigin)
286 {
287     if (this->boundsOrigin() == boundsOrigin)
288         return;
289
290     GraphicsLayer::syncBoundsOrigin(boundsOrigin);
291     m_nicosia.delta.boundsOriginChanged = true;
292     didChangeGeometry(FlushNotification::NotRequired);
293 }
294
295 void CoordinatedGraphicsLayer::setTransform(const TransformationMatrix& t)
296 {
297     if (transform() == t)
298         return;
299
300     GraphicsLayer::setTransform(t);
301     m_nicosia.delta.transformChanged = true;
302
303     didChangeGeometry();
304 }
305
306 void CoordinatedGraphicsLayer::setChildrenTransform(const TransformationMatrix& t)
307 {
308     if (childrenTransform() == t)
309         return;
310
311     GraphicsLayer::setChildrenTransform(t);
312     m_nicosia.delta.childrenTransformChanged = true;
313
314     didChangeGeometry();
315 }
316
317 void CoordinatedGraphicsLayer::setPreserves3D(bool b)
318 {
319     if (preserves3D() == b)
320         return;
321
322     GraphicsLayer::setPreserves3D(b);
323     m_nicosia.delta.flagsChanged = true;
324
325     didChangeGeometry();
326 }
327
328 void CoordinatedGraphicsLayer::setMasksToBounds(bool b)
329 {
330     if (masksToBounds() == b)
331         return;
332     GraphicsLayer::setMasksToBounds(b);
333     m_nicosia.delta.flagsChanged = true;
334
335     didChangeGeometry();
336 }
337
338 void CoordinatedGraphicsLayer::setDrawsContent(bool b)
339 {
340     if (drawsContent() == b)
341         return;
342     GraphicsLayer::setDrawsContent(b);
343     m_nicosia.delta.flagsChanged = true;
344
345     notifyFlushRequired();
346 }
347
348 void CoordinatedGraphicsLayer::setContentsVisible(bool b)
349 {
350     if (contentsAreVisible() == b)
351         return;
352     GraphicsLayer::setContentsVisible(b);
353     m_nicosia.delta.flagsChanged = true;
354
355     if (maskLayer())
356         maskLayer()->setContentsVisible(b);
357
358     notifyFlushRequired();
359 }
360
361 void CoordinatedGraphicsLayer::setContentsOpaque(bool b)
362 {
363     if (contentsOpaque() == b)
364         return;
365
366     GraphicsLayer::setContentsOpaque(b);
367     m_nicosia.delta.flagsChanged = true;
368
369     // Demand a repaint of the whole layer.
370     if (!m_needsDisplay.completeLayer) {
371         m_needsDisplay.completeLayer = true;
372         m_needsDisplay.rects.clear();
373
374         addRepaintRect({ { }, m_size });
375     }
376
377     notifyFlushRequired();
378 }
379
380 void CoordinatedGraphicsLayer::setBackfaceVisibility(bool b)
381 {
382     if (backfaceVisibility() == b)
383         return;
384
385     GraphicsLayer::setBackfaceVisibility(b);
386     m_nicosia.delta.flagsChanged = true;
387
388     notifyFlushRequired();
389 }
390
391 void CoordinatedGraphicsLayer::setOpacity(float opacity)
392 {
393     if (this->opacity() == opacity)
394         return;
395
396     GraphicsLayer::setOpacity(opacity);
397     m_nicosia.delta.opacityChanged = true;
398
399     notifyFlushRequired();
400 }
401
402 void CoordinatedGraphicsLayer::setContentsRect(const FloatRect& r)
403 {
404     if (contentsRect() == r)
405         return;
406
407     GraphicsLayer::setContentsRect(r);
408     m_nicosia.delta.contentsRectChanged = true;
409
410     notifyFlushRequired();
411 }
412
413 void CoordinatedGraphicsLayer::setContentsTileSize(const FloatSize& s)
414 {
415     if (contentsTileSize() == s)
416         return;
417
418     GraphicsLayer::setContentsTileSize(s);
419     m_nicosia.delta.contentsTilingChanged = true;
420     notifyFlushRequired();
421 }
422
423 void CoordinatedGraphicsLayer::setContentsTilePhase(const FloatSize& p)
424 {
425     if (contentsTilePhase() == p)
426         return;
427
428     GraphicsLayer::setContentsTilePhase(p);
429     m_nicosia.delta.contentsTilingChanged = true;
430     notifyFlushRequired();
431 }
432
433 bool GraphicsLayer::supportsContentsTiling()
434 {
435     return true;
436 }
437
438 void CoordinatedGraphicsLayer::setContentsNeedsDisplay()
439 {
440 #if USE(COORDINATED_GRAPHICS) && USE(NICOSIA)
441     if (m_nicosia.contentLayer)
442         m_shouldUpdatePlatformLayer = true;
443 #endif
444
445     notifyFlushRequired();
446     addRepaintRect(contentsRect());
447 }
448
449 void CoordinatedGraphicsLayer::setContentsToPlatformLayer(PlatformLayer* platformLayer, ContentsLayerPurpose)
450 {
451 #if USE(COORDINATED_GRAPHICS) && USE(NICOSIA)
452     auto* contentLayer = downcast<Nicosia::ContentLayer>(platformLayer);
453     if (m_nicosia.contentLayer != contentLayer) {
454         m_nicosia.contentLayer = contentLayer;
455         m_nicosia.delta.contentLayerChanged = true;
456         if (m_nicosia.contentLayer)
457             m_shouldUpdatePlatformLayer = true;
458     }
459     notifyFlushRequired();
460 #else
461     UNUSED_PARAM(platformLayer);
462 #endif
463 }
464
465 bool CoordinatedGraphicsLayer::filtersCanBeComposited(const FilterOperations& filters) const
466 {
467     if (!filters.size())
468         return false;
469
470     for (const auto& filterOperation : filters.operations()) {
471         if (filterOperation->type() == FilterOperation::REFERENCE)
472             return false;
473     }
474
475     return true;
476 }
477
478 bool CoordinatedGraphicsLayer::setFilters(const FilterOperations& newFilters)
479 {
480     bool canCompositeFilters = filtersCanBeComposited(newFilters);
481     if (filters() == newFilters)
482         return canCompositeFilters;
483
484     if (canCompositeFilters) {
485         if (!GraphicsLayer::setFilters(newFilters))
486             return false;
487         didChangeFilters();
488     } else if (filters().size()) {
489         clearFilters();
490         didChangeFilters();
491     }
492
493     return canCompositeFilters;
494 }
495
496 void CoordinatedGraphicsLayer::setContentsToSolidColor(const Color& color)
497 {
498     if (m_solidColor == color)
499         return;
500
501     m_solidColor = color;
502     m_nicosia.delta.solidColorChanged = true;
503
504     notifyFlushRequired();
505 }
506
507 void CoordinatedGraphicsLayer::setShowDebugBorder(bool show)
508 {
509     if (isShowingDebugBorder() == show)
510         return;
511
512     GraphicsLayer::setShowDebugBorder(show);
513     m_nicosia.debugBorder.visible = show;
514     m_nicosia.delta.debugBorderChanged = true;
515
516     if (m_nicosia.debugBorder.visible)
517         updateDebugIndicators();
518
519     notifyFlushRequired();
520 }
521
522 void CoordinatedGraphicsLayer::setShowRepaintCounter(bool show)
523 {
524     if (isShowingRepaintCounter() == show)
525         return;
526
527     GraphicsLayer::setShowRepaintCounter(show);
528     m_nicosia.repaintCounter.visible = show;
529     m_nicosia.delta.repaintCounterChanged = true;
530
531     notifyFlushRequired();
532 }
533
534 void CoordinatedGraphicsLayer::setContentsToImage(Image* image)
535 {
536     NativeImagePtr nativeImagePtr = image ? image->nativeImageForCurrentFrame() : nullptr;
537     if (m_compositedImage == image && m_compositedNativeImagePtr == nativeImagePtr)
538         return;
539
540     m_compositedImage = image;
541     m_compositedNativeImagePtr = nativeImagePtr;
542
543     GraphicsLayer::setContentsToImage(image);
544     notifyFlushRequired();
545 }
546
547 void CoordinatedGraphicsLayer::setMaskLayer(RefPtr<GraphicsLayer>&& layer)
548 {
549     if (layer == maskLayer())
550         return;
551
552     GraphicsLayer* rawLayer = layer.get();
553     GraphicsLayer::setMaskLayer(WTFMove(layer));
554
555     if (!rawLayer)
556         return;
557
558     rawLayer->setSize(size());
559     rawLayer->setContentsVisible(contentsAreVisible());
560
561     m_nicosia.delta.maskChanged = true;
562
563     notifyFlushRequired();
564 }
565
566 bool CoordinatedGraphicsLayer::shouldDirectlyCompositeImage(Image* image) const
567 {
568     if (!image || !image->isBitmapImage())
569         return false;
570
571     enum { MaxDimenstionForDirectCompositing = 2000 };
572     if (image->width() > MaxDimenstionForDirectCompositing || image->height() > MaxDimenstionForDirectCompositing)
573         return false;
574
575     return true;
576 }
577
578 void CoordinatedGraphicsLayer::setReplicatedByLayer(RefPtr<GraphicsLayer>&& layer)
579 {
580     if (layer == replicaLayer())
581         return;
582
583     GraphicsLayer::setReplicatedByLayer(WTFMove(layer));
584     m_nicosia.delta.replicaChanged = true;
585     notifyFlushRequired();
586 }
587
588 void CoordinatedGraphicsLayer::setNeedsDisplay()
589 {
590     if (!drawsContent() || !contentsAreVisible() || m_size.isEmpty() || m_needsDisplay.completeLayer)
591         return;
592
593     m_needsDisplay.completeLayer = true;
594     m_needsDisplay.rects.clear();
595
596     notifyFlushRequired();
597     addRepaintRect({ { }, m_size });
598 }
599
600 void CoordinatedGraphicsLayer::setNeedsDisplayInRect(const FloatRect& initialRect, ShouldClipToLayer shouldClip)
601 {
602     if (!drawsContent() || !contentsAreVisible() || m_size.isEmpty() || m_needsDisplay.completeLayer)
603         return;
604
605     auto rect = initialRect;
606     if (shouldClip == ClipToLayer)
607         rect.intersect({ { }, m_size });
608
609     if (rect.isEmpty())
610         return;
611
612     auto& rects = m_needsDisplay.rects;
613     bool alreadyRecorded = std::any_of(rects.begin(), rects.end(),
614         [&](auto& dirtyRect) { return dirtyRect.contains(rect); });
615     if (alreadyRecorded)
616         return;
617
618     if (rects.size() < 32)
619         rects.append(rect);
620     else
621         rects[0].unite(rect);
622
623     notifyFlushRequired();
624     addRepaintRect(rect);
625 }
626
627 void CoordinatedGraphicsLayer::flushCompositingState(const FloatRect& rect)
628 {
629     if (CoordinatedGraphicsLayer* mask = downcast<CoordinatedGraphicsLayer>(maskLayer()))
630         mask->flushCompositingStateForThisLayerOnly();
631
632     if (CoordinatedGraphicsLayer* replica = downcast<CoordinatedGraphicsLayer>(replicaLayer()))
633         replica->flushCompositingStateForThisLayerOnly();
634
635     flushCompositingStateForThisLayerOnly();
636
637     for (auto& child : children())
638         child->flushCompositingState(rect);
639 }
640
641 void CoordinatedGraphicsLayer::setDebugBorder(const Color& color, float width)
642 {
643     ASSERT(m_nicosia.debugBorder.visible);
644     if (m_nicosia.debugBorder.color != color) {
645         m_nicosia.debugBorder.color = color;
646         m_nicosia.delta.debugBorderChanged = true;
647     }
648
649     if (m_nicosia.debugBorder.width != width) {
650         m_nicosia.debugBorder.width = width;
651         m_nicosia.delta.debugBorderChanged = true;
652     }
653 }
654
655 void CoordinatedGraphicsLayer::updatePlatformLayer()
656 {
657     if (!m_shouldUpdatePlatformLayer)
658         return;
659
660     m_shouldUpdatePlatformLayer = false;
661 #if USE(COORDINATED_GRAPHICS) && USE(NICOSIA)
662     if (m_nicosia.contentLayer)
663         downcast<Nicosia::ContentLayerTextureMapperImpl>(m_nicosia.contentLayer->impl()).swapBuffersIfNeeded();
664 #endif
665 }
666
667 static void clampToContentsRectIfRectIsInfinite(FloatRect& rect, const FloatSize& contentsSize)
668 {
669     if (rect.width() >= LayoutUnit::nearlyMax() || rect.width() <= LayoutUnit::nearlyMin()) {
670         rect.setX(0);
671         rect.setWidth(contentsSize.width());
672     }
673
674     if (rect.height() >= LayoutUnit::nearlyMax() || rect.height() <= LayoutUnit::nearlyMin()) {
675         rect.setY(0);
676         rect.setHeight(contentsSize.height());
677     }
678 }
679
680 class CoordinatedAnimatedBackingStoreClient final : public Nicosia::AnimatedBackingStoreClient {
681 public:
682     static Ref<CoordinatedAnimatedBackingStoreClient> create(RefPtr<CoordinatedGraphicsLayer::AnimatedBackingStoreHost>&& host, const FloatRect& visibleRect, const FloatRect& coverRect, const FloatSize& size, float contentsScale)
683     {
684         return adoptRef(*new CoordinatedAnimatedBackingStoreClient(WTFMove(host), visibleRect, coverRect, size, contentsScale));
685     }
686
687     ~CoordinatedAnimatedBackingStoreClient() = default;
688
689     void setCoverRect(const IntRect& rect) { m_coverRect = rect; }
690     void requestBackingStoreUpdateIfNeeded(const TransformationMatrix& transform) final
691     {
692         ASSERT(!isMainThread());
693
694         // Calculate the contents rectangle of the layer in backingStore coordinates.
695         FloatRect contentsRect = { { 0, 0 }, m_size };
696         contentsRect.scale(m_contentsScale);
697
698         // If the area covered by tiles (the coverRect, already in backingStore coordinates) covers the whole
699         // layer contents then we don't need to do anything.
700         if (m_coverRect.contains(contentsRect))
701             return;
702
703         // Non-invertible layers are not visible.
704         if (!transform.isInvertible())
705             return;
706
707         // Calculate the inverse of the layer transformation. The inverse transform will have the inverse of the
708         // scaleFactor applied, so we need to scale it back.
709         TransformationMatrix inverse = transform.inverse().valueOr(TransformationMatrix()).scale(m_contentsScale);
710
711         // Apply the inverse transform to the visible rectangle, so we have the visible rectangle in layer coordinates.
712         FloatRect rect = inverse.clampedBoundsOfProjectedQuad(FloatQuad(m_visibleRect));
713         clampToContentsRectIfRectIsInfinite(rect, m_size);
714         FloatRect transformedVisibleRect = enclosingIntRect(rect);
715
716         // Convert the calculated visible rectangle to backingStore coordinates.
717         transformedVisibleRect.scale(m_contentsScale);
718
719         // Restrict the calculated visible rect to the contents rectangle of the layer.
720         transformedVisibleRect.intersect(contentsRect);
721
722         // If the coverRect doesn't contain the calculated visible rectangle we need to request a backingStore
723         // update to render more tiles.
724         if (!m_coverRect.contains(transformedVisibleRect)) {
725             callOnMainThread([protectedHost = m_host.copyRef()]() {
726                 protectedHost->requestBackingStoreUpdate();
727             });
728         }
729     }
730
731 private:
732     CoordinatedAnimatedBackingStoreClient(RefPtr<CoordinatedGraphicsLayer::AnimatedBackingStoreHost>&& host, const FloatRect& visibleRect, const FloatRect& coverRect, const FloatSize& size, float contentsScale)
733         : Nicosia::AnimatedBackingStoreClient(Type::Coordinated)
734         , m_host(WTFMove(host))
735         , m_visibleRect(visibleRect)
736         , m_coverRect(coverRect)
737         , m_size(size)
738         , m_contentsScale(contentsScale)
739     { }
740
741     RefPtr<CoordinatedGraphicsLayer::AnimatedBackingStoreHost> m_host;
742     FloatRect m_visibleRect;
743     FloatRect m_coverRect;
744     FloatSize m_size;
745     float m_contentsScale;
746 };
747
748 void CoordinatedGraphicsLayer::flushCompositingStateForThisLayerOnly()
749 {
750     // Whether it kicked or not, we don't need this timer running anymore.
751     m_requestPendingTileCreationTimer.stop();
752
753     // When we have a transform animation, we need to update visible rect every frame to adjust the visible rect of a backing store.
754     bool hasActiveTransformAnimation = selfOrAncestorHasActiveTransformAnimation();
755     if (hasActiveTransformAnimation)
756         m_movingVisibleRect = true;
757
758     // Sets the values.
759     computePixelAlignment(m_adjustedPosition, m_adjustedSize, m_adjustedAnchorPoint, m_pixelAlignmentOffset);
760
761     computeTransformedVisibleRect();
762     updatePlatformLayer();
763
764     // Only unset m_movingVisibleRect after we have updated the visible rect after the animation stopped.
765     if (!hasActiveTransformAnimation)
766         m_movingVisibleRect = false;
767
768     // Determine the backing store presence. Content is painted later, in the updateContentBuffers() traversal.
769     if (shouldHaveBackingStore()) {
770         if (!m_nicosia.backingStore) {
771             m_nicosia.backingStore = Nicosia::BackingStore::create(Nicosia::BackingStoreTextureMapperImpl::createFactory());
772             m_nicosia.delta.backingStoreChanged = true;
773         }
774     } else if (m_nicosia.backingStore) {
775         auto& layerState = downcast<Nicosia::BackingStoreTextureMapperImpl>(m_nicosia.backingStore->impl()).layerState();
776         layerState.isPurging = true;
777         layerState.mainBackingStore = nullptr;
778
779         m_nicosia.backingStore = nullptr;
780         m_nicosia.delta.backingStoreChanged = true;
781     }
782
783     if (hasActiveTransformAnimation && m_nicosia.backingStore) {
784         // The layer has a backingStore and a transformation animation. This means that we need to add an
785         // AnimatedBackingStoreClient to check whether we need to update the backingStore due to the animation.
786         // At this point we don't know the area covered by tiles available, so we just pass an empty rectangle
787         // for that. The call to updateContentBuffers will calculate the tile coverage and set the appropriate
788         // rectangle to the client.
789         if (!m_animatedBackingStoreHost)
790             m_animatedBackingStoreHost = AnimatedBackingStoreHost::create(*this);
791         m_nicosia.animatedBackingStoreClient = CoordinatedAnimatedBackingStoreClient::create(m_animatedBackingStoreHost.copyRef(), m_coordinator->visibleContentsRect(), { }, m_size, effectiveContentsScale());
792     }
793     // Each layer flush changes the AnimatedBackingStoreClient, being it null or a real one.
794     m_nicosia.delta.animatedBackingStoreClientChanged = true;
795
796     // Determine image backing presence according to the composited image source.
797     if (m_compositedNativeImagePtr) {
798         ASSERT(m_compositedImage);
799         auto& image = *m_compositedImage;
800         uintptr_t imageID = reinterpret_cast<uintptr_t>(&image);
801         uintptr_t nativeImageID = reinterpret_cast<uintptr_t>(m_compositedNativeImagePtr.get());
802
803         // Respawn the ImageBacking object if the underlying image changed.
804         if (m_nicosia.imageBacking) {
805             auto& impl = downcast<Nicosia::ImageBackingTextureMapperImpl>(m_nicosia.imageBacking->impl());
806             if (impl.layerState().imageID != imageID) {
807                 impl.layerState().update = Nicosia::ImageBackingTextureMapperImpl::Update { };
808                 m_nicosia.imageBacking = nullptr;
809             }
810         }
811         if (!m_nicosia.imageBacking) {
812             m_nicosia.imageBacking = Nicosia::ImageBacking::create(Nicosia::ImageBackingTextureMapperImpl::createFactory());
813             m_nicosia.delta.imageBackingChanged = true;
814         }
815
816         // Update the image contents only when the image layer is visible and the native image changed.
817         auto& impl = downcast<Nicosia::ImageBackingTextureMapperImpl>(m_nicosia.imageBacking->impl());
818         auto& layerState = impl.layerState();
819         layerState.imageID = imageID;
820         layerState.update.isVisible = transformedVisibleRect().intersects(IntRect(contentsRect()));
821         if (layerState.update.isVisible && layerState.nativeImageID != nativeImageID) {
822             auto buffer = Nicosia::Buffer::create(IntSize(image.size()),
823                 !image.currentFrameKnownToBeOpaque() ? Nicosia::Buffer::SupportsAlpha : Nicosia::Buffer::NoFlags);
824             Nicosia::PaintingContext::paint(buffer,
825                 [&image](GraphicsContext& context)
826                 {
827                     IntRect rect { { }, IntSize { image.size() } };
828                     context.drawImage(image, rect, rect, ImagePaintingOptions(CompositeCopy));
829                 });
830             layerState.nativeImageID = nativeImageID;
831             layerState.update.buffer = WTFMove(buffer);
832             m_nicosia.delta.imageBackingChanged = true;
833         }
834     } else if (m_nicosia.imageBacking) {
835         auto& layerState = downcast<Nicosia::ImageBackingTextureMapperImpl>(m_nicosia.imageBacking->impl()).layerState();
836         layerState.update = Nicosia::ImageBackingTextureMapperImpl::Update { };
837         m_nicosia.imageBacking = nullptr;
838         m_nicosia.delta.imageBackingChanged = true;
839     }
840
841     {
842         m_nicosia.layer->updateState(
843             [this](Nicosia::CompositionLayer::LayerState& state)
844             {
845                 // OR the local delta value into the layer's pending state delta. After that,
846                 // go through each local change and update the pending state accordingly.
847                 auto& localDelta = m_nicosia.delta;
848                 state.delta.value |= localDelta.value;
849
850                 if (localDelta.positionChanged)
851                     state.position = m_adjustedPosition;
852                 if (localDelta.anchorPointChanged)
853                     state.anchorPoint = m_adjustedAnchorPoint;
854                 if (localDelta.sizeChanged)
855                     state.size = m_adjustedSize;
856
857                 if (localDelta.transformChanged)
858                     state.transform = transform();
859                 if (localDelta.childrenTransformChanged)
860                     state.childrenTransform = childrenTransform();
861
862                 if (localDelta.contentsRectChanged)
863                     state.contentsRect = contentsRect();
864                 if (localDelta.contentsTilingChanged) {
865                     state.contentsTilePhase = contentsTilePhase();
866                     state.contentsTileSize = contentsTileSize();
867                 }
868
869                 if (localDelta.opacityChanged)
870                     state.opacity = opacity();
871                 if (localDelta.solidColorChanged)
872                     state.solidColor = m_solidColor;
873
874                 if (localDelta.filtersChanged)
875                     state.filters = filters();
876                 if (localDelta.animationsChanged)
877                     state.animations = m_animations.getActiveAnimations();
878
879                 if (localDelta.childrenChanged) {
880                     state.children = WTF::map(children(),
881                         [](auto& child)
882                         {
883                             return downcast<CoordinatedGraphicsLayer>(child.get()).m_nicosia.layer;
884                         });
885                 }
886
887                 if (localDelta.maskChanged) {
888                     auto* mask = downcast<CoordinatedGraphicsLayer>(maskLayer());
889                     state.mask = mask ? mask->m_nicosia.layer : nullptr;
890                 }
891
892                 if (localDelta.replicaChanged) {
893                     auto* replica = downcast<CoordinatedGraphicsLayer>(replicaLayer());
894                     state.replica = replica ? replica->m_nicosia.layer : nullptr;
895                 }
896
897                 if (localDelta.flagsChanged) {
898                     state.flags.contentsOpaque = contentsOpaque();
899                     state.flags.drawsContent = drawsContent();
900                     state.flags.contentsVisible = contentsAreVisible();
901                     state.flags.backfaceVisible = backfaceVisibility();
902                     state.flags.masksToBounds = masksToBounds();
903                     state.flags.preserves3D = preserves3D();
904                 }
905
906                 if (localDelta.repaintCounterChanged)
907                     state.repaintCounter = m_nicosia.repaintCounter;
908                 if (localDelta.debugBorderChanged)
909                     state.debugBorder = m_nicosia.debugBorder;
910
911                 if (localDelta.backingStoreChanged)
912                     state.backingStore = m_nicosia.backingStore;
913                 if (localDelta.contentLayerChanged)
914                     state.contentLayer = m_nicosia.contentLayer;
915                 if (localDelta.imageBackingChanged)
916                     state.imageBacking = m_nicosia.imageBacking;
917                 if (localDelta.animatedBackingStoreClientChanged)
918                     state.animatedBackingStoreClient = m_nicosia.animatedBackingStoreClient;
919             });
920         m_nicosia.performLayerSync = !!m_nicosia.delta.value;
921         m_nicosia.delta = { };
922     }
923 }
924
925 void CoordinatedGraphicsLayer::syncPendingStateChangesIncludingSubLayers()
926 {
927     if (m_nicosia.performLayerSync)
928         m_coordinator->syncLayerState();
929     m_nicosia.performLayerSync = false;
930
931     if (maskLayer())
932         downcast<CoordinatedGraphicsLayer>(*maskLayer()).syncPendingStateChangesIncludingSubLayers();
933
934     for (auto& child : children())
935         downcast<CoordinatedGraphicsLayer>(child.get()).syncPendingStateChangesIncludingSubLayers();
936 }
937
938 void CoordinatedGraphicsLayer::deviceOrPageScaleFactorChanged()
939 {
940     if (shouldHaveBackingStore())
941         m_pendingContentsScaleAdjustment = true;
942 }
943
944 float CoordinatedGraphicsLayer::effectiveContentsScale()
945 {
946     return selfOrAncestorHaveNonAffineTransforms() ? 1 : deviceScaleFactor() * pageScaleFactor();
947 }
948
949 IntRect CoordinatedGraphicsLayer::transformedVisibleRect()
950 {
951     // Non-invertible layers are not visible.
952     if (!m_layerTransform.combined().isInvertible())
953         return IntRect();
954
955     // Return a projection of the visible rect (surface coordinates) onto the layer's plane (layer coordinates).
956     // The resulting quad might be squewed and the visible rect is the bounding box of this quad,
957     // so it might spread further than the real visible area (and then even more amplified by the cover rect multiplier).
958     ASSERT(m_cachedInverseTransform == m_layerTransform.combined().inverse().valueOr(TransformationMatrix()));
959     FloatRect rect = m_cachedInverseTransform.clampedBoundsOfProjectedQuad(FloatQuad(m_coordinator->visibleContentsRect()));
960     clampToContentsRectIfRectIsInfinite(rect, size());
961     return enclosingIntRect(rect);
962 }
963
964 void CoordinatedGraphicsLayer::requestBackingStoreUpdate()
965 {
966     setNeedsVisibleRectAdjustment();
967     notifyFlushRequired();
968 }
969
970 void CoordinatedGraphicsLayer::updateContentBuffersIncludingSubLayers()
971 {
972     if (CoordinatedGraphicsLayer* mask = downcast<CoordinatedGraphicsLayer>(maskLayer()))
973         mask->updateContentBuffers();
974
975     if (CoordinatedGraphicsLayer* replica = downcast<CoordinatedGraphicsLayer>(replicaLayer()))
976         replica->updateContentBuffers();
977
978     updateContentBuffers();
979
980     for (auto& child : children())
981         downcast<CoordinatedGraphicsLayer>(child.get()).updateContentBuffersIncludingSubLayers();
982 }
983
984 void CoordinatedGraphicsLayer::updateContentBuffers()
985 {
986     if (!m_nicosia.backingStore)
987         return;
988
989     // Prepare for painting on the impl-contained backing store. isFlushing is used there
990     // for internal sanity checks.
991     auto& impl = downcast<Nicosia::BackingStoreTextureMapperImpl>(m_nicosia.backingStore->impl());
992     auto& layerState = impl.layerState();
993     layerState.isFlushing = true;
994
995     // Helper lambda that finished the flush update and determines layer sync necessity.
996     auto finishUpdate =
997         [this, &layerState] {
998             auto& update = layerState.update;
999             m_nicosia.performLayerSync |= !update.tilesToCreate.isEmpty()
1000                 || !update.tilesToRemove.isEmpty() || !update.tilesToUpdate.isEmpty();
1001             layerState.isFlushing = false;
1002         };
1003
1004     // Address the content scale adjustment.
1005     if (m_pendingContentsScaleAdjustment) {
1006         if (layerState.mainBackingStore && layerState.mainBackingStore->contentsScale() != effectiveContentsScale()) {
1007             // Discard the TiledBackingStore object to reconstruct it with new content scale.
1008             layerState.mainBackingStore = nullptr;
1009         }
1010         m_pendingContentsScaleAdjustment = false;
1011     }
1012
1013     // Ensure the TiledBackingStore object, and enforce a complete repaint if it's not been present yet.
1014     if (!layerState.mainBackingStore) {
1015         layerState.mainBackingStore = makeUnique<TiledBackingStore>(impl, effectiveContentsScale());
1016         m_pendingVisibleRectAdjustment = true;
1017     }
1018
1019     // Bail if there's no painting recorded or enforced.
1020     if (!m_pendingVisibleRectAdjustment && !m_needsDisplay.completeLayer && m_needsDisplay.rects.isEmpty()) {
1021         finishUpdate();
1022         return;
1023     }
1024
1025     if (!m_needsDisplay.completeLayer) {
1026         for (auto& rect : m_needsDisplay.rects)
1027             layerState.mainBackingStore->invalidate(enclosingIntRect(rect));
1028     } else
1029         layerState.mainBackingStore->invalidate({ { }, IntSize { m_size } });
1030
1031     m_needsDisplay.completeLayer = false;
1032     m_needsDisplay.rects.clear();
1033
1034     if (m_pendingVisibleRectAdjustment) {
1035         m_pendingVisibleRectAdjustment = false;
1036         layerState.mainBackingStore->createTilesIfNeeded(transformedVisibleRect(), IntRect(0, 0, m_size.width(), m_size.height()));
1037     }
1038
1039     if (is<CoordinatedAnimatedBackingStoreClient>(m_nicosia.animatedBackingStoreClient)) {
1040         // Determine the coverRect and set it to the client.
1041         downcast<CoordinatedAnimatedBackingStoreClient>(*m_nicosia.animatedBackingStoreClient).setCoverRect(layerState.mainBackingStore->coverRect());
1042     }
1043
1044     ASSERT(m_coordinator && m_coordinator->isFlushingLayerChanges());
1045
1046     // With all the affected tiles created and/or invalidated, we can finally paint them.
1047     auto dirtyTiles = layerState.mainBackingStore->dirtyTiles();
1048     if (!dirtyTiles.isEmpty()) {
1049         bool didUpdateTiles = false;
1050
1051         for (auto& tileReference : dirtyTiles) {
1052             auto& tile = tileReference.get();
1053             tile.ensureTileID();
1054
1055             auto& tileRect = tile.rect();
1056             auto& dirtyRect = tile.dirtyRect();
1057
1058             auto coordinatedBuffer = Nicosia::Buffer::create(dirtyRect.size(), contentsOpaque() ? Nicosia::Buffer::NoFlags : Nicosia::Buffer::SupportsAlpha);
1059             SurfaceUpdateInfo updateInfo;
1060             updateInfo.updateRect = dirtyRect;
1061             updateInfo.updateRect.move(-tileRect.x(), -tileRect.y());
1062             updateInfo.buffer = coordinatedBuffer.copyRef();
1063
1064             if (!m_coordinator->paintingEngine().paint(*this, WTFMove(coordinatedBuffer),
1065                 dirtyRect, layerState.mainBackingStore->mapToContents(dirtyRect),
1066                 IntRect { { 0, 0 }, dirtyRect.size() }, layerState.mainBackingStore->contentsScale()))
1067                 continue;
1068
1069             impl.updateTile(tile.tileID(), updateInfo, tileRect);
1070
1071             tile.markClean();
1072             didUpdateTiles |= true;
1073         }
1074
1075         if (didUpdateTiles)
1076             didUpdateTileBuffers();
1077     }
1078
1079     // Request a new update immediately if some tiles are still pending creation. Do this on a timer
1080     // as we're in a layer flush and flush requests at this point would be discarded.
1081     if (layerState.hasPendingTileCreation) {
1082         setNeedsVisibleRectAdjustment();
1083         m_requestPendingTileCreationTimer.startOneShot(0_s);
1084     }
1085
1086     finishUpdate();
1087 }
1088
1089 void CoordinatedGraphicsLayer::purgeBackingStores()
1090 {
1091 #ifndef NDEBUG
1092     SetForScope<bool> updateModeProtector(m_isPurging, true);
1093 #endif
1094     if (m_nicosia.backingStore) {
1095         auto& layerState = downcast<Nicosia::BackingStoreTextureMapperImpl>(m_nicosia.backingStore->impl()).layerState();
1096         layerState.isPurging = true;
1097         layerState.mainBackingStore = nullptr;
1098
1099         m_nicosia.backingStore = nullptr;
1100     }
1101
1102     if (m_nicosia.imageBacking) {
1103         auto& layerState = downcast<Nicosia::ImageBackingTextureMapperImpl>(m_nicosia.imageBacking->impl()).layerState();
1104         layerState.imageID = 0;
1105         layerState.nativeImageID = 0;
1106         layerState.update = { };
1107
1108         m_nicosia.imageBacking = nullptr;
1109     }
1110
1111     notifyFlushRequired();
1112 }
1113
1114 void CoordinatedGraphicsLayer::setCoordinator(CoordinatedGraphicsLayerClient* coordinator)
1115 {
1116     m_coordinator = coordinator;
1117 }
1118
1119 void CoordinatedGraphicsLayer::setCoordinatorIncludingSubLayersIfNeeded(CoordinatedGraphicsLayerClient* coordinator)
1120 {
1121     if (!coordinator || m_coordinator == coordinator)
1122         return;
1123
1124     // If the coordinators are different it means that we are attaching a layer that was created by a different
1125     // CompositingCoordinator than the current one. This happens because the layer was taken out of the tree
1126     // and then added back after AC was disabled and enabled again. We need to set the new coordinator to the
1127     // layer and its children.
1128     //
1129     // During each layer flush, the state stores the values that have changed since the previous one, and these
1130     // are updated once in the scene. When adding CoordinatedGraphicsLayers back to the tree, the fields that
1131     // are not updated during the next flush won't be sent to the scene, so they won't be updated there and the
1132     // rendering will fail.
1133     //
1134     // For example the drawsContent flag. This is set when the layer is created and is not updated anymore (unless
1135     // the content changes). When the layer is added back to the tree, the state won't reflect any change in the
1136     // flag value, so the scene won't update it and the layer won't be rendered.
1137     //
1138     // We need to update here the layer changeMask so the scene gets all the current values.
1139     m_nicosia.delta.value = UINT_MAX;
1140
1141     coordinator->attachLayer(this);
1142     for (auto& child : children())
1143         downcast<CoordinatedGraphicsLayer>(child.get()).setCoordinatorIncludingSubLayersIfNeeded(coordinator);
1144 }
1145
1146 const RefPtr<Nicosia::CompositionLayer>& CoordinatedGraphicsLayer::compositionLayer() const
1147 {
1148     return m_nicosia.layer;
1149 }
1150
1151 void CoordinatedGraphicsLayer::setNeedsVisibleRectAdjustment()
1152 {
1153     if (shouldHaveBackingStore())
1154         m_pendingVisibleRectAdjustment = true;
1155 }
1156
1157 static inline bool isIntegral(float value)
1158 {
1159     return static_cast<int>(value) == value;
1160 }
1161
1162 FloatPoint CoordinatedGraphicsLayer::computePositionRelativeToBase()
1163 {
1164     FloatPoint offset;
1165     for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent())
1166         offset += (currLayer->position() - currLayer->boundsOrigin());
1167
1168     return offset;
1169 }
1170
1171 void CoordinatedGraphicsLayer::computePixelAlignment(FloatPoint& position, FloatSize& size, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset)
1172 {
1173     if (isIntegral(effectiveContentsScale())) {
1174         position = m_position;
1175         size = m_size;
1176         anchorPoint = m_anchorPoint;
1177         alignmentOffset = FloatSize();
1178         return;
1179     }
1180
1181     FloatPoint positionRelativeToBase = computePositionRelativeToBase();
1182
1183     FloatRect baseRelativeBounds(positionRelativeToBase, m_size);
1184     FloatRect scaledBounds = baseRelativeBounds;
1185
1186     // Scale by the effective scale factor to compute the screen-relative bounds.
1187     scaledBounds.scale(effectiveContentsScale());
1188
1189     // Round to integer boundaries.
1190     // NOTE: When using enclosingIntRect (as mac) it will have different sizes depending on position.
1191     FloatRect alignedBounds = enclosingIntRect(scaledBounds);
1192
1193     // Convert back to layer coordinates.
1194     alignedBounds.scale(1 / effectiveContentsScale());
1195
1196     // Convert back to layer coordinates.
1197     alignmentOffset = baseRelativeBounds.location() - alignedBounds.location();
1198
1199     position = m_position - alignmentOffset;
1200     size = alignedBounds.size();
1201
1202     // Now we have to compute a new anchor point which compensates for rounding.
1203     float anchorPointX = m_anchorPoint.x();
1204     float anchorPointY = m_anchorPoint.y();
1205
1206     if (alignedBounds.width())
1207         anchorPointX = (baseRelativeBounds.width() * anchorPointX + alignmentOffset.width()) / alignedBounds.width();
1208
1209     if (alignedBounds.height())
1210         anchorPointY = (baseRelativeBounds.height() * anchorPointY + alignmentOffset.height()) / alignedBounds.height();
1211
1212     anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * effectiveContentsScale());
1213 }
1214
1215 void CoordinatedGraphicsLayer::computeTransformedVisibleRect()
1216 {
1217     if (!m_shouldUpdateVisibleRect && !m_movingVisibleRect)
1218         return;
1219
1220     m_shouldUpdateVisibleRect = false;
1221     TransformationMatrix currentTransform = transform();
1222     if (m_movingVisibleRect)
1223         client().getCurrentTransform(this, currentTransform);
1224     m_layerTransform.setLocalTransform(currentTransform);
1225
1226     m_layerTransform.setAnchorPoint(m_adjustedAnchorPoint);
1227     m_layerTransform.setPosition(m_adjustedPosition);
1228     m_layerTransform.setSize(m_adjustedSize);
1229
1230     m_layerTransform.setFlattening(!preserves3D());
1231     m_layerTransform.setChildrenTransform(childrenTransform());
1232     m_layerTransform.combineTransforms(parent() ? downcast<CoordinatedGraphicsLayer>(*parent()).m_layerTransform.combinedForChildren() : TransformationMatrix());
1233
1234     m_cachedInverseTransform = m_layerTransform.combined().inverse().valueOr(TransformationMatrix());
1235
1236     // The combined transform will be used in tiledBackingStoreVisibleRect.
1237     setNeedsVisibleRectAdjustment();
1238 }
1239
1240 bool CoordinatedGraphicsLayer::shouldHaveBackingStore() const
1241 {
1242     return drawsContent() && contentsAreVisible() && !m_size.isEmpty()
1243         && (!!opacity() || m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity));
1244 }
1245
1246 bool CoordinatedGraphicsLayer::selfOrAncestorHasActiveTransformAnimation() const
1247 {
1248     if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyTransform))
1249         return true;
1250
1251     if (!parent())
1252         return false;
1253
1254     return downcast<CoordinatedGraphicsLayer>(*parent()).selfOrAncestorHasActiveTransformAnimation();
1255 }
1256
1257 bool CoordinatedGraphicsLayer::selfOrAncestorHaveNonAffineTransforms()
1258 {
1259     if (!m_layerTransform.combined().isAffine())
1260         return true;
1261
1262     if (!parent())
1263         return false;
1264
1265     return downcast<CoordinatedGraphicsLayer>(*parent()).selfOrAncestorHaveNonAffineTransforms();
1266 }
1267
1268 bool CoordinatedGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double delayAsNegativeTimeOffset)
1269 {
1270     ASSERT(!keyframesName.isEmpty());
1271
1272     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyTransform && valueList.property() != AnimatedPropertyOpacity && valueList.property() != AnimatedPropertyFilter))
1273         return false;
1274
1275     if (valueList.property() == AnimatedPropertyFilter) {
1276         int listIndex = validateFilterOperations(valueList);
1277         if (listIndex < 0)
1278             return false;
1279
1280         const auto& filters = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
1281         if (!filtersCanBeComposited(filters))
1282             return false;
1283     }
1284
1285     bool listsMatch = false;
1286     bool ignoredHasBigRotation;
1287
1288     if (valueList.property() == AnimatedPropertyTransform)
1289         listsMatch = validateTransformOperations(valueList, ignoredHasBigRotation) >= 0;
1290
1291     m_lastAnimationStartTime = MonotonicTime::now() - Seconds(delayAsNegativeTimeOffset);
1292     m_animations.add(Nicosia::Animation(keyframesName, valueList, boxSize, *anim, listsMatch, m_lastAnimationStartTime, 0_s, Nicosia::Animation::AnimationState::Playing));
1293     m_animationStartedTimer.startOneShot(0_s);
1294     didChangeAnimations();
1295     return true;
1296 }
1297
1298 void CoordinatedGraphicsLayer::pauseAnimation(const String& animationName, double time)
1299 {
1300     m_animations.pause(animationName, Seconds(time));
1301     didChangeAnimations();
1302 }
1303
1304 void CoordinatedGraphicsLayer::removeAnimation(const String& animationName)
1305 {
1306     m_animations.remove(animationName);
1307     didChangeAnimations();
1308 }
1309
1310 void CoordinatedGraphicsLayer::suspendAnimations(MonotonicTime time)
1311 {
1312     m_animations.suspend(time);
1313     didChangeAnimations();
1314 }
1315
1316 void CoordinatedGraphicsLayer::resumeAnimations()
1317 {
1318     m_animations.resume();
1319     didChangeAnimations();
1320 }
1321
1322 void CoordinatedGraphicsLayer::animationStartedTimerFired()
1323 {
1324     client().notifyAnimationStarted(this, "", m_lastAnimationStartTime);
1325 }
1326
1327 void CoordinatedGraphicsLayer::requestPendingTileCreationTimerFired()
1328 {
1329     notifyFlushRequired();
1330 }
1331
1332 bool CoordinatedGraphicsLayer::usesContentsLayer() const
1333 {
1334     return m_nicosia.contentLayer || m_compositedImage;
1335 }
1336
1337 #if USE(NICOSIA)
1338 PlatformLayer* CoordinatedGraphicsLayer::platformLayer() const
1339 {
1340     return m_nicosia.layer.get();
1341 }
1342 #endif
1343
1344 } // namespace WebCore
1345
1346 SPECIALIZE_TYPE_TRAITS_ANIMATEDBACKINGSTORECLIENT(WebCore::CoordinatedAnimatedBackingStoreClient, type() == Nicosia::AnimatedBackingStoreClient::Type::Coordinated)
1347
1348 #endif // USE(COORDINATED_GRAPHICS)