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 "ui/compositor/compositor.h" | 5 #include "ui/compositor/compositor.h" | 
| 6 | 6 | 
| 7 #include <algorithm> | 7 #include <algorithm> | 
| 8 #include <deque> | 8 #include <deque> | 
| 9 | 9 | 
| 10 #include "base/bind.h" | 10 #include "base/bind.h" | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 56 CancelLock(); | 56 CancelLock(); | 
| 57 } | 57 } | 
| 58 | 58 | 
| 59 void CompositorLock::CancelLock() { | 59 void CompositorLock::CancelLock() { | 
| 60 if (!compositor_) | 60 if (!compositor_) | 
| 61 return; | 61 return; | 
| 62 compositor_->UnlockCompositor(); | 62 compositor_->UnlockCompositor(); | 
| 63 compositor_ = NULL; | 63 compositor_ = NULL; | 
| 64 } | 64 } | 
| 65 | 65 | 
| 66 } // namespace ui | |
| 67 | |
| 68 namespace {} // namespace | |
| 69 | |
| 70 namespace ui { | |
| 71 | |
| 72 class SatisfySwapPromise : public cc::SwapPromise { | 66 class SatisfySwapPromise : public cc::SwapPromise { | 
| 73 public: | 67 public: | 
| 74 explicit SatisfySwapPromise(uint32_t id) : id_(id) {} | 68 explicit SatisfySwapPromise(uint32_t id) : id_(id) {} | 
| 75 | 69 | 
| 76 private: | 70 private: | 
| 77 virtual void DidSwap(cc::CompositorFrameMetadata* metadata) override { | 71 virtual void DidSwap(cc::CompositorFrameMetadata* metadata) override { | 
| 78 metadata->satisfies_sequences.push_back(id_); | 72 metadata->satisfies_sequences.push_back(id_); | 
| 79 } | 73 } | 
| 80 | 74 | 
| 81 virtual void DidNotSwap(DidNotSwapReason reason) override { | 75 virtual void DidNotSwap(DidNotSwapReason reason) override { | 
| 82 // TODO(jbauman): Send to the SurfaceManager immediately. | 76 // TODO(jbauman): Send to the SurfaceManager immediately. | 
| 83 DCHECK(false); | 77 DCHECK(false); | 
| 84 } | 78 } | 
| 85 virtual int64 TraceId() const override { return 0; } | 79 virtual int64 TraceId() const override { return 0; } | 
| 86 uint32_t id_; | 80 uint32_t id_; | 
| 87 }; | 81 }; | 
| 88 | 82 | 
| 89 Compositor::Compositor(gfx::AcceleratedWidget widget, | 83 Compositor::Compositor(gfx::AcceleratedWidget widget, | 
| 90 ui::ContextFactory* context_factory, | 84 ui::ContextFactory* context_factory, | 
| 91 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | 85 scoped_refptr<base::SingleThreadTaskRunner> task_runner) | 
| 92 : context_factory_(context_factory), | 86 : context_factory_(context_factory), | 
| 93 root_layer_(NULL), | 87 root_layer_(NULL), | 
| 94 widget_(widget), | 88 widget_(widget), | 
| 95 surface_id_allocator_(context_factory->CreateSurfaceIdAllocator()), | 89 surface_id_allocator_(context_factory->CreateSurfaceIdAllocator()), | 
| 96 surface_sequence_number_(0), | 90 surface_sequence_number_(0), | 
| 97 compositor_thread_loop_(context_factory->GetCompositorMessageLoop()), | 91 compositor_thread_loop_(context_factory->GetCompositorMessageLoop()), | 
| 98 task_runner_(task_runner), | 92 task_runner_(task_runner), | 
| 99 vsync_manager_(new CompositorVSyncManager()), | 93 vsync_manager_(new CompositorVSyncManager()), | 
| 100 device_scale_factor_(0.0f), | 94 device_scale_factor_(0.0f), | 
| 101 last_started_frame_(0), | |
| 102 last_ended_frame_(0), | |
| 103 disable_schedule_composite_(false), | 95 disable_schedule_composite_(false), | 
| 104 compositor_lock_(NULL), | 96 compositor_lock_(NULL), | 
| 105 defer_draw_scheduling_(false), | 97 layer_animator_collection_(this) { | 
| 106 waiting_on_compositing_end_(false), | |
| 107 draw_on_compositing_end_(false), | |
| 108 swap_state_(SWAP_NONE), | |
| 109 layer_animator_collection_(this), | |
| 110 schedule_draw_factory_(this) { | |
| 111 root_web_layer_ = cc::Layer::Create(); | 98 root_web_layer_ = cc::Layer::Create(); | 
| 112 | 99 | 
| 113 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 100 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 
| 114 | 101 | 
| 115 cc::LayerTreeSettings settings; | 102 cc::LayerTreeSettings settings; | 
| 116 settings.refresh_rate = | 103 settings.refresh_rate = | 
| 117 context_factory_->DoesCreateTestContexts() | 104 context_factory_->DoesCreateTestContexts() | 
| 118 ? kTestRefreshRate | 105 ? kTestRefreshRate | 
| 119 : kDefaultRefreshRate; | 106 : kDefaultRefreshRate; | 
| 120 settings.main_frame_before_activation_enabled = false; | 107 settings.main_frame_before_activation_enabled = false; | 
| (...skipping 27 matching lines...) Expand all Loading... | |
| 148 settings.initial_debug_state.show_occluding_rects = | 135 settings.initial_debug_state.show_occluding_rects = | 
| 149 command_line->HasSwitch(cc::switches::kUIShowOccludingRects); | 136 command_line->HasSwitch(cc::switches::kUIShowOccludingRects); | 
| 150 settings.initial_debug_state.show_non_occluding_rects = | 137 settings.initial_debug_state.show_non_occluding_rects = | 
| 151 command_line->HasSwitch(cc::switches::kUIShowNonOccludingRects); | 138 command_line->HasSwitch(cc::switches::kUIShowNonOccludingRects); | 
| 152 | 139 | 
| 153 settings.initial_debug_state.SetRecordRenderingStats( | 140 settings.initial_debug_state.SetRecordRenderingStats( | 
| 154 command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking)); | 141 command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking)); | 
| 155 | 142 | 
| 156 settings.impl_side_painting = IsUIImplSidePaintingEnabled(); | 143 settings.impl_side_painting = IsUIImplSidePaintingEnabled(); | 
| 157 settings.use_zero_copy = IsUIZeroCopyEnabled(); | 144 settings.use_zero_copy = IsUIZeroCopyEnabled(); | 
| 158 settings.single_thread_proxy_scheduler = false; | |
| 159 | 145 | 
| 160 base::TimeTicks before_create = base::TimeTicks::Now(); | 146 base::TimeTicks before_create = base::TimeTicks::Now(); | 
| 161 if (compositor_thread_loop_.get()) { | 147 if (compositor_thread_loop_.get()) { | 
| 162 host_ = cc::LayerTreeHost::CreateThreaded( | 148 host_ = cc::LayerTreeHost::CreateThreaded( | 
| 163 this, | 149 this, | 
| 164 context_factory_->GetSharedBitmapManager(), | 150 context_factory_->GetSharedBitmapManager(), | 
| 165 context_factory_->GetGpuMemoryBufferManager(), | 151 context_factory_->GetGpuMemoryBufferManager(), | 
| 166 settings, | 152 settings, | 
| 167 task_runner_, | 153 task_runner_, | 
| 168 compositor_thread_loop_); | 154 compositor_thread_loop_); | 
| (...skipping 22 matching lines...) Expand all Loading... | |
| 191 root_layer_->SetCompositor(NULL); | 177 root_layer_->SetCompositor(NULL); | 
| 192 | 178 | 
| 193 // Stop all outstanding draws before telling the ContextFactory to tear | 179 // Stop all outstanding draws before telling the ContextFactory to tear | 
| 194 // down any contexts that the |host_| may rely upon. | 180 // down any contexts that the |host_| may rely upon. | 
| 195 host_.reset(); | 181 host_.reset(); | 
| 196 | 182 | 
| 197 context_factory_->RemoveCompositor(this); | 183 context_factory_->RemoveCompositor(this); | 
| 198 } | 184 } | 
| 199 | 185 | 
| 200 void Compositor::ScheduleDraw() { | 186 void Compositor::ScheduleDraw() { | 
| 201 if (compositor_thread_loop_.get()) { | 187 host_->SetNeedsCommit(); | 
| 202 host_->SetNeedsCommit(); | |
| 203 } else if (!defer_draw_scheduling_) { | |
| 204 defer_draw_scheduling_ = true; | |
| 205 task_runner_->PostTask( | |
| 206 FROM_HERE, | |
| 207 base::Bind(&Compositor::Draw, schedule_draw_factory_.GetWeakPtr())); | |
| 208 } | |
| 209 } | 188 } | 
| 210 | 189 | 
| 211 void Compositor::SetRootLayer(Layer* root_layer) { | 190 void Compositor::SetRootLayer(Layer* root_layer) { | 
| 212 if (root_layer_ == root_layer) | 191 if (root_layer_ == root_layer) | 
| 213 return; | 192 return; | 
| 214 if (root_layer_) | 193 if (root_layer_) | 
| 215 root_layer_->SetCompositor(NULL); | 194 root_layer_->SetCompositor(NULL); | 
| 216 root_layer_ = root_layer; | 195 root_layer_ = root_layer; | 
| 217 if (root_layer_ && !root_layer_->GetCompositor()) | 196 if (root_layer_ && !root_layer_->GetCompositor()) | 
| 218 root_layer_->SetCompositor(this); | 197 root_layer_->SetCompositor(this); | 
| 219 root_web_layer_->RemoveAllChildren(); | 198 root_web_layer_->RemoveAllChildren(); | 
| 220 if (root_layer_) | 199 if (root_layer_) | 
| 221 root_web_layer_->AddChild(root_layer_->cc_layer()); | 200 root_web_layer_->AddChild(root_layer_->cc_layer()); | 
| 222 } | 201 } | 
| 223 | 202 | 
| 224 void Compositor::SetHostHasTransparentBackground( | 203 void Compositor::SetHostHasTransparentBackground( | 
| 225 bool host_has_transparent_background) { | 204 bool host_has_transparent_background) { | 
| 226 host_->set_has_transparent_background(host_has_transparent_background); | 205 host_->set_has_transparent_background(host_has_transparent_background); | 
| 227 } | 206 } | 
| 228 | 207 | 
| 229 void Compositor::Draw() { | |
| 230 DCHECK(!compositor_thread_loop_.get()); | |
| 231 | |
| 232 defer_draw_scheduling_ = false; | |
| 233 if (waiting_on_compositing_end_) { | |
| 234 draw_on_compositing_end_ = true; | |
| 235 return; | |
| 236 } | |
| 237 if (!root_layer_) | |
| 238 return; | |
| 239 | |
| 240 TRACE_EVENT_ASYNC_BEGIN0("ui", "Compositor::Draw", last_started_frame_ + 1); | |
| 241 | |
| 242 DCHECK_NE(swap_state_, SWAP_POSTED); | |
| 243 swap_state_ = SWAP_NONE; | |
| 244 | |
| 245 waiting_on_compositing_end_ = true; | |
| 246 last_started_frame_++; | |
| 247 if (!IsLocked()) { | |
| 248 // TODO(nduca): Temporary while compositor calls | |
| 249 // compositeImmediately() directly. | |
| 250 cc::BeginFrameArgs args = | |
| 251 cc::BeginFrameArgs::Create(gfx::FrameTime::Now(), | |
| 252 base::TimeTicks(), | |
| 253 cc::BeginFrameArgs::DefaultInterval()); | |
| 254 BeginMainFrame(args); | |
| 255 host_->Composite(args.frame_time); | |
| 256 } | |
| 257 if (swap_state_ == SWAP_NONE) | |
| 258 NotifyEnd(); | |
| 259 } | |
| 260 | |
| 261 void Compositor::ScheduleFullRedraw() { | 208 void Compositor::ScheduleFullRedraw() { | 
| 209 // TODO(enne): Some callers (mac) call this function expecting that it | |
| 210 // will also commit. This should probably just redraw the screen | |
| 211 // from damage and not commit. ScheduleDraw/ScheduleRedraw need | |
| 212 // better names. | |
| 262 host_->SetNeedsRedraw(); | 213 host_->SetNeedsRedraw(); | 
| 214 host_->SetNeedsCommit(); | |
| 263 } | 215 } | 
| 264 | 216 | 
| 265 void Compositor::ScheduleRedrawRect(const gfx::Rect& damage_rect) { | 217 void Compositor::ScheduleRedrawRect(const gfx::Rect& damage_rect) { | 
| 218 // TODO(enne): Make this not commit. See ScheduleFullRedraw. | |
| 266 host_->SetNeedsRedrawRect(damage_rect); | 219 host_->SetNeedsRedrawRect(damage_rect); | 
| 220 host_->SetNeedsCommit(); | |
| 267 } | 221 } | 
| 268 | 222 | 
| 269 void Compositor::FinishAllRendering() { | 223 void Compositor::FinishAllRendering() { | 
| 270 host_->FinishAllRendering(); | 224 host_->FinishAllRendering(); | 
| 271 } | 225 } | 
| 272 | 226 | 
| 273 void Compositor::SetLatencyInfo(const ui::LatencyInfo& latency_info) { | 227 void Compositor::SetLatencyInfo(const ui::LatencyInfo& latency_info) { | 
| 274 scoped_ptr<cc::SwapPromise> swap_promise( | 228 scoped_ptr<cc::SwapPromise> swap_promise( | 
| 275 new cc::LatencyInfoSwapPromise(latency_info)); | 229 new cc::LatencyInfoSwapPromise(latency_info)); | 
| 276 host_->QueueSwapPromise(swap_promise.Pass()); | 230 host_->QueueSwapPromise(swap_promise.Pass()); | 
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 339 void Compositor::RemoveAnimationObserver( | 293 void Compositor::RemoveAnimationObserver( | 
| 340 CompositorAnimationObserver* observer) { | 294 CompositorAnimationObserver* observer) { | 
| 341 animation_observer_list_.RemoveObserver(observer); | 295 animation_observer_list_.RemoveObserver(observer); | 
| 342 } | 296 } | 
| 343 | 297 | 
| 344 bool Compositor::HasAnimationObserver(CompositorAnimationObserver* observer) { | 298 bool Compositor::HasAnimationObserver(CompositorAnimationObserver* observer) { | 
| 345 return animation_observer_list_.HasObserver(observer); | 299 return animation_observer_list_.HasObserver(observer); | 
| 346 } | 300 } | 
| 347 | 301 | 
| 348 void Compositor::BeginMainFrame(const cc::BeginFrameArgs& args) { | 302 void Compositor::BeginMainFrame(const cc::BeginFrameArgs& args) { | 
| 303 // If a compositor lock is grabbed before BeginMainFrame, commit would be | |
| 304 // deferred. It is possible for compositor lock to be grabbed after | |
| 305 // BeginMainFrame, but then it is too late to stop commit and we will go | |
| 306 // through it anyway. | |
| 
 
piman
2014/10/14 20:50:11
I think that's a problem... It means we'll flash d
 
danakj
2014/10/14 20:52:49
Once beginframe has happened the main thread has a
 
 | |
| 307 DCHECK(!IsLocked()); | |
| 349 FOR_EACH_OBSERVER(CompositorAnimationObserver, | 308 FOR_EACH_OBSERVER(CompositorAnimationObserver, | 
| 350 animation_observer_list_, | 309 animation_observer_list_, | 
| 351 OnAnimationStep(args.frame_time)); | 310 OnAnimationStep(args.frame_time)); | 
| 352 if (animation_observer_list_.might_have_observers()) | 311 if (animation_observer_list_.might_have_observers()) | 
| 353 host_->SetNeedsAnimate(); | 312 host_->SetNeedsAnimate(); | 
| 354 } | 313 } | 
| 355 | 314 | 
| 356 void Compositor::Layout() { | 315 void Compositor::Layout() { | 
| 357 // We're sending damage that will be addressed during this composite | 316 // We're sending damage that will be addressed during this composite | 
| 358 // cycle, so we don't need to schedule another composite to address it. | 317 // cycle, so we don't need to schedule another composite to address it. | 
| 359 disable_schedule_composite_ = true; | 318 disable_schedule_composite_ = true; | 
| 360 if (root_layer_) | 319 if (root_layer_) | 
| 361 root_layer_->SendDamagedRects(); | 320 root_layer_->SendDamagedRects(); | 
| 362 disable_schedule_composite_ = false; | 321 disable_schedule_composite_ = false; | 
| 363 } | 322 } | 
| 364 | 323 | 
| 365 void Compositor::RequestNewOutputSurface(bool fallback) { | 324 void Compositor::RequestNewOutputSurface(bool fallback) { | 
| 366 host_->SetOutputSurface( | 325 host_->SetOutputSurface( | 
| 367 context_factory_->CreateOutputSurface(this, fallback)); | 326 context_factory_->CreateOutputSurface(this, fallback)); | 
| 368 } | 327 } | 
| 369 | 328 | 
| 370 void Compositor::DidCommit() { | 329 void Compositor::DidCommit() { | 
| 371 DCHECK(!IsLocked()); | |
| 372 FOR_EACH_OBSERVER(CompositorObserver, | 330 FOR_EACH_OBSERVER(CompositorObserver, | 
| 373 observer_list_, | 331 observer_list_, | 
| 374 OnCompositingDidCommit(this)); | 332 OnCompositingDidCommit(this)); | 
| 375 } | 333 } | 
| 376 | 334 | 
| 377 void Compositor::DidCommitAndDrawFrame() { | 335 void Compositor::DidCommitAndDrawFrame() { | 
| 336 } | |
| 337 | |
| 338 void Compositor::DidCompleteSwapBuffers() { | |
| 339 // DidPostSwapBuffers is a SingleThreadProxy-only feature. Synthetically | |
| 340 // generate OnCompositingStarted messages for the threaded case so that | |
| 341 // OnCompositingStarted/OnCompositingEnded messages match. | |
| 342 if (compositor_thread_loop_.get()) { | |
| 343 base::TimeTicks start_time = gfx::FrameTime::Now(); | |
| 344 FOR_EACH_OBSERVER(CompositorObserver, | |
| 345 observer_list_, | |
| 346 OnCompositingStarted(this, start_time)); | |
| 347 } | |
| 348 FOR_EACH_OBSERVER( | |
| 349 CompositorObserver, observer_list_, OnCompositingEnded(this)); | |
| 350 } | |
| 351 | |
| 352 void Compositor::DidPostSwapBuffers() { | |
| 378 base::TimeTicks start_time = gfx::FrameTime::Now(); | 353 base::TimeTicks start_time = gfx::FrameTime::Now(); | 
| 379 FOR_EACH_OBSERVER(CompositorObserver, | 354 FOR_EACH_OBSERVER(CompositorObserver, | 
| 380 observer_list_, | 355 observer_list_, | 
| 381 OnCompositingStarted(this, start_time)); | 356 OnCompositingStarted(this, start_time)); | 
| 382 } | 357 } | 
| 383 | 358 | 
| 384 void Compositor::DidCompleteSwapBuffers() { | |
| 385 if (compositor_thread_loop_.get()) { | |
| 386 NotifyEnd(); | |
| 387 } else { | |
| 388 DCHECK_EQ(swap_state_, SWAP_POSTED); | |
| 389 NotifyEnd(); | |
| 390 swap_state_ = SWAP_COMPLETED; | |
| 391 } | |
| 392 } | |
| 393 | |
| 394 void Compositor::ScheduleComposite() { | |
| 395 if (!disable_schedule_composite_) | |
| 396 ScheduleDraw(); | |
| 397 } | |
| 398 | |
| 399 void Compositor::ScheduleAnimation() { | |
| 400 ScheduleComposite(); | |
| 401 } | |
| 402 | |
| 403 void Compositor::DidPostSwapBuffers() { | |
| 404 DCHECK(!compositor_thread_loop_.get()); | |
| 405 DCHECK_EQ(swap_state_, SWAP_NONE); | |
| 406 swap_state_ = SWAP_POSTED; | |
| 407 } | |
| 408 | |
| 409 void Compositor::DidAbortSwapBuffers() { | 359 void Compositor::DidAbortSwapBuffers() { | 
| 410 if (!compositor_thread_loop_.get()) { | |
| 411 if (swap_state_ == SWAP_POSTED) { | |
| 412 NotifyEnd(); | |
| 413 swap_state_ = SWAP_COMPLETED; | |
| 414 } | |
| 415 } | |
| 416 | |
| 417 FOR_EACH_OBSERVER(CompositorObserver, | 360 FOR_EACH_OBSERVER(CompositorObserver, | 
| 418 observer_list_, | 361 observer_list_, | 
| 419 OnCompositingAborted(this)); | 362 OnCompositingAborted(this)); | 
| 420 } | 363 } | 
| 421 | 364 | 
| 422 const cc::LayerTreeDebugState& Compositor::GetLayerTreeDebugState() const { | 365 const cc::LayerTreeDebugState& Compositor::GetLayerTreeDebugState() const { | 
| 423 return host_->debug_state(); | 366 return host_->debug_state(); | 
| 424 } | 367 } | 
| 425 | 368 | 
| 426 void Compositor::SetLayerTreeDebugState( | 369 void Compositor::SetLayerTreeDebugState( | 
| 427 const cc::LayerTreeDebugState& debug_state) { | 370 const cc::LayerTreeDebugState& debug_state) { | 
| 428 host_->SetDebugState(debug_state); | 371 host_->SetDebugState(debug_state); | 
| 429 } | 372 } | 
| 430 | 373 | 
| 431 cc::SurfaceSequence Compositor::InsertSurfaceSequenceForNextFrame() { | 374 cc::SurfaceSequence Compositor::InsertSurfaceSequenceForNextFrame() { | 
| 432 cc::SurfaceSequence sequence; | 375 cc::SurfaceSequence sequence; | 
| 433 sequence.id_namespace = surface_id_allocator_->id_namespace(); | 376 sequence.id_namespace = surface_id_allocator_->id_namespace(); | 
| 434 sequence.sequence = ++surface_sequence_number_; | 377 sequence.sequence = ++surface_sequence_number_; | 
| 435 scoped_ptr<cc::SwapPromise> promise( | 378 scoped_ptr<cc::SwapPromise> promise( | 
| 436 new SatisfySwapPromise(surface_sequence_number_)); | 379 new SatisfySwapPromise(surface_sequence_number_)); | 
| 437 host_->QueueSwapPromise(promise.Pass()); | 380 host_->QueueSwapPromise(promise.Pass()); | 
| 438 return sequence; | 381 return sequence; | 
| 439 } | 382 } | 
| 440 | 383 | 
| 441 scoped_refptr<CompositorLock> Compositor::GetCompositorLock() { | 384 scoped_refptr<CompositorLock> Compositor::GetCompositorLock() { | 
| 442 if (!compositor_lock_) { | 385 if (!compositor_lock_) { | 
| 443 compositor_lock_ = new CompositorLock(this); | 386 compositor_lock_ = new CompositorLock(this); | 
| 444 if (compositor_thread_loop_.get()) | 387 host_->SetDeferCommits(true); | 
| 445 host_->SetDeferCommits(true); | |
| 446 FOR_EACH_OBSERVER(CompositorObserver, | 388 FOR_EACH_OBSERVER(CompositorObserver, | 
| 447 observer_list_, | 389 observer_list_, | 
| 448 OnCompositingLockStateChanged(this)); | 390 OnCompositingLockStateChanged(this)); | 
| 449 } | 391 } | 
| 450 return compositor_lock_; | 392 return compositor_lock_; | 
| 451 } | 393 } | 
| 452 | 394 | 
| 453 void Compositor::UnlockCompositor() { | 395 void Compositor::UnlockCompositor() { | 
| 454 DCHECK(compositor_lock_); | 396 DCHECK(compositor_lock_); | 
| 455 compositor_lock_ = NULL; | 397 compositor_lock_ = NULL; | 
| 456 if (compositor_thread_loop_.get()) | 398 host_->SetDeferCommits(false); | 
| 457 host_->SetDeferCommits(false); | |
| 458 FOR_EACH_OBSERVER(CompositorObserver, | 399 FOR_EACH_OBSERVER(CompositorObserver, | 
| 459 observer_list_, | 400 observer_list_, | 
| 460 OnCompositingLockStateChanged(this)); | 401 OnCompositingLockStateChanged(this)); | 
| 461 } | 402 } | 
| 462 | 403 | 
| 463 void Compositor::CancelCompositorLock() { | 404 void Compositor::CancelCompositorLock() { | 
| 464 if (compositor_lock_) | 405 if (compositor_lock_) | 
| 465 compositor_lock_->CancelLock(); | 406 compositor_lock_->CancelLock(); | 
| 466 } | 407 } | 
| 467 | 408 | 
| 468 void Compositor::NotifyEnd() { | |
| 469 last_ended_frame_++; | |
| 470 TRACE_EVENT_ASYNC_END0("ui", "Compositor::Draw", last_ended_frame_); | |
| 471 waiting_on_compositing_end_ = false; | |
| 472 if (draw_on_compositing_end_) { | |
| 473 draw_on_compositing_end_ = false; | |
| 474 | |
| 475 // Call ScheduleDraw() instead of Draw() in order to allow other | |
| 476 // CompositorObservers to be notified before starting another | |
| 477 // draw cycle. | |
| 478 ScheduleDraw(); | |
| 479 } | |
| 480 FOR_EACH_OBSERVER( | |
| 481 CompositorObserver, observer_list_, OnCompositingEnded(this)); | |
| 482 } | |
| 483 | |
| 484 } // namespace ui | 409 } // namespace ui | 
| OLD | NEW |