1 /*
2 * Copyright (C) 2011 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 #include "WKCACFViewLayerTreeHost.h"
28
29 #if USE(ACCELERATED_COMPOSITING)
30
31 #include "PlatformCALayer.h"
32 #include "SoftLinking.h"
33 #include <wtf/CurrentTime.h>
34 #include <wtf/Threading.h>
35
36 typedef struct _CACFLayer* CACFLayerRef;
37
38 namespace WebCore {
39
40 #ifdef DEBUG_ALL
41 SOFT_LINK_DEBUG_LIBRARY(WebKitQuartzCoreAdditions)
42 #else
43 SOFT_LINK_LIBRARY(WebKitQuartzCoreAdditions)
44 #endif
45
46 enum WKCACFViewDrawingDestination {
47 kWKCACFViewDrawingDestinationWindow = 0,
48 kWKCACFViewDrawingDestinationImage,
49 };
50 typedef enum WKCACFViewDrawingDestination WKCACFViewDrawingDestination;
51
52 SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewCreate, WKCACFViewRef, __cdecl, (WKCACFViewDrawingDestination destination), (destination))
53 SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewSetLayer, void, __cdecl, (WKCACFViewRef view, CACFLayerRef layer), (view, layer))
54 SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewUpdate, void, __cdecl, (WKCACFViewRef view, HWND window, const CGRect* bounds), (view, window, bounds))
55 SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewCanDraw, bool, __cdecl, (WKCACFViewRef view), (view))
56 SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewDraw, void, __cdecl, (WKCACFViewRef view), (view))
57 SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewFlushContext, void, __cdecl, (WKCACFViewRef view), (view))
58 SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewInvalidateRects, void, __cdecl, (WKCACFViewRef view, const CGRect rects[], size_t count), (view, rects, count))
59 typedef void (*WKCACFViewContextDidChangeCallback)(WKCACFViewRef view, void* info);
60 SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewSetContextDidChangeCallback, void, __cdecl, (WKCACFViewRef view, WKCACFViewContextDidChangeCallback callback, void* info), (view, callback, info))
61 SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewGetLastCommitTime, CFTimeInterval, __cdecl, (WKCACFViewRef view), (view))
62 SOFT_LINK(WebKitQuartzCoreAdditions, WKCACFViewSetContextUserData, void, __cdecl, (WKCACFViewRef view, void* userData), (view, userData))
63
create()64 PassRefPtr<WKCACFViewLayerTreeHost> WKCACFViewLayerTreeHost::create()
65 {
66 if (!WebKitQuartzCoreAdditionsLibrary())
67 return 0;
68
69 return adoptRef(new WKCACFViewLayerTreeHost);
70 }
71
WKCACFViewLayerTreeHost()72 WKCACFViewLayerTreeHost::WKCACFViewLayerTreeHost()
73 : m_view(AdoptCF, WKCACFViewCreate(kWKCACFViewDrawingDestinationWindow))
74 , m_viewNeedsUpdate(true)
75 {
76 }
77
updateViewIfNeeded()78 void WKCACFViewLayerTreeHost::updateViewIfNeeded()
79 {
80 if (!m_viewNeedsUpdate)
81 return;
82 m_viewNeedsUpdate = false;
83
84 CGRect layerBounds = rootLayer()->bounds();
85
86 CGRect bounds = this->bounds();
87 WKCACFViewUpdate(m_view.get(), window(), &bounds);
88
89 if (CGRectEqualToRect(layerBounds, rootLayer()->bounds()))
90 return;
91
92 // Flush the context so the layer's rendered bounds will match our bounds.
93 flushContext();
94 }
95
contextDidChangeCallback(WKCACFViewRef view,void * info)96 void WKCACFViewLayerTreeHost::contextDidChangeCallback(WKCACFViewRef view, void* info)
97 {
98 ASSERT_ARG(view, view);
99 ASSERT_ARG(info, info);
100
101 WKCACFViewLayerTreeHost* host = static_cast<WKCACFViewLayerTreeHost*>(info);
102 ASSERT_ARG(view, view == host->m_view);
103 host->contextDidChange();
104 }
105
contextDidChange()106 void WKCACFViewLayerTreeHost::contextDidChange()
107 {
108 // This should only be called on a background thread when no changes have actually
109 // been committed to the context, eg. when a video frame has been added to an image
110 // queue, so return without triggering animations etc.
111 if (!isMainThread())
112 return;
113
114 // Tell the WKCACFView to start rendering now that we have some contents to render.
115 updateViewIfNeeded();
116
117 CACFLayerTreeHost::contextDidChange();
118 }
119
initializeContext(void * userData,PlatformCALayer * layer)120 void WKCACFViewLayerTreeHost::initializeContext(void* userData, PlatformCALayer* layer)
121 {
122 WKCACFViewSetContextUserData(m_view.get(), userData);
123 WKCACFViewSetLayer(m_view.get(), layer->platformLayer());
124 WKCACFViewSetContextDidChangeCallback(m_view.get(), contextDidChangeCallback, this);
125 }
126
resize()127 void WKCACFViewLayerTreeHost::resize()
128 {
129 m_viewNeedsUpdate = true;
130 }
131
createRenderer()132 bool WKCACFViewLayerTreeHost::createRenderer()
133 {
134 updateViewIfNeeded();
135 return WKCACFViewCanDraw(m_view.get());
136 }
137
destroyRenderer()138 void WKCACFViewLayerTreeHost::destroyRenderer()
139 {
140 m_viewNeedsUpdate = true;
141 WKCACFViewUpdate(m_view.get(), 0, 0);
142 WKCACFViewSetContextUserData(m_view.get(), 0);
143 WKCACFViewSetLayer(m_view.get(), 0);
144 WKCACFViewSetContextDidChangeCallback(m_view.get(), 0, 0);
145
146 CACFLayerTreeHost::destroyRenderer();
147 }
148
lastCommitTime() const149 CFTimeInterval WKCACFViewLayerTreeHost::lastCommitTime() const
150 {
151 return WKCACFViewGetLastCommitTime(m_view.get());
152 }
153
flushContext()154 void WKCACFViewLayerTreeHost::flushContext()
155 {
156 WKCACFViewFlushContext(m_view.get());
157 }
158
paint()159 void WKCACFViewLayerTreeHost::paint()
160 {
161 updateViewIfNeeded();
162 CACFLayerTreeHost::paint();
163 }
164
render(const Vector<CGRect> & dirtyRects)165 void WKCACFViewLayerTreeHost::render(const Vector<CGRect>& dirtyRects)
166 {
167 WKCACFViewInvalidateRects(m_view.get(), dirtyRects.data(), dirtyRects.size());
168 WKCACFViewDraw(m_view.get());
169 }
170
171 } // namespace WebCore
172
173 #endif // USE(ACCELERATED_COMPOSITING)
174