Make GraphicsLayers ref-counted, so their tree can persist when disconnected from...
[WebKit-https.git] / Source / WebCore / platform / graphics / texmap / GraphicsLayerTextureMapper.cpp
1 /*
2     Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies)
3
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.
8
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.
13
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.
18 */
19
20 #include "config.h"
21 #include "GraphicsLayerTextureMapper.h"
22
23 #include "GraphicsContext.h"
24 #include "GraphicsLayerFactory.h"
25 #include "ImageBuffer.h"
26 #include "TextureMapperAnimation.h"
27
28 #if !USE(COORDINATED_GRAPHICS)
29
30 namespace WebCore {
31
32 Ref<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client, Type layerType)
33 {
34     if (!factory)
35         return adoptRef(*new GraphicsLayerTextureMapper(layerType, client));
36
37     return factory->createGraphicsLayer(layerType, client);
38 }
39
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)
46     , m_contentsLayer(0)
47 {
48 }
49
50 void GraphicsLayerTextureMapper::notifyChange(ChangeMask changeMask)
51 {
52     bool flushRequired = m_changeMask == NoChanges;
53     m_changeMask |= changeMask;
54
55     if (flushRequired)
56         client().notifyFlushRequired(this);
57 }
58
59 GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper()
60 {
61     if (m_contentsLayer)
62         m_contentsLayer->setClient(0);
63
64     willBeDestroyed();
65 }
66
67 void GraphicsLayerTextureMapper::setNeedsDisplay()
68 {
69     if (!drawsContent())
70         return;
71
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));
76 }
77
78 void GraphicsLayerTextureMapper::setContentsNeedsDisplay()
79 {
80     notifyChange(DisplayChange);
81     addRepaintRect(contentsRect());
82 }
83
84 void GraphicsLayerTextureMapper::setNeedsDisplayInRect(const FloatRect& rect, ShouldClipToLayer)
85 {
86     if (!drawsContent())
87         return;
88
89     if (m_needsDisplay)
90         return;
91     m_needsDisplayRect.unite(rect);
92     notifyChange(DisplayChange);
93     addRepaintRect(rect);
94 }
95
96 bool GraphicsLayerTextureMapper::setChildren(Vector<Ref<GraphicsLayer>>&& children)
97 {
98     if (GraphicsLayer::setChildren(WTFMove(children))) {
99         notifyChange(ChildrenChange);
100         return true;
101     }
102     return false;
103 }
104
105 void GraphicsLayerTextureMapper::addChild(Ref<GraphicsLayer>&& layer)
106 {
107     notifyChange(ChildrenChange);
108     GraphicsLayer::addChild(WTFMove(layer));
109 }
110
111 void GraphicsLayerTextureMapper::addChildAtIndex(Ref<GraphicsLayer>&& layer, int index)
112 {
113     GraphicsLayer::addChildAtIndex(WTFMove(layer), index);
114     notifyChange(ChildrenChange);
115 }
116
117 void GraphicsLayerTextureMapper::addChildAbove(Ref<GraphicsLayer>&& layer, GraphicsLayer* sibling)
118 {
119     GraphicsLayer::addChildAbove(WTFMove(layer), sibling);
120     notifyChange(ChildrenChange);
121 }
122
123 void GraphicsLayerTextureMapper::addChildBelow(Ref<GraphicsLayer>&& layer, GraphicsLayer* sibling)
124 {
125     GraphicsLayer::addChildBelow(WTFMove(layer), sibling);
126     notifyChange(ChildrenChange);
127 }
128
129 bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, Ref<GraphicsLayer>&& newChild)
130 {
131     if (GraphicsLayer::replaceChild(oldChild, WTFMove(newChild))) {
132         notifyChange(ChildrenChange);
133         return true;
134     }
135     return false;
136 }
137
138 void GraphicsLayerTextureMapper::setMaskLayer(RefPtr<GraphicsLayer>&& value)
139 {
140     if (value == maskLayer())
141         return;
142
143     GraphicsLayer* rawLayer = value.get();
144     GraphicsLayer::setMaskLayer(WTFMove(value));
145     notifyChange(MaskLayerChange);
146
147     if (!rawLayer)
148         return;
149     rawLayer->setSize(size());
150     rawLayer->setContentsVisible(contentsAreVisible());
151 }
152
153
154 void GraphicsLayerTextureMapper::setReplicatedByLayer(GraphicsLayer* value)
155 {
156     if (value == replicaLayer())
157         return;
158     GraphicsLayer::setReplicatedByLayer(value);
159     notifyChange(ReplicaLayerChange);
160 }
161
162 void GraphicsLayerTextureMapper::setPosition(const FloatPoint& value)
163 {
164     if (value == position())
165         return;
166     GraphicsLayer::setPosition(value);
167     notifyChange(PositionChange);
168 }
169
170 void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value)
171 {
172     if (value == anchorPoint())
173         return;
174     GraphicsLayer::setAnchorPoint(value);
175     notifyChange(AnchorPointChange);
176 }
177
178 void GraphicsLayerTextureMapper::setSize(const FloatSize& value)
179 {
180     if (value == size())
181         return;
182
183     GraphicsLayer::setSize(value);
184     if (maskLayer())
185         maskLayer()->setSize(value);
186     notifyChange(SizeChange);
187 }
188
189 void GraphicsLayerTextureMapper::setTransform(const TransformationMatrix& value)
190 {
191     if (value == transform())
192         return;
193
194     GraphicsLayer::setTransform(value);
195     notifyChange(TransformChange);
196 }
197
198 void GraphicsLayerTextureMapper::setChildrenTransform(const TransformationMatrix& value)
199 {
200     if (value == childrenTransform())
201         return;
202     GraphicsLayer::setChildrenTransform(value);
203     notifyChange(ChildrenTransformChange);
204 }
205
206 void GraphicsLayerTextureMapper::setPreserves3D(bool value)
207 {
208     if (value == preserves3D())
209         return;
210     GraphicsLayer::setPreserves3D(value);
211     notifyChange(Preserves3DChange);
212 }
213
214 void GraphicsLayerTextureMapper::setMasksToBounds(bool value)
215 {
216     if (value == masksToBounds())
217         return;
218     GraphicsLayer::setMasksToBounds(value);
219     notifyChange(MasksToBoundsChange);
220 }
221
222 void GraphicsLayerTextureMapper::setDrawsContent(bool value)
223 {
224     if (value == drawsContent())
225         return;
226     GraphicsLayer::setDrawsContent(value);
227     notifyChange(DrawsContentChange);
228
229     if (value)
230         setNeedsDisplay();
231 }
232
233 void GraphicsLayerTextureMapper::setContentsVisible(bool value)
234 {
235     if (value == contentsAreVisible())
236         return;
237     notifyChange(ContentsVisibleChange);
238     GraphicsLayer::setContentsVisible(value);
239     if (maskLayer())
240         maskLayer()->setContentsVisible(value);
241 }
242
243 void GraphicsLayerTextureMapper::setContentsOpaque(bool value)
244 {
245     if (value == contentsOpaque())
246         return;
247     notifyChange(ContentsOpaqueChange);
248     GraphicsLayer::setContentsOpaque(value);
249 }
250
251 void GraphicsLayerTextureMapper::setBackfaceVisibility(bool value)
252 {
253     if (value == backfaceVisibility())
254         return;
255     GraphicsLayer::setBackfaceVisibility(value);
256     notifyChange(BackfaceVisibilityChange);
257 }
258
259 void GraphicsLayerTextureMapper::setOpacity(float value)
260 {
261     if (value == opacity())
262         return;
263     GraphicsLayer::setOpacity(value);
264     notifyChange(OpacityChange);
265 }
266
267 void GraphicsLayerTextureMapper::setContentsRect(const FloatRect& value)
268 {
269     if (value == contentsRect())
270         return;
271     GraphicsLayer::setContentsRect(value);
272     notifyChange(ContentsRectChange);
273 }
274
275 void GraphicsLayerTextureMapper::setContentsToSolidColor(const Color& color)
276 {
277     if (color == m_solidColor)
278         return;
279
280     m_solidColor = color;
281     notifyChange(BackgroundColorChange);
282 }
283
284 void GraphicsLayerTextureMapper::setContentsToImage(Image* image)
285 {
286     if (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)
292             return;
293
294         if (newNativeImagePtr == m_compositedNativeImagePtr)
295             return;
296
297         m_compositedNativeImagePtr = newNativeImagePtr;
298         if (!m_compositedImage)
299             m_compositedImage = TextureMapperTiledBackingStore::create();
300         m_compositedImage->setContentsToImage(image);
301         m_compositedImage->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
302     } else {
303         m_compositedNativeImagePtr = nullptr;
304         m_compositedImage = nullptr;
305     }
306
307     setContentsToPlatformLayer(m_compositedImage.get(), ContentsLayerPurpose::Image);
308     notifyChange(ContentChange);
309     GraphicsLayer::setContentsToImage(image);
310 }
311
312 void GraphicsLayerTextureMapper::setContentsToPlatformLayer(TextureMapperPlatformLayer* platformLayer, ContentsLayerPurpose purpose)
313 {
314     if (platformLayer == m_contentsLayer)
315         return;
316
317     GraphicsLayer::setContentsToPlatformLayer(platformLayer, purpose);
318     notifyChange(ContentChange);
319
320     if (m_contentsLayer)
321         m_contentsLayer->setClient(0);
322
323     m_contentsLayer = platformLayer;
324
325     if (m_contentsLayer)
326         m_contentsLayer->setClient(this);
327 }
328
329 void GraphicsLayerTextureMapper::setShowDebugBorder(bool show)
330 {
331     if (isShowingDebugBorder() == show)
332         return;
333
334     GraphicsLayer::setShowDebugBorder(show);
335     notifyChange(DebugVisualsChange);
336 }
337
338 void GraphicsLayerTextureMapper::setShowRepaintCounter(bool show)
339 {
340     if (isShowingRepaintCounter() == show)
341         return;
342
343     GraphicsLayer::setShowRepaintCounter(show);
344     notifyChange(RepaintCountChange);
345 }
346
347 void GraphicsLayerTextureMapper::flushCompositingStateForThisLayerOnly()
348 {
349     prepareBackingStoreIfNeeded();
350     commitLayerChanges();
351     m_layer.syncAnimations(MonotonicTime::now());
352 }
353
354 void GraphicsLayerTextureMapper::prepareBackingStoreIfNeeded()
355 {
356     if (shouldHaveBackingStore()) {
357         if (!m_backingStore) {
358             m_backingStore = TextureMapperTiledBackingStore::create();
359             m_changeMask |= BackingStoreChange;
360         }
361     } else {
362         if (m_backingStore) {
363             m_backingStore = nullptr;
364             m_changeMask |= BackingStoreChange;
365         }
366     }
367
368     updateDebugBorderAndRepaintCount();
369 }
370
371 void GraphicsLayerTextureMapper::updateDebugBorderAndRepaintCount()
372 {
373     if (isShowingDebugBorder())
374         updateDebugIndicators();
375
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;
381     }
382 }
383
384 void GraphicsLayerTextureMapper::setDebugBorder(const Color& color, float width)
385 {
386     m_debugBorderColor = color;
387     m_debugBorderWidth = width;
388     m_changeMask |= DebugVisualsChange;
389 }
390
391 void GraphicsLayerTextureMapper::commitLayerChanges()
392 {
393     if (m_changeMask == NoChanges)
394         return;
395
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);
402     }
403
404     if (m_changeMask & MaskLayerChange)
405         m_layer.setMaskLayer(&downcast<GraphicsLayerTextureMapper>(maskLayer())->layer());
406
407     if (m_changeMask & ReplicaLayerChange)
408         m_layer.setReplicaLayer(&downcast<GraphicsLayerTextureMapper>(replicaLayer())->layer());
409
410     if (m_changeMask & PositionChange)
411         m_layer.setPosition(position());
412
413     if (m_changeMask & AnchorPointChange)
414         m_layer.setAnchorPoint(anchorPoint());
415
416     if (m_changeMask & SizeChange)
417         m_layer.setSize(size());
418
419     if (m_changeMask & TransformChange)
420         m_layer.setTransform(transform());
421
422     if (m_changeMask & ChildrenTransformChange)
423         m_layer.setChildrenTransform(childrenTransform());
424
425     if (m_changeMask & Preserves3DChange)
426         m_layer.setPreserves3D(preserves3D());
427
428     if (m_changeMask & ContentsRectChange)
429         m_layer.setContentsRect(contentsRect());
430
431     if (m_changeMask & MasksToBoundsChange)
432         m_layer.setMasksToBounds(masksToBounds());
433
434     if (m_changeMask & DrawsContentChange)
435         m_layer.setDrawsContent(drawsContent());
436
437     if (m_changeMask & ContentsVisibleChange)
438         m_layer.setContentsVisible(contentsAreVisible());
439
440     if (m_changeMask & ContentsOpaqueChange)
441         m_layer.setContentsOpaque(contentsOpaque());
442
443     if (m_changeMask & BackfaceVisibilityChange)
444         m_layer.setBackfaceVisibility(backfaceVisibility());
445
446     if (m_changeMask & OpacityChange)
447         m_layer.setOpacity(opacity());
448
449     if (m_changeMask & BackgroundColorChange)
450         m_layer.setSolidColor(m_solidColor);
451
452     if (m_changeMask & FilterChange)
453         m_layer.setFilters(filters());
454
455     if (m_changeMask & BackingStoreChange)
456         m_layer.setBackingStore(m_backingStore.get());
457
458     if (m_changeMask & DebugVisualsChange)
459         m_layer.setDebugVisuals(isShowingDebugBorder(), debugBorderColor(), debugBorderWidth());
460
461     if (m_changeMask & RepaintCountChange)
462         m_layer.setRepaintCounter(isShowingRepaintCounter(), repaintCount());
463
464     if (m_changeMask & ContentChange)
465         m_layer.setContentsLayer(platformLayer());
466
467     if (m_changeMask & AnimationChange)
468         m_layer.setAnimations(m_animations);
469
470     if (m_changeMask & AnimationStarted)
471         client().notifyAnimationStarted(this, "", m_animationStartTime);
472
473     m_changeMask = NoChanges;
474 }
475
476 void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect& rect)
477 {
478     if (!m_layer.textureMapper())
479         return;
480
481     flushCompositingStateForThisLayerOnly();
482
483     if (maskLayer())
484         maskLayer()->flushCompositingState(rect);
485     if (replicaLayer())
486         replicaLayer()->flushCompositingState(rect);
487     for (auto& child : children())
488         child->flushCompositingState(rect);
489 }
490
491 void GraphicsLayerTextureMapper::updateBackingStoreIncludingSubLayers()
492 {
493     if (!m_layer.textureMapper())
494         return;
495
496     updateBackingStoreIfNeeded();
497
498     if (maskLayer())
499         downcast<GraphicsLayerTextureMapper>(*maskLayer()).updateBackingStoreIfNeeded();
500     if (replicaLayer())
501         downcast<GraphicsLayerTextureMapper>(*replicaLayer()).updateBackingStoreIfNeeded();
502     for (auto& child : children())
503         downcast<GraphicsLayerTextureMapper>(child.get()).updateBackingStoreIncludingSubLayers();
504 }
505
506 void GraphicsLayerTextureMapper::updateBackingStoreIfNeeded()
507 {
508     TextureMapper* textureMapper = m_layer.textureMapper();
509     if (!textureMapper)
510         return;
511
512     if (!shouldHaveBackingStore()) {
513         ASSERT(!m_backingStore);
514         return;
515     }
516     ASSERT(m_backingStore);
517
518     IntRect dirtyRect = enclosingIntRect(FloatRect(FloatPoint::zero(), m_size));
519     if (!m_needsDisplay)
520         dirtyRect.intersect(enclosingIntRect(m_needsDisplayRect));
521     if (dirtyRect.isEmpty())
522         return;
523
524     m_backingStore->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
525
526     dirtyRect.scale(pageScaleFactor() * deviceScaleFactor());
527     m_backingStore->updateContents(*textureMapper, this, m_size, dirtyRect);
528
529     m_needsDisplay = false;
530     m_needsDisplayRect = IntRect();
531 }
532
533 bool GraphicsLayerTextureMapper::shouldHaveBackingStore() const
534 {
535     return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
536 }
537
538 bool GraphicsLayerTextureMapper::filtersCanBeComposited(const FilterOperations& filters) const
539 {
540     if (!filters.size())
541         return false;
542
543     for (const auto& filterOperation : filters.operations()) {
544         if (filterOperation->type() == FilterOperation::REFERENCE)
545             return false;
546     }
547
548     return true;
549 }
550
551 bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
552 {
553     ASSERT(!keyframesName.isEmpty());
554
555     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyTransform && valueList.property() != AnimatedPropertyOpacity))
556         return false;
557
558     if (valueList.property() == AnimatedPropertyFilter) {
559         int listIndex = validateFilterOperations(valueList);
560         if (listIndex < 0)
561             return false;
562
563         const auto& filters = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
564         if (!filtersCanBeComposited(filters))
565             return false;
566     }
567
568     bool listsMatch = false;
569     bool hasBigRotation;
570
571     if (valueList.property() == AnimatedPropertyTransform)
572         listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0;
573
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;
579     else
580         m_animationStartTime = currentTime - Seconds(timeOffset);
581     notifyChange(AnimationChange);
582     notifyChange(AnimationStarted);
583     return true;
584 }
585
586 void GraphicsLayerTextureMapper::pauseAnimation(const String& animationName, double timeOffset)
587 {
588     m_animations.pause(animationName, Seconds(timeOffset));
589 }
590
591 void GraphicsLayerTextureMapper::removeAnimation(const String& animationName)
592 {
593     m_animations.remove(animationName);
594 }
595
596 bool GraphicsLayerTextureMapper::setFilters(const FilterOperations& filters)
597 {
598     if (!m_layer.textureMapper())
599         return false;
600
601     bool canCompositeFilters = filtersCanBeComposited(filters);
602     if (GraphicsLayer::filters() == filters)
603         return canCompositeFilters;
604
605     if (canCompositeFilters) {
606         if (!GraphicsLayer::setFilters(filters))
607             return false;
608         notifyChange(FilterChange);
609     } else if (GraphicsLayer::filters().size()) {
610         clearFilters();
611         notifyChange(FilterChange);
612     }
613
614     return canCompositeFilters;
615 }
616
617 }
618 #endif