[EFL][Qt] REGRESSION(r144787): A fixed element lags when scrolling and wheeling.
[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.flagsChanged = 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.flagsChanged) {
649         m_layerState.drawsContent = drawsContent();
650         m_layerState.contentsVisible = contentsAreVisible();
651         m_layerState.backfaceVisible = backfaceVisibility();
652         m_layerState.masksToBounds = masksToBounds();
653         m_layerState.preserves3D = preserves3D();
654         m_layerState.fixedToViewport = fixedToViewport();
655         m_layerState.showDebugBorders = isShowingDebugBorder();
656         m_layerState.showRepaintCounter = isShowingRepaintCounter();
657         m_layerState.isScrollable = isScrollable();
658     }
659
660     if (m_layerState.showDebugBorders)
661         updateDebugIndicators();
662 }
663
664 void CoordinatedGraphicsLayer::setDebugBorder(const Color& color, float width)
665 {
666     ASSERT(m_layerState.showDebugBorders);
667     if (m_layerState.debugBorderColor != color) {
668         m_layerState.debugBorderColor = color;
669         m_layerState.debugBorderColorChanged = true;
670     }
671
672     if (m_layerState.debugBorderWidth != width) {
673         m_layerState.debugBorderWidth = width;
674         m_layerState.debugBorderWidthChanged = true;
675     }
676 }
677
678 void CoordinatedGraphicsLayer::syncAnimations()
679 {
680     if (!m_shouldSyncAnimations)
681         return;
682
683     m_shouldSyncAnimations = false;
684     m_layerState.animations = m_animations.getActiveAnimations();
685     m_layerState.animationsChanged = true;
686 }
687
688 #if USE(GRAPHICS_SURFACE)
689 void CoordinatedGraphicsLayer::syncCanvas()
690 {
691     destroyCanvasIfNeeded();
692     createCanvasIfNeeded();
693
694     if (!(m_pendingCanvasOperation & SyncCanvas))
695         return;
696
697     m_pendingCanvasOperation &= ~SyncCanvas;
698
699     if (!m_isValidCanvas)
700         return;
701
702     ASSERT(m_canvasPlatformLayer);
703     m_layerState.canvasFrontBuffer = m_canvasPlatformLayer->copyToGraphicsSurface();
704     m_layerState.canvasShouldSwapBuffers = true;
705 }
706
707 void CoordinatedGraphicsLayer::destroyCanvasIfNeeded()
708 {
709     if (!(m_pendingCanvasOperation & DestroyCanvas))
710         return;
711
712     if (m_isValidCanvas) {
713         m_isValidCanvas = false;
714         m_layerState.canvasToken = GraphicsSurfaceToken();
715         m_layerState.canvasChanged = true;
716     }
717
718     m_pendingCanvasOperation &= ~DestroyCanvas;
719 }
720
721 void CoordinatedGraphicsLayer::createCanvasIfNeeded()
722 {
723     if (!(m_pendingCanvasOperation & CreateCanvas))
724         return;
725
726     ASSERT(m_canvasPlatformLayer);
727     if (!m_isValidCanvas) {
728         m_layerState.canvasSize = m_canvasPlatformLayer->platformLayerSize();
729         m_layerState.canvasToken = m_canvasPlatformLayer->graphicsSurfaceToken();
730         m_layerState.canvasChanged = true;
731         m_isValidCanvas = true;
732     }
733
734     m_pendingCanvasOperation &= ~CreateCanvas;
735 }
736 #endif
737
738 void CoordinatedGraphicsLayer::flushCompositingStateForThisLayerOnly()
739 {
740     ASSERT(m_coordinator->isFlushingLayerChanges());
741
742     // When we have a transform animation, we need to update visible rect every frame to adjust the visible rect of a backing store.
743     bool hasActiveTransformAnimation = selfOrAncestorHasActiveTransformAnimation();
744     if (hasActiveTransformAnimation)
745         m_movingVisibleRect = true;
746
747     // Sets the values.
748     computePixelAlignment(m_adjustedPosition, m_adjustedSize, m_adjustedAnchorPoint, m_pixelAlignmentOffset);
749
750     syncImageBacking();
751     syncLayerState();
752     syncAnimations();
753     computeTransformedVisibleRect();
754     syncChildren();
755 #if ENABLE(CSS_FILTERS)
756     syncFilters();
757 #endif
758     updateContentBuffers();
759 #if USE(GRAPHICS_SURFACE)
760     syncCanvas();
761 #endif
762
763     m_coordinator->syncLayerState(m_id, m_layerState);
764     resetLayerState();
765
766     // Only unset m_movingVisibleRect after we have updated the visible rect after the animation stopped.
767     if (!hasActiveTransformAnimation)
768         m_movingVisibleRect = false;
769 }
770
771 void CoordinatedGraphicsLayer::resetLayerState()
772 {
773     m_layerState.changeMask = 0;
774     m_layerState.tilesToCreate.clear();
775     m_layerState.tilesToRemove.clear();
776     m_layerState.tilesToUpdate.clear();
777     m_layerState.committedScrollOffset = IntSize();
778 }
779
780 bool CoordinatedGraphicsLayer::imageBackingVisible()
781 {
782     ASSERT(m_coordinatedImageBacking);
783     return tiledBackingStoreVisibleRect().intersects(contentsRect());
784 }
785
786 void CoordinatedGraphicsLayer::releaseImageBackingIfNeeded()
787 {
788     if (!m_coordinatedImageBacking)
789         return;
790
791     ASSERT(m_coordinator);
792     m_coordinatedImageBacking->removeHost(this);
793     m_coordinatedImageBacking.clear();
794     m_layerState.imageID = InvalidCoordinatedImageBackingID;
795     m_layerState.imageChanged = true;
796 }
797
798 void CoordinatedGraphicsLayer::tiledBackingStorePaintBegin()
799 {
800 }
801
802 void CoordinatedGraphicsLayer::setRootLayer(bool isRoot)
803 {
804     m_layerState.isRootLayer = isRoot;
805     m_layerState.flagsChanged = true;
806     didChangeLayerState();
807 }
808
809 void CoordinatedGraphicsLayer::setVisibleContentRectTrajectoryVector(const FloatPoint& trajectoryVector)
810 {
811     if (!m_mainBackingStore)
812         return;
813
814     m_mainBackingStore->setTrajectoryVector(trajectoryVector);
815     setNeedsVisibleRectAdjustment();
816 }
817
818 void CoordinatedGraphicsLayer::deviceOrPageScaleFactorChanged()
819 {
820     if (shouldHaveBackingStore())
821         m_pendingContentsScaleAdjustment = true;
822 }
823
824 float CoordinatedGraphicsLayer::effectiveContentsScale()
825 {
826     return selfOrAncestorHaveNonAffineTransforms() ? 1 : deviceScaleFactor() * pageScaleFactor();
827 }
828
829 void CoordinatedGraphicsLayer::adjustContentsScale()
830 {
831     ASSERT(shouldHaveBackingStore());
832     if (!m_mainBackingStore || m_mainBackingStore->contentsScale() == effectiveContentsScale())
833         return;
834
835     // Between creating the new backing store and painting the content,
836     // we do not want to drop the previous one as that might result in
837     // briefly seeing flickering as the old tiles may be dropped before
838     // something replaces them.
839     m_previousBackingStore = m_mainBackingStore.release();
840
841     // No reason to save the previous backing store for non-visible areas.
842     m_previousBackingStore->removeAllNonVisibleTiles();
843 }
844
845 void CoordinatedGraphicsLayer::createBackingStore()
846 {
847     m_mainBackingStore = adoptPtr(new TiledBackingStore(this, CoordinatedTileBackend::create(this)));
848     m_mainBackingStore->setSupportsAlpha(!contentsOpaque());
849     m_mainBackingStore->setContentsScale(effectiveContentsScale());
850 }
851
852 void CoordinatedGraphicsLayer::tiledBackingStorePaint(GraphicsContext* context, const IntRect& rect)
853 {
854     if (rect.isEmpty())
855         return;
856     paintGraphicsLayerContents(*context, rect);
857 }
858
859 void CoordinatedGraphicsLayer::tiledBackingStorePaintEnd(const Vector<IntRect>& updatedRects)
860 {
861     if (!isShowingRepaintCounter() || updatedRects.isEmpty())
862         return;
863
864     m_layerState.repaintCount = incrementRepaintCount();
865     m_layerState.repaintCountChanged = true;
866 }
867
868 void CoordinatedGraphicsLayer::tiledBackingStoreHasPendingTileCreation()
869 {
870     setNeedsVisibleRectAdjustment();
871     if (client())
872         client()->notifyFlushRequired(this);
873 }
874
875 IntRect CoordinatedGraphicsLayer::tiledBackingStoreContentsRect()
876 {
877     return IntRect(0, 0, size().width(), size().height());
878 }
879
880 static void clampToContentsRectIfRectIsInfinite(FloatRect& rect, const IntRect& contentsRect)
881 {
882     if (rect.width() >= LayoutUnit::nearlyMax() || rect.width() <= LayoutUnit::nearlyMin()) {
883         rect.setX(contentsRect.x());
884         rect.setWidth(contentsRect.width());
885     }
886
887     if (rect.height() >= LayoutUnit::nearlyMax() || rect.height() <= LayoutUnit::nearlyMin()) {
888         rect.setY(contentsRect.y());
889         rect.setHeight(contentsRect.height());
890     }
891 }
892
893 IntRect CoordinatedGraphicsLayer::tiledBackingStoreVisibleRect()
894 {
895     // Non-invertible layers are not visible.
896     if (!m_layerTransform.combined().isInvertible())
897         return IntRect();
898
899     // Return a projection of the visible rect (surface coordinates) onto the layer's plane (layer coordinates).
900     // The resulting quad might be squewed and the visible rect is the bounding box of this quad,
901     // so it might spread further than the real visible area (and then even more amplified by the cover rect multiplier).
902     ASSERT(m_cachedInverseTransform == m_layerTransform.combined().inverse());
903     FloatRect rect = m_cachedInverseTransform.clampedBoundsOfProjectedQuad(FloatQuad(m_coordinator->visibleContentsRect()));
904     clampToContentsRectIfRectIsInfinite(rect, tiledBackingStoreContentsRect());
905     return enclosingIntRect(rect);
906 }
907
908 Color CoordinatedGraphicsLayer::tiledBackingStoreBackgroundColor() const
909 {
910     return contentsOpaque() ? Color::white : Color::transparent;
911 }
912
913 PassOwnPtr<GraphicsContext> CoordinatedGraphicsLayer::beginContentUpdate(const IntSize& size, uint32_t& atlas, IntPoint& offset)
914 {
915     ASSERT(m_coordinator);
916     ASSERT(m_coordinator->isFlushingLayerChanges());
917     return m_coordinator->beginContentUpdate(size, contentsOpaque() ? CoordinatedSurface::NoFlags : CoordinatedSurface::SupportsAlpha, atlas, offset);
918 }
919
920 void CoordinatedGraphicsLayer::createTile(uint32_t tileID, const SurfaceUpdateInfo& updateInfo, const IntRect& tileRect)
921 {
922     ASSERT(m_coordinator);
923     ASSERT(m_coordinator->isFlushingLayerChanges());
924
925     TileCreationInfo creationInfo;
926     creationInfo.tileID = tileID;
927     creationInfo.scale = updateInfo.scaleFactor;
928
929     m_layerState.tilesToCreate.append(creationInfo);
930     updateTile(tileID, updateInfo, tileRect);
931 }
932
933 void CoordinatedGraphicsLayer::updateTile(uint32_t tileID, const SurfaceUpdateInfo& updateInfo, const IntRect& tileRect)
934 {
935     ASSERT(m_coordinator);
936     ASSERT(m_coordinator->isFlushingLayerChanges());
937
938     TileUpdateInfo tileUpdateInfo;
939     tileUpdateInfo.tileID = tileID;
940     tileUpdateInfo.tileRect = tileRect;
941     tileUpdateInfo.updateInfo = updateInfo;
942     m_layerState.tilesToUpdate.append(tileUpdateInfo);
943 }
944
945 void CoordinatedGraphicsLayer::removeTile(uint32_t tileID)
946 {
947     ASSERT(m_coordinator);
948     ASSERT(m_coordinator->isFlushingLayerChanges() || m_isPurging);
949     m_layerState.tilesToRemove.append(tileID);
950 }
951
952 void CoordinatedGraphicsLayer::updateContentBuffers()
953 {
954     if (!shouldHaveBackingStore()) {
955         m_mainBackingStore.clear();
956         m_previousBackingStore.clear();
957         return;
958     }
959
960     if (m_pendingContentsScaleAdjustment) {
961         adjustContentsScale();
962         m_pendingContentsScaleAdjustment = false;
963     }
964
965     // This is the only place we (re)create the main tiled backing store, once we
966     // have a remote client and we are ready to send our data to the UI process.
967     if (!m_mainBackingStore)
968         createBackingStore();
969
970     if (m_pendingVisibleRectAdjustment) {
971         m_pendingVisibleRectAdjustment = false;
972         m_mainBackingStore->coverWithTilesIfNeeded();
973     }
974
975     m_mainBackingStore->updateTileBuffers();
976
977     // The previous backing store is kept around to avoid flickering between
978     // removing the existing tiles and painting the new ones. The first time
979     // the visibleRect is full painted we remove the previous backing store.
980     if (m_mainBackingStore->visibleAreaIsCovered())
981         m_previousBackingStore.clear();
982 }
983
984 void CoordinatedGraphicsLayer::purgeBackingStores()
985 {
986 #ifndef NDEBUG
987     TemporaryChange<bool> updateModeProtector(m_isPurging, true);
988 #endif
989     m_mainBackingStore.clear();
990     m_previousBackingStore.clear();
991
992     releaseImageBackingIfNeeded();
993
994     didChangeLayerState();
995 }
996
997 void CoordinatedGraphicsLayer::setCoordinator(CoordinatedGraphicsLayerClient* coordinator)
998 {
999     m_coordinator = coordinator;
1000 }
1001
1002 void CoordinatedGraphicsLayer::setNeedsVisibleRectAdjustment()
1003 {
1004     if (shouldHaveBackingStore())
1005         m_pendingVisibleRectAdjustment = true;
1006 }
1007
1008 bool CoordinatedGraphicsLayer::hasPendingVisibleChanges()
1009 {
1010     if (opacity() < 0.01 && !m_animations.hasActiveAnimationsOfType(AnimatedPropertyOpacity))
1011         return false;
1012
1013     for (size_t i = 0; i < children().size(); ++i) {
1014         if (toCoordinatedGraphicsLayer(children()[i])->hasPendingVisibleChanges())
1015             return true;
1016     }
1017
1018     bool shouldSyncCanvas = false;
1019 #if USE(GRAPHICS_SURFACE)
1020     shouldSyncCanvas = m_pendingCanvasOperation & SyncCanvas;
1021 #endif
1022
1023     if (!m_shouldSyncLayerState && !m_shouldSyncChildren && !m_shouldSyncFilters && !m_shouldSyncImageBacking && !m_shouldSyncAnimations && !shouldSyncCanvas)
1024         return false;
1025
1026     return tiledBackingStoreVisibleRect().intersects(tiledBackingStoreContentsRect());
1027 }
1028
1029 static inline bool isIntegral(float value)
1030 {
1031     return static_cast<int>(value) == value;
1032 }
1033
1034 FloatPoint CoordinatedGraphicsLayer::computePositionRelativeToBase()
1035 {
1036     FloatPoint offset;
1037     for (const GraphicsLayer* currLayer = this; currLayer; currLayer = currLayer->parent())
1038         offset += currLayer->position();
1039
1040     return offset;
1041 }
1042
1043 void CoordinatedGraphicsLayer::computePixelAlignment(FloatPoint& position, FloatSize& size, FloatPoint3D& anchorPoint, FloatSize& alignmentOffset)
1044 {
1045     if (isIntegral(effectiveContentsScale())) {
1046         position = m_position;
1047         size = m_size;
1048         anchorPoint = m_anchorPoint;
1049         alignmentOffset = FloatSize();
1050         return;
1051     }
1052
1053     FloatPoint positionRelativeToBase = computePositionRelativeToBase();
1054
1055     FloatRect baseRelativeBounds(positionRelativeToBase, m_size);
1056     FloatRect scaledBounds = baseRelativeBounds;
1057
1058     // Scale by the effective scale factor to compute the screen-relative bounds.
1059     scaledBounds.scale(effectiveContentsScale());
1060
1061     // Round to integer boundaries.
1062     // NOTE: When using enclosingIntRect (as mac) it will have different sizes depending on position.
1063     FloatRect alignedBounds = roundedIntRect(scaledBounds);
1064
1065     // Convert back to layer coordinates.
1066     alignedBounds.scale(1 / effectiveContentsScale());
1067
1068     // Convert back to layer coordinates.
1069     alignmentOffset = baseRelativeBounds.location() - alignedBounds.location();
1070
1071     position = m_position - alignmentOffset;
1072     size = alignedBounds.size();
1073
1074     // Now we have to compute a new anchor point which compensates for rounding.
1075     float anchorPointX = m_anchorPoint.x();
1076     float anchorPointY = m_anchorPoint.y();
1077
1078     if (alignedBounds.width())
1079         anchorPointX = (baseRelativeBounds.width() * anchorPointX + alignmentOffset.width()) / alignedBounds.width();
1080
1081     if (alignedBounds.height())
1082         anchorPointY = (baseRelativeBounds.height() * anchorPointY + alignmentOffset.height()) / alignedBounds.height();
1083
1084     anchorPoint = FloatPoint3D(anchorPointX, anchorPointY, m_anchorPoint.z() * effectiveContentsScale());
1085 }
1086
1087 void CoordinatedGraphicsLayer::computeTransformedVisibleRect()
1088 {
1089     if (!m_shouldUpdateVisibleRect && !m_movingVisibleRect)
1090         return;
1091
1092     m_shouldUpdateVisibleRect = false;
1093     TransformationMatrix currentTransform = transform();
1094     if (m_movingVisibleRect)
1095         client()->getCurrentTransform(this, currentTransform);
1096     m_layerTransform.setLocalTransform(currentTransform);
1097
1098     m_layerTransform.setAnchorPoint(m_adjustedAnchorPoint);
1099     m_layerTransform.setPosition(m_adjustedPosition);
1100     m_layerTransform.setSize(m_adjustedSize);
1101
1102     m_layerTransform.setFlattening(!preserves3D());
1103     m_layerTransform.setChildrenTransform(childrenTransform());
1104     m_layerTransform.combineTransforms(parent() ? toCoordinatedGraphicsLayer(parent())->m_layerTransform.combinedForChildren() : TransformationMatrix());
1105
1106     m_cachedInverseTransform = m_layerTransform.combined().inverse();
1107
1108     // The combined transform will be used in tiledBackingStoreVisibleRect.
1109     setNeedsVisibleRectAdjustment();
1110 }
1111
1112 bool CoordinatedGraphicsLayer::shouldHaveBackingStore() const
1113 {
1114     return drawsContent() && contentsAreVisible() && !m_size.isEmpty();
1115 }
1116
1117 bool CoordinatedGraphicsLayer::selfOrAncestorHasActiveTransformAnimation() const
1118 {
1119     if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
1120         return true;
1121
1122     if (!parent())
1123         return false;
1124
1125     return toCoordinatedGraphicsLayer(parent())->selfOrAncestorHasActiveTransformAnimation();
1126 }
1127
1128 bool CoordinatedGraphicsLayer::selfOrAncestorHaveNonAffineTransforms()
1129 {
1130     if (m_animations.hasActiveAnimationsOfType(AnimatedPropertyWebkitTransform))
1131         return true;
1132
1133     if (!m_layerTransform.combined().isAffine())
1134         return true;
1135
1136     if (!parent())
1137         return false;
1138
1139     return toCoordinatedGraphicsLayer(parent())->selfOrAncestorHaveNonAffineTransforms();
1140 }
1141
1142 bool CoordinatedGraphicsLayer::addAnimation(const KeyframeValueList& valueList, const IntSize& boxSize, const Animation* anim, const String& keyframesName, double delayAsNegativeTimeOffset)
1143 {
1144     ASSERT(!keyframesName.isEmpty());
1145
1146     if (!anim || anim->isEmptyOrZeroDuration() || valueList.size() < 2 || (valueList.property() != AnimatedPropertyWebkitTransform && valueList.property() != AnimatedPropertyOpacity))
1147         return false;
1148
1149     bool listsMatch = false;
1150     bool ignoredHasBigRotation;
1151
1152     if (valueList.property() == AnimatedPropertyWebkitTransform)
1153         listsMatch = validateTransformOperations(valueList, ignoredHasBigRotation) >= 0;
1154
1155     m_lastAnimationStartTime = WTF::currentTime() - delayAsNegativeTimeOffset;
1156     m_animations.add(GraphicsLayerAnimation(keyframesName, valueList, boxSize, anim, m_lastAnimationStartTime, listsMatch));
1157     m_animationStartedTimer.startOneShot(0);
1158     didChangeAnimations();
1159     return true;
1160 }
1161
1162 void CoordinatedGraphicsLayer::pauseAnimation(const String& animationName, double time)
1163 {
1164     m_animations.pause(animationName, time);
1165     didChangeAnimations();
1166 }
1167
1168 void CoordinatedGraphicsLayer::removeAnimation(const String& animationName)
1169 {
1170     m_animations.remove(animationName);
1171     didChangeAnimations();
1172 }
1173
1174 void CoordinatedGraphicsLayer::suspendAnimations(double time)
1175 {
1176     m_animations.suspend(time);
1177     didChangeAnimations();
1178 }
1179
1180 void CoordinatedGraphicsLayer::resumeAnimations()
1181 {
1182     m_animations.resume();
1183     didChangeAnimations();
1184 }
1185
1186 void CoordinatedGraphicsLayer::animationStartedTimerFired(Timer<CoordinatedGraphicsLayer>*)
1187 {
1188     client()->notifyAnimationStarted(this, m_lastAnimationStartTime);
1189 }
1190 } // namespace WebCore
1191 #endif // USE(COORDINATED_GRAPHICS)