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 Ref<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client, Type layerType)
35 return adoptRef(*new 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(Vector<Ref<GraphicsLayer>>&& children)
98 if (GraphicsLayer::setChildren(WTFMove(children))) {
99 notifyChange(ChildrenChange);
105 void GraphicsLayerTextureMapper::addChild(Ref<GraphicsLayer>&& layer)
107 notifyChange(ChildrenChange);
108 GraphicsLayer::addChild(WTFMove(layer));
111 void GraphicsLayerTextureMapper::addChildAtIndex(Ref<GraphicsLayer>&& layer, int index)
113 GraphicsLayer::addChildAtIndex(WTFMove(layer), index);
114 notifyChange(ChildrenChange);
117 void GraphicsLayerTextureMapper::addChildAbove(Ref<GraphicsLayer>&& layer, GraphicsLayer* sibling)
119 GraphicsLayer::addChildAbove(WTFMove(layer), sibling);
120 notifyChange(ChildrenChange);
123 void GraphicsLayerTextureMapper::addChildBelow(Ref<GraphicsLayer>&& layer, GraphicsLayer* sibling)
125 GraphicsLayer::addChildBelow(WTFMove(layer), sibling);
126 notifyChange(ChildrenChange);
129 bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, Ref<GraphicsLayer>&& newChild)
131 if (GraphicsLayer::replaceChild(oldChild, WTFMove(newChild))) {
132 notifyChange(ChildrenChange);
138 void GraphicsLayerTextureMapper::setMaskLayer(RefPtr<GraphicsLayer>&& value)
140 if (value == maskLayer())
143 GraphicsLayer* rawLayer = value.get();
144 GraphicsLayer::setMaskLayer(WTFMove(value));
145 notifyChange(MaskLayerChange);
149 rawLayer->setSize(size());
150 rawLayer->setContentsVisible(contentsAreVisible());
154 void GraphicsLayerTextureMapper::setReplicatedByLayer(GraphicsLayer* value)
156 if (value == replicaLayer())
158 GraphicsLayer::setReplicatedByLayer(value);
159 notifyChange(ReplicaLayerChange);
162 void GraphicsLayerTextureMapper::setPosition(const FloatPoint& value)
164 if (value == position())
166 GraphicsLayer::setPosition(value);
167 notifyChange(PositionChange);
170 void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value)
172 if (value == anchorPoint())
174 GraphicsLayer::setAnchorPoint(value);
175 notifyChange(AnchorPointChange);
178 void GraphicsLayerTextureMapper::setSize(const FloatSize& value)
183 GraphicsLayer::setSize(value);
185 maskLayer()->setSize(value);
186 notifyChange(SizeChange);
189 void GraphicsLayerTextureMapper::setTransform(const TransformationMatrix& value)
191 if (value == transform())
194 GraphicsLayer::setTransform(value);
195 notifyChange(TransformChange);
198 void GraphicsLayerTextureMapper::setChildrenTransform(const TransformationMatrix& value)
200 if (value == childrenTransform())
202 GraphicsLayer::setChildrenTransform(value);
203 notifyChange(ChildrenTransformChange);
206 void GraphicsLayerTextureMapper::setPreserves3D(bool value)
208 if (value == preserves3D())
210 GraphicsLayer::setPreserves3D(value);
211 notifyChange(Preserves3DChange);
214 void GraphicsLayerTextureMapper::setMasksToBounds(bool value)
216 if (value == masksToBounds())
218 GraphicsLayer::setMasksToBounds(value);
219 notifyChange(MasksToBoundsChange);
222 void GraphicsLayerTextureMapper::setDrawsContent(bool value)
224 if (value == drawsContent())
226 GraphicsLayer::setDrawsContent(value);
227 notifyChange(DrawsContentChange);
233 void GraphicsLayerTextureMapper::setContentsVisible(bool value)
235 if (value == contentsAreVisible())
237 notifyChange(ContentsVisibleChange);
238 GraphicsLayer::setContentsVisible(value);
240 maskLayer()->setContentsVisible(value);
243 void GraphicsLayerTextureMapper::setContentsOpaque(bool value)
245 if (value == contentsOpaque())
247 notifyChange(ContentsOpaqueChange);
248 GraphicsLayer::setContentsOpaque(value);
251 void GraphicsLayerTextureMapper::setBackfaceVisibility(bool value)
253 if (value == backfaceVisibility())
255 GraphicsLayer::setBackfaceVisibility(value);
256 notifyChange(BackfaceVisibilityChange);
259 void GraphicsLayerTextureMapper::setOpacity(float value)
261 if (value == opacity())
263 GraphicsLayer::setOpacity(value);
264 notifyChange(OpacityChange);
267 void GraphicsLayerTextureMapper::setContentsRect(const FloatRect& value)
269 if (value == contentsRect())
271 GraphicsLayer::setContentsRect(value);
272 notifyChange(ContentsRectChange);
275 void GraphicsLayerTextureMapper::setContentsToSolidColor(const Color& color)
277 if (color == m_solidColor)
280 m_solidColor = color;
281 notifyChange(BackgroundColorChange);
284 void GraphicsLayerTextureMapper::setContentsToImage(Image* image)
287 // Make the decision about whether the image has changed.
288 // This code makes the assumption that pointer equality on a NativeImagePtr is a valid way to tell if the image is changed.
289 // This assumption is true for the GTK+ port.
290 NativeImagePtr newNativeImagePtr = image->nativeImageForCurrentFrame();
291 if (!newNativeImagePtr)
294 if (newNativeImagePtr == m_compositedNativeImagePtr)
297 m_compositedNativeImagePtr = newNativeImagePtr;
298 if (!m_compositedImage)
299 m_compositedImage = TextureMapperTiledBackingStore::create();
300 m_compositedImage->setContentsToImage(image);
301 m_compositedImage->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
303 m_compositedNativeImagePtr = nullptr;
304 m_compositedImage = nullptr;
307 setContentsToPlatformLayer(m_compositedImage.get(), ContentsLayerPurpose::Image);
308 notifyChange(ContentChange);
309 GraphicsLayer::setContentsToImage(image);
312 void GraphicsLayerTextureMapper::setContentsToPlatformLayer(TextureMapperPlatformLayer* platformLayer, ContentsLayerPurpose purpose)
314 if (platformLayer == m_contentsLayer)
317 GraphicsLayer::setContentsToPlatformLayer(platformLayer, purpose);
318 notifyChange(ContentChange);
321 m_contentsLayer->setClient(0);
323 m_contentsLayer = platformLayer;
326 m_contentsLayer->setClient(this);
329 void GraphicsLayerTextureMapper::setShowDebugBorder(bool show)
331 if (isShowingDebugBorder() == show)
334 GraphicsLayer::setShowDebugBorder(show);
335 notifyChange(DebugVisualsChange);
338 void GraphicsLayerTextureMapper::setShowRepaintCounter(bool show)
340 if (isShowingRepaintCounter() == show)
343 GraphicsLayer::setShowRepaintCounter(show);
344 notifyChange(RepaintCountChange);
347 void GraphicsLayerTextureMapper::flushCompositingStateForThisLayerOnly()
349 prepareBackingStoreIfNeeded();
350 commitLayerChanges();
351 m_layer.syncAnimations(MonotonicTime::now());
354 void GraphicsLayerTextureMapper::prepareBackingStoreIfNeeded()
356 if (shouldHaveBackingStore()) {
357 if (!m_backingStore) {
358 m_backingStore = TextureMapperTiledBackingStore::create();
359 m_changeMask |= BackingStoreChange;
362 if (m_backingStore) {
363 m_backingStore = nullptr;
364 m_changeMask |= BackingStoreChange;
368 updateDebugBorderAndRepaintCount();
371 void GraphicsLayerTextureMapper::updateDebugBorderAndRepaintCount()
373 if (isShowingDebugBorder())
374 updateDebugIndicators();
376 // When this has its own backing store (e.g. Qt WK1), update the repaint count before calling TextureMapperLayer::flushCompositingStateForThisLayerOnly().
377 bool needsToRepaint = shouldHaveBackingStore() && (m_needsDisplay || !m_needsDisplayRect.isEmpty());
378 if (isShowingRepaintCounter() && needsToRepaint) {
379 incrementRepaintCount();
380 m_changeMask |= RepaintCountChange;
384 void GraphicsLayerTextureMapper::setDebugBorder(const Color& color, float width)
386 m_debugBorderColor = color;
387 m_debugBorderWidth = width;
388 m_changeMask |= DebugVisualsChange;
391 void GraphicsLayerTextureMapper::commitLayerChanges()
393 if (m_changeMask == NoChanges)
396 if (m_changeMask & ChildrenChange) {
397 Vector<GraphicsLayer*> rawChildren;
398 rawChildren.reserveInitialCapacity(children().size());
399 for (auto& layer : children())
400 rawChildren.uncheckedAppend(layer.ptr());
401 m_layer.setChildren(rawChildren);
404 if (m_changeMask & MaskLayerChange)
405 m_layer.setMaskLayer(&downcast<GraphicsLayerTextureMapper>(maskLayer())->layer());
407 if (m_changeMask & ReplicaLayerChange)
408 m_layer.setReplicaLayer(&downcast<GraphicsLayerTextureMapper>(replicaLayer())->layer());
410 if (m_changeMask & PositionChange)
411 m_layer.setPosition(position());
413 if (m_changeMask & AnchorPointChange)
414 m_layer.setAnchorPoint(anchorPoint());
416 if (m_changeMask & SizeChange)
417 m_layer.setSize(size());
419 if (m_changeMask & TransformChange)
420 m_layer.setTransform(transform());
422 if (m_changeMask & ChildrenTransformChange)
423 m_layer.setChildrenTransform(childrenTransform());
425 if (m_changeMask & Preserves3DChange)
426 m_layer.setPreserves3D(preserves3D());
428 if (m_changeMask & ContentsRectChange)
429 m_layer.setContentsRect(contentsRect());
431 if (m_changeMask & MasksToBoundsChange)
432 m_layer.setMasksToBounds(masksToBounds());
434 if (m_changeMask & DrawsContentChange)
435 m_layer.setDrawsContent(drawsContent());
437 if (m_changeMask & ContentsVisibleChange)
438 m_layer.setContentsVisible(contentsAreVisible());
440 if (m_changeMask & ContentsOpaqueChange)
441 m_layer.setContentsOpaque(contentsOpaque());
443 if (m_changeMask & BackfaceVisibilityChange)
444 m_layer.setBackfaceVisibility(backfaceVisibility());
446 if (m_changeMask & OpacityChange)
447 m_layer.setOpacity(opacity());
449 if (m_changeMask & BackgroundColorChange)
450 m_layer.setSolidColor(m_solidColor);
452 if (m_changeMask & FilterChange)
453 m_layer.setFilters(filters());
455 if (m_changeMask & BackingStoreChange)
456 m_layer.setBackingStore(m_backingStore.get());
458 if (m_changeMask & DebugVisualsChange)
459 m_layer.setDebugVisuals(isShowingDebugBorder(), debugBorderColor(), debugBorderWidth());
461 if (m_changeMask & RepaintCountChange)
462 m_layer.setRepaintCounter(isShowingRepaintCounter(), repaintCount());
464 if (m_changeMask & ContentChange)
465 m_layer.setContentsLayer(platformLayer());
467 if (m_changeMask & AnimationChange)
468 m_layer.setAnimations(m_animations);
470 if (m_changeMask & AnimationStarted)
471 client().notifyAnimationStarted(this, "", m_animationStartTime);
473 m_changeMask = NoChanges;
476 void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect& rect)
478 if (!m_layer.textureMapper())
481 flushCompositingStateForThisLayerOnly();
484 maskLayer()->flushCompositingState(rect);
486 replicaLayer()->flushCompositingState(rect);
487 for (auto& child : children())
488 child->flushCompositingState(rect);
491 void GraphicsLayerTextureMapper::updateBackingStoreIncludingSubLayers()
493 if (!m_layer.textureMapper())
496 updateBackingStoreIfNeeded();
499 downcast<GraphicsLayerTextureMapper>(*maskLayer()).updateBackingStoreIfNeeded();
501 downcast<GraphicsLayerTextureMapper>(*replicaLayer()).updateBackingStoreIfNeeded();
502 for (auto& child : children())
503 downcast<GraphicsLayerTextureMapper>(child.get()).updateBackingStoreIncludingSubLayers();
506 void GraphicsLayerTextureMapper::updateBackingStoreIfNeeded()
508 TextureMapper* textureMapper = m_layer.textureMapper();
512 if (!shouldHaveBackingStore()) {
513 ASSERT(!m_backingStore);
516 ASSERT(m_backingStore);
518 IntRect dirtyRect = enclosingIntRect(FloatRect(FloatPoint::zero(), m_size));
520 dirtyRect.intersect(enclosingIntRect(m_needsDisplayRect));
521 if (dirtyRect.isEmpty())
524 m_backingStore->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
526 dirtyRect.scale(pageScaleFactor() * deviceScaleFactor());
527 m_backingStore->updateContents(*textureMapper, this, m_size, dirtyRect);
529 m_needsDisplay = false;
530 m_needsDisplayRect = IntRect();
533 bool GraphicsLayerTextureMapper::shouldHaveBackingStore() const
535 return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
538 bool GraphicsLayerTextureMapper::filtersCanBeComposited(const FilterOperations& filters) const
543 for (const auto& filterOperation : filters.operations()) {
544 if (filterOperation->type() == FilterOperation::REFERENCE)
551 bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
553 ASSERT(!keyframesName.isEmpty());
555 if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyTransform && valueList.property() != AnimatedPropertyOpacity))
558 if (valueList.property() == AnimatedPropertyFilter) {
559 int listIndex = validateFilterOperations(valueList);
563 const auto& filters = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
564 if (!filtersCanBeComposited(filters))
568 bool listsMatch = false;
571 if (valueList.property() == AnimatedPropertyTransform)
572 listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0;
574 const MonotonicTime currentTime = MonotonicTime::now();
575 m_animations.add(TextureMapperAnimation(keyframesName, valueList, boxSize, *anim, listsMatch, currentTime - Seconds(timeOffset), 0_s, TextureMapperAnimation::AnimationState::Playing));
576 // m_animationStartTime is the time of the first real frame of animation, now or delayed by a negative offset.
577 if (Seconds(timeOffset) > 0_s)
578 m_animationStartTime = currentTime;
580 m_animationStartTime = currentTime - Seconds(timeOffset);
581 notifyChange(AnimationChange);
582 notifyChange(AnimationStarted);
586 void GraphicsLayerTextureMapper::pauseAnimation(const String& animationName, double timeOffset)
588 m_animations.pause(animationName, Seconds(timeOffset));
591 void GraphicsLayerTextureMapper::removeAnimation(const String& animationName)
593 m_animations.remove(animationName);
596 bool GraphicsLayerTextureMapper::setFilters(const FilterOperations& filters)
598 if (!m_layer.textureMapper())
601 bool canCompositeFilters = filtersCanBeComposited(filters);
602 if (GraphicsLayer::filters() == filters)
603 return canCompositeFilters;
605 if (canCompositeFilters) {
606 if (!GraphicsLayer::setFilters(filters))
608 notifyChange(FilterChange);
609 } else if (GraphicsLayer::filters().size()) {
611 notifyChange(FilterChange);
614 return canCompositeFilters;