Index: content/browser/renderer_host/compositor_impl_android.cc |
diff --git a/content/browser/renderer_host/compositor_impl_android.cc b/content/browser/renderer_host/compositor_impl_android.cc |
index 2e8e8825d31f4c3f7804e9d1fc078e0362ac75a6..dacf72fd7641a51fc47dd682ca6886c2e04db00b 100644 |
--- a/content/browser/renderer_host/compositor_impl_android.cc |
+++ b/content/browser/renderer_host/compositor_impl_android.cc |
@@ -238,7 +238,14 @@ CompositorImpl::CompositorImpl(CompositorClient* client, |
window_(NULL), |
surface_id_(0), |
client_(client), |
- root_window_(root_window) { |
+ root_window_(root_window), |
+ did_post_swapbuffers_(false), |
+ ignore_schedule_composite_(false), |
+ needs_composite_(false), |
+ should_composite_on_vsync_(false), |
+ did_composite_outside_vsync_(false), |
+ pending_swapbuffers_(0U), |
+ weak_factory_(this) { |
DCHECK(client); |
DCHECK(root_window); |
ImageTransportFactoryAndroid::AddObserver(this); |
@@ -252,9 +259,64 @@ CompositorImpl::~CompositorImpl() { |
SetSurface(NULL); |
} |
-void CompositorImpl::Composite() { |
- if (host_) |
- host_->Composite(gfx::FrameTime::Now()); |
+void CompositorImpl::PostComposite(base::TimeDelta delay) { |
+ base::MessageLoop::current()->PostDelayedTask( |
Sami
2014/05/09 13:21:14
Is there a chance we could post this task several
no sievers
2014/05/09 22:53:44
ScheduleComposite() has an early-out if needs_comp
|
+ FROM_HERE, |
+ base::Bind(&CompositorImpl::Composite, weak_factory_.GetWeakPtr(), false), |
+ delay); |
+} |
+ |
+void CompositorImpl::Composite(bool is_vsync) { |
+ if (!host_) |
+ return; |
+ |
+ if (!needs_composite_) |
+ return; |
+ |
+ if (!is_vsync && should_composite_on_vsync_) { |
+ TRACE_EVENT0("compositor", "CompositorImpl_DeferCompositeToVSync"); |
+ root_window_->RequestVSyncUpdate(); |
+ return; |
+ } |
+ |
+ // Don't Composite immediately more than once in between vsync ticks. |
Sami
2014/05/09 13:21:14
Maybe add something like this as a safeguard: DCHE
no sievers
2014/05/09 22:53:44
Actually obsolete now with your other comment addr
|
+ if (did_composite_outside_vsync_) { |
+ TRACE_EVENT0("compositor", "CompositorImpl_ThrottleComposite"); |
+ PostComposite(vsync_period_); |
Sami
2014/05/09 13:21:14
Just thinking out loud here: we generally composit
no sievers
2014/05/09 22:53:44
Yea I was wondering too and logged when it happens
|
+ return; |
+ } |
+ |
+ const unsigned int kMaxSwapBuffers = 2U; |
+ DCHECK_LE(pending_swapbuffers_, kMaxSwapBuffers); |
+ if (pending_swapbuffers_ == kMaxSwapBuffers) { |
+ TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit"); |
+ if (should_composite_on_vsync_) |
+ root_window_->RequestVSyncUpdate(); |
+ else |
+ PostComposite(vsync_period_); |
Sami
2014/05/09 13:21:14
Should we instead trigger the composite as soon as
no sievers
2014/05/09 22:53:44
I was actually wondering if this is better for lat
|
+ return; |
+ } |
+ |
+ // Reset state before Layout+Composite since that might create more |
+ // requests to Composite that we need to respect. |
+ needs_composite_ = false; |
+ should_composite_on_vsync_ = false; |
+ |
+ // Ignore ScheduleComposite() from layer tree changes during Layout. |
+ ignore_schedule_composite_ = true; |
+ client_->Layout(); |
+ ignore_schedule_composite_ = false; |
+ |
+ did_post_swapbuffers_ = false; |
+ host_->Composite(gfx::FrameTime::Now()); |
Sami
2014/05/09 13:21:14
This should probably be derived from the most rece
no sievers
2014/05/09 22:53:44
Hmm if we composite on vsync, now is the vsync tim
|
+ if (did_post_swapbuffers_) |
+ pending_swapbuffers_++; |
+ |
+ if (!is_vsync) { |
+ // Need to track vsync to avoid compositing more than once per frame. |
+ root_window_->RequestVSyncUpdate(); |
+ did_composite_outside_vsync_ = true; |
+ } |
} |
void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) { |
@@ -316,6 +378,10 @@ void CompositorImpl::SetVisible(bool visible) { |
host_.reset(); |
client_->UIResourcesAreInvalid(); |
} else if (!host_) { |
+ needs_composite_ = false; |
+ did_composite_outside_vsync_ = false; |
+ should_composite_on_vsync_ = false; |
+ pending_swapbuffers_ = 0; |
cc::LayerTreeSettings settings; |
settings.refresh_rate = 60.0; |
settings.impl_side_painting = false; |
@@ -374,6 +440,15 @@ bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) { |
return false; |
} |
+void CompositorImpl::SetNeedsComposite() { |
+ if (!host_.get()) |
+ return; |
+ |
+ needs_composite_ = true; |
+ should_composite_on_vsync_ = true; |
Sami
2014/05/09 13:21:14
Doesn't this have the effect of re-scheduling any
no sievers
2014/05/09 22:53:44
Done.
|
+ root_window_->RequestVSyncUpdate(); |
+} |
+ |
cc::UIResourceId CompositorImpl::GenerateUIResourceFromUIResourceBitmap( |
const cc::UIResourceBitmap& bitmap, |
bool is_transient) { |
@@ -468,6 +543,13 @@ CreateGpuProcessViewContext( |
NULL)); |
} |
+void CompositorImpl::Layout() { |
+ // TODO: If we get this callback from the SingleThreadProxy, we need |
+ // to stop calling it ourselves in Composite() below. |
Sami
2014/05/09 13:21:14
Composite() is above, not below :)
no sievers
2014/05/09 22:53:44
Done :)
|
+ NOTREACHED(); |
+ client_->Layout(); |
+} |
+ |
scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface( |
bool fallback) { |
blink::WebGraphicsContext3D::Attributes attrs; |
@@ -493,12 +575,12 @@ void CompositorImpl::OnLostResources() { |
client_->DidLoseResources(); |
} |
-void CompositorImpl::DidCompleteSwapBuffers() { |
- client_->OnSwapBuffersCompleted(); |
-} |
- |
void CompositorImpl::ScheduleComposite() { |
- client_->ScheduleComposite(); |
+ if (needs_composite_ || ignore_schedule_composite_) |
+ return; |
+ |
+ needs_composite_ = true; |
+ PostComposite(base::TimeDelta()); |
} |
void CompositorImpl::ScheduleAnimation() { |
@@ -507,12 +589,19 @@ void CompositorImpl::ScheduleAnimation() { |
void CompositorImpl::DidPostSwapBuffers() { |
TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers"); |
- client_->OnSwapBuffersPosted(); |
+ did_post_swapbuffers_ = true; |
+} |
+ |
+void CompositorImpl::DidCompleteSwapBuffers() { |
+ TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers"); |
+ DCHECK_GT(pending_swapbuffers_, 0U); |
+ client_->OnSwapBuffersCompleted(pending_swapbuffers_--); |
} |
void CompositorImpl::DidAbortSwapBuffers() { |
TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers"); |
- client_->OnSwapBuffersCompleted(); |
+ DCHECK_GT(pending_swapbuffers_, 0U); |
+ client_->OnSwapBuffersCompleted(pending_swapbuffers_--); |
} |
void CompositorImpl::DidCommit() { |
@@ -523,4 +612,13 @@ void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) { |
root_layer_->AddChild(layer); |
} |
+void CompositorImpl::OnVSync(base::TimeTicks frame_time, |
+ base::TimeDelta vsync_period) { |
+ vsync_period_ = vsync_period; |
+ did_composite_outside_vsync_ = false; |
+ |
+ if (should_composite_on_vsync_) |
+ Composite(true); |
+} |
+ |
} // namespace content |