/src/mozilla-central/gfx/webrender_bindings/RendererOGL.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #include "RendererOGL.h" |
8 | | #include "GLContext.h" |
9 | | #include "mozilla/gfx/Logging.h" |
10 | | #include "mozilla/gfx/gfxVars.h" |
11 | | #include "mozilla/layers/CompositorBridgeParent.h" |
12 | | #include "mozilla/layers/CompositorThread.h" |
13 | | #include "mozilla/layers/LayersTypes.h" |
14 | | #include "mozilla/webrender/RenderCompositor.h" |
15 | | #include "mozilla/webrender/RenderTextureHost.h" |
16 | | #include "mozilla/widget/CompositorWidget.h" |
17 | | |
18 | | namespace mozilla { |
19 | | namespace wr { |
20 | | |
21 | | wr::WrExternalImage |
22 | | LockExternalImage(void* aObj, |
23 | | wr::WrExternalImageId aId, |
24 | | uint8_t aChannelIndex, |
25 | | wr::ImageRendering aRendering) |
26 | 0 | { |
27 | 0 | RendererOGL* renderer = reinterpret_cast<RendererOGL*>(aObj); |
28 | 0 | RenderTextureHost* texture = renderer->GetRenderTexture(aId); |
29 | 0 | MOZ_ASSERT(texture); |
30 | 0 | if (!texture) { |
31 | 0 | gfxCriticalNote << "Failed to lock ExternalImage for extId:" << AsUint64(aId); |
32 | 0 | return InvalidToWrExternalImage(); |
33 | 0 | } |
34 | 0 | return texture->Lock(aChannelIndex, renderer->gl(), aRendering); |
35 | 0 | } |
36 | | |
37 | | void UnlockExternalImage(void* aObj, wr::WrExternalImageId aId, uint8_t aChannelIndex) |
38 | 0 | { |
39 | 0 | RendererOGL* renderer = reinterpret_cast<RendererOGL*>(aObj); |
40 | 0 | RenderTextureHost* texture = renderer->GetRenderTexture(aId); |
41 | 0 | MOZ_ASSERT(texture); |
42 | 0 | if (!texture) { |
43 | 0 | return; |
44 | 0 | } |
45 | 0 | texture->Unlock(); |
46 | 0 | } |
47 | | |
48 | | RendererOGL::RendererOGL(RefPtr<RenderThread>&& aThread, |
49 | | UniquePtr<RenderCompositor> aCompositor, |
50 | | wr::WindowId aWindowId, |
51 | | wr::Renderer* aRenderer, |
52 | | layers::CompositorBridgeParent* aBridge) |
53 | | : mThread(aThread) |
54 | | , mCompositor(std::move(aCompositor)) |
55 | | , mRenderer(aRenderer) |
56 | | , mBridge(aBridge) |
57 | | , mWindowId(aWindowId) |
58 | | , mDebugFlags({ 0 }) |
59 | 0 | { |
60 | 0 | MOZ_ASSERT(mThread); |
61 | 0 | MOZ_ASSERT(mCompositor); |
62 | 0 | MOZ_ASSERT(mRenderer); |
63 | 0 | MOZ_ASSERT(mBridge); |
64 | 0 | MOZ_COUNT_CTOR(RendererOGL); |
65 | 0 | } |
66 | | |
67 | | RendererOGL::~RendererOGL() |
68 | 0 | { |
69 | 0 | MOZ_COUNT_DTOR(RendererOGL); |
70 | 0 | if (!mCompositor->gl()->MakeCurrent()) { |
71 | 0 | gfxCriticalNote << "Failed to make render context current during destroying."; |
72 | 0 | // Leak resources! |
73 | 0 | return; |
74 | 0 | } |
75 | 0 | wr_renderer_delete(mRenderer); |
76 | 0 | } |
77 | | |
78 | | wr::WrExternalImageHandler |
79 | | RendererOGL::GetExternalImageHandler() |
80 | 0 | { |
81 | 0 | return wr::WrExternalImageHandler { |
82 | 0 | this, |
83 | 0 | LockExternalImage, |
84 | 0 | UnlockExternalImage, |
85 | 0 | }; |
86 | 0 | } |
87 | | |
88 | | void |
89 | | RendererOGL::Update() |
90 | 0 | { |
91 | 0 | uint32_t flags = gfx::gfxVars::WebRenderDebugFlags(); |
92 | 0 | if (mDebugFlags.mBits != flags) { |
93 | 0 | mDebugFlags.mBits = flags; |
94 | 0 | wr_renderer_set_debug_flags(mRenderer, mDebugFlags); |
95 | 0 | } |
96 | 0 |
|
97 | 0 | if (gl()->MakeCurrent()) { |
98 | 0 | wr_renderer_update(mRenderer); |
99 | 0 | } |
100 | 0 | } |
101 | | |
102 | | static void |
103 | | DoNotifyWebRenderContextPurge(layers::CompositorBridgeParent* aBridge) |
104 | 0 | { |
105 | 0 | aBridge->NotifyWebRenderContextPurge(); |
106 | 0 | } |
107 | | |
108 | | bool |
109 | | RendererOGL::UpdateAndRender(bool aReadback) |
110 | 0 | { |
111 | 0 | uint32_t flags = gfx::gfxVars::WebRenderDebugFlags(); |
112 | 0 | // Disable debug flags during readback |
113 | 0 | if (aReadback) { |
114 | 0 | flags = 0; |
115 | 0 | } |
116 | 0 |
|
117 | 0 | if (mDebugFlags.mBits != flags) { |
118 | 0 | mDebugFlags.mBits = flags; |
119 | 0 | wr_renderer_set_debug_flags(mRenderer, mDebugFlags); |
120 | 0 | } |
121 | 0 |
|
122 | 0 | mozilla::widget::WidgetRenderingContext widgetContext; |
123 | 0 |
|
124 | | #if defined(XP_MACOSX) |
125 | | widgetContext.mGL = mCompositor->gl(); |
126 | | // TODO: we don't have a notion of compositor here. |
127 | | //#elif defined(MOZ_WIDGET_ANDROID) |
128 | | // widgetContext.mCompositor = mCompositor; |
129 | | #endif |
130 | |
|
131 | 0 | if (!mCompositor->GetWidget()->PreRender(&widgetContext)) { |
132 | 0 | // XXX This could cause oom in webrender since pending_texture_updates is not handled. |
133 | 0 | // It needs to be addressed. |
134 | 0 | return false; |
135 | 0 | } |
136 | 0 | // XXX set clear color if MOZ_WIDGET_ANDROID is defined. |
137 | 0 | |
138 | 0 | if (!mCompositor->BeginFrame()) { |
139 | 0 | return false; |
140 | 0 | } |
141 | 0 | |
142 | 0 | wr_renderer_update(mRenderer); |
143 | 0 |
|
144 | 0 | auto size = mCompositor->GetBufferSize(); |
145 | 0 |
|
146 | 0 | if (!wr_renderer_render(mRenderer, size.width, size.height)) { |
147 | 0 | NotifyWebRenderError(WebRenderError::RENDER); |
148 | 0 | } |
149 | 0 |
|
150 | 0 | mCompositor->EndFrame(); |
151 | 0 |
|
152 | 0 | mCompositor->GetWidget()->PostRender(&widgetContext); |
153 | 0 |
|
154 | | #if defined(ENABLE_FRAME_LATENCY_LOG) |
155 | | if (mFrameStartTime) { |
156 | | uint32_t latencyMs = round((TimeStamp::Now() - mFrameStartTime).ToMilliseconds()); |
157 | | printf_stderr("generate frame latencyMs latencyMs %d\n", latencyMs); |
158 | | } |
159 | | // Clear frame start time |
160 | | mFrameStartTime = TimeStamp(); |
161 | | #endif |
162 | |
|
163 | 0 | gl::GLContext* gl = mCompositor->gl(); |
164 | 0 | if (gl->IsSupported(gl::GLFeature::robustness)) { |
165 | 0 | GLenum resetStatus = gl->fGetGraphicsResetStatus(); |
166 | 0 | if (resetStatus == LOCAL_GL_PURGED_CONTEXT_RESET_NV) { |
167 | 0 | layers::CompositorThreadHolder::Loop()->PostTask(NewRunnableFunction( |
168 | 0 | "DoNotifyWebRenderContextPurgeRunnable", |
169 | 0 | &DoNotifyWebRenderContextPurge, |
170 | 0 | mBridge |
171 | 0 | )); |
172 | 0 | } |
173 | 0 | } |
174 | 0 |
|
175 | 0 | // TODO: Flush pending actions such as texture deletions/unlocks and |
176 | 0 | // textureHosts recycling. |
177 | 0 |
|
178 | 0 | return true; |
179 | 0 | } |
180 | | |
181 | | void |
182 | | RendererOGL::Pause() |
183 | 0 | { |
184 | 0 | mCompositor->Pause(); |
185 | 0 | } |
186 | | |
187 | | bool |
188 | | RendererOGL::Resume() |
189 | 0 | { |
190 | 0 | return mCompositor->Resume(); |
191 | 0 | } |
192 | | |
193 | | layers::SyncObjectHost* |
194 | | RendererOGL::GetSyncObject() const |
195 | 0 | { |
196 | 0 | return mCompositor->GetSyncObject(); |
197 | 0 | } |
198 | | |
199 | | gl::GLContext* |
200 | | RendererOGL::gl() const |
201 | 0 | { |
202 | 0 | return mCompositor->gl(); |
203 | 0 | } |
204 | | |
205 | | void |
206 | | RendererOGL::SetFrameStartTime(const TimeStamp& aTime) |
207 | 0 | { |
208 | 0 | if (mFrameStartTime) { |
209 | 0 | // frame start time is already set. This could happen when multiple |
210 | 0 | // generate frame requests are merged by webrender. |
211 | 0 | return; |
212 | 0 | } |
213 | 0 | mFrameStartTime = aTime; |
214 | 0 | } |
215 | | |
216 | | wr::WrPipelineInfo |
217 | | RendererOGL::FlushPipelineInfo() |
218 | 0 | { |
219 | 0 | return wr_renderer_flush_pipeline_info(mRenderer); |
220 | 0 | } |
221 | | |
222 | | RenderTextureHost* |
223 | | RendererOGL::GetRenderTexture(wr::WrExternalImageId aExternalImageId) |
224 | 0 | { |
225 | 0 | return mThread->GetRenderTexture(aExternalImageId); |
226 | 0 | } |
227 | | |
228 | | static void |
229 | | DoNotifyWebRenderError(layers::CompositorBridgeParent* aBridge, WebRenderError aError) |
230 | 0 | { |
231 | 0 | aBridge->NotifyWebRenderError(aError); |
232 | 0 | } |
233 | | |
234 | | void |
235 | | RendererOGL::NotifyWebRenderError(WebRenderError aError) |
236 | 0 | { |
237 | 0 | layers::CompositorThreadHolder::Loop()->PostTask(NewRunnableFunction( |
238 | 0 | "DoNotifyWebRenderErrorRunnable", |
239 | 0 | &DoNotifyWebRenderError, |
240 | 0 | mBridge, |
241 | 0 | aError |
242 | 0 | )); |
243 | 0 | } |
244 | | |
245 | | } // namespace wr |
246 | | } // namespace mozilla |