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