fb0900bbc1a757c1da3b81cccc700bd9442db2ac
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / GraphicsLayerChromium.cpp
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  * Copyright (C) 2009 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32
33 /** FIXME
34  * This file borrows code heavily from platform/graphics/win/GraphicsLayerCACF.cpp
35  * (and hence it includes both copyrights)
36  * Ideally the common code (mostly the code that keeps track of the layer hierarchy)
37  * should be kept separate and shared between platforms. It would be a well worthwhile
38  * effort once the Windows implementation (binaries and headers) of CoreAnimation is
39  * checked in to the WebKit repository. Until then only Apple can make this happen.
40  */
41
42 #include "config.h"
43
44 #if USE(ACCELERATED_COMPOSITING)
45
46 #include "GraphicsLayerChromium.h"
47
48 #include "AnimationIdVendor.h"
49 #include "AnimationTranslationUtil.h"
50 #include "ContentLayerChromium.h"
51 #include "FloatConversion.h"
52 #include "FloatRect.h"
53 #include "GraphicsContext.h"
54 #include "Image.h"
55 #include "LinkHighlight.h"
56 #include "NativeImageSkia.h"
57 #include "PlatformContextSkia.h"
58 #include "PlatformString.h"
59 #include "SkMatrix44.h"
60 #include "SystemTime.h"
61
62 #include <public/WebAnimation.h>
63 #include <public/WebFilterOperation.h>
64 #include <public/WebFilterOperations.h>
65 #include <public/WebFloatPoint.h>
66 #include <public/WebFloatRect.h>
67 #include <public/WebImageLayer.h>
68 #include <public/WebSize.h>
69 #include <public/WebTransformationMatrix.h>
70 #include <wtf/CurrentTime.h>
71 #include <wtf/StringExtras.h>
72 #include <wtf/text/CString.h>
73
74 using namespace std;
75 using namespace WebKit;
76
77 namespace WebCore {
78
79 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
80 {
81     return adoptPtr(new GraphicsLayerChromium(client));
82 }
83
84 GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
85     : GraphicsLayer(client)
86     , m_contentsLayerPurpose(NoContentsLayer)
87     , m_contentsLayerHasBackgroundColor(false)
88     , m_inSetChildren(false)
89     , m_pageScaleChanged(false)
90 {
91     m_opaqueRectTrackingContentLayerDelegate = adoptPtr(new OpaqueRectTrackingContentLayerDelegate(this));
92     m_layer = WebContentLayer::create(m_opaqueRectTrackingContentLayerDelegate.get());
93     m_layer.setDrawsContent(m_drawsContent && m_contentsVisible);
94     if (client)
95         deviceOrPageScaleFactorChanged();
96     updateDebugIndicators();
97 }
98
99 GraphicsLayerChromium::~GraphicsLayerChromium()
100 {
101     // Do cleanup while we can still safely call methods on the derived class.
102     willBeDestroyed();
103 }
104
105 void GraphicsLayerChromium::willBeDestroyed()
106 {
107     if (!m_layer.isNull()) {
108         m_layer.clearClient();
109         m_layer.clearRenderSurface();
110         m_layer.setAnimationDelegate(0);
111     }
112
113     if (!m_contentsLayer.isNull()) {
114         m_contentsLayer.clearRenderSurface();
115         m_contentsLayer.setAnimationDelegate(0);
116     }
117
118     if (!m_transformLayer.isNull()) {
119         m_transformLayer.clearRenderSurface();
120         m_transformLayer.setAnimationDelegate(0);
121     }
122
123     if (m_linkHighlight)
124         m_linkHighlight.clear();
125
126     GraphicsLayer::willBeDestroyed();
127 }
128
129 void GraphicsLayerChromium::setName(const String& inName)
130 {
131     m_nameBase = inName;
132     String name = String::format("GraphicsLayer(%p) ", this) + inName;
133     GraphicsLayer::setName(name);
134     updateNames();
135 }
136
137 void GraphicsLayerChromium::updateNames()
138 {
139     if (!m_layer.isNull()) {
140         String debugName = "Layer for " + m_nameBase;
141         m_layer.setDebugName(debugName);
142     }
143     if (!m_transformLayer.isNull()) {
144         String debugName = "TransformLayer for " + m_nameBase;
145         m_transformLayer.setDebugName(debugName);
146     }
147     if (!m_contentsLayer.isNull()) {
148         String debugName = "ContentsLayer for " + m_nameBase;
149         m_contentsLayer.setDebugName(debugName);
150     }
151     if (m_linkHighlight) {
152         String debugName = "LinkHighlight for " + m_nameBase;
153         m_linkHighlight->contentLayer()->setDebugName(debugName);
154     }
155 }
156
157 bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children)
158 {
159     m_inSetChildren = true;
160     bool childrenChanged = GraphicsLayer::setChildren(children);
161
162     if (childrenChanged)
163         updateChildList();
164     m_inSetChildren = false;
165
166     return childrenChanged;
167 }
168
169 void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer)
170 {
171     GraphicsLayer::addChild(childLayer);
172     if (!m_inSetChildren)
173         updateChildList();
174 }
175
176 void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index)
177 {
178     GraphicsLayer::addChildAtIndex(childLayer, index);
179     updateChildList();
180 }
181
182 void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
183 {
184     GraphicsLayer::addChildBelow(childLayer, sibling);
185     updateChildList();
186 }
187
188 void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
189 {
190     GraphicsLayer::addChildAbove(childLayer, sibling);
191     updateChildList();
192 }
193
194 bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
195 {
196     if (GraphicsLayer::replaceChild(oldChild, newChild)) {
197         updateChildList();
198         return true;
199     }
200     return false;
201 }
202
203 void GraphicsLayerChromium::removeFromParent()
204 {
205     GraphicsLayer::removeFromParent();
206     primaryLayer().removeFromParent();
207 }
208
209 void GraphicsLayerChromium::setPosition(const FloatPoint& point)
210 {
211     GraphicsLayer::setPosition(point);
212     updateLayerPosition();
213 }
214
215 void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point)
216 {
217     GraphicsLayer::setAnchorPoint(point);
218     updateAnchorPoint();
219 }
220
221 void GraphicsLayerChromium::setSize(const FloatSize& size)
222 {
223     // We are receiving negative sizes here that cause assertions to fail in the compositor. Clamp them to 0 to
224     // avoid those assertions.
225     // FIXME: This should be an ASSERT instead, as negative sizes should not exist in WebCore.
226     FloatSize clampedSize = size;
227     if (clampedSize.width() < 0 || clampedSize.height() < 0)
228         clampedSize = FloatSize();
229
230     if (clampedSize == m_size)
231         return;
232
233     GraphicsLayer::setSize(clampedSize);
234     updateLayerSize();
235
236     if (m_pageScaleChanged && !m_layer.isNull())
237         m_layer.invalidate();
238     m_pageScaleChanged = false;
239 }
240
241 void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform)
242 {
243     // Call this method first to assign contents scale to our layer so the painter can apply the scale transform.
244     updateContentsScale();
245
246     GraphicsLayer::setTransform(transform);
247     updateTransform();
248 }
249
250 void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform)
251 {
252     GraphicsLayer::setChildrenTransform(transform);
253     updateChildrenTransform();
254 }
255
256 void GraphicsLayerChromium::setPreserves3D(bool preserves3D)
257 {
258     if (preserves3D == m_preserves3D)
259         return;
260
261     GraphicsLayer::setPreserves3D(preserves3D);
262     updateLayerPreserves3D();
263 }
264
265 void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds)
266 {
267     GraphicsLayer::setMasksToBounds(masksToBounds);
268     updateMasksToBounds();
269 }
270
271 void GraphicsLayerChromium::setDrawsContent(bool drawsContent)
272 {
273     // Note carefully this early-exit is only correct because we also properly call
274     // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
275     if (drawsContent == m_drawsContent)
276         return;
277
278     GraphicsLayer::setDrawsContent(drawsContent);
279     updateLayerIsDrawable();
280 }
281
282 void GraphicsLayerChromium::setContentsVisible(bool contentsVisible)
283 {
284     // Note carefully this early-exit is only correct because we also properly call
285     // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
286     if (contentsVisible == m_contentsVisible)
287         return;
288
289     GraphicsLayer::setContentsVisible(contentsVisible);
290     updateLayerIsDrawable();
291 }
292
293 void GraphicsLayerChromium::setBackgroundColor(const Color& color)
294 {
295     GraphicsLayer::setBackgroundColor(color.rgb());
296
297     m_contentsLayerHasBackgroundColor = true;
298     updateLayerBackgroundColor();
299 }
300
301 void GraphicsLayerChromium::clearBackgroundColor()
302 {
303     GraphicsLayer::clearBackgroundColor();
304     m_contentsLayer.setBackgroundColor(static_cast<RGBA32>(0));
305 }
306
307 void GraphicsLayerChromium::setContentsOpaque(bool opaque)
308 {
309     GraphicsLayer::setContentsOpaque(opaque);
310     m_layer.setOpaque(m_contentsOpaque);
311 }
312
313 static bool copyWebCoreFilterOperationsToWebFilterOperations(const FilterOperations& filters, WebFilterOperations& webFilters)
314 {
315     for (size_t i = 0; i < filters.size(); ++i) {
316         const FilterOperation& op = *filters.at(i);
317         switch (op.getOperationType()) {
318         case FilterOperation::REFERENCE:
319             return false; // Not supported.
320         case FilterOperation::GRAYSCALE:
321         case FilterOperation::SEPIA:
322         case FilterOperation::SATURATE:
323         case FilterOperation::HUE_ROTATE: {
324             float amount = static_cast<const BasicColorMatrixFilterOperation*>(&op)->amount();
325             switch (op.getOperationType()) {
326             case FilterOperation::GRAYSCALE:
327                 webFilters.append(WebFilterOperation::createGrayscaleFilter(amount));
328                 break;
329             case FilterOperation::SEPIA:
330                 webFilters.append(WebFilterOperation::createSepiaFilter(amount));
331                 break;
332             case FilterOperation::SATURATE:
333                 webFilters.append(WebFilterOperation::createSaturateFilter(amount));
334                 break;
335             case FilterOperation::HUE_ROTATE:
336                 webFilters.append(WebFilterOperation::createHueRotateFilter(amount));
337                 break;
338             default:
339                 ASSERT_NOT_REACHED();
340             }
341             break;
342         }
343         case FilterOperation::INVERT:
344         case FilterOperation::OPACITY:
345         case FilterOperation::BRIGHTNESS:
346         case FilterOperation::CONTRAST: {
347             float amount = static_cast<const BasicComponentTransferFilterOperation*>(&op)->amount();
348             switch (op.getOperationType()) {
349             case FilterOperation::INVERT:
350                 webFilters.append(WebFilterOperation::createInvertFilter(amount));
351                 break;
352             case FilterOperation::OPACITY:
353                 webFilters.append(WebFilterOperation::createOpacityFilter(amount));
354                 break;
355             case FilterOperation::BRIGHTNESS:
356                 webFilters.append(WebFilterOperation::createBrightnessFilter(amount));
357                 break;
358             case FilterOperation::CONTRAST:
359                 webFilters.append(WebFilterOperation::createContrastFilter(amount));
360                 break;
361             default:
362                 ASSERT_NOT_REACHED();
363             }
364             break;
365         }
366         case FilterOperation::BLUR: {
367             float pixelRadius = static_cast<const BlurFilterOperation*>(&op)->stdDeviation().getFloatValue();
368             webFilters.append(WebFilterOperation::createBlurFilter(pixelRadius));
369             break;
370         }
371         case FilterOperation::DROP_SHADOW: {
372             const DropShadowFilterOperation& dropShadowOp = *static_cast<const DropShadowFilterOperation*>(&op);
373             webFilters.append(WebFilterOperation::createDropShadowFilter(WebPoint(dropShadowOp.x(), dropShadowOp.y()), dropShadowOp.stdDeviation(), dropShadowOp.color().rgb()));
374             break;
375         }
376 #if ENABLE(CSS_SHADERS)
377         case FilterOperation::CUSTOM:
378             return false; // Not supported.
379 #endif
380         case FilterOperation::PASSTHROUGH:
381         case FilterOperation::NONE:
382             break;
383         }
384     }
385     return true;
386 }
387
388 bool GraphicsLayerChromium::setFilters(const FilterOperations& filters)
389 {
390     WebFilterOperations webFilters;
391     if (!copyWebCoreFilterOperationsToWebFilterOperations(filters, webFilters)) {
392         // Make sure the filters are removed from the platform layer, as they are
393         // going to fallback to software mode.
394         m_layer.setFilters(WebFilterOperations());
395         GraphicsLayer::setFilters(FilterOperations());
396         return false;
397     }
398     m_layer.setFilters(webFilters);
399     return GraphicsLayer::setFilters(filters);
400 }
401
402 void GraphicsLayerChromium::setBackgroundFilters(const FilterOperations& filters)
403 {
404     WebFilterOperations webFilters;
405     if (!copyWebCoreFilterOperationsToWebFilterOperations(filters, webFilters))
406         return;
407     m_layer.setBackgroundFilters(webFilters);
408 }
409
410 void GraphicsLayerChromium::setMaskLayer(GraphicsLayer* maskLayer)
411 {
412     if (maskLayer == m_maskLayer)
413         return;
414
415     GraphicsLayer::setMaskLayer(maskLayer);
416
417     WebLayer maskWebLayer;
418     if (m_maskLayer)
419         maskWebLayer = *m_maskLayer->platformLayer();
420     m_layer.setMaskLayer(maskWebLayer);
421 }
422
423 void GraphicsLayerChromium::setBackfaceVisibility(bool visible)
424 {
425     GraphicsLayer::setBackfaceVisibility(visible);
426     m_layer.setDoubleSided(m_backfaceVisibility);
427 }
428
429 void GraphicsLayerChromium::setOpacity(float opacity)
430 {
431     float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
432     GraphicsLayer::setOpacity(clampedOpacity);
433     primaryLayer().setOpacity(opacity);
434 }
435
436 void GraphicsLayerChromium::setReplicatedByLayer(GraphicsLayer* layer)
437 {
438     GraphicsLayerChromium* layerChromium = static_cast<GraphicsLayerChromium*>(layer);
439     GraphicsLayer::setReplicatedByLayer(layer);
440
441     WebLayer webReplicaLayer;
442     if (layerChromium)
443         webReplicaLayer = layerChromium->primaryLayer();
444     primaryLayer().setReplicaLayer(webReplicaLayer);
445 }
446
447
448 void GraphicsLayerChromium::setContentsNeedsDisplay()
449 {
450     if (!m_contentsLayer.isNull())
451         m_contentsLayer.invalidate();
452 }
453
454 void GraphicsLayerChromium::setNeedsDisplay()
455 {
456     if (drawsContent())
457         m_layer.invalidate();
458 }
459
460 void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect)
461 {
462     if (drawsContent())
463         m_layer.invalidateRect(rect);
464 }
465
466 void GraphicsLayerChromium::setContentsRect(const IntRect& rect)
467 {
468     if (rect == m_contentsRect)
469         return;
470
471     GraphicsLayer::setContentsRect(rect);
472     updateContentsRect();
473 }
474
475 void GraphicsLayerChromium::setContentsToImage(Image* image)
476 {
477     bool childrenChanged = false;
478     if (image) {
479         if (m_contentsLayer.isNull() || m_contentsLayerPurpose != ContentsLayerForImage) {
480             WebKit::WebImageLayer imageLayer = WebKit::WebImageLayer::create();
481             setupContentsLayer(imageLayer);
482             m_contentsLayerPurpose = ContentsLayerForImage;
483             childrenChanged = true;
484         }
485         WebKit::WebImageLayer imageLayer = m_contentsLayer.to<WebKit::WebImageLayer>();
486         NativeImageSkia* nativeImage = image->nativeImageForCurrentFrame();
487         imageLayer.setBitmap(nativeImage->bitmap());
488         imageLayer.setOpaque(image->isBitmapImage() && !image->currentFrameHasAlpha());
489         updateContentsRect();
490     } else {
491         if (!m_contentsLayer.isNull()) {
492             childrenChanged = true;
493
494             // The old contents layer will be removed via updateChildList.
495             m_contentsLayer.reset();
496         }
497     }
498
499     if (childrenChanged)
500         updateChildList();
501 }
502
503 void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* platformLayer)
504 {
505     bool childrenChanged = false;
506     if (platformLayer) {
507         if (m_contentsLayer != *platformLayer) {
508             setupContentsLayer(*platformLayer);
509             m_contentsLayerPurpose = ContentsLayerForCanvas;
510             childrenChanged = true;
511         }
512         updateContentsRect();
513     } else {
514         if (!m_contentsLayer.isNull()) {
515             childrenChanged = true;
516
517             // The old contents layer will be removed via updateChildList.
518             m_contentsLayer.reset();
519         }
520     }
521
522     if (childrenChanged)
523         updateChildList();
524 }
525
526 bool GraphicsLayerChromium::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& animationName, double timeOffset)
527 {
528     primaryLayer().setAnimationDelegate(this);
529
530     int animationId = mapAnimationNameToId(animationName);
531     int groupId = AnimationIdVendor::getNextGroupId();
532
533     OwnPtr<WebKit::WebAnimation> toAdd(createWebAnimation(values, animation, animationId, groupId, timeOffset, boxSize));
534
535     if (toAdd) {
536         // Remove any existing animations with the same animation id and target property.
537         primaryLayer().removeAnimation(animationId, toAdd->targetProperty());
538         return primaryLayer().addAnimation(toAdd.get());
539     }
540
541     return false;
542 }
543
544 void GraphicsLayerChromium::pauseAnimation(const String& animationName, double timeOffset)
545 {
546     primaryLayer().pauseAnimation(mapAnimationNameToId(animationName), timeOffset);
547 }
548
549 void GraphicsLayerChromium::removeAnimation(const String& animationName)
550 {
551     primaryLayer().removeAnimation(mapAnimationNameToId(animationName));
552 }
553
554 void GraphicsLayerChromium::suspendAnimations(double wallClockTime)
555 {
556     // |wallClockTime| is in the wrong time base. Need to convert here.
557     // FIXME: find a more reliable way to do this.
558     double monotonicTime = wallClockTime + monotonicallyIncreasingTime() - currentTime();
559     primaryLayer().suspendAnimations(monotonicTime);
560 }
561
562 void GraphicsLayerChromium::resumeAnimations()
563 {
564     primaryLayer().resumeAnimations(monotonicallyIncreasingTime());
565 }
566
567 void GraphicsLayerChromium::addLinkHighlight(const Path& path)
568 {
569     m_linkHighlight = LinkHighlight::create(this, path, AnimationIdVendor::LinkHighlightAnimationId, AnimationIdVendor::getNextGroupId());
570     updateChildList();
571 }
572
573 void GraphicsLayerChromium::didFinishLinkHighlight()
574 {
575     if (m_linkHighlight)
576         m_linkHighlight->contentLayer()->removeFromParent();
577
578     m_linkHighlight.clear();
579 }
580
581 void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer)
582 {
583     bool childrenChanged = false;
584     if (layer) {
585         if (m_contentsLayer.isNull() || m_contentsLayerPurpose != ContentsLayerForVideo) {
586             setupContentsLayer(*layer);
587             m_contentsLayerPurpose = ContentsLayerForVideo;
588             childrenChanged = true;
589         }
590         updateContentsRect();
591     } else {
592         if (!m_contentsLayer.isNull()) {
593             childrenChanged = true;
594
595             // The old contents layer will be removed via updateChildList.
596             m_contentsLayer.reset();
597         }
598     }
599
600     if (childrenChanged)
601         updateChildList();
602 }
603
604 WebKit::WebLayer GraphicsLayerChromium::primaryLayer() const
605 {
606     return m_transformLayer.isNull() ? m_layer : m_transformLayer;
607 }
608
609 PlatformLayer* GraphicsLayerChromium::platformLayer() const
610 {
611     return const_cast<PlatformLayer*>(m_transformLayer.isNull() ? &m_layer : &m_transformLayer);
612 }
613
614 void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color)
615 {
616     if (color.isValid())
617         m_layer.setBackgroundColor(color.rgb());
618     else
619         m_layer.setBackgroundColor(static_cast<RGBA32>(0));
620 }
621
622 void GraphicsLayerChromium::setDebugBorder(const Color& color, float borderWidth)
623 {
624     if (color.isValid()) {
625         m_layer.setDebugBorderColor(color.rgb());
626         m_layer.setDebugBorderWidth(borderWidth);
627     } else {
628         m_layer.setDebugBorderColor(static_cast<RGBA32>(0));
629         m_layer.setDebugBorderWidth(0);
630     }
631 }
632
633 void GraphicsLayerChromium::updateChildList()
634 {
635     Vector<WebLayer> newChildren;
636
637     if (!m_transformLayer.isNull()) {
638         // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
639         newChildren.append(m_layer);
640     } else if (!m_contentsLayer.isNull()) {
641         // FIXME: add the contents layer in the correct order with negative z-order children.
642         // This does not cause visible rendering issues because currently contents layers are only used
643         // for replaced elements that don't have children.
644         newChildren.append(m_contentsLayer);
645     }
646
647     const Vector<GraphicsLayer*>& childLayers = children();
648     size_t numChildren = childLayers.size();
649     for (size_t i = 0; i < numChildren; ++i) {
650         GraphicsLayerChromium* curChild = static_cast<GraphicsLayerChromium*>(childLayers[i]);
651
652         newChildren.append(curChild->primaryLayer());
653     }
654
655     if (m_linkHighlight)
656         newChildren.append(m_linkHighlight->contentLayer());
657
658     for (size_t i = 0; i < newChildren.size(); ++i)
659         newChildren[i].removeFromParent();
660
661     WebVector<WebLayer> newWebChildren;
662     newWebChildren.assign(newChildren.data(), newChildren.size());
663
664     if (!m_transformLayer.isNull()) {
665         m_transformLayer.setChildren(newWebChildren);
666
667         if (!m_contentsLayer.isNull()) {
668             // If we have a transform layer, then the contents layer is parented in the
669             // primary layer (which is itself a child of the transform layer).
670             m_layer.removeAllChildren();
671             m_layer.addChild(m_contentsLayer);
672         }
673     } else
674         m_layer.setChildren(newWebChildren);
675 }
676
677 void GraphicsLayerChromium::updateLayerPosition()
678 {
679     primaryLayer().setPosition(m_position);
680 }
681
682 void GraphicsLayerChromium::updateLayerSize()
683 {
684     IntSize layerSize(m_size.width(), m_size.height());
685     if (!m_transformLayer.isNull()) {
686         m_transformLayer.setBounds(layerSize);
687         m_layer.setPosition(FloatPoint());
688     }
689
690     m_layer.setBounds(layerSize);
691
692     // Note that we don't resize m_contentsLayer. It's up the caller to do that.
693 }
694
695 void GraphicsLayerChromium::updateAnchorPoint()
696 {
697     primaryLayer().setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
698     primaryLayer().setAnchorPointZ(m_anchorPoint.z());
699 }
700
701 void GraphicsLayerChromium::updateTransform()
702 {
703     primaryLayer().setTransform(WebTransformationMatrix(m_transform));
704 }
705
706 void GraphicsLayerChromium::updateChildrenTransform()
707 {
708     primaryLayer().setSublayerTransform(WebTransformationMatrix(m_childrenTransform));
709 }
710
711 void GraphicsLayerChromium::updateMasksToBounds()
712 {
713     m_layer.setMasksToBounds(m_masksToBounds);
714     updateDebugIndicators();
715 }
716
717 void GraphicsLayerChromium::updateLayerPreserves3D()
718 {
719     if (m_preserves3D && m_transformLayer.isNull()) {
720         // Create the transform layer.
721         m_transformLayer = WebLayer::create();
722         m_transformLayer.setPreserves3D(true);
723         m_transformLayer.setAnimationDelegate(this);
724         m_layer.transferAnimationsTo(&m_transformLayer);
725
726         // Copy the position from this layer.
727         updateLayerPosition();
728         updateLayerSize();
729         updateAnchorPoint();
730         updateTransform();
731         updateChildrenTransform();
732
733         m_layer.setPosition(FloatPoint::zero());
734
735         m_layer.setAnchorPoint(FloatPoint(0.5f, 0.5f));
736         m_layer.setTransform(SkMatrix44());
737
738         // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer.
739         m_layer.setOpacity(1);
740
741         m_layer.setContentsScale(contentsScale());
742
743         // Move this layer to be a child of the transform layer.
744         if (parent())
745             parent()->platformLayer()->replaceChild(m_layer, m_transformLayer);
746         m_transformLayer.addChild(m_layer);
747
748         updateChildList();
749     } else if (!m_preserves3D && !m_transformLayer.isNull()) {
750         // Relace the transformLayer in the parent with this layer.
751         m_layer.removeFromParent();
752         if (parent())
753             parent()->platformLayer()->replaceChild(m_transformLayer, m_layer);
754
755         m_layer.setAnimationDelegate(this);
756         m_transformLayer.transferAnimationsTo(&m_layer);
757
758         // Release the transform layer.
759         m_transformLayer.setAnimationDelegate(0);
760         m_transformLayer.reset();
761
762         updateLayerPosition();
763         updateLayerSize();
764         updateAnchorPoint();
765         updateTransform();
766         updateChildrenTransform();
767
768         updateChildList();
769     }
770
771     m_layer.setPreserves3D(m_preserves3D);
772     primaryLayer().setOpacity(m_opacity);
773     updateNames();
774 }
775
776 void GraphicsLayerChromium::updateLayerIsDrawable()
777 {
778     // For the rest of the accelerated compositor code, there is no reason to make a
779     // distinction between drawsContent and contentsVisible. So, for m_layer, these two
780     // flags are combined here. m_contentsLayer shouldn't receive the drawsContent flag
781     // so it is only given contentsVisible.
782
783     m_layer.setDrawsContent(m_drawsContent && m_contentsVisible);
784
785     if (!m_contentsLayer.isNull())
786         m_contentsLayer.setDrawsContent(m_contentsVisible);
787
788     if (m_drawsContent)
789         m_layer.invalidate();
790
791     updateDebugIndicators();
792 }
793
794 void GraphicsLayerChromium::updateLayerBackgroundColor()
795 {
796     if (m_contentsLayer.isNull())
797         return;
798
799     // We never create the contents layer just for background color yet.
800     if (m_backgroundColorSet)
801         m_contentsLayer.setBackgroundColor(m_backgroundColor.rgb());
802     else
803         m_contentsLayer.setBackgroundColor(static_cast<RGBA32>(0));
804 }
805
806 void GraphicsLayerChromium::updateContentsVideo()
807 {
808     // FIXME: Implement
809 }
810
811 void GraphicsLayerChromium::updateContentsRect()
812 {
813     if (m_contentsLayer.isNull())
814         return;
815
816     m_contentsLayer.setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
817     m_contentsLayer.setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
818 }
819
820 void GraphicsLayerChromium::updateContentsScale()
821 {
822     // If page scale is already applied then there's no need to apply it again.
823     if (appliesPageScale() || m_layer.isNull())
824         return;
825
826     m_layer.setContentsScale(contentsScale());
827 }
828
829 void GraphicsLayerChromium::setupContentsLayer(WebLayer contentsLayer)
830 {
831     if (contentsLayer == m_contentsLayer)
832         return;
833
834     if (!m_contentsLayer.isNull()) {
835         m_contentsLayer.setUseParentBackfaceVisibility(false);
836         m_contentsLayer.removeFromParent();
837         m_contentsLayer.reset();
838     }
839
840     m_contentsLayer = contentsLayer;
841
842     if (!m_contentsLayer.isNull()) {
843         m_contentsLayer.setAnchorPoint(FloatPoint(0, 0));
844         m_contentsLayer.setUseParentBackfaceVisibility(true);
845
846         // It is necessary to call setDrawsContent as soon as we receive the new contentsLayer, for
847         // the correctness of early exit conditions in setDrawsContent() and setContentsVisible().
848         m_contentsLayer.setDrawsContent(m_contentsVisible);
849
850         // Insert the content layer first. Video elements require this, because they have
851         // shadow content that must display in front of the video.
852         m_layer.insertChild(m_contentsLayer, 0);
853
854         if (showDebugBorders()) {
855             m_contentsLayer.setDebugBorderColor(Color(0, 0, 128, 180).rgb());
856             m_contentsLayer.setDebugBorderWidth(1);
857         }
858     }
859     updateDebugIndicators();
860     updateNames();
861 }
862
863 float GraphicsLayerChromium::contentsScale() const
864 {
865     if (!appliesPageScale())
866         return pageScaleFactor() * deviceScaleFactor();
867     return 1;
868 }
869
870 void GraphicsLayerChromium::deviceOrPageScaleFactorChanged()
871 {
872     updateContentsScale();
873     // Invalidations are clamped to the layer's bounds but we receive the scale changed notification before receiving
874     // the new layer bounds. When the scale changes, we really want to invalidate the post-scale layer bounds, so we
875     // remember that the scale has changed and then invalidate the full layer bounds when we receive the new size.
876     m_pageScaleChanged = true;
877 }
878
879 void GraphicsLayerChromium::paint(GraphicsContext& context, const IntRect& clip)
880 {
881     context.platformContext()->setDrawingToImageBuffer(true);
882     paintGraphicsLayerContents(context, clip);
883 }
884
885 int GraphicsLayerChromium::mapAnimationNameToId(const String& animationName)
886 {
887     if (animationName.isEmpty())
888         return 0;
889
890     if (!m_animationIdMap.contains(animationName))
891         m_animationIdMap.add(animationName, AnimationIdVendor::getNextAnimationId());
892
893     return m_animationIdMap.find(animationName)->second;
894 }
895
896 void GraphicsLayerChromium::notifyAnimationStarted(double startTime)
897 {
898     if (m_client)
899         m_client->notifyAnimationStarted(this, startTime);
900 }
901
902 void GraphicsLayerChromium::notifyAnimationFinished(double)
903 {
904     // Do nothing.
905 }
906
907 } // namespace WebCore
908
909 #endif // USE(ACCELERATED_COMPOSITING)