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