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_this_frame_(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( |
257 host_->Composite(gfx::FrameTime::Now()); | 264 FROM_HERE, |
| 265 base::Bind(&CompositorImpl::Composite, |
| 266 weak_factory_.GetWeakPtr(), |
| 267 COMPOSITE_IMMEDIATELY), |
| 268 delay); |
| 269 } |
| 270 |
| 271 void CompositorImpl::Composite(CompositingTrigger trigger) { |
| 272 if (!host_) |
| 273 return; |
| 274 |
| 275 if (!needs_composite_) |
| 276 return; |
| 277 |
| 278 if (trigger != COMPOSITE_ON_VSYNC && should_composite_on_vsync_) { |
| 279 TRACE_EVENT0("compositor", "CompositorImpl_DeferCompositeToVSync"); |
| 280 root_window_->RequestVSyncUpdate(); |
| 281 return; |
| 282 } |
| 283 |
| 284 // Don't Composite more than once in between vsync ticks. |
| 285 if (did_composite_this_frame_) { |
| 286 TRACE_EVENT0("compositor", "CompositorImpl_ThrottleComposite"); |
| 287 if (should_composite_on_vsync_) |
| 288 root_window_->RequestVSyncUpdate(); |
| 289 else |
| 290 PostComposite(vsync_period_); |
| 291 return; |
| 292 } |
| 293 |
| 294 const unsigned int kMaxSwapBuffers = 2U; |
| 295 DCHECK_LE(pending_swapbuffers_, kMaxSwapBuffers); |
| 296 if (pending_swapbuffers_ == kMaxSwapBuffers) { |
| 297 TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit"); |
| 298 if (should_composite_on_vsync_) |
| 299 root_window_->RequestVSyncUpdate(); |
| 300 else |
| 301 PostComposite(vsync_period_); |
| 302 return; |
| 303 } |
| 304 |
| 305 // Reset state before Layout+Composite since that might create more |
| 306 // requests to Composite that we need to respect. |
| 307 needs_composite_ = false; |
| 308 should_composite_on_vsync_ = false; |
| 309 |
| 310 // Ignore ScheduleComposite() from layer tree changes during Layout. |
| 311 ignore_schedule_composite_ = true; |
| 312 client_->Layout(); |
| 313 ignore_schedule_composite_ = false; |
| 314 |
| 315 did_post_swapbuffers_ = false; |
| 316 host_->Composite(gfx::FrameTime::Now()); |
| 317 if (did_post_swapbuffers_) |
| 318 pending_swapbuffers_++; |
| 319 |
| 320 if (trigger != COMPOSITE_ON_VSYNC) { |
| 321 // Need to track vsync to avoid compositing more than once per frame. |
| 322 root_window_->RequestVSyncUpdate(); |
| 323 } |
| 324 did_composite_this_frame_ = true; |
258 } | 325 } |
259 | 326 |
260 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) { | 327 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) { |
261 root_layer_->RemoveAllChildren(); | 328 root_layer_->RemoveAllChildren(); |
262 if (root_layer) | 329 if (root_layer) |
263 root_layer_->AddChild(root_layer); | 330 root_layer_->AddChild(root_layer); |
264 } | 331 } |
265 | 332 |
266 void CompositorImpl::SetWindowSurface(ANativeWindow* window) { | 333 void CompositorImpl::SetWindowSurface(ANativeWindow* window) { |
267 GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get(); | 334 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()); | 376 content::RegisterViewSurface(surface_id_, j_surface.obj()); |
310 } | 377 } |
311 } | 378 } |
312 | 379 |
313 void CompositorImpl::SetVisible(bool visible) { | 380 void CompositorImpl::SetVisible(bool visible) { |
314 if (!visible) { | 381 if (!visible) { |
315 ui_resource_map_.clear(); | 382 ui_resource_map_.clear(); |
316 host_.reset(); | 383 host_.reset(); |
317 client_->UIResourcesAreInvalid(); | 384 client_->UIResourcesAreInvalid(); |
318 } else if (!host_) { | 385 } else if (!host_) { |
| 386 needs_composite_ = false; |
| 387 did_composite_this_frame_ = false; |
| 388 should_composite_on_vsync_ = false; |
| 389 pending_swapbuffers_ = 0; |
319 cc::LayerTreeSettings settings; | 390 cc::LayerTreeSettings settings; |
320 settings.refresh_rate = 60.0; | 391 settings.refresh_rate = 60.0; |
321 settings.impl_side_painting = false; | 392 settings.impl_side_painting = false; |
322 settings.allow_antialiasing = false; | 393 settings.allow_antialiasing = false; |
323 settings.calculate_top_controls_position = false; | 394 settings.calculate_top_controls_position = false; |
324 settings.top_controls_height = 0.f; | 395 settings.top_controls_height = 0.f; |
325 settings.highp_threshold_min = 2048; | 396 settings.highp_threshold_min = 2048; |
326 | 397 |
327 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 398 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
328 settings.initial_debug_state.SetRecordRenderingStats( | 399 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); | 438 host_->set_has_transparent_background(flag); |
368 } | 439 } |
369 | 440 |
370 bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) { | 441 bool CompositorImpl::CompositeAndReadback(void *pixels, const gfx::Rect& rect) { |
371 if (host_) | 442 if (host_) |
372 return host_->CompositeAndReadback(pixels, rect); | 443 return host_->CompositeAndReadback(pixels, rect); |
373 else | 444 else |
374 return false; | 445 return false; |
375 } | 446 } |
376 | 447 |
| 448 void CompositorImpl::SetNeedsComposite() { |
| 449 if (!host_.get() || needs_composite_) |
| 450 return; |
| 451 |
| 452 needs_composite_ = true; |
| 453 |
| 454 // For explicit requests we try to composite regularly on vsync. |
| 455 should_composite_on_vsync_ = true; |
| 456 root_window_->RequestVSyncUpdate(); |
| 457 } |
| 458 |
377 cc::UIResourceId CompositorImpl::GenerateUIResourceFromUIResourceBitmap( | 459 cc::UIResourceId CompositorImpl::GenerateUIResourceFromUIResourceBitmap( |
378 const cc::UIResourceBitmap& bitmap, | 460 const cc::UIResourceBitmap& bitmap, |
379 bool is_transient) { | 461 bool is_transient) { |
380 if (!host_) | 462 if (!host_) |
381 return 0; | 463 return 0; |
382 | 464 |
383 cc::UIResourceId id = 0; | 465 cc::UIResourceId id = 0; |
384 scoped_ptr<cc::UIResourceClient> resource; | 466 scoped_ptr<cc::UIResourceClient> resource; |
385 if (is_transient) { | 467 if (is_transient) { |
386 scoped_ptr<TransientUIResource> transient_resource = | 468 scoped_ptr<TransientUIResource> transient_resource = |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
461 return make_scoped_ptr( | 543 return make_scoped_ptr( |
462 new WebGraphicsContext3DCommandBufferImpl(surface_id, | 544 new WebGraphicsContext3DCommandBufferImpl(surface_id, |
463 url, | 545 url, |
464 gpu_channel_host.get(), | 546 gpu_channel_host.get(), |
465 attributes, | 547 attributes, |
466 lose_context_when_out_of_memory, | 548 lose_context_when_out_of_memory, |
467 limits, | 549 limits, |
468 NULL)); | 550 NULL)); |
469 } | 551 } |
470 | 552 |
| 553 void CompositorImpl::Layout() { |
| 554 // TODO: If we get this callback from the SingleThreadProxy, we need |
| 555 // to stop calling it ourselves in CompositorImpl::Composite(). |
| 556 NOTREACHED(); |
| 557 client_->Layout(); |
| 558 } |
| 559 |
471 scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface( | 560 scoped_ptr<cc::OutputSurface> CompositorImpl::CreateOutputSurface( |
472 bool fallback) { | 561 bool fallback) { |
473 blink::WebGraphicsContext3D::Attributes attrs; | 562 blink::WebGraphicsContext3D::Attributes attrs; |
474 attrs.shareResources = true; | 563 attrs.shareResources = true; |
475 attrs.noAutomaticFlushes = true; | 564 attrs.noAutomaticFlushes = true; |
476 | 565 |
477 DCHECK(window_); | 566 DCHECK(window_); |
478 DCHECK(surface_id_); | 567 DCHECK(surface_id_); |
479 | 568 |
480 scoped_refptr<ContextProviderCommandBuffer> context_provider = | 569 scoped_refptr<ContextProviderCommandBuffer> context_provider = |
481 ContextProviderCommandBuffer::Create( | 570 ContextProviderCommandBuffer::Create( |
482 CreateGpuProcessViewContext(attrs, surface_id_), "BrowserCompositor"); | 571 CreateGpuProcessViewContext(attrs, surface_id_), "BrowserCompositor"); |
483 if (!context_provider.get()) { | 572 if (!context_provider.get()) { |
484 LOG(ERROR) << "Failed to create 3D context for compositor."; | 573 LOG(ERROR) << "Failed to create 3D context for compositor."; |
485 return scoped_ptr<cc::OutputSurface>(); | 574 return scoped_ptr<cc::OutputSurface>(); |
486 } | 575 } |
487 | 576 |
488 return scoped_ptr<cc::OutputSurface>( | 577 return scoped_ptr<cc::OutputSurface>( |
489 new OutputSurfaceWithoutParent(context_provider)); | 578 new OutputSurfaceWithoutParent(context_provider)); |
490 } | 579 } |
491 | 580 |
492 void CompositorImpl::OnLostResources() { | 581 void CompositorImpl::OnLostResources() { |
493 client_->DidLoseResources(); | 582 client_->DidLoseResources(); |
494 } | 583 } |
495 | 584 |
496 void CompositorImpl::DidCompleteSwapBuffers() { | 585 void CompositorImpl::ScheduleComposite() { |
497 client_->OnSwapBuffersCompleted(); | 586 if (needs_composite_ || ignore_schedule_composite_) |
498 } | 587 return; |
499 | 588 |
500 void CompositorImpl::ScheduleComposite() { | 589 needs_composite_ = true; |
501 client_->ScheduleComposite(); | 590 |
| 591 // We currently expect layer tree invalidations at most once per frame |
| 592 // during normal operation and therefore try to composite immediately |
| 593 // to minimize latency. |
| 594 PostComposite(base::TimeDelta()); |
502 } | 595 } |
503 | 596 |
504 void CompositorImpl::ScheduleAnimation() { | 597 void CompositorImpl::ScheduleAnimation() { |
505 ScheduleComposite(); | 598 ScheduleComposite(); |
506 } | 599 } |
507 | 600 |
508 void CompositorImpl::DidPostSwapBuffers() { | 601 void CompositorImpl::DidPostSwapBuffers() { |
509 TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers"); | 602 TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers"); |
510 client_->OnSwapBuffersPosted(); | 603 did_post_swapbuffers_ = true; |
| 604 } |
| 605 |
| 606 void CompositorImpl::DidCompleteSwapBuffers() { |
| 607 TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers"); |
| 608 DCHECK_GT(pending_swapbuffers_, 0U); |
| 609 client_->OnSwapBuffersCompleted(pending_swapbuffers_--); |
511 } | 610 } |
512 | 611 |
513 void CompositorImpl::DidAbortSwapBuffers() { | 612 void CompositorImpl::DidAbortSwapBuffers() { |
514 TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers"); | 613 TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers"); |
515 client_->OnSwapBuffersCompleted(); | 614 DCHECK_GT(pending_swapbuffers_, 0U); |
| 615 client_->OnSwapBuffersCompleted(pending_swapbuffers_--); |
516 } | 616 } |
517 | 617 |
518 void CompositorImpl::DidCommit() { | 618 void CompositorImpl::DidCommit() { |
519 root_window_->OnCompositingDidCommit(); | 619 root_window_->OnCompositingDidCommit(); |
520 } | 620 } |
521 | 621 |
522 void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) { | 622 void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) { |
523 root_layer_->AddChild(layer); | 623 root_layer_->AddChild(layer); |
524 } | 624 } |
525 | 625 |
| 626 void CompositorImpl::OnVSync(base::TimeTicks frame_time, |
| 627 base::TimeDelta vsync_period) { |
| 628 vsync_period_ = vsync_period; |
| 629 did_composite_this_frame_ = false; |
| 630 |
| 631 if (should_composite_on_vsync_) |
| 632 Composite(COMPOSITE_ON_VSYNC); |
| 633 } |
| 634 |
526 } // namespace content | 635 } // namespace content |
OLD | NEW |