Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "gpu/command_buffer/service/gpu_tracer.h" | 5 #include "gpu/command_buffer/service/gpu_tracer.h" |
| 6 | 6 |
| 7 #include <deque> | 7 #include <deque> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "base/time/time.h" | 12 #include "base/time/time.h" |
| 13 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 13 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| 14 | 14 |
| 15 namespace gpu { | 15 namespace gpu { |
| 16 namespace gles2 { | 16 namespace gles2 { |
| 17 | 17 |
| 18 static const unsigned int kProcessInterval = 16; | 18 static const unsigned int kProcessInterval = 16; |
| 19 static TraceOutputter* g_outputter_thread = NULL; | 19 static TraceOutputter* g_outputter_thread = NULL; |
| 20 | 20 |
| 21 CPUTime::CPUTime() { | |
| 22 } | |
| 23 | |
| 24 int64 CPUTime::GetCurrentTime() { | |
| 25 return base::TimeTicks::NowFromSystemTraceTime().ToInternalValue(); | |
| 26 } | |
| 27 | |
| 28 CPUTime::~CPUTime() { | |
| 29 } | |
| 30 | |
| 21 TraceMarker::TraceMarker(const std::string& category, const std::string& name) | 31 TraceMarker::TraceMarker(const std::string& category, const std::string& name) |
| 22 : category_(category), | 32 : category_(category), |
| 23 name_(name), | 33 name_(name), |
| 24 trace_(NULL) { | 34 trace_(NULL) { |
| 25 } | 35 } |
| 26 | 36 |
| 27 TraceMarker::~TraceMarker() { | 37 TraceMarker::~TraceMarker() { |
| 28 } | 38 } |
| 29 | 39 |
| 30 scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) { | 40 scoped_refptr<TraceOutputter> TraceOutputter::Create(const std::string& name) { |
| 31 if (!g_outputter_thread) { | 41 if (!g_outputter_thread) { |
| 32 g_outputter_thread = new TraceOutputter(name); | 42 g_outputter_thread = new TraceOutputter(name); |
| 33 } | 43 } |
| 34 return g_outputter_thread; | 44 return g_outputter_thread; |
| 35 } | 45 } |
| 36 | 46 |
| 37 TraceOutputter::TraceOutputter(const std::string& name) | 47 TraceOutputter::TraceOutputter(const std::string& name) |
| 38 : named_thread_(name.c_str()), local_trace_id_(0) { | 48 : named_thread_(name.c_str()), local_trace_id_(0) { |
| 39 named_thread_.Start(); | 49 named_thread_.Start(); |
| 40 named_thread_.Stop(); | 50 named_thread_.Stop(); |
| 41 } | 51 } |
| 42 | 52 |
| 43 TraceOutputter::~TraceOutputter() { g_outputter_thread = NULL; } | 53 TraceOutputter::~TraceOutputter() { g_outputter_thread = NULL; } |
| 44 | 54 |
| 45 void TraceOutputter::Trace(const std::string& category, | 55 void TraceOutputter::TraceDevice(const std::string& category, |
| 46 const std::string& name, | 56 const std::string& name, |
| 47 int64 start_time, | 57 int64 start_time, |
| 48 int64 end_time) { | 58 int64 end_time) { |
| 49 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(), | 59 TRACE_EVENT_COPY_BEGIN_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(), |
| 50 name.c_str(), | 60 name.c_str(), |
| 51 local_trace_id_, | 61 local_trace_id_, |
| 52 named_thread_.thread_id(), | 62 named_thread_.thread_id(), |
| 53 start_time); | 63 start_time); |
| 54 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(), | 64 TRACE_EVENT_COPY_END_WITH_ID_TID_AND_TIMESTAMP0(category.c_str(), |
| 55 name.c_str(), | 65 name.c_str(), |
| 56 local_trace_id_, | 66 local_trace_id_, |
| 57 named_thread_.thread_id(), | 67 named_thread_.thread_id(), |
| 58 end_time); | 68 end_time); |
| 59 ++local_trace_id_; | 69 ++local_trace_id_; |
| 60 } | 70 } |
| 61 | 71 |
| 72 void TraceOutputter::TraceServiceBegin(const std::string& category, | |
| 73 const std::string& name, | |
| 74 void* id) { | |
| 75 TRACE_EVENT_COPY_ASYNC_BEGIN0(category.c_str(), name.c_str(), id); | |
|
vmiura
2015/01/07 00:40:56
Using dynamic category strings isn't working right
David Yen
2015/01/07 18:11:47
Yes, that change is still in the other CL where gl
| |
| 76 } | |
| 77 | |
| 78 void TraceOutputter::TraceServiceEnd(const std::string& category, | |
| 79 const std::string& name, | |
| 80 void* id) { | |
| 81 TRACE_EVENT_COPY_ASYNC_END0(category.c_str(), name.c_str(), id); | |
| 82 } | |
| 83 | |
| 62 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, | 84 GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, |
| 85 scoped_refptr<CPUTime> cpu_time, | |
| 63 const std::string& category, | 86 const std::string& category, |
| 64 const std::string& name, | 87 const std::string& name, |
| 65 int64 offset, | 88 int64 offset, |
| 66 GpuTracerType tracer_type) | 89 GpuTracerType tracer_type) |
| 67 : category_(category), | 90 : category_(category), |
| 68 name_(name), | 91 name_(name), |
| 69 outputter_(outputter), | 92 outputter_(outputter), |
| 93 cpu_time_(cpu_time), | |
| 70 offset_(offset), | 94 offset_(offset), |
| 71 start_time_(0), | 95 start_time_(0), |
| 72 end_time_(0), | 96 end_time_(0), |
| 73 tracer_type_(tracer_type), | 97 tracer_type_(tracer_type), |
| 74 end_requested_(false) { | 98 end_requested_(false) { |
| 75 memset(queries_, 0, sizeof(queries_)); | 99 memset(queries_, 0, sizeof(queries_)); |
| 76 switch (tracer_type_) { | 100 switch (tracer_type_) { |
| 77 case kTracerTypeARBTimer: | 101 case kTracerTypeARBTimer: |
| 78 case kTracerTypeDisjointTimer: | 102 case kTracerTypeDisjointTimer: |
| 79 glGenQueriesARB(2, queries_); | 103 glGenQueriesARB(2, queries_); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 91 | 115 |
| 92 case kTracerTypeARBTimer: | 116 case kTracerTypeARBTimer: |
| 93 case kTracerTypeDisjointTimer: | 117 case kTracerTypeDisjointTimer: |
| 94 glDeleteQueriesARB(2, queries_); | 118 glDeleteQueriesARB(2, queries_); |
| 95 break; | 119 break; |
| 96 } | 120 } |
| 97 } | 121 } |
| 98 | 122 |
| 99 void GPUTrace::Start(bool trace_service) { | 123 void GPUTrace::Start(bool trace_service) { |
| 100 if (trace_service) { | 124 if (trace_service) { |
| 101 TRACE_EVENT_COPY_ASYNC_BEGIN0(category().c_str(), name().c_str(), this); | 125 outputter_->TraceServiceBegin(category_, name_, this); |
| 102 } | 126 } |
| 103 | 127 |
| 104 switch (tracer_type_) { | 128 switch (tracer_type_) { |
| 105 case kTracerTypeInvalid: | 129 case kTracerTypeInvalid: |
| 106 break; | 130 break; |
| 107 | 131 |
| 108 case kTracerTypeDisjointTimer: | 132 case kTracerTypeDisjointTimer: |
| 109 // For the disjoint timer, GPU idle time does not seem to increment the | 133 // For the disjoint timer, GPU idle time does not seem to increment the |
| 110 // internal counter. We must calculate the offset before any query. The | 134 // internal counter. We must calculate the offset before any query. The |
| 111 // good news is any device that supports disjoint timer will also support | 135 // good news is any device that supports disjoint timer will also support |
| 112 // glGetInteger64v, so we can query it directly unlike the ARBTimer case. | 136 // glGetInteger64v, so we can query it directly unlike the ARBTimer case. |
| 113 // The "offset_" variable will always be 0 during normal use cases, only | 137 // The "offset_" variable will always be 0 during normal use cases, only |
| 114 // under the unit tests will it be set to specific test values. | 138 // under the unit tests will it be set to specific test values. |
| 115 if (offset_ == 0) { | 139 if (offset_ == 0) { |
| 116 GLint64 gl_now = 0; | 140 GLint64 gl_now = 0; |
| 117 glGetInteger64v(GL_TIMESTAMP, &gl_now); | 141 glGetInteger64v(GL_TIMESTAMP, &gl_now); |
| 118 offset_ = base::TimeTicks::NowFromSystemTraceTime().ToInternalValue() - | 142 offset_ = cpu_time_->GetCurrentTime() - |
| 119 gl_now / base::Time::kNanosecondsPerMicrosecond; | 143 gl_now / base::Time::kNanosecondsPerMicrosecond; |
| 120 } | 144 } |
| 121 // Intentionally fall through to kTracerTypeARBTimer case.xs | 145 // Intentionally fall through to kTracerTypeARBTimer case.xs |
| 122 case kTracerTypeARBTimer: | 146 case kTracerTypeARBTimer: |
| 123 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. | 147 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. |
| 124 glQueryCounter(queries_[0], GL_TIMESTAMP); | 148 glQueryCounter(queries_[0], GL_TIMESTAMP); |
| 125 break; | 149 break; |
| 126 } | 150 } |
| 127 } | 151 } |
| 128 | 152 |
| 129 void GPUTrace::End(bool tracing_service) { | 153 void GPUTrace::End(bool tracing_service) { |
| 130 end_requested_ = true; | 154 end_requested_ = true; |
| 131 switch (tracer_type_) { | 155 switch (tracer_type_) { |
| 132 case kTracerTypeInvalid: | 156 case kTracerTypeInvalid: |
| 133 break; | 157 break; |
| 134 | 158 |
| 135 case kTracerTypeARBTimer: | 159 case kTracerTypeARBTimer: |
| 136 case kTracerTypeDisjointTimer: | 160 case kTracerTypeDisjointTimer: |
| 137 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. | 161 // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. |
| 138 glQueryCounter(queries_[1], GL_TIMESTAMP); | 162 glQueryCounter(queries_[1], GL_TIMESTAMP); |
| 139 break; | 163 break; |
| 140 } | 164 } |
| 141 | 165 |
| 142 if (tracing_service) { | 166 if (tracing_service) { |
| 143 TRACE_EVENT_COPY_ASYNC_END0(category().c_str(), name().c_str(), this); | 167 outputter_->TraceServiceEnd(category_, name_, this); |
| 144 } | 168 } |
| 145 } | 169 } |
| 146 | 170 |
| 147 bool GPUTrace::IsAvailable() { | 171 bool GPUTrace::IsAvailable() { |
| 148 if (tracer_type_ != kTracerTypeInvalid) { | 172 if (tracer_type_ != kTracerTypeInvalid) { |
| 149 if (!end_requested_) | 173 if (!end_requested_) |
| 150 return false; | 174 return false; |
| 151 | 175 |
| 152 GLint done = 0; | 176 GLint done = 0; |
| 153 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); | 177 glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 168 | 192 |
| 169 // TODO(dsinclair): It's possible for the timer to wrap during the start/end. | 193 // TODO(dsinclair): It's possible for the timer to wrap during the start/end. |
| 170 // We need to detect if the end is less then the start and correct for the | 194 // We need to detect if the end is less then the start and correct for the |
| 171 // wrapping. | 195 // wrapping. |
| 172 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp); | 196 glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp); |
| 173 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp); | 197 glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp); |
| 174 | 198 |
| 175 start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) + | 199 start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) + |
| 176 offset_; | 200 offset_; |
| 177 end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_; | 201 end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_; |
| 178 outputter_->Trace(category(), name(), start_time_, end_time_); | 202 outputter_->TraceDevice(category(), name(), start_time_, end_time_); |
| 179 } | 203 } |
| 180 | 204 |
| 181 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) | 205 GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) |
| 182 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( | 206 : gpu_trace_srv_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( |
| 183 TRACE_DISABLED_BY_DEFAULT("gpu.service"))), | 207 TRACE_DISABLED_BY_DEFAULT("gpu.service"))), |
| 184 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( | 208 gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( |
| 185 TRACE_DISABLED_BY_DEFAULT("gpu.device"))), | 209 TRACE_DISABLED_BY_DEFAULT("gpu.device"))), |
| 186 decoder_(decoder), | 210 decoder_(decoder), |
| 187 timer_offset_(0), | 211 timer_offset_(0), |
| 188 last_tracer_source_(kTraceGroupInvalid), | 212 last_tracer_source_(kTraceGroupInvalid), |
| 189 tracer_type_(kTracerTypeInvalid), | 213 tracer_type_(kTracerTypeInvalid), |
| 190 gpu_timing_synced_(false), | 214 gpu_timing_synced_(false), |
| 191 gpu_executing_(false), | 215 gpu_executing_(false), |
| 192 process_posted_(false) { | 216 process_posted_(false) { |
| 193 if (gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) { | |
| 194 tracer_type_ = kTracerTypeDisjointTimer; | |
| 195 outputter_ = TraceOutputter::Create("GL_EXT_disjoint_timer_query"); | |
| 196 } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) { | |
| 197 tracer_type_ = kTracerTypeARBTimer; | |
| 198 outputter_ = TraceOutputter::Create("GL_ARB_timer_query"); | |
| 199 } | |
| 200 } | 217 } |
| 201 | 218 |
| 202 GPUTracer::~GPUTracer() { | 219 GPUTracer::~GPUTracer() { |
| 203 } | 220 } |
| 204 | 221 |
| 205 bool GPUTracer::BeginDecoding() { | 222 bool GPUTracer::BeginDecoding() { |
| 206 if (gpu_executing_) | 223 if (gpu_executing_) |
| 207 return false; | 224 return false; |
| 208 | 225 |
| 226 if (outputter_ == NULL) { | |
| 227 tracer_type_ = DetermineTracerType(); | |
| 228 const char* tracer_type_name = "Unknown"; | |
| 229 switch (tracer_type_) { | |
| 230 case kTracerTypeDisjointTimer: | |
| 231 tracer_type_name = "GL_EXT_disjoint_timer_query"; | |
| 232 break; | |
| 233 case kTracerTypeARBTimer: | |
| 234 tracer_type_name = "GL_ARB_timer_query"; | |
| 235 break; | |
| 236 | |
| 237 default: | |
| 238 break; | |
| 239 } | |
| 240 | |
| 241 outputter_ = CreateOutputter(tracer_type_name); | |
| 242 } | |
| 243 | |
| 244 if (cpu_time_ == NULL) { | |
| 245 cpu_time_ = CreateCPUTime(); | |
| 246 } | |
| 247 | |
| 209 CalculateTimerOffset(); | 248 CalculateTimerOffset(); |
| 210 gpu_executing_ = true; | 249 gpu_executing_ = true; |
| 211 | 250 |
| 212 if (IsTracing()) { | 251 if (IsTracing()) { |
| 213 // Reset disjoint bit for the disjoint timer. | 252 // Reset disjoint bit for the disjoint timer. |
| 214 if (tracer_type_ == kTracerTypeDisjointTimer) { | 253 if (tracer_type_ == kTracerTypeDisjointTimer) { |
| 215 GLint disjoint_value = 0; | 254 GLint disjoint_value = 0; |
| 216 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); | 255 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); |
| 217 } | 256 } |
| 218 | 257 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 320 return markers_[last_tracer_source_].back().name_; | 359 return markers_[last_tracer_source_].back().name_; |
| 321 } | 360 } |
| 322 return base::EmptyString(); | 361 return base::EmptyString(); |
| 323 } | 362 } |
| 324 | 363 |
| 325 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& category, | 364 scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& category, |
| 326 const std::string& name) { | 365 const std::string& name) { |
| 327 GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ : | 366 GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ : |
| 328 kTracerTypeInvalid; | 367 kTracerTypeInvalid; |
| 329 | 368 |
| 330 return new GPUTrace(outputter_, category, name, timer_offset_, tracer_type); | 369 return new GPUTrace(outputter_, cpu_time_, category, name, |
| 370 timer_offset_, tracer_type); | |
| 371 } | |
| 372 | |
| 373 scoped_refptr<Outputter> GPUTracer::CreateOutputter(const std::string& name) { | |
| 374 return TraceOutputter::Create(name); | |
| 375 } | |
| 376 | |
| 377 scoped_refptr<CPUTime> GPUTracer::CreateCPUTime() { | |
| 378 return new CPUTime(); | |
| 379 } | |
| 380 | |
| 381 GpuTracerType GPUTracer::DetermineTracerType() { | |
| 382 if (gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) { | |
| 383 return kTracerTypeDisjointTimer; | |
| 384 } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) { | |
| 385 return kTracerTypeARBTimer; | |
| 386 } | |
| 387 | |
| 388 return kTracerTypeInvalid; | |
| 389 } | |
| 390 | |
| 391 void GPUTracer::PostTask() { | |
| 392 base::MessageLoop::current()->PostDelayedTask( | |
| 393 FROM_HERE, | |
| 394 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)), | |
| 395 base::TimeDelta::FromMilliseconds(kProcessInterval)); | |
| 331 } | 396 } |
| 332 | 397 |
| 333 void GPUTracer::Process() { | 398 void GPUTracer::Process() { |
| 334 process_posted_ = false; | 399 process_posted_ = false; |
| 335 ProcessTraces(); | 400 ProcessTraces(); |
| 336 IssueProcessTask(); | 401 IssueProcessTask(); |
| 337 } | 402 } |
| 338 | 403 |
| 339 void GPUTracer::ProcessTraces() { | 404 void GPUTracer::ProcessTraces() { |
| 340 if (tracer_type_ == kTracerTypeInvalid) { | 405 if (tracer_type_ == kTracerTypeInvalid) { |
| 341 traces_.clear(); | 406 traces_.clear(); |
| 342 return; | 407 return; |
| 343 } | 408 } |
| 344 | 409 |
| 345 TRACE_EVENT0("gpu", "GPUTracer::ProcessTraces"); | 410 TRACE_EVENT0("gpu", "GPUTracer::ProcessTraces"); |
| 346 | 411 |
| 347 // Make owning decoder's GL context current | 412 // Make owning decoder's GL context current |
| 348 if (!decoder_->MakeCurrent()) { | 413 if (decoder_ && !decoder_->MakeCurrent()) { |
|
vmiura
2015/01/07 00:40:56
Should the tests use a mock decoder instead?
David Yen
2015/01/07 18:11:48
Done.
| |
| 349 // Skip subsequent GL calls if MakeCurrent fails | 414 // Skip subsequent GL calls if MakeCurrent fails |
| 350 traces_.clear(); | 415 traces_.clear(); |
| 351 return; | 416 return; |
| 352 } | 417 } |
| 353 | 418 |
| 354 // Check if disjoint operation has occurred, discard ongoing traces if so. | 419 // Check if disjoint operation has occurred, discard ongoing traces if so. |
| 355 if (tracer_type_ == kTracerTypeDisjointTimer) { | 420 if (tracer_type_ == kTracerTypeDisjointTimer) { |
| 356 GLint disjoint_value = 0; | 421 GLint disjoint_value = 0; |
| 357 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); | 422 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); |
| 358 if (disjoint_value) | 423 if (disjoint_value) |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 394 | 459 |
| 395 glGenQueriesARB(1, &query); | 460 glGenQueriesARB(1, &query); |
| 396 | 461 |
| 397 glFinish(); | 462 glFinish(); |
| 398 glQueryCounter(query, GL_TIMESTAMP); | 463 glQueryCounter(query, GL_TIMESTAMP); |
| 399 glFinish(); | 464 glFinish(); |
| 400 | 465 |
| 401 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now); | 466 glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now); |
| 402 glDeleteQueriesARB(1, &query); | 467 glDeleteQueriesARB(1, &query); |
| 403 | 468 |
| 404 base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime(); | |
| 405 | |
| 406 gl_now /= base::Time::kNanosecondsPerMicrosecond; | 469 gl_now /= base::Time::kNanosecondsPerMicrosecond; |
| 407 timer_offset_ = system_now.ToInternalValue() - gl_now; | 470 timer_offset_ = cpu_time_->GetCurrentTime() - gl_now; |
| 408 gpu_timing_synced_ = true; | 471 gpu_timing_synced_ = true; |
| 409 } | 472 } |
| 410 } | 473 } |
| 411 | 474 |
| 412 void GPUTracer::IssueProcessTask() { | 475 void GPUTracer::IssueProcessTask() { |
| 413 if (traces_.empty() || process_posted_) | 476 if (traces_.empty() || process_posted_) |
| 414 return; | 477 return; |
| 415 | 478 |
| 416 process_posted_ = true; | 479 process_posted_ = true; |
| 417 base::MessageLoop::current()->PostDelayedTask( | 480 PostTask(); |
| 418 FROM_HERE, | |
| 419 base::Bind(&GPUTracer::Process, base::AsWeakPtr(this)), | |
| 420 base::TimeDelta::FromMilliseconds(kProcessInterval)); | |
| 421 } | 481 } |
| 422 | 482 |
| 423 } // namespace gles2 | 483 } // namespace gles2 |
| 424 } // namespace gpu | 484 } // namespace gpu |
| OLD | NEW |