[Win][PAL] Move WebCoreHeaderDetection.h to PAL
[WebKit-https.git] / Source / WebCore / platform / graphics / ca / win / PlatformCALayerWinInternal.cpp
1 /*
2  * Copyright (C) 2011, 2015 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 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 #include "PlatformCALayerWinInternal.h"
29
30 #if USE(CA)
31
32 #include "FontCascade.h"
33 #include "GraphicsContext.h"
34 #include "PlatformCALayer.h"
35 #include "TileController.h"
36 #include "TiledBacking.h"
37 #include <QuartzCore/CACFLayer.h>
38 #include <wtf/MainThread.h>
39
40 using namespace std;
41 using namespace WebCore;
42
43 PlatformCALayerWinInternal::PlatformCALayerWinInternal(PlatformCALayer* owner)
44     : m_owner(owner)
45 {
46 }
47
48 PlatformCALayerWinInternal::~PlatformCALayerWinInternal()
49 {
50 }
51
52 struct DisplayOnMainThreadContext {
53     RetainPtr<CACFLayerRef> layer;
54     RetainPtr<CGContextRef> context;
55
56     DisplayOnMainThreadContext(CACFLayerRef caLayer, CGContextRef caContext)
57         : layer(caLayer)
58         , context(caContext)
59     {
60     }
61 };
62
63 static void redispatchOnMainQueue(void* context)
64 {
65     ASSERT(isMainThread());
66     std::unique_ptr<DisplayOnMainThreadContext> retainedContext(reinterpret_cast<DisplayOnMainThreadContext*>(context));
67     if (!retainedContext)
68         return;
69
70     PlatformCALayerWinInternal* self = static_cast<PlatformCALayerWinInternal*>(CACFLayerGetUserData(retainedContext->layer.get()));
71
72     self->displayCallback(retainedContext->layer.get(), retainedContext->context.get());
73 }
74
75 static bool repaintCountersAreDrawnByGridController(PlatformCALayer::LayerType layerType)
76 {
77     return layerType == PlatformCALayer::LayerTypeTiledBackingTileLayer;
78 }
79
80 void PlatformCALayerWinInternal::displayCallback(CACFLayerRef caLayer, CGContextRef context)
81 {
82     if (!isMainThread()) {
83         dispatch_async_f(dispatch_get_main_queue(), new DisplayOnMainThreadContext(caLayer, context), redispatchOnMainQueue);
84         return;
85     }
86     
87     if (!owner() || !owner()->owner())
88         return;
89
90     CGContextSaveGState(context);
91
92     CGRect layerBounds = owner()->bounds();
93     PlatformCALayer::LayerType layerType = owner()->layerType();
94
95     PlatformCALayerClient* client = owner()->owner();
96     GraphicsLayer::CompositingCoordinatesOrientation orientation = client->platformCALayerContentsOrientation();
97
98     PlatformCALayer::flipContext(context, layerBounds.size.height);
99
100     GraphicsContext graphicsContext(context);
101
102     // It's important to get the clip from the context, because it may be significantly
103     // smaller than the layer bounds (e.g. tiled layers)
104     CGRect clipBounds = CGContextGetClipBoundingBox(context);
105     IntRect clip(enclosingIntRect(clipBounds));
106     client->platformCALayerPaintContents(owner(), graphicsContext, clip, GraphicsLayerPaintNormal);
107
108     if (client->platformCALayerShowRepaintCounter(owner())
109         && !repaintCountersAreDrawnByGridController(layerType)) {
110         int drawCount = client->platformCALayerIncrementRepaintCount(owner());
111         drawRepaintCounters(caLayer, context, layerBounds, drawCount);
112     }
113
114     CGContextRestoreGState(context);
115
116     client->platformCALayerLayerDidDisplay(owner());
117 }
118
119 void PlatformCALayerWinInternal::drawRepaintCounters(CACFLayerRef caLayer, CGContextRef context, CGRect layerBounds, int drawCount)
120 {
121     // We always update the repaint count, but we do not paint it for layers that
122     // only contain tiled backing layers. Those report their repaint counts themselves.
123     if (!owner() || owner()->usesTiledBackingLayer())
124         return;
125
126     CGColorRef backgroundColor = nullptr;
127     // Make the background of the counter the same as the border color,
128     // unless there is no border, then make it red
129     float borderWidth = CACFLayerGetBorderWidth(caLayer);
130     if (borderWidth > 0)
131         backgroundColor = CACFLayerGetBorderColor(caLayer);
132     else
133         backgroundColor = cachedCGColor(Color(255, 0, 0));
134
135     PlatformCALayer::drawRepaintIndicator(context, owner(), drawCount, backgroundColor);
136 }
137
138 void PlatformCALayerWinInternal::internalSetNeedsDisplay(const FloatRect* dirtyRect)
139 {
140     if (dirtyRect) {
141         CGRect rect = *dirtyRect;
142         CACFLayerSetNeedsDisplay(owner()->platformLayer(), &rect);
143     } else
144         CACFLayerSetNeedsDisplay(owner()->platformLayer(), nullptr);
145 }
146
147 void PlatformCALayerWinInternal::setNeedsDisplay()
148 {
149     internalSetNeedsDisplay(nullptr);
150 }
151
152 void PlatformCALayerWinInternal::setNeedsDisplayInRect(const FloatRect& dirtyRect)
153 {
154     if (!owner())
155         return;
156
157     ASSERT(owner()->layerType() != PlatformCALayer::LayerTypeTiledBackingLayer);
158
159     if (owner()->owner()) {
160         if (owner()->owner()->platformCALayerShowRepaintCounter(owner())) {
161             FloatRect layerBounds = owner()->bounds();
162             FloatRect repaintCounterRect = layerBounds;
163
164             // We assume a maximum of 4 digits and a font size of 18.
165             repaintCounterRect.setWidth(80);
166             repaintCounterRect.setHeight(22);
167             if (owner()->owner()->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown)
168                 repaintCounterRect.setY(layerBounds.height() - (layerBounds.y() + repaintCounterRect.height()));
169             internalSetNeedsDisplay(&repaintCounterRect);
170         }
171         if (owner()->owner()->platformCALayerContentsOrientation() == WebCore::GraphicsLayer::CompositingCoordinatesTopDown) {
172             FloatRect flippedDirtyRect = dirtyRect;
173             flippedDirtyRect.setY(owner()->bounds().height() - (flippedDirtyRect.y() + flippedDirtyRect.height()));
174             internalSetNeedsDisplay(&flippedDirtyRect);
175             return;
176         }
177     }
178
179     internalSetNeedsDisplay(&dirtyRect);
180
181     owner()->setNeedsCommit();
182 }
183
184 void PlatformCALayerWinInternal::setSublayers(const PlatformCALayerList& list)
185 {
186     // Remove all the current sublayers and add the passed layers
187     CACFLayerSetSublayers(owner()->platformLayer(), 0);
188
189     // Perform removeFromSuperLayer in a separate pass. CACF requires superlayer to
190     // be null or CACFLayerInsertSublayer silently fails.
191     for (size_t i = 0; i < list.size(); i++)
192         CACFLayerRemoveFromSuperlayer(list[i]->platformLayer());
193
194     for (size_t i = 0; i < list.size(); i++)
195         CACFLayerInsertSublayer(owner()->platformLayer(), list[i]->platformLayer(), i);
196
197     owner()->setNeedsCommit();
198 }
199
200 void PlatformCALayerWinInternal::getSublayers(PlatformCALayerList& list) const
201 {
202     CFArrayRef sublayers = CACFLayerGetSublayers(owner()->platformLayer());
203     if (!sublayers) {
204         list.clear();
205         return;
206     }
207
208     size_t count = CFArrayGetCount(sublayers);
209
210     list.resize(count);
211     for (size_t arrayIndex = 0; arrayIndex < count; ++arrayIndex)
212         list[arrayIndex] = PlatformCALayer::platformCALayer(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, arrayIndex)));
213 }
214
215 void PlatformCALayerWinInternal::removeAllSublayers()
216 {
217     CACFLayerSetSublayers(owner()->platformLayer(), nullptr);
218     owner()->setNeedsCommit();
219 }
220
221 void PlatformCALayerWinInternal::insertSublayer(PlatformCALayer& layer, size_t index)
222 {
223     index = min(index, sublayerCount());
224
225     layer.removeFromSuperlayer();
226     CACFLayerInsertSublayer(owner()->platformLayer(), layer.platformLayer(), index);
227     owner()->setNeedsCommit();
228 }
229
230 size_t PlatformCALayerWinInternal::sublayerCount() const
231 {
232     CFArrayRef sublayers = CACFLayerGetSublayers(owner()->platformLayer());
233     return sublayers ? CFArrayGetCount(sublayers) : 0;
234 }
235
236 int PlatformCALayerWinInternal::indexOfSublayer(const PlatformCALayer* reference)
237 {
238     CACFLayerRef ref = reference->platformLayer();
239     if (!ref)
240         return -1;
241
242     CFArrayRef sublayers = CACFLayerGetSublayers(owner()->platformLayer());
243     if (!sublayers)
244         return -1;
245
246     size_t n = CFArrayGetCount(sublayers);
247
248     for (size_t i = 0; i < n; ++i) {
249         if (CFArrayGetValueAtIndex(sublayers, i) == ref)
250             return i;
251     }
252
253     return -1;
254 }
255
256 PlatformCALayer* PlatformCALayerWinInternal::sublayerAtIndex(int index) const
257 {
258     CFArrayRef sublayers = CACFLayerGetSublayers(owner()->platformLayer());
259     if (!sublayers || index < 0 || CFArrayGetCount(sublayers) <= index)
260         return nullptr;
261     
262     return PlatformCALayer::platformCALayer(static_cast<CACFLayerRef>(const_cast<void*>(CFArrayGetValueAtIndex(sublayers, index))));
263 }
264
265 void PlatformCALayerWinInternal::setBounds(const FloatRect& rect)
266 {
267     if (CGRectEqualToRect(rect, owner()->bounds()))
268         return;
269
270     CACFLayerSetBounds(owner()->platformLayer(), rect);
271     owner()->setNeedsCommit();
272 }
273
274 void PlatformCALayerWinInternal::setFrame(const FloatRect& rect)
275 {
276     CGRect oldFrame = CACFLayerGetFrame(owner()->platformLayer());
277     if (CGRectEqualToRect(rect, oldFrame))
278         return;
279
280     CACFLayerSetFrame(owner()->platformLayer(), rect);
281     owner()->setNeedsCommit();
282 }
283
284 bool PlatformCALayerWinInternal::isOpaque() const
285 {
286     return CACFLayerIsOpaque(owner()->platformLayer());
287 }
288
289 void PlatformCALayerWinInternal::setOpaque(bool value)
290 {
291     CACFLayerSetOpaque(owner()->platformLayer(), value);
292 }
293
294 float PlatformCALayerWinInternal::contentsScale() const
295 {
296 #if HAVE(CACFLAYER_SETCONTENTSSCALE)
297     return CACFLayerGetContentsScale(owner()->platformLayer());
298 #else
299     return 1.0f;
300 #endif
301 }
302
303 void PlatformCALayerWinInternal::setContentsScale(float scaleFactor)
304 {
305 #if HAVE(CACFLAYER_SETCONTENTSSCALE)
306     CACFLayerSetContentsScale(owner()->platformLayer(), scaleFactor);
307 #endif
308 }
309
310 void PlatformCALayerWinInternal::setBorderWidth(float value)
311 {
312     CACFLayerSetBorderWidth(owner()->platformLayer(), value);
313 }
314
315 void PlatformCALayerWinInternal::setBorderColor(const Color& value)
316 {
317     CGFloat components[4] = { 0, 0, 0, 0 };
318     RetainPtr<CGColorSpaceRef> colorSpace = adoptCF(CGColorSpaceCreateDeviceRGB());
319
320     if (value.isValid())
321         value.getRGBA(components[0], components[1], components[2], components[3]);
322
323     RetainPtr<CGColorRef> color = adoptCF(CGColorCreate(colorSpace.get(), components));
324
325     CACFLayerSetBorderColor(owner()->platformLayer(), color.get());
326 }
327
328 #endif