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