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