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 "content/browser/renderer_host/compositor_impl_android.h" | 5 #include "content/browser/renderer_host/compositor_impl_android.h" |
6 | 6 |
7 #include <android/bitmap.h> | 7 #include <android/bitmap.h> |
8 #include <android/native_window_jni.h> | 8 #include <android/native_window_jni.h> |
9 | 9 |
10 #include "base/android/jni_android.h" | 10 #include "base/android/jni_android.h" |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
231 } | 231 } |
232 | 232 |
233 CompositorImpl::CompositorImpl(CompositorClient* client, | 233 CompositorImpl::CompositorImpl(CompositorClient* client, |
234 gfx::NativeWindow root_window) | 234 gfx::NativeWindow root_window) |
235 : root_layer_(cc::Layer::Create()), | 235 : root_layer_(cc::Layer::Create()), |
236 has_transparent_background_(false), | 236 has_transparent_background_(false), |
237 device_scale_factor_(1), | 237 device_scale_factor_(1), |
238 window_(NULL), | 238 window_(NULL), |
239 surface_id_(0), | 239 surface_id_(0), |
240 client_(client), | 240 client_(client), |
241 root_window_(root_window) { | 241 root_window_(root_window), |
242 did_post_swapbuffers_(false), | |
243 ignore_schedule_composite_(false), | |
244 needs_composite_(false), | |
245 should_composite_on_vsync_(false), | |
246 did_composite_outside_vsync_(false), | |
247 pending_swapbuffers_(0U), | |
248 weak_factory_(this) { | |
242 DCHECK(client); | 249 DCHECK(client); |
243 DCHECK(root_window); | 250 DCHECK(root_window); |
244 ImageTransportFactoryAndroid::AddObserver(this); | 251 ImageTransportFactoryAndroid::AddObserver(this); |
245 root_window->AttachCompositor(this); | 252 root_window->AttachCompositor(this); |
246 } | 253 } |
247 | 254 |
248 CompositorImpl::~CompositorImpl() { | 255 CompositorImpl::~CompositorImpl() { |
249 root_window_->DetachCompositor(); | 256 root_window_->DetachCompositor(); |
250 ImageTransportFactoryAndroid::RemoveObserver(this); | 257 ImageTransportFactoryAndroid::RemoveObserver(this); |
251 // Clean-up any surface references. | 258 // Clean-up any surface references. |
252 SetSurface(NULL); | 259 SetSurface(NULL); |
253 } | 260 } |
254 | 261 |
255 void CompositorImpl::Composite() { | 262 void CompositorImpl::PostComposite(base::TimeDelta delay) { |
256 if (host_) | 263 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
| |
257 host_->Composite(gfx::FrameTime::Now()); | 264 FROM_HERE, |
265 base::Bind(&CompositorImpl::Composite, weak_factory_.GetWeakPtr(), false), | |
266 delay); | |
267 } | |
268 | |
269 void CompositorImpl::Composite(bool is_vsync) { | |
270 if (!host_) | |
271 return; | |
272 | |
273 if (!needs_composite_) | |
274 return; | |
275 | |
276 if (!is_vsync && should_composite_on_vsync_) { | |
277 TRACE_EVENT0("compositor", "CompositorImpl_DeferCompositeToVSync"); | |
278 root_window_->RequestVSyncUpdate(); | |
279 return; | |
280 } | |
281 | |
282 // 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
| |
283 if (did_composite_outside_vsync_) { | |
284 TRACE_EVENT0("compositor", "CompositorImpl_ThrottleComposite"); | |
285 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
| |
286 return; | |
287 } | |
288 | |
289 const unsigned int kMaxSwapBuffers = 2U; | |
290 DCHECK_LE(pending_swapbuffers_, kMaxSwapBuffers); | |
291 if (pending_swapbuffers_ == kMaxSwapBuffers) { | |
292 TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit"); | |
293 if (should_composite_on_vsync_) | |
294 root_window_->RequestVSyncUpdate(); | |
295 else | |
296 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
| |
297 return; | |
298 } | |
299 | |
300 // Reset state before Layout+Composite since that might create more | |
301 // requests to Composite that we need to respect. | |
302 needs_composite_ = false; | |
303 should_composite_on_vsync_ = false; | |
304 | |
305 // Ignore ScheduleComposite() from layer tree changes during Layout. | |
306 ignore_schedule_composite_ = true; | |
307 client_->Layout(); | |
308 ignore_schedule_composite_ = false; | |
309 | |
310 did_post_swapbuffers_ = false; | |
311 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
| |
312 if (did_post_swapbuffers_) | |
313 pending_swapbuffers_++; | |
314 | |
315 if (!is_vsync) { | |
316 // Need to track vsync to avoid compositing more than once per frame. | |
317 root_window_->RequestVSyncUpdate(); | |
318 did_composite_outside_vsync_ = true; | |
319 } | |
258 } | 320 } |
259 | 321 |
260 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) { | 322 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) { |
261 root_layer_->RemoveAllChildren(); | 323 root_layer_->RemoveAllChildren(); |
262 if (root_layer) | 324 if (root_layer) |
263 root_layer_->AddChild(root_layer); | 325 root_layer_->AddChild(root_layer); |
264 } | 326 } |
265 | 327 |
266 void CompositorImpl::SetWindowSurface(ANativeWindow* window) { | 328 void CompositorImpl::SetWindowSurface(ANativeWindow* window) { |
267 GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get(); | 329 GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
309 content::RegisterViewSurface(surface_id_, j_surface.obj()); | 371 content::RegisterViewSurface(surface_id_, j_surface.obj()); |
310 } | 372 } |
311 } | 373 } |
312 | 374 |
313 void CompositorImpl::SetVisible(bool visible) { | 375 void CompositorImpl::SetVisible(bool visible) { |
314 if (!visible) { | 376 if (!visible) { |
315 ui_resource_map_.clear(); | 377 ui_resource_map_.clear(); |
316 host_.reset(); | 378 host_.reset(); |
317 client_->UIResourcesAreInvalid(); | 379 client_->UIResourcesAreInvalid(); |
318 } else if (!host_) { | 380 } else if (!host_) { |
381 needs_composite_ = false; | |
382 did_composite_outside_vsync_ = false; | |
383 should_composite_on_vsync_ = false; | |
384 pending_swapbuffers_ = 0; | |
319 cc::LayerTreeSettings settings; | 385 cc::LayerTreeSettings settings; |
320 settings.refresh_rate = 60.0; | 386 settings.refresh_rate = 60.0; |
321 settings.impl_side_painting = false; | 387 settings.impl_side_painting = false; |
322 settings.allow_antialiasing = false; | 388 settings.allow_antialiasing = false; |
323 settings.calculate_top_controls_position = false; | 389 settings.calculate_top_controls_position = false; |
324 settings.top_controls_height = 0.f; | 390 settings.top_controls_height = 0.f; |
325 settings.highp_threshold_min = 2048; | 391 settings.highp_threshold_min = 2048; |
326 | 392 |
327 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 393 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
328 settings.initial_debug_state.SetRecordRenderingStats( | 394 settings.initial_debug_state.SetRecordRenderingStats( |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 host_->set_has_transparent_background(flag); | 433 host_->set_has_transparent_background(flag); |
368 } | 434 } |
369 | 435 |
370 bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) { | 436 bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) { |
371 if (host_) | 437 if (host_) |
372 return host_->CompositeAndReadback(pixels, rect); | 438 return host_->CompositeAndReadback(pixels, rect); |
373 else | 439 else |
374 return false; | 440 return false; |
375 } | 441 } |
376 | 442 |
443 void CompositorImpl::SetNeedsComposite() { | |
444 if (!host_.get()) | |
445 return; | |
446 | |
447 needs_composite_ = true; | |
448 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.
| |
449 root_window_->RequestVSyncUpdate(); | |
450 } | |
451 | |
377 cc::UIResourceId CompositorImpl::GenerateUIResourceFromUIResourceBitmap( | 452 cc::UIResourceId CompositorImpl::GenerateUIResourceFromUIResourceBitmap( |
378 const cc::UIResourceBitmap& bitmap, | 453 const cc::UIResourceBitmap& bitmap, |
379 bool is_transient) { | 454 bool is_transient) { |
380 if (!host_) | 455 if (!host_) |
381 return 0; | 456 return 0; |
382 | 457 |
383 cc::UIResourceId id = 0; | 458 cc::UIResourceId id = 0; |
384 scoped_ptr<cc::UIResourceClient> resource; | 459 scoped_ptr<cc::UIResourceClient> resource; |
385 if (is_transient) { | 460 if (is_transient) { |
386 scoped_ptr<TransientUIResource> transient_resource = | 461 scoped_ptr<TransientUIResource> transient_resource = |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
461 return make_scoped_ptr( | 536 return make_scoped_ptr( |
462 new WebGraphicsContext3DCommandBufferImpl(surface_id, | 537 new WebGraphicsContext3DCommandBufferImpl(surface_id, |
463 url, | 538 url, |
464 gpu_channel_host.get(), | 539 gpu_channel_host.get(), |
465 attributes, | 540 attributes, |
466 lose_context_when_out_of_memory, | 541 lose_context_when_out_of_memory, |
467 limits, | 542 limits, |
468 NULL)); | 543 NULL)); |
469 } | 544 } |
470 | 545 |
546 void CompositorImpl::Layout() { | |
547 // TODO: If we get this callback from the SingleThreadProxy, we need | |
548 // 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 :)
| |
549 NOTREACHED(); | |
550 client_->Layout(); | |
551 } | |
552 | |
471 scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface( | 553 scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface( |
472 bool fallback) { | 554 bool fallback) { |
473 blink::WebGraphicsContext3D::Attributes attrs; | 555 blink::WebGraphicsContext3D::Attributes attrs; |
474 attrs.shareResources = true; | 556 attrs.shareResources = true; |
475 attrs.noAutomaticFlushes = true; | 557 attrs.noAutomaticFlushes = true; |
476 | 558 |
477 DCHECK(window_); | 559 DCHECK(window_); |
478 DCHECK(surface_id_); | 560 DCHECK(surface_id_); |
479 | 561 |
480 scoped_refptr<ContextProviderCommandBuffer> context_provider = | 562 scoped_refptr<ContextProviderCommandBuffer> context_provider = |
481 ContextProviderCommandBuffer::Create( | 563 ContextProviderCommandBuffer::Create( |
482 CreateGpuProcessViewContext(attrs, surface_id_), "BrowserCompositor"); | 564 CreateGpuProcessViewContext(attrs, surface_id_), "BrowserCompositor"); |
483 if (!context_provider.get()) { | 565 if (!context_provider.get()) { |
484 LOG(ERROR) << "Failed to create 3D context for compositor."; | 566 LOG(ERROR) << "Failed to create 3D context for compositor."; |
485 return scoped_ptr<cc::OutputSurface>(); | 567 return scoped_ptr<cc::OutputSurface>(); |
486 } | 568 } |
487 | 569 |
488 return scoped_ptr<cc::OutputSurface>( | 570 return scoped_ptr<cc::OutputSurface>( |
489 new OutputSurfaceWithoutParent(context_provider)); | 571 new OutputSurfaceWithoutParent(context_provider)); |
490 } | 572 } |
491 | 573 |
492 void CompositorImpl::OnLostResources() { | 574 void CompositorImpl::OnLostResources() { |
493 client_->DidLoseResources(); | 575 client_->DidLoseResources(); |
494 } | 576 } |
495 | 577 |
496 void CompositorImpl::DidCompleteSwapBuffers() { | 578 void CompositorImpl::ScheduleComposite() { |
497 client_->OnSwapBuffersCompleted(); | 579 if (needs_composite_ || ignore_schedule_composite_) |
498 } | 580 return; |
499 | 581 |
500 void CompositorImpl::ScheduleComposite() { | 582 needs_composite_ = true; |
501 client_->ScheduleComposite(); | 583 PostComposite(base::TimeDelta()); |
502 } | 584 } |
503 | 585 |
504 void CompositorImpl::ScheduleAnimation() { | 586 void CompositorImpl::ScheduleAnimation() { |
505 ScheduleComposite(); | 587 ScheduleComposite(); |
506 } | 588 } |
507 | 589 |
508 void CompositorImpl::DidPostSwapBuffers() { | 590 void CompositorImpl::DidPostSwapBuffers() { |
509 TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers"); | 591 TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers"); |
510 client_->OnSwapBuffersPosted(); | 592 did_post_swapbuffers_ = true; |
593 } | |
594 | |
595 void CompositorImpl::DidCompleteSwapBuffers() { | |
596 TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers"); | |
597 DCHECK_GT(pending_swapbuffers_, 0U); | |
598 client_->OnSwapBuffersCompleted(pending_swapbuffers_--); | |
511 } | 599 } |
512 | 600 |
513 void CompositorImpl::DidAbortSwapBuffers() { | 601 void CompositorImpl::DidAbortSwapBuffers() { |
514 TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers"); | 602 TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers"); |
515 client_->OnSwapBuffersCompleted(); | 603 DCHECK_GT(pending_swapbuffers_, 0U); |
604 client_->OnSwapBuffersCompleted(pending_swapbuffers_--); | |
516 } | 605 } |
517 | 606 |
518 void CompositorImpl::DidCommit() { | 607 void CompositorImpl::DidCommit() { |
519 root_window_->OnCompositingDidCommit(); | 608 root_window_->OnCompositingDidCommit(); |
520 } | 609 } |
521 | 610 |
522 void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) { | 611 void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) { |
523 root_layer_->AddChild(layer); | 612 root_layer_->AddChild(layer); |
524 } | 613 } |
525 | 614 |
615 void CompositorImpl::OnVSync(base::TimeTicks frame_time, | |
616 base::TimeDelta vsync_period) { | |
617 vsync_period_ = vsync_period; | |
618 did_composite_outside_vsync_ = false; | |
619 | |
620 if (should_composite_on_vsync_) | |
621 Composite(true); | |
622 } | |
623 | |
526 } // namespace content | 624 } // namespace content |
OLD | NEW |