Accelerated overflow scrolling for Coordinated Graphics.
[WebKit-https.git] / Source / WebCore / platform / graphics / texmap / coordinated / CoordinatedGraphicsLayer.cpp
1 /*
2  Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies)
3  Copyright (C) 2010 Apple Inc. All rights reserved.
4  Copyright (C) 2012 Company 100, Inc.
5  Copyright (C) 2012 Intel Corporation. All rights reserved.
6
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Library General Public
9  License as published by the Free Software Foundation; either
10  version 2 of the License, or (at your option) any later version.
11
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  Library General Public License for more details.
16
17  You should have received a copy of the GNU Library General Public License
18  along with this library; see the file COPYING.LIB.  If not, write to
19  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20  Boston, MA 02110-1301, USA.
21  */
22
23 #include "config.h"
24
25 #if USE(COORDINATED_GRAPHICS)
26 #include "CoordinatedGraphicsLayer.h"
27
28 #include "CoordinatedTile.h"
29 #include "FloatQuad.h"
30 #include "Frame.h"
31 #include "FrameView.h"
32 #include "GraphicsContext.h"
33 #include "GraphicsLayer.h"
34 #include "Page.h"
35 #include "ScrollableArea.h"
36 #include "TextureMapperPlatformLayer.h"
37 #include <wtf/CurrentTime.h>
38 #include <wtf/HashMap.h>
39 #ifndef NDEBUG
40 #include <wtf/TemporaryChange.h>
41 #endif
42 #include <wtf/text/CString.h>
43
44 namespace WebCore {
45
46 static CoordinatedLayerID toCoordinatedLayerID(GraphicsLayer* layer)
47 {
48     return layer ? toCoordinatedGraphicsLayer(layer)->id() : 0;
49 }
50
51 void CoordinatedGraphicsLayer::didChangeLayerState()
52 {
53     m_shouldSyncLayerState = true;
54     if (client())
55         client()->notifyFlushRequired(this);
56 }
57
58 void CoordinatedGraphicsLayer::didChangeAnimations()
59 {
60     m_shouldSyncAnimations = true;
61     if (client())
62         client()->notifyFlushRequired(this);
63 }
64
65 void CoordinatedGraphicsLayer::didChangeChildren()
66 {
67     m_shouldSyncChildren = true;
68     if (client())
69         client()->notifyFlushRequired(this);
70 }
71
72 #if ENABLE(CSS_FILTERS)
73 void CoordinatedGraphicsLayer::didChangeFilters()
74 {
75     m_shouldSyncFilters = true;
76     if (client())
77         client()->notifyFlushRequired(this);
78 }
79 #endif
80
81 void CoordinatedGraphicsLayer::didChangeImageBacking()
82 {
83     m_shouldSyncImageBacking = true;
84     if (client())
85         client()->notifyFlushRequired(this);
86 }
87
88 void CoordinatedGraphicsLayer::setShouldUpdateVisibleRect()
89 {
90     m_shouldUpdateVisibleRect = true;
91     for (size_t i = 0; i < children().size(); ++i)
92         toCoordinatedGraphicsLayer(children()[i])->setShouldUpdateVisibleRect();
93     if (replicaLayer())
94         toCoordinatedGraphicsLayer(replicaLayer())->setShouldUpdateVisibleRect();
95 }
96
97 void CoordinatedGraphicsLayer::didChangeGeometry()
98 {
99     didChangeLayerState();
100     setShouldUpdateVisibleRect();
101 }
102
103 CoordinatedGraphicsLayer::CoordinatedGraphicsLayer(GraphicsLayerClient* client)
104     : GraphicsLayer(client)
105 #ifndef NDEBUG
106     , m_isPurging(false)
107 #endif
108     , m_shouldUpdateVisibleRect(true)
109     , m_shouldSyncLayerState(true)
110     , m_shouldSyncChildren(true)
111     , m_shouldSyncFilters(true)
112     , m_shouldSyncImageBacking(true)
113     , m_shouldSyncAnimations(true)
114     , m_fixedToViewport(false)
115     , m_movingVisibleRect(false)
116     , m_pendingContentsScaleAdjustment(false)
117     , m_pendingVisibleRectAdjustment(false)
118 #if USE(GRAPHICS_SURFACE)
119     , m_isValidCanvas(false)
120     , m_pendingCanvasOperation(None)
121 #endif
122     , m_coordinator(0)
123     , m_compositedNativeImagePtr(0)
124     , m_canvasPlatformLayer(0)
125     , m_animationStartedTimer(this, &CoordinatedGraphicsLayer::animationStartedTimerFired)
126     , m_scrollableArea(0)
127 {
128     static CoordinatedLayerID nextLayerID = 1;
129     m_id = nextLayerID++;
130 }
131
132 CoordinatedGraphicsLayer::~CoordinatedGraphicsLayer()
133 {
134     if (m_coordinator) {
135         purgeBackingStores();
136         m_coordinator->detachLayer(this);
137     }
138     ASSERT(!m_coordinatedImageBacking && !m_mainBackingStore);
139     willBeDestroyed();
140 }
141
142 bool CoordinatedGraphicsLayer::setChildren(const Vector<GraphicsLayer*>& children)
143 {
144     bool ok = GraphicsLayer::setChildren(children);
145     if (!ok)
146         return false;
147     didChangeChildren();
148     return true;
149 }
150
151 void CoordinatedGraphicsLayer::addChild(GraphicsLayer* layer)
152 {
153     GraphicsLayer::addChild(layer);
154     didChangeChildren();
155 }
156
157 void CoordinatedGraphicsLayer::addChildAtIndex(GraphicsLayer* layer, int index)
158 {
159     GraphicsLayer::addChildAtIndex(layer, index);
160     didChangeChildren();
161 }
162
163 void CoordinatedGraphicsLayer::addChildAbove(GraphicsLayer* layer, GraphicsLayer* sibling)
164 {
165     GraphicsLayer::addChildAbove(layer, sibling);
166     didChangeChildren();
167 }
168
169 void CoordinatedGraphicsLayer::addChildBelow(GraphicsLayer* layer, GraphicsLayer* sibling)
170 {
171     GraphicsLayer::addChildBelow(layer, sibling);
172     didChangeChildren();
173 }
174
175 bool CoordinatedGraphicsLayer::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
176 {
177     bool ok = GraphicsLayer::replaceChild(oldChild, newChild);
178     if (!ok)
179         return false;
180     didChangeChildren();
181     return true;
182 }
183
184 void CoordinatedGraphicsLayer::removeFromParent()
185 {
186     if (CoordinatedGraphicsLayer* parentLayer = toCoordinatedGraphicsLayer(parent()))
187         parentLayer->didChangeChildren();
188     GraphicsLayer::removeFromParent();
189 }
190
191 void CoordinatedGraphicsLayer::setPosition(const FloatPoint& p)
192 {
193     if (position() == p)
194         return;
195
196     GraphicsLayer::setPosition(p);
197     m_layerState.positionChanged = true;
198     didChangeGeometry();
199 }
200
201 void CoordinatedGraphicsLayer::setAnchorPoint(const FloatPoint3D& p)
202 {
203     if (anchorPoint() == p)
204         return;
205
206     GraphicsLayer::setAnchorPoint(p);
207     m_layerState.anchorPointChanged = true;
208     didChangeGeometry();
209 }
210
211 void CoordinatedGraphicsLayer::setSize(const FloatSize& size)
212 {
213     if (this->size() == size)
214         return;
215
216     GraphicsLayer::setSize(size);
217     m_layerState.sizeChanged = true;
218
219     if (maskLayer())
220         maskLayer()->setSize(size);
221     didChangeGeometry();
222 }
223
224 void CoordinatedGraphicsLayer::setTransform(const TransformationMatrix& t)
225 {
226     if (transform() == t)
227         return;
228
229     GraphicsLayer::setTransform(t);
230     m_layerState.transformChanged = true;
231
232     didChangeGeometry();
233 }
234
235 void CoordinatedGraphicsLayer::setChildrenTransform(const TransformationMatrix& t)
236 {
237     if (childrenTransform() == t)
238         return;
239
240     GraphicsLayer::setChildrenTransform(t);
241     m_layerState.childrenTransformChanged = true;
242
243     didChangeGeometry();
244 }
245
246 void CoordinatedGraphicsLayer::setPreserves3D(bool b)
247 {
248     if (preserves3D() == b)
249         return;
250
251     GraphicsLayer::setPreserves3D(b);
252     m_layerState.preserves3D = b;
253     m_layerState.flagsChanged = true;
254
255     didChangeGeometry();
256 }
257
258 void CoordinatedGraphicsLayer::setMasksToBounds(bool b)
259 {
260     if (masksToBounds() == b)
261         return;
262     GraphicsLayer::setMasksToBounds(b);
263     m_layerState.masksToBounds = b;
264     m_layerState.flagsChanged = true;
265
266     didChangeGeometry();
267 }
268
269 void CoordinatedGraphicsLayer::setDrawsContent(bool b)
270 {
271     if (drawsContent() == b)
272         return;
273     GraphicsLayer::setDrawsContent(b);
274     m_layerState.drawsContent = b;
275     m_layerState.flagsChanged = true;
276
277     didChangeLayerState();
278 }
279
280 void CoordinatedGraphicsLayer::setContentsVisible(bool b)
281 {
282     if (contentsAreVisible() == b)
283         return;
284     GraphicsLayer::setContentsVisible(b);
285     m_layerState.contentsVisible = b;
286     m_layerState.flagsChanged = true;
287
288     if (maskLayer())
289         maskLayer()->setContentsVisible(b);
290
291     didChangeLayerState();
292 }
293
294 void CoordinatedGraphicsLayer::setContentsOpaque(bool b)
295 {
296     if (contentsOpaque() == b)
297         return;
298     if (m_mainBackingStore)
299         m_mainBackingStore->setSupportsAlpha(!b);
300     GraphicsLayer::setContentsOpaque(b);
301     m_layerState.contentsOpaque = b;
302     m_layerState.flagsChanged = true;
303
304     didChangeLayerState();
305 }
306
307 void CoordinatedGraphicsLayer::setBackfaceVisibility(bool b)
308 {
309     if (backfaceVisibility() == b)
310         return;
311
312     GraphicsLayer::setBackfaceVisibility(b);
313     m_layerState.backfaceVisible = b;
314     m_layerState.flagsChanged = true;
315
316     didChangeLayerState();
317 }
318
319 void CoordinatedGraphicsLayer::setOpacity(float opacity)
320 {
321     if (this->opacity() == opacity)
322         return;
323
324     GraphicsLayer::setOpacity(opacity);
325     m_layerState.opacity = opacity;
326     m_layerState.opacityChanged = true;
327
328     didChangeLayerState();
329 }
330
331 void CoordinatedGraphicsLayer::setContentsRect(const IntRect& r)
332 {
333     if (contentsRect() == r)
334         return;
335
336     GraphicsLayer::setContentsRect(r);
337     m_layerState.contentsRect = r;
338     m_layerState.contentsRectChanged = true;
339
340     didChangeLayerState();
341 }
342
343 void CoordinatedGraphicsLayer::setContentsNeedsDisplay()
344 {
345 #if USE(GRAPHICS_SURFACE)
346     if (m_canvasPlatformLayer)
347         m_pendingCanvasOperation |= SyncCanvas;
348 #endif
349
350     if (client())
351         client()->notifyFlushRequired(this);
352
353     addRepaintRect(contentsRect());
354 }
355
356 void CoordinatedGraphicsLayer::setContentsToCanvas(PlatformLayer* platformLayer)
357 {
358 #if USE(GRAPHICS_SURFACE)
359     if (m_canvasPlatformLayer) {
360         ASSERT(m_canvasToken.isValid());
361         if (!platformLayer) {
362             m_pendingCanvasOperation |= DestroyCanvas;
363             m_pendingCanvasOperation &= ~CreateCanvas;
364         }  else if ((m_canvasSize != platformLayer->platformLayerSize()) || (m_canvasToken != platformLayer->graphicsSurfaceToken())) {
365             // m_canvasToken can be different to platformLayer->graphicsSurfaceToken(), even if m_canvasPlatformLayer equals platformLayer.
366             m_pendingCanvasOperation |= RecreateCanvas;
367         }
368     } else {
369         if (platformLayer)
370             m_pendingCanvasOperation |= CreateAndSyncCanvas;
371     }
372
373     m_canvasPlatformLayer = platformLayer;
374     // m_canvasToken is updated only here. In detail, when GraphicsContext3D is changed or reshaped, m_canvasToken is changed and setContentsToCanvas() is always called.
375     m_canvasSize = m_canvasPlatformLayer ? m_canvasPlatformLayer->platformLayerSize() : IntSize();
376     m_canvasToken = m_canvasPlatformLayer ? m_canvasPlatformLayer->graphicsSurfaceToken() : GraphicsSurfaceToken();
377     ASSERT(!(!m_canvasToken.isValid() && m_canvasPlatformLayer));
378
379     if (client())
380         client()->notifyFlushRequired(this);
381 #else
382     UNUSED_PARAM(platformLayer);
383 #endif
384 }
385
386 #if ENABLE(CSS_FILTERS)
387 bool CoordinatedGraphicsLayer::setFilters(const FilterOperations& newFilters)
388 {
389     if (filters() == newFilters)
390         return true;
391
392     if (!GraphicsLayer::setFilters(newFilters))
393         return false;
394
395     didChangeFilters();
396     return true;
397 }
398 #endif
399
400 void CoordinatedGraphicsLayer::setContentsToSolidColor(const Color& color)
401 {
402     if (m_layerState.solidColor == color)
403         return;
404
405     m_layerState.solidColor = color;
406     m_layerState.solidColorChanged = true;
407
408     didChangeLayerState();
409 }
410
411 void CoordinatedGraphicsLayer::setShowDebugBorder(bool show)
412 {
413     if (isShowingDebugBorder() == show)
414         return;
415
416     GraphicsLayer::setShowDebugBorder(show);
417     m_layerState.showDebugBorders = true;
418     m_layerState.flagsChanged = true;
419
420     didChangeLayerState();
421 }
422
423 void CoordinatedGraphicsLayer::setShowRepaintCounter(bool show)
424 {
425     if (isShowingRepaintCounter() == show)
426         return;
427
428     GraphicsLayer::setShowRepaintCounter(show);
429     m_layerState.showRepaintCounter = true;
430     m_layerState.flagsChanged = true;
431
432     didChangeLayerState();
433 }
434
435 void CoordinatedGraphicsLayer::setContentsToImage(Image* image)
436 {
437     NativeImagePtr newNativeImagePtr = image ? image->nativeImageForCurrentFrame() : 0;
438     if (newNativeImagePtr) {
439         // This code makes the assumption that pointer equality on a NativeImagePtr is a valid way to tell if the image is changed.
440         // This assumption is true in Qt, GTK and EFL.
441         if (newNativeImagePtr == m_compositedNativeImagePtr)
442             return;
443
444         m_compositedImage = image;
445         m_compositedNativeImagePtr = newNativeImagePtr;
446     } else {
447         m_compositedImage = 0;
448         m_compositedNativeImagePtr = 0;
449     }
450
451     GraphicsLayer::setContentsToImage(image);
452     didChangeImageBacking();
453 }
454
455 void CoordinatedGraphicsLayer::setMaskLayer(GraphicsLayer* layer)
456 {
457     if (layer == maskLayer())
458         return;
459
460     GraphicsLayer::setMaskLayer(layer);
461
462     if (!layer)
463         return;
464
465     layer->setSize(size());
466     layer->setContentsVisible(contentsAreVisible());
467     CoordinatedGraphicsLayer* coordinatedLayer = toCoordinatedGraphicsLayer(layer);
468     coordinatedLayer->didChangeLayerState();
469
470     m_layerState.mask = coordinatedLayer->id();
471     m_layerState.maskChanged = true;
472
473     didChangeLayerState();
474 }
475
476 bool CoordinatedGraphicsLayer::shouldDirectlyCompositeImage(Image* image) const
477 {
478     if (!image || !image->isBitmapImage())
479         return false;
480
481     enum { MaxDimenstionForDirectCompositing = 2000 };
482     if (image->width() > MaxDimenstionForDirectCompositing || image->height() > MaxDimenstionForDirectCompositing)
483         return false;
484
485     return true;
486 }
487
488 void CoordinatedGraphicsLayer::setReplicatedByLayer(GraphicsLayer* layer)
489 {
490     if (layer == replicaLayer())
491         return;
492
493     GraphicsLayer::setReplicatedByLayer(layer);
494     m_layerState.replica = toCoordinatedLayerID(layer);
495     m_layerState.replicaChanged = true;
496     didChangeLayerState();
497 }
498
499 void CoordinatedGraphicsLayer::setNeedsDisplay()
500 {
501     setNeedsDisplayInRect(FloatRect(FloatPoint(), size()));
502 }
503
504 void CoordinatedGraphicsLayer::setNeedsDisplayInRect(const FloatRect& rect)
505 {
506     if (m_mainBackingStore)
507         m_mainBackingStore->invalidate(IntRect(rect));
508
509     didChangeLayerState();
510
511     addRepaintRect(rect);
512 }
513
514 CoordinatedLayerID CoordinatedGraphicsLayer::id() const
515 {
516     return m_id;
517 }
518
519 void CoordinatedGraphicsLayer::setScrollableArea(ScrollableArea* scrollableArea)
520 {
521     bool oldScrollable = isScrollable();
522     m_scrollableArea = scrollableArea;
523     if (oldScrollable == isScrollable())
524         return;
525
526     m_layerState.isScrollable = isScrollable();
527     m_layerState.isScrollableChanged = true;
528     didChangeLayerState();
529 }
530
531 void CoordinatedGraphicsLayer::commitScrollOffset(const IntSize& offset)
532 {
533     if (!isScrollable() || offset.isZero())
534         return;
535
536     m_scrollableArea->notifyScrollPositionChanged(m_scrollableArea->scrollPosition() + offset);
537     m_layerState.committedScrollOffset += offset;
538     m_layerState.committedScrollOffsetChanged = true;
539     didChangeLayerState();
540 }
541
542 void CoordinatedGraphicsLayer::setFixedToViewport(bool isFixed)
543 {
544     if (m_fixedToViewport == isFixed)
545         return;
546
547     m_fixedToViewport = isFixed;
548     m_layerState.fixedToViewport = isFixed;
549     m_layerState.flagsChanged = true;
550
551     didChangeLayerState();
552 }
553
554 void CoordinatedGraphicsLayer::flushCompositingState(const FloatRect& rect)
555 {
556     if (!m_coordinator->isFlushingLayerChanges()) {
557         if (client())
558             client()->notifyFlushRequired(this);
559         return;
560     }
561
562     if (CoordinatedGraphicsLayer* mask = toCoordinatedGraphicsLayer(maskLayer()))
563         mask->flushCompositingStateForThisLayerOnly();
564
565     if (CoordinatedGraphicsLayer* replica = toCoordinatedGraphicsLayer(replicaLayer()))
566         replica->flushCompositingStateForThisLayerOnly();
567
568     flushCompositingStateForThisLayerOnly();
569
570     for (size_t i = 0; i < children().size(); ++i)
571         children()[i]->flushCompositingState(rect);
572 }
573
574 CoordinatedGraphicsLayer* toCoordinatedGraphicsLayer(GraphicsLayer* layer)
575 {
576     return static_cast<CoordinatedGraphicsLayer*>(layer);
577 }
578
579 void CoordinatedGraphicsLayer::syncChildren()
580 {
581     if (!m_shouldSyncChildren)
582         return;
583     m_shouldSyncChildren = false;
584     m_layerState.childrenChanged = true;
585     m_layerState.children.clear();
586     for (size_t i = 0; i < children().size(); ++i)
587         m_layerState.children.append(toCoordinatedLayerID(children()[i]));
588 }
589
590 #if ENABLE(CSS_FILTERS)
591 void CoordinatedGraphicsLayer::syncFilters()
592 {
593     if (!m_shouldSyncFilters)
594         return;
595     m_shouldSyncFilters = false;
596
597     m_layerState.filters = GraphicsLayer::filters();
598     m_layerState.filtersChanged = true;
599 }
600 #endif
601
602 void CoordinatedGraphicsLayer::syncImageBacking()
603 {
604     if (!m_shouldSyncImageBacking)
605         return;
606     m_shouldSyncImageBacking = false;
607
608     if (m_compositedNativeImagePtr) {
609         ASSERT(!shouldHaveBackingStore());
610         ASSERT(m_compositedImage);
611
612         bool imageInstanceReplaced = m_coordinatedImageBacking && (m_coordinatedImageBacking->id() != CoordinatedImageBacking::getCoordinatedImageBackingID(m_compositedImage.get()));
613         if (imageInstanceReplaced)
614             releaseImageBackingIfNeeded();
615
616         if (!m_coordinatedImageBacking) {
617             m_coordinatedImageBacking = m_coordinator->createImageBackingIfNeeded(m_compositedImage.get());
618             m_coordinatedImageBacking->addHost(this);
619             m_layerState.imageID = m_coordinatedImageBacking->id();
620         }
621
622         m_coordinatedImageBacking->markDirty();
623         m_layerState.imageChanged = true;
624     } else
625         releaseImageBackingIfNeeded();
626
627     // syncImageBacking() changed m_layerState.imageID.
628     didChangeLayerState();
629 }
630
631 void CoordinatedGraphicsLayer::syncLayerState()
632 {
633     if (!m_shouldSyncLayerState)
634         return;
635     m_shouldSyncLayerState = false;
636
637     m_layerState.childrenTransform = childrenTransform();
638     m_layerState.contentsRect = contentsRect();
639     m_layerState.mask = toCoordinatedLayerID(maskLayer());
640     m_layerState.opacity = opacity();
641     m_layerState.replica = toCoordinatedLayerID(replicaLayer());
642     m_layerState.transform = transform();
643
644     m_layerState.anchorPoint = m_adjustedAnchorPoint;
645     m_layerState.pos = m_adjustedPosition;
646     m_layerState.size = m_adjustedSize;
647
648     if (m_layerState.showDebugBorders)
649         updateDebugIndicators();
650 }
651
652 void CoordinatedGraphicsLayer::setDebugBorder(const Color& color, float width)
653 {
654     ASSERT(m_layerState.showDebugBorders);
655     if (m_layerState.debugBorderColor != color) {
656         m_layerState.debugBorderColor = color;
657         m_layerState.debugBorderColorChanged = true;
658     }
659
660     if (m_layerState.debugBorderWidth != width) {
661         m_layerState.debugBorderWidth = width;
662         m_layerState.debugBorderWidthChanged = true;
663     }
664 }
665
666 void CoordinatedGraphicsLayer::syncAnimations()
667 {
668     if (!m_shouldSyncAnimations)
669         return;
670
671     m_shouldSyncAnimations = false;
672     m_layerState.animations = m_animations.getActiveAnimations();
673     m_layerState.animationsChanged = true;
674 }
675
676 #if USE(GRAPHICS_SURFACE)
677 void CoordinatedGraphicsLayer::syncCanvas()
678 {
679     destroyCanvasIfNeeded();
680     createCanvasIfNeeded();
681
682     if (!(m_pendingCanvasOperation & SyncCanvas))
683         return;
684
685     m_pendingCanvasOperation &= ~SyncCanvas;
686
687     if (!m_isValidCanvas)
688         return;
689
690     ASSERT(m_canvasPlatformLayer);
691     m_layerState.canvasFrontBuffer = m_canvasPlatformLayer->copyToGraphicsSurface();
692     m_layerState.canvasShouldSwapBuffers = true;
693 }
694
695 void CoordinatedGraphicsLayer::destroyCanvasIfNeeded()
696 {
697     if (!(m_pendingCanvasOperation & DestroyCanvas))
698         return;
699
700     if (m_isValidCanvas) {
701         m_isValidCanvas = false;
702         m_layerState.canvasToken = GraphicsSurfaceToken();
703         m_layerState.canvasChanged = true;
704     }
705
706     m_pendingCanvasOperation &= ~DestroyCanvas;
707 }
708
709 void CoordinatedGraphicsLayer::createCanvasIfNeeded()
710 {
711     if (!(m_pendingCanvasOperation & CreateCanvas))
712         return;
713
714     ASSERT(m_canvasPlatformLayer);
715     if (!m_isValidCanvas) {
716         m_layerState.canvasSize = m_canvasPlatformLayer->platformLayerSize();
717         m_layerState.canvasToken = m_canvasPlatformLayer->graphicsSurfaceToken();
718         m_layerState.canvasChanged = true;
719         m_isValidCanvas = true;
720     }
721
722     m_pendingCanvasOperation &= ~CreateCanvas;
723 }
724 #endif
725
726 void CoordinatedGraphicsLayer::flushCompositingStateForThisLayerOnly()
727 {
728     ASSERT(m_coordinator->isFlushingLayerChanges());
729
730     // When we have a transform animation, we need to update visible rect every frame to adjust the visible rect of a backing store.
731     bool hasActiveTransformAnimation = selfOrAncestorHasActiveTransformAnimation();
732     if (hasActiveTransformAnimation)
733         m_movingVisibleRect = true;
734
735     // Sets the values.
736     computePixelAlignment(m_adjustedPosition, m_adjustedSize, m_adjustedAnchorPoint, m_pixelAlignmentOffset);
737
738     syncImageBacking();
739     syncLayerState();
740     syncAnimations();
741     computeTransformedVisibleRect();
742     syncChildren();
743 #if ENABLE(CSS_FILTERS)
744     syncFilters();
745 #endif
746     updateContentBuffers();
747 #if USE(GRAPHICS_SURFACE)
748     syncCanvas();
749 #endif
750
751     m_coordinator->syncLayerState(m_id, m_layerState);
752     resetLayerState();
753
754     // Only unset m_movingVisibleRect after we have updated the visible rect after the animation stopped.
755     if (!hasActiveTransformAnimation)
756         m_movingVisibleRect = false;
757 }
758
759 void CoordinatedGraphicsLayer::resetLayerState()
760 {
761     m_layerState.changeMask = 0;
762     m_layerState.tilesToCreate.clear();
763     m_layerState.tilesToRemove.clear();
764     m_layerState.tilesToUpdate.clear();
765     m_layerState.committedScrollOffset = IntSize();
766 }
767
768 bool CoordinatedGraphicsLayer::imageBackingVisible()
769 {
770     ASSERT(m_coordinatedImageBacking);
771     return tiledBackingStoreVisibleRect().intersects(contentsRect());
772 }
773
774 void CoordinatedGraphicsLayer::releaseImageBackingIfNeeded()
775 {
776     if (!m_coordinatedImageBacking)
777         return;
778
779     ASSERT(m_coordinator);
780     m_coordinatedImageBacking->removeHost(this);
781     m_coordinatedImageBacking.clear();
782     m_layerState.imageID = InvalidCoordinatedImageBackingID;
783     m_layerState.imageChanged = true;
784 }
785
786 void CoordinatedGraphicsLayer::tiledBackingStorePaintBegin()
787 {
788 }
789
790 void CoordinatedGraphicsLayer::setRootLayer(bool isRoot)
791 {
792     m_layerState.isRootLayer = isRoot;
793     m_layerState.flagsChanged = true;
794     didChangeLayerState();
795 }
796
797 void CoordinatedGraphicsLayer::setVisibleContentRectTrajectoryVector(const FloatPoint& trajectoryVector)
798 {
799     if (!m_mainBackingStore)
800         return;
801
802     m_mainBackingStore->setTrajectoryVector(trajectoryVector);
803     setNeedsVisibleRectAdjustment();
804 }
805
806 void CoordinatedGraphicsLayer::deviceOrPageScaleFactorChanged()
807 {
808     if (shouldHaveBackingStore())
809         m_pendingContentsScaleAdjustment = true;
810 }
811
812 float CoordinatedGraphicsLayer::effectiveContentsScale()
813 {
814     return selfOrAncestorHaveNonAffineTransforms() ? 1 : deviceScaleFactor() * pageScaleFactor();
815 }
816
817 void CoordinatedGraphicsLayer::adjustContentsScale()
818 {
819     ASSERT(shouldHaveBackingStore());
820     if (!m_mainBackingStore || m_mainBackingStore->contentsScale() == effectiveContentsScale())
821         return;
822
823     // Between creating the new backing store and painting the content,
824     // we do not want to drop the previous one as that might result in
825     // briefly seeing flickering as the old tiles may be dropped before
826     // something replaces them.
827     m_previousBackingStore = m_mainBackingStore.release();
828
829     // No reason to save the previous backing store for non-visible areas.
830     m_previousBackingStore->removeAllNonVisibleTiles();
831 }
832
833 void CoordinatedGraphicsLayer::createBackingStore()
834 {
835     m_mainBackingStore = adoptPtr(new TiledBackingStore(this, CoordinatedTileBackend::create(this)));
836     m_mainBackingStore->setSupportsAlpha(!contentsOpaque());
837     m_mainBackingStore->setContentsScale(effectiveContentsScale());
838 }
839
840 void CoordinatedGraphicsLayer::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect)
841 {
842     if (rect.isEmpty())
843         return;
844     paintGraphicsLayerContents(*context, rect);
845 }
846
847 void CoordinatedGraphicsLayer::tiledBackingStorePaintEnd(const Vector<IntRect>& updatedRects)
848 {
849     if (!isShowingRepaintCounter() || updatedRects.isEmpty())
850         return;
851
852     m_layerState.repaintCount = incrementRepaintCount();
853     m_layerState.repaintCountChanged = true;
854 }
855
856 void CoordinatedGraphicsLayer::tiledBackingStoreHasPendingTileCreation()
857 {
858     setNeedsVisibleRectAdjustment();
859     if (client())
860         client()->notifyFlushRequired(this);
861 }
862
863 IntRect CoordinatedGraphicsLayer::tiledBackingStoreContentsRect()
864 {
865     return IntRect(0, 0, size().width(), size().height());
866 }
867
868 static void clampToContentsRectIfRectIsInfinite(FloatRect& rect, const IntRect& contentsRect)
869 {
870     if (rect.width() >= LayoutUnit::nearlyMax() || rect.width() <= LayoutUnit::nearlyMin()) {
871         rect.setX(contentsRect.x());
872         rect.setWidth(contentsRect.width());
873     }
874
875     if (rect.height() >= LayoutUnit::nearlyMax() || rect.height() <= LayoutUnit::nearlyMin()) {
876         rect.setY(contentsRect.y());
877         rect.setHeight(contentsRect.height());
878     }
879 }
880
881 IntRect CoordinatedGraphicsLayer::tiledBackingStoreVisibleRect()
882 {
883     // Non-invertible layers are not visible.
884     if (!m_layerTransform.combined().isInvertible())
885         return IntRect();
886
887     // Return a projection of the visible rect (surface coordinates) onto the layer's plane (layer coordinates).
888     // The resulting quad might be squewed and the visible rect is the bounding box of this quad,
889     // so it might spread further than the real visible area (and then even more amplified by the cover rect multiplier).
890     ASSERT(m_cachedInverseTransform == m_layerTransform.combined().inverse());
891     FloatRect rect = m_cachedInverseTransform.clampedBoundsOfProjectedQuad(FloatQuad(m_coordinator->visibleContentsRect()));
892     clampToContentsRectIfRectIsInfinite(rect, tiledBackingStoreContentsRect());
893     return enclosingIntRect(rect);
894 }
895
896 Color CoordinatedGraphicsLayer::tiledBackingStoreBackgroundColor() const
897 {
898     return contentsOpaque() ? Color::white : Color::transparent;
899 }
900
901 PassOwnPtr<GraphicsContext> CoordinatedGraphicsLayer::beginContentUpdate(const IntSize& size, uint32_t& atlas, IntPoint& offset)
902 {
903     ASSERT(m_coordinator);
904     ASSERT(m_coordinator->isFlushingLayerChanges());
905     return m_coordinator->beginContentUpdate(size, contentsOpaque() ? CoordinatedSurface::NoFlags : CoordinatedSurface::SupportsAlpha, atlas, offset);
906 }
907
908 void CoordinatedGraphicsLayer::createTile(uint32_t tileID, const SurfaceUpdateInfo& updateInfo, const IntRect& tileRect)
909 {
910     ASSERT(m_coordinator);
911     ASSERT(m_coordinator->isFlushingLayerChanges());
912
913     TileCreationInfo creationInfo;
914     creationInfo.tileID = tileID;
915     creationInfo.scale = updateInfo.scaleFactor;
916
917     m_layerState.tilesToCreate.append(creationInfo);
918     updateTile(tileID, updateInfo, tileRect);
919 }
920
921 void CoordinatedGraphicsLayer::updateTile(uint32_t tileID, const SurfaceUpdateInfo& updateInfo, const IntRect& tileRect)
922 {
923     ASSERT(m_coordinator);
924     ASSERT(m_coordinator->isFlushingLayerChanges());
925
926     TileUpdateInfo tileUpdateInfo;
927     tileUpdateInfo.tileID = tileID;
928     tileUpdateInfo.tileRect = tileRect;
929     tileUpdateInfo.updateInfo = updateInfo;
930     m_layerState.tilesToUpdate.append(tileUpdateInfo);
931 }
932
933 void CoordinatedGraphicsLayer::removeTile(uint32_t tileID)
934 {
935     ASSERT(m_coordinator);
936     ASSERT(m_coordinator->isFlushingLayerChanges() || m_isPurging);
937     m_layerState.tilesToRemove.append(tileID);
938 }
939
940 void CoordinatedGraphicsLayer::updateContentBuffers()
941 {
942     if (!shouldHaveBackingStore()) {
943         m_mainBackingStore.clear();
944         m_previousBackingStore.clear();
945         return;
946     }
947
948     if (m_pendingContentsScaleAdjustment) {
949         adjustContentsScale();
950         m_pendingContentsScaleAdjustment = false;
951     }
952
953     // This is the only place we (re)create the main tiled backing store, once we
954     // have a remote client and we are ready to send our data to the UI process.
955     if (!m_mainBackingStore)
956         createBackingStore();
957
958     if (m_pendingVisibleRectAdjustment) {
959         m_pendingVisibleRectAdjustment = false;
960         m_mainBackingStore->coverWithTilesIfNeeded();
961     }
962
963     m_mainBackingStore->updateTileBuffers();
964
965     // The previous backing store is kept around to avoid flickering between
966     // removing the existing tiles and painting the new ones. The first time
967     // the visibleRect is full painted we remove the previous backing store.
968     if (m_mainBackingStore->visibleAreaIsCovered())
969         m_previousBackingStore.clear();
970 }
971
972 void CoordinatedGraphicsLayer::purgeBackingStores()
973 {
974 #ifndef NDEBUG
975     TemporaryChange<bool> updateModeProtector(m_isPurging, true);
976 #endif
977     m_mainBackingStore.clear();
978     m_previousBackingStore.clear();
979
980     releaseImageBackingIfNeeded();
981
982     didChangeLayerState();
983 }
984
985 void CoordinatedGraphicsLayer::setCoordinator(CoordinatedGraphicsLayerClient* coordinator)
986 {
987     m_coordinator = coordinator;
988 }
989
990 void CoordinatedGraphicsLayer::setNeedsVisibleRectAdjustment()
991 {
992     if (shouldHaveBackingStore())
993         m_pendingVisibleRectAdjustment = true;
994 }
995
996 bool CoordinatedGraphicsLayer::hasPendingVisibleChanges()
997 {
998     if (opacity() < 0.01 && !m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity))
999         return false;
1000
1001     for (size_t i = 0; i < children().size(); ++i) {
1002         if (toCoordinatedGraphicsLayer(children()[i])->hasPendingVisibleChanges())
1003             return true;
1004     }
1005
1006     bool shouldSyncCanvas = false;
1007 #if USE(GRAPHICS_SURFACE)
1008     shouldSyncCanvas = m_pendingCanvasOperation & SyncCanvas;
1009 #endif
1010
1011     if (!m_shouldSyncLayerState && !m_shouldSyncChildren && !m_shouldSyncFilters && !m_shouldSyncImageBacking && !m_shouldSyncAnimations && !shouldSyncCanvas)
1012         return false;
1013
1014     return tiledBackingStoreVisibleRect().intersects(tiledBackingStoreContentsRect());
1015 }
1016
1017 static inline bool isIntegral(float value)
1018 {
1019     return static_cast<int>(value) == value;
1020 }
1021
1022 FloatPoint CoordinatedGraphicsLayer::computePositionRelativeToBase()
1023 {
1024     FloatPoint offset;
1025     for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent())
1026         offset += currLayer->position();
1027
1028     return offset;
1029 }
1030
1031 void CoordinatedGraphicsLayer::computePixelAlignment(FloatPoint& position, FloatSize& size, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset)
1032 {
1033     if (isIntegral(effectiveContentsScale())) {
1034         position = m_position;
1035         size = m_size;
1036         anchorPoint = m_anchorPoint;
1037         alignmentOffset = FloatSize();
1038         return;
1039     }
1040
1041     FloatPoint positionRelativeToBase = computePositionRelativeToBase();
1042
1043     FloatRect baseRelativeBounds(positionRelativeToBase, m_size);
1044     FloatRect scaledBounds = baseRelativeBounds;
1045
1046     // Scale by the effective scale factor to compute the screen-relative bounds.
1047     scaledBounds.scale(effectiveContentsScale());
1048
1049     // Round to integer boundaries.
1050     // NOTE: When using enclosingIntRect (as mac) it will have different sizes depending on position.
1051     FloatRect alignedBounds = roundedIntRect(scaledBounds);
1052
1053     // Convert back to layer coordinates.
1054     alignedBounds.scale(1 / effectiveContentsScale());
1055
1056     // Convert back to layer coordinates.
1057     alignmentOffset = baseRelativeBounds.location() - alignedBounds.location();
1058
1059     position = m_position - alignmentOffset;
1060     size = alignedBounds.size();
1061
1062     // Now we have to compute a new anchor point which compensates for rounding.
1063     float anchorPointX = m_anchorPoint.x();
1064     float anchorPointY = m_anchorPoint.y();
1065
1066     if (alignedBounds.width())
1067         anchorPointX = (baseRelativeBounds.width() * anchorPointX + alignmentOffset.width()) / alignedBounds.width();
1068
1069     if (alignedBounds.height())
1070         anchorPointY = (baseRelativeBounds.height() * anchorPointY + alignmentOffset.height()) / alignedBounds.height();
1071
1072     anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * effectiveContentsScale());
1073 }
1074
1075 void CoordinatedGraphicsLayer::computeTransformedVisibleRect()
1076 {
1077     if (!m_shouldUpdateVisibleRect && !m_movingVisibleRect)
1078         return;
1079
1080     m_shouldUpdateVisibleRect = false;
1081     TransformationMatrix currentTransform = transform();
1082     if (m_movingVisibleRect)
1083         client()->getCurrentTransform(this, currentTransform);
1084     m_layerTransform.setLocalTransform(currentTransform);
1085
1086     m_layerTransform.setAnchorPoint(m_adjustedAnchorPoint);
1087     m_layerTransform.setPosition(m_adjustedPosition);
1088     m_layerTransform.setSize(m_adjustedSize);
1089
1090     m_layerTransform.setFlattening(!preserves3D());
1091     m_layerTransform.setChildrenTransform(childrenTransform());
1092     m_layerTransform.combineTransforms(parent() ? toCoordinatedGraphicsLayer(parent())->m_layerTransform.combinedForChildren() : TransformationMatrix());
1093
1094     m_cachedInverseTransform = m_layerTransform.combined().inverse();
1095
1096     // The combined transform will be used in tiledBackingStoreVisibleRect.
1097     setNeedsVisibleRectAdjustment();
1098 }
1099
1100 bool CoordinatedGraphicsLayer::shouldHaveBackingStore() const
1101 {
1102     return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
1103 }
1104
1105 bool CoordinatedGraphicsLayer::selfOrAncestorHasActiveTransformAnimation() const
1106 {
1107     if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
1108         return true;
1109
1110     if (!parent())
1111         return false;
1112
1113     return toCoordinatedGraphicsLayer(parent())->selfOrAncestorHasActiveTransformAnimation();
1114 }
1115
1116 bool CoordinatedGraphicsLayer::selfOrAncestorHaveNonAffineTransforms()
1117 {
1118     if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
1119         return true;
1120
1121     if (!m_layerTransform.combined().isAffine())
1122         return true;
1123
1124     if (!parent())
1125         return false;
1126
1127     return toCoordinatedGraphicsLayer(parent())->selfOrAncestorHaveNonAffineTransforms();
1128 }
1129
1130 bool CoordinatedGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double delayAsNegativeTimeOffset)
1131 {
1132     ASSERT(!keyframesName.isEmpty());
1133
1134     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity))
1135         return false;
1136
1137     bool listsMatch = false;
1138     bool ignoredHasBigRotation;
1139
1140     if (valueList.property() == AnimatedPropertyWebkitTransform)
1141         listsMatch = validateTransformOperations(valueList, ignoredHasBigRotation) >= 0;
1142
1143     m_lastAnimationStartTime = WTF::currentTime() - delayAsNegativeTimeOffset;
1144     m_animations.add(GraphicsLayerAnimation(keyframesName, valueList, boxSize, anim, m_lastAnimationStartTime, listsMatch));
1145     m_animationStartedTimer.startOneShot(0);
1146     didChangeAnimations();
1147     return true;
1148 }
1149
1150 void CoordinatedGraphicsLayer::pauseAnimation(const String& animationName, double time)
1151 {
1152     m_animations.pause(animationName, time);
1153     didChangeAnimations();
1154 }
1155
1156 void CoordinatedGraphicsLayer::removeAnimation(const String& animationName)
1157 {
1158     m_animations.remove(animationName);
1159     didChangeAnimations();
1160 }
1161
1162 void CoordinatedGraphicsLayer::suspendAnimations(double time)
1163 {
1164     m_animations.suspend(time);
1165     didChangeAnimations();
1166 }
1167
1168 void CoordinatedGraphicsLayer::resumeAnimations()
1169 {
1170     m_animations.resume();
1171     didChangeAnimations();
1172 }
1173
1174 void CoordinatedGraphicsLayer::animationStartedTimerFired(Timer<CoordinatedGraphicsLayer>*)
1175 {
1176     client()->notifyAnimationStarted(this, m_lastAnimationStartTime);
1177 }
1178 } // namespace WebCore
1179 #endif // USE(COORDINATED_GRAPHICS)