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