2 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
21 #include "GraphicsLayerTextureMapper.h"
23 #include "GraphicsContext.h"
24 #include "GraphicsLayerFactory.h"
25 #include "ImageBuffer.h"
26 #include "TextureMapperAnimation.h"
28 #if !USE(COORDINATED_GRAPHICS)
32 std::unique_ptr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client, Type layerType)
35 return std::make_unique<GraphicsLayerTextureMapper>(layerType, client);
37 return factory->createGraphicsLayer(layerType, client);
40 GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(Type layerType, GraphicsLayerClient& client)
41 : GraphicsLayer(layerType, client)
42 , m_compositedNativeImagePtr(0)
43 , m_changeMask(NoChanges)
44 , m_needsDisplay(false)
45 , m_debugBorderWidth(0)
50 void GraphicsLayerTextureMapper::notifyChange(ChangeMask changeMask)
52 bool flushRequired = m_changeMask == NoChanges;
53 m_changeMask |= changeMask;
56 client().notifyFlushRequired(this);
59 GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper()
62 m_contentsLayer->setClient(0);
67 void GraphicsLayerTextureMapper::setNeedsDisplay()
72 // The current size might change, thus we need to update the whole display.
73 m_needsDisplay = true;
74 notifyChange(DisplayChange);
75 addRepaintRect(FloatRect(FloatPoint(), m_size));
78 void GraphicsLayerTextureMapper::setContentsNeedsDisplay()
80 notifyChange(DisplayChange);
81 addRepaintRect(contentsRect());
84 void GraphicsLayerTextureMapper::setNeedsDisplayInRect(const FloatRect& rect, ShouldClipToLayer)
91 m_needsDisplayRect.unite(rect);
92 notifyChange(DisplayChange);
96 bool GraphicsLayerTextureMapper::setChildren(const Vector<GraphicsLayer*>& children)
98 if (GraphicsLayer::setChildren(children)) {
99 notifyChange(ChildrenChange);
105 void GraphicsLayerTextureMapper::addChild(GraphicsLayer* layer)
107 notifyChange(ChildrenChange);
108 GraphicsLayer::addChild(layer);
111 void GraphicsLayerTextureMapper::addChildAtIndex(GraphicsLayer* layer, int index)
113 GraphicsLayer::addChildAtIndex(layer, index);
114 notifyChange(ChildrenChange);
117 void GraphicsLayerTextureMapper::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
119 GraphicsLayer::addChildAbove(layer, sibling);
120 notifyChange(ChildrenChange);
123 void GraphicsLayerTextureMapper::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
125 GraphicsLayer::addChildBelow(layer, sibling);
126 notifyChange(ChildrenChange);
129 bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
131 if (GraphicsLayer::replaceChild(oldChild, newChild)) {
132 notifyChange(ChildrenChange);
138 void GraphicsLayerTextureMapper::setMaskLayer(GraphicsLayer* value)
140 if (value == maskLayer())
142 GraphicsLayer::setMaskLayer(value);
143 notifyChange(MaskLayerChange);
147 value->setSize(size());
148 value->setContentsVisible(contentsAreVisible());
152 void GraphicsLayerTextureMapper::setReplicatedByLayer(GraphicsLayer* value)
154 if (value == replicaLayer())
156 GraphicsLayer::setReplicatedByLayer(value);
157 notifyChange(ReplicaLayerChange);
160 void GraphicsLayerTextureMapper::setPosition(const FloatPoint& value)
162 if (value == position())
164 GraphicsLayer::setPosition(value);
165 notifyChange(PositionChange);
168 void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value)
170 if (value == anchorPoint())
172 GraphicsLayer::setAnchorPoint(value);
173 notifyChange(AnchorPointChange);
176 void GraphicsLayerTextureMapper::setSize(const FloatSize& value)
181 GraphicsLayer::setSize(value);
183 maskLayer()->setSize(value);
184 notifyChange(SizeChange);
187 void GraphicsLayerTextureMapper::setTransform(const TransformationMatrix& value)
189 if (value == transform())
192 GraphicsLayer::setTransform(value);
193 notifyChange(TransformChange);
196 void GraphicsLayerTextureMapper::setChildrenTransform(const TransformationMatrix& value)
198 if (value == childrenTransform())
200 GraphicsLayer::setChildrenTransform(value);
201 notifyChange(ChildrenTransformChange);
204 void GraphicsLayerTextureMapper::setPreserves3D(bool value)
206 if (value == preserves3D())
208 GraphicsLayer::setPreserves3D(value);
209 notifyChange(Preserves3DChange);
212 void GraphicsLayerTextureMapper::setMasksToBounds(bool value)
214 if (value == masksToBounds())
216 GraphicsLayer::setMasksToBounds(value);
217 notifyChange(MasksToBoundsChange);
220 void GraphicsLayerTextureMapper::setDrawsContent(bool value)
222 if (value == drawsContent())
224 GraphicsLayer::setDrawsContent(value);
225 notifyChange(DrawsContentChange);
231 void GraphicsLayerTextureMapper::setContentsVisible(bool value)
233 if (value == contentsAreVisible())
235 notifyChange(ContentsVisibleChange);
236 GraphicsLayer::setContentsVisible(value);
238 maskLayer()->setContentsVisible(value);
241 void GraphicsLayerTextureMapper::setContentsOpaque(bool value)
243 if (value == contentsOpaque())
245 notifyChange(ContentsOpaqueChange);
246 GraphicsLayer::setContentsOpaque(value);
249 void GraphicsLayerTextureMapper::setBackfaceVisibility(bool value)
251 if (value == backfaceVisibility())
253 GraphicsLayer::setBackfaceVisibility(value);
254 notifyChange(BackfaceVisibilityChange);
257 void GraphicsLayerTextureMapper::setOpacity(float value)
259 if (value == opacity())
261 GraphicsLayer::setOpacity(value);
262 notifyChange(OpacityChange);
265 void GraphicsLayerTextureMapper::setContentsRect(const FloatRect& value)
267 if (value == contentsRect())
269 GraphicsLayer::setContentsRect(value);
270 notifyChange(ContentsRectChange);
273 void GraphicsLayerTextureMapper::setContentsToSolidColor(const Color& color)
275 if (color == m_solidColor)
278 m_solidColor = color;
279 notifyChange(BackgroundColorChange);
282 void GraphicsLayerTextureMapper::setContentsToImage(Image* image)
285 // Make the decision about whether the image has changed.
286 // This code makes the assumption that pointer equality on a NativeImagePtr is a valid way to tell if the image is changed.
287 // This assumption is true for the GTK+ port.
288 NativeImagePtr newNativeImagePtr = image->nativeImageForCurrentFrame();
289 if (!newNativeImagePtr)
292 if (newNativeImagePtr == m_compositedNativeImagePtr)
295 m_compositedNativeImagePtr = newNativeImagePtr;
296 if (!m_compositedImage)
297 m_compositedImage = TextureMapperTiledBackingStore::create();
298 m_compositedImage->setContentsToImage(image);
299 m_compositedImage->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
301 m_compositedNativeImagePtr = nullptr;
302 m_compositedImage = nullptr;
305 setContentsToPlatformLayer(m_compositedImage.get(), ContentsLayerPurpose::Image);
306 notifyChange(ContentChange);
307 GraphicsLayer::setContentsToImage(image);
310 void GraphicsLayerTextureMapper::setContentsToPlatformLayer(TextureMapperPlatformLayer* platformLayer, ContentsLayerPurpose purpose)
312 if (platformLayer == m_contentsLayer)
315 GraphicsLayer::setContentsToPlatformLayer(platformLayer, purpose);
316 notifyChange(ContentChange);
319 m_contentsLayer->setClient(0);
321 m_contentsLayer = platformLayer;
324 m_contentsLayer->setClient(this);
327 void GraphicsLayerTextureMapper::setShowDebugBorder(bool show)
329 if (isShowingDebugBorder() == show)
332 GraphicsLayer::setShowDebugBorder(show);
333 notifyChange(DebugVisualsChange);
336 void GraphicsLayerTextureMapper::setShowRepaintCounter(bool show)
338 if (isShowingRepaintCounter() == show)
341 GraphicsLayer::setShowRepaintCounter(show);
342 notifyChange(RepaintCountChange);
345 void GraphicsLayerTextureMapper::flushCompositingStateForThisLayerOnly()
347 prepareBackingStoreIfNeeded();
348 commitLayerChanges();
349 m_layer.syncAnimations(MonotonicTime::now());
352 void GraphicsLayerTextureMapper::prepareBackingStoreIfNeeded()
354 if (shouldHaveBackingStore()) {
355 if (!m_backingStore) {
356 m_backingStore = TextureMapperTiledBackingStore::create();
357 m_changeMask |= BackingStoreChange;
360 if (m_backingStore) {
361 m_backingStore = nullptr;
362 m_changeMask |= BackingStoreChange;
366 updateDebugBorderAndRepaintCount();
369 void GraphicsLayerTextureMapper::updateDebugBorderAndRepaintCount()
371 if (isShowingDebugBorder())
372 updateDebugIndicators();
374 // When this has its own backing store (e.g. Qt WK1), update the repaint count before calling TextureMapperLayer::flushCompositingStateForThisLayerOnly().
375 bool needsToRepaint = shouldHaveBackingStore() && (m_needsDisplay || !m_needsDisplayRect.isEmpty());
376 if (isShowingRepaintCounter() && needsToRepaint) {
377 incrementRepaintCount();
378 m_changeMask |= RepaintCountChange;
382 void GraphicsLayerTextureMapper::setDebugBorder(const Color& color, float width)
384 m_debugBorderColor = color;
385 m_debugBorderWidth = width;
386 m_changeMask |= DebugVisualsChange;
389 void GraphicsLayerTextureMapper::commitLayerChanges()
391 if (m_changeMask == NoChanges)
394 if (m_changeMask & ChildrenChange)
395 m_layer.setChildren(children());
397 if (m_changeMask & MaskLayerChange)
398 m_layer.setMaskLayer(&downcast<GraphicsLayerTextureMapper>(maskLayer())->layer());
400 if (m_changeMask & ReplicaLayerChange)
401 m_layer.setReplicaLayer(&downcast<GraphicsLayerTextureMapper>(replicaLayer())->layer());
403 if (m_changeMask & PositionChange)
404 m_layer.setPosition(position());
406 if (m_changeMask & AnchorPointChange)
407 m_layer.setAnchorPoint(anchorPoint());
409 if (m_changeMask & SizeChange)
410 m_layer.setSize(size());
412 if (m_changeMask & TransformChange)
413 m_layer.setTransform(transform());
415 if (m_changeMask & ChildrenTransformChange)
416 m_layer.setChildrenTransform(childrenTransform());
418 if (m_changeMask & Preserves3DChange)
419 m_layer.setPreserves3D(preserves3D());
421 if (m_changeMask & ContentsRectChange)
422 m_layer.setContentsRect(contentsRect());
424 if (m_changeMask & MasksToBoundsChange)
425 m_layer.setMasksToBounds(masksToBounds());
427 if (m_changeMask & DrawsContentChange)
428 m_layer.setDrawsContent(drawsContent());
430 if (m_changeMask & ContentsVisibleChange)
431 m_layer.setContentsVisible(contentsAreVisible());
433 if (m_changeMask & ContentsOpaqueChange)
434 m_layer.setContentsOpaque(contentsOpaque());
436 if (m_changeMask & BackfaceVisibilityChange)
437 m_layer.setBackfaceVisibility(backfaceVisibility());
439 if (m_changeMask & OpacityChange)
440 m_layer.setOpacity(opacity());
442 if (m_changeMask & BackgroundColorChange)
443 m_layer.setSolidColor(m_solidColor);
445 if (m_changeMask & FilterChange)
446 m_layer.setFilters(filters());
448 if (m_changeMask & BackingStoreChange)
449 m_layer.setBackingStore(m_backingStore.get());
451 if (m_changeMask & DebugVisualsChange)
452 m_layer.setDebugVisuals(isShowingDebugBorder(), debugBorderColor(), debugBorderWidth());
454 if (m_changeMask & RepaintCountChange)
455 m_layer.setRepaintCounter(isShowingRepaintCounter(), repaintCount());
457 if (m_changeMask & ContentChange)
458 m_layer.setContentsLayer(platformLayer());
460 if (m_changeMask & AnimationChange)
461 m_layer.setAnimations(m_animations);
463 if (m_changeMask & AnimationStarted)
464 client().notifyAnimationStarted(this, "", m_animationStartTime);
466 m_changeMask = NoChanges;
469 void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect& rect)
471 if (!m_layer.textureMapper())
474 flushCompositingStateForThisLayerOnly();
477 maskLayer()->flushCompositingState(rect);
479 replicaLayer()->flushCompositingState(rect);
480 for (auto* child : children())
481 child->flushCompositingState(rect);
484 void GraphicsLayerTextureMapper::updateBackingStoreIncludingSubLayers()
486 if (!m_layer.textureMapper())
489 updateBackingStoreIfNeeded();
492 downcast<GraphicsLayerTextureMapper>(*maskLayer()).updateBackingStoreIfNeeded();
494 downcast<GraphicsLayerTextureMapper>(*replicaLayer()).updateBackingStoreIfNeeded();
495 for (auto* child : children())
496 downcast<GraphicsLayerTextureMapper>(*child).updateBackingStoreIncludingSubLayers();
499 void GraphicsLayerTextureMapper::updateBackingStoreIfNeeded()
501 TextureMapper* textureMapper = m_layer.textureMapper();
505 if (!shouldHaveBackingStore()) {
506 ASSERT(!m_backingStore);
509 ASSERT(m_backingStore);
511 IntRect dirtyRect = enclosingIntRect(FloatRect(FloatPoint::zero(), m_size));
513 dirtyRect.intersect(enclosingIntRect(m_needsDisplayRect));
514 if (dirtyRect.isEmpty())
517 m_backingStore->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
519 dirtyRect.scale(pageScaleFactor() * deviceScaleFactor());
520 m_backingStore->updateContents(*textureMapper, this, m_size, dirtyRect);
522 m_needsDisplay = false;
523 m_needsDisplayRect = IntRect();
526 bool GraphicsLayerTextureMapper::shouldHaveBackingStore() const
528 return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
531 bool GraphicsLayerTextureMapper::filtersCanBeComposited(const FilterOperations& filters) const
536 for (const auto& filterOperation : filters.operations()) {
537 if (filterOperation->type() == FilterOperation::REFERENCE)
544 bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
546 ASSERT(!keyframesName.isEmpty());
548 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyTransform && valueList.property() != AnimatedPropertyOpacity))
551 if (valueList.property() == AnimatedPropertyFilter) {
552 int listIndex = validateFilterOperations(valueList);
556 const auto& filters = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
557 if (!filtersCanBeComposited(filters))
561 bool listsMatch = false;
564 if (valueList.property() == AnimatedPropertyTransform)
565 listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0;
567 const MonotonicTime currentTime = MonotonicTime::now();
568 m_animations.add(TextureMapperAnimation(keyframesName, valueList, boxSize, *anim, listsMatch, currentTime - Seconds(timeOffset), 0_s, TextureMapperAnimation::AnimationState::Playing));
569 // m_animationStartTime is the time of the first real frame of animation, now or delayed by a negative offset.
570 if (Seconds(timeOffset) > 0_s)
571 m_animationStartTime = currentTime;
573 m_animationStartTime = currentTime - Seconds(timeOffset);
574 notifyChange(AnimationChange);
575 notifyChange(AnimationStarted);
579 void GraphicsLayerTextureMapper::pauseAnimation(const String& animationName, double timeOffset)
581 m_animations.pause(animationName, Seconds(timeOffset));
584 void GraphicsLayerTextureMapper::removeAnimation(const String& animationName)
586 m_animations.remove(animationName);
589 bool GraphicsLayerTextureMapper::setFilters(const FilterOperations& filters)
591 if (!m_layer.textureMapper())
594 bool canCompositeFilters = filtersCanBeComposited(filters);
595 if (GraphicsLayer::filters() == filters)
596 return canCompositeFilters;
598 if (canCompositeFilters) {
599 if (!GraphicsLayer::setFilters(filters))
601 notifyChange(FilterChange);
602 } else if (GraphicsLayer::filters().size()) {
604 notifyChange(FilterChange);
607 return canCompositeFilters;