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