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