| Index: trunk/src/ui/compositor/compositor.cc
 | 
| ===================================================================
 | 
| --- trunk/src/ui/compositor/compositor.cc	(revision 287765)
 | 
| +++ trunk/src/ui/compositor/compositor.cc	(working copy)
 | 
| @@ -61,6 +61,14 @@
 | 
|    compositor_ = NULL;
 | 
|  }
 | 
|  
 | 
| +}  // namespace ui
 | 
| +
 | 
| +namespace {
 | 
| +
 | 
| +}  // namespace
 | 
| +
 | 
| +namespace ui {
 | 
| +
 | 
|  Compositor::Compositor(gfx::AcceleratedWidget widget,
 | 
|                         ui::ContextFactory* context_factory,
 | 
|                         scoped_refptr<base::SingleThreadTaskRunner> task_runner)
 | 
| @@ -71,9 +79,16 @@
 | 
|        task_runner_(task_runner),
 | 
|        vsync_manager_(new CompositorVSyncManager()),
 | 
|        device_scale_factor_(0.0f),
 | 
| +      last_started_frame_(0),
 | 
| +      last_ended_frame_(0),
 | 
|        disable_schedule_composite_(false),
 | 
|        compositor_lock_(NULL),
 | 
| -      layer_animator_collection_(this) {
 | 
| +      defer_draw_scheduling_(false),
 | 
| +      waiting_on_compositing_end_(false),
 | 
| +      draw_on_compositing_end_(false),
 | 
| +      swap_state_(SWAP_NONE),
 | 
| +      layer_animator_collection_(this),
 | 
| +      schedule_draw_factory_(this) {
 | 
|    root_web_layer_ = cc::Layer::Create();
 | 
|  
 | 
|    CommandLine* command_line = CommandLine::ForCurrentProcess();
 | 
| @@ -162,7 +177,14 @@
 | 
|  }
 | 
|  
 | 
|  void Compositor::ScheduleDraw() {
 | 
| -  host_->SetNeedsCommit();
 | 
| +  if (compositor_thread_loop_) {
 | 
| +    host_->SetNeedsCommit();
 | 
| +  } else if (!defer_draw_scheduling_) {
 | 
| +    defer_draw_scheduling_ = true;
 | 
| +    task_runner_->PostTask(
 | 
| +        FROM_HERE,
 | 
| +        base::Bind(&Compositor::Draw, schedule_draw_factory_.GetWeakPtr()));
 | 
| +  }
 | 
|  }
 | 
|  
 | 
|  void Compositor::SetRootLayer(Layer* root_layer) {
 | 
| @@ -183,19 +205,42 @@
 | 
|    host_->set_has_transparent_background(host_has_transparent_background);
 | 
|  }
 | 
|  
 | 
| +void Compositor::Draw() {
 | 
| +  DCHECK(!compositor_thread_loop_);
 | 
| +
 | 
| +  defer_draw_scheduling_ = false;
 | 
| +  if (waiting_on_compositing_end_) {
 | 
| +    draw_on_compositing_end_ = true;
 | 
| +    return;
 | 
| +  }
 | 
| +  if (!root_layer_)
 | 
| +    return;
 | 
| +
 | 
| +  TRACE_EVENT_ASYNC_BEGIN0("ui", "Compositor::Draw", last_started_frame_ + 1);
 | 
| +
 | 
| +  DCHECK_NE(swap_state_, SWAP_POSTED);
 | 
| +  swap_state_ = SWAP_NONE;
 | 
| +
 | 
| +  waiting_on_compositing_end_ = true;
 | 
| +  last_started_frame_++;
 | 
| +  if (!IsLocked()) {
 | 
| +    // TODO(nduca): Temporary while compositor calls
 | 
| +    // compositeImmediately() directly.
 | 
| +    base::TimeTicks now = gfx::FrameTime::Now();
 | 
| +    Animate(now);
 | 
| +    Layout();
 | 
| +    host_->Composite(now);
 | 
| +  }
 | 
| +  if (swap_state_ == SWAP_NONE)
 | 
| +    NotifyEnd();
 | 
| +}
 | 
| +
 | 
|  void Compositor::ScheduleFullRedraw() {
 | 
| -  // TODO(enne): Some callers (mac) call this function expecting that it
 | 
| -  // will also commit.  This should probably just redraw the screen
 | 
| -  // from damage and not commit.  ScheduleDraw/ScheduleRedraw need
 | 
| -  // better names.
 | 
|    host_->SetNeedsRedraw();
 | 
| -  host_->SetNeedsCommit();
 | 
|  }
 | 
|  
 | 
|  void Compositor::ScheduleRedrawRect(const gfx::Rect& damage_rect) {
 | 
| -  // TODO(enne): Make this not commit.  See ScheduleFullRedraw.
 | 
|    host_->SetNeedsRedrawRect(damage_rect);
 | 
| -  host_->SetNeedsCommit();
 | 
|  }
 | 
|  
 | 
|  void Compositor::FinishAllRendering() {
 | 
| @@ -287,30 +332,45 @@
 | 
|  }
 | 
|  
 | 
|  void Compositor::DidCommitAndDrawFrame() {
 | 
| +  base::TimeTicks start_time = gfx::FrameTime::Now();
 | 
| +  FOR_EACH_OBSERVER(CompositorObserver,
 | 
| +                    observer_list_,
 | 
| +                    OnCompositingStarted(this, start_time));
 | 
|  }
 | 
|  
 | 
|  void Compositor::DidCompleteSwapBuffers() {
 | 
| -  // DidPostSwapBuffers is a SingleThreadProxy-only feature.  Synthetically
 | 
| -  // generate OnCompositingStarted messages for the threaded case so that
 | 
| -  // OnCompositingStarted/OnCompositingEnded messages match.
 | 
|    if (compositor_thread_loop_) {
 | 
| -    base::TimeTicks start_time = gfx::FrameTime::Now();
 | 
| -    FOR_EACH_OBSERVER(CompositorObserver,
 | 
| -                      observer_list_,
 | 
| -                      OnCompositingStarted(this, start_time));
 | 
| +    NotifyEnd();
 | 
| +  } else {
 | 
| +    DCHECK_EQ(swap_state_, SWAP_POSTED);
 | 
| +    NotifyEnd();
 | 
| +    swap_state_ = SWAP_COMPLETED;
 | 
|    }
 | 
| -  FOR_EACH_OBSERVER(
 | 
| -      CompositorObserver, observer_list_, OnCompositingEnded(this));
 | 
|  }
 | 
|  
 | 
| +void Compositor::ScheduleComposite() {
 | 
| +  if (!disable_schedule_composite_)
 | 
| +    ScheduleDraw();
 | 
| +}
 | 
| +
 | 
| +void Compositor::ScheduleAnimation() {
 | 
| +  ScheduleComposite();
 | 
| +}
 | 
| +
 | 
|  void Compositor::DidPostSwapBuffers() {
 | 
| -  base::TimeTicks start_time = gfx::FrameTime::Now();
 | 
| -  FOR_EACH_OBSERVER(CompositorObserver,
 | 
| -                    observer_list_,
 | 
| -                    OnCompositingStarted(this, start_time));
 | 
| +  DCHECK(!compositor_thread_loop_);
 | 
| +  DCHECK_EQ(swap_state_, SWAP_NONE);
 | 
| +  swap_state_ = SWAP_POSTED;
 | 
|  }
 | 
|  
 | 
|  void Compositor::DidAbortSwapBuffers() {
 | 
| +  if (!compositor_thread_loop_) {
 | 
| +    if (swap_state_ == SWAP_POSTED) {
 | 
| +      NotifyEnd();
 | 
| +      swap_state_ = SWAP_COMPLETED;
 | 
| +    }
 | 
| +  }
 | 
| +
 | 
|    FOR_EACH_OBSERVER(CompositorObserver,
 | 
|                      observer_list_,
 | 
|                      OnCompositingAborted(this));
 | 
| @@ -328,7 +388,8 @@
 | 
|  scoped_refptr<CompositorLock> Compositor::GetCompositorLock() {
 | 
|    if (!compositor_lock_) {
 | 
|      compositor_lock_ = new CompositorLock(this);
 | 
| -    host_->SetDeferCommits(true);
 | 
| +    if (compositor_thread_loop_)
 | 
| +      host_->SetDeferCommits(true);
 | 
|      FOR_EACH_OBSERVER(CompositorObserver,
 | 
|                        observer_list_,
 | 
|                        OnCompositingLockStateChanged(this));
 | 
| @@ -339,7 +400,8 @@
 | 
|  void Compositor::UnlockCompositor() {
 | 
|    DCHECK(compositor_lock_);
 | 
|    compositor_lock_ = NULL;
 | 
| -  host_->SetDeferCommits(false);
 | 
| +  if (compositor_thread_loop_)
 | 
| +    host_->SetDeferCommits(false);
 | 
|    FOR_EACH_OBSERVER(CompositorObserver,
 | 
|                      observer_list_,
 | 
|                      OnCompositingLockStateChanged(this));
 | 
| @@ -350,4 +412,21 @@
 | 
|      compositor_lock_->CancelLock();
 | 
|  }
 | 
|  
 | 
| +void Compositor::NotifyEnd() {
 | 
| +  last_ended_frame_++;
 | 
| +  TRACE_EVENT_ASYNC_END0("ui", "Compositor::Draw", last_ended_frame_);
 | 
| +  waiting_on_compositing_end_ = false;
 | 
| +  if (draw_on_compositing_end_) {
 | 
| +    draw_on_compositing_end_ = false;
 | 
| +
 | 
| +    // Call ScheduleDraw() instead of Draw() in order to allow other
 | 
| +    // CompositorObservers to be notified before starting another
 | 
| +    // draw cycle.
 | 
| +    ScheduleDraw();
 | 
| +  }
 | 
| +  FOR_EACH_OBSERVER(CompositorObserver,
 | 
| +                    observer_list_,
 | 
| +                    OnCompositingEnded(this));
 | 
| +}
 | 
| +
 | 
|  }  // namespace ui
 | 
| 
 |