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