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