892f6b201344a46f94c0d8989321b2dd0b7682d4
[WebKit.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
651         m_nicosia.backingStore = nullptr;
652         m_nicosia.delta.backingStoreChanged = true;
653     }
654
655     // Determine image backing presence according to the composited image source.
656     if (m_compositedNativeImagePtr) {
657         ASSERT(m_compositedImage);
658         auto& image = *m_compositedImage;
659         uintptr_t imageID = reinterpret_cast<uintptr_t>(&image);
660         uintptr_t nativeImageID = reinterpret_cast<uintptr_t>(m_compositedNativeImagePtr.get());
661
662         // Respawn the ImageBacking object if the underlying image changed.
663         if (m_nicosia.imageBacking) {
664             auto& impl = downcast<Nicosia::ImageBackingTextureMapperImpl>(m_nicosia.imageBacking->impl());
665             if (impl.layerState().imageID != imageID) {
666                 impl.layerState().update = Nicosia::ImageBackingTextureMapperImpl::Update { };
667                 m_nicosia.imageBacking = nullptr;
668             }
669         }
670         if (!m_nicosia.imageBacking) {
671             m_nicosia.imageBacking = Nicosia::ImageBacking::create(Nicosia::ImageBackingTextureMapperImpl::createFactory());
672             m_nicosia.delta.imageBackingChanged = true;
673         }
674
675         // Update the image contents only when the image layer is visible and the native image changed.
676         auto& impl = downcast<Nicosia::ImageBackingTextureMapperImpl>(m_nicosia.imageBacking->impl());
677         auto& layerState = impl.layerState();
678         layerState.imageID = imageID;
679         layerState.update.isVisible = transformedVisibleRect().intersects(IntRect(contentsRect()));
680         if (layerState.update.isVisible && layerState.nativeImageID != nativeImageID) {
681             auto buffer = Nicosia::Buffer::create(IntSize(image.size()),
682                 !image.currentFrameKnownToBeOpaque() ? Nicosia::Buffer::SupportsAlpha : Nicosia::Buffer::NoFlags);
683             Nicosia::PaintingContext::paint(buffer,
684                 [&image](GraphicsContext& context)
685                 {
686                     IntRect rect { { }, IntSize { image.size() } };
687                     context.drawImage(image, rect, rect, ImagePaintingOptions(CompositeCopy));
688                 });
689             layerState.nativeImageID = nativeImageID;
690             layerState.update.buffer = WTFMove(buffer);
691             m_nicosia.delta.imageBackingChanged = true;
692         }
693     } else if (m_nicosia.imageBacking) {
694         auto& layerState = downcast<Nicosia::ImageBackingTextureMapperImpl>(m_nicosia.imageBacking->impl()).layerState();
695         layerState.update = Nicosia::ImageBackingTextureMapperImpl::Update { };
696         m_nicosia.imageBacking = nullptr;
697         m_nicosia.delta.imageBackingChanged = true;
698     }
699
700     {
701         m_nicosia.layer->updateState(
702             [this](Nicosia::CompositionLayer::LayerState& state)
703             {
704                 // OR the local delta value into the layer's pending state delta. After that,
705                 // go through each local change and update the pending state accordingly.
706                 auto& localDelta = m_nicosia.delta;
707                 state.delta.value |= localDelta.value;
708
709                 if (localDelta.positionChanged)
710                     state.position = m_adjustedPosition;
711                 if (localDelta.anchorPointChanged)
712                     state.anchorPoint = m_adjustedAnchorPoint;
713                 if (localDelta.sizeChanged)
714                     state.size = m_adjustedSize;
715
716                 if (localDelta.transformChanged)
717                     state.transform = transform();
718                 if (localDelta.childrenTransformChanged)
719                     state.childrenTransform = childrenTransform();
720
721                 if (localDelta.contentsRectChanged)
722                     state.contentsRect = contentsRect();
723                 if (localDelta.contentsTilingChanged) {
724                     state.contentsTilePhase = contentsTilePhase();
725                     state.contentsTileSize = contentsTileSize();
726                 }
727
728                 if (localDelta.opacityChanged)
729                     state.opacity = opacity();
730                 if (localDelta.solidColorChanged)
731                     state.solidColor = m_solidColor;
732
733                 if (localDelta.filtersChanged)
734                     state.filters = filters();
735                 if (localDelta.animationsChanged)
736                     state.animations = m_animations.getActiveAnimations();
737
738                 if (localDelta.childrenChanged) {
739                     state.children = WTF::map(children(),
740                         [](auto& child)
741                         {
742                             return downcast<CoordinatedGraphicsLayer>(child.get()).m_nicosia.layer;
743                         });
744                 }
745
746                 if (localDelta.maskChanged) {
747                     auto* mask = downcast<CoordinatedGraphicsLayer>(maskLayer());
748                     state.mask = mask ? mask->m_nicosia.layer : nullptr;
749                 }
750
751                 if (localDelta.replicaChanged) {
752                     auto* replica = downcast<CoordinatedGraphicsLayer>(replicaLayer());
753                     state.replica = replica ? replica->m_nicosia.layer : nullptr;
754                 }
755
756                 if (localDelta.flagsChanged) {
757                     state.flags.contentsOpaque = contentsOpaque();
758                     state.flags.drawsContent = drawsContent();
759                     state.flags.contentsVisible = contentsAreVisible();
760                     state.flags.backfaceVisible = backfaceVisibility();
761                     state.flags.masksToBounds = masksToBounds();
762                     state.flags.preserves3D = preserves3D();
763                 }
764
765                 if (localDelta.repaintCounterChanged)
766                     state.repaintCounter = m_nicosia.repaintCounter;
767                 if (localDelta.debugBorderChanged)
768                     state.debugBorder = m_nicosia.debugBorder;
769
770                 if (localDelta.backingStoreChanged)
771                     state.backingStore = m_nicosia.backingStore;
772                 if (localDelta.contentLayerChanged)
773                     state.contentLayer = m_nicosia.contentLayer;
774                 if (localDelta.imageBackingChanged)
775                     state.imageBacking = m_nicosia.imageBacking;
776             });
777         m_nicosia.performLayerSync = !!m_nicosia.delta.value;
778         m_nicosia.delta = { };
779     }
780 }
781
782 void CoordinatedGraphicsLayer::syncPendingStateChangesIncludingSubLayers()
783 {
784     if (m_nicosia.performLayerSync)
785         m_coordinator->syncLayerState();
786     m_nicosia.performLayerSync = false;
787
788     if (maskLayer())
789         downcast<CoordinatedGraphicsLayer>(*maskLayer()).syncPendingStateChangesIncludingSubLayers();
790
791     for (auto& child : children())
792         downcast<CoordinatedGraphicsLayer>(child.get()).syncPendingStateChangesIncludingSubLayers();
793 }
794
795 void CoordinatedGraphicsLayer::deviceOrPageScaleFactorChanged()
796 {
797     if (shouldHaveBackingStore())
798         m_pendingContentsScaleAdjustment = true;
799 }
800
801 float CoordinatedGraphicsLayer::effectiveContentsScale()
802 {
803     return selfOrAncestorHaveNonAffineTransforms() ? 1 : deviceScaleFactor() * pageScaleFactor();
804 }
805
806 static void clampToContentsRectIfRectIsInfinite(FloatRect& rect, const FloatSize& contentsSize)
807 {
808     if (rect.width() >= LayoutUnit::nearlyMax() || rect.width() <= LayoutUnit::nearlyMin()) {
809         rect.setX(0);
810         rect.setWidth(contentsSize.width());
811     }
812
813     if (rect.height() >= LayoutUnit::nearlyMax() || rect.height() <= LayoutUnit::nearlyMin()) {
814         rect.setY(0);
815         rect.setHeight(contentsSize.height());
816     }
817 }
818
819 IntRect CoordinatedGraphicsLayer::transformedVisibleRect()
820 {
821     // Non-invertible layers are not visible.
822     if (!m_layerTransform.combined().isInvertible())
823         return IntRect();
824
825     // Return a projection of the visible rect (surface coordinates) onto the layer's plane (layer coordinates).
826     // The resulting quad might be squewed and the visible rect is the bounding box of this quad,
827     // so it might spread further than the real visible area (and then even more amplified by the cover rect multiplier).
828     ASSERT(m_cachedInverseTransform == m_layerTransform.combined().inverse().valueOr(TransformationMatrix()));
829     FloatRect rect = m_cachedInverseTransform.clampedBoundsOfProjectedQuad(FloatQuad(m_coordinator->visibleContentsRect()));
830     clampToContentsRectIfRectIsInfinite(rect, size());
831     return enclosingIntRect(rect);
832 }
833
834 void CoordinatedGraphicsLayer::updateContentBuffersIncludingSubLayers()
835 {
836     if (CoordinatedGraphicsLayer* mask = downcast<CoordinatedGraphicsLayer>(maskLayer()))
837         mask->updateContentBuffers();
838
839     if (CoordinatedGraphicsLayer* replica = downcast<CoordinatedGraphicsLayer>(replicaLayer()))
840         replica->updateContentBuffers();
841
842     updateContentBuffers();
843
844     for (auto& child : children())
845         downcast<CoordinatedGraphicsLayer>(child.get()).updateContentBuffersIncludingSubLayers();
846 }
847
848 void CoordinatedGraphicsLayer::updateContentBuffers()
849 {
850     if (!m_nicosia.backingStore)
851         return;
852
853     // Prepare for painting on the impl-contained backing store. isFlushing is used there
854     // for internal sanity checks.
855     auto& impl = downcast<Nicosia::BackingStoreTextureMapperImpl>(m_nicosia.backingStore->impl());
856     auto& layerState = impl.layerState();
857     layerState.isFlushing = true;
858
859     // Helper lambda that finished the flush update and determines layer sync necessity.
860     auto finishUpdate =
861         [this, &layerState] {
862             auto& update = layerState.update;
863             m_nicosia.performLayerSync |= !update.tilesToCreate.isEmpty()
864                 || !update.tilesToRemove.isEmpty() || !update.tilesToUpdate.isEmpty();
865             layerState.isFlushing = false;
866         };
867
868     // Address the content scale adjustment.
869     if (m_pendingContentsScaleAdjustment) {
870         if (layerState.mainBackingStore && layerState.mainBackingStore->contentsScale() != effectiveContentsScale()) {
871             // Discard the TiledBackingStore object to reconstruct it with new content scale.
872             layerState.mainBackingStore = nullptr;
873         }
874         m_pendingContentsScaleAdjustment = false;
875     }
876
877     // Ensure the TiledBackingStore object, and enforce a complete repaint if it's not been present yet.
878     if (!layerState.mainBackingStore) {
879         layerState.mainBackingStore = std::make_unique<TiledBackingStore>(impl, effectiveContentsScale());
880         m_pendingVisibleRectAdjustment = true;
881     }
882
883     // Bail if there's no painting recorded or enforced.
884     if (!m_pendingVisibleRectAdjustment && !m_needsDisplay.completeLayer && m_needsDisplay.rects.isEmpty()) {
885         finishUpdate();
886         return;
887     }
888
889     if (!m_needsDisplay.completeLayer) {
890         for (auto& rect : m_needsDisplay.rects)
891             layerState.mainBackingStore->invalidate(enclosingIntRect(rect));
892     } else
893         layerState.mainBackingStore->invalidate({ { }, IntSize { m_size } });
894
895     m_needsDisplay.completeLayer = false;
896     m_needsDisplay.rects.clear();
897
898     if (m_pendingVisibleRectAdjustment) {
899         m_pendingVisibleRectAdjustment = false;
900         layerState.mainBackingStore->createTilesIfNeeded(transformedVisibleRect(), IntRect(0, 0, m_size.width(), m_size.height()));
901     }
902
903     ASSERT(m_coordinator && m_coordinator->isFlushingLayerChanges());
904
905     // With all the affected tiles created and/or invalidated, we can finally paint them.
906     auto dirtyTiles = layerState.mainBackingStore->dirtyTiles();
907     if (!dirtyTiles.isEmpty()) {
908         bool didUpdateTiles = false;
909
910         for (auto& tileReference : dirtyTiles) {
911             auto& tile = tileReference.get();
912             tile.ensureTileID();
913
914             auto& tileRect = tile.rect();
915             auto& dirtyRect = tile.dirtyRect();
916
917             auto coordinatedBuffer = Nicosia::Buffer::create(dirtyRect.size(), contentsOpaque() ? Nicosia::Buffer::NoFlags : Nicosia::Buffer::SupportsAlpha);
918             SurfaceUpdateInfo updateInfo;
919             updateInfo.updateRect = dirtyRect;
920             updateInfo.updateRect.move(-tileRect.x(), -tileRect.y());
921             updateInfo.buffer = coordinatedBuffer.copyRef();
922
923             if (!m_coordinator->paintingEngine().paint(*this, WTFMove(coordinatedBuffer),
924                 dirtyRect, layerState.mainBackingStore->mapToContents(dirtyRect),
925                 IntRect { { 0, 0 }, dirtyRect.size() }, layerState.mainBackingStore->contentsScale()))
926                 continue;
927
928             impl.updateTile(tile.tileID(), updateInfo, tileRect);
929
930             tile.markClean();
931             didUpdateTiles |= true;
932         }
933
934         if (didUpdateTiles)
935             didUpdateTileBuffers();
936     }
937
938     // Request a second update immediately if some tiles are still pending creation.
939     if (layerState.hasPendingTileCreation) {
940         setNeedsVisibleRectAdjustment();
941         notifyFlushRequired();
942     }
943
944     finishUpdate();
945 }
946
947 void CoordinatedGraphicsLayer::purgeBackingStores()
948 {
949 #ifndef NDEBUG
950     SetForScope<bool> updateModeProtector(m_isPurging, true);
951 #endif
952     if (m_nicosia.backingStore) {
953         auto& layerState = downcast<Nicosia::BackingStoreTextureMapperImpl>(m_nicosia.backingStore->impl()).layerState();
954         layerState.isPurging = true;
955         layerState.mainBackingStore = nullptr;
956
957         m_nicosia.backingStore = nullptr;
958     }
959
960     if (m_nicosia.imageBacking) {
961         auto& layerState = downcast<Nicosia::ImageBackingTextureMapperImpl>(m_nicosia.imageBacking->impl()).layerState();
962         layerState.imageID = 0;
963         layerState.nativeImageID = 0;
964         layerState.update = { };
965
966         m_nicosia.imageBacking = nullptr;
967     }
968
969     notifyFlushRequired();
970 }
971
972 void CoordinatedGraphicsLayer::setCoordinator(CoordinatedGraphicsLayerClient* coordinator)
973 {
974     m_coordinator = coordinator;
975 }
976
977 void CoordinatedGraphicsLayer::setCoordinatorIncludingSubLayersIfNeeded(CoordinatedGraphicsLayerClient* coordinator)
978 {
979     if (m_coordinator == coordinator)
980         return;
981
982     // If the coordinators are different it means that we are attaching a layer that was created by a different
983     // CompositingCoordinator than the current one. This happens because the layer was taken out of the tree
984     // and then added back after AC was disabled and enabled again. We need to set the new coordinator to the
985     // layer and its children.
986     //
987     // During each layer flush, the state stores the values that have changed since the previous one, and these
988     // are updated once in the scene. When adding CoordinatedGraphicsLayers back to the tree, the fields that
989     // are not updated during the next flush won't be sent to the scene, so they won't be updated there and the
990     // rendering will fail.
991     //
992     // For example the drawsContent flag. This is set when the layer is created and is not updated anymore (unless
993     // the content changes). When the layer is added back to the tree, the state won't reflect any change in the
994     // flag value, so the scene won't update it and the layer won't be rendered.
995     //
996     // We need to update here the layer changeMask so the scene gets all the current values.
997     m_nicosia.delta.value = UINT_MAX;
998
999     coordinator->attachLayer(this);
1000     for (auto& child : children())
1001         downcast<CoordinatedGraphicsLayer>(child.get()).setCoordinatorIncludingSubLayersIfNeeded(coordinator);
1002 }
1003
1004 const RefPtr<Nicosia::CompositionLayer>& CoordinatedGraphicsLayer::compositionLayer() const
1005 {
1006     return m_nicosia.layer;
1007 }
1008
1009 void CoordinatedGraphicsLayer::setNeedsVisibleRectAdjustment()
1010 {
1011     if (shouldHaveBackingStore())
1012         m_pendingVisibleRectAdjustment = true;
1013 }
1014
1015 static inline bool isIntegral(float value)
1016 {
1017     return static_cast<int>(value) == value;
1018 }
1019
1020 FloatPoint CoordinatedGraphicsLayer::computePositionRelativeToBase()
1021 {
1022     FloatPoint offset;
1023     for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent())
1024         offset += currLayer->position();
1025
1026     return offset;
1027 }
1028
1029 void CoordinatedGraphicsLayer::computePixelAlignment(FloatPoint& position, FloatSize& size, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset)
1030 {
1031     if (isIntegral(effectiveContentsScale())) {
1032         position = m_position;
1033         size = m_size;
1034         anchorPoint = m_anchorPoint;
1035         alignmentOffset = FloatSize();
1036         return;
1037     }
1038
1039     FloatPoint positionRelativeToBase = computePositionRelativeToBase();
1040
1041     FloatRect baseRelativeBounds(positionRelativeToBase, m_size);
1042     FloatRect scaledBounds = baseRelativeBounds;
1043
1044     // Scale by the effective scale factor to compute the screen-relative bounds.
1045     scaledBounds.scale(effectiveContentsScale());
1046
1047     // Round to integer boundaries.
1048     // NOTE: When using enclosingIntRect (as mac) it will have different sizes depending on position.
1049     FloatRect alignedBounds = enclosingIntRect(scaledBounds);
1050
1051     // Convert back to layer coordinates.
1052     alignedBounds.scale(1 / effectiveContentsScale());
1053
1054     // Convert back to layer coordinates.
1055     alignmentOffset = baseRelativeBounds.location() - alignedBounds.location();
1056
1057     position = m_position - alignmentOffset;
1058     size = alignedBounds.size();
1059
1060     // Now we have to compute a new anchor point which compensates for rounding.
1061     float anchorPointX = m_anchorPoint.x();
1062     float anchorPointY = m_anchorPoint.y();
1063
1064     if (alignedBounds.width())
1065         anchorPointX = (baseRelativeBounds.width() * anchorPointX + alignmentOffset.width()) / alignedBounds.width();
1066
1067     if (alignedBounds.height())
1068         anchorPointY = (baseRelativeBounds.height() * anchorPointY + alignmentOffset.height()) / alignedBounds.height();
1069
1070     anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * effectiveContentsScale());
1071 }
1072
1073 void CoordinatedGraphicsLayer::computeTransformedVisibleRect()
1074 {
1075     if (!m_shouldUpdateVisibleRect && !m_movingVisibleRect)
1076         return;
1077
1078     m_shouldUpdateVisibleRect = false;
1079     TransformationMatrix currentTransform = transform();
1080     if (m_movingVisibleRect)
1081         client().getCurrentTransform(this, currentTransform);
1082     m_layerTransform.setLocalTransform(currentTransform);
1083
1084     m_layerTransform.setAnchorPoint(m_adjustedAnchorPoint);
1085     m_layerTransform.setPosition(m_adjustedPosition);
1086     m_layerTransform.setSize(m_adjustedSize);
1087
1088     m_layerTransform.setFlattening(!preserves3D());
1089     m_layerTransform.setChildrenTransform(childrenTransform());
1090     m_layerTransform.combineTransforms(parent() ? downcast<CoordinatedGraphicsLayer>(*parent()).m_layerTransform.combinedForChildren() : TransformationMatrix());
1091
1092     m_cachedInverseTransform = m_layerTransform.combined().inverse().valueOr(TransformationMatrix());
1093
1094     // The combined transform will be used in tiledBackingStoreVisibleRect.
1095     setNeedsVisibleRectAdjustment();
1096 }
1097
1098 bool CoordinatedGraphicsLayer::shouldHaveBackingStore() const
1099 {
1100     return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
1101 }
1102
1103 bool CoordinatedGraphicsLayer::selfOrAncestorHasActiveTransformAnimation() const
1104 {
1105     if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyTransform))
1106         return true;
1107
1108     if (!parent())
1109         return false;
1110
1111     return downcast<CoordinatedGraphicsLayer>(*parent()).selfOrAncestorHasActiveTransformAnimation();
1112 }
1113
1114 bool CoordinatedGraphicsLayer::selfOrAncestorHaveNonAffineTransforms()
1115 {
1116     if (!m_layerTransform.combined().isAffine())
1117         return true;
1118
1119     if (!parent())
1120         return false;
1121
1122     return downcast<CoordinatedGraphicsLayer>(*parent()).selfOrAncestorHaveNonAffineTransforms();
1123 }
1124
1125 bool CoordinatedGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double delayAsNegativeTimeOffset)
1126 {
1127     ASSERT(!keyframesName.isEmpty());
1128
1129     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyTransform && valueList.property() != AnimatedPropertyOpacity && valueList.property() != AnimatedPropertyFilter))
1130         return false;
1131
1132     if (valueList.property() == AnimatedPropertyFilter) {
1133         int listIndex = validateFilterOperations(valueList);
1134         if (listIndex < 0)
1135             return false;
1136
1137         const auto& filters = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
1138         if (!filtersCanBeComposited(filters))
1139             return false;
1140     }
1141
1142     bool listsMatch = false;
1143     bool ignoredHasBigRotation;
1144
1145     if (valueList.property() == AnimatedPropertyTransform)
1146         listsMatch = validateTransformOperations(valueList, ignoredHasBigRotation) >= 0;
1147
1148     m_lastAnimationStartTime = MonotonicTime::now() - Seconds(delayAsNegativeTimeOffset);
1149     m_animations.add(TextureMapperAnimation(keyframesName, valueList, boxSize, *anim, listsMatch, m_lastAnimationStartTime, 0_s, TextureMapperAnimation::AnimationState::Playing));
1150     m_animationStartedTimer.startOneShot(0_s);
1151     didChangeAnimations();
1152     return true;
1153 }
1154
1155 void CoordinatedGraphicsLayer::pauseAnimation(const String& animationName, double time)
1156 {
1157     m_animations.pause(animationName, Seconds(time));
1158     didChangeAnimations();
1159 }
1160
1161 void CoordinatedGraphicsLayer::removeAnimation(const String& animationName)
1162 {
1163     m_animations.remove(animationName);
1164     didChangeAnimations();
1165 }
1166
1167 void CoordinatedGraphicsLayer::suspendAnimations(MonotonicTime time)
1168 {
1169     m_animations.suspend(time);
1170     didChangeAnimations();
1171 }
1172
1173 void CoordinatedGraphicsLayer::resumeAnimations()
1174 {
1175     m_animations.resume();
1176     didChangeAnimations();
1177 }
1178
1179 void CoordinatedGraphicsLayer::animationStartedTimerFired()
1180 {
1181     client().notifyAnimationStarted(this, "", m_lastAnimationStartTime);
1182 }
1183
1184 bool CoordinatedGraphicsLayer::usesContentsLayer() const
1185 {
1186     return m_nicosia.contentLayer || m_compositedImage;
1187 }
1188
1189 } // namespace WebCore
1190
1191 #endif // USE(COORDINATED_GRAPHICS)