[chromium] Hook WebCompositor interface for input events up to the compositor proper
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCSingleThreadProxy.cpp
1 /*
2  * Copyright (C) 2011 Google 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. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "cc/CCSingleThreadProxy.h"
28
29 #include "GraphicsContext3D.h"
30 #include "LayerRendererChromium.h"
31 #include "TraceEvent.h"
32 #include "cc/CCLayerTreeHost.h"
33 #include "cc/CCMainThreadTask.h"
34 #include "cc/CCScrollController.h"
35 #include <wtf/CurrentTime.h>
36
37 using namespace WTF;
38
39 namespace WebCore {
40
41 PassOwnPtr<CCProxy> CCSingleThreadProxy::create(CCLayerTreeHost* layerTreeHost)
42 {
43     return adoptPtr(new CCSingleThreadProxy(layerTreeHost));
44 }
45
46 CCSingleThreadProxy::CCSingleThreadProxy(CCLayerTreeHost* layerTreeHost)
47     : m_layerTreeHost(layerTreeHost)
48     , m_compositorIdentifier(-1)
49     , m_numFailedRecreateAttempts(0)
50     , m_graphicsContextLost(false)
51     , m_timesRecreateShouldFail(0)
52 {
53     TRACE_EVENT("CCSingleThreadProxy::CCSingleThreadProxy", this, 0);
54     ASSERT(CCProxy::isMainThread());
55 }
56
57 void CCSingleThreadProxy::start()
58 {
59     DebugScopedSetImplThread impl;
60     m_layerTreeHostImpl = m_layerTreeHost->createLayerTreeHostImpl();
61 }
62
63 CCSingleThreadProxy::~CCSingleThreadProxy()
64 {
65     TRACE_EVENT("CCSingleThreadProxy::~CCSingleThreadProxy", this, 0);
66     ASSERT(CCProxy::isMainThread());
67     ASSERT(!m_layerTreeHostImpl && !m_layerTreeHost); // make sure stop() got called.
68 }
69
70 bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect)
71 {
72     ASSERT(CCProxy::isMainThread());
73
74     if (!recreateContextIfNeeded())
75         return false;
76
77     commitIfNeeded();
78
79     if (!doComposite())
80         return false;
81
82     m_layerTreeHostImpl->readback(pixels, rect);
83
84     if (m_layerTreeHostImpl->isContextLost())
85         return false;
86
87     return true;
88 }
89
90 GraphicsContext3D* CCSingleThreadProxy::context()
91 {
92     ASSERT(CCProxy::isMainThread());
93     DebugScopedSetImplThread impl;
94     return m_layerTreeHostImpl->context();
95 }
96
97 void CCSingleThreadProxy::finishAllRendering()
98 {
99     ASSERT(CCProxy::isMainThread());
100     {
101         DebugScopedSetImplThread impl;
102         m_layerTreeHostImpl->finishAllRendering();
103     }
104 }
105
106 bool CCSingleThreadProxy::isStarted() const
107 {
108     ASSERT(CCProxy::isMainThread());
109     return m_layerTreeHostImpl;
110 }
111
112 bool CCSingleThreadProxy::initializeLayerRenderer()
113 {
114     ASSERT(CCProxy::isMainThread());
115     RefPtr<GraphicsContext3D> context = m_layerTreeHost->createLayerTreeHostContext3D();
116     if (!context)
117         return false;
118     ASSERT(context->hasOneRef());
119
120     {
121         DebugScopedSetImplThread impl;
122         bool ok = m_layerTreeHostImpl->initializeLayerRenderer(context);
123         if (ok)
124             m_layerRendererCapabilitiesForMainThread = m_layerTreeHostImpl->layerRendererCapabilities();
125         return ok;
126     }
127 }
128
129 const LayerRendererCapabilities& CCSingleThreadProxy::layerRendererCapabilities() const
130 {
131     // Note: this gets called during the commit by the "impl" thread
132     return m_layerRendererCapabilitiesForMainThread;
133 }
134
135 void CCSingleThreadProxy::loseCompositorContext(int numTimes)
136 {
137     m_graphicsContextLost = true;
138     m_timesRecreateShouldFail = numTimes - 1;
139 }
140
141 void CCSingleThreadProxy::setNeedsCommit()
142 {
143     ASSERT(CCProxy::isMainThread());
144     // Commit immediately
145     {
146         DebugScopedSetImplThread impl;
147         m_layerTreeHostImpl->beginCommit();
148         m_layerTreeHost->commitToOnCCThread(m_layerTreeHostImpl.get());
149         m_layerTreeHostImpl->commitComplete();
150
151 #if !ASSERT_DISABLED
152         // In the single-threaded case, the scroll deltas should never be
153         // touched on the impl layer tree.
154         OwnPtr<CCScrollUpdateSet> scrollInfo = m_layerTreeHostImpl->processScrollDeltas();
155         ASSERT(!scrollInfo->size());
156 #endif
157     }
158     m_layerTreeHost->commitComplete();
159 }
160
161 void CCSingleThreadProxy::setNeedsCommitThenRedraw()
162 {
163     ASSERT(CCProxy::isMainThread());
164 #if !USE(THREADED_COMPOSITING)
165     m_layerTreeHost->scheduleComposite();
166 #else
167     // Single threaded only works with THREADED_COMPOSITING.
168     CRASH();
169 #endif
170 }
171
172 void CCSingleThreadProxy::setNeedsRedraw()
173 {
174     // FIXME: Once we move render_widget scheduling into this class, we can
175     // treat redraw requests more efficiently than commitAndRedraw requests.
176     setNeedsCommitThenRedraw();
177 }
178
179 void CCSingleThreadProxy::stop()
180 {
181     TRACE_EVENT("CCSingleThreadProxy::stop", this, 0);
182     ASSERT(CCProxy::isMainThread());
183     {
184         DebugScopedSetImplThread impl;
185         m_layerTreeHost->deleteContentsTexturesOnCCThread(m_layerTreeHostImpl->contentsTextureAllocator());
186         m_layerTreeHostImpl.clear();
187     }
188     m_layerTreeHost = 0;
189 }
190
191 #if !USE(THREADED_COMPOSITING)
192 // Called by the legacy scheduling path (e.g. where render_widget does the scheduling)
193 void CCSingleThreadProxy::compositeImmediately()
194 {
195     if (!recreateContextIfNeeded())
196         return;
197
198     commitIfNeeded();
199
200     if (doComposite())
201         m_layerTreeHostImpl->present();
202 }
203 #endif
204
205
206 bool CCSingleThreadProxy::recreateContextIfNeeded()
207 {
208     ASSERT(CCProxy::isMainThread());
209     if (!m_graphicsContextLost)
210         return true;
211     RefPtr<GraphicsContext3D> context;
212     if (!m_timesRecreateShouldFail)
213         context = m_layerTreeHost->createLayerTreeHostContext3D();
214     else
215         m_timesRecreateShouldFail--;
216
217     if (context) {
218         ASSERT(context->hasOneRef());
219         bool ok;
220         {
221             DebugScopedSetImplThread impl;
222             m_layerTreeHost->deleteContentsTexturesOnCCThread(m_layerTreeHostImpl->contentsTextureAllocator());
223             ok = m_layerTreeHostImpl->initializeLayerRenderer(context);
224             if (ok)
225                 m_layerRendererCapabilitiesForMainThread = m_layerTreeHostImpl->layerRendererCapabilities();
226         }
227         if (ok) {
228             m_layerTreeHost->didRecreateGraphicsContext(true);
229             m_graphicsContextLost = false;
230             return true;
231         }
232     }
233
234     // Tolerate a certain number of recreation failures to work around races
235     // in the context-lost machinery.
236     m_numFailedRecreateAttempts++;
237     if (m_numFailedRecreateAttempts < 5) {
238         setNeedsCommitThenRedraw();
239         return false;
240     }
241
242     // We have tried too many times to recreate the context. Tell the host to fall
243     // back to software rendering.
244     m_layerTreeHost->didRecreateGraphicsContext(false);
245     return false;
246 }
247
248 void CCSingleThreadProxy::commitIfNeeded()
249 {
250     ASSERT(CCProxy::isMainThread());
251
252     // Update
253     m_layerTreeHost->updateLayers();
254
255     // Commit
256     {
257         DebugScopedSetImplThread impl;
258         m_layerTreeHostImpl->beginCommit();
259         m_layerTreeHost->commitToOnCCThread(m_layerTreeHostImpl.get());
260         m_layerTreeHostImpl->commitComplete();
261     }
262     m_layerTreeHost->commitComplete();
263 }
264
265 bool CCSingleThreadProxy::doComposite()
266 {
267     ASSERT(!m_graphicsContextLost);
268
269     {
270       DebugScopedSetImplThread impl;
271       m_layerTreeHostImpl->drawLayers();
272       if (m_layerTreeHostImpl->isContextLost()) {
273           // Trying to recover the context right here will not work if GPU process
274           // died. This is because GpuChannelHost::OnErrorMessage will only be
275           // called at the next iteration of the message loop, reverting our
276           // recovery attempts here. Instead, we detach the root layer from the
277           // renderer, recreate the renderer at the next message loop iteration
278           // and request a repaint yet again.
279           m_graphicsContextLost = true;
280           m_numFailedRecreateAttempts = 0;
281           setNeedsCommitThenRedraw();
282           return false;
283       }
284     }
285
286     return true;
287 }
288
289 }