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