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