1/*
2 * Copyright (C) 2010, 2011, 2012 Research In Motion Limited. All rights reserved.
3 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Copyright (C) 2009 Apple Inc. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33
34/** FIXME
35 * This file borrows code heavily from platform/graphics/win/GraphicsLayerCACF.cpp
36 * (and hence it includes both copyrights)
37 * Ideally the common code (mostly the code that keeps track of the layer hierarchy)
38 * should be kept separate and shared between platforms. It would be a well worthwhile
39 * effort once the Windows implementation (binaries and headers) of CoreAnimation is
40 * checked in to the WebKit repository. Until then only Apple can make this happen.
41 */
42
43#include "config.h"
44
45#if USE(ACCELERATED_COMPOSITING)
46
47#include "GraphicsLayerBlackBerry.h"
48
49#include "FloatConversion.h"
50#include "FloatRect.h"
51#include "Image.h"
52#include "LayerWebKitThread.h"
53#include "NotImplemented.h"
54#include "PlatformString.h"
55#include "SystemTime.h"
56#include <wtf/CurrentTime.h>
57#include <wtf/StringExtras.h>
58#include <wtf/text/CString.h>
59
60using namespace std;
61
62namespace WebCore {
63
64static void setLayerBorderColor(LayerWebKitThread& layer, const Color& color)
65{
66 layer.setBorderColor(color);
67}
68
69static void clearBorderColor(LayerWebKitThread& layer)
70{
71 layer.setBorderColor(static_cast<RGBA32>(0));
72}
73
74static void setLayerBackgroundColor(LayerWebKitThread& layer, const Color& color)
75{
76 layer.setBackgroundColor(color);
77}
78
79static void clearLayerBackgroundColor(LayerWebKitThread& layer)
80{
81 layer.setBackgroundColor(static_cast<RGBA32>(0));
82}
83
84PassOwnPtr<GraphicsLayer> GraphicsLayer::create(GraphicsLayerClient* client)
85{
86 return adoptPtr(new GraphicsLayerBlackBerry(client));
87}
88
89GraphicsLayerBlackBerry::GraphicsLayerBlackBerry(GraphicsLayerClient* client)
90 : GraphicsLayer(client)
91 , m_suspendTime(0)
92 , m_contentsLayerPurpose(NoContentsLayer)
93 , m_contentsLayerHasBackgroundColor(false)
94{
95 m_layer = LayerWebKitThread::create(LayerData::Layer, this);
96
97 updateDebugIndicators();
98}
99
100GraphicsLayerBlackBerry::~GraphicsLayerBlackBerry()
101{
102 if (m_layer)
103 m_layer->setOwner(0);
104 if (m_contentsLayer)
105 m_contentsLayer->setOwner(0);
106 if (m_transformLayer)
107 m_transformLayer->setOwner(0);
108}
109
110void GraphicsLayerBlackBerry::setName(const String& inName)
111{
112 String name = String::format("GraphicsLayerBlackBerry(%p) GraphicsLayer(%p) ", m_layer.get(), this) + inName;
113 GraphicsLayer::setName(name);
114}
115
116bool GraphicsLayerBlackBerry::setChildren(const Vector<GraphicsLayer*>& children)
117{
118 bool childrenChanged = GraphicsLayer::setChildren(children);
119 // FIXME: GraphicsLayer::setChildren calls addChild() for each sublayer, which
120 // will end up calling updateSublayerList() N times.
121 if (childrenChanged)
122 updateSublayerList();
123
124 return childrenChanged;
125}
126
127void GraphicsLayerBlackBerry::addChild(GraphicsLayer* childLayer)
128{
129 GraphicsLayer::addChild(childLayer);
130 updateSublayerList();
131}
132
133void GraphicsLayerBlackBerry::addChildAtIndex(GraphicsLayer* childLayer, int index)
134{
135 GraphicsLayer::addChildAtIndex(childLayer, index);
136 updateSublayerList();
137}
138
139void GraphicsLayerBlackBerry::addChildBelow(GraphicsLayer* childLayer, GraphicsLayer* sibling)
140{
141 GraphicsLayer::addChildBelow(childLayer, sibling);
142 updateSublayerList();
143}
144
145void GraphicsLayerBlackBerry::addChildAbove(GraphicsLayer* childLayer, GraphicsLayer *sibling)
146{
147 GraphicsLayer::addChildAbove(childLayer, sibling);
148 updateSublayerList();
149}
150
151bool GraphicsLayerBlackBerry::replaceChild(GraphicsLayer* oldChild, GraphicsLayer* newChild)
152{
153 if (GraphicsLayer::replaceChild(oldChild, newChild)) {
154 updateSublayerList();
155 return true;
156 }
157 return false;
158}
159
160void GraphicsLayerBlackBerry::removeFromParent()
161{
162 GraphicsLayer::removeFromParent();
163 layerForSuperlayer()->removeFromSuperlayer();
164}
165
166void GraphicsLayerBlackBerry::setPosition(const FloatPoint& point)
167{
168 GraphicsLayer::setPosition(point);
169 updateLayerPosition();
170}
171
172void GraphicsLayerBlackBerry::setAnchorPoint(const FloatPoint3D& point)
173{
174 if (point == m_anchorPoint)
175 return;
176
177 GraphicsLayer::setAnchorPoint(point);
178 updateAnchorPoint();
179}
180
181void GraphicsLayerBlackBerry::setSize(const FloatSize& size)
182{
183 if (size == m_size)
184 return;
185
186 GraphicsLayer::setSize(size);
187 updateLayerSize();
188}
189
190void GraphicsLayerBlackBerry::setTransform(const TransformationMatrix& transform)
191{
192 if (transform == m_transform)
193 return;
194
195 GraphicsLayer::setTransform(transform);
196 updateTransform();
197}
198
199void GraphicsLayerBlackBerry::setChildrenTransform(const TransformationMatrix& transform)
200{
201 if (transform == m_childrenTransform)
202 return;
203
204 GraphicsLayer::setChildrenTransform(transform);
205 updateChildrenTransform();
206}
207
208void GraphicsLayerBlackBerry::setPreserves3D(bool preserves3D)
209{
210 if (preserves3D == m_preserves3D)
211 return;
212
213 GraphicsLayer::setPreserves3D(preserves3D);
214 updateLayerPreserves3D();
215}
216
217void GraphicsLayerBlackBerry::setMasksToBounds(bool masksToBounds)
218{
219 if (masksToBounds == m_masksToBounds)
220 return;
221
222 GraphicsLayer::setMasksToBounds(masksToBounds);
223 updateMasksToBounds();
224}
225
226void GraphicsLayerBlackBerry::setDrawsContent(bool drawsContent)
227{
228 // Note carefully this early-exit is only correct because we also properly initialize
229 // LayerWebKitThread::isDrawable() whenever m_contentsLayer is set to a new layer in setupContentsLayer().
230 if (drawsContent == m_drawsContent)
231 return;
232
233 GraphicsLayer::setDrawsContent(drawsContent);
234 updateLayerIsDrawable();
235}
236
237void GraphicsLayerBlackBerry::setContentsVisible(bool contentsVisible)
238{
239 // Note carefully this early-exit is only correct because we also properly initialize
240 // LayerWebKitThread::isDrawable() whenever m_contentsLayer is set to a new layer in setupContentsLayer().
241 if (contentsVisible == m_contentsVisible)
242 return;
243
244 GraphicsLayer::setContentsVisible(contentsVisible);
245 updateLayerIsDrawable();
246}
247
248void GraphicsLayerBlackBerry::setMaskLayer(GraphicsLayer* maskLayer)
249{
250 if (maskLayer == m_maskLayer)
251 return;
252
253 GraphicsLayer::setMaskLayer(maskLayer);
254
255 LayerWebKitThread* maskLayerWebKit = m_maskLayer ? m_maskLayer->platformLayer() : 0;
256 if (maskLayerWebKit)
257 maskLayerWebKit->setIsMask(true);
258 m_layer->setMaskLayer(maskLayerWebKit);
259}
260
261void GraphicsLayerBlackBerry::setReplicatedByLayer(GraphicsLayer* layer)
262{
263 GraphicsLayerBlackBerry* layerWebKit = static_cast<GraphicsLayerBlackBerry*>(layer);
264 GraphicsLayer::setReplicatedByLayer(layer);
265 LayerWebKitThread* replicaLayer = layerWebKit ? layerWebKit->primaryLayer() : 0;
266 primaryLayer()->setReplicaLayer(replicaLayer);
267}
268
269void GraphicsLayerBlackBerry::setFixedPosition(bool fixed)
270{
271 if (fixed == m_fixedPosition)
272 return;
273
274 GraphicsLayer::setFixedPosition(fixed);
275 updateFixedPosition();
276}
277
278void GraphicsLayerBlackBerry::setHasFixedContainer(bool b)
279{
280 if (b == m_hasFixedContainer)
281 return;
282
283 GraphicsLayer::setHasFixedContainer(b);
284 updateHasFixedContainer();
285}
286
287void GraphicsLayerBlackBerry::setHasFixedAncestorInDOMTree(bool b)
288{
289 if (b == m_hasFixedAncestorInDOMTree)
290 return;
291
292 GraphicsLayer::setHasFixedAncestorInDOMTree(b);
293 updateHasFixedAncestorInDOMTree();
294}
295
296void GraphicsLayerBlackBerry::setBackgroundColor(const Color& color)
297{
298 if (m_backgroundColorSet && m_backgroundColor == color)
299 return;
300
301 GraphicsLayer::setBackgroundColor(color);
302
303 m_contentsLayerHasBackgroundColor = true;
304 updateLayerBackgroundColor();
305}
306
307void GraphicsLayerBlackBerry::clearBackgroundColor()
308{
309 if (!m_backgroundColorSet)
310 return;
311
312 GraphicsLayer::clearBackgroundColor();
313 clearLayerBackgroundColor(*m_contentsLayer);
314}
315
316void GraphicsLayerBlackBerry::setContentsOpaque(bool opaque)
317{
318 if (m_contentsOpaque == opaque)
319 return;
320
321 GraphicsLayer::setContentsOpaque(opaque);
322 updateContentsOpaque();
323}
324
325void GraphicsLayerBlackBerry::setBackfaceVisibility(bool visible)
326{
327 if (m_backfaceVisibility == visible)
328 return;
329
330 GraphicsLayer::setBackfaceVisibility(visible);
331 updateBackfaceVisibility();
332}
333
334void GraphicsLayerBlackBerry::setOpacity(float opacity)
335{
336 float clampedOpacity = max(min(opacity, 1.0f), 0.0f);
337
338 if (m_opacity == clampedOpacity)
339 return;
340
341 GraphicsLayer::setOpacity(clampedOpacity);
342 primaryLayer()->setOpacity(opacity);
343}
344
345void GraphicsLayerBlackBerry::setContentsNeedsDisplay()
346{
347 if (m_contentsLayer)
348 m_contentsLayer->setNeedsDisplay();
349}
350
351void GraphicsLayerBlackBerry::setNeedsDisplay()
352{
353 if (drawsContent())
354 m_layer->setNeedsDisplay();
355}
356
357void GraphicsLayerBlackBerry::setNeedsDisplayInRect(const FloatRect& rect)
358{
359 if (drawsContent())
360 m_layer->setNeedsDisplayInRect(rect);
361}
362
363void GraphicsLayerBlackBerry::setContentsRect(const IntRect& rect)
364{
365 if (rect == m_contentsRect)
366 return;
367
368 GraphicsLayer::setContentsRect(rect);
369 updateContentsRect();
370}
371
372static PassRefPtr<LayerAnimation> removeAnimationByIdAndProperty(int id, AnimatedPropertyID property, Vector<RefPtr<LayerAnimation> >& list)
373{
374 for (size_t i = 0; i < list.size(); ++i) {
375 if (list[i]->id() == id && list[i]->property() == property) {
376 RefPtr<LayerAnimation> layerAnimation = list[i];
377 list.remove(i);
378 return layerAnimation;
379 }
380 }
381
382 return PassRefPtr<LayerAnimation>();
383}
384
385static PassRefPtr<LayerAnimation> removeAnimationByName(const String& animationName, Vector<RefPtr<LayerAnimation> >& list)
386{
387 for (size_t i = 0; i < list.size(); ++i) {
388 if (list[i]->name() == animationName) {
389 RefPtr<LayerAnimation> layerAnimation = list[i];
390 list.remove(i);
391 return layerAnimation.release();
392 }
393 }
394
395 return PassRefPtr<LayerAnimation>();
396}
397
398bool GraphicsLayerBlackBerry::addAnimation(const KeyframeValueList& values, const IntSize& boxSize, const Animation* animation, const String& animationName, double timeOffset)
399{
400 // This is what GraphicsLayerCA checks for
401 if (!animation || animation->isEmptyOrZeroDuration() || values.size() < 2)
402 return false;
403
404 // We only support these two kinds of properties ATM
405 if (values.property() != AnimatedPropertyWebkitTransform
406 && values.property() != AnimatedPropertyOpacity)
407 return false;
408
409 // Remove any running animation for the same property.
410 // FIXME: Maybe this is superstition, I got the idea from GraphicsLayerQt
411 // WebCore might be adding an animation with the same name, but for a different property
412 removeAnimationByIdAndProperty(LayerAnimation::idFromAnimation(animation), values.property(), m_runningAnimations);
413 removeAnimationByIdAndProperty(LayerAnimation::idFromAnimation(animation), values.property(), m_suspendedAnimations);
414
415 RefPtr<LayerAnimation> layerAnimation = LayerAnimation::create(values, boxSize, animation, animationName, timeOffset);
416
417#if DEBUG_LAYER_ANIMATION
418 fprintf(stderr, "LayerAnimation 0x%08x: Adding animation %s for property %d\n", layerAnimation.get(), animationName.latin1().data(), values.property());
419#endif
420
421 m_runningAnimations.append(layerAnimation);
422
423 updateAnimations();
424
425 return true;
426}
427
428void GraphicsLayerBlackBerry::pauseAnimation(const String& animationName, double timeOffset)
429{
430 // WebCore might have added several animations with the same name, but for different properties
431
432 RefPtr<LayerAnimation> animation;
433 while (animation = removeAnimationByName(animationName, m_runningAnimations)) {
434#if DEBUG_LAYER_ANIMATION
435 fprintf(stderr, "LayerAnimation 0x%08x: Pausing animation %s\n", animation.get(), animation->name().latin1().data());
436#endif
437
438 // LayerAnimation is readonly. Create a new animation with the same data except for timeOffset.
439 // WebCore will adjust the timeOffset for paused animations so it can be used to calculate the
440 // progress for the paused animation without knowing the exact timestamp when the animation was
441 // paused.
442 // If an animation was started with a timeOffset dt_orig and paused dt_pause seconds later, the
443 // cloned animation will have a timeOffset of dt_pause + dt_orig.
444 animation = animation->clone(timeOffset);
445 m_suspendedAnimations.append(animation);
446
447#if DEBUG_LAYER_ANIMATION
448 fprintf(stderr, "LayerAnimation 0x%08x: Paused animation %s\n", animation.get(), animation->name().latin1().data());
449#endif
450 };
451
452 updateAnimations();
453}
454
455void GraphicsLayerBlackBerry::removeAnimation(const String& animationName)
456{
457 // WebCore might have added several animations with the same name, but for different properties
458
459#if DEBUG_LAYER_ANIMATION
460 fprintf(stderr, "LayerAnimation: Removing animation %s\n", animationName.latin1().data());
461#endif
462
463 while (removeAnimationByName(animationName, m_runningAnimations)) { }
464 while (removeAnimationByName(animationName, m_suspendedAnimations)) { }
465
466 updateAnimations();
467}
468
469void GraphicsLayerBlackBerry::suspendAnimations(double time)
470{
471#if DEBUG_LAYER_ANIMATION
472 fprintf(stderr, "LayerAnimation: Suspending animations\n");
473#endif
474 m_suspendTime = time;
475}
476
477void GraphicsLayerBlackBerry::resumeAnimations()
478{
479#if DEBUG_LAYER_ANIMATION
480 fprintf(stderr, "LayerAnimation: Resuming animations\n");
481#endif
482 m_suspendTime = 0;
483}
484
485void GraphicsLayerBlackBerry::setContentsToImage(Image* image)
486{
487 bool childrenChanged = false;
488 if (image) {
489 m_contentsLayerPurpose = ContentsLayerForImage;
490 if (!m_contentsLayer)
491 childrenChanged = true;
492 } else {
493 m_contentsLayerPurpose = NoContentsLayer;
494 if (m_contentsLayer)
495 childrenChanged = true;
496 }
497
498 updateContentsImage(image);
499
500 if (childrenChanged)
501 updateSublayerList();
502}
503
504void GraphicsLayerBlackBerry::updateContentsImage(Image* image)
505{
506 if (image) {
507 if (!m_contentsLayer.get()) {
508 RefPtr<LayerWebKitThread> imageLayer = LayerWebKitThread::create(LayerData::Layer, this);
509
510 setupContentsLayer(imageLayer.get());
511 m_contentsLayer = imageLayer;
512 // m_contentsLayer will be parented by updateSublayerList.
513 }
514 m_contentsLayer->setContents(image);
515
516 updateContentsRect();
517 } else {
518 // No image. m_contentsLayer will be removed via updateSublayerList.
519 m_contentsLayer = 0;
520 }
521}
522
523void GraphicsLayerBlackBerry::setContentsToCanvas(PlatformLayer* platformLayer)
524{
525 bool childrenChanged = false;
526 if (platformLayer) {
527 platformLayer->setOwner(this);
528 if (m_contentsLayer.get() != platformLayer) {
529 setupContentsLayer(platformLayer);
530 m_contentsLayer = platformLayer;
531 m_contentsLayerPurpose = ContentsLayerForCanvas;
532 childrenChanged = true;
533 }
534 m_contentsLayer->setNeedsDisplay();
535 updateContentsRect();
536 } else {
537 if (m_contentsLayer) {
538 childrenChanged = true;
539
540 // The old contents layer will be removed via updateSublayerList.
541 m_contentsLayer = 0;
542 }
543 }
544
545 if (childrenChanged)
546 updateSublayerList();
547}
548
549void GraphicsLayerBlackBerry::setContentsToMedia(PlatformLayer* layer)
550{
551 bool childrenChanged = false;
552 if (layer) {
553 if (!m_contentsLayer.get() || m_contentsLayerPurpose != ContentsLayerForVideo) {
554 setupContentsLayer(layer);
555 m_contentsLayer = layer;
556 m_contentsLayerPurpose = ContentsLayerForVideo;
557 childrenChanged = true;
558 }
559 layer->setOwner(this);
560 layer->setNeedsDisplay();
561 updateContentsRect();
562 } else {
563 if (m_contentsLayer) {
564 childrenChanged = true;
565
566 // The old contents layer will be removed via updateSublayerList.
567 m_contentsLayer = 0;
568 }
569 }
570
571 if (childrenChanged)
572 updateSublayerList();
573}
574
575PlatformLayer* GraphicsLayerBlackBerry::hostLayerForSublayers() const
576{
577 return m_transformLayer ? m_transformLayer.get() : m_layer.get();
578}
579
580PlatformLayer* GraphicsLayerBlackBerry::layerForSuperlayer() const
581{
582 return m_transformLayer ? m_transformLayer.get() : m_layer.get();
583}
584
585PlatformLayer* GraphicsLayerBlackBerry::platformLayer() const
586{
587 return primaryLayer();
588}
589
590void GraphicsLayerBlackBerry::setDebugBackgroundColor(const Color& color)
591{
592 if (color.isValid())
593 setLayerBackgroundColor(*m_layer, color);
594 else
595 clearLayerBackgroundColor(*m_layer);
596}
597
598void GraphicsLayerBlackBerry::setDebugBorder(const Color& color, float borderWidth)
599{
600 if (color.isValid()) {
601 setLayerBorderColor(*m_layer, color);
602 m_layer->setBorderWidth(borderWidth);
603 } else {
604 clearBorderColor(*m_layer);
605 m_layer->setBorderWidth(0);
606 }
607}
608
609void GraphicsLayerBlackBerry::updateSublayerList()
610{
611 Vector<RefPtr<LayerWebKitThread> > newSublayers;
612
613 if (m_transformLayer) {
614 // Add the primary layer first. Even if we have negative z-order children, the primary layer always comes behind.
615 newSublayers.append(m_layer.get());
616 } else if (m_contentsLayer) {
617 // FIXME: add the contents layer in the correct order with negative z-order children.
618 // This does not cause visible rendering issues because currently contents layers are only used
619 // for replaced elements that don't have children.
620 newSublayers.append(m_contentsLayer.get());
621 }
622
623 const Vector<GraphicsLayer*>& childLayers = children();
624 size_t numChildren = childLayers.size();
625 for (size_t i = 0; i < numChildren; ++i) {
626 GraphicsLayerBlackBerry* curChild = static_cast<GraphicsLayerBlackBerry*>(childLayers[i]);
627
628 LayerWebKitThread* childLayer = curChild->layerForSuperlayer();
629 newSublayers.append(childLayer);
630 }
631
632 for (size_t i = 0; i < newSublayers.size(); ++i)
633 newSublayers[i]->removeFromSuperlayer();
634
635 if (m_transformLayer) {
636 m_transformLayer->setSublayers(newSublayers);
637
638 if (m_contentsLayer) {
639 // If we have a transform layer, then the contents layer is parented in the
640 // primary layer (which is itself a child of the transform layer).
641 m_layer->removeAllSublayers();
642 m_layer->addSublayer(m_contentsLayer);
643 }
644 } else
645 m_layer->setSublayers(newSublayers);
646}
647
648void GraphicsLayerBlackBerry::updateLayerPosition()
649{
650 // Position is offset on the layer by the layer anchor point.
651 FloatPoint layerPosition(m_position.x() + m_anchorPoint.x() * m_size.width(),
652 m_position.y() + m_anchorPoint.y() * m_size.height());
653
654 primaryLayer()->setPosition(layerPosition);
655}
656
657void GraphicsLayerBlackBerry::updateLayerSize()
658{
659 IntSize layerSize(m_size.width(), m_size.height());
660 if (m_transformLayer) {
661 m_transformLayer->setBounds(layerSize);
662 // The anchor of the contents layer is always at 0.5, 0.5, so the position is center-relative.
663 FloatPoint centerPoint(m_size.width() / 2, m_size.height() / 2);
664 m_layer->setPosition(centerPoint);
665 }
666
667 m_layer->setBounds(layerSize);
668
669 // Note that we don't resize m_contentsLayer. It's up the caller to do that.
670
671 // If we've changed the bounds, we need to recalculate the position
672 // of the layer, taking anchor point into account.
673 updateLayerPosition();
674}
675
676void GraphicsLayerBlackBerry::updateAnchorPoint()
677{
678 primaryLayer()->setAnchorPoint(FloatPoint(m_anchorPoint.x(), m_anchorPoint.y()));
679 primaryLayer()->setAnchorPointZ(m_anchorPoint.z());
680 updateLayerPosition();
681}
682
683void GraphicsLayerBlackBerry::updateTransform()
684{
685 primaryLayer()->setTransform(m_transform);
686}
687
688void GraphicsLayerBlackBerry::updateChildrenTransform()
689{
690 primaryLayer()->setSublayerTransform(m_childrenTransform);
691}
692
693void GraphicsLayerBlackBerry::updateMasksToBounds()
694{
695 m_layer->setMasksToBounds(m_masksToBounds);
696 updateDebugIndicators();
697}
698
699void GraphicsLayerBlackBerry::updateContentsOpaque()
700{
701 m_layer->setOpaque(m_contentsOpaque);
702}
703
704void GraphicsLayerBlackBerry::updateBackfaceVisibility()
705{
706 m_layer->setDoubleSided(m_backfaceVisibility);
707}
708
709void GraphicsLayerBlackBerry::updateLayerPreserves3D()
710{
711 if (m_preserves3D && !m_transformLayer) {
712 // Create the transform layer.
713 m_transformLayer = LayerWebKitThread::create(LayerData::TransformLayer, this);
714
715 // Copy the position from this layer.
716 updateLayerPosition();
717 updateLayerSize();
718 updateAnchorPoint();
719 updateTransform();
720 updateChildrenTransform();
721 updateAnimations();
722
723 m_layer->setPosition(FloatPoint(m_size.width() / 2.0f, m_size.height() / 2.0f));
724
725 m_layer->setAnchorPoint(FloatPoint(0.5f, 0.5f));
726 TransformationMatrix identity;
727 m_layer->setTransform(identity);
728
729 // Set the old layer to opacity of 1. Further down we will set the opacity on the transform layer.
730 m_layer->setOpacity(1);
731
732 // Move this layer to be a child of the transform layer.
733 if (m_layer->superlayer())
734 m_layer->superlayer()->replaceSublayer(m_layer.get(), m_transformLayer.get());
735 m_transformLayer->addSublayer(m_layer.get());
736
737 m_transformLayer->setPreserves3D(true);
738 m_layer->setPreserves3D(true);
739
740 updateSublayerList();
741 } else if (!m_preserves3D && m_transformLayer) {
742 // Relace the transformLayer in the parent with this layer.
743 m_layer->removeFromSuperlayer();
744 if (m_transformLayer->superlayer())
745 m_transformLayer->superlayer()->replaceSublayer(m_transformLayer.get(), m_layer.get());
746
747 // Release the transform layer.
748 m_transformLayer = 0;
749
750 updateLayerPosition();
751 updateLayerSize();
752 updateAnchorPoint();
753 updateTransform();
754 updateChildrenTransform();
755 updateAnimations();
756
757 m_layer->setPreserves3D(false);
758
759 updateSublayerList();
760 }
761
762 updateOpacityOnLayer();
763}
764
765void GraphicsLayerBlackBerry::updateLayerIsDrawable()
766{
767 // For the rest of the accelerated compositor code, there is no reason to make a
768 // distinction between drawsContent and contentsVisible. So, for m_layer, these two
769 // flags are combined here. m_contentsLayer shouldn't receive the drawsContent flag
770 // so it is only given contentsVisible.
771 m_layer->setDrawable(m_drawsContent && m_contentsVisible);
772
773 if (m_contentsLayer)
774 m_contentsLayer->setDrawable(m_contentsVisible);
775
776 if (m_drawsContent)
777 m_layer->setNeedsDisplay();
778
779 updateDebugIndicators();
780}
781
782void GraphicsLayerBlackBerry::updateFixedPosition()
783{
784 m_layer->setFixedPosition(m_fixedPosition);
785}
786
787void GraphicsLayerBlackBerry::updateHasFixedContainer()
788{
789 m_layer->setHasFixedContainer(m_hasFixedContainer);
790}
791
792void GraphicsLayerBlackBerry::updateHasFixedAncestorInDOMTree()
793{
794 m_layer->setHasFixedAncestorInDOMTree(m_hasFixedAncestorInDOMTree);
795}
796
797void GraphicsLayerBlackBerry::updateLayerBackgroundColor()
798{
799 if (!m_contentsLayer)
800 return;
801
802 // We never create the contents layer just for background color yet.
803 if (m_backgroundColorSet)
804 setLayerBackgroundColor(*m_contentsLayer, m_backgroundColor);
805 else
806 clearLayerBackgroundColor(*m_contentsLayer);
807}
808
809void GraphicsLayerBlackBerry::updateAnimations()
810{
811 // When there is a transform layer, the transform must be set on that layer
812 // instead of the content layer. Opacity can be set on the transform layer or the
813 // layer with equal outcome, but currently it is also set on the transform
814 // layer. Since we only accelerate animations of these two properties, it
815 // is safe to move all accelerated animations to the transform layer, and
816 // remove them from the layer proper.
817 // So the following code, while it looks strange, is correct:
818 // we transfer all animations to the transform layer if it exists.
819 // FIXME: If other properties become animated, it may not be equivalent to
820 // move them to the transform layer. Then this code needs to be revisited
821 // to only move the transform animations to the transform layer.
822 primaryLayer()->setRunningAnimations(m_runningAnimations);
823 primaryLayer()->setSuspendedAnimations(m_suspendedAnimations);
824
825 // We need to move the animations to the transform layer if there is one.
826 if (m_transformLayer) {
827 m_layer->setRunningAnimations(Vector<RefPtr<LayerAnimation> >());
828 m_layer->setSuspendedAnimations(Vector<RefPtr<LayerAnimation> >());
829 }
830}
831
832void GraphicsLayerBlackBerry::updateContentsVideo()
833{
834 // FIXME: Implement
835}
836
837void GraphicsLayerBlackBerry::updateContentsRect()
838{
839 if (!m_contentsLayer)
840 return;
841
842 m_contentsLayer->setPosition(FloatPoint(m_contentsRect.x(), m_contentsRect.y()));
843 m_contentsLayer->setBounds(IntSize(m_contentsRect.width(), m_contentsRect.height()));
844}
845
846void GraphicsLayerBlackBerry::setupContentsLayer(LayerWebKitThread* contentsLayer)
847{
848 if (contentsLayer == m_contentsLayer)
849 return;
850
851 if (m_contentsLayer) {
852 m_contentsLayer->removeFromSuperlayer();
853 m_contentsLayer = 0;
854 }
855
856 if (contentsLayer) {
857 m_contentsLayer = contentsLayer;
858
859 m_contentsLayer->setAnchorPoint(FloatPoint(0, 0));
860
861 // It is necessary to update setDrawable as soon as we receive the new contentsLayer, for
862 // the correctness of early exit conditions in setDrawsContent() and setContentsVisible().
863 m_contentsLayer->setDrawable(m_contentsVisible);
864
865 // Insert the content layer first. Video elements require this, because they have
866 // shadow content that must display in front of the video.
867 m_layer->insertSublayer(m_contentsLayer.get(), 0);
868
869 updateContentsRect();
870
871 if (showDebugBorders()) {
872 setLayerBorderColor(*m_contentsLayer, Color(0, 0, 128, 180));
873 m_contentsLayer->setBorderWidth(1);
874 }
875 }
876 updateDebugIndicators();
877}
878
879// This function simply mimics the operation of GraphicsLayerCA
880void GraphicsLayerBlackBerry::updateOpacityOnLayer()
881{
882 primaryLayer()->setOpacity(m_opacity);
883}
884
885bool GraphicsLayerBlackBerry::contentsVisible(const IntRect& contentRect) const
886{
887 if (!m_client)
888 return false;
889
890 return m_client->contentsVisible(this, contentRect);
891}
892
893} // namespace WebCore
894
895#endif // USE(ACCELERATED_COMPOSITING)