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