2 * Copyright (C) 2009 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 "WKCACFLayer.h"
32 #include "WKCACFLayerRenderer.h"
33 #include <WebKitSystemInterface/WebKitSystemInterface.h>
35 #include <wtf/CurrentTime.h>
36 #include <wtf/text/CString.h>
42 static void displayCallback(CACFLayerRef layer, CGContextRef context)
44 ASSERT_ARG(layer, WKCACFLayer::layer(layer));
45 WKCACFLayer::layer(layer)->drawInContext(context);
48 static CFStringRef toCACFLayerType(WKCACFLayer::LayerType type)
51 case WKCACFLayer::Layer: return kCACFLayer;
52 case WKCACFLayer::TransformLayer: return kCACFTransformLayer;
57 static CFStringRef toCACFContentsGravityType(WKCACFLayer::ContentsGravityType type)
60 case WKCACFLayer::Center: return kCACFGravityCenter;
61 case WKCACFLayer::Top: return kCACFGravityTop;
62 case WKCACFLayer::Bottom: return kCACFGravityBottom;
63 case WKCACFLayer::Left: return kCACFGravityLeft;
64 case WKCACFLayer::Right: return kCACFGravityRight;
65 case WKCACFLayer::TopLeft: return kCACFGravityTopLeft;
66 case WKCACFLayer::TopRight: return kCACFGravityTopRight;
67 case WKCACFLayer::BottomLeft: return kCACFGravityBottomLeft;
68 case WKCACFLayer::BottomRight: return kCACFGravityBottomRight;
69 case WKCACFLayer::Resize: return kCACFGravityResize;
70 case WKCACFLayer::ResizeAspect: return kCACFGravityResizeAspect;
71 case WKCACFLayer::ResizeAspectFill: return kCACFGravityResizeAspectFill;
76 static WKCACFLayer::ContentsGravityType fromCACFContentsGravityType(CFStringRef string)
78 if (CFEqual(string, kCACFGravityTop))
79 return WKCACFLayer::Top;
81 if (CFEqual(string, kCACFGravityBottom))
82 return WKCACFLayer::Bottom;
84 if (CFEqual(string, kCACFGravityLeft))
85 return WKCACFLayer::Left;
87 if (CFEqual(string, kCACFGravityRight))
88 return WKCACFLayer::Right;
90 if (CFEqual(string, kCACFGravityTopLeft))
91 return WKCACFLayer::TopLeft;
93 if (CFEqual(string, kCACFGravityTopRight))
94 return WKCACFLayer::TopRight;
96 if (CFEqual(string, kCACFGravityBottomLeft))
97 return WKCACFLayer::BottomLeft;
99 if (CFEqual(string, kCACFGravityBottomRight))
100 return WKCACFLayer::BottomRight;
102 if (CFEqual(string, kCACFGravityResize))
103 return WKCACFLayer::Resize;
105 if (CFEqual(string, kCACFGravityResizeAspect))
106 return WKCACFLayer::ResizeAspect;
108 if (CFEqual(string, kCACFGravityResizeAspectFill))
109 return WKCACFLayer::ResizeAspectFill;
111 return WKCACFLayer::Center;
114 static CFStringRef toCACFFilterType(WKCACFLayer::FilterType type)
117 case WKCACFLayer::Linear: return kCACFFilterLinear;
118 case WKCACFLayer::Nearest: return kCACFFilterNearest;
119 case WKCACFLayer::Trilinear: return kCACFFilterTrilinear;
124 static WKCACFLayer::FilterType fromCACFFilterType(CFStringRef string)
126 if (CFEqual(string, kCACFFilterNearest))
127 return WKCACFLayer::Nearest;
129 if (CFEqual(string, kCACFFilterTrilinear))
130 return WKCACFLayer::Trilinear;
132 return WKCACFLayer::Linear;
135 PassRefPtr<WKCACFLayer> WKCACFLayer::create(LayerType type)
137 if (!WKCACFLayerRenderer::acceleratedCompositingAvailable())
139 return adoptRef(new WKCACFLayer(type));
142 // FIXME: It might be good to have a way of ensuring that all WKCACFLayers eventually
143 // get destroyed in debug builds. A static counter could accomplish this pretty easily.
145 WKCACFLayer::WKCACFLayer(LayerType type)
146 : m_layer(AdoptCF, CACFLayerCreate(toCACFLayerType(type)))
148 , m_needsDisplayOnBoundsChange(false)
150 CACFLayerSetUserData(layer(), this);
151 CACFLayerSetDisplayCallback(layer(), displayCallback);
154 WKCACFLayer::~WKCACFLayer()
156 // Our superlayer should be holding a reference to us, so there should be no way for us to be destroyed while we still have a superlayer.
157 ASSERT(!superlayer());
159 CACFLayerSetUserData(layer(), 0);
160 CACFLayerSetDisplayCallback(layer(), 0);
163 void WKCACFLayer::becomeRootLayerForContext(WKCACFContext* context)
165 wkCACFContextSetLayer(context, layer());
169 void WKCACFLayer::setNeedsCommit()
171 WKCACFLayer* root = rootLayer();
173 // Call setNeedsRender on the root layer, which will cause a render to
174 // happen in WKCACFLayerRenderer
175 root->setNeedsRender();
178 bool WKCACFLayer::isTransformLayer() const
180 return CACFLayerGetClass(layer()) == kCACFTransformLayer;
183 void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer)
185 insertSublayer(sublayer, sublayerCount());
188 void WKCACFLayer::internalInsertSublayer(PassRefPtr<WKCACFLayer> sublayer, size_t index)
190 index = min(index, sublayerCount());
191 sublayer->removeFromSuperlayer();
192 CACFLayerInsertSublayer(layer(), sublayer->layer(), index);
196 void WKCACFLayer::insertSublayerAboveLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
199 insertSublayer(sublayer, 0);
203 int referenceIndex = internalIndexOfSublayer(reference);
204 if (referenceIndex == -1) {
205 addSublayer(sublayer);
209 insertSublayer(sublayer, referenceIndex + 1);
212 void WKCACFLayer::insertSublayerBelowLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
215 insertSublayer(sublayer, 0);
219 int referenceIndex = internalIndexOfSublayer(reference);
220 if (referenceIndex == -1) {
221 addSublayer(sublayer);
225 insertSublayer(sublayer, referenceIndex);
228 void WKCACFLayer::replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer> newLayer)
230 ASSERT_ARG(reference, reference);
231 ASSERT_ARG(reference, reference->superlayer() == this);
233 if (reference == newLayer)
236 int referenceIndex = internalIndexOfSublayer(reference);
237 ASSERT(referenceIndex != -1);
238 if (referenceIndex == -1)
241 reference->removeFromSuperlayer();
244 newLayer->removeFromSuperlayer();
245 insertSublayer(newLayer, referenceIndex);
249 size_t WKCACFLayer::internalSublayerCount() const
251 CFArrayRef sublayers = CACFLayerGetSublayers(layer());
252 return sublayers ? CFArrayGetCount(sublayers) : 0;
255 void WKCACFLayer::adoptSublayers(WKCACFLayer* source)
257 // We will use setSublayers() because it properly nulls
258 // out the superlayer pointer.
259 Vector<RefPtr<WKCACFLayer> > sublayers;
260 size_t n = source->sublayerCount();
262 for (size_t i = 0; i < n; ++i)
263 sublayers.append(source->internalSublayerAtIndex(i));
265 setSublayers(sublayers);
268 void WKCACFLayer::removeFromSuperlayer()
270 WKCACFLayer* superlayer = this->superlayer();
271 CACFLayerRemoveFromSuperlayer(layer());
274 superlayer->setNeedsCommit();
277 WKCACFLayer* WKCACFLayer::internalSublayerAtIndex(int index) const
279 CFArrayRef sublayers = CACFLayerGetSublayers(layer());
280 if (!sublayers || index < 0 || CFArrayGetCount(sublayers) <= index)
283 return layer(static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, index))));
286 int WKCACFLayer::internalIndexOfSublayer(const WKCACFLayer* reference)
288 CACFLayerRef ref = reference->layer();
292 CFArrayRef sublayers = CACFLayerGetSublayers(layer());
296 size_t n = CFArrayGetCount(sublayers);
298 for (size_t i = 0; i < n; ++i)
299 if (CFArrayGetValueAtIndex(sublayers, i) == ref)
305 WKCACFLayer* WKCACFLayer::ancestorOrSelfWithSuperlayer(WKCACFLayer* superlayer) const
307 WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
308 for (WKCACFLayer* ancestor = this->superlayer(); ancestor; layer = ancestor, ancestor = ancestor->superlayer()) {
309 if (ancestor == superlayer)
315 void WKCACFLayer::setBounds(const CGRect& rect)
317 if (CGRectEqualToRect(rect, bounds()))
320 CACFLayerSetBounds(layer(), rect);
323 if (m_needsDisplayOnBoundsChange)
327 void WKCACFLayer::setFrame(const CGRect& rect)
329 CGRect oldFrame = frame();
330 if (CGRectEqualToRect(rect, oldFrame))
333 CACFLayerSetFrame(layer(), rect);
336 if (m_needsDisplayOnBoundsChange && !CGSizeEqualToSize(rect.size, oldFrame.size))
340 void WKCACFLayer::setContentsGravity(ContentsGravityType type)
342 CACFLayerSetContentsGravity(layer(), toCACFContentsGravityType(type));
346 WKCACFLayer::ContentsGravityType WKCACFLayer::contentsGravity() const
348 return fromCACFContentsGravityType(CACFLayerGetContentsGravity(layer()));
351 void WKCACFLayer::setMagnificationFilter(FilterType type)
353 CACFLayerSetMagnificationFilter(layer(), toCACFFilterType(type));
357 WKCACFLayer::FilterType WKCACFLayer::magnificationFilter() const
359 return fromCACFFilterType(CACFLayerGetMagnificationFilter(layer()));
362 void WKCACFLayer::setMinificationFilter(FilterType type)
364 CACFLayerSetMinificationFilter(layer(), toCACFFilterType(type));
368 WKCACFLayer::FilterType WKCACFLayer::minificationFilter() const
370 return fromCACFFilterType(CACFLayerGetMinificationFilter(layer()));
373 WKCACFLayer* WKCACFLayer::rootLayer() const
375 WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
376 for (WKCACFLayer* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
380 void WKCACFLayer::internalRemoveAllSublayers()
382 CACFLayerSetSublayers(layer(), 0);
386 void WKCACFLayer::internalSetSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers)
388 // Remove all the current sublayers and add the passed layers
389 CACFLayerSetSublayers(layer(), 0);
391 // Perform removeFromSuperLayer in a separate pass. CACF requires superlayer to
392 // be null or CACFLayerInsertSublayer silently fails.
393 for (size_t i = 0; i < sublayers.size(); i++)
394 CACFLayerRemoveFromSuperlayer(sublayers[i]->layer());
396 for (size_t i = 0; i < sublayers.size(); i++)
397 CACFLayerInsertSublayer(layer(), sublayers[i]->layer(), i);
402 WKCACFLayer* WKCACFLayer::superlayer() const
404 CACFLayerRef super = CACFLayerGetSuperlayer(layer());
407 return WKCACFLayer::layer(super);
410 void WKCACFLayer::internalSetNeedsDisplay(const CGRect* dirtyRect)
412 CACFLayerSetNeedsDisplay(layer(), dirtyRect);
415 void WKCACFLayer::setLayoutClient(WKCACFLayerLayoutClient* layoutClient)
417 if (layoutClient == m_layoutClient)
420 m_layoutClient = layoutClient;
421 CACFLayerSetLayoutCallback(layer(), m_layoutClient ? layoutSublayersProc : 0);
424 void WKCACFLayer::layoutSublayersProc(CACFLayerRef caLayer)
426 WKCACFLayer* layer = WKCACFLayer::layer(caLayer);
427 if (layer && layer->m_layoutClient)
428 layer->m_layoutClient->layoutSublayersOfLayer(layer);
432 static void printIndent(int indent)
434 for ( ; indent > 0; --indent)
435 fprintf(stderr, " ");
438 static void printTransform(const CATransform3D& transform)
440 fprintf(stderr, "[%g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g]",
441 transform.m11, transform.m12, transform.m13, transform.m14,
442 transform.m21, transform.m22, transform.m23, transform.m24,
443 transform.m31, transform.m32, transform.m33, transform.m34,
444 transform.m41, transform.m42, transform.m43, transform.m44);
447 void WKCACFLayer::printTree() const
449 // Print heading info
450 CGRect rootBounds = bounds();
451 fprintf(stderr, "\n\n** Render tree at time %g (bounds %g, %g %gx%g) **\n\n",
452 currentTime(), rootBounds.origin.x, rootBounds.origin.y, rootBounds.size.width, rootBounds.size.height);
454 // Print layer tree from the root
458 void WKCACFLayer::printLayer(int indent) const
460 CGPoint layerPosition = position();
461 CGPoint layerAnchorPoint = anchorPoint();
462 CGRect layerBounds = bounds();
464 fprintf(stderr, "(%s [%g %g %g] [%g %g %g %g] [%g %g %g] superlayer=%p\n",
465 isTransformLayer() ? "transform-layer" : "layer",
466 layerPosition.x, layerPosition.y, zPosition(),
467 layerBounds.origin.x, layerBounds.origin.y, layerBounds.size.width, layerBounds.size.height,
468 layerAnchorPoint.x, layerAnchorPoint.y, anchorPointZ(), superlayer());
470 // Print name if needed
471 String layerName = name();
472 if (!layerName.isEmpty()) {
473 printIndent(indent + 1);
474 fprintf(stderr, "(name %s)\n", layerName.utf8().data());
477 // Print masksToBounds if needed
478 bool layerMasksToBounds = masksToBounds();
479 if (layerMasksToBounds) {
480 printIndent(indent + 1);
481 fprintf(stderr, "(masksToBounds true)\n");
484 // Print opacity if needed
485 float layerOpacity = opacity();
486 if (layerOpacity != 1) {
487 printIndent(indent + 1);
488 fprintf(stderr, "(opacity %hf)\n", layerOpacity);
491 // Print sublayerTransform if needed
492 CATransform3D layerTransform = sublayerTransform();
493 if (!CATransform3DIsIdentity(layerTransform)) {
494 printIndent(indent + 1);
495 fprintf(stderr, "(sublayerTransform ");
496 printTransform(layerTransform);
497 fprintf(stderr, ")\n");
500 // Print transform if needed
501 layerTransform = transform();
502 if (!CATransform3DIsIdentity(layerTransform)) {
503 printIndent(indent + 1);
504 fprintf(stderr, "(transform ");
505 printTransform(layerTransform);
506 fprintf(stderr, ")\n");
509 // Print contents if needed
510 CFTypeRef layerContents = contents();
512 if (CFGetTypeID(layerContents) == CGImageGetTypeID()) {
513 CGImageRef imageContents = static_cast<CGImageRef>(const_cast<void*>(layerContents));
514 printIndent(indent + 1);
515 fprintf(stderr, "(contents (image [%d %d]))\n",
516 CGImageGetWidth(imageContents), CGImageGetHeight(imageContents));
520 // Print sublayers if needed
521 int n = sublayerCount();
523 printIndent(indent + 1);
524 fprintf(stderr, "(sublayers\n");
525 for (int i = 0; i < n; ++i)
526 internalSublayerAtIndex(i)->printLayer(indent + 2);
528 printIndent(indent + 1);
529 fprintf(stderr, ")\n");
533 fprintf(stderr, ")\n");
535 #endif // #ifndef NDEBUG
538 #endif // USE(ACCELERATED_COMPOSITING)