2 * Copyright (C) 2011 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #if USE(ACCELERATED_COMPOSITING)
30 #include "PlatformCALayer.h"
33 #include "GraphicsContext.h"
34 #include "PlatformCALayerWinInternal.h"
35 #include "WKCACFLayerRenderer.h"
36 #include <QuartzCore/CoreAnimationCF.h>
37 #include <WebKitSystemInterface/WebKitSystemInterface.h>
38 #include <wtf/CurrentTime.h>
39 #include <wtf/text/CString.h>
41 using namespace WebCore;
43 bool PlatformCALayer::isValueFunctionSupported()
48 void PlatformCALayer::setOwner(PlatformCALayerClient* owner)
53 static CFStringRef toCACFLayerType(PlatformCALayer::LayerType type)
55 return (type == PlatformCALayer::LayerTypeTransformLayer) ? kCACFTransformLayer : kCACFLayer;
58 static CFStringRef toCACFFilterType(PlatformCALayer::FilterType type)
61 case PlatformCALayer::Linear: return kCACFFilterLinear;
62 case PlatformCALayer::Nearest: return kCACFFilterNearest;
63 case PlatformCALayer::Trilinear: return kCACFFilterTrilinear;
68 static WKCACFLayerRenderer* rendererForLayer(const PlatformCALayer* layer)
70 // We need the WKCACFLayerRenderer associated with this layer, which is stored in the UserData of the CACFContext
71 void* userData = wkCACFLayerGetContextUserData(layer->platformLayer());
75 return static_cast<WKCACFLayerRenderer*>(userData);
78 static PlatformCALayerWinInternal* intern(const PlatformCALayer* layer)
80 return static_cast<PlatformCALayerWinInternal*>(CACFLayerGetUserData(layer->platformLayer()));
83 static PlatformCALayerWinInternal* intern(void* layer)
85 return static_cast<PlatformCALayerWinInternal*>(CACFLayerGetUserData(static_cast<CACFLayerRef>(layer)));
88 PassRefPtr<PlatformCALayer> PlatformCALayer::create(LayerType layerType, PlatformCALayerClient* owner)
90 return adoptRef(new PlatformCALayer(layerType, 0, owner));
93 PassRefPtr<PlatformCALayer> PlatformCALayer::create(void* platformLayer, PlatformCALayerClient* owner)
95 return adoptRef(new PlatformCALayer(LayerTypeCustom, static_cast<PlatformLayer*>(platformLayer), owner));
98 static void displayCallback(CACFLayerRef caLayer, CGContextRef context)
100 ASSERT_ARG(caLayer, CACFLayerGetUserData(caLayer));
101 intern(caLayer)->displayCallback(caLayer, context);
104 static void layoutSublayersProc(CACFLayerRef caLayer)
106 PlatformCALayer* layer = PlatformCALayer::platformCALayer(caLayer);
107 if (layer && layer->owner())
108 layer->owner()->platformCALayerLayoutSublayersOfLayer(layer);
111 PlatformCALayer::PlatformCALayer(LayerType layerType, PlatformLayer* layer, PlatformCALayerClient* owner)
115 m_layerType = LayerTypeCustom;
118 m_layerType = layerType;
119 m_layer.adoptCF(CACFLayerCreate(toCACFLayerType(layerType)));
121 // Create the PlatformCALayerWinInternal object and point to it in the userdata.
122 PlatformCALayerWinInternal* intern = new PlatformCALayerWinInternal(this);
123 CACFLayerSetUserData(m_layer.get(), intern);
125 // Set the display callback
126 CACFLayerSetDisplayCallback(m_layer.get(), displayCallback);
127 CACFLayerSetLayoutCallback(m_layer.get(), layoutSublayersProc);
131 PlatformCALayer::~PlatformCALayer()
134 removeAllSublayers();
136 // Get rid of the user data
137 PlatformCALayerWinInternal* layerIntern = intern(this);
138 CACFLayerSetUserData(m_layer.get(), 0);
143 PlatformCALayer* PlatformCALayer::platformCALayer(void* platformLayer)
148 PlatformCALayerWinInternal* layerIntern = intern(platformLayer);
149 return layerIntern ? layerIntern->owner() : 0;
152 PlatformLayer* PlatformCALayer::platformLayer() const
154 return m_layer.get();
157 PlatformCALayer* PlatformCALayer::rootLayer() const
159 WKCACFLayerRenderer* renderer = rendererForLayer(this);
160 return renderer ? renderer->rootLayer() : 0;
163 void PlatformCALayer::setNeedsDisplay(const FloatRect* dirtyRect)
165 intern(this)->setNeedsDisplay(dirtyRect);
168 void PlatformCALayer::setNeedsCommit()
170 WKCACFLayerRenderer* renderer = rendererForLayer(this);
172 renderer->layerTreeDidChange();
175 void PlatformCALayer::setContentsChanged()
177 // FIXME: There is no equivalent of setContentsChanged in CACF. For now I will
178 // set contents to 0 and then back to its original value to see if that
179 // kicks CACF into redisplaying.
180 RetainPtr<CFTypeRef> contents = CACFLayerGetContents(m_layer.get());
181 CACFLayerSetContents(m_layer.get(), 0);
182 CACFLayerSetContents(m_layer.get(), contents.get());
186 void PlatformCALayer::setNeedsLayout()
188 if (!m_owner || !m_owner->platformCALayerRespondsToLayoutChanges())
191 CACFLayerSetNeedsLayout(m_layer.get());
195 PlatformCALayer* PlatformCALayer::superlayer() const
197 return platformCALayer(CACFLayerGetSuperlayer(m_layer.get()));
200 void PlatformCALayer::removeFromSuperlayer()
202 CACFLayerRemoveFromSuperlayer(m_layer.get());
206 void PlatformCALayer::setSublayers(const PlatformCALayerList& list)
208 intern(this)->setSublayers(list);
211 void PlatformCALayer::removeAllSublayers()
213 intern(this)->removeAllSublayers();
216 void PlatformCALayer::appendSublayer(PlatformCALayer* layer)
218 // This must be in terms of insertSublayer instead of a direct call so PlatformCALayerInternal can override.
219 insertSublayer(layer, sublayerCount());
222 void PlatformCALayer::insertSublayer(PlatformCALayer* layer, size_t index)
224 intern(this)->insertSublayer(layer, index);
227 void PlatformCALayer::replaceSublayer(PlatformCALayer* reference, PlatformCALayer* newLayer)
229 // This must not use direct calls to allow PlatformCALayerInternal to override.
230 ASSERT_ARG(reference, reference);
231 ASSERT_ARG(reference, reference->superlayer() == this);
233 if (reference == newLayer)
236 int referenceIndex = intern(this)->indexOfSublayer(reference);
237 ASSERT(referenceIndex != -1);
238 if (referenceIndex == -1)
241 reference->removeFromSuperlayer();
244 newLayer->removeFromSuperlayer();
245 insertSublayer(newLayer, referenceIndex);
249 size_t PlatformCALayer::sublayerCount() const
251 return intern(this)->sublayerCount();
254 void PlatformCALayer::adoptSublayers(PlatformCALayer* source)
256 // Make a list of the sublayers from source
257 PlatformCALayerList sublayers;
258 size_t n = source->sublayerCount();
259 CFArrayRef sourceSublayers = CACFLayerGetSublayers(source->platformLayer());
261 for (size_t i = 0; i < n; ++i) {
262 CACFLayerRef layer = static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(sourceSublayers, i)));
263 sublayers.append(platformCALayer(layer));
266 // Use setSublayers() because it properly nulls out the superlayer pointers.
267 setSublayers(sublayers);
270 void PlatformCALayer::addAnimationForKey(const String& key, PlatformCAAnimation* animation)
272 // Add it to the animation list
273 m_animations.add(key, animation);
275 RetainPtr<CFStringRef> s(AdoptCF, key.createCFString());
276 CACFLayerAddAnimation(m_layer.get(), s.get(), animation->platformAnimation());
279 // Tell the renderer about it so we can fire the start animation event
280 WKCACFLayerRenderer* renderer = rendererForLayer(this);
282 renderer->addPendingAnimatedLayer(this);
285 void PlatformCALayer::removeAnimationForKey(const String& key)
287 // Remove it from the animation list
288 m_animations.remove(key);
290 RetainPtr<CFStringRef> s(AdoptCF, key.createCFString());
291 CACFLayerRemoveAnimation(m_layer.get(), s.get());
293 // We don't "remove" a layer from WKCACFLayerRenderer when it loses an animation.
294 // There may be other active animations on the layer and if an animation
295 // callback is fired on a layer without any animations no harm is done.
300 PassRefPtr<PlatformCAAnimation> PlatformCALayer::animationForKey(const String& key)
302 HashMap<String, RefPtr<PlatformCAAnimation> >::iterator it = m_animations.find(key);
303 if (it == m_animations.end())
309 PlatformCALayer* PlatformCALayer::mask() const
311 return platformCALayer(CACFLayerGetMask(m_layer.get()));
314 void PlatformCALayer::setMask(PlatformCALayer* layer)
316 CACFLayerSetMask(m_layer.get(), layer ? layer->platformLayer() : 0);
320 bool PlatformCALayer::isOpaque() const
322 return CACFLayerIsOpaque(m_layer.get());
325 void PlatformCALayer::setOpaque(bool value)
327 CACFLayerSetOpaque(m_layer.get(), value);
331 FloatRect PlatformCALayer::bounds() const
333 return CACFLayerGetBounds(m_layer.get());
336 void PlatformCALayer::setBounds(const FloatRect& value)
338 intern(this)->setBounds(value);
342 FloatPoint3D PlatformCALayer::position() const
344 CGPoint point = CACFLayerGetPosition(m_layer.get());
345 return FloatPoint3D(point.x, point.y, CACFLayerGetZPosition(m_layer.get()));
348 void PlatformCALayer::setPosition(const FloatPoint3D& value)
350 CACFLayerSetPosition(m_layer.get(), CGPointMake(value.x(), value.y()));
351 CACFLayerSetZPosition(m_layer.get(), value.z());
355 FloatPoint3D PlatformCALayer::anchorPoint() const
357 CGPoint point = CACFLayerGetAnchorPoint(m_layer.get());
358 float z = CACFLayerGetAnchorPointZ(m_layer.get());
359 return FloatPoint3D(point.x, point.y, z);
362 void PlatformCALayer::setAnchorPoint(const FloatPoint3D& value)
364 CACFLayerSetAnchorPoint(m_layer.get(), CGPointMake(value.x(), value.y()));
365 CACFLayerSetAnchorPointZ(m_layer.get(), value.z());
369 TransformationMatrix PlatformCALayer::transform() const
371 return CACFLayerGetTransform(m_layer.get());
374 void PlatformCALayer::setTransform(const TransformationMatrix& value)
376 CACFLayerSetTransform(m_layer.get(), value);
380 TransformationMatrix PlatformCALayer::sublayerTransform() const
382 return CACFLayerGetSublayerTransform(m_layer.get());
385 void PlatformCALayer::setSublayerTransform(const TransformationMatrix& value)
387 CACFLayerSetSublayerTransform(m_layer.get(), value);
391 TransformationMatrix PlatformCALayer::contentsTransform() const
393 // ContentsTransform is not used
394 return TransformationMatrix();
397 void PlatformCALayer::setContentsTransform(const TransformationMatrix&)
399 // ContentsTransform is not used
402 bool PlatformCALayer::isHidden() const
404 return CACFLayerIsHidden(m_layer.get());
407 void PlatformCALayer::setHidden(bool value)
409 CACFLayerSetHidden(m_layer.get(), value);
413 bool PlatformCALayer::isGeometryFlipped() const
415 return CACFLayerIsGeometryFlipped(m_layer.get());
418 void PlatformCALayer::setGeometryFlipped(bool value)
420 CACFLayerSetGeometryFlipped(m_layer.get(), value);
424 bool PlatformCALayer::isDoubleSided() const
426 return CACFLayerIsDoubleSided(m_layer.get());
429 void PlatformCALayer::setDoubleSided(bool value)
431 CACFLayerSetDoubleSided(m_layer.get(), value);
435 bool PlatformCALayer::masksToBounds() const
437 return CACFLayerGetMasksToBounds(m_layer.get());
440 void PlatformCALayer::setMasksToBounds(bool value)
442 CACFLayerSetMasksToBounds(m_layer.get(), value);
446 bool PlatformCALayer::acceleratesDrawing() const
451 void PlatformCALayer::setAcceleratesDrawing(bool)
455 CFTypeRef PlatformCALayer::contents() const
457 return CACFLayerGetContents(m_layer.get());
460 void PlatformCALayer::setContents(CFTypeRef value)
462 CACFLayerSetContents(m_layer.get(), value);
466 FloatRect PlatformCALayer::contentsRect() const
468 return CACFLayerGetContentsRect(m_layer.get());
471 void PlatformCALayer::setContentsRect(const FloatRect& value)
473 CACFLayerSetContentsRect(m_layer.get(), value);
477 void PlatformCALayer::setMinificationFilter(FilterType value)
479 CACFLayerSetMinificationFilter(m_layer.get(), toCACFFilterType(value));
482 void PlatformCALayer::setMagnificationFilter(FilterType value)
484 CACFLayerSetMagnificationFilter(m_layer.get(), toCACFFilterType(value));
488 Color PlatformCALayer::backgroundColor() const
490 return CACFLayerGetBackgroundColor(m_layer.get());
493 void PlatformCALayer::setBackgroundColor(const Color& value)
495 CGFloat components[4];
496 value.getRGBA(components[0], components[1], components[2], components[3]);
498 RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
499 RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
501 CACFLayerSetBackgroundColor(m_layer.get(), color.get());
505 float PlatformCALayer::borderWidth() const
507 return CACFLayerGetBorderWidth(m_layer.get());
510 void PlatformCALayer::setBorderWidth(float value)
512 CACFLayerSetBorderWidth(m_layer.get(), value);
516 Color PlatformCALayer::borderColor() const
518 return CACFLayerGetBorderColor(m_layer.get());
521 void PlatformCALayer::setBorderColor(const Color& value)
523 CGFloat components[4];
524 value.getRGBA(components[0], components[1], components[2], components[3]);
526 RetainPtr<CGColorSpaceRef> colorSpace(AdoptCF, CGColorSpaceCreateDeviceRGB());
527 RetainPtr<CGColorRef> color(AdoptCF, CGColorCreate(colorSpace.get(), components));
529 CACFLayerSetBorderColor(m_layer.get(), color.get());
533 float PlatformCALayer::opacity() const
535 return CACFLayerGetOpacity(m_layer.get());
538 void PlatformCALayer::setOpacity(float value)
540 CACFLayerSetOpacity(m_layer.get(), value);
544 String PlatformCALayer::name() const
546 return CACFLayerGetName(m_layer.get());
549 void PlatformCALayer::setName(const String& value)
551 RetainPtr<CFStringRef> s(AdoptCF, value.createCFString());
552 CACFLayerSetName(m_layer.get(), s.get());
556 FloatRect PlatformCALayer::frame() const
558 return CACFLayerGetFrame(m_layer.get());
561 void PlatformCALayer::setFrame(const FloatRect& value)
563 intern(this)->setFrame(value);
567 float PlatformCALayer::speed() const
569 return CACFLayerGetSpeed(m_layer.get());
572 void PlatformCALayer::setSpeed(float value)
574 CACFLayerSetSpeed(m_layer.get(), value);
578 CFTimeInterval PlatformCALayer::timeOffset() const
580 return CACFLayerGetTimeOffset(m_layer.get());
583 void PlatformCALayer::setTimeOffset(CFTimeInterval value)
585 CACFLayerSetTimeOffset(m_layer.get(), value);
590 static void printIndent(int indent)
592 for ( ; indent > 0; --indent)
593 fprintf(stderr, " ");
596 static void printTransform(const CATransform3D& transform)
598 fprintf(stderr, "[%g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g]",
599 transform.m11, transform.m12, transform.m13, transform.m14,
600 transform.m21, transform.m22, transform.m23, transform.m24,
601 transform.m31, transform.m32, transform.m33, transform.m34,
602 transform.m41, transform.m42, transform.m43, transform.m44);
605 static void printLayer(const PlatformCALayer* layer, int indent)
607 FloatPoint3D layerPosition = layer->position();
608 FloatPoint3D layerAnchorPoint = layer->anchorPoint();
609 FloatRect layerBounds = layer->bounds();
612 char* layerTypeName = 0;
613 switch (layer->layerType()) {
614 case PlatformCALayer::LayerTypeLayer: layerTypeName = "layer"; break;
615 case PlatformCALayer::LayerTypeWebLayer: layerTypeName = "web-layer"; break;
616 case PlatformCALayer::LayerTypeTransformLayer: layerTypeName = "transform-layer"; break;
617 case PlatformCALayer::LayerTypeWebTiledLayer: layerTypeName = "web-tiled-layer"; break;
618 case PlatformCALayer::LayerTypeRootLayer: layerTypeName = "root-layer"; break;
619 case PlatformCALayer::LayerTypeCustom: layerTypeName = "custom-layer"; break;
622 fprintf(stderr, "(%s [%g %g %g] [%g %g %g %g] [%g %g %g] superlayer=%p\n",
624 layerPosition.x(), layerPosition.y(), layerPosition.z(),
625 layerBounds.x(), layerBounds.y(), layerBounds.width(), layerBounds.height(),
626 layerAnchorPoint.x(), layerAnchorPoint.y(), layerAnchorPoint.z(), layer->superlayer());
628 // Print name if needed
629 String layerName = layer->name();
630 if (!layerName.isEmpty()) {
631 printIndent(indent + 1);
632 fprintf(stderr, "(name %s)\n", layerName.utf8().data());
635 // Print masksToBounds if needed
636 bool layerMasksToBounds = layer->masksToBounds();
637 if (layerMasksToBounds) {
638 printIndent(indent + 1);
639 fprintf(stderr, "(masksToBounds true)\n");
642 // Print opacity if needed
643 float layerOpacity = layer->opacity();
644 if (layerOpacity != 1) {
645 printIndent(indent + 1);
646 fprintf(stderr, "(opacity %hf)\n", layerOpacity);
649 // Print sublayerTransform if needed
650 TransformationMatrix layerTransform = layer->sublayerTransform();
651 if (!layerTransform.isIdentity()) {
652 printIndent(indent + 1);
653 fprintf(stderr, "(sublayerTransform ");
654 printTransform(layerTransform);
655 fprintf(stderr, ")\n");
658 // Print transform if needed
659 layerTransform = layer->transform();
660 if (!layerTransform.isIdentity()) {
661 printIndent(indent + 1);
662 fprintf(stderr, "(transform ");
663 printTransform(layerTransform);
664 fprintf(stderr, ")\n");
667 // Print contents if needed
668 CFTypeRef layerContents = layer->contents();
670 if (CFGetTypeID(layerContents) == CGImageGetTypeID()) {
671 CGImageRef imageContents = static_cast<CGImageRef>(const_cast<void*>(layerContents));
672 printIndent(indent + 1);
673 fprintf(stderr, "(contents (image [%d %d]))\n",
674 CGImageGetWidth(imageContents), CGImageGetHeight(imageContents));
678 // Print sublayers if needed
679 int n = layer->sublayerCount();
681 printIndent(indent + 1);
682 fprintf(stderr, "(sublayers\n");
684 CFArrayRef sublayers = CACFLayerGetSublayers(layer->platformLayer());
685 for (int i = 0; i < n; ++i) {
686 PlatformCALayer* sublayer = PlatformCALayer::platformCALayer(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, i)));
687 printLayer(sublayer, indent + 2);
690 printIndent(indent + 1);
691 fprintf(stderr, ")\n");
695 fprintf(stderr, ")\n");
698 void PlatformCALayer::printTree() const
700 // Print heading info
701 CGRect rootBounds = bounds();
702 fprintf(stderr, "\n\n** Render tree at time %g (bounds %g, %g %gx%g) **\n\n",
703 currentTime(), rootBounds.origin.x, rootBounds.origin.y, rootBounds.size.width, rootBounds.size.height);
705 // Print layer tree from the root
708 #endif // #ifndef NDEBUG
710 #endif // USE(ACCELERATED_COMPOSITING)