Roll our r64361 and r64363
[WebKit-https.git] / WebCore / platform / graphics / win / WKCACFLayer.cpp
1 /*
2  * Copyright (C) 2009 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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. 
24  */
25
26 #include "config.h"
27
28 #if USE(ACCELERATED_COMPOSITING)
29
30 #include "WKCACFLayer.h"
31
32 #include "WKCACFLayerRenderer.h"
33 #include <wtf/text/CString.h>
34
35 #include <stdio.h>
36 #include <QuartzCore/CACFContext.h>
37 #include <QuartzCore/CARender.h>
38
39 #ifndef NDEBUG
40 #include <wtf/CurrentTime.h>
41 #endif
42
43 namespace WebCore {
44
45 using namespace std;
46
47 static void displayCallback(CACFLayerRef layer, CGContextRef context)
48 {
49     ASSERT_ARG(layer, WKCACFLayer::layer(layer));
50     WKCACFLayer::layer(layer)->drawInContext(context);
51 }
52
53 static CFStringRef toCACFLayerType(WKCACFLayer::LayerType type)
54 {
55     switch (type) {
56     case WKCACFLayer::Layer: return kCACFLayer;
57     case WKCACFLayer::TransformLayer: return kCACFTransformLayer;
58     default: return 0;
59     }
60 }
61
62 static CFStringRef toCACFContentsGravityType(WKCACFLayer::ContentsGravityType type)
63 {
64     switch (type) {
65     case WKCACFLayer::Center: return kCACFGravityCenter;
66     case WKCACFLayer::Top: return kCACFGravityTop;
67     case WKCACFLayer::Bottom: return kCACFGravityBottom;
68     case WKCACFLayer::Left: return kCACFGravityLeft;
69     case WKCACFLayer::Right: return kCACFGravityRight;
70     case WKCACFLayer::TopLeft: return kCACFGravityTopLeft;
71     case WKCACFLayer::TopRight: return kCACFGravityTopRight;
72     case WKCACFLayer::BottomLeft: return kCACFGravityBottomLeft;
73     case WKCACFLayer::BottomRight: return kCACFGravityBottomRight;
74     case WKCACFLayer::Resize: return kCACFGravityResize;
75     case WKCACFLayer::ResizeAspect: return kCACFGravityResizeAspect;
76     case WKCACFLayer::ResizeAspectFill: return kCACFGravityResizeAspectFill;
77     default: return 0;
78     }
79 }
80
81 static WKCACFLayer::ContentsGravityType fromCACFContentsGravityType(CFStringRef string)
82 {
83     if (CFEqual(string, kCACFGravityTop))
84         return WKCACFLayer::Top;
85
86     if (CFEqual(string, kCACFGravityBottom))
87         return WKCACFLayer::Bottom;
88
89     if (CFEqual(string, kCACFGravityLeft))
90         return WKCACFLayer::Left;
91
92     if (CFEqual(string, kCACFGravityRight))
93         return WKCACFLayer::Right;
94
95     if (CFEqual(string, kCACFGravityTopLeft))
96         return WKCACFLayer::TopLeft;
97
98     if (CFEqual(string, kCACFGravityTopRight))
99         return WKCACFLayer::TopRight;
100
101     if (CFEqual(string, kCACFGravityBottomLeft))
102         return WKCACFLayer::BottomLeft;
103
104     if (CFEqual(string, kCACFGravityBottomRight))
105         return WKCACFLayer::BottomRight;
106
107     if (CFEqual(string, kCACFGravityResize))
108         return WKCACFLayer::Resize;
109
110     if (CFEqual(string, kCACFGravityResizeAspect))
111         return WKCACFLayer::ResizeAspect;
112
113     if (CFEqual(string, kCACFGravityResizeAspectFill))
114         return WKCACFLayer::ResizeAspectFill;
115
116     return WKCACFLayer::Center;
117 }
118
119 static CFStringRef toCACFFilterType(WKCACFLayer::FilterType type)
120 {
121     switch (type) {
122     case WKCACFLayer::Linear: return kCACFFilterLinear;
123     case WKCACFLayer::Nearest: return kCACFFilterNearest;
124     case WKCACFLayer::Trilinear: return kCACFFilterTrilinear;
125     default: return 0;
126     }
127 }
128
129 static WKCACFLayer::FilterType fromCACFFilterType(CFStringRef string)
130 {
131     if (CFEqual(string, kCACFFilterNearest))
132         return WKCACFLayer::Nearest;
133
134     if (CFEqual(string, kCACFFilterTrilinear))
135         return WKCACFLayer::Trilinear;
136
137     return WKCACFLayer::Linear;
138 }
139
140 PassRefPtr<WKCACFLayer> WKCACFLayer::create(LayerType type)
141 {
142     if (!WKCACFLayerRenderer::acceleratedCompositingAvailable())
143         return 0;
144     return adoptRef(new WKCACFLayer(type));
145 }
146
147 // FIXME: It might be good to have a way of ensuring that all WKCACFLayers eventually
148 // get destroyed in debug builds. A static counter could accomplish this pretty easily.
149
150 WKCACFLayer::WKCACFLayer(LayerType type)
151     : m_layer(AdoptCF, CACFLayerCreate(toCACFLayerType(type)))
152     , m_layoutClient(0)
153     , m_needsDisplayOnBoundsChange(false)
154 {
155     CACFLayerSetUserData(layer(), this);
156     CACFLayerSetDisplayCallback(layer(), displayCallback);
157 }
158
159 WKCACFLayer::~WKCACFLayer()
160 {
161     // 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.
162     ASSERT(!superlayer());
163
164     CACFLayerSetUserData(layer(), 0);
165     CACFLayerSetDisplayCallback(layer(), 0);
166 }
167
168 void WKCACFLayer::becomeRootLayerForContext(CACFContextRef context)
169 {
170     CACFContextSetLayer(context, layer());
171     setNeedsCommit();
172 }
173
174 void WKCACFLayer::setNeedsCommit()
175 {
176     WKCACFLayer* root = rootLayer();
177
178     // Call setNeedsRender on the root layer, which will cause a render to 
179     // happen in WKCACFLayerRenderer
180     root->setNeedsRender();
181 }
182
183 bool WKCACFLayer::isTransformLayer() const
184 {
185     return CACFLayerGetClass(layer()) == kCACFTransformLayer;
186 }
187
188 void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer)
189 {
190     insertSublayer(sublayer, sublayerCount());
191 }
192
193 void WKCACFLayer::internalInsertSublayer(PassRefPtr<WKCACFLayer> sublayer, size_t index)
194 {
195     index = min(index, sublayerCount());
196     sublayer->removeFromSuperlayer();
197     CACFLayerInsertSublayer(layer(), sublayer->layer(), index);
198     setNeedsCommit();
199 }
200
201 void WKCACFLayer::insertSublayerAboveLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
202 {
203     if (!reference) {
204         insertSublayer(sublayer, 0);
205         return;
206     }
207
208     int referenceIndex = internalIndexOfSublayer(reference);
209     if (referenceIndex == -1) {
210         addSublayer(sublayer);
211         return;
212     }
213
214     insertSublayer(sublayer, referenceIndex + 1);
215 }
216
217 void WKCACFLayer::insertSublayerBelowLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
218 {
219     if (!reference) {
220         insertSublayer(sublayer, 0);
221         return;
222     }
223
224     int referenceIndex = internalIndexOfSublayer(reference);
225     if (referenceIndex == -1) {
226         addSublayer(sublayer);
227         return;
228     }
229
230     insertSublayer(sublayer, referenceIndex);
231 }
232
233 void WKCACFLayer::replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer> newLayer)
234 {
235     ASSERT_ARG(reference, reference);
236     ASSERT_ARG(reference, reference->superlayer() == this);
237
238     if (reference == newLayer)
239         return;
240
241     int referenceIndex = internalIndexOfSublayer(reference);
242     ASSERT(referenceIndex != -1);
243     if (referenceIndex == -1)
244         return;
245
246     reference->removeFromSuperlayer();
247
248     if (newLayer) {
249         newLayer->removeFromSuperlayer();
250         insertSublayer(newLayer, referenceIndex);
251     }
252 }
253
254 size_t WKCACFLayer::internalSublayerCount() const
255 {
256     CFArrayRef sublayers = CACFLayerGetSublayers(layer());
257     return sublayers ? CFArrayGetCount(sublayers) : 0;
258 }
259
260 void  WKCACFLayer::adoptSublayers(WKCACFLayer* source)
261 {
262     // We will use setSublayers() because it properly nulls
263     // out the superlayer pointer.
264     Vector<RefPtr<WKCACFLayer> > sublayers;
265     size_t n = source->sublayerCount();
266
267     for (size_t i = 0; i < n; ++i)
268         sublayers.append(source->internalSublayerAtIndex(i));
269
270     setSublayers(sublayers);
271 }
272
273 void WKCACFLayer::removeFromSuperlayer()
274 {
275     WKCACFLayer* superlayer = this->superlayer();
276     CACFLayerRemoveFromSuperlayer(layer());
277
278     if (superlayer)
279         superlayer->setNeedsCommit();
280 }
281
282 WKCACFLayer* WKCACFLayer::internalSublayerAtIndex(int index) const
283 {
284     CFArrayRef sublayers = CACFLayerGetSublayers(layer());
285     if (!sublayers || index < 0 || CFArrayGetCount(sublayers) <= index)
286         return 0;
287     
288     return layer(static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, index))));
289 }
290
291 int WKCACFLayer::internalIndexOfSublayer(const WKCACFLayer* reference)
292 {
293     CACFLayerRef ref = reference->layer();
294     if (!ref)
295         return -1;
296
297     CFArrayRef sublayers = CACFLayerGetSublayers(layer());
298     if (!sublayers)
299         return -1;
300
301     size_t n = CFArrayGetCount(sublayers);
302
303     for (size_t i = 0; i < n; ++i)
304         if (CFArrayGetValueAtIndex(sublayers, i) == ref)
305             return i;
306
307     return -1;
308 }
309
310 WKCACFLayer* WKCACFLayer::ancestorOrSelfWithSuperlayer(WKCACFLayer* superlayer) const
311 {
312     WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
313     for (WKCACFLayer* ancestor = this->superlayer(); ancestor; layer = ancestor, ancestor = ancestor->superlayer()) {
314         if (ancestor == superlayer)
315             return layer;
316     }
317     return 0;
318 }
319
320 void WKCACFLayer::setBounds(const CGRect& rect)
321 {
322     if (CGRectEqualToRect(rect, bounds()))
323         return;
324
325     CACFLayerSetBounds(layer(), rect);
326     setNeedsCommit();
327
328     if (m_needsDisplayOnBoundsChange)
329         setNeedsDisplay();
330 }
331
332 void WKCACFLayer::setFrame(const CGRect& rect)
333 {
334     CGRect oldFrame = frame();
335     if (CGRectEqualToRect(rect, oldFrame))
336         return;
337
338     CACFLayerSetFrame(layer(), rect);
339     setNeedsCommit();
340
341     if (m_needsDisplayOnBoundsChange && !CGSizeEqualToSize(rect.size, oldFrame.size))
342         setNeedsDisplay();
343 }
344
345 void WKCACFLayer::setContentsGravity(ContentsGravityType type)
346 {
347     CACFLayerSetContentsGravity(layer(), toCACFContentsGravityType(type));
348     setNeedsCommit();
349 }
350
351 WKCACFLayer::ContentsGravityType WKCACFLayer::contentsGravity() const
352 {
353     return fromCACFContentsGravityType(CACFLayerGetContentsGravity(layer()));
354 }
355
356 void WKCACFLayer::setMagnificationFilter(FilterType type)
357 {
358     CACFLayerSetMagnificationFilter(layer(), toCACFFilterType(type));
359     setNeedsCommit();
360 }
361
362 WKCACFLayer::FilterType WKCACFLayer::magnificationFilter() const
363 {
364     return fromCACFFilterType(CACFLayerGetMagnificationFilter(layer()));
365 }
366
367 void WKCACFLayer::setMinificationFilter(FilterType type)
368 {
369     CACFLayerSetMinificationFilter(layer(), toCACFFilterType(type));
370     setNeedsCommit();
371 }
372
373 WKCACFLayer::FilterType WKCACFLayer::minificationFilter() const
374 {
375     return fromCACFFilterType(CACFLayerGetMinificationFilter(layer()));
376 }
377
378 WKCACFLayer* WKCACFLayer::rootLayer() const
379 {
380     WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
381     for (WKCACFLayer* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
382     return layer;
383 }
384
385 void WKCACFLayer::internalRemoveAllSublayers()
386 {
387     CACFLayerSetSublayers(layer(), 0);
388     setNeedsCommit();
389 }
390
391 void WKCACFLayer::internalSetSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers)
392 {
393     // Remove all the current sublayers and add the passed layers
394     CACFLayerSetSublayers(layer(), 0);
395
396     // Perform removeFromSuperLayer in a separate pass. CACF requires superlayer to
397     // be null or CACFLayerInsertSublayer silently fails.
398     for (size_t i = 0; i < sublayers.size(); i++)
399         CACFLayerRemoveFromSuperlayer(sublayers[i]->layer());
400
401     for (size_t i = 0; i < sublayers.size(); i++)
402         CACFLayerInsertSublayer(layer(), sublayers[i]->layer(), i);
403
404     setNeedsCommit();
405 }
406
407 WKCACFLayer* WKCACFLayer::superlayer() const
408 {
409     CACFLayerRef super = CACFLayerGetSuperlayer(layer());
410     if (!super)
411         return 0;
412     return WKCACFLayer::layer(super);
413 }
414
415 void WKCACFLayer::internalSetNeedsDisplay(const CGRect* dirtyRect)
416 {
417     CACFLayerSetNeedsDisplay(layer(), dirtyRect);
418 }
419
420 void WKCACFLayer::setLayoutClient(WKCACFLayerLayoutClient* layoutClient)
421 {
422     if (layoutClient == m_layoutClient)
423         return;
424
425     m_layoutClient = layoutClient;
426     CACFLayerSetLayoutCallback(layer(), m_layoutClient ? layoutSublayersProc : 0);    
427 }
428
429 void WKCACFLayer::layoutSublayersProc(CACFLayerRef caLayer) 
430 {
431     WKCACFLayer* layer = WKCACFLayer::layer(caLayer);
432     if (layer && layer->m_layoutClient)
433         layer->m_layoutClient->layoutSublayersOfLayer(layer);
434 }
435
436 #ifndef NDEBUG
437 static void printIndent(int indent)
438 {
439     for ( ; indent > 0; --indent)
440         fprintf(stderr, "  ");
441 }
442
443 static void printTransform(const CATransform3D& transform)
444 {
445     fprintf(stderr, "[%g %g %g %g; %g %g %g %g; %g %g %g %g; %g %g %g %g]",
446                     transform.m11, transform.m12, transform.m13, transform.m14, 
447                     transform.m21, transform.m22, transform.m23, transform.m24, 
448                     transform.m31, transform.m32, transform.m33, transform.m34, 
449                     transform.m41, transform.m42, transform.m43, transform.m44);
450 }
451
452 void WKCACFLayer::printTree() const
453 {
454     // Print heading info
455     CGRect rootBounds = bounds();
456     fprintf(stderr, "\n\n** Render tree at time %g (bounds %g, %g %gx%g) **\n\n", 
457         currentTime(), rootBounds.origin.x, rootBounds.origin.y, rootBounds.size.width, rootBounds.size.height);
458
459     // Print layer tree from the root
460     printLayer(0);
461 }
462
463 void WKCACFLayer::printLayer(int indent) const
464 {
465     CGPoint layerPosition = position();
466     CGPoint layerAnchorPoint = anchorPoint();
467     CGRect layerBounds = bounds();
468     printIndent(indent);
469     fprintf(stderr, "(%s [%g %g %g] [%g %g %g %g] [%g %g %g] superlayer=%p\n",
470         isTransformLayer() ? "transform-layer" : "layer",
471         layerPosition.x, layerPosition.y, zPosition(), 
472         layerBounds.origin.x, layerBounds.origin.y, layerBounds.size.width, layerBounds.size.height,
473         layerAnchorPoint.x, layerAnchorPoint.y, anchorPointZ(), superlayer());
474
475     // Print name if needed
476     String layerName = name();
477     if (!layerName.isEmpty()) {
478         printIndent(indent + 1);
479         fprintf(stderr, "(name %s)\n", layerName.utf8().data());
480     }
481
482     // Print masksToBounds if needed
483     bool layerMasksToBounds = masksToBounds();
484     if (layerMasksToBounds) {
485         printIndent(indent + 1);
486         fprintf(stderr, "(masksToBounds true)\n");
487     }
488
489     // Print opacity if needed
490     float layerOpacity = opacity();
491     if (layerOpacity != 1) {
492         printIndent(indent + 1);
493         fprintf(stderr, "(opacity %hf)\n", layerOpacity);
494     }
495
496     // Print sublayerTransform if needed
497     CATransform3D layerTransform = sublayerTransform();
498     if (!CATransform3DIsIdentity(layerTransform)) {
499         printIndent(indent + 1);
500         fprintf(stderr, "(sublayerTransform ");
501         printTransform(layerTransform);
502         fprintf(stderr, ")\n");
503     }
504
505     // Print transform if needed
506     layerTransform = transform();
507     if (!CATransform3DIsIdentity(layerTransform)) {
508         printIndent(indent + 1);
509         fprintf(stderr, "(transform ");
510         printTransform(layerTransform);
511         fprintf(stderr, ")\n");
512     }
513
514     // Print contents if needed
515     CFTypeRef layerContents = contents();
516     if (layerContents) {
517         if (CFGetTypeID(layerContents) == CGImageGetTypeID()) {
518             CGImageRef imageContents = static_cast<CGImageRef>(const_cast<void*>(layerContents));
519             printIndent(indent + 1);
520             fprintf(stderr, "(contents (image [%d %d]))\n",
521                 CGImageGetWidth(imageContents), CGImageGetHeight(imageContents));
522         }
523     }
524
525     // Print sublayers if needed
526     int n = sublayerCount();
527     if (n > 0) {
528         printIndent(indent + 1);
529         fprintf(stderr, "(sublayers\n");
530         for (int i = 0; i < n; ++i)
531             internalSublayerAtIndex(i)->printLayer(indent + 2);
532
533         printIndent(indent + 1);
534         fprintf(stderr, ")\n");
535     }
536
537     printIndent(indent);
538     fprintf(stderr, ")\n");
539 }
540 #endif // #ifndef NDEBUG
541 }
542
543 #endif // USE(ACCELERATED_COMPOSITING)