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