Chromium Code Reviews| OLD | NEW |
|---|---|
| 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_output.h" | 5 #include "services/gfx/compositor/backend/gpu_output.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| 11 #include "base/location.h" | 11 #include "base/location.h" |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/message_loop/message_loop.h" | 13 #include "base/message_loop/message_loop.h" |
| 14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 15 #include "base/trace_event/trace_event.h" | 15 #include "base/trace_event/trace_event.h" |
| 16 #include "services/gfx/compositor/render/render_frame.h" | 16 #include "services/gfx/compositor/render/render_frame.h" |
| 17 | 17 |
| 18 namespace compositor { | 18 namespace compositor { |
| 19 namespace { | 19 namespace { |
| 20 constexpr const char* kPipelineDepthSwitch = "pipeline-depth"; | 20 constexpr const char* kPipelineDepthSwitch = "pipeline-depth"; |
| 21 constexpr uint32_t kDefaultPipelineDepth = 2u; // ideally should be 1 | 21 constexpr uint32_t kDefaultPipelineDepth = 1u; |
| 22 constexpr uint32_t kMinPipelineDepth = 1u; | 22 constexpr uint32_t kMinPipelineDepth = 1u; |
| 23 constexpr uint32_t kMaxPipelineDepth = 10u; | 23 constexpr uint32_t kMaxPipelineDepth = 10u; // for experimentation |
| 24 | 24 |
| 25 scoped_ptr<base::MessagePump> CreateMessagePumpMojo() { | 25 scoped_ptr<base::MessagePump> CreateMessagePumpMojo() { |
| 26 return base::MessageLoop::CreateMessagePumpForType( | 26 return base::MessageLoop::CreateMessagePumpForType( |
| 27 base::MessageLoop::TYPE_DEFAULT); | 27 base::MessageLoop::TYPE_DEFAULT); |
| 28 } | 28 } |
| 29 } // namespace | 29 } // namespace |
| 30 | 30 |
| 31 GpuOutput::GpuOutput( | 31 GpuOutput::GpuOutput( |
| 32 mojo::InterfaceHandle<mojo::ContextProvider> context_provider, | 32 mojo::InterfaceHandle<mojo::ContextProvider> context_provider, |
| 33 const SchedulerCallbacks& scheduler_callbacks, | 33 const SchedulerCallbacks& scheduler_callbacks, |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 | 79 |
| 80 Scheduler* GpuOutput::GetScheduler() { | 80 Scheduler* GpuOutput::GetScheduler() { |
| 81 return vsync_scheduler_.get(); | 81 return vsync_scheduler_.get(); |
| 82 } | 82 } |
| 83 | 83 |
| 84 void GpuOutput::SubmitFrame(const scoped_refptr<RenderFrame>& frame) { | 84 void GpuOutput::SubmitFrame(const scoped_refptr<RenderFrame>& frame) { |
| 85 DCHECK(frame); | 85 DCHECK(frame); |
| 86 TRACE_EVENT0("gfx", "GpuOutput::SubmitFrame"); | 86 TRACE_EVENT0("gfx", "GpuOutput::SubmitFrame"); |
| 87 | 87 |
| 88 const int64_t submit_time = MojoGetTimeTicksNow(); | 88 const int64_t submit_time = MojoGetTimeTicksNow(); |
| 89 scoped_refptr<FrameData> frame_data( | 89 std::unique_ptr<FrameData> frame_data( |
| 90 new FrameData(frame, submit_time)); // drop outside lock | 90 new FrameData(frame, submit_time)); // drop outside lock |
| 91 { | 91 { |
| 92 std::lock_guard<std::mutex> lock(shared_state_.mutex); | 92 std::lock_guard<std::mutex> lock(shared_state_.mutex); |
| 93 | 93 |
| 94 TRACE_EVENT_FLOW_BEGIN0("gfx", "Frame Queued", frame_data.get()); | 94 // Enqueue the frame, ensuring that the queue only contains at most |
| 95 shared_state_.current_frame_data.swap(frame_data); | 95 // one undrawn frame. If the last frame hasn't been drawn by now then |
| 96 if (frame_data && !frame_data->drawn) { | 96 // the rasterizer must be falling behind. |
| 97 // Dropped an undrawn frame. | 97 if (!shared_state_.frames.empty() && shared_state_.frames.front()->finished) |
|
mikejurka
2016/05/25 21:11:46
if you introduce a pinned_for_draw variable, i wou
jeffbrown
2016/05/25 23:45:43
Maybe add a DCHECK here that the queue size is exa
| |
| 98 DVLOG(2) << "Rasterizer stalled, dropping frame to catch up."; | 98 shared_state_.frames.pop(); |
|
mikejurka
2016/05/25 21:11:46
should we have a DCHECK after this pop that the fr
mikejurka
2016/05/25 23:54:06
actually, on second thought, shouldn't the above "
| |
| 99 if (shared_state_.frames.empty() || shared_state_.frames.back()->drawn) { | |
| 100 shared_state_.frames.emplace(std::move(frame_data)); | |
| 101 } else { | |
|
jeffbrown
2016/05/25 23:45:43
Add a comment here explaining why it's safe to rep
| |
| 102 shared_state_.frames.back().swap(frame_data); | |
|
mikejurka
2016/05/25 21:11:46
if you introduce a pinned_for_draw variable, i wou
| |
| 99 TRACE_EVENT_FLOW_END1("gfx", "Frame Queued", frame_data.get(), "drawn", | 103 TRACE_EVENT_FLOW_END1("gfx", "Frame Queued", frame_data.get(), "drawn", |
| 100 false); | 104 false); |
| 105 DVLOG(2) << "Rasterizer stalled, dropped a frame to catch up."; | |
| 101 } | 106 } |
| 102 | 107 |
| 103 // TODO(jeffbrown): If the draw queue is full, we should pause | 108 TRACE_EVENT_FLOW_BEGIN0("gfx", "Frame Queued", |
| 109 shared_state_.frames.back().get()); | |
| 110 | |
| 111 if (!shared_state_.rasterizer_ready) | |
| 112 return; | |
| 113 | |
| 114 // TODO(jeffbrown): If the draw queue is overfull, we should pause | |
| 104 // scheduling until the queue drains. | 115 // scheduling until the queue drains. |
| 105 if (shared_state_.rasterizer_ready && | 116 if (shared_state_.frames.size() <= pipeline_depth_) |
| 106 shared_state_.drawn_frames_awaiting_finish.size() < pipeline_depth_) | |
| 107 ScheduleDrawLocked(); | 117 ScheduleDrawLocked(); |
|
mikejurka
2016/05/25 21:11:46
might be useful to track another time here ie draw
jeffbrown
2016/05/25 23:45:43
I'm going to leave this out. The other two timest
| |
| 108 } | 118 } |
| 109 } | 119 } |
| 110 | 120 |
| 111 void GpuOutput::OnRasterizerReady(int64_t vsync_timebase, | 121 void GpuOutput::OnRasterizerReady(int64_t vsync_timebase, |
| 112 int64_t vsync_interval) { | 122 int64_t vsync_interval) { |
| 113 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); | 123 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); |
| 114 | 124 |
| 115 // TODO(jeffbrown): This shouldn't be hardcoded. | 125 // TODO(jeffbrown): This shouldn't be hardcoded. |
| 116 // Need to do some real tuning and possibly determine values adaptively. | 126 // Need to do some real tuning and possibly determine values adaptively. |
| 117 // We should probably split the Start() method in two to separate the | 127 // We should probably split the Start() method in two to separate the |
| 118 // process of setting parameters from starting / stopping scheduling. | 128 // process of setting parameters from starting / stopping scheduling. |
| 119 const int64_t update_phase = -vsync_interval; | 129 const int64_t update_phase = -vsync_interval; |
| 120 const int64_t snapshot_phase = -vsync_interval / 6; | 130 const int64_t snapshot_phase = -vsync_interval / 6; |
| 121 // TODO(jeffbrown): Determine the presentation phase based on queue depth. | 131 // TODO(jeffbrown): Determine the presentation phase based on queue depth. |
| 122 const int64_t presentation_phase = vsync_interval * pipeline_depth_; | 132 const int64_t presentation_phase = vsync_interval * pipeline_depth_; |
| 123 if (!vsync_scheduler_->Start(vsync_timebase, vsync_interval, update_phase, | 133 if (!vsync_scheduler_->Start(vsync_timebase, vsync_interval, update_phase, |
| 124 snapshot_phase, presentation_phase)) { | 134 snapshot_phase, presentation_phase)) { |
| 125 LOG(ERROR) << "Received invalid vsync parameters: timebase=" | 135 LOG(ERROR) << "Received invalid vsync parameters: timebase=" |
| 126 << vsync_timebase << ", interval=" << vsync_interval; | 136 << vsync_timebase << ", interval=" << vsync_interval; |
| 127 PostErrorCallback(); | 137 PostErrorCallback(); |
| 128 return; | 138 return; |
| 129 } | 139 } |
| 130 | 140 |
| 131 { | 141 { |
| 132 std::lock_guard<std::mutex> lock(shared_state_.mutex); | 142 std::lock_guard<std::mutex> lock(shared_state_.mutex); |
| 133 | 143 |
| 134 if (shared_state_.rasterizer_ready) | 144 if (shared_state_.rasterizer_ready) |
| 135 return; | 145 return; |
| 136 | 146 |
| 137 DCHECK(shared_state_.drawn_frames_awaiting_finish.empty()); | |
| 138 shared_state_.rasterizer_ready = true; | 147 shared_state_.rasterizer_ready = true; |
| 139 | 148 |
| 140 if (!shared_state_.current_frame_data) | 149 if (shared_state_.frames.empty()) |
| 141 return; | 150 return; |
| 142 | 151 |
| 143 shared_state_.current_frame_data->Recycle(); | 152 shared_state_.frames.back()->ClearDrawState(); |
| 144 TRACE_EVENT_FLOW_BEGIN0("gfx", "Frame Queued", | 153 TRACE_EVENT_FLOW_BEGIN0("gfx", "Frame Queued", |
| 145 shared_state_.current_frame_data.get()); | 154 shared_state_.frames.back().get()); |
| 146 ScheduleDrawLocked(); | 155 ScheduleDrawLocked(); |
| 147 } | 156 } |
| 148 } | 157 } |
| 149 | 158 |
| 150 void GpuOutput::OnRasterizerSuspended() { | 159 void GpuOutput::OnRasterizerSuspended() { |
| 151 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); | 160 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); |
| 152 | 161 |
| 153 vsync_scheduler_->Stop(); | 162 vsync_scheduler_->Stop(); |
| 154 | 163 |
| 155 { | 164 { |
| 156 std::lock_guard<std::mutex> lock(shared_state_.mutex); | 165 std::lock_guard<std::mutex> lock(shared_state_.mutex); |
| 157 | 166 |
| 158 if (!shared_state_.rasterizer_ready) | 167 if (!shared_state_.rasterizer_ready) |
| 159 return; | 168 return; |
| 160 | 169 |
| 161 shared_state_.rasterizer_ready = false; | 170 shared_state_.rasterizer_ready = false; |
| 162 } | 171 } |
| 163 } | 172 } |
| 164 | 173 |
| 165 void GpuOutput::OnRasterizerError() { | 174 void GpuOutput::OnRasterizerError() { |
| 166 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); | 175 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); |
| 167 | 176 |
| 168 PostErrorCallback(); | 177 PostErrorCallback(); |
| 169 } | 178 } |
| 170 | 179 |
| 171 void GpuOutput::ScheduleDrawLocked() { | 180 void GpuOutput::ScheduleDrawLocked() { |
| 172 DCHECK(shared_state_.current_frame_data); | 181 DCHECK(!shared_state_.frames.empty()); |
| 173 DCHECK(!shared_state_.current_frame_data->drawn); | 182 DCHECK(!shared_state_.frames.back()->drawn); |
| 183 DCHECK(shared_state_.frames.size() <= pipeline_depth_); | |
| 174 | 184 |
| 175 if (shared_state_.draw_scheduled) | 185 if (shared_state_.draw_scheduled) |
| 176 return; | 186 return; |
| 177 | 187 |
| 178 shared_state_.draw_scheduled = true; | 188 shared_state_.draw_scheduled = true; |
| 179 rasterizer_task_runner_->PostTask( | 189 rasterizer_task_runner_->PostTask( |
| 180 FROM_HERE, base::Bind(&GpuOutput::OnDraw, base::Unretained(this))); | 190 FROM_HERE, base::Bind(&GpuOutput::OnDraw, base::Unretained(this))); |
| 181 } | 191 } |
| 182 | 192 |
| 183 void GpuOutput::OnDraw() { | 193 void GpuOutput::OnDraw() { |
| 184 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); | 194 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); |
| 185 TRACE_EVENT0("gfx", "GpuOutput::OnDraw"); | 195 TRACE_EVENT0("gfx", "GpuOutput::OnDraw"); |
| 186 | 196 |
| 187 scoped_refptr<FrameData> frame_data; // used outside lock | 197 FrameData* frame_data; |
|
mikejurka
2016/05/25 21:11:46
probably a good idea to initialize to null (just f
jeffbrown
2016/05/25 23:45:43
The compiler will yell at me if I try to use an un
| |
| 188 { | 198 { |
| 189 std::lock_guard<std::mutex> lock(shared_state_.mutex); | 199 std::lock_guard<std::mutex> lock(shared_state_.mutex); |
| 190 | 200 |
| 191 DCHECK(shared_state_.draw_scheduled); | 201 DCHECK(shared_state_.draw_scheduled); |
| 192 DCHECK(shared_state_.current_frame_data); | 202 DCHECK(!shared_state_.frames.empty()); |
| 193 DCHECK(!shared_state_.current_frame_data->drawn); | 203 DCHECK(!shared_state_.frames.back()->drawn); |
| 194 | 204 |
| 195 shared_state_.draw_scheduled = false; | 205 shared_state_.draw_scheduled = false; |
| 196 | 206 if (!shared_state_.rasterizer_ready) |
| 197 if (!shared_state_.rasterizer_ready || | |
| 198 shared_state_.drawn_frames_awaiting_finish.size() >= pipeline_depth_) | |
| 199 return; | 207 return; |
| 200 | 208 |
| 201 frame_data = shared_state_.current_frame_data; | 209 frame_data = shared_state_.frames.back().get(); |
|
mikejurka
2016/05/25 21:11:46
maybe move DCHECK(!frame_data->drawn) to here inst
jeffbrown
2016/05/25 23:45:43
I'd rather leave it where it is since the invarian
| |
| 202 frame_data->drawn = true; | 210 frame_data->drawn = true; |
| 203 frame_data->draw_time = MojoGetTimeTicksNow(); | 211 frame_data->draw_time = MojoGetTimeTicksNow(); |
| 204 TRACE_EVENT_FLOW_END1("gfx", "Frame Queued", frame_data.get(), "drawn", | 212 TRACE_EVENT_FLOW_END1("gfx", "Frame Queued", frame_data, "drawn", true); |
| 205 true); | |
| 206 | |
| 207 TRACE_EVENT_ASYNC_BEGIN0("gfx", "Rasterize", frame_data.get()); | |
| 208 shared_state_.drawn_frames_awaiting_finish.emplace(frame_data); | |
| 209 } | 213 } |
| 210 | 214 |
|
mikejurka
2016/05/25 21:11:46
Do a DCHECK to ensure frame_data is not null here
jeffbrown
2016/05/25 23:45:43
I don't think that's really necessary. It must ob
| |
| 215 // It is safe to access |frame_data| outside of the lock here because | |
| 216 // it will not be dequeued until |OnRasterizerFinishedDraw| gets posted | |
| 217 // to this thread's message loop. Moreover |SubmitFrame| will not replace | |
| 218 // the frame because the |drawn| flag has been set. | |
|
mikejurka
2016/05/25 21:11:46
I would put a note in the header file next to the
jeffbrown
2016/05/25 23:45:43
I don't actually need extra state here. I could a
| |
| 219 TRACE_EVENT_ASYNC_BEGIN0("gfx", "Rasterize", frame_data); | |
| 211 rasterizer_->DrawFrame(frame_data->frame); | 220 rasterizer_->DrawFrame(frame_data->frame); |
| 212 frame_data->wait_time = MojoGetTimeTicksNow(); | 221 frame_data->wait_time = MojoGetTimeTicksNow(); |
| 213 } | 222 } |
| 214 | 223 |
| 215 void GpuOutput::OnRasterizerFinishedDraw(bool presented) { | 224 void GpuOutput::OnRasterizerFinishedDraw(bool presented) { |
| 216 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); | 225 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); |
| 217 TRACE_EVENT0("gfx", "GpuOutput::OnRasterizerFinishedDraw"); | 226 TRACE_EVENT0("gfx", "GpuOutput::OnRasterizerFinishedDraw"); |
| 218 | 227 |
| 219 const int64_t finish_time = MojoGetTimeTicksNow(); | 228 const int64_t finish_time = MojoGetTimeTicksNow(); |
| 220 scoped_refptr<FrameData> frame_data; // drop outside lock | 229 std::unique_ptr<FrameData> old_frame_data; // drop outside lock |
|
mikejurka
2016/05/25 21:11:46
change comment for "drop outside lock" to "keep ol
jeffbrown
2016/05/25 23:45:43
Done.
| |
| 221 { | 230 { |
| 222 std::lock_guard<std::mutex> lock(shared_state_.mutex); | 231 std::lock_guard<std::mutex> lock(shared_state_.mutex); |
| 223 | 232 |
| 224 DCHECK(shared_state_.rasterizer_ready); | 233 DCHECK(shared_state_.rasterizer_ready); |
| 225 DCHECK(!shared_state_.drawn_frames_awaiting_finish.empty()); | 234 DCHECK(!shared_state_.frames.empty()); |
| 226 size_t draw_queue_depth = shared_state_.drawn_frames_awaiting_finish.size(); | 235 |
| 227 shared_state_.drawn_frames_awaiting_finish.front().swap(frame_data); | 236 FrameData* frame_data = shared_state_.frames.front().get(); |
| 228 shared_state_.drawn_frames_awaiting_finish.pop(); | |
| 229 DCHECK(frame_data); | 237 DCHECK(frame_data); |
| 230 DCHECK(frame_data->drawn); | 238 DCHECK(frame_data->drawn); |
| 231 TRACE_EVENT_ASYNC_END1("gfx", "Rasterize", frame_data.get(), "presented", | 239 TRACE_EVENT_ASYNC_END1("gfx", "Rasterize", frame_data, "presented", |
| 232 presented); | 240 presented); |
| 241 frame_data->finished = true; | |
|
mikejurka
2016/05/25 21:11:46
if you decide to use a "pinned_for_draw" var, i gu
| |
| 233 | 242 |
| 234 // TODO(jeffbrown): Adjust scheduler behavior based on observed timing. | 243 // TODO(jeffbrown): Adjust scheduler behavior based on observed timing. |
| 235 // Note: These measurements don't account for systematic downstream delay | 244 // Note: These measurements don't account for systematic downstream delay |
| 236 // in the display pipeline (how long it takes pixels to actually light up). | 245 // in the display pipeline (how long it takes pixels to actually light up). |
| 237 if (presented) { | 246 if (presented) { |
| 238 const RenderFrame::Metadata& frame_metadata = | 247 const RenderFrame::Metadata& frame_metadata = |
| 239 frame_data->frame->metadata(); | 248 frame_data->frame->metadata(); |
| 240 const mojo::gfx::composition::FrameInfo& frame_info = | 249 const mojo::gfx::composition::FrameInfo& frame_info = |
| 241 frame_metadata.frame_info(); | 250 frame_metadata.frame_info(); |
| 242 const int64_t frame_time = frame_info.frame_time; | 251 const int64_t frame_time = frame_info.frame_time; |
| 243 const int64_t presentation_time = frame_info.presentation_time; | 252 const int64_t presentation_time = frame_info.presentation_time; |
| 244 const int64_t composition_time = frame_metadata.composition_time(); | 253 const int64_t composition_time = frame_metadata.composition_time(); |
| 245 const int64_t draw_time = frame_data->draw_time; | 254 const int64_t draw_time = frame_data->draw_time; |
| 246 const int64_t wait_time = frame_data->wait_time; | 255 const int64_t wait_time = frame_data->wait_time; |
| 247 const int64_t submit_time = frame_data->submit_time; | 256 const int64_t submit_time = frame_data->submit_time; |
| 257 const size_t draw_queue_depth = shared_state_.frames.size(); | |
| 248 | 258 |
| 249 DVLOG(2) << "Presented frame: composition latency " | 259 DVLOG(2) << "Presented frame: composition latency " |
| 250 << (composition_time - frame_time) << " us, submission latency " | 260 << (composition_time - frame_time) << " us, submission latency " |
| 251 << (submit_time - composition_time) << " us, queue latency " | 261 << (submit_time - composition_time) << " us, queue latency " |
| 252 << (draw_time - submit_time) << " us, draw latency " | 262 << (draw_time - submit_time) << " us, draw latency " |
| 253 << (wait_time - draw_time) << " us, GPU latency " | 263 << (wait_time - draw_time) << " us, GPU latency " |
| 254 << (finish_time - wait_time) << " us, total latency " | 264 << (finish_time - wait_time) << " us, total latency " |
| 255 << (finish_time - frame_time) << " us, presentation time error " | 265 << (finish_time - frame_time) << " us, presentation time error " |
| 256 << (finish_time - presentation_time) << " us" | 266 << (finish_time - presentation_time) << " us" |
| 257 << ", draw queue depth " << draw_queue_depth; | 267 << ", draw queue depth " << draw_queue_depth; |
| 258 } else { | 268 } else { |
| 259 DVLOG(2) << "Rasterizer dropped frame."; | 269 DVLOG(2) << "Rasterizer dropped frame."; |
| 260 } | 270 } |
| 261 | 271 |
| 262 DCHECK(shared_state_.current_frame_data); | 272 if (shared_state_.frames.size() > 1u) { |
| 263 if (!shared_state_.current_frame_data->drawn) | 273 shared_state_.frames.front().swap(old_frame_data); |
|
mikejurka
2016/05/25 21:11:46
I would add the earlier comment here again to clar
jeffbrown
2016/05/25 23:45:43
Done.
| |
| 264 ScheduleDrawLocked(); | 274 shared_state_.frames.pop(); |
| 275 if (!shared_state_.frames.back()->drawn) | |
| 276 ScheduleDrawLocked(); | |
| 277 } | |
| 265 } | 278 } |
| 266 } | 279 } |
| 267 | 280 |
| 268 void GpuOutput::InitializeRasterizer( | 281 void GpuOutput::InitializeRasterizer( |
| 269 mojo::InterfaceHandle<mojo::ContextProvider> context_provider) { | 282 mojo::InterfaceHandle<mojo::ContextProvider> context_provider) { |
| 270 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); | 283 DCHECK(rasterizer_task_runner_->RunsTasksOnCurrentThread()); |
| 271 DCHECK(!rasterizer_); | 284 DCHECK(!rasterizer_); |
| 272 TRACE_EVENT0("gfx", "GpuOutput::InitializeRasterizer"); | 285 TRACE_EVENT0("gfx", "GpuOutput::InitializeRasterizer"); |
| 273 | 286 |
| 274 rasterizer_.reset(new GpuRasterizer( | 287 rasterizer_.reset(new GpuRasterizer( |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 288 void GpuOutput::PostErrorCallback() { | 301 void GpuOutput::PostErrorCallback() { |
| 289 compositor_task_runner_->PostTask(FROM_HERE, error_callback_); | 302 compositor_task_runner_->PostTask(FROM_HERE, error_callback_); |
| 290 } | 303 } |
| 291 | 304 |
| 292 GpuOutput::FrameData::FrameData(const scoped_refptr<RenderFrame>& frame, | 305 GpuOutput::FrameData::FrameData(const scoped_refptr<RenderFrame>& frame, |
| 293 int64_t submit_time) | 306 int64_t submit_time) |
| 294 : frame(frame), submit_time(submit_time) {} | 307 : frame(frame), submit_time(submit_time) {} |
| 295 | 308 |
| 296 GpuOutput::FrameData::~FrameData() {} | 309 GpuOutput::FrameData::~FrameData() {} |
| 297 | 310 |
| 298 void GpuOutput::FrameData::Recycle() { | 311 void GpuOutput::FrameData::ClearDrawState() { |
| 299 drawn = false; | 312 drawn = false; |
| 313 finished = false; | |
| 300 draw_time = 0; | 314 draw_time = 0; |
| 301 wait_time = 0; | 315 wait_time = 0; |
| 302 } | 316 } |
| 303 | 317 |
| 304 } // namespace compositor | 318 } // namespace compositor |
| OLD | NEW |