78a0246f7f550882c30d5fd06a24222eec80ac04
[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 #include <wtf/CurrentTime.h>
28
29 #if !USE(COORDINATED_GRAPHICS)
30
31 namespace WebCore {
32
33 std::unique_ptr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerFactory* factory, GraphicsLayerClient& client, Type layerType)
34 {
35     if (!factory)
36         return std::make_unique<GraphicsLayerTextureMapper>(layerType, client);
37
38     return factory->createGraphicsLayer(layerType, client);
39 }
40
41 GraphicsLayerTextureMapper::GraphicsLayerTextureMapper(Type layerType, GraphicsLayerClient& client)
42     : GraphicsLayer(layerType, client)
43     , m_compositedNativeImagePtr(0)
44     , m_changeMask(NoChanges)
45     , m_needsDisplay(false)
46     , m_fixedToViewport(false)
47     , m_debugBorderWidth(0)
48     , m_contentsLayer(0)
49     , m_animationStartTime(0)
50     , m_isScrollable(false)
51 {
52 }
53
54 void GraphicsLayerTextureMapper::notifyChange(ChangeMask changeMask)
55 {
56     bool flushRequired = m_changeMask == NoChanges;
57     m_changeMask |= changeMask;
58
59     if (flushRequired)
60         client().notifyFlushRequired(this);
61 }
62
63 GraphicsLayerTextureMapper::~GraphicsLayerTextureMapper()
64 {
65     if (m_contentsLayer)
66         m_contentsLayer->setClient(0);
67
68     willBeDestroyed();
69 }
70
71 void GraphicsLayerTextureMapper::setNeedsDisplay()
72 {
73     if (!drawsContent())
74         return;
75
76     // The current size might change, thus we need to update the whole display.
77     m_needsDisplay = true;
78     notifyChange(DisplayChange);
79     addRepaintRect(FloatRect(FloatPoint(), m_size));
80 }
81
82 void GraphicsLayerTextureMapper::setContentsNeedsDisplay()
83 {
84     notifyChange(DisplayChange);
85     addRepaintRect(contentsRect());
86 }
87
88 void GraphicsLayerTextureMapper::setNeedsDisplayInRect(const FloatRect& rect, ShouldClipToLayer)
89 {
90     if (!drawsContent())
91         return;
92
93     if (m_needsDisplay)
94         return;
95     m_needsDisplayRect.unite(rect);
96     notifyChange(DisplayChange);
97     addRepaintRect(rect);
98 }
99
100 bool GraphicsLayerTextureMapper::setChildren(const Vector<GraphicsLayer*>& children)
101 {
102     if (GraphicsLayer::setChildren(children)) {
103         notifyChange(ChildrenChange);
104         return true;
105     }
106     return false;
107 }
108
109 void GraphicsLayerTextureMapper::addChild(GraphicsLayer* layer)
110 {
111     notifyChange(ChildrenChange);
112     GraphicsLayer::addChild(layer);
113 }
114
115 void GraphicsLayerTextureMapper::addChildAtIndex(GraphicsLayer* layer, int index)
116 {
117     GraphicsLayer::addChildAtIndex(layer, index);
118     notifyChange(ChildrenChange);
119 }
120
121 void GraphicsLayerTextureMapper::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
122 {
123     GraphicsLayer::addChildAbove(layer, sibling);
124     notifyChange(ChildrenChange);
125 }
126
127 void GraphicsLayerTextureMapper::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
128 {
129     GraphicsLayer::addChildBelow(layer, sibling);
130     notifyChange(ChildrenChange);
131 }
132
133 bool GraphicsLayerTextureMapper::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
134 {
135     if (GraphicsLayer::replaceChild(oldChild, newChild)) {
136         notifyChange(ChildrenChange);
137         return true;
138     }
139     return false;
140 }
141
142 void GraphicsLayerTextureMapper::setMaskLayer(GraphicsLayer* value)
143 {
144     if (value == maskLayer())
145         return;
146     GraphicsLayer::setMaskLayer(value);
147     notifyChange(MaskLayerChange);
148
149     if (!value)
150         return;
151     value->setSize(size());
152     value->setContentsVisible(contentsAreVisible());
153 }
154
155
156 void GraphicsLayerTextureMapper::setReplicatedByLayer(GraphicsLayer* value)
157 {
158     if (value == replicaLayer())
159         return;
160     GraphicsLayer::setReplicatedByLayer(value);
161     notifyChange(ReplicaLayerChange);
162 }
163
164 void GraphicsLayerTextureMapper::setPosition(const FloatPoint& value)
165 {
166     if (value == position())
167         return;
168     GraphicsLayer::setPosition(value);
169     notifyChange(PositionChange);
170 }
171
172 void GraphicsLayerTextureMapper::setAnchorPoint(const FloatPoint3D& value)
173 {
174     if (value == anchorPoint())
175         return;
176     GraphicsLayer::setAnchorPoint(value);
177     notifyChange(AnchorPointChange);
178 }
179
180 void GraphicsLayerTextureMapper::setSize(const FloatSize& value)
181 {
182     if (value == size())
183         return;
184
185     GraphicsLayer::setSize(value);
186     if (maskLayer())
187         maskLayer()->setSize(value);
188     notifyChange(SizeChange);
189 }
190
191 void GraphicsLayerTextureMapper::setTransform(const TransformationMatrix& value)
192 {
193     if (value == transform())
194         return;
195
196     GraphicsLayer::setTransform(value);
197     notifyChange(TransformChange);
198 }
199
200 void GraphicsLayerTextureMapper::setChildrenTransform(const TransformationMatrix& value)
201 {
202     if (value == childrenTransform())
203         return;
204     GraphicsLayer::setChildrenTransform(value);
205     notifyChange(ChildrenTransformChange);
206 }
207
208 void GraphicsLayerTextureMapper::setPreserves3D(bool value)
209 {
210     if (value == preserves3D())
211         return;
212     GraphicsLayer::setPreserves3D(value);
213     notifyChange(Preserves3DChange);
214 }
215
216 void GraphicsLayerTextureMapper::setMasksToBounds(bool value)
217 {
218     if (value == masksToBounds())
219         return;
220     GraphicsLayer::setMasksToBounds(value);
221     notifyChange(MasksToBoundsChange);
222 }
223
224 void GraphicsLayerTextureMapper::setDrawsContent(bool value)
225 {
226     if (value == drawsContent())
227         return;
228     GraphicsLayer::setDrawsContent(value);
229     notifyChange(DrawsContentChange);
230
231     if (value)
232         setNeedsDisplay();
233 }
234
235 void GraphicsLayerTextureMapper::setContentsVisible(bool value)
236 {
237     if (value == contentsAreVisible())
238         return;
239     notifyChange(ContentsVisibleChange);
240     GraphicsLayer::setContentsVisible(value);
241     if (maskLayer())
242         maskLayer()->setContentsVisible(value);
243 }
244
245 void GraphicsLayerTextureMapper::setContentsOpaque(bool value)
246 {
247     if (value == contentsOpaque())
248         return;
249     notifyChange(ContentsOpaqueChange);
250     GraphicsLayer::setContentsOpaque(value);
251 }
252
253 void GraphicsLayerTextureMapper::setBackfaceVisibility(bool value)
254 {
255     if (value == backfaceVisibility())
256         return;
257     GraphicsLayer::setBackfaceVisibility(value);
258     notifyChange(BackfaceVisibilityChange);
259 }
260
261 void GraphicsLayerTextureMapper::setOpacity(float value)
262 {
263     if (value == opacity())
264         return;
265     GraphicsLayer::setOpacity(value);
266     notifyChange(OpacityChange);
267 }
268
269 void GraphicsLayerTextureMapper::setContentsRect(const FloatRect& value)
270 {
271     if (value == contentsRect())
272         return;
273     GraphicsLayer::setContentsRect(value);
274     notifyChange(ContentsRectChange);
275 }
276
277 void GraphicsLayerTextureMapper::setContentsToSolidColor(const Color& color)
278 {
279     if (color == m_solidColor)
280         return;
281
282     m_solidColor = color;
283     notifyChange(BackgroundColorChange);
284 }
285
286 void GraphicsLayerTextureMapper::setContentsToImage(Image* image)
287 {
288     if (image) {
289         // Make the decision about whether the image has changed.
290         // This code makes the assumption that pointer equality on a NativeImagePtr is a valid way to tell if the image is changed.
291         // This assumption is true for the GTK+ port.
292         NativeImagePtr newNativeImagePtr = image->nativeImageForCurrentFrame();
293         if (!newNativeImagePtr)
294             return;
295
296         if (newNativeImagePtr == m_compositedNativeImagePtr)
297             return;
298
299         m_compositedNativeImagePtr = newNativeImagePtr;
300         if (!m_compositedImage)
301             m_compositedImage = TextureMapperTiledBackingStore::create();
302         m_compositedImage->setContentsToImage(image);
303         m_compositedImage->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
304     } else {
305         m_compositedNativeImagePtr = nullptr;
306         m_compositedImage = nullptr;
307     }
308
309     setContentsToPlatformLayer(m_compositedImage.get(), ContentsLayerForImage);
310     notifyChange(ContentChange);
311     GraphicsLayer::setContentsToImage(image);
312 }
313
314 void GraphicsLayerTextureMapper::setContentsToPlatformLayer(TextureMapperPlatformLayer* platformLayer, ContentsLayerPurpose purpose)
315 {
316     if (platformLayer == m_contentsLayer)
317         return;
318
319     GraphicsLayer::setContentsToPlatformLayer(platformLayer, purpose);
320     notifyChange(ContentChange);
321
322     if (m_contentsLayer)
323         m_contentsLayer->setClient(0);
324
325     m_contentsLayer = platformLayer;
326
327     if (m_contentsLayer)
328         m_contentsLayer->setClient(this);
329 }
330
331 void GraphicsLayerTextureMapper::setShowDebugBorder(bool show)
332 {
333     if (isShowingDebugBorder() == show)
334         return;
335
336     GraphicsLayer::setShowDebugBorder(show);
337     notifyChange(DebugVisualsChange);
338 }
339
340 void GraphicsLayerTextureMapper::setShowRepaintCounter(bool show)
341 {
342     if (isShowingRepaintCounter() == show)
343         return;
344
345     GraphicsLayer::setShowRepaintCounter(show);
346     notifyChange(DebugVisualsChange);
347 }
348
349 void GraphicsLayerTextureMapper::didCommitScrollOffset(const IntSize& offset)
350 {
351     if (offset.isZero())
352         return;
353
354     m_committedScrollOffset = offset;
355     notifyChange(CommittedScrollOffsetChange);
356 }
357
358 void GraphicsLayerTextureMapper::setIsScrollable(bool isScrollable)
359 {
360     if (m_isScrollable == isScrollable)
361         return;
362
363     m_isScrollable = isScrollable;
364     notifyChange(IsScrollableChange);
365 }
366
367 void GraphicsLayerTextureMapper::flushCompositingStateForThisLayerOnly()
368 {
369     prepareBackingStoreIfNeeded();
370     commitLayerChanges();
371     m_layer.syncAnimations();
372 }
373
374 void GraphicsLayerTextureMapper::prepareBackingStoreIfNeeded()
375 {
376     if (shouldHaveBackingStore()) {
377         if (!m_backingStore) {
378             m_backingStore = TextureMapperTiledBackingStore::create();
379             m_changeMask |= BackingStoreChange;
380         }
381     } else {
382         if (m_backingStore) {
383             m_backingStore = nullptr;
384             m_changeMask |= BackingStoreChange;
385         }
386     }
387
388     updateDebugBorderAndRepaintCount();
389 }
390
391 void GraphicsLayerTextureMapper::updateDebugBorderAndRepaintCount()
392 {
393     if (isShowingDebugBorder())
394         updateDebugIndicators();
395
396     // When this has its own backing store (e.g. Qt WK1), update the repaint count before calling TextureMapperLayer::flushCompositingStateForThisLayerOnly().
397     bool needsToRepaint = shouldHaveBackingStore() && (m_needsDisplay || !m_needsDisplayRect.isEmpty());
398     if (isShowingRepaintCounter() && needsToRepaint) {
399         incrementRepaintCount();
400         m_changeMask |= RepaintCountChange;
401     }
402 }
403
404 void GraphicsLayerTextureMapper::setDebugBorder(const Color& color, float width)
405 {
406     m_debugBorderColor = color;
407     m_debugBorderWidth = width;
408     m_changeMask |= DebugVisualsChange;
409 }
410
411 void GraphicsLayerTextureMapper::commitLayerChanges()
412 {
413     if (m_changeMask == NoChanges)
414         return;
415
416     if (m_changeMask & ChildrenChange)
417         m_layer.setChildren(children());
418
419     if (m_changeMask & MaskLayerChange)
420         m_layer.setMaskLayer(&downcast<GraphicsLayerTextureMapper>(maskLayer())->layer());
421
422     if (m_changeMask & ReplicaLayerChange)
423         m_layer.setReplicaLayer(&downcast<GraphicsLayerTextureMapper>(replicaLayer())->layer());
424
425     if (m_changeMask & PositionChange)
426         m_layer.setPosition(position());
427
428     if (m_changeMask & AnchorPointChange)
429         m_layer.setAnchorPoint(anchorPoint());
430
431     if (m_changeMask & SizeChange)
432         m_layer.setSize(size());
433
434     if (m_changeMask & TransformChange)
435         m_layer.setTransform(transform());
436
437     if (m_changeMask & ChildrenTransformChange)
438         m_layer.setChildrenTransform(childrenTransform());
439
440     if (m_changeMask & Preserves3DChange)
441         m_layer.setPreserves3D(preserves3D());
442
443     if (m_changeMask & ContentsRectChange)
444         m_layer.setContentsRect(contentsRect());
445
446     if (m_changeMask & MasksToBoundsChange)
447         m_layer.setMasksToBounds(masksToBounds());
448
449     if (m_changeMask & DrawsContentChange)
450         m_layer.setDrawsContent(drawsContent());
451
452     if (m_changeMask & ContentsVisibleChange)
453         m_layer.setContentsVisible(contentsAreVisible());
454
455     if (m_changeMask & ContentsOpaqueChange)
456         m_layer.setContentsOpaque(contentsOpaque());
457
458     if (m_changeMask & BackfaceVisibilityChange)
459         m_layer.setBackfaceVisibility(backfaceVisibility());
460
461     if (m_changeMask & OpacityChange)
462         m_layer.setOpacity(opacity());
463
464     if (m_changeMask & BackgroundColorChange)
465         m_layer.setSolidColor(m_solidColor);
466
467     if (m_changeMask & FilterChange)
468         m_layer.setFilters(filters());
469
470     if (m_changeMask & BackingStoreChange)
471         m_layer.setBackingStore(m_backingStore);
472
473     if (m_changeMask & DebugVisualsChange)
474         m_layer.setDebugVisuals(isShowingDebugBorder(), debugBorderColor(), debugBorderWidth(), isShowingRepaintCounter());
475
476     if (m_changeMask & RepaintCountChange)
477         m_layer.setRepaintCount(repaintCount());
478
479     if (m_changeMask & ContentChange)
480         m_layer.setContentsLayer(platformLayer());
481
482     if (m_changeMask & AnimationChange)
483         m_layer.setAnimations(m_animations);
484
485     if (m_changeMask & AnimationStarted)
486         client().notifyAnimationStarted(this, "", m_animationStartTime);
487
488     if (m_changeMask & FixedToViewporChange)
489         m_layer.setFixedToViewport(fixedToViewport());
490
491     if (m_changeMask & IsScrollableChange)
492         m_layer.setIsScrollable(isScrollable());
493
494     if (m_changeMask & CommittedScrollOffsetChange)
495         m_layer.didCommitScrollOffset(m_committedScrollOffset);
496
497     m_changeMask = NoChanges;
498 }
499
500 void GraphicsLayerTextureMapper::flushCompositingState(const FloatRect& rect)
501 {
502     if (!m_layer.textureMapper())
503         return;
504
505     flushCompositingStateForThisLayerOnly();
506
507     if (maskLayer())
508         maskLayer()->flushCompositingState(rect);
509     if (replicaLayer())
510         replicaLayer()->flushCompositingState(rect);
511     for (auto* child : children())
512         child->flushCompositingState(rect);
513 }
514
515 void GraphicsLayerTextureMapper::updateBackingStoreIncludingSubLayers()
516 {
517     if (!m_layer.textureMapper())
518         return;
519
520     updateBackingStoreIfNeeded();
521
522     if (maskLayer())
523         downcast<GraphicsLayerTextureMapper>(*maskLayer()).updateBackingStoreIfNeeded();
524     if (replicaLayer())
525         downcast<GraphicsLayerTextureMapper>(*replicaLayer()).updateBackingStoreIfNeeded();
526     for (auto* child : children())
527         downcast<GraphicsLayerTextureMapper>(*child).updateBackingStoreIncludingSubLayers();
528 }
529
530 void GraphicsLayerTextureMapper::updateBackingStoreIfNeeded()
531 {
532     TextureMapper* textureMapper = m_layer.textureMapper();
533     if (!textureMapper)
534         return;
535
536     if (!shouldHaveBackingStore()) {
537         ASSERT(!m_backingStore);
538         return;
539     }
540     ASSERT(m_backingStore);
541
542     IntRect dirtyRect = enclosingIntRect(FloatRect(FloatPoint::zero(), m_size));
543     if (!m_needsDisplay)
544         dirtyRect.intersect(enclosingIntRect(m_needsDisplayRect));
545     if (dirtyRect.isEmpty())
546         return;
547
548     TextureMapperTiledBackingStore* backingStore = static_cast<TextureMapperTiledBackingStore*>(m_backingStore.get());
549     backingStore->updateContentsScale(pageScaleFactor() * deviceScaleFactor());
550
551     dirtyRect.scale(pageScaleFactor() * deviceScaleFactor());
552     backingStore->updateContents(*textureMapper, this, m_size, dirtyRect, BitmapTexture::UpdateCanModifyOriginalImageData);
553
554     m_needsDisplay = false;
555     m_needsDisplayRect = IntRect();
556 }
557
558 bool GraphicsLayerTextureMapper::shouldHaveBackingStore() const
559 {
560     return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
561 }
562
563 bool GraphicsLayerTextureMapper::filtersCanBeComposited(const FilterOperations& filters) const
564 {
565     if (!filters.size())
566         return false;
567
568     for (const auto& filterOperation : filters.operations()) {
569         if (filterOperation->type() == FilterOperation::REFERENCE)
570             return false;
571     }
572
573     return true;
574 }
575
576 bool GraphicsLayerTextureMapper::addAnimation(const KeyframeValueList& valueList, const FloatSize& boxSize, const Animation* anim, const String& keyframesName, double timeOffset)
577 {
578     ASSERT(!keyframesName.isEmpty());
579
580     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyTransform && valueList.property() != AnimatedPropertyOpacity))
581         return false;
582
583     if (valueList.property() == AnimatedPropertyFilter) {
584         int listIndex = validateFilterOperations(valueList);
585         if (listIndex < 0)
586             return false;
587
588         const auto& filters = static_cast<const FilterAnimationValue&>(valueList.at(listIndex)).value();
589         if (!filtersCanBeComposited(filters))
590             return false;
591     }
592
593     bool listsMatch = false;
594     bool hasBigRotation;
595
596     if (valueList.property() == AnimatedPropertyTransform)
597         listsMatch = validateTransformOperations(valueList, hasBigRotation) >= 0;
598
599     const double currentTime = monotonicallyIncreasingTime();
600     m_animations.add(TextureMapperAnimation(keyframesName, valueList, boxSize, *anim, listsMatch, currentTime - timeOffset, 0, TextureMapperAnimation::AnimationState::Playing));
601     // m_animationStartTime is the time of the first real frame of animation, now or delayed by a negative offset.
602     if (timeOffset > 0)
603         m_animationStartTime = currentTime;
604     else
605         m_animationStartTime = currentTime - timeOffset;
606     notifyChange(AnimationChange);
607     notifyChange(AnimationStarted);
608     return true;
609 }
610
611 void GraphicsLayerTextureMapper::setAnimations(const TextureMapperAnimations& animations)
612 {
613     m_animations = animations;
614     notifyChange(AnimationChange);
615 }
616
617
618 void GraphicsLayerTextureMapper::pauseAnimation(const String& animationName, double timeOffset)
619 {
620     m_animations.pause(animationName, timeOffset);
621 }
622
623 void GraphicsLayerTextureMapper::removeAnimation(const String& animationName)
624 {
625     m_animations.remove(animationName);
626 }
627
628 bool GraphicsLayerTextureMapper::setFilters(const FilterOperations& filters)
629 {
630     if (!m_layer.textureMapper())
631         return false;
632
633     bool canCompositeFilters = filtersCanBeComposited(filters);
634     if (GraphicsLayer::filters() == filters)
635         return canCompositeFilters;
636
637     if (canCompositeFilters) {
638         if (!GraphicsLayer::setFilters(filters))
639             return false;
640         notifyChange(FilterChange);
641     } else if (GraphicsLayer::filters().size()) {
642         clearFilters();
643         notifyChange(FilterChange);
644     }
645
646     return canCompositeFilters;
647 }
648
649 void GraphicsLayerTextureMapper::setFixedToViewport(bool fixed)
650 {
651     if (m_fixedToViewport == fixed)
652         return;
653
654     m_fixedToViewport = fixed;
655     notifyChange(FixedToViewporChange);
656 }
657
658 void GraphicsLayerTextureMapper::setRepaintCount(int repaintCount)
659 {
660     m_repaintCount = repaintCount;
661     notifyChange(RepaintCountChange);
662 }
663
664 }
665 #endif