Remove uses of CACFContextRef and CARender* from WebCore
[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 <WebKitSystemInterface/WebKitSystemInterface.h>
34 #include <stdio.h>
35 #include <wtf/CurrentTime.h>
36 #include <wtf/text/CString.h>
37
38 namespace WebCore {
39
40 using namespace std;
41
42 static void displayCallback(CACFLayerRef layer, CGContextRef context)
43 {
44     ASSERT_ARG(layer, WKCACFLayer::layer(layer));
45     WKCACFLayer::layer(layer)->drawInContext(context);
46 }
47
48 static CFStringRef toCACFLayerType(WKCACFLayer::LayerType type)
49 {
50     switch (type) {
51     case WKCACFLayer::Layer: return kCACFLayer;
52     case WKCACFLayer::TransformLayer: return kCACFTransformLayer;
53     default: return 0;
54     }
55 }
56
57 static CFStringRef toCACFContentsGravityType(WKCACFLayer::ContentsGravityType type)
58 {
59     switch (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;
72     default: return 0;
73     }
74 }
75
76 static WKCACFLayer::ContentsGravityType fromCACFContentsGravityType(CFStringRef string)
77 {
78     if (CFEqual(string, kCACFGravityTop))
79         return WKCACFLayer::Top;
80
81     if (CFEqual(string, kCACFGravityBottom))
82         return WKCACFLayer::Bottom;
83
84     if (CFEqual(string, kCACFGravityLeft))
85         return WKCACFLayer::Left;
86
87     if (CFEqual(string, kCACFGravityRight))
88         return WKCACFLayer::Right;
89
90     if (CFEqual(string, kCACFGravityTopLeft))
91         return WKCACFLayer::TopLeft;
92
93     if (CFEqual(string, kCACFGravityTopRight))
94         return WKCACFLayer::TopRight;
95
96     if (CFEqual(string, kCACFGravityBottomLeft))
97         return WKCACFLayer::BottomLeft;
98
99     if (CFEqual(string, kCACFGravityBottomRight))
100         return WKCACFLayer::BottomRight;
101
102     if (CFEqual(string, kCACFGravityResize))
103         return WKCACFLayer::Resize;
104
105     if (CFEqual(string, kCACFGravityResizeAspect))
106         return WKCACFLayer::ResizeAspect;
107
108     if (CFEqual(string, kCACFGravityResizeAspectFill))
109         return WKCACFLayer::ResizeAspectFill;
110
111     return WKCACFLayer::Center;
112 }
113
114 static CFStringRef toCACFFilterType(WKCACFLayer::FilterType type)
115 {
116     switch (type) {
117     case WKCACFLayer::Linear: return kCACFFilterLinear;
118     case WKCACFLayer::Nearest: return kCACFFilterNearest;
119     case WKCACFLayer::Trilinear: return kCACFFilterTrilinear;
120     default: return 0;
121     }
122 }
123
124 static WKCACFLayer::FilterType fromCACFFilterType(CFStringRef string)
125 {
126     if (CFEqual(string, kCACFFilterNearest))
127         return WKCACFLayer::Nearest;
128
129     if (CFEqual(string, kCACFFilterTrilinear))
130         return WKCACFLayer::Trilinear;
131
132     return WKCACFLayer::Linear;
133 }
134
135 PassRefPtr<WKCACFLayer> WKCACFLayer::create(LayerType type)
136 {
137     if (!WKCACFLayerRenderer::acceleratedCompositingAvailable())
138         return 0;
139     return adoptRef(new WKCACFLayer(type));
140 }
141
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.
144
145 WKCACFLayer::WKCACFLayer(LayerType type)
146     : m_layer(AdoptCF, CACFLayerCreate(toCACFLayerType(type)))
147     , m_layoutClient(0)
148     , m_needsDisplayOnBoundsChange(false)
149 {
150     CACFLayerSetUserData(layer(), this);
151     CACFLayerSetDisplayCallback(layer(), displayCallback);
152 }
153
154 WKCACFLayer::~WKCACFLayer()
155 {
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());
158
159     CACFLayerSetUserData(layer(), 0);
160     CACFLayerSetDisplayCallback(layer(), 0);
161 }
162
163 void WKCACFLayer::becomeRootLayerForContext(WKCACFContext* context)
164 {
165     wkCACFContextSetLayer(context, layer());
166     setNeedsCommit();
167 }
168
169 void WKCACFLayer::setNeedsCommit()
170 {
171     WKCACFLayer* root = rootLayer();
172
173     // Call setNeedsRender on the root layer, which will cause a render to 
174     // happen in WKCACFLayerRenderer
175     root->setNeedsRender();
176 }
177
178 bool WKCACFLayer::isTransformLayer() const
179 {
180     return CACFLayerGetClass(layer()) == kCACFTransformLayer;
181 }
182
183 void WKCACFLayer::addSublayer(PassRefPtr<WKCACFLayer> sublayer)
184 {
185     insertSublayer(sublayer, sublayerCount());
186 }
187
188 void WKCACFLayer::internalInsertSublayer(PassRefPtr<WKCACFLayer> sublayer, size_t index)
189 {
190     index = min(index, sublayerCount());
191     sublayer->removeFromSuperlayer();
192     CACFLayerInsertSublayer(layer(), sublayer->layer(), index);
193     setNeedsCommit();
194 }
195
196 void WKCACFLayer::insertSublayerAboveLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
197 {
198     if (!reference) {
199         insertSublayer(sublayer, 0);
200         return;
201     }
202
203     int referenceIndex = internalIndexOfSublayer(reference);
204     if (referenceIndex == -1) {
205         addSublayer(sublayer);
206         return;
207     }
208
209     insertSublayer(sublayer, referenceIndex + 1);
210 }
211
212 void WKCACFLayer::insertSublayerBelowLayer(PassRefPtr<WKCACFLayer> sublayer, const WKCACFLayer* reference)
213 {
214     if (!reference) {
215         insertSublayer(sublayer, 0);
216         return;
217     }
218
219     int referenceIndex = internalIndexOfSublayer(reference);
220     if (referenceIndex == -1) {
221         addSublayer(sublayer);
222         return;
223     }
224
225     insertSublayer(sublayer, referenceIndex);
226 }
227
228 void WKCACFLayer::replaceSublayer(WKCACFLayer* reference, PassRefPtr<WKCACFLayer> newLayer)
229 {
230     ASSERT_ARG(reference, reference);
231     ASSERT_ARG(reference, reference->superlayer() == this);
232
233     if (reference == newLayer)
234         return;
235
236     int referenceIndex = internalIndexOfSublayer(reference);
237     ASSERT(referenceIndex != -1);
238     if (referenceIndex == -1)
239         return;
240
241     reference->removeFromSuperlayer();
242
243     if (newLayer) {
244         newLayer->removeFromSuperlayer();
245         insertSublayer(newLayer, referenceIndex);
246     }
247 }
248
249 size_t WKCACFLayer::internalSublayerCount() const
250 {
251     CFArrayRef sublayers = CACFLayerGetSublayers(layer());
252     return sublayers ? CFArrayGetCount(sublayers) : 0;
253 }
254
255 void  WKCACFLayer::adoptSublayers(WKCACFLayer* source)
256 {
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();
261
262     for (size_t i = 0; i < n; ++i)
263         sublayers.append(source->internalSublayerAtIndex(i));
264
265     setSublayers(sublayers);
266 }
267
268 void WKCACFLayer::removeFromSuperlayer()
269 {
270     WKCACFLayer* superlayer = this->superlayer();
271     CACFLayerRemoveFromSuperlayer(layer());
272
273     if (superlayer)
274         superlayer->setNeedsCommit();
275 }
276
277 WKCACFLayer* WKCACFLayer::internalSublayerAtIndex(int index) const
278 {
279     CFArrayRef sublayers = CACFLayerGetSublayers(layer());
280     if (!sublayers || index < 0 || CFArrayGetCount(sublayers) <= index)
281         return 0;
282     
283     return layer(static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, index))));
284 }
285
286 int WKCACFLayer::internalIndexOfSublayer(const WKCACFLayer* reference)
287 {
288     CACFLayerRef ref = reference->layer();
289     if (!ref)
290         return -1;
291
292     CFArrayRef sublayers = CACFLayerGetSublayers(layer());
293     if (!sublayers)
294         return -1;
295
296     size_t n = CFArrayGetCount(sublayers);
297
298     for (size_t i = 0; i < n; ++i)
299         if (CFArrayGetValueAtIndex(sublayers, i) == ref)
300             return i;
301
302     return -1;
303 }
304
305 WKCACFLayer* WKCACFLayer::ancestorOrSelfWithSuperlayer(WKCACFLayer* superlayer) const
306 {
307     WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
308     for (WKCACFLayer* ancestor = this->superlayer(); ancestor; layer = ancestor, ancestor = ancestor->superlayer()) {
309         if (ancestor == superlayer)
310             return layer;
311     }
312     return 0;
313 }
314
315 void WKCACFLayer::setBounds(const CGRect& rect)
316 {
317     if (CGRectEqualToRect(rect, bounds()))
318         return;
319
320     CACFLayerSetBounds(layer(), rect);
321     setNeedsCommit();
322
323     if (m_needsDisplayOnBoundsChange)
324         setNeedsDisplay();
325 }
326
327 void WKCACFLayer::setFrame(const CGRect& rect)
328 {
329     CGRect oldFrame = frame();
330     if (CGRectEqualToRect(rect, oldFrame))
331         return;
332
333     CACFLayerSetFrame(layer(), rect);
334     setNeedsCommit();
335
336     if (m_needsDisplayOnBoundsChange && !CGSizeEqualToSize(rect.size, oldFrame.size))
337         setNeedsDisplay();
338 }
339
340 void WKCACFLayer::setContentsGravity(ContentsGravityType type)
341 {
342     CACFLayerSetContentsGravity(layer(), toCACFContentsGravityType(type));
343     setNeedsCommit();
344 }
345
346 WKCACFLayer::ContentsGravityType WKCACFLayer::contentsGravity() const
347 {
348     return fromCACFContentsGravityType(CACFLayerGetContentsGravity(layer()));
349 }
350
351 void WKCACFLayer::setMagnificationFilter(FilterType type)
352 {
353     CACFLayerSetMagnificationFilter(layer(), toCACFFilterType(type));
354     setNeedsCommit();
355 }
356
357 WKCACFLayer::FilterType WKCACFLayer::magnificationFilter() const
358 {
359     return fromCACFFilterType(CACFLayerGetMagnificationFilter(layer()));
360 }
361
362 void WKCACFLayer::setMinificationFilter(FilterType type)
363 {
364     CACFLayerSetMinificationFilter(layer(), toCACFFilterType(type));
365     setNeedsCommit();
366 }
367
368 WKCACFLayer::FilterType WKCACFLayer::minificationFilter() const
369 {
370     return fromCACFFilterType(CACFLayerGetMinificationFilter(layer()));
371 }
372
373 WKCACFLayer* WKCACFLayer::rootLayer() const
374 {
375     WKCACFLayer* layer = const_cast<WKCACFLayer*>(this);
376     for (WKCACFLayer* superlayer = layer->superlayer(); superlayer; layer = superlayer, superlayer = superlayer->superlayer()) { }
377     return layer;
378 }
379
380 void WKCACFLayer::internalRemoveAllSublayers()
381 {
382     CACFLayerSetSublayers(layer(), 0);
383     setNeedsCommit();
384 }
385
386 void WKCACFLayer::internalSetSublayers(const Vector<RefPtr<WKCACFLayer> >& sublayers)
387 {
388     // Remove all the current sublayers and add the passed layers
389     CACFLayerSetSublayers(layer(), 0);
390
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());
395
396     for (size_t i = 0; i < sublayers.size(); i++)
397         CACFLayerInsertSublayer(layer(), sublayers[i]->layer(), i);
398
399     setNeedsCommit();
400 }
401
402 WKCACFLayer* WKCACFLayer::superlayer() const
403 {
404     CACFLayerRef super = CACFLayerGetSuperlayer(layer());
405     if (!super)
406         return 0;
407     return WKCACFLayer::layer(super);
408 }
409
410 void WKCACFLayer::internalSetNeedsDisplay(const CGRect* dirtyRect)
411 {
412     CACFLayerSetNeedsDisplay(layer(), dirtyRect);
413 }
414
415 void WKCACFLayer::setLayoutClient(WKCACFLayerLayoutClient* layoutClient)
416 {
417     if (layoutClient == m_layoutClient)
418         return;
419
420     m_layoutClient = layoutClient;
421     CACFLayerSetLayoutCallback(layer(), m_layoutClient ? layoutSublayersProc : 0);    
422 }
423
424 void WKCACFLayer::layoutSublayersProc(CACFLayerRef caLayer) 
425 {
426     WKCACFLayer* layer = WKCACFLayer::layer(caLayer);
427     if (layer && layer->m_layoutClient)
428         layer->m_layoutClient->layoutSublayersOfLayer(layer);
429 }
430
431 #ifndef NDEBUG
432 static void printIndent(int indent)
433 {
434     for ( ; indent > 0; --indent)
435         fprintf(stderr, "  ");
436 }
437
438 static void printTransform(const CATransform3D& transform)
439 {
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);
445 }
446
447 void WKCACFLayer::printTree() const
448 {
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);
453
454     // Print layer tree from the root
455     printLayer(0);
456 }
457
458 void WKCACFLayer::printLayer(int indent) const
459 {
460     CGPoint layerPosition = position();
461     CGPoint layerAnchorPoint = anchorPoint();
462     CGRect layerBounds = bounds();
463     printIndent(indent);
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());
469
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());
475     }
476
477     // Print masksToBounds if needed
478     bool layerMasksToBounds = masksToBounds();
479     if (layerMasksToBounds) {
480         printIndent(indent + 1);
481         fprintf(stderr, "(masksToBounds true)\n");
482     }
483
484     // Print opacity if needed
485     float layerOpacity = opacity();
486     if (layerOpacity != 1) {
487         printIndent(indent + 1);
488         fprintf(stderr, "(opacity %hf)\n", layerOpacity);
489     }
490
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");
498     }
499
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");
507     }
508
509     // Print contents if needed
510     CFTypeRef layerContents = contents();
511     if (layerContents) {
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));
517         }
518     }
519
520     // Print sublayers if needed
521     int n = sublayerCount();
522     if (n > 0) {
523         printIndent(indent + 1);
524         fprintf(stderr, "(sublayers\n");
525         for (int i = 0; i < n; ++i)
526             internalSublayerAtIndex(i)->printLayer(indent + 2);
527
528         printIndent(indent + 1);
529         fprintf(stderr, ")\n");
530     }
531
532     printIndent(indent);
533     fprintf(stderr, ")\n");
534 }
535 #endif // #ifndef NDEBUG
536 }
537
538 #endif // USE(ACCELERATED_COMPOSITING)