Stop using PassRefPtr in platform/graphics
[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 "ScrollableArea.h"
34 #include <wtf/CurrentTime.h>
35 #ifndef NDEBUG
36 #include <wtf/SetForScope.h>
37 #endif
38 #include <wtf/text/CString.h>
39
40 namespace WebCore {
41
42 std::unique_ptr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client, Type layerType)
43 {
44     if (!factory)
45         return std::make_unique<CoordinatedGraphicsLayer>(layerType, client);
46
47     return factory->createGraphicsLayer(layerType, client);
48 }
49
50 static CoordinatedLayerID toCoordinatedLayerID(GraphicsLayer* layer)
51 {
52     return is<CoordinatedGraphicsLayer>(layer) ? downcast<CoordinatedGraphicsLayer>(*layer).id() : 0;
53 }
54
55 void CoordinatedGraphicsLayer::notifyFlushRequired()
56 {
57     if (!m_coordinator)
58         return;
59
60     if (m_coordinator->isFlushingLayerChanges())
61         return;
62
63     client().notifyFlushRequired(this);
64 }
65
66 void CoordinatedGraphicsLayer::didChangeLayerState()
67 {
68     m_shouldSyncLayerState = true;
69     notifyFlushRequired();
70 }
71
72 void CoordinatedGraphicsLayer::didChangeAnimations()
73 {
74     m_shouldSyncAnimations = true;
75     notifyFlushRequired();
76 }
77
78 void CoordinatedGraphicsLayer::didChangeChildren()
79 {
80     m_shouldSyncChildren = true;
81     notifyFlushRequired();
82 }
83
84 void CoordinatedGraphicsLayer::didChangeFilters()
85 {
86     m_shouldSyncFilters = true;
87     notifyFlushRequired();
88 }
89
90 void CoordinatedGraphicsLayer::didChangeImageBacking()
91 {
92     m_shouldSyncImageBacking = true;
93     notifyFlushRequired();
94 }
95
96 void CoordinatedGraphicsLayer::setShouldUpdateVisibleRect()
97 {
98     m_shouldUpdateVisibleRect = true;
99     for (auto& child : children())
100         downcast<CoordinatedGraphicsLayer>(*child).setShouldUpdateVisibleRect();
101     if (replicaLayer())
102         downcast<CoordinatedGraphicsLayer>(*replicaLayer()).setShouldUpdateVisibleRect();
103 }
104
105 void CoordinatedGraphicsLayer::didChangeGeometry()
106 {
107     didChangeLayerState();
108     setShouldUpdateVisibleRect();
109 }
110
111 CoordinatedGraphicsLayer::CoordinatedGraphicsLayer(Type layerType, GraphicsLayerClient& client)
112     : GraphicsLayer(layerType, client)
113 #ifndef NDEBUG
114     , m_isPurging(false)
115 #endif
116     , m_shouldUpdateVisibleRect(true)
117     , m_shouldSyncLayerState(true)
118     , m_shouldSyncChildren(true)
119     , m_shouldSyncFilters(true)
120     , m_shouldSyncImageBacking(true)
121     , m_shouldSyncAnimations(true)
122     , m_fixedToViewport(false)
123     , m_movingVisibleRect(false)
124     , m_pendingContentsScaleAdjustment(false)
125     , m_pendingVisibleRectAdjustment(false)
126 #if USE(COORDINATED_GRAPHICS_THREADED)
127     , m_shouldSyncPlatformLayer(false)
128     , m_shouldUpdatePlatformLayer(false)
129 #endif
130     , m_coordinator(0)
131     , m_compositedNativeImagePtr(0)
132     , m_platformLayer(0)
133     , m_animationStartedTimer(*this, &CoordinatedGraphicsLayer::animationStartedTimerFired)
134     , m_scrollableArea(0)
135 {
136     static CoordinatedLayerID nextLayerID = 1;
137     m_id = nextLayerID++;
138 }
139
140 CoordinatedGraphicsLayer::~CoordinatedGraphicsLayer()
141 {
142     if (m_coordinator) {
143         purgeBackingStores();
144         m_coordinator->detachLayer(this);
145     }
146     ASSERT(!m_coordinatedImageBacking);
147     ASSERT(!m_mainBackingStore);
148     willBeDestroyed();
149 }
150
151 bool CoordinatedGraphicsLayer::setChildren(const Vector<GraphicsLayer*>& children)
152 {
153     bool ok = GraphicsLayer::setChildren(children);
154     if (!ok)
155         return false;
156     didChangeChildren();
157     return true;
158 }
159
160 void CoordinatedGraphicsLayer::addChild(GraphicsLayer* layer)
161 {
162     GraphicsLayer::addChild(layer);
163     didChangeChildren();
164 }
165
166 void CoordinatedGraphicsLayer::addChildAtIndex(GraphicsLayer* layer, int index)
167 {
168     GraphicsLayer::addChildAtIndex(layer, index);
169     didChangeChildren();
170 }
171
172 void CoordinatedGraphicsLayer::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
173 {
174     GraphicsLayer::addChildAbove(layer, sibling);
175     didChangeChildren();
176 }
177
178 void CoordinatedGraphicsLayer::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
179 {
180     GraphicsLayer::addChildBelow(layer, sibling);
181     didChangeChildren();
182 }
183
184 bool CoordinatedGraphicsLayer::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
185 {
186     bool ok = GraphicsLayer::replaceChild(oldChild, newChild);
187     if (!ok)
188         return false;
189     didChangeChildren();
190     return true;
191 }
192
193 void CoordinatedGraphicsLayer::removeFromParent()
194 {
195     if (CoordinatedGraphicsLayer* parentLayer = downcast<CoordinatedGraphicsLayer>(parent()))
196         parentLayer->didChangeChildren();
197     GraphicsLayer::removeFromParent();
198 }
199
200 void CoordinatedGraphicsLayer::setPosition(const FloatPoint& p)
201 {
202     if (position() == p)
203         return;
204
205     GraphicsLayer::setPosition(p);
206     m_layerState.positionChanged = true;
207     didChangeGeometry();
208 }
209
210 void CoordinatedGraphicsLayer::setAnchorPoint(const FloatPoint3D& p)
211 {
212     if (anchorPoint() == p)
213         return;
214
215     GraphicsLayer::setAnchorPoint(p);
216     m_layerState.anchorPointChanged = true;
217     didChangeGeometry();
218 }
219
220 void CoordinatedGraphicsLayer::setSize(const FloatSize& size)
221 {
222     if (this->size() == size)
223         return;
224
225     GraphicsLayer::setSize(size);
226     m_layerState.sizeChanged = true;
227
228     if (maskLayer())
229         maskLayer()->setSize(size);
230     didChangeGeometry();
231 }
232
233 void CoordinatedGraphicsLayer::setTransform(const TransformationMatrix& t)
234 {
235     if (transform() == t)
236         return;
237
238     GraphicsLayer::setTransform(t);
239     m_layerState.transformChanged = true;
240
241     didChangeGeometry();
242 }
243
244 void CoordinatedGraphicsLayer::setChildrenTransform(const TransformationMatrix& t)
245 {
246     if (childrenTransform() == t)
247         return;
248
249     GraphicsLayer::setChildrenTransform(t);
250     m_layerState.childrenTransformChanged = true;
251
252     didChangeGeometry();
253 }
254
255 void CoordinatedGraphicsLayer::setPreserves3D(bool b)
256 {
257     if (preserves3D() == b)
258         return;
259
260     GraphicsLayer::setPreserves3D(b);
261     m_layerState.preserves3D = b;
262     m_layerState.flagsChanged = true;
263
264     didChangeGeometry();
265 }
266
267 void CoordinatedGraphicsLayer::setMasksToBounds(bool b)
268 {
269     if (masksToBounds() == b)
270         return;
271     GraphicsLayer::setMasksToBounds(b);
272     m_layerState.masksToBounds = b;
273     m_layerState.flagsChanged = true;
274
275     didChangeGeometry();
276 }
277
278 void CoordinatedGraphicsLayer::setDrawsContent(bool b)
279 {
280     if (drawsContent() == b)
281         return;
282     GraphicsLayer::setDrawsContent(b);
283     m_layerState.drawsContent = b;
284     m_layerState.flagsChanged = true;
285
286     didChangeLayerState();
287 }
288
289 void CoordinatedGraphicsLayer::setContentsVisible(bool b)
290 {
291     if (contentsAreVisible() == b)
292         return;
293     GraphicsLayer::setContentsVisible(b);
294     m_layerState.contentsVisible = b;
295     m_layerState.flagsChanged = true;
296
297     if (maskLayer())
298         maskLayer()->setContentsVisible(b);
299
300     didChangeLayerState();
301 }
302
303 void CoordinatedGraphicsLayer::setContentsOpaque(bool b)
304 {
305     if (contentsOpaque() == b)
306         return;
307     if (m_mainBackingStore)
308         m_mainBackingStore->setSupportsAlpha(!b);
309     GraphicsLayer::setContentsOpaque(b);
310     m_layerState.contentsOpaque = b;
311     m_layerState.flagsChanged = true;
312
313     didChangeLayerState();
314 }
315
316 void CoordinatedGraphicsLayer::setBackfaceVisibility(bool b)
317 {
318     if (backfaceVisibility() == b)
319         return;
320
321     GraphicsLayer::setBackfaceVisibility(b);
322     m_layerState.backfaceVisible = b;
323     m_layerState.flagsChanged = true;
324
325     didChangeLayerState();
326 }
327
328 void CoordinatedGraphicsLayer::setOpacity(float opacity)
329 {
330     if (this->opacity() == opacity)
331         return;
332
333     GraphicsLayer::setOpacity(opacity);
334     m_layerState.opacity = opacity;
335     m_layerState.opacityChanged = true;
336
337     didChangeLayerState();
338 }
339
340 void CoordinatedGraphicsLayer::setContentsRect(const FloatRect& r)
341 {
342     if (contentsRect() == r)
343         return;
344
345     GraphicsLayer::setContentsRect(r);
346     m_layerState.contentsRect = r;
347     m_layerState.contentsRectChanged = true;
348
349     didChangeLayerState();
350 }
351
352 void CoordinatedGraphicsLayer::setContentsTileSize(const FloatSize& s)
353 {
354     if (contentsTileSize() == s)
355         return;
356
357     GraphicsLayer::setContentsTileSize(s);
358     m_layerState.contentsTileSize = s;
359     m_layerState.contentsTilingChanged = true;
360     didChangeLayerState();
361 }
362
363 void CoordinatedGraphicsLayer::setContentsTilePhase(const FloatSize& p)
364 {
365     if (contentsTilePhase() == p)
366         return;
367
368     GraphicsLayer::setContentsTilePhase(p);
369     m_layerState.contentsTilePhase = p;
370     m_layerState.contentsTilingChanged = true;
371     didChangeLayerState();
372 }
373
374 bool GraphicsLayer::supportsContentsTiling()
375 {
376     return true;
377 }
378
379 void CoordinatedGraphicsLayer::setContentsNeedsDisplay()
380 {
381 #if USE(COORDINATED_GRAPHICS_THREADED)
382     if (m_platformLayer)
383         m_shouldUpdatePlatformLayer = true;
384 #endif
385
386     notifyFlushRequired();
387     addRepaintRect(contentsRect());
388 }
389
390 void CoordinatedGraphicsLayer::setContentsToPlatformLayer(PlatformLayer* platformLayer, ContentsLayerPurpose)
391 {
392 #if USE(COORDINATED_GRAPHICS_THREADED)
393     if (m_platformLayer != platformLayer)
394         m_shouldSyncPlatformLayer = true;
395
396     m_platformLayer = platformLayer;
397     notifyFlushRequired();
398 #else
399     UNUSED_PARAM(platformLayer);
400 #endif
401 }
402
403 bool CoordinatedGraphicsLayer::filtersCanBeComposited(const FilterOperations& filters) const
404 {
405     if (!filters.size())
406         return false;
407
408     for (const auto& filterOperation : filters.operations()) {
409         if (filterOperation->type() == FilterOperation::REFERENCE)
410             return false;
411     }
412
413     return true;
414 }
415
416 bool CoordinatedGraphicsLayer::setFilters(const FilterOperations& newFilters)
417 {
418     bool canCompositeFilters = filtersCanBeComposited(newFilters);
419     if (filters() == newFilters)
420         return canCompositeFilters;
421
422     if (canCompositeFilters) {
423         if (!GraphicsLayer::setFilters(newFilters))
424             return false;
425         didChangeFilters();
426     } else if (filters().size()) {
427         clearFilters();
428         didChangeFilters();
429     }
430
431     return canCompositeFilters;
432 }
433
434 void CoordinatedGraphicsLayer::setContentsToSolidColor(const Color& color)
435 {
436     if (m_layerState.solidColor == color)
437         return;
438
439     m_layerState.solidColor = color;
440     m_layerState.solidColorChanged = true;
441
442     didChangeLayerState();
443 }
444
445 void CoordinatedGraphicsLayer::setShowDebugBorder(bool show)
446 {
447     if (isShowingDebugBorder() == show)
448         return;
449
450     GraphicsLayer::setShowDebugBorder(show);
451     m_layerState.debugVisuals.showDebugBorders = show;
452     m_layerState.debugVisualsChanged = true;
453
454     didChangeLayerState();
455 }
456
457 void CoordinatedGraphicsLayer::setShowRepaintCounter(bool show)
458 {
459     if (isShowingRepaintCounter() == show)
460         return;
461
462     GraphicsLayer::setShowRepaintCounter(show);
463     m_layerState.debugVisuals.showRepaintCounter = show;
464     m_layerState.debugVisualsChanged = true;
465
466     didChangeLayerState();
467 }
468
469 void CoordinatedGraphicsLayer::setContentsToImage(Image* image)
470 {
471     NativeImagePtr nativeImagePtr = image ? image->nativeImageForCurrentFrame() : nullptr;
472     if (m_compositedImage == image && m_compositedNativeImagePtr == nativeImagePtr)
473         return;
474
475     m_compositedImage = image;
476     m_compositedNativeImagePtr = nativeImagePtr;
477
478     GraphicsLayer::setContentsToImage(image);
479     didChangeImageBacking();
480 }
481
482 void CoordinatedGraphicsLayer::setMaskLayer(GraphicsLayer* layer)
483 {
484     if (layer == maskLayer())
485         return;
486
487     GraphicsLayer::setMaskLayer(layer);
488
489     if (!layer)
490         return;
491
492     layer->setSize(size());
493     layer->setContentsVisible(contentsAreVisible());
494     auto& coordinatedLayer = downcast<CoordinatedGraphicsLayer>(*layer);
495     coordinatedLayer.didChangeLayerState();
496
497     m_layerState.mask = coordinatedLayer.id();
498     m_layerState.maskChanged = true;
499
500     didChangeLayerState();
501 }
502
503 bool CoordinatedGraphicsLayer::shouldDirectlyCompositeImage(Image* image) const
504 {
505     if (!image || !image->isBitmapImage())
506         return false;
507
508     enum { MaxDimenstionForDirectCompositing = 2000 };
509     if (image->width() > MaxDimenstionForDirectCompositing || image->height() > MaxDimenstionForDirectCompositing)
510         return false;
511
512     return true;
513 }
514
515 void CoordinatedGraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
516 {
517     if (layer == replicaLayer())
518         return;
519
520     GraphicsLayer::setReplicatedByLayer(layer);
521     m_layerState.replica = toCoordinatedLayerID(layer);
522     m_layerState.replicaChanged = true;
523     didChangeLayerState();
524 }
525
526 void CoordinatedGraphicsLayer::setNeedsDisplay()
527 {
528     setNeedsDisplayInRect(FloatRect(FloatPoint(), size()));
529 }
530
531 void CoordinatedGraphicsLayer::setNeedsDisplayInRect(const FloatRect& rect, ShouldClipToLayer)
532 {
533     if (m_mainBackingStore)
534         m_mainBackingStore->invalidate(IntRect(rect));
535
536     didChangeLayerState();
537
538     addRepaintRect(rect);
539 }
540
541 void CoordinatedGraphicsLayer::setScrollableArea(ScrollableArea* scrollableArea)
542 {
543     bool oldScrollable = isScrollable();
544     m_scrollableArea = scrollableArea;
545     if (oldScrollable == isScrollable())
546         return;
547
548     m_layerState.isScrollable = isScrollable();
549     m_layerState.flagsChanged = true;
550     didChangeLayerState();
551 }
552
553 void CoordinatedGraphicsLayer::commitScrollOffset(const IntSize& offset)
554 {
555     if (!isScrollable() || offset.isZero())
556         return;
557
558     m_scrollableArea->notifyScrollPositionChanged(m_scrollableArea->scrollPosition() + offset);
559     m_layerState.committedScrollOffset += offset;
560     m_layerState.committedScrollOffsetChanged = true;
561     didChangeLayerState();
562 }
563
564 void CoordinatedGraphicsLayer::setFixedToViewport(bool isFixed)
565 {
566     if (m_fixedToViewport == isFixed)
567         return;
568
569     m_fixedToViewport = isFixed;
570     m_layerState.fixedToViewport = isFixed;
571     m_layerState.flagsChanged = true;
572
573     didChangeLayerState();
574 }
575
576 void CoordinatedGraphicsLayer::flushCompositingState(const FloatRect& rect)
577 {
578     if (CoordinatedGraphicsLayer* mask = downcast<CoordinatedGraphicsLayer>(maskLayer()))
579         mask->flushCompositingStateForThisLayerOnly();
580
581     if (CoordinatedGraphicsLayer* replica = downcast<CoordinatedGraphicsLayer>(replicaLayer()))
582         replica->flushCompositingStateForThisLayerOnly();
583
584     flushCompositingStateForThisLayerOnly();
585
586     for (auto& child : children())
587         child->flushCompositingState(rect);
588 }
589
590 void CoordinatedGraphicsLayer::syncChildren()
591 {
592     if (!m_shouldSyncChildren)
593         return;
594     m_shouldSyncChildren = false;
595     m_layerState.childrenChanged = true;
596     m_layerState.children.clear();
597     for (auto& child : children())
598         m_layerState.children.append(toCoordinatedLayerID(child));
599 }
600
601 void CoordinatedGraphicsLayer::syncFilters()
602 {
603     if (!m_shouldSyncFilters)
604         return;
605     m_shouldSyncFilters = false;
606
607     m_layerState.filters = GraphicsLayer::filters();
608     m_layerState.filtersChanged = true;
609 }
610
611 void CoordinatedGraphicsLayer::syncImageBacking()
612 {
613     if (!m_shouldSyncImageBacking)
614         return;
615     m_shouldSyncImageBacking = false;
616
617     if (m_compositedNativeImagePtr) {
618         ASSERT(!shouldHaveBackingStore());
619         ASSERT(m_compositedImage);
620
621         bool imageInstanceReplaced = m_coordinatedImageBacking && (m_coordinatedImageBacking->id() != CoordinatedImageBacking::getCoordinatedImageBackingID(m_compositedImage.get()));
622         if (imageInstanceReplaced)
623             releaseImageBackingIfNeeded();
624
625         if (!m_coordinatedImageBacking) {
626             m_coordinatedImageBacking = m_coordinator->createImageBackingIfNeeded(*m_compositedImage);
627             m_coordinatedImageBacking->addHost(this);
628             m_layerState.imageID = m_coordinatedImageBacking->id();
629         }
630
631         m_coordinatedImageBacking->markDirty();
632         m_layerState.imageChanged = true;
633     } else
634         releaseImageBackingIfNeeded();
635
636     // syncImageBacking() changed m_layerState.imageID.
637     didChangeLayerState();
638 }
639
640 void CoordinatedGraphicsLayer::syncLayerState()
641 {
642     if (!m_shouldSyncLayerState)
643         return;
644     m_shouldSyncLayerState = false;
645
646     m_layerState.childrenTransform = childrenTransform();
647     m_layerState.contentsRect = contentsRect();
648     m_layerState.mask = toCoordinatedLayerID(maskLayer());
649     m_layerState.opacity = opacity();
650     m_layerState.replica = toCoordinatedLayerID(replicaLayer());
651     m_layerState.transform = transform();
652
653     m_layerState.anchorPoint = m_adjustedAnchorPoint;
654     m_layerState.pos = m_adjustedPosition;
655     m_layerState.size = m_adjustedSize;
656
657     if (m_layerState.flagsChanged) {
658         m_layerState.contentsOpaque = contentsOpaque();
659         m_layerState.drawsContent = drawsContent();
660         m_layerState.contentsVisible = contentsAreVisible();
661         m_layerState.backfaceVisible = backfaceVisibility();
662         m_layerState.masksToBounds = masksToBounds();
663         m_layerState.preserves3D = preserves3D();
664         m_layerState.fixedToViewport = fixedToViewport();
665         m_layerState.isScrollable = isScrollable();
666     }
667
668     if (m_layerState.debugVisualsChanged) {
669         m_layerState.debugVisuals.showDebugBorders = isShowingDebugBorder();
670         m_layerState.debugVisuals.showRepaintCounter = isShowingRepaintCounter();
671     }
672
673     if (m_layerState.debugVisuals.showDebugBorders)
674         updateDebugIndicators();
675 }
676
677 void CoordinatedGraphicsLayer::setDebugBorder(const Color& color, float width)
678 {
679     ASSERT(m_layerState.debugVisuals.showDebugBorders);
680     if (m_layerState.debugVisuals.debugBorderColor != color) {
681         m_layerState.debugVisuals.debugBorderColor = color;
682         m_layerState.debugVisualsChanged = true;
683     }
684
685     if (m_layerState.debugVisuals.debugBorderWidth != width) {
686         m_layerState.debugVisuals.debugBorderWidth = width;
687         m_layerState.debugVisualsChanged = true;
688     }
689 }
690
691 void CoordinatedGraphicsLayer::syncAnimations()
692 {
693     if (!m_shouldSyncAnimations)
694         return;
695
696     m_shouldSyncAnimations = false;
697     m_layerState.animations = m_animations.getActiveAnimations();
698     m_layerState.animationsChanged = true;
699 }
700
701 void CoordinatedGraphicsLayer::syncPlatformLayer()
702 {
703 #if USE(COORDINATED_GRAPHICS_THREADED)
704     if (!m_shouldSyncPlatformLayer)
705         return;
706
707     m_shouldSyncPlatformLayer = false;
708     m_layerState.platformLayerChanged = true;
709     if (m_platformLayer)
710         m_layerState.platformLayerProxy = m_platformLayer->proxy();
711 #endif
712 }
713
714 void CoordinatedGraphicsLayer::updatePlatformLayer()
715 {
716 #if USE(COORDINATED_GRAPHICS_THREADED)
717     if (!m_shouldUpdatePlatformLayer)
718         return;
719
720     m_shouldUpdatePlatformLayer = false;
721     m_layerState.platformLayerUpdated = true;
722     if (m_platformLayer)
723         m_platformLayer->swapBuffersIfNeeded();
724 #endif
725 }
726
727 void CoordinatedGraphicsLayer::flushCompositingStateForThisLayerOnly()
728 {
729     // When we have a transform animation, we need to update visible rect every frame to adjust the visible rect of a backing store.
730     bool hasActiveTransformAnimation = selfOrAncestorHasActiveTransformAnimation();
731     if (hasActiveTransformAnimation)
732         m_movingVisibleRect = true;
733
734     // Sets the values.
735     computePixelAlignment(m_adjustedPosition, m_adjustedSize, m_adjustedAnchorPoint, m_pixelAlignmentOffset);
736
737     syncImageBacking();
738     syncLayerState();
739     syncAnimations();
740     computeTransformedVisibleRect();
741     syncChildren();
742     syncFilters();
743     syncPlatformLayer();
744     updatePlatformLayer();
745
746     // Only unset m_movingVisibleRect after we have updated the visible rect after the animation stopped.
747     if (!hasActiveTransformAnimation)
748         m_movingVisibleRect = false;
749 }
750
751 void CoordinatedGraphicsLayer::syncPendingStateChangesIncludingSubLayers()
752 {
753     if (m_layerState.hasPendingChanges()) {
754         m_coordinator->syncLayerState(m_id, m_layerState);
755         resetLayerState();
756     }
757
758     if (maskLayer())
759         downcast<CoordinatedGraphicsLayer>(*maskLayer()).syncPendingStateChangesIncludingSubLayers();
760
761     for (auto& child : children())
762         downcast<CoordinatedGraphicsLayer>(*child).syncPendingStateChangesIncludingSubLayers();
763 }
764
765 void CoordinatedGraphicsLayer::resetLayerState()
766 {
767     m_layerState.changeMask = 0;
768     m_layerState.tilesToCreate.clear();
769     m_layerState.tilesToRemove.clear();
770     m_layerState.tilesToUpdate.clear();
771     m_layerState.committedScrollOffset = IntSize();
772 }
773
774 bool CoordinatedGraphicsLayer::imageBackingVisible()
775 {
776     ASSERT(m_coordinatedImageBacking);
777     return transformedVisibleRect().intersects(IntRect(contentsRect()));
778 }
779
780 void CoordinatedGraphicsLayer::releaseImageBackingIfNeeded()
781 {
782     if (!m_coordinatedImageBacking)
783         return;
784
785     ASSERT(m_coordinator);
786     m_coordinatedImageBacking->removeHost(this);
787     m_coordinatedImageBacking = nullptr;
788     m_layerState.imageID = InvalidCoordinatedImageBackingID;
789     m_layerState.imageChanged = true;
790 }
791
792 CoordinatedGraphicsLayer* CoordinatedGraphicsLayer::findFirstDescendantWithContentsRecursively()
793 {
794     if (shouldHaveBackingStore())
795         return this;
796
797     for (auto& child : children()) {
798         if (CoordinatedGraphicsLayer* layer = downcast<CoordinatedGraphicsLayer>(*child).findFirstDescendantWithContentsRecursively())
799             return layer;
800     }
801
802     return nullptr;
803 }
804
805 void CoordinatedGraphicsLayer::setVisibleContentRectTrajectoryVector(const FloatPoint& trajectoryVector)
806 {
807     if (!m_mainBackingStore)
808         return;
809
810     m_mainBackingStore->setTrajectoryVector(trajectoryVector);
811     setNeedsVisibleRectAdjustment();
812 }
813
814 void CoordinatedGraphicsLayer::deviceOrPageScaleFactorChanged()
815 {
816     if (shouldHaveBackingStore())
817         m_pendingContentsScaleAdjustment = true;
818 }
819
820 float CoordinatedGraphicsLayer::effectiveContentsScale()
821 {
822     return selfOrAncestorHaveNonAffineTransforms() ? 1 : deviceScaleFactor() * pageScaleFactor();
823 }
824
825 void CoordinatedGraphicsLayer::adjustContentsScale()
826 {
827     ASSERT(shouldHaveBackingStore());
828     if (!m_mainBackingStore || m_mainBackingStore->contentsScale() == effectiveContentsScale())
829         return;
830
831     // Between creating the new backing store and painting the content,
832     // we do not want to drop the previous one as that might result in
833     // briefly seeing flickering as the old tiles may be dropped before
834     // something replaces them.
835     m_previousBackingStore = WTFMove(m_mainBackingStore);
836
837     // No reason to save the previous backing store for non-visible areas.
838     m_previousBackingStore->removeAllNonVisibleTiles(transformedVisibleRect(), IntRect(0, 0, size().width(), size().height()));
839 }
840
841 void CoordinatedGraphicsLayer::createBackingStore()
842 {
843     m_mainBackingStore = std::make_unique<TiledBackingStore>(this, effectiveContentsScale());
844     m_mainBackingStore->setSupportsAlpha(!contentsOpaque());
845 }
846
847 void CoordinatedGraphicsLayer::tiledBackingStorePaint(GraphicsContext& context, const IntRect& rect)
848 {
849     if (rect.isEmpty())
850         return;
851     paintGraphicsLayerContents(context, rect);
852 }
853
854 void CoordinatedGraphicsLayer::didUpdateTileBuffers()
855 {
856     if (!isShowingRepaintCounter())
857         return;
858
859     m_layerState.repaintCount = incrementRepaintCount();
860     m_layerState.repaintCountChanged = true;
861 }
862
863 void CoordinatedGraphicsLayer::tiledBackingStoreHasPendingTileCreation()
864 {
865     setNeedsVisibleRectAdjustment();
866     notifyFlushRequired();
867 }
868
869 static void clampToContentsRectIfRectIsInfinite(FloatRect& rect, const FloatSize& contentsSize)
870 {
871     if (rect.width() >= LayoutUnit::nearlyMax() || rect.width() <= LayoutUnit::nearlyMin()) {
872         rect.setX(0);
873         rect.setWidth(contentsSize.width());
874     }
875
876     if (rect.height() >= LayoutUnit::nearlyMax() || rect.height() <= LayoutUnit::nearlyMin()) {
877         rect.setY(0);
878         rect.setHeight(contentsSize.height());
879     }
880 }
881
882 IntRect CoordinatedGraphicsLayer::transformedVisibleRect()
883 {
884     // Non-invertible layers are not visible.
885     if (!m_layerTransform.combined().isInvertible())
886         return IntRect();
887
888     // Return a projection of the visible rect (surface coordinates) onto the layer's plane (layer coordinates).
889     // The resulting quad might be squewed and the visible rect is the bounding box of this quad,
890     // so it might spread further than the real visible area (and then even more amplified by the cover rect multiplier).
891     ASSERT(m_cachedInverseTransform == m_layerTransform.combined().inverse().value_or(TransformationMatrix()));
892     FloatRect rect = m_cachedInverseTransform.clampedBoundsOfProjectedQuad(FloatQuad(m_coordinator->visibleContentsRect()));
893     clampToContentsRectIfRectIsInfinite(rect, size());
894     return enclosingIntRect(rect);
895 }
896
897 bool CoordinatedGraphicsLayer::paintToSurface(const IntSize& size, uint32_t& atlas, IntPoint& offset, CoordinatedSurface::Client& client)
898 {
899     ASSERT(m_coordinator);
900     ASSERT(m_coordinator->isFlushingLayerChanges());
901     return m_coordinator->paintToSurface(size, contentsOpaque() ? CoordinatedSurface::NoFlags : CoordinatedSurface::SupportsAlpha, atlas, offset, client);
902 }
903
904 void CoordinatedGraphicsLayer::createTile(uint32_t tileID, float scaleFactor)
905 {
906     ASSERT(m_coordinator);
907     ASSERT(m_coordinator->isFlushingLayerChanges());
908
909     TileCreationInfo creationInfo;
910     creationInfo.tileID = tileID;
911     creationInfo.scale = scaleFactor;
912     m_layerState.tilesToCreate.append(creationInfo);
913 }
914
915 void CoordinatedGraphicsLayer::updateTile(uint32_t tileID, const SurfaceUpdateInfo& updateInfo, const IntRect& tileRect)
916 {
917     ASSERT(m_coordinator);
918     ASSERT(m_coordinator->isFlushingLayerChanges());
919
920     TileUpdateInfo tileUpdateInfo;
921     tileUpdateInfo.tileID = tileID;
922     tileUpdateInfo.tileRect = tileRect;
923     tileUpdateInfo.updateInfo = updateInfo;
924     m_layerState.tilesToUpdate.append(tileUpdateInfo);
925 }
926
927 void CoordinatedGraphicsLayer::removeTile(uint32_t tileID)
928 {
929     ASSERT(m_coordinator);
930     ASSERT(m_coordinator->isFlushingLayerChanges() || m_isPurging);
931     m_layerState.tilesToRemove.append(tileID);
932 }
933
934 void CoordinatedGraphicsLayer::updateContentBuffersIncludingSubLayers()
935 {
936     if (CoordinatedGraphicsLayer* mask = downcast<CoordinatedGraphicsLayer>(maskLayer()))
937         mask->updateContentBuffers();
938
939     if (CoordinatedGraphicsLayer* replica = downcast<CoordinatedGraphicsLayer>(replicaLayer()))
940         replica->updateContentBuffers();
941
942     updateContentBuffers();
943
944     for (auto& child : children())
945         downcast<CoordinatedGraphicsLayer>(*child).updateContentBuffersIncludingSubLayers();
946 }
947
948 void CoordinatedGraphicsLayer::updateContentBuffers()
949 {
950     if (!shouldHaveBackingStore()) {
951         m_mainBackingStore = nullptr;
952         m_previousBackingStore = nullptr;
953         return;
954     }
955
956     if (m_pendingContentsScaleAdjustment) {
957         adjustContentsScale();
958         m_pendingContentsScaleAdjustment = false;
959     }
960
961     // This is the only place we (re)create the main tiled backing store, once we
962     // have a remote client and we are ready to send our data to the UI process.
963     if (!m_mainBackingStore) {
964         createBackingStore();
965         m_pendingVisibleRectAdjustment = true;
966     }
967
968     if (m_pendingVisibleRectAdjustment) {
969         m_pendingVisibleRectAdjustment = false;
970         m_mainBackingStore->createTilesIfNeeded(transformedVisibleRect(), IntRect(0, 0, size().width(), size().height()));
971     }
972
973     m_mainBackingStore->updateTileBuffers();
974
975     // The previous backing store is kept around to avoid flickering between
976     // removing the existing tiles and painting the new ones. The first time
977     // the visibleRect is full painted we remove the previous backing store.
978     if (m_mainBackingStore->visibleAreaIsCovered())
979         m_previousBackingStore = nullptr;
980 }
981
982 void CoordinatedGraphicsLayer::purgeBackingStores()
983 {
984 #ifndef NDEBUG
985     SetForScope<bool> updateModeProtector(m_isPurging, true);
986 #endif
987     m_mainBackingStore = nullptr;
988     m_previousBackingStore = nullptr;
989
990     releaseImageBackingIfNeeded();
991
992     didChangeLayerState();
993 }
994
995 void CoordinatedGraphicsLayer::setCoordinator(CoordinatedGraphicsLayerClient* coordinator)
996 {
997     m_coordinator = coordinator;
998 }
999
1000 void CoordinatedGraphicsLayer::setNeedsVisibleRectAdjustment()
1001 {
1002     if (shouldHaveBackingStore())
1003         m_pendingVisibleRectAdjustment = true;
1004 }
1005
1006 static inline bool isIntegral(float value)
1007 {
1008     return static_cast<int>(value) == value;
1009 }
1010
1011 FloatPoint CoordinatedGraphicsLayer::computePositionRelativeToBase()
1012 {
1013     FloatPoint offset;
1014     for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent())
1015         offset += currLayer->position();
1016
1017     return offset;
1018 }
1019
1020 void CoordinatedGraphicsLayer::computePixelAlignment(FloatPoint& position, FloatSize& size, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset)
1021 {
1022     if (isIntegral(effectiveContentsScale())) {
1023         position = m_position;
1024         size = m_size;
1025         anchorPoint = m_anchorPoint;
1026         alignmentOffset = FloatSize();
1027         return;
1028     }
1029
1030     FloatPoint positionRelativeToBase = computePositionRelativeToBase();
1031
1032     FloatRect baseRelativeBounds(positionRelativeToBase, m_size);
1033     FloatRect scaledBounds = baseRelativeBounds;
1034
1035     // Scale by the effective scale factor to compute the screen-relative bounds.
1036     scaledBounds.scale(effectiveContentsScale());
1037
1038     // Round to integer boundaries.
1039     // NOTE: When using enclosingIntRect (as mac) it will have different sizes depending on position.
1040     FloatRect alignedBounds = enclosingIntRect(scaledBounds);
1041
1042     // Convert back to layer coordinates.
1043     alignedBounds.scale(1 / effectiveContentsScale());
1044
1045     // Convert back to layer coordinates.
1046     alignmentOffset = baseRelativeBounds.location() - alignedBounds.location();
1047
1048     position = m_position - alignmentOffset;
1049     size = alignedBounds.size();
1050
1051     // Now we have to compute a new anchor point which compensates for rounding.
1052     float anchorPointX = m_anchorPoint.x();
1053     float anchorPointY = m_anchorPoint.y();
1054
1055     if (alignedBounds.width())
1056         anchorPointX = (baseRelativeBounds.width() * anchorPointX + alignmentOffset.width()) / alignedBounds.width();
1057
1058     if (alignedBounds.height())
1059         anchorPointY = (baseRelativeBounds.height() * anchorPointY + alignmentOffset.height()) / alignedBounds.height();
1060
1061     anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * effectiveContentsScale());
1062 }
1063
1064 void CoordinatedGraphicsLayer::computeTransformedVisibleRect()
1065 {
1066     if (!m_shouldUpdateVisibleRect && !m_movingVisibleRect)
1067         return;
1068
1069     m_shouldUpdateVisibleRect = false;
1070     TransformationMatrix currentTransform = transform();
1071     if (m_movingVisibleRect)
1072         client().getCurrentTransform(this, currentTransform);
1073     m_layerTransform.setLocalTransform(currentTransform);
1074
1075     m_layerTransform.setAnchorPoint(m_adjustedAnchorPoint);
1076     m_layerTransform.setPosition(m_adjustedPosition);
1077     m_layerTransform.setSize(m_adjustedSize);
1078
1079     m_layerTransform.setFlattening(!preserves3D());
1080     m_layerTransform.setChildrenTransform(childrenTransform());
1081     m_layerTransform.combineTransforms(parent() ? downcast<CoordinatedGraphicsLayer>(*parent()).m_layerTransform.combinedForChildren() : TransformationMatrix());
1082
1083     m_cachedInverseTransform = m_layerTransform.combined().inverse().value_or(TransformationMatrix());
1084
1085     // The combined transform will be used in tiledBackingStoreVisibleRect.
1086     setNeedsVisibleRectAdjustment();
1087 }
1088
1089 bool CoordinatedGraphicsLayer::shouldHaveBackingStore() const
1090 {
1091     return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
1092 }
1093
1094 bool CoordinatedGraphicsLayer::selfOrAncestorHasActiveTransformAnimation() const
1095 {
1096     if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyTransform))
1097         return true;
1098
1099     if (!parent())
1100         return false;
1101
1102     return downcast<CoordinatedGraphicsLayer>(*parent()).selfOrAncestorHasActiveTransformAnimation();
1103 }
1104
1105 bool CoordinatedGraphicsLayer::selfOrAncestorHaveNonAffineTransforms()
1106 {
1107     if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyTransform))
1108         return true;
1109
1110     if (!m_layerTransform.combined().isAffine())
1111         return true;
1112
1113     if (!parent())
1114         return false;
1115
1116     return downcast<CoordinatedGraphicsLayer>(*parent()).selfOrAncestorHaveNonAffineTransforms();
1117 }
1118
1119 bool CoordinatedGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double delayAsNegativeTimeOffset)
1120 {
1121     ASSERT(!keyframesName.isEmpty());
1122
1123     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyTransform && valueList.property() != AnimatedPropertyOpacity && valueList.property() != AnimatedPropertyFilter))
1124         return false;
1125
1126     if (valueList.property() == AnimatedPropertyFilter) {
1127         int listIndex = validateFilterOperations(valueList);
1128         if (listIndex < 0)
1129             return false;
1130
1131         const auto& filters = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
1132         if (!filtersCanBeComposited(filters))
1133             return false;
1134     }
1135
1136     bool listsMatch = false;
1137     bool ignoredHasBigRotation;
1138
1139     if (valueList.property() == AnimatedPropertyTransform)
1140         listsMatch = validateTransformOperations(valueList, ignoredHasBigRotation) >= 0;
1141
1142     m_lastAnimationStartTime = monotonicallyIncreasingTime() - delayAsNegativeTimeOffset;
1143     m_animations.add(TextureMapperAnimation(keyframesName, valueList, boxSize, *anim, listsMatch, m_lastAnimationStartTime, 0, TextureMapperAnimation::AnimationState::Playing));
1144     m_animationStartedTimer.startOneShot(0_s);
1145     didChangeAnimations();
1146     return true;
1147 }
1148
1149 void CoordinatedGraphicsLayer::pauseAnimation(const String& animationName, double time)
1150 {
1151     m_animations.pause(animationName, time);
1152     didChangeAnimations();
1153 }
1154
1155 void CoordinatedGraphicsLayer::removeAnimation(const String& animationName)
1156 {
1157     m_animations.remove(animationName);
1158     didChangeAnimations();
1159 }
1160
1161 void CoordinatedGraphicsLayer::suspendAnimations(double time)
1162 {
1163     m_animations.suspend(time);
1164     didChangeAnimations();
1165 }
1166
1167 void CoordinatedGraphicsLayer::resumeAnimations()
1168 {
1169     m_animations.resume();
1170     didChangeAnimations();
1171 }
1172
1173 void CoordinatedGraphicsLayer::animationStartedTimerFired()
1174 {
1175     client().notifyAnimationStarted(this, "", m_lastAnimationStartTime);
1176 }
1177
1178 #if USE(COORDINATED_GRAPHICS_THREADED)
1179 void CoordinatedGraphicsLayer::platformLayerWillBeDestroyed()
1180 {
1181 }
1182
1183 void CoordinatedGraphicsLayer::setPlatformLayerNeedsDisplay()
1184 {
1185 }
1186 #endif
1187
1188 } // namespace WebCore
1189
1190 #endif // USE(COORDINATED_GRAPHICS)