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