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