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