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.
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.
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.
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.
24 #include "CoordinatedGraphicsLayer.h"
26 #if USE(COORDINATED_GRAPHICS)
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>
35 #include <wtf/SetForScope.h>
37 #include <wtf/text/CString.h>
41 std::unique_ptr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client, Type layerType)
44 return std::make_unique<CoordinatedGraphicsLayer>(layerType, client);
46 return factory->createGraphicsLayer(layerType, client);
49 static CoordinatedLayerID toCoordinatedLayerID(GraphicsLayer* layer)
51 return is<CoordinatedGraphicsLayer>(layer) ? downcast<CoordinatedGraphicsLayer>(*layer).id() : 0;
54 void CoordinatedGraphicsLayer::notifyFlushRequired()
59 if (m_coordinator->isFlushingLayerChanges())
62 client().notifyFlushRequired(this);
65 void CoordinatedGraphicsLayer::didChangeLayerState()
67 m_shouldSyncLayerState = true;
68 notifyFlushRequired();
71 void CoordinatedGraphicsLayer::didChangeAnimations()
73 m_shouldSyncAnimations = true;
74 notifyFlushRequired();
77 void CoordinatedGraphicsLayer::didChangeChildren()
79 m_shouldSyncChildren = true;
80 notifyFlushRequired();
83 void CoordinatedGraphicsLayer::didChangeFilters()
85 m_shouldSyncFilters = true;
86 notifyFlushRequired();
89 void CoordinatedGraphicsLayer::didChangeImageBacking()
91 m_shouldSyncImageBacking = true;
92 notifyFlushRequired();
95 void CoordinatedGraphicsLayer::setShouldUpdateVisibleRect()
97 m_shouldUpdateVisibleRect = true;
98 for (auto& child : children())
99 downcast<CoordinatedGraphicsLayer>(*child).setShouldUpdateVisibleRect();
101 downcast<CoordinatedGraphicsLayer>(*replicaLayer()).setShouldUpdateVisibleRect();
104 void CoordinatedGraphicsLayer::didChangeGeometry()
106 didChangeLayerState();
107 setShouldUpdateVisibleRect();
110 CoordinatedGraphicsLayer::CoordinatedGraphicsLayer(Type layerType, GraphicsLayerClient& client)
111 : GraphicsLayer(layerType, client)
115 , m_shouldUpdateVisibleRect(true)
116 , m_shouldSyncLayerState(true)
117 , m_shouldSyncChildren(true)
118 , m_shouldSyncFilters(true)
119 , m_shouldSyncImageBacking(true)
120 , m_shouldSyncAnimations(true)
121 , m_fixedToViewport(false)
122 , m_movingVisibleRect(false)
123 , m_pendingContentsScaleAdjustment(false)
124 , m_pendingVisibleRectAdjustment(false)
125 #if USE(COORDINATED_GRAPHICS_THREADED)
126 , m_shouldSyncPlatformLayer(false)
127 , m_shouldUpdatePlatformLayer(false)
130 , m_compositedNativeImagePtr(0)
132 , m_animationStartedTimer(*this, &CoordinatedGraphicsLayer::animationStartedTimerFired)
133 , m_scrollableArea(0)
135 static CoordinatedLayerID nextLayerID = 1;
136 m_id = nextLayerID++;
139 CoordinatedGraphicsLayer::~CoordinatedGraphicsLayer()
142 purgeBackingStores();
143 m_coordinator->detachLayer(this);
145 ASSERT(!m_coordinatedImageBacking);
146 ASSERT(!m_mainBackingStore);
150 bool CoordinatedGraphicsLayer::setChildren(const Vector<GraphicsLayer*>& children)
152 bool ok = GraphicsLayer::setChildren(children);
159 void CoordinatedGraphicsLayer::addChild(GraphicsLayer* layer)
161 GraphicsLayer::addChild(layer);
165 void CoordinatedGraphicsLayer::addChildAtIndex(GraphicsLayer* layer, int index)
167 GraphicsLayer::addChildAtIndex(layer, index);
171 void CoordinatedGraphicsLayer::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
173 GraphicsLayer::addChildAbove(layer, sibling);
177 void CoordinatedGraphicsLayer::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
179 GraphicsLayer::addChildBelow(layer, sibling);
183 bool CoordinatedGraphicsLayer::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
185 bool ok = GraphicsLayer::replaceChild(oldChild, newChild);
192 void CoordinatedGraphicsLayer::removeFromParent()
194 if (CoordinatedGraphicsLayer* parentLayer = downcast<CoordinatedGraphicsLayer>(parent()))
195 parentLayer->didChangeChildren();
196 GraphicsLayer::removeFromParent();
199 void CoordinatedGraphicsLayer::setPosition(const FloatPoint& p)
204 GraphicsLayer::setPosition(p);
205 m_layerState.positionChanged = true;
209 void CoordinatedGraphicsLayer::setAnchorPoint(const FloatPoint3D& p)
211 if (anchorPoint() == p)
214 GraphicsLayer::setAnchorPoint(p);
215 m_layerState.anchorPointChanged = true;
219 void CoordinatedGraphicsLayer::setSize(const FloatSize& size)
221 if (this->size() == size)
224 GraphicsLayer::setSize(size);
225 m_layerState.sizeChanged = true;
228 maskLayer()->setSize(size);
232 void CoordinatedGraphicsLayer::setTransform(const TransformationMatrix& t)
234 if (transform() == t)
237 GraphicsLayer::setTransform(t);
238 m_layerState.transformChanged = true;
243 void CoordinatedGraphicsLayer::setChildrenTransform(const TransformationMatrix& t)
245 if (childrenTransform() == t)
248 GraphicsLayer::setChildrenTransform(t);
249 m_layerState.childrenTransformChanged = true;
254 void CoordinatedGraphicsLayer::setPreserves3D(bool b)
256 if (preserves3D() == b)
259 GraphicsLayer::setPreserves3D(b);
260 m_layerState.preserves3D = b;
261 m_layerState.flagsChanged = true;
266 void CoordinatedGraphicsLayer::setMasksToBounds(bool b)
268 if (masksToBounds() == b)
270 GraphicsLayer::setMasksToBounds(b);
271 m_layerState.masksToBounds = b;
272 m_layerState.flagsChanged = true;
277 void CoordinatedGraphicsLayer::setDrawsContent(bool b)
279 if (drawsContent() == b)
281 GraphicsLayer::setDrawsContent(b);
282 m_layerState.drawsContent = b;
283 m_layerState.flagsChanged = true;
285 didChangeLayerState();
288 void CoordinatedGraphicsLayer::setContentsVisible(bool b)
290 if (contentsAreVisible() == b)
292 GraphicsLayer::setContentsVisible(b);
293 m_layerState.contentsVisible = b;
294 m_layerState.flagsChanged = true;
297 maskLayer()->setContentsVisible(b);
299 didChangeLayerState();
302 void CoordinatedGraphicsLayer::setContentsOpaque(bool b)
304 if (contentsOpaque() == b)
306 if (m_mainBackingStore)
307 m_mainBackingStore->setSupportsAlpha(!b);
308 GraphicsLayer::setContentsOpaque(b);
309 m_layerState.contentsOpaque = b;
310 m_layerState.flagsChanged = true;
312 didChangeLayerState();
315 void CoordinatedGraphicsLayer::setBackfaceVisibility(bool b)
317 if (backfaceVisibility() == b)
320 GraphicsLayer::setBackfaceVisibility(b);
321 m_layerState.backfaceVisible = b;
322 m_layerState.flagsChanged = true;
324 didChangeLayerState();
327 void CoordinatedGraphicsLayer::setOpacity(float opacity)
329 if (this->opacity() == opacity)
332 GraphicsLayer::setOpacity(opacity);
333 m_layerState.opacity = opacity;
334 m_layerState.opacityChanged = true;
336 didChangeLayerState();
339 void CoordinatedGraphicsLayer::setContentsRect(const FloatRect& r)
341 if (contentsRect() == r)
344 GraphicsLayer::setContentsRect(r);
345 m_layerState.contentsRect = r;
346 m_layerState.contentsRectChanged = true;
348 didChangeLayerState();
351 void CoordinatedGraphicsLayer::setContentsTileSize(const FloatSize& s)
353 if (contentsTileSize() == s)
356 GraphicsLayer::setContentsTileSize(s);
357 m_layerState.contentsTileSize = s;
358 m_layerState.contentsTilingChanged = true;
359 didChangeLayerState();
362 void CoordinatedGraphicsLayer::setContentsTilePhase(const FloatSize& p)
364 if (contentsTilePhase() == p)
367 GraphicsLayer::setContentsTilePhase(p);
368 m_layerState.contentsTilePhase = p;
369 m_layerState.contentsTilingChanged = true;
370 didChangeLayerState();
373 bool GraphicsLayer::supportsContentsTiling()
378 void CoordinatedGraphicsLayer::setContentsNeedsDisplay()
380 #if USE(COORDINATED_GRAPHICS_THREADED)
382 m_shouldUpdatePlatformLayer = true;
385 notifyFlushRequired();
386 addRepaintRect(contentsRect());
389 void CoordinatedGraphicsLayer::setContentsToPlatformLayer(PlatformLayer* platformLayer, ContentsLayerPurpose)
391 #if USE(COORDINATED_GRAPHICS_THREADED)
392 if (m_platformLayer != platformLayer)
393 m_shouldSyncPlatformLayer = true;
395 m_platformLayer = platformLayer;
396 notifyFlushRequired();
398 UNUSED_PARAM(platformLayer);
402 bool CoordinatedGraphicsLayer::filtersCanBeComposited(const FilterOperations& filters) const
407 for (const auto& filterOperation : filters.operations()) {
408 if (filterOperation->type() == FilterOperation::REFERENCE)
415 bool CoordinatedGraphicsLayer::setFilters(const FilterOperations& newFilters)
417 bool canCompositeFilters = filtersCanBeComposited(newFilters);
418 if (filters() == newFilters)
419 return canCompositeFilters;
421 if (canCompositeFilters) {
422 if (!GraphicsLayer::setFilters(newFilters))
425 } else if (filters().size()) {
430 return canCompositeFilters;
433 void CoordinatedGraphicsLayer::setContentsToSolidColor(const Color& color)
435 if (m_layerState.solidColor == color)
438 m_layerState.solidColor = color;
439 m_layerState.solidColorChanged = true;
441 didChangeLayerState();
444 void CoordinatedGraphicsLayer::setShowDebugBorder(bool show)
446 if (isShowingDebugBorder() == show)
449 GraphicsLayer::setShowDebugBorder(show);
450 m_layerState.showDebugBorders = true;
451 m_layerState.flagsChanged = true;
453 didChangeLayerState();
456 void CoordinatedGraphicsLayer::setShowRepaintCounter(bool show)
458 if (isShowingRepaintCounter() == show)
461 GraphicsLayer::setShowRepaintCounter(show);
462 m_layerState.showRepaintCounter = true;
463 m_layerState.flagsChanged = true;
465 didChangeLayerState();
468 void CoordinatedGraphicsLayer::setContentsToImage(Image* image)
470 NativeImagePtr nativeImagePtr = image ? image->nativeImageForCurrentFrame() : nullptr;
471 if (m_compositedImage == image && m_compositedNativeImagePtr == nativeImagePtr)
474 m_compositedImage = image;
475 m_compositedNativeImagePtr = nativeImagePtr;
477 GraphicsLayer::setContentsToImage(image);
478 didChangeImageBacking();
481 void CoordinatedGraphicsLayer::setMaskLayer(GraphicsLayer* layer)
483 if (layer == maskLayer())
486 GraphicsLayer::setMaskLayer(layer);
491 layer->setSize(size());
492 layer->setContentsVisible(contentsAreVisible());
493 auto& coordinatedLayer = downcast<CoordinatedGraphicsLayer>(*layer);
494 coordinatedLayer.didChangeLayerState();
496 m_layerState.mask = coordinatedLayer.id();
497 m_layerState.maskChanged = true;
499 didChangeLayerState();
502 bool CoordinatedGraphicsLayer::shouldDirectlyCompositeImage(Image* image) const
504 if (!image || !image->isBitmapImage())
507 enum { MaxDimenstionForDirectCompositing = 2000 };
508 if (image->width() > MaxDimenstionForDirectCompositing || image->height() > MaxDimenstionForDirectCompositing)
514 void CoordinatedGraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
516 if (layer == replicaLayer())
519 GraphicsLayer::setReplicatedByLayer(layer);
520 m_layerState.replica = toCoordinatedLayerID(layer);
521 m_layerState.replicaChanged = true;
522 didChangeLayerState();
525 void CoordinatedGraphicsLayer::setNeedsDisplay()
527 setNeedsDisplayInRect(FloatRect(FloatPoint(), size()));
530 void CoordinatedGraphicsLayer::setNeedsDisplayInRect(const FloatRect& rect, ShouldClipToLayer)
532 if (m_mainBackingStore)
533 m_mainBackingStore->invalidate(IntRect(rect));
535 didChangeLayerState();
537 addRepaintRect(rect);
540 void CoordinatedGraphicsLayer::setScrollableArea(ScrollableArea* scrollableArea)
542 bool oldScrollable = isScrollable();
543 m_scrollableArea = scrollableArea;
544 if (oldScrollable == isScrollable())
547 m_layerState.isScrollable = isScrollable();
548 m_layerState.flagsChanged = true;
549 didChangeLayerState();
552 void CoordinatedGraphicsLayer::commitScrollOffset(const IntSize& offset)
554 if (!isScrollable() || offset.isZero())
557 m_scrollableArea->notifyScrollPositionChanged(m_scrollableArea->scrollPosition() + offset);
558 m_layerState.committedScrollOffset += offset;
559 m_layerState.committedScrollOffsetChanged = true;
560 didChangeLayerState();
563 void CoordinatedGraphicsLayer::setFixedToViewport(bool isFixed)
565 if (m_fixedToViewport == isFixed)
568 m_fixedToViewport = isFixed;
569 m_layerState.fixedToViewport = isFixed;
570 m_layerState.flagsChanged = true;
572 didChangeLayerState();
575 void CoordinatedGraphicsLayer::flushCompositingState(const FloatRect& rect)
577 if (CoordinatedGraphicsLayer* mask = downcast<CoordinatedGraphicsLayer>(maskLayer()))
578 mask->flushCompositingStateForThisLayerOnly();
580 if (CoordinatedGraphicsLayer* replica = downcast<CoordinatedGraphicsLayer>(replicaLayer()))
581 replica->flushCompositingStateForThisLayerOnly();
583 flushCompositingStateForThisLayerOnly();
585 for (auto& child : children())
586 child->flushCompositingState(rect);
589 void CoordinatedGraphicsLayer::syncChildren()
591 if (!m_shouldSyncChildren)
593 m_shouldSyncChildren = false;
594 m_layerState.childrenChanged = true;
595 m_layerState.children.clear();
596 for (auto& child : children())
597 m_layerState.children.append(toCoordinatedLayerID(child));
600 void CoordinatedGraphicsLayer::syncFilters()
602 if (!m_shouldSyncFilters)
604 m_shouldSyncFilters = false;
606 m_layerState.filters = GraphicsLayer::filters();
607 m_layerState.filtersChanged = true;
610 void CoordinatedGraphicsLayer::syncImageBacking()
612 if (!m_shouldSyncImageBacking)
614 m_shouldSyncImageBacking = false;
616 if (m_compositedNativeImagePtr) {
617 ASSERT(!shouldHaveBackingStore());
618 ASSERT(m_compositedImage);
620 bool imageInstanceReplaced = m_coordinatedImageBacking && (m_coordinatedImageBacking->id() != CoordinatedImageBacking::getCoordinatedImageBackingID(m_compositedImage.get()));
621 if (imageInstanceReplaced)
622 releaseImageBackingIfNeeded();
624 if (!m_coordinatedImageBacking) {
625 m_coordinatedImageBacking = m_coordinator->createImageBackingIfNeeded(m_compositedImage.get());
626 m_coordinatedImageBacking->addHost(this);
627 m_layerState.imageID = m_coordinatedImageBacking->id();
630 m_coordinatedImageBacking->markDirty();
631 m_layerState.imageChanged = true;
633 releaseImageBackingIfNeeded();
635 // syncImageBacking() changed m_layerState.imageID.
636 didChangeLayerState();
639 void CoordinatedGraphicsLayer::syncLayerState()
641 if (!m_shouldSyncLayerState)
643 m_shouldSyncLayerState = false;
645 m_layerState.childrenTransform = childrenTransform();
646 m_layerState.contentsRect = contentsRect();
647 m_layerState.mask = toCoordinatedLayerID(maskLayer());
648 m_layerState.opacity = opacity();
649 m_layerState.replica = toCoordinatedLayerID(replicaLayer());
650 m_layerState.transform = transform();
652 m_layerState.anchorPoint = m_adjustedAnchorPoint;
653 m_layerState.pos = m_adjustedPosition;
654 m_layerState.size = m_adjustedSize;
656 if (m_layerState.flagsChanged) {
657 m_layerState.contentsOpaque = contentsOpaque();
658 m_layerState.drawsContent = drawsContent();
659 m_layerState.contentsVisible = contentsAreVisible();
660 m_layerState.backfaceVisible = backfaceVisibility();
661 m_layerState.masksToBounds = masksToBounds();
662 m_layerState.preserves3D = preserves3D();
663 m_layerState.fixedToViewport = fixedToViewport();
664 m_layerState.showDebugBorders = isShowingDebugBorder();
665 m_layerState.showRepaintCounter = isShowingRepaintCounter();
666 m_layerState.isScrollable = isScrollable();
669 if (m_layerState.showDebugBorders)
670 updateDebugIndicators();
673 void CoordinatedGraphicsLayer::setDebugBorder(const Color& color, float width)
675 ASSERT(m_layerState.showDebugBorders);
676 if (m_layerState.debugBorderColor != color) {
677 m_layerState.debugBorderColor = color;
678 m_layerState.debugBorderColorChanged = true;
681 if (m_layerState.debugBorderWidth != width) {
682 m_layerState.debugBorderWidth = width;
683 m_layerState.debugBorderWidthChanged = true;
687 void CoordinatedGraphicsLayer::syncAnimations()
689 if (!m_shouldSyncAnimations)
692 m_shouldSyncAnimations = false;
693 m_layerState.animations = m_animations.getActiveAnimations();
694 m_layerState.animationsChanged = true;
697 void CoordinatedGraphicsLayer::syncPlatformLayer()
699 #if USE(COORDINATED_GRAPHICS_THREADED)
700 if (!m_shouldSyncPlatformLayer)
703 m_shouldSyncPlatformLayer = false;
704 m_layerState.platformLayerChanged = true;
706 m_layerState.platformLayerProxy = m_platformLayer->proxy();
710 void CoordinatedGraphicsLayer::updatePlatformLayer()
712 #if USE(COORDINATED_GRAPHICS_THREADED)
713 if (!m_shouldUpdatePlatformLayer)
716 m_shouldUpdatePlatformLayer = false;
717 m_layerState.platformLayerUpdated = true;
719 m_platformLayer->swapBuffersIfNeeded();
723 void CoordinatedGraphicsLayer::flushCompositingStateForThisLayerOnly()
725 // When we have a transform animation, we need to update visible rect every frame to adjust the visible rect of a backing store.
726 bool hasActiveTransformAnimation = selfOrAncestorHasActiveTransformAnimation();
727 if (hasActiveTransformAnimation)
728 m_movingVisibleRect = true;
731 computePixelAlignment(m_adjustedPosition, m_adjustedSize, m_adjustedAnchorPoint, m_pixelAlignmentOffset);
736 computeTransformedVisibleRect();
740 updatePlatformLayer();
742 // Only unset m_movingVisibleRect after we have updated the visible rect after the animation stopped.
743 if (!hasActiveTransformAnimation)
744 m_movingVisibleRect = false;
747 void CoordinatedGraphicsLayer::syncPendingStateChangesIncludingSubLayers()
749 if (m_layerState.hasPendingChanges()) {
750 m_coordinator->syncLayerState(m_id, m_layerState);
755 downcast<CoordinatedGraphicsLayer>(*maskLayer()).syncPendingStateChangesIncludingSubLayers();
757 for (auto& child : children())
758 downcast<CoordinatedGraphicsLayer>(*child).syncPendingStateChangesIncludingSubLayers();
761 void CoordinatedGraphicsLayer::resetLayerState()
763 m_layerState.changeMask = 0;
764 m_layerState.tilesToCreate.clear();
765 m_layerState.tilesToRemove.clear();
766 m_layerState.tilesToUpdate.clear();
767 m_layerState.committedScrollOffset = IntSize();
770 bool CoordinatedGraphicsLayer::imageBackingVisible()
772 ASSERT(m_coordinatedImageBacking);
773 return transformedVisibleRect().intersects(IntRect(contentsRect()));
776 void CoordinatedGraphicsLayer::releaseImageBackingIfNeeded()
778 if (!m_coordinatedImageBacking)
781 ASSERT(m_coordinator);
782 m_coordinatedImageBacking->removeHost(this);
783 m_coordinatedImageBacking = nullptr;
784 m_layerState.imageID = InvalidCoordinatedImageBackingID;
785 m_layerState.imageChanged = true;
788 CoordinatedGraphicsLayer* CoordinatedGraphicsLayer::findFirstDescendantWithContentsRecursively()
790 if (shouldHaveBackingStore())
793 for (auto& child : children()) {
794 if (CoordinatedGraphicsLayer* layer = downcast<CoordinatedGraphicsLayer>(*child).findFirstDescendantWithContentsRecursively())
801 void CoordinatedGraphicsLayer::setVisibleContentRectTrajectoryVector(const FloatPoint& trajectoryVector)
803 if (!m_mainBackingStore)
806 m_mainBackingStore->setTrajectoryVector(trajectoryVector);
807 setNeedsVisibleRectAdjustment();
810 void CoordinatedGraphicsLayer::deviceOrPageScaleFactorChanged()
812 if (shouldHaveBackingStore())
813 m_pendingContentsScaleAdjustment = true;
816 float CoordinatedGraphicsLayer::effectiveContentsScale()
818 return selfOrAncestorHaveNonAffineTransforms() ? 1 : deviceScaleFactor() * pageScaleFactor();
821 void CoordinatedGraphicsLayer::adjustContentsScale()
823 ASSERT(shouldHaveBackingStore());
824 if (!m_mainBackingStore || m_mainBackingStore->contentsScale() == effectiveContentsScale())
827 // Between creating the new backing store and painting the content,
828 // we do not want to drop the previous one as that might result in
829 // briefly seeing flickering as the old tiles may be dropped before
830 // something replaces them.
831 m_previousBackingStore = WTFMove(m_mainBackingStore);
833 // No reason to save the previous backing store for non-visible areas.
834 m_previousBackingStore->removeAllNonVisibleTiles(transformedVisibleRect(), IntRect(0, 0, size().width(), size().height()));
837 void CoordinatedGraphicsLayer::createBackingStore()
839 m_mainBackingStore = std::make_unique<TiledBackingStore>(this, effectiveContentsScale());
840 m_mainBackingStore->setSupportsAlpha(!contentsOpaque());
843 void CoordinatedGraphicsLayer::tiledBackingStorePaint(GraphicsContext& context, const IntRect& rect)
847 paintGraphicsLayerContents(context, rect);
850 void CoordinatedGraphicsLayer::didUpdateTileBuffers()
852 if (!isShowingRepaintCounter())
855 m_layerState.repaintCount = incrementRepaintCount();
856 m_layerState.repaintCountChanged = true;
859 void CoordinatedGraphicsLayer::tiledBackingStoreHasPendingTileCreation()
861 setNeedsVisibleRectAdjustment();
862 notifyFlushRequired();
865 static void clampToContentsRectIfRectIsInfinite(FloatRect& rect, const FloatSize& contentsSize)
867 if (rect.width() >= LayoutUnit::nearlyMax() || rect.width() <= LayoutUnit::nearlyMin()) {
869 rect.setWidth(contentsSize.width());
872 if (rect.height() >= LayoutUnit::nearlyMax() || rect.height() <= LayoutUnit::nearlyMin()) {
874 rect.setHeight(contentsSize.height());
878 IntRect CoordinatedGraphicsLayer::transformedVisibleRect()
880 // Non-invertible layers are not visible.
881 if (!m_layerTransform.combined().isInvertible())
884 // Return a projection of the visible rect (surface coordinates) onto the layer's plane (layer coordinates).
885 // The resulting quad might be squewed and the visible rect is the bounding box of this quad,
886 // so it might spread further than the real visible area (and then even more amplified by the cover rect multiplier).
887 ASSERT(m_cachedInverseTransform == m_layerTransform.combined().inverse().value_or(TransformationMatrix()));
888 FloatRect rect = m_cachedInverseTransform.clampedBoundsOfProjectedQuad(FloatQuad(m_coordinator->visibleContentsRect()));
889 clampToContentsRectIfRectIsInfinite(rect, size());
890 return enclosingIntRect(rect);
893 bool CoordinatedGraphicsLayer::paintToSurface(const IntSize& size, uint32_t& atlas, IntPoint& offset, CoordinatedSurface::Client& client)
895 ASSERT(m_coordinator);
896 ASSERT(m_coordinator->isFlushingLayerChanges());
897 return m_coordinator->paintToSurface(size, contentsOpaque() ? CoordinatedSurface::NoFlags : CoordinatedSurface::SupportsAlpha, atlas, offset, client);
900 void CoordinatedGraphicsLayer::createTile(uint32_t tileID, float scaleFactor)
902 ASSERT(m_coordinator);
903 ASSERT(m_coordinator->isFlushingLayerChanges());
905 TileCreationInfo creationInfo;
906 creationInfo.tileID = tileID;
907 creationInfo.scale = scaleFactor;
908 m_layerState.tilesToCreate.append(creationInfo);
911 void CoordinatedGraphicsLayer::updateTile(uint32_t tileID, const SurfaceUpdateInfo& updateInfo, const IntRect& tileRect)
913 ASSERT(m_coordinator);
914 ASSERT(m_coordinator->isFlushingLayerChanges());
916 TileUpdateInfo tileUpdateInfo;
917 tileUpdateInfo.tileID = tileID;
918 tileUpdateInfo.tileRect = tileRect;
919 tileUpdateInfo.updateInfo = updateInfo;
920 m_layerState.tilesToUpdate.append(tileUpdateInfo);
923 void CoordinatedGraphicsLayer::removeTile(uint32_t tileID)
925 ASSERT(m_coordinator);
926 ASSERT(m_coordinator->isFlushingLayerChanges() || m_isPurging);
927 m_layerState.tilesToRemove.append(tileID);
930 void CoordinatedGraphicsLayer::updateContentBuffersIncludingSubLayers()
932 if (CoordinatedGraphicsLayer* mask = downcast<CoordinatedGraphicsLayer>(maskLayer()))
933 mask->updateContentBuffers();
935 if (CoordinatedGraphicsLayer* replica = downcast<CoordinatedGraphicsLayer>(replicaLayer()))
936 replica->updateContentBuffers();
938 updateContentBuffers();
940 for (auto& child : children())
941 downcast<CoordinatedGraphicsLayer>(*child).updateContentBuffersIncludingSubLayers();
944 void CoordinatedGraphicsLayer::updateContentBuffers()
946 if (!shouldHaveBackingStore()) {
947 m_mainBackingStore = nullptr;
948 m_previousBackingStore = nullptr;
952 if (m_pendingContentsScaleAdjustment) {
953 adjustContentsScale();
954 m_pendingContentsScaleAdjustment = false;
957 // This is the only place we (re)create the main tiled backing store, once we
958 // have a remote client and we are ready to send our data to the UI process.
959 if (!m_mainBackingStore) {
960 createBackingStore();
961 m_pendingVisibleRectAdjustment = true;
964 if (m_pendingVisibleRectAdjustment) {
965 m_pendingVisibleRectAdjustment = false;
966 m_mainBackingStore->createTilesIfNeeded(transformedVisibleRect(), IntRect(0, 0, size().width(), size().height()));
969 m_mainBackingStore->updateTileBuffers();
971 // The previous backing store is kept around to avoid flickering between
972 // removing the existing tiles and painting the new ones. The first time
973 // the visibleRect is full painted we remove the previous backing store.
974 if (m_mainBackingStore->visibleAreaIsCovered())
975 m_previousBackingStore = nullptr;
978 void CoordinatedGraphicsLayer::purgeBackingStores()
981 SetForScope<bool> updateModeProtector(m_isPurging, true);
983 m_mainBackingStore = nullptr;
984 m_previousBackingStore = nullptr;
986 releaseImageBackingIfNeeded();
988 didChangeLayerState();
991 void CoordinatedGraphicsLayer::setCoordinator(CoordinatedGraphicsLayerClient* coordinator)
993 m_coordinator = coordinator;
996 void CoordinatedGraphicsLayer::setNeedsVisibleRectAdjustment()
998 if (shouldHaveBackingStore())
999 m_pendingVisibleRectAdjustment = true;
1002 static inline bool isIntegral(float value)
1004 return static_cast<int>(value) == value;
1007 FloatPoint CoordinatedGraphicsLayer::computePositionRelativeToBase()
1010 for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent())
1011 offset += currLayer->position();
1016 void CoordinatedGraphicsLayer::computePixelAlignment(FloatPoint& position, FloatSize& size, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset)
1018 if (isIntegral(effectiveContentsScale())) {
1019 position = m_position;
1021 anchorPoint = m_anchorPoint;
1022 alignmentOffset = FloatSize();
1026 FloatPoint positionRelativeToBase = computePositionRelativeToBase();
1028 FloatRect baseRelativeBounds(positionRelativeToBase, m_size);
1029 FloatRect scaledBounds = baseRelativeBounds;
1031 // Scale by the effective scale factor to compute the screen-relative bounds.
1032 scaledBounds.scale(effectiveContentsScale());
1034 // Round to integer boundaries.
1035 // NOTE: When using enclosingIntRect (as mac) it will have different sizes depending on position.
1036 FloatRect alignedBounds = enclosingIntRect(scaledBounds);
1038 // Convert back to layer coordinates.
1039 alignedBounds.scale(1 / effectiveContentsScale());
1041 // Convert back to layer coordinates.
1042 alignmentOffset = baseRelativeBounds.location() - alignedBounds.location();
1044 position = m_position - alignmentOffset;
1045 size = alignedBounds.size();
1047 // Now we have to compute a new anchor point which compensates for rounding.
1048 float anchorPointX = m_anchorPoint.x();
1049 float anchorPointY = m_anchorPoint.y();
1051 if (alignedBounds.width())
1052 anchorPointX = (baseRelativeBounds.width() * anchorPointX + alignmentOffset.width()) / alignedBounds.width();
1054 if (alignedBounds.height())
1055 anchorPointY = (baseRelativeBounds.height() * anchorPointY + alignmentOffset.height()) / alignedBounds.height();
1057 anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * effectiveContentsScale());
1060 void CoordinatedGraphicsLayer::computeTransformedVisibleRect()
1062 if (!m_shouldUpdateVisibleRect && !m_movingVisibleRect)
1065 m_shouldUpdateVisibleRect = false;
1066 TransformationMatrix currentTransform = transform();
1067 if (m_movingVisibleRect)
1068 client().getCurrentTransform(this, currentTransform);
1069 m_layerTransform.setLocalTransform(currentTransform);
1071 m_layerTransform.setAnchorPoint(m_adjustedAnchorPoint);
1072 m_layerTransform.setPosition(m_adjustedPosition);
1073 m_layerTransform.setSize(m_adjustedSize);
1075 m_layerTransform.setFlattening(!preserves3D());
1076 m_layerTransform.setChildrenTransform(childrenTransform());
1077 m_layerTransform.combineTransforms(parent() ? downcast<CoordinatedGraphicsLayer>(*parent()).m_layerTransform.combinedForChildren() : TransformationMatrix());
1079 m_cachedInverseTransform = m_layerTransform.combined().inverse().value_or(TransformationMatrix());
1081 // The combined transform will be used in tiledBackingStoreVisibleRect.
1082 setNeedsVisibleRectAdjustment();
1085 bool CoordinatedGraphicsLayer::shouldHaveBackingStore() const
1087 return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
1090 bool CoordinatedGraphicsLayer::selfOrAncestorHasActiveTransformAnimation() const
1092 if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyTransform))
1098 return downcast<CoordinatedGraphicsLayer>(*parent()).selfOrAncestorHasActiveTransformAnimation();
1101 bool CoordinatedGraphicsLayer::selfOrAncestorHaveNonAffineTransforms()
1103 if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyTransform))
1106 if (!m_layerTransform.combined().isAffine())
1112 return downcast<CoordinatedGraphicsLayer>(*parent()).selfOrAncestorHaveNonAffineTransforms();
1115 bool CoordinatedGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double delayAsNegativeTimeOffset)
1117 ASSERT(!keyframesName.isEmpty());
1119 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyTransform && valueList.property() != AnimatedPropertyOpacity && valueList.property() != AnimatedPropertyFilter))
1122 if (valueList.property() == AnimatedPropertyFilter) {
1123 int listIndex = validateFilterOperations(valueList);
1127 const auto& filters = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
1128 if (!filtersCanBeComposited(filters))
1132 bool listsMatch = false;
1133 bool ignoredHasBigRotation;
1135 if (valueList.property() == AnimatedPropertyTransform)
1136 listsMatch = validateTransformOperations(valueList, ignoredHasBigRotation) >= 0;
1138 m_lastAnimationStartTime = monotonicallyIncreasingTime() - delayAsNegativeTimeOffset;
1139 m_animations.add(TextureMapperAnimation(keyframesName, valueList, boxSize, *anim, listsMatch, m_lastAnimationStartTime, 0, TextureMapperAnimation::AnimationState::Playing));
1140 m_animationStartedTimer.startOneShot(0_s);
1141 didChangeAnimations();
1145 void CoordinatedGraphicsLayer::pauseAnimation(const String& animationName, double time)
1147 m_animations.pause(animationName, time);
1148 didChangeAnimations();
1151 void CoordinatedGraphicsLayer::removeAnimation(const String& animationName)
1153 m_animations.remove(animationName);
1154 didChangeAnimations();
1157 void CoordinatedGraphicsLayer::suspendAnimations(double time)
1159 m_animations.suspend(time);
1160 didChangeAnimations();
1163 void CoordinatedGraphicsLayer::resumeAnimations()
1165 m_animations.resume();
1166 didChangeAnimations();
1169 void CoordinatedGraphicsLayer::animationStartedTimerFired()
1171 client().notifyAnimationStarted(this, "", m_lastAnimationStartTime);
1174 #if USE(COORDINATED_GRAPHICS_THREADED)
1175 void CoordinatedGraphicsLayer::platformLayerWillBeDestroyed()
1179 void CoordinatedGraphicsLayer::setPlatformLayerNeedsDisplay()
1184 } // namespace WebCore
1186 #endif // USE(COORDINATED_GRAPHICS)