Part 2 of removing PlatformString.h, remove PlatformString.h
[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 "AnimationTranslationUtil.h"
49 #include "ContentLayerChromium.h"
50 #include "FloatConversion.h"
51 #include "FloatRect.h"
52 #include "GraphicsContext.h"
53 #include "Image.h"
54 #include "NativeImageSkia.h"
55 #include "PlatformContextSkia.h"
56 #include "ScrollableArea.h"
57 #include "SkMatrix44.h"
58 #include "SystemTime.h"
59 #include <public/Platform.h>
60 #include <public/WebAnimation.h>
61 #include <public/WebCompositorSupport.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/HashSet.h>
71 #include <wtf/StringExtras.h>
72 #include <wtf/text/CString.h>
73 #include <wtf/text/WTFString.h>
74
75 using namespace std;
76 using namespace WebKit;
77
78 namespace WebCore {
79
80 PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
81 {
82     return adoptPtr(new GraphicsLayerChromium(client));
83 }
84
85 GraphicsLayerChromium::GraphicsLayerChromium(GraphicsLayerClient* client)
86     : GraphicsLayer(client)
87     , m_contentsLayer(0)
88     , m_contentsLayerId(0)
89     , m_linkHighlight(0)
90     , m_contentsLayerPurpose(NoContentsLayer)
91     , m_contentsLayerHasBackgroundColor(false)
92     , m_inSetChildren(false)
93     , m_pageScaleChanged(false)
94     , m_scrollableArea(0)
95 {
96     m_opaqueRectTrackingContentLayerDelegate = adoptPtr(new OpaqueRectTrackingContentLayerDelegate(this));
97
98     if (WebCompositorSupport* compositorSupport = Platform::current()->compositorSupport())
99         m_layer = adoptPtr(compositorSupport->createContentLayer(m_opaqueRectTrackingContentLayerDelegate.get()));
100     else
101         m_layer = adoptPtr(WebContentLayer::create(m_opaqueRectTrackingContentLayerDelegate.get()));
102
103     m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible);
104     m_layer->layer()->setScrollClient(this);
105     if (client)
106         deviceOrPageScaleFactorChanged();
107     updateDebugIndicators();
108 }
109
110 GraphicsLayerChromium::~GraphicsLayerChromium()
111 {
112     willBeDestroyed();
113 }
114
115 void GraphicsLayerChromium::willBeDestroyed()
116 {
117     if (m_linkHighlight) {
118         m_linkHighlight->clearCurrentGraphicsLayer();
119         m_linkHighlight = 0;
120     }
121
122     GraphicsLayer::willBeDestroyed();
123 }
124
125 void GraphicsLayerChromium::setName(const String& inName)
126 {
127     m_nameBase = inName;
128     String name = String::format("GraphicsLayer(%p) ", this) + inName;
129     GraphicsLayer::setName(name);
130     updateNames();
131 }
132
133 void GraphicsLayerChromium::updateNames()
134 {
135     String debugName = "Layer for " + m_nameBase;
136     m_layer->layer()->setDebugName(debugName);
137
138     if (m_transformLayer) {
139         String debugName = "TransformLayer for " + m_nameBase;
140         m_transformLayer->setDebugName(debugName);
141     }
142     if (WebLayer* contentsLayer = contentsLayerIfRegistered()) {
143         String debugName = "ContentsLayer for " + m_nameBase;
144         contentsLayer->setDebugName(debugName);
145     }
146     if (m_linkHighlight) {
147         String debugName = "LinkHighlight for " + m_nameBase;
148         m_linkHighlight->layer()->setDebugName(debugName);
149     }
150 }
151
152 bool GraphicsLayerChromium::setChildren(const Vector<GraphicsLayer*>& children)
153 {
154     m_inSetChildren = true;
155     bool childrenChanged = GraphicsLayer::setChildren(children);
156
157     if (childrenChanged)
158         updateChildList();
159     m_inSetChildren = false;
160
161     return childrenChanged;
162 }
163
164 void GraphicsLayerChromium::addChild(GraphicsLayer* childLayer)
165 {
166     GraphicsLayer::addChild(childLayer);
167     if (!m_inSetChildren)
168         updateChildList();
169 }
170
171 void GraphicsLayerChromium::addChildAtIndex(GraphicsLayer* childLayer, int index)
172 {
173     GraphicsLayer::addChildAtIndex(childLayer, index);
174     updateChildList();
175 }
176
177 void GraphicsLayerChromium::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
178 {
179     GraphicsLayer::addChildBelow(childLayer, sibling);
180     updateChildList();
181 }
182
183 void GraphicsLayerChromium::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
184 {
185     GraphicsLayer::addChildAbove(childLayer, sibling);
186     updateChildList();
187 }
188
189 bool GraphicsLayerChromium::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
190 {
191     if (GraphicsLayer::replaceChild(oldChild, newChild)) {
192         updateChildList();
193         return true;
194     }
195     return false;
196 }
197
198 void GraphicsLayerChromium::removeFromParent()
199 {
200     GraphicsLayer::removeFromParent();
201     platformLayer()->removeFromParent();
202 }
203
204 void GraphicsLayerChromium::setPosition(const FloatPoint& point)
205 {
206     GraphicsLayer::setPosition(point);
207     updateLayerPosition();
208 }
209
210 void GraphicsLayerChromium::setAnchorPoint(const FloatPoint3D& point)
211 {
212     GraphicsLayer::setAnchorPoint(point);
213     updateAnchorPoint();
214 }
215
216 void GraphicsLayerChromium::setSize(const FloatSize& size)
217 {
218     // We are receiving negative sizes here that cause assertions to fail in the compositor. Clamp them to 0 to
219     // avoid those assertions.
220     // FIXME: This should be an ASSERT instead, as negative sizes should not exist in WebCore.
221     FloatSize clampedSize = size;
222     if (clampedSize.width() < 0 || clampedSize.height() < 0)
223         clampedSize = FloatSize();
224
225     if (clampedSize == m_size)
226         return;
227
228     GraphicsLayer::setSize(clampedSize);
229     updateLayerSize();
230
231     if (m_pageScaleChanged) {
232         m_layer->layer()->invalidate();
233         if (m_linkHighlight)
234             m_linkHighlight->invalidate();
235     }
236     m_pageScaleChanged = false;
237 }
238
239 void GraphicsLayerChromium::setTransform(const TransformationMatrix& transform)
240 {
241     // Call this method first to assign contents scale to our layer so the painter can apply the scale transform.
242     updateContentsScale();
243
244     GraphicsLayer::setTransform(transform);
245     updateTransform();
246 }
247
248 void GraphicsLayerChromium::setChildrenTransform(const TransformationMatrix& transform)
249 {
250     GraphicsLayer::setChildrenTransform(transform);
251     updateChildrenTransform();
252 }
253
254 void GraphicsLayerChromium::setPreserves3D(bool preserves3D)
255 {
256     if (preserves3D == m_preserves3D)
257         return;
258
259     GraphicsLayer::setPreserves3D(preserves3D);
260     updateLayerPreserves3D();
261 }
262
263 void GraphicsLayerChromium::setMasksToBounds(bool masksToBounds)
264 {
265     GraphicsLayer::setMasksToBounds(masksToBounds);
266     updateMasksToBounds();
267 }
268
269 void GraphicsLayerChromium::setDrawsContent(bool drawsContent)
270 {
271     // Note carefully this early-exit is only correct because we also properly call
272     // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
273     if (drawsContent == m_drawsContent)
274         return;
275
276     GraphicsLayer::setDrawsContent(drawsContent);
277     updateLayerIsDrawable();
278 }
279
280 void GraphicsLayerChromium::setContentsVisible(bool contentsVisible)
281 {
282     // Note carefully this early-exit is only correct because we also properly call
283     // WebLayer::setDrawsContent whenever m_contentsLayer is set to a new layer in setupContentsLayer().
284     if (contentsVisible == m_contentsVisible)
285         return;
286
287     GraphicsLayer::setContentsVisible(contentsVisible);
288     updateLayerIsDrawable();
289 }
290
291 void GraphicsLayerChromium::setBackgroundColor(const Color& color)
292 {
293     GraphicsLayer::setBackgroundColor(color.rgb());
294
295     m_contentsLayerHasBackgroundColor = true;
296     updateLayerBackgroundColor();
297 }
298
299 void GraphicsLayerChromium::clearBackgroundColor()
300 {
301     GraphicsLayer::clearBackgroundColor();
302
303     if (WebLayer* contentsLayer = contentsLayerIfRegistered())
304         contentsLayer->setBackgroundColor(static_cast<RGBA32>(0));
305 }
306
307 void GraphicsLayerChromium::setContentsOpaque(bool opaque)
308 {
309     GraphicsLayer::setContentsOpaque(opaque);
310     m_layer->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->layer()->setFilters(WebFilterOperations());
395         GraphicsLayer::setFilters(FilterOperations());
396         return false;
397     }
398     m_layer->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->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 = m_maskLayer ? m_maskLayer->platformLayer() : 0;
418     m_layer->layer()->setMaskLayer(maskWebLayer);
419 }
420
421 void GraphicsLayerChromium::setBackfaceVisibility(bool visible)
422 {
423     GraphicsLayer::setBackfaceVisibility(visible);
424     m_layer->setDoubleSided(m_backfaceVisibility);
425 }
426
427 void GraphicsLayerChromium::setOpacity(float opacity)
428 {
429     float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
430     GraphicsLayer::setOpacity(clampedOpacity);
431     platformLayer()->setOpacity(opacity);
432 }
433
434 void GraphicsLayerChromium::setReplicatedByLayer(GraphicsLayer* layer)
435 {
436     GraphicsLayerChromium* layerChromium = static_cast<GraphicsLayerChromium*>(layer);
437     GraphicsLayer::setReplicatedByLayer(layer);
438
439     WebLayer* webReplicaLayer = layerChromium ? layerChromium->platformLayer() : 0;
440     platformLayer()->setReplicaLayer(webReplicaLayer);
441 }
442
443
444 void GraphicsLayerChromium::setContentsNeedsDisplay()
445 {
446     if (WebLayer* contentsLayer = contentsLayerIfRegistered())
447         contentsLayer->invalidate();
448 }
449
450 void GraphicsLayerChromium::setNeedsDisplay()
451 {
452     if (drawsContent()) {
453         m_layer->layer()->invalidate();
454         if (m_linkHighlight)
455             m_linkHighlight->invalidate();
456     }
457 }
458
459 void GraphicsLayerChromium::setNeedsDisplayInRect(const FloatRect& rect)
460 {
461     if (drawsContent()) {
462         m_layer->layer()->invalidateRect(rect);
463         if (m_linkHighlight)
464             m_linkHighlight->invalidate();
465     }
466 }
467
468 void GraphicsLayerChromium::setContentsRect(const IntRect& rect)
469 {
470     if (rect == m_contentsRect)
471         return;
472
473     GraphicsLayer::setContentsRect(rect);
474     updateContentsRect();
475 }
476
477 void GraphicsLayerChromium::setContentsToImage(Image* image)
478 {
479     bool childrenChanged = false;
480     if (image) {
481         if (m_contentsLayerPurpose != ContentsLayerForImage) {
482             if (WebCompositorSupport* compositorSupport = Platform::current()->compositorSupport())
483                 m_imageLayer = adoptPtr(compositorSupport->createImageLayer());
484             else
485                 m_imageLayer = adoptPtr(WebImageLayer::create());
486             registerContentsLayer(m_imageLayer->layer());
487
488             setupContentsLayer(m_imageLayer->layer());
489             m_contentsLayerPurpose = ContentsLayerForImage;
490             childrenChanged = true;
491         }
492         NativeImageSkia* nativeImage = image->nativeImageForCurrentFrame();
493         m_imageLayer->setBitmap(nativeImage->bitmap());
494         m_imageLayer->layer()->setOpaque(image->isBitmapImage() && !image->currentFrameHasAlpha());
495         updateContentsRect();
496     } else {
497         if (m_imageLayer) {
498             childrenChanged = true;
499
500             unregisterContentsLayer(m_imageLayer->layer());
501             m_imageLayer.clear();
502         }
503         // The old contents layer will be removed via updateChildList.
504         m_contentsLayer = 0;
505     }
506
507     if (childrenChanged)
508         updateChildList();
509 }
510
511 static HashSet<int>* s_registeredLayerSet;
512
513 void GraphicsLayerChromium::registerContentsLayer(WebLayer* layer)
514 {
515     if (!s_registeredLayerSet)
516         s_registeredLayerSet = new HashSet<int>;
517     if (s_registeredLayerSet->contains(layer->id()))
518         CRASH();
519     s_registeredLayerSet->add(layer->id());
520 }
521
522 void GraphicsLayerChromium::unregisterContentsLayer(WebLayer* layer)
523 {
524     ASSERT(s_registeredLayerSet);
525     if (!s_registeredLayerSet->contains(layer->id()))
526         CRASH();
527     s_registeredLayerSet->remove(layer->id());
528 }
529
530 void GraphicsLayerChromium::clearContentsLayerIfUnregistered()
531 {
532     if (!m_contentsLayerId || s_registeredLayerSet->contains(m_contentsLayerId))
533         return;
534
535     m_contentsLayer = 0;
536     m_contentsLayerId = 0;
537 }
538
539 WebLayer* GraphicsLayerChromium::contentsLayerIfRegistered()
540 {
541     clearContentsLayerIfUnregistered();
542     return m_contentsLayer;
543 }
544
545 void GraphicsLayerChromium::setContentsToCanvas(PlatformLayer* layer)
546 {
547     setContentsTo(ContentsLayerForCanvas, layer);
548 }
549
550 void GraphicsLayerChromium::setContentsToMedia(PlatformLayer* layer)
551 {
552     setContentsTo(ContentsLayerForVideo, layer);
553 }
554
555 void GraphicsLayerChromium::setContentsTo(ContentsLayerPurpose purpose, WebLayer* layer)
556 {
557     bool childrenChanged = false;
558     if (layer) {
559         ASSERT(s_registeredLayerSet);
560         if (!s_registeredLayerSet->contains(layer->id()))
561             CRASH();
562         if (m_contentsLayerId != layer->id()) {
563             setupContentsLayer(layer);
564             m_contentsLayerPurpose = purpose;
565             childrenChanged = true;
566         }
567         updateContentsRect();
568     } else {
569         if (m_contentsLayer) {
570             childrenChanged = true;
571
572             // The old contents layer will be removed via updateChildList.
573             m_contentsLayer = 0;
574         }
575     }
576
577     if (childrenChanged)
578         updateChildList();
579 }
580
581 bool GraphicsLayerChromium::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& animationName, double timeOffset)
582 {
583     platformLayer()->setAnimationDelegate(this);
584
585     int animationId = 0;
586
587     if (m_animationIdMap.contains(animationName))
588         animationId = m_animationIdMap.get(animationName);
589
590     OwnPtr<WebAnimation> toAdd(createWebAnimation(values, animation, animationId, timeOffset, boxSize));
591
592     if (toAdd) {
593         animationId = toAdd->id();
594         m_animationIdMap.set(animationName, animationId);
595
596         // Remove any existing animations with the same animation id and target property.
597         platformLayer()->removeAnimation(animationId, toAdd->targetProperty());
598         return platformLayer()->addAnimation(toAdd.get());
599     }
600
601     return false;
602 }
603
604 void GraphicsLayerChromium::pauseAnimation(const String& animationName, double timeOffset)
605 {
606     if (m_animationIdMap.contains(animationName))
607         platformLayer()->pauseAnimation(m_animationIdMap.get(animationName), timeOffset);
608 }
609
610 void GraphicsLayerChromium::removeAnimation(const String& animationName)
611 {
612     if (m_animationIdMap.contains(animationName))
613         platformLayer()->removeAnimation(m_animationIdMap.get(animationName));
614 }
615
616 void GraphicsLayerChromium::suspendAnimations(double wallClockTime)
617 {
618     // |wallClockTime| is in the wrong time base. Need to convert here.
619     // FIXME: find a more reliable way to do this.
620     double monotonicTime = wallClockTime + monotonicallyIncreasingTime() - currentTime();
621     platformLayer()->suspendAnimations(monotonicTime);
622 }
623
624 void GraphicsLayerChromium::resumeAnimations()
625 {
626     platformLayer()->resumeAnimations(monotonicallyIncreasingTime());
627 }
628
629 void GraphicsLayerChromium::setLinkHighlight(LinkHighlightClient* linkHighlight)
630 {
631     m_linkHighlight = linkHighlight;
632     updateChildList();
633 }
634
635 PlatformLayer* GraphicsLayerChromium::platformLayer() const
636 {
637     return m_transformLayer ? m_transformLayer.get() : m_layer->layer();
638 }
639
640 void GraphicsLayerChromium::setDebugBackgroundColor(const Color& color)
641 {
642     if (color.isValid())
643         m_layer->layer()->setBackgroundColor(color.rgb());
644     else
645         m_layer->layer()->setBackgroundColor(static_cast<RGBA32>(0));
646 }
647
648 void GraphicsLayerChromium::setDebugBorder(const Color& color, float borderWidth)
649 {
650     if (color.isValid()) {
651         m_layer->layer()->setDebugBorderColor(color.rgb());
652         m_layer->layer()->setDebugBorderWidth(borderWidth);
653     } else {
654         m_layer->layer()->setDebugBorderColor(static_cast<RGBA32>(0));
655         m_layer->layer()->setDebugBorderWidth(0);
656     }
657 }
658
659 void GraphicsLayerChromium::updateChildList()
660 {
661     WebLayer* childHost = m_transformLayer ? m_transformLayer.get() : m_layer->layer();
662     childHost->removeAllChildren();
663
664     clearContentsLayerIfUnregistered();
665
666     if (m_transformLayer) {
667         // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
668         childHost->addChild(m_layer->layer());
669     } else if (m_contentsLayer) {
670         // FIXME: add the contents layer in the correct order with negative z-order children.
671         // This does not cause visible rendering issues because currently contents layers are only used
672         // for replaced elements that don't have children.
673         childHost->addChild(m_contentsLayer);
674     }
675
676     const Vector<GraphicsLayer*>& childLayers = children();
677     size_t numChildren = childLayers.size();
678     for (size_t i = 0; i < numChildren; ++i) {
679         GraphicsLayerChromium* curChild = static_cast<GraphicsLayerChromium*>(childLayers[i]);
680
681         childHost->addChild(curChild->platformLayer());
682     }
683
684     if (m_linkHighlight)
685         childHost->addChild(m_linkHighlight->layer());
686
687     if (m_transformLayer && m_contentsLayer) {
688         // If we have a transform layer, then the contents layer is parented in the
689         // primary layer (which is itself a child of the transform layer).
690         m_layer->layer()->removeAllChildren();
691         m_layer->layer()->addChild(m_contentsLayer);
692     }
693 }
694
695 void GraphicsLayerChromium::updateLayerPosition()
696 {
697     platformLayer()->setPosition(m_position);
698 }
699
700 void GraphicsLayerChromium::updateLayerSize()
701 {
702     IntSize layerSize(m_size.width(), m_size.height());
703     if (m_transformLayer) {
704         m_transformLayer->setBounds(layerSize);
705         m_layer->layer()->setPosition(FloatPoint());
706     }
707
708     m_layer->layer()->setBounds(layerSize);
709
710     // Note that we don't resize m_contentsLayer-> It's up the caller to do that.
711 }
712
713 void GraphicsLayerChromium::updateAnchorPoint()
714 {
715     platformLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
716     platformLayer()->setAnchorPointZ(m_anchorPoint.z());
717 }
718
719 void GraphicsLayerChromium::updateTransform()
720 {
721     platformLayer()->setTransform(WebTransformationMatrix(m_transform));
722 }
723
724 void GraphicsLayerChromium::updateChildrenTransform()
725 {
726     platformLayer()->setSublayerTransform(WebTransformationMatrix(m_childrenTransform));
727 }
728
729 void GraphicsLayerChromium::updateMasksToBounds()
730 {
731     m_layer->layer()->setMasksToBounds(m_masksToBounds);
732     updateDebugIndicators();
733 }
734
735 void GraphicsLayerChromium::updateLayerPreserves3D()
736 {
737     if (m_preserves3D && !m_transformLayer) {
738         if (WebCompositorSupport* compositorSupport = Platform::current()->compositorSupport())
739             m_transformLayer = adoptPtr(compositorSupport->createLayer());
740         else
741             m_transformLayer = adoptPtr(WebLayer::create());
742
743         m_transformLayer->setPreserves3D(true);
744         m_transformLayer->setAnimationDelegate(this);
745         m_layer->layer()->transferAnimationsTo(m_transformLayer.get());
746
747         // Copy the position from this layer.
748         updateLayerPosition();
749         updateLayerSize();
750         updateAnchorPoint();
751         updateTransform();
752         updateChildrenTransform();
753
754         m_layer->layer()->setPosition(FloatPoint::zero());
755
756         m_layer->layer()->setAnchorPoint(FloatPoint(0.5f, 0.5f));
757         m_layer->layer()->setTransform(SkMatrix44());
758
759         // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer.
760         m_layer->layer()->setOpacity(1);
761
762         m_layer->setContentsScale(contentsScale());
763
764         // Move this layer to be a child of the transform layer.
765         if (parent())
766             parent()->platformLayer()->replaceChild(m_layer->layer(), m_transformLayer.get());
767         m_transformLayer->addChild(m_layer->layer());
768
769         updateChildList();
770     } else if (m_preserves3D && !m_transformLayer) {
771         // Relace the transformLayer in the parent with this layer.
772         m_layer->layer()->removeFromParent();
773         if (parent())
774             parent()->platformLayer()->replaceChild(m_transformLayer.get(), m_layer->layer());
775
776         m_layer->layer()->setAnimationDelegate(this);
777         m_transformLayer->transferAnimationsTo(m_layer->layer());
778
779         // Release the transform layer.
780         m_transformLayer->setAnimationDelegate(0);
781         m_transformLayer.clear();
782
783         updateLayerPosition();
784         updateLayerSize();
785         updateAnchorPoint();
786         updateTransform();
787         updateChildrenTransform();
788
789         updateChildList();
790     }
791
792     m_layer->layer()->setPreserves3D(m_preserves3D);
793     platformLayer()->setOpacity(m_opacity);
794     updateNames();
795 }
796
797 void GraphicsLayerChromium::updateLayerIsDrawable()
798 {
799     // For the rest of the accelerated compositor code, there is no reason to make a
800     // distinction between drawsContent and contentsVisible. So, for m_layer->layer(), these two
801     // flags are combined here. m_contentsLayer shouldn't receive the drawsContent flag
802     // so it is only given contentsVisible.
803
804     m_layer->layer()->setDrawsContent(m_drawsContent && m_contentsVisible);
805     if (WebLayer* contentsLayer = contentsLayerIfRegistered())
806         contentsLayer->setDrawsContent(m_contentsVisible);
807
808     if (m_drawsContent) {
809         m_layer->layer()->invalidate();
810         if (m_linkHighlight)
811             m_linkHighlight->invalidate();
812     }
813
814     updateDebugIndicators();
815 }
816
817 void GraphicsLayerChromium::updateLayerBackgroundColor()
818 {
819     WebLayer* contentsLayer = contentsLayerIfRegistered();
820     if (!contentsLayer)
821         return;
822
823     // We never create the contents layer just for background color yet.
824     if (m_backgroundColorSet)
825         contentsLayer->setBackgroundColor(m_backgroundColor.rgb());
826     else
827         contentsLayer->setBackgroundColor(static_cast<RGBA32>(0));
828 }
829
830 void GraphicsLayerChromium::updateContentsVideo()
831 {
832     // FIXME: Implement
833 }
834
835 void GraphicsLayerChromium::updateContentsRect()
836 {
837     WebLayer* contentsLayer = contentsLayerIfRegistered();
838     if (!contentsLayer)
839         return;
840
841     contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
842     contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
843 }
844
845 void GraphicsLayerChromium::updateContentsScale()
846 {
847     // If page scale is already applied then there's no need to apply it again.
848     if (appliesPageScale())
849         return;
850
851     m_layer->setContentsScale(contentsScale());
852 }
853
854 void GraphicsLayerChromium::setupContentsLayer(WebLayer* contentsLayer)
855 {
856     m_contentsLayer = contentsLayer;
857     m_contentsLayerId = m_contentsLayer->id();
858
859     if (m_contentsLayer) {
860         m_contentsLayer->setAnchorPoint(FloatPoint(0, 0));
861         m_contentsLayer->setUseParentBackfaceVisibility(true);
862
863         // It is necessary to call setDrawsContent as soon as we receive the new contentsLayer, for
864         // the correctness of early exit conditions in setDrawsContent() and setContentsVisible().
865         m_contentsLayer->setDrawsContent(m_contentsVisible);
866
867         // Insert the content layer first. Video elements require this, because they have
868         // shadow content that must display in front of the video.
869         m_layer->layer()->insertChild(m_contentsLayer, 0);
870
871         if (showDebugBorders()) {
872             m_contentsLayer->setDebugBorderColor(Color(0, 0, 128, 180).rgb());
873             m_contentsLayer->setDebugBorderWidth(1);
874         }
875     }
876     updateDebugIndicators();
877     updateNames();
878 }
879
880 float GraphicsLayerChromium::contentsScale() const
881 {
882     if (!appliesPageScale())
883         return pageScaleFactor() * deviceScaleFactor();
884     return 1;
885 }
886
887 void GraphicsLayerChromium::deviceOrPageScaleFactorChanged()
888 {
889     updateContentsScale();
890     // Invalidations are clamped to the layer's bounds but we receive the scale changed notification before receiving
891     // the new layer bounds. When the scale changes, we really want to invalidate the post-scale layer bounds, so we
892     // remember that the scale has changed and then invalidate the full layer bounds when we receive the new size.
893     m_pageScaleChanged = true;
894 }
895
896 void GraphicsLayerChromium::paint(GraphicsContext& context, const IntRect& clip)
897 {
898     context.platformContext()->setDrawingToImageBuffer(true);
899     paintGraphicsLayerContents(context, clip);
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 void GraphicsLayerChromium::didScroll()
914 {
915     if (m_scrollableArea)
916         m_scrollableArea->scrollToOffsetWithoutAnimation(IntPoint(m_layer->layer()->scrollPosition()));
917 }
918
919 } // namespace WebCore
920
921 #endif // USE(ACCELERATED_COMPOSITING)