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>
43 void WKCACFLayer::internalCheckLayerConsistency()
46 size_t n = sublayerCount();
47 for (size_t i = 0; i < n; ++i) {
48 // This will ASSERT in internalSublayerAtIndex if this entry doesn't have proper user data
49 WKCACFLayer* sublayer = internalSublayerAtIndex(i);
51 // Make sure we don't have any null entries in the list
54 // Make sure the each layer has a corresponding CACFLayer
55 ASSERT(sublayer->layer());
60 static void displayCallback(CACFLayerRef layer, CGContextRef context)
62 ASSERT_ARG(layer, WKCACFLayer::layer(layer));
63 WKCACFLayer::layer(layer)->drawInContext(context);
66 static CFStringRef toCACFLayerType(WKCACFLayer::LayerType type)
69 case WKCACFLayer::Layer: return kCACFLayer;
70 case WKCACFLayer::TransformLayer: return kCACFTransformLayer;
75 static CFStringRef toCACFContentsGravityType(WKCACFLayer::ContentsGravityType type)
78 case WKCACFLayer::Center: return kCACFGravityCenter;
79 case WKCACFLayer::Top: return kCACFGravityTop;
80 case WKCACFLayer::Bottom: return kCACFGravityBottom;
81 case WKCACFLayer::Left: return kCACFGravityLeft;
82 case WKCACFLayer::Right: return kCACFGravityRight;
83 case WKCACFLayer::TopLeft: return kCACFGravityTopLeft;
84 case WKCACFLayer::TopRight: return kCACFGravityTopRight;
85 case WKCACFLayer::BottomLeft: return kCACFGravityBottomLeft;
86 case WKCACFLayer::BottomRight: return kCACFGravityBottomRight;
87 case WKCACFLayer::Resize: return kCACFGravityResize;
88 case WKCACFLayer::ResizeAspect: return kCACFGravityResizeAspect;
89 case WKCACFLayer::ResizeAspectFill: return kCACFGravityResizeAspectFill;
94 static WKCACFLayer::ContentsGravityType fromCACFContentsGravityType(CFStringRef string)
96 if (CFEqual(string, kCACFGravityTop))
97 return WKCACFLayer::Top;
99 if (CFEqual(string, kCACFGravityBottom))
100 return WKCACFLayer::Bottom;
102 if (CFEqual(string, kCACFGravityLeft))
103 return WKCACFLayer::Left;
105 if (CFEqual(string, kCACFGravityRight))
106 return WKCACFLayer::Right;
108 if (CFEqual(string, kCACFGravityTopLeft))
109 return WKCACFLayer::TopLeft;
111 if (CFEqual(string, kCACFGravityTopRight))
112 return WKCACFLayer::TopRight;
114 if (CFEqual(string, kCACFGravityBottomLeft))
115 return WKCACFLayer::BottomLeft;
117 if (CFEqual(string, kCACFGravityBottomRight))
118 return WKCACFLayer::BottomRight;
120 if (CFEqual(string, kCACFGravityResize))
121 return WKCACFLayer::Resize;
123 if (CFEqual(string, kCACFGravityResizeAspect))
124 return WKCACFLayer::ResizeAspect;
126 if (CFEqual(string, kCACFGravityResizeAspectFill))
127 return WKCACFLayer::ResizeAspectFill;
129 return WKCACFLayer::Center;
132 static CFStringRef toCACFFilterType(WKCACFLayer::FilterType type)
135 case WKCACFLayer::Linear: return kCACFFilterLinear;
136 case WKCACFLayer::Nearest: return kCACFFilterNearest;
137 case WKCACFLayer::Trilinear: return kCACFFilterTrilinear;
142 static WKCACFLayer::FilterType fromCACFFilterType(CFStringRef string)
144 if (CFEqual(string, kCACFFilterNearest))
145 return WKCACFLayer::Nearest;
147 if (CFEqual(string, kCACFFilterTrilinear))
148 return WKCACFLayer::Trilinear;
150 return WKCACFLayer::Linear;
153 PassRefPtr<WKCACFLayer> WKCACFLayer::create(LayerType type)
155 if (!WKCACFLayerRenderer::acceleratedCompositingAvailable())
157 return adoptRef(new WKCACFLayer(type));
160 // FIXME: It might be good to have a way of ensuring that all WKCACFLayers eventually
161 // get destroyed in debug builds. A static counter could accomplish this pretty easily.
163 WKCACFLayer::WKCACFLayer(LayerType type)
164 : m_layer(AdoptCF, CACFLayerCreate(toCACFLayerType(type)))
166 , m_needsDisplayOnBoundsChange(false)
168 CACFLayerSetUserData(layer(), this);
169 CACFLayerSetDisplayCallback(layer(), displayCallback);
172 WKCACFLayer::~WKCACFLayer()
174 // 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.
175 ASSERT(!superlayer());
177 // Get rid of the children so we don't have any dangling references around
178 removeAllSublayers();
181 CACFLayerSetUserData(layer(), reinterpret_cast<void*>(0xDEADBEEF));
183 CACFLayerSetUserData(layer(), 0);
185 CACFLayerSetDisplayCallback(layer(), 0);
188 void WKCACFLayer::becomeRootLayerForContext(WKCACFContext* context)
190 wkCACFContextSetLayer(context, layer());
194 void WKCACFLayer::setNeedsCommit()
196 WKCACFLayer* root = rootLayer();
198 // Call setNeedsRender on the root layer, which will cause a render to
199 // happen in WKCACFLayerRenderer
200 root->setNeedsRender();
203 bool WKCACFLayer::isTransformLayer() const
205 return CACFLayerGetClass(layer()) == kCACFTransformLayer;
208 void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer)
210 insertSublayer(sublayer, sublayerCount());
213 void WKCACFLayer::internalInsertSublayer(PassRefPtr<WKCACFLayer> sublayer, size_t index)
215 index = min(index, sublayerCount() + 1);
216 sublayer->removeFromSuperlayer();
217 CACFLayerInsertSublayer(layer(), sublayer->layer(), index);
219 checkLayerConsistency();
222 void WKCACFLayer::insertSublayerAboveLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
225 insertSublayer(sublayer, 0);
229 int referenceIndex = internalIndexOfSublayer(reference);
230 if (referenceIndex == -1) {
231 addSublayer(sublayer);
235 insertSublayer(sublayer, referenceIndex + 1);
238 void WKCACFLayer::insertSublayerBelowLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
241 insertSublayer(sublayer, 0);
245 int referenceIndex = internalIndexOfSublayer(reference);
246 if (referenceIndex == -1) {
247 addSublayer(sublayer);
251 insertSublayer(sublayer, referenceIndex);
254 void WKCACFLayer::replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer> newLayer)
256 ASSERT_ARG(reference, reference);
257 ASSERT_ARG(reference, reference->superlayer() == this);
259 if (reference == newLayer)
262 int referenceIndex = internalIndexOfSublayer(reference);
263 ASSERT(referenceIndex != -1);
264 if (referenceIndex == -1)
267 reference->removeFromSuperlayer();
270 newLayer->removeFromSuperlayer();
271 insertSublayer(newLayer, referenceIndex);
275 size_t WKCACFLayer::internalSublayerCount() const
277 CFArrayRef sublayers = CACFLayerGetSublayers(layer());
278 return sublayers ? CFArrayGetCount(sublayers) : 0;
281 void WKCACFLayer::adoptSublayers(WKCACFLayer* source)
283 // We will use setSublayers() because it properly nulls
284 // out the superlayer pointer.
285 Vector<RefPtr<WKCACFLayer> > sublayers;
286 size_t n = source->sublayerCount();
288 for (size_t i = 0; i < n; ++i)
289 sublayers.append(source->internalSublayerAtIndex(i));
291 setSublayers(sublayers);
292 source->checkLayerConsistency();
295 void WKCACFLayer::removeFromSuperlayer()
297 WKCACFLayer* superlayer = this->superlayer();
298 CACFLayerRemoveFromSuperlayer(layer());
299 checkLayerConsistency();
302 superlayer->setNeedsCommit();
305 WKCACFLayer* WKCACFLayer::internalSublayerAtIndex(int index) const
307 CFArrayRef sublayers = CACFLayerGetSublayers(layer());
308 if (!sublayers || index < 0 || CFArrayGetCount(sublayers) <= index)
311 return layer(static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, index))));
314 int WKCACFLayer::internalIndexOfSublayer(const WKCACFLayer* reference)
316 CACFLayerRef ref = reference->layer();
320 CFArrayRef sublayers = CACFLayerGetSublayers(layer());
324 size_t n = CFArrayGetCount(sublayers);
326 for (size_t i = 0; i < n; ++i)
327 if (CFArrayGetValueAtIndex(sublayers, i) == ref)
333 WKCACFLayer* WKCACFLayer::ancestorOrSelfWithSuperlayer(WKCACFLayer* superlayer) const
335 WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
336 for (WKCACFLayer* ancestor = this->superlayer(); ancestor; layer = ancestor, ancestor = ancestor->superlayer()) {
337 if (ancestor == superlayer)
343 void WKCACFLayer::setBounds(const CGRect& rect)
345 if (CGRectEqualToRect(rect, bounds()))
348 CACFLayerSetBounds(layer(), rect);
351 if (m_needsDisplayOnBoundsChange)
358 void WKCACFLayer::setFrame(const CGRect& rect)
360 CGRect oldFrame = frame();
361 if (CGRectEqualToRect(rect, oldFrame))
364 CACFLayerSetFrame(layer(), rect);
367 if (m_needsDisplayOnBoundsChange && !CGSizeEqualToSize(rect.size, oldFrame.size))
374 void WKCACFLayer::setContentsGravity(ContentsGravityType type)
376 CACFLayerSetContentsGravity(layer(), toCACFContentsGravityType(type));
380 WKCACFLayer::ContentsGravityType WKCACFLayer::contentsGravity() const
382 return fromCACFContentsGravityType(CACFLayerGetContentsGravity(layer()));
385 void WKCACFLayer::setMagnificationFilter(FilterType type)
387 CACFLayerSetMagnificationFilter(layer(), toCACFFilterType(type));
391 WKCACFLayer::FilterType WKCACFLayer::magnificationFilter() const
393 return fromCACFFilterType(CACFLayerGetMagnificationFilter(layer()));
396 void WKCACFLayer::setMinificationFilter(FilterType type)
398 CACFLayerSetMinificationFilter(layer(), toCACFFilterType(type));
402 WKCACFLayer::FilterType WKCACFLayer::minificationFilter() const
404 return fromCACFFilterType(CACFLayerGetMinificationFilter(layer()));
407 WKCACFLayer* WKCACFLayer::rootLayer() const
409 WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
410 for (WKCACFLayer* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
414 void WKCACFLayer::internalRemoveAllSublayers()
416 CACFLayerSetSublayers(layer(), 0);
420 void WKCACFLayer::internalSetSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers)
422 // Remove all the current sublayers and add the passed layers
423 CACFLayerSetSublayers(layer(), 0);
425 // Perform removeFromSuperLayer in a separate pass. CACF requires superlayer to
426 // be null or CACFLayerInsertSublayer silently fails.
427 for (size_t i = 0; i < sublayers.size(); i++)
428 CACFLayerRemoveFromSuperlayer(sublayers[i]->layer());
430 for (size_t i = 0; i < sublayers.size(); i++)
431 CACFLayerInsertSublayer(layer(), sublayers[i]->layer(), i);
436 WKCACFLayer* WKCACFLayer::superlayer() const
438 CACFLayerRef super = CACFLayerGetSuperlayer(layer());
441 return WKCACFLayer::layer(super);
444 void WKCACFLayer::internalSetNeedsDisplay(const CGRect* dirtyRect)
446 CACFLayerSetNeedsDisplay(layer(), dirtyRect);
449 void WKCACFLayer::setLayoutClient(WKCACFLayerLayoutClient* layoutClient)
451 if (layoutClient == m_layoutClient)
454 m_layoutClient = layoutClient;
455 CACFLayerSetLayoutCallback(layer(), m_layoutClient ? layoutSublayersProc : 0);
458 void WKCACFLayer::layoutSublayersProc(CACFLayerRef caLayer)
460 WKCACFLayer* layer = WKCACFLayer::layer(caLayer);
461 if (layer && layer->m_layoutClient)
462 layer->m_layoutClient->layoutSublayersOfLayer(layer);
466 static void printIndent(int indent)
468 for ( ; indent > 0; --indent)
469 fprintf(stderr, " ");
472 static void printTransform(const CATransform3D& transform)
474 fprintf(stderr, "[%g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g]",
475 transform.m11, transform.m12, transform.m13, transform.m14,
476 transform.m21, transform.m22, transform.m23, transform.m24,
477 transform.m31, transform.m32, transform.m33, transform.m34,
478 transform.m41, transform.m42, transform.m43, transform.m44);
481 void WKCACFLayer::printTree() const
483 // Print heading info
484 CGRect rootBounds = bounds();
485 fprintf(stderr, "\n\n** Render tree at time %g (bounds %g, %g %gx%g) **\n\n",
486 currentTime(), rootBounds.origin.x, rootBounds.origin.y, rootBounds.size.width, rootBounds.size.height);
488 // Print layer tree from the root
492 void WKCACFLayer::printLayer(int indent) const
494 CGPoint layerPosition = position();
495 CGPoint layerAnchorPoint = anchorPoint();
496 CGRect layerBounds = bounds();
498 fprintf(stderr, "(%s [%g %g %g] [%g %g %g %g] [%g %g %g] superlayer=%p\n",
499 isTransformLayer() ? "transform-layer" : "layer",
500 layerPosition.x, layerPosition.y, zPosition(),
501 layerBounds.origin.x, layerBounds.origin.y, layerBounds.size.width, layerBounds.size.height,
502 layerAnchorPoint.x, layerAnchorPoint.y, anchorPointZ(), superlayer());
504 // Print name if needed
505 String layerName = name();
506 if (!layerName.isEmpty()) {
507 printIndent(indent + 1);
508 fprintf(stderr, "(name %s)\n", layerName.utf8().data());
511 // Print masksToBounds if needed
512 bool layerMasksToBounds = masksToBounds();
513 if (layerMasksToBounds) {
514 printIndent(indent + 1);
515 fprintf(stderr, "(masksToBounds true)\n");
518 // Print opacity if needed
519 float layerOpacity = opacity();
520 if (layerOpacity != 1) {
521 printIndent(indent + 1);
522 fprintf(stderr, "(opacity %hf)\n", layerOpacity);
525 // Print sublayerTransform if needed
526 CATransform3D layerTransform = sublayerTransform();
527 if (!CATransform3DIsIdentity(layerTransform)) {
528 printIndent(indent + 1);
529 fprintf(stderr, "(sublayerTransform ");
530 printTransform(layerTransform);
531 fprintf(stderr, ")\n");
534 // Print transform if needed
535 layerTransform = transform();
536 if (!CATransform3DIsIdentity(layerTransform)) {
537 printIndent(indent + 1);
538 fprintf(stderr, "(transform ");
539 printTransform(layerTransform);
540 fprintf(stderr, ")\n");
543 // Print contents if needed
544 CFTypeRef layerContents = contents();
546 if (CFGetTypeID(layerContents) == CGImageGetTypeID()) {
547 CGImageRef imageContents = static_cast<CGImageRef>(const_cast<void*>(layerContents));
548 printIndent(indent + 1);
549 fprintf(stderr, "(contents (image [%d %d]))\n",
550 CGImageGetWidth(imageContents), CGImageGetHeight(imageContents));
554 // Print sublayers if needed
555 int n = sublayerCount();
557 printIndent(indent + 1);
558 fprintf(stderr, "(sublayers\n");
559 for (int i = 0; i < n; ++i)
560 internalSublayerAtIndex(i)->printLayer(indent + 2);
562 printIndent(indent + 1);
563 fprintf(stderr, ")\n");
567 fprintf(stderr, ")\n");
569 #endif // #ifndef NDEBUG
572 #endif // USE(ACCELERATED_COMPOSITING)