[chromium] Implement CCThread in terms of WebThread
[WebKit-https.git] / Source / WebCore / platform / graphics / chromium / cc / CCLayerTreeHost.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/CCLayerTreeHost.h"
28
29 #include "LayerChromium.h"
30 #include "LayerPainterChromium.h"
31 #include "LayerRendererChromium.h"
32 #include "NonCompositedContentHost.h"
33 #include "PlatformColor.h"
34 #include "TraceEvent.h"
35 #include "cc/CCLayerTreeHostCommitter.h"
36 #include "cc/CCLayerTreeHostImpl.h"
37
38 namespace WebCore {
39
40 PassRefPtr<CCLayerTreeHost> CCLayerTreeHost::create(CCLayerTreeHostClient* client, const CCSettings& settings)
41 {
42     RefPtr<CCLayerTreeHost> layerTreeHost = adoptRef(new CCLayerTreeHost(client, settings));
43     if (!layerTreeHost->initialize())
44         return 0;
45     return layerTreeHost;
46 }
47
48 CCLayerTreeHost::CCLayerTreeHost(CCLayerTreeHostClient* client, const CCSettings& settings)
49     : m_recreatingGraphicsContext(false)
50     , m_maxTextureSize(0)
51     , m_contextSupportsMapSub(false)
52     , m_animating(false)
53     , m_client(client)
54     , m_frameNumber(0)
55     , m_nonCompositedContentHost(NonCompositedContentHost::create(m_client->createRootLayerPainter()))
56     , m_settings(settings)
57 {
58 }
59
60 bool CCLayerTreeHost::initialize()
61 {
62     m_layerRenderer = createLayerRenderer();
63     if (!m_layerRenderer)
64         return false;
65
66     // FIXME: In the threaded case, these values will need to be initialized
67     // by something other than m_layerRenderer.
68     m_maxTextureSize = m_layerRenderer->maxTextureSize();
69     m_bestTextureFormat = PlatformColor::bestTextureFormat(m_layerRenderer->context());
70     m_contextSupportsMapSub = m_layerRenderer->contextSupportsMapSub();
71
72     m_rootLayer = GraphicsLayer::create(0);
73 #ifndef NDEBUG
74     m_rootLayer->setName("root layer");
75 #endif
76     m_rootLayer->setDrawsContent(false);
77
78     m_rootLayer->addChild(m_nonCompositedContentHost->graphicsLayer());
79
80
81 #if USE(THREADED_COMPOSITING)
82     m_proxy = CCLayerTreeHostImplProxy::create(this);
83     ASSERT(m_proxy->isStarted());
84     m_proxy->setNeedsCommitAndRedraw();
85 #endif
86
87     return true;
88 }
89
90 CCLayerTreeHost::~CCLayerTreeHost()
91 {
92     TRACE_EVENT("CCLayerTreeHost::~CCLayerTreeHost", this, 0);
93 #if USE(THREADED_COMPOSITING)
94     m_proxy->stop();
95     m_proxy.clear();
96 #endif
97 }
98
99 void CCLayerTreeHost::beginCommit()
100 {
101 }
102
103 void CCLayerTreeHost::commitComplete()
104 {
105     m_frameNumber++;
106 }
107
108 void CCLayerTreeHost::animateAndLayout(double frameBeginTime)
109 {
110     m_animating = true;
111     m_client->animateAndLayout(frameBeginTime);
112     m_animating = false;
113 }
114
115 PassOwnPtr<CCLayerTreeHostCommitter> CCLayerTreeHost::createLayerTreeHostCommitter()
116 {
117     // FIXME: only called in threading case, fix when possible.
118     return nullptr;
119 }
120
121 PassOwnPtr<CCLayerTreeHostImpl> CCLayerTreeHost::createLayerTreeHostImpl(CCLayerTreeHostImplClient* client)
122 {
123     RefPtr<LayerRendererChromium> renderer(m_layerRenderer);
124     return CCLayerTreeHostImpl::create(client, renderer);
125 }
126
127 GraphicsContext3D* CCLayerTreeHost::context()
128 {
129     return m_layerRenderer->context();
130 }
131
132 void CCLayerTreeHost::compositeAndReadback(void *pixels, const IntRect& rect)
133 {
134 #if USE(THREADED_COMPOSITING)
135     // FIXME: need to implement this.
136 #else
137     doComposite();
138     m_layerRenderer->getFramebufferPixels(pixels, rect);
139 #endif
140 }
141
142 void CCLayerTreeHost::finishAllRendering()
143 {
144 #if USE(THREADED_COMPOSITING)
145     // FIXME: need to implement this.
146 #else
147     m_layerRenderer->finish();
148 #endif
149 }
150
151 void CCLayerTreeHost::invalidateRootLayerRect(const IntRect& dirtyRect)
152 {
153     m_nonCompositedContentHost->invalidateRect(dirtyRect);
154 }
155
156 void CCLayerTreeHost::setNeedsCommitAndRedraw()
157 {
158 #if USE(THREADED_COMPOSITING)
159     TRACE_EVENT("CCLayerTreeHost::setNeedsRedraw", this, 0);
160     m_proxy->setNeedsCommitAndRedraw();
161 #else
162     m_client->scheduleComposite();
163 #endif
164 }
165
166 void CCLayerTreeHost::setNeedsRedraw()
167 {
168 #if USE(THREADED_COMPOSITING)
169     TRACE_EVENT("CCLayerTreeHost::setNeedsRedraw", this, 0);
170     m_proxy->setNeedsRedraw();
171 #else
172     m_client->scheduleComposite();
173 #endif
174 }
175
176 void CCLayerTreeHost::setRootLayer(GraphicsLayer* layer)
177 {
178     m_nonCompositedContentHost->graphicsLayer()->removeAllChildren();
179     m_nonCompositedContentHost->invalidateEntireLayer();
180     if (layer) {
181         m_nonCompositedContentHost->graphicsLayer()->addChild(layer);
182         layer->platformLayer()->setLayerRenderer(m_layerRenderer.get());
183     }
184
185 }
186
187 void CCLayerTreeHost::setViewport(const IntSize& viewportSize, const IntSize& contentsSize, const IntPoint& scrollPosition)
188 {
189     bool visibleRectChanged = m_viewportSize != viewportSize;
190
191     m_viewportSize = viewportSize;
192     m_nonCompositedContentHost->setScrollPosition(scrollPosition);
193     m_nonCompositedContentHost->graphicsLayer()->setSize(contentsSize);
194
195     if (visibleRectChanged) {
196         m_nonCompositedContentHost->invalidateEntireLayer();
197         if (m_layerRenderer)
198             m_layerRenderer->viewportChanged();
199     }
200
201     setNeedsCommitAndRedraw();
202 }
203
204 void CCLayerTreeHost::setVisible(bool visible)
205 {
206 #if !USE(THREADED_COMPOSITING)
207     if (!visible)
208         m_layerRenderer->releaseTextures();
209 #endif
210 }
211
212 PassRefPtr<LayerRendererChromium> CCLayerTreeHost::createLayerRenderer()
213 {
214     // GraphicsContext3D::create might fail and return 0, in that case fall back to software.
215     RefPtr<GraphicsContext3D> context = m_client->createLayerTreeHostContext3D();
216     if (!context)
217         return 0;
218
219     // Actually create the renderer.
220     RefPtr<LayerRendererChromium> layerRenderer = LayerRendererChromium::create(this, context);
221
222     // If creation failed, and we had asked for accelerated painting, disable accelerated painting
223     // and try creating the renderer again.
224     if (m_settings.acceleratePainting && !layerRenderer) {
225         m_settings.acceleratePainting = false;
226         layerRenderer = LayerRendererChromium::create(this, context);
227     }
228
229     return layerRenderer;
230 }
231
232 #if !USE(THREADED_COMPOSITING)
233 void CCLayerTreeHost::doComposite()
234 {
235 #ifndef NDEBUG
236     CCLayerTreeHostImplProxy::setImplThread(true);
237 #endif
238     ASSERT(m_layerRenderer);
239     m_layerRenderer->updateLayers();
240     m_layerRenderer->drawLayers();
241 #ifndef NDEBUG
242     CCLayerTreeHostImplProxy::setImplThread(false);
243 #endif
244 }
245
246 void CCLayerTreeHost::composite(bool finish)
247 {
248     TRACE_EVENT("CCLayerTreeHost::composite", this, 0);
249
250     if (m_recreatingGraphicsContext) {
251         // reallocateRenderer will request a repaint whether or not it succeeded
252         // in creating a new context.
253         reallocateRenderer();
254         m_recreatingGraphicsContext = false;
255         return;
256     }
257
258     // Do not composite if the compositor context is already lost.
259     if (!m_layerRenderer->isCompositorContextLost()) {
260         doComposite();
261
262         // Put result onscreen.
263         m_layerRenderer->present();
264     }
265
266     if (m_layerRenderer->isCompositorContextLost()) {
267         // Trying to recover the context right here will not work if GPU process
268         // died. This is because GpuChannelHost::OnErrorMessage will only be
269         // called at the next iteration of the message loop, reverting our
270         // recovery attempts here. Instead, we detach the root layer from the
271         // renderer, recreate the renderer at the next message loop iteration
272         // and request a repaint yet again.
273         m_recreatingGraphicsContext = true;
274         setNeedsCommitAndRedraw();
275     }
276 }
277
278 void CCLayerTreeHost::reallocateRenderer()
279 {
280     RefPtr<LayerRendererChromium> layerRenderer = createLayerRenderer();
281     if (!layerRenderer) {
282         m_client->didRecreateGraphicsContext(false);
283         return;
284     }
285
286     layerRenderer->setLayerRendererRecursive(m_rootLayer->platformLayer());
287     m_layerRenderer = layerRenderer;
288
289     m_client->didRecreateGraphicsContext(true);
290 }
291 #endif // !USE(THREADED_COMPOSITING)
292
293 }