Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(887)

Side by Side Diff: services/gfx/compositor/backend/gpu_rasterizer.cc

Issue 1995873002: Mozart: Improve tracing and backpressure. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: address review comments Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "services/gfx/compositor/backend/gpu_rasterizer.h" 5 #include "services/gfx/compositor/backend/gpu_rasterizer.h"
6 6
7 #ifndef GL_GLEXT_PROTOTYPES 7 #ifndef GL_GLEXT_PROTOTYPES
8 #define GL_GLEXT_PROTOTYPES 8 #define GL_GLEXT_PROTOTYPES
9 #endif 9 #endif
10 10
11 #include <GLES2/gl2.h> 11 #include <GLES2/gl2.h>
12 #include <GLES2/gl2extmojo.h> 12 #include <GLES2/gl2extmojo.h>
13 #include <MGL/mgl.h> 13 #include <MGL/mgl.h>
14 #include <MGL/mgl_echo.h> 14 #include <MGL/mgl_echo.h>
15 #include <MGL/mgl_onscreen.h> 15 #include <MGL/mgl_onscreen.h>
16 #include <MGL/mgl_signal_sync_point.h>
17 16
18 #include "base/bind.h" 17 #include "base/bind.h"
19 #include "base/location.h" 18 #include "base/location.h"
20 #include "base/logging.h" 19 #include "base/logging.h"
21 #include "base/message_loop/message_loop.h" 20 #include "base/message_loop/message_loop.h"
22 #include "base/time/time.h" 21 #include "base/time/time.h"
23 #include "base/trace_event/trace_event.h" 22 #include "base/trace_event/trace_event.h"
24 #include "services/gfx/compositor/backend/vsync_scheduler.h"
25 #include "services/gfx/compositor/render/render_frame.h" 23 #include "services/gfx/compositor/render/render_frame.h"
26 24
27 namespace compositor { 25 namespace compositor {
28 namespace { 26 namespace {
27 // Timeout for receiving initial viewport parameters from the GPU service.
29 constexpr int64_t kViewportParameterTimeoutMs = 1000; 28 constexpr int64_t kViewportParameterTimeoutMs = 1000;
29
30 // Default vsync interval when the GPU service failed to provide viewport
31 // parameters promptly.
30 constexpr int64_t kDefaultVsyncIntervalUs = 100000; // deliberately sluggish 32 constexpr int64_t kDefaultVsyncIntervalUs = 100000; // deliberately sluggish
31 } 33 }
32 34
33 GpuRasterizer::GpuRasterizer(mojo::ContextProviderPtr context_provider, 35 GpuRasterizer::GpuRasterizer(mojo::ContextProviderPtr context_provider,
34 const scoped_refptr<VsyncScheduler>& scheduler, 36 Callbacks* callbacks)
35 const scoped_refptr<base::TaskRunner>& task_runner,
36 const base::Closure& error_callback)
37 : context_provider_(context_provider.Pass()), 37 : context_provider_(context_provider.Pass()),
38 scheduler_(scheduler), 38 callbacks_(callbacks),
39 task_runner_(task_runner),
40 error_callback_(error_callback),
41 viewport_parameter_listener_binding_(this), 39 viewport_parameter_listener_binding_(this),
42 viewport_parameter_timeout_(false, false), 40 viewport_parameter_timeout_(false, false),
43 weak_ptr_factory_(this) { 41 weak_ptr_factory_(this) {
44 DCHECK(context_provider_); 42 DCHECK(context_provider_);
45 DCHECK(scheduler_); 43 DCHECK(callbacks_);
46 DCHECK(task_runner_);
47 44
48 context_provider_.set_connection_error_handler( 45 context_provider_.set_connection_error_handler(
49 base::Bind(&GpuRasterizer::OnContextProviderConnectionError, 46 base::Bind(&GpuRasterizer::OnContextProviderConnectionError,
50 base::Unretained(this))); 47 base::Unretained(this)));
51 CreateContext(); 48 CreateContext();
52 } 49 }
53 50
54 GpuRasterizer::~GpuRasterizer() { 51 GpuRasterizer::~GpuRasterizer() {
55 DestroyContext(); 52 DestroyContext();
56 } 53 }
(...skipping 12 matching lines...) Expand all
69 } 66 }
70 67
71 void GpuRasterizer::InitContext( 68 void GpuRasterizer::InitContext(
72 mojo::InterfaceHandle<mojo::CommandBuffer> command_buffer) { 69 mojo::InterfaceHandle<mojo::CommandBuffer> command_buffer) {
73 DCHECK(!gl_context_); 70 DCHECK(!gl_context_);
74 DCHECK(!ganesh_context_); 71 DCHECK(!ganesh_context_);
75 DCHECK(!ganesh_surface_); 72 DCHECK(!ganesh_surface_);
76 73
77 if (!command_buffer) { 74 if (!command_buffer) {
78 LOG(ERROR) << "Could not create GL context."; 75 LOG(ERROR) << "Could not create GL context.";
79 PostErrorCallback(); 76 callbacks_->OnRasterizerError();
80 return; 77 return;
81 } 78 }
82 79
83 gl_context_ = mojo::GLContext::CreateFromCommandBuffer( 80 gl_context_ = mojo::GLContext::CreateFromCommandBuffer(
84 mojo::CommandBufferPtr::Create(std::move(command_buffer))); 81 mojo::CommandBufferPtr::Create(std::move(command_buffer)));
82 DCHECK(!gl_context_->is_lost());
85 gl_context_->AddObserver(this); 83 gl_context_->AddObserver(this);
86 ganesh_context_ = new mojo::skia::GaneshContext(gl_context_); 84 ganesh_context_ = new mojo::skia::GaneshContext(gl_context_);
87 85
88 if (have_viewport_parameters_) { 86 if (have_viewport_parameters_) {
89 ApplyViewportParameters(); 87 ApplyViewportParameters();
90 } else { 88 } else {
91 viewport_parameter_timeout_.Start( 89 viewport_parameter_timeout_.Start(
92 FROM_HERE, 90 FROM_HERE,
93 base::TimeDelta::FromMilliseconds(kViewportParameterTimeoutMs), 91 base::TimeDelta::FromMilliseconds(kViewportParameterTimeoutMs),
94 base::Bind(&GpuRasterizer::OnViewportParameterTimeout, 92 base::Bind(&GpuRasterizer::OnViewportParameterTimeout,
95 base::Unretained(this))); 93 base::Unretained(this)));
96 } 94 }
97
98 if (frame_)
99 Draw();
100 } 95 }
101 96
102 void GpuRasterizer::AbandonContext() { 97 void GpuRasterizer::AbandonContext() {
103 if (gl_context_)
104 scheduler_->Stop();
105
106 if (viewport_parameter_listener_binding_.is_bound()) { 98 if (viewport_parameter_listener_binding_.is_bound()) {
107 viewport_parameter_timeout_.Stop(); 99 viewport_parameter_timeout_.Stop();
108 viewport_parameter_listener_binding_.Close(); 100 viewport_parameter_listener_binding_.Close();
109 } 101 }
102
103 if (ready_) {
104 while (frames_in_progress_)
105 DrawFinished(false /*presented*/);
106 ready_ = false;
107 callbacks_->OnRasterizerSuspended();
108 }
110 } 109 }
111 110
112 void GpuRasterizer::DestroyContext() { 111 void GpuRasterizer::DestroyContext() {
113 AbandonContext(); 112 AbandonContext();
114 113
115 if (gl_context_) { 114 if (gl_context_) {
116 ganesh_context_ = nullptr; 115 ganesh_context_ = nullptr;
117 gl_context_ = nullptr; 116 gl_context_ = nullptr;
118 117
119 // Do this after releasing the GL context so that we will already have 118 // Do this after releasing the GL context so that we will already have
120 // told the Ganesh context to abandon its context. 119 // told the Ganesh context to abandon its context.
121 ganesh_surface_.reset(); 120 ganesh_surface_.reset();
122 } 121 }
123 } 122 }
124 123
125 void GpuRasterizer::OnContextProviderConnectionError() { 124 void GpuRasterizer::OnContextProviderConnectionError() {
126 LOG(ERROR) << "Context provider connection lost."; 125 LOG(ERROR) << "Context provider connection lost.";
127 PostErrorCallback(); 126
127 callbacks_->OnRasterizerError();
128 } 128 }
129 129
130 void GpuRasterizer::OnContextLost() { 130 void GpuRasterizer::OnContextLost() {
131 LOG(WARNING) << "GL context lost!"; 131 LOG(WARNING) << "GL context lost!";
132 132
133 AbandonContext(); 133 AbandonContext();
134 frames_pending_ = 0u;
135
136 base::MessageLoop::current()->PostTask( 134 base::MessageLoop::current()->PostTask(
137 FROM_HERE, base::Bind(&GpuRasterizer::RecreateContextAfterLoss, 135 FROM_HERE, base::Bind(&GpuRasterizer::RecreateContextAfterLoss,
138 weak_ptr_factory_.GetWeakPtr())); 136 weak_ptr_factory_.GetWeakPtr()));
139 } 137 }
140 138
141 void GpuRasterizer::RecreateContextAfterLoss() { 139 void GpuRasterizer::RecreateContextAfterLoss() {
142 LOG(WARNING) << "Recreating GL context."; 140 LOG(WARNING) << "Recreating GL context.";
143 141
144 DestroyContext(); 142 DestroyContext();
145 CreateContext(); 143 CreateContext();
(...skipping 14 matching lines...) Expand all
160 int64_t interval) { 158 int64_t interval) {
161 DVLOG(1) << "Vsync parameters: timebase=" << timebase 159 DVLOG(1) << "Vsync parameters: timebase=" << timebase
162 << ", interval=" << interval; 160 << ", interval=" << interval;
163 161
164 if (!have_viewport_parameters_) { 162 if (!have_viewport_parameters_) {
165 viewport_parameter_timeout_.Stop(); 163 viewport_parameter_timeout_.Stop();
166 have_viewport_parameters_ = true; 164 have_viewport_parameters_ = true;
167 } 165 }
168 vsync_timebase_ = timebase; 166 vsync_timebase_ = timebase;
169 vsync_interval_ = interval; 167 vsync_interval_ = interval;
170 168 ApplyViewportParameters();
171 if (gl_context_ && !gl_context_->is_lost())
172 ApplyViewportParameters();
173 } 169 }
174 170
175 void GpuRasterizer::ApplyViewportParameters() { 171 void GpuRasterizer::ApplyViewportParameters() {
176 DCHECK(have_viewport_parameters_); 172 DCHECK(have_viewport_parameters_);
177 DCHECK(gl_context_);
178 173
179 // TODO(jeffbrown): This shouldn't be hardcoded. 174 if (gl_context_ && !gl_context_->is_lost()) {
180 // Need to do some real tuning and possibly determine values adaptively. 175 ready_ = true;
181 int64_t update_phase = -vsync_interval_; 176 callbacks_->OnRasterizerReady(vsync_timebase_, vsync_interval_);
182 int64_t snapshot_phase = -vsync_interval_ / 6;
183 int64_t presentation_phase = vsync_interval_;
184 if (!scheduler_->Start(vsync_timebase_, vsync_interval_, update_phase,
185 snapshot_phase, presentation_phase)) {
186 LOG(ERROR) << "Received invalid vsync parameters: timebase="
187 << vsync_timebase_ << ", interval=" << vsync_interval_;
188 PostErrorCallback();
189 } 177 }
190 } 178 }
191 179
192 constexpr uint32_t kMaxFramesPending = 2; 180 void GpuRasterizer::DrawFrame(const scoped_refptr<RenderFrame>& frame) {
181 DCHECK(frame);
182 DCHECK(ready_);
183 DCHECK(gl_context_);
184 DCHECK(!gl_context_->is_lost());
185 DCHECK(ganesh_context_);
193 186
194 void GpuRasterizer::SubmitFrame(const scoped_refptr<RenderFrame>& frame, 187 uint32_t frame_number = total_frames_++;
195 const FrameCallback& frame_callback) { 188 frames_in_progress_++;
196 TRACE_EVENT0("gfx", "GpuRasterizer::SubmitFrame"); 189 TRACE_EVENT1("gfx", "GpuRasterizer::DrawFrame", "num", frame_number);
197 DCHECK(frame);
198
199 if (frame_ && !frame_callback_.is_null())
200 frame_callback_.Run(false); // frame discarded
201
202 frame_ = frame;
203 frame_callback_ = frame_callback;
204
205 if (gl_context_ && !gl_context_->is_lost()) {
206 if (frames_pending_ == kMaxFramesPending) {
207 TRACE_EVENT_INSTANT0("gfx", "GpuRasterizer dropping",
208 TRACE_EVENT_SCOPE_THREAD);
209 LOG(ERROR) << "too many frames pending, dropping";
210 frame_callback_.Run(false);
211 return;
212 }
213 Draw();
214 } else
215 frame_callback_.Run(false);
216 }
217
218 static void DidEcho(void* context) {
219 TRACE_EVENT_ASYNC_END0("gfx", "SwapBuffers Echo", context);
220 auto cb = static_cast<base::Closure*>(context);
221 cb->Run();
222 delete cb;
223 }
224
225 void GpuRasterizer::Draw() {
226 TRACE_EVENT0("gfx", "GpuRasterizer::Draw");
227 DCHECK(gl_context_);
228 DCHECK(ganesh_context_);
229 DCHECK(frame_);
230 190
231 mojo::GLContext::Scope gl_scope(gl_context_); 191 mojo::GLContext::Scope gl_scope(gl_context_);
232 192
233 // Update the viewport. 193 // Update the viewport.
234 const SkIRect& viewport = frame_->viewport(); 194 const SkIRect& viewport = frame->viewport();
235 bool stale_surface = false; 195 bool stale_surface = false;
236 if (!ganesh_surface_ || 196 if (!ganesh_surface_ ||
237 ganesh_surface_->surface()->width() != viewport.width() || 197 ganesh_surface_->surface()->width() != viewport.width() ||
238 ganesh_surface_->surface()->height() != viewport.height()) { 198 ganesh_surface_->surface()->height() != viewport.height()) {
239 glResizeCHROMIUM(viewport.width(), viewport.height(), 1.0f); 199 glResizeCHROMIUM(viewport.width(), viewport.height(), 1.0f);
240 glViewport(viewport.x(), viewport.y(), viewport.width(), viewport.height()); 200 glViewport(viewport.x(), viewport.y(), viewport.width(), viewport.height());
241 stale_surface = true; 201 stale_surface = true;
242 } 202 }
243 203
244 // Paint the frame. 204 // Draw the frame content.
245 { 205 {
246 mojo::skia::GaneshContext::Scope ganesh_scope(ganesh_context_); 206 mojo::skia::GaneshContext::Scope ganesh_scope(ganesh_context_);
247 207
248 if (stale_surface) { 208 if (stale_surface) {
249 ganesh_surface_.reset( 209 ganesh_surface_.reset(
250 new mojo::skia::GaneshFramebufferSurface(ganesh_scope)); 210 new mojo::skia::GaneshFramebufferSurface(ganesh_scope));
251 } 211 }
252 212
253 frame_->Paint(ganesh_surface_->canvas()); 213 frame->Draw(ganesh_surface_->canvas());
254 } 214 }
255 215
256 // Swap buffers and listen for completion. 216 // Swap buffers.
257 // TODO: Investigate using |MGLSignalSyncPoint| to wait for completion.
258 { 217 {
259 TRACE_EVENT0("gfx", "MGLSwapBuffers"); 218 TRACE_EVENT0("gfx", "MGLSwapBuffers");
260 MGLSwapBuffers(); 219 MGLSwapBuffers();
261 } 220 }
262 base::Closure* echo_callback = new base::Closure( 221
263 base::Bind(&GpuRasterizer::DidEchoCallback, 222 // Listen for completion.
264 weak_ptr_factory_.GetWeakPtr(), frame_callback_)); 223 TRACE_EVENT_ASYNC_BEGIN0("gfx", "MGLEcho", frame_number);
265 frame_callback_.Reset(); 224 MGLEcho(&GpuRasterizer::OnMGLEchoReply, this);
266 TRACE_EVENT_ASYNC_BEGIN0("gfx", "SwapBuffers Echo", echo_callback);
267 MGLEcho(DidEcho, echo_callback);
268 frames_pending_++;
269 TRACE_COUNTER1("gfx", "GpuRasterizer::frames_pending_", frames_pending_);
270 } 225 }
271 226
272 void GpuRasterizer::DidEchoCallback(FrameCallback frame_callback) { 227 void GpuRasterizer::DrawFinished(bool presented) {
273 frames_pending_--; 228 DCHECK(frames_in_progress_);
274 TRACE_COUNTER1("gfx", "GpuRasterizer::frames_pending_", frames_pending_); 229
275 TRACE_EVENT0("gfx", "GpuRasterizer::DidEchoCallback"); 230 uint32_t frame_number = total_frames_ - frames_in_progress_;
276 // Signal pending callback for backpressure. 231 frames_in_progress_--;
277 if (!frame_callback.is_null()) { 232 TRACE_EVENT2("gfx", "GpuRasterizer::DrawFinished", "num", frame_number,
278 frame_callback.Run(true); 233 "presented", presented);
279 frame_callback.Reset(); 234 TRACE_EVENT_ASYNC_END0("gfx", "MGLEcho", frame_number);
280 } 235
236 callbacks_->OnRasterizerFinishedDraw(presented);
281 } 237 }
282 238
283 void GpuRasterizer::PostErrorCallback() { 239 void GpuRasterizer::OnMGLEchoReply(void* context) {
284 task_runner_->PostTask(FROM_HERE, error_callback_); 240 auto rasterizer = static_cast<GpuRasterizer*>(context);
241 if (rasterizer->ready_)
242 rasterizer->DrawFinished(true /*presented*/);
285 } 243 }
286 244
287 } // namespace compositor 245 } // namespace compositor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698