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 3 // found in the LICENSE file. 4 5 #include "content/browser/renderer_host/compositor_impl_android.h" 6 7 #include <android/bitmap.h> 8 #include <android/native_window_jni.h> 9 10 #include "base/android/jni_android.h" 11 #include "base/android/scoped_java_ref.h" 12 #include "base/bind.h" 13 #include "base/command_line.h" 14 #include "base/containers/hash_tables.h" 15 #include "base/lazy_instance.h" 16 #include "base/logging.h" 17 #include "base/memory/weak_ptr.h" 18 #include "base/single_thread_task_runner.h" 19 #include "base/synchronization/lock.h" 20 #include "base/threading/thread.h" 21 #include "base/threading/thread_checker.h" 22 #include "cc/base/switches.h" 23 #include "cc/input/input_handler.h" 24 #include "cc/layers/layer.h" 25 #include "cc/output/compositor_frame.h" 26 #include "cc/output/context_provider.h" 27 #include "cc/output/output_surface.h" 28 #include "cc/trees/layer_tree_host.h" 29 #include "content/browser/android/child_process_launcher_android.h" 30 #include "content/browser/gpu/browser_gpu_channel_host_factory.h" 31 #include "content/browser/gpu/gpu_surface_tracker.h" 32 #include "content/common/gpu/client/command_buffer_proxy_impl.h" 33 #include "content/common/gpu/client/context_provider_command_buffer.h" 34 #include "content/common/gpu/client/gl_helper.h" 35 #include "content/common/gpu/client/gpu_channel_host.h" 36 #include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h" 37 #include "content/common/gpu/gpu_process_launch_causes.h" 38 #include "content/common/host_shared_bitmap_manager.h" 39 #include "content/public/browser/android/compositor_client.h" 40 #include "gpu/command_buffer/client/gles2_interface.h" 41 #include "third_party/khronos/GLES2/gl2.h" 42 #include "third_party/khronos/GLES2/gl2ext.h" 43 #include "third_party/skia/include/core/SkMallocPixelRef.h" 44 #include "ui/base/android/window_android.h" 45 #include "ui/gfx/android/device_display_info.h" 46 #include "ui/gfx/frame_time.h" 47 #include "ui/gl/android/surface_texture.h" 48 #include "ui/gl/android/surface_texture_tracker.h" 49 #include "webkit/common/gpu/context_provider_in_process.h" 50 #include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h" 51 52 namespace { 53 54 const unsigned int kMaxSwapBuffers = 2U; 55 56 // Used to override capabilities_.adjust_deadline_for_parent to false 57 class OutputSurfaceWithoutParent : public cc::OutputSurface { 58 public: 59 OutputSurfaceWithoutParent(const scoped_refptr< 60 content::ContextProviderCommandBuffer>& context_provider, 61 base::WeakPtr<content::CompositorImpl> compositor_impl) 62 : cc::OutputSurface(context_provider) { 63 capabilities_.adjust_deadline_for_parent = false; 64 compositor_impl_ = compositor_impl; 65 main_thread_ = base::MessageLoopProxy::current(); 66 } 67 68 virtual void SwapBuffers(cc::CompositorFrame* frame) OVERRIDE { 69 content::ContextProviderCommandBuffer* provider_command_buffer = 70 static_cast<content::ContextProviderCommandBuffer*>( 71 context_provider_.get()); 72 content::CommandBufferProxyImpl* command_buffer_proxy = 73 provider_command_buffer->GetCommandBufferProxy(); 74 DCHECK(command_buffer_proxy); 75 command_buffer_proxy->SetLatencyInfo(frame->metadata.latency_info); 76 77 OutputSurface::SwapBuffers(frame); 78 } 79 80 virtual bool BindToClient(cc::OutputSurfaceClient* client) OVERRIDE { 81 if (!OutputSurface::BindToClient(client)) 82 return false; 83 84 main_thread_->PostTask( 85 FROM_HERE, 86 base::Bind(&content::CompositorImpl::PopulateGpuCapabilities, 87 compositor_impl_, 88 context_provider_->ContextCapabilities().gpu)); 89 90 return true; 91 } 92 93 scoped_refptr<base::MessageLoopProxy> main_thread_; 94 base::WeakPtr<content::CompositorImpl> compositor_impl_; 95 }; 96 97 class SurfaceTextureTrackerImpl : public gfx::SurfaceTextureTracker { 98 public: 99 SurfaceTextureTrackerImpl() : next_surface_texture_id_(1) { 100 thread_checker_.DetachFromThread(); 101 } 102 103 // Overridden from gfx::SurfaceTextureTracker: 104 virtual scoped_refptr<gfx::SurfaceTexture> AcquireSurfaceTexture( 105 int primary_id, 106 int secondary_id) OVERRIDE { 107 base::AutoLock lock(surface_textures_lock_); 108 SurfaceTextureMapKey key(primary_id, secondary_id); 109 SurfaceTextureMap::iterator it = surface_textures_.find(key); 110 if (it == surface_textures_.end()) 111 return scoped_refptr<gfx::SurfaceTexture>(); 112 scoped_refptr<gfx::SurfaceTexture> surface_texture = it->second; 113 surface_textures_.erase(it); 114 return surface_texture; 115 } 116 117 int AddSurfaceTexture(gfx::SurfaceTexture* surface_texture, 118 int child_process_id) { 119 DCHECK(thread_checker_.CalledOnValidThread()); 120 int surface_texture_id = next_surface_texture_id_++; 121 if (next_surface_texture_id_ == INT_MAX) 122 next_surface_texture_id_ = 1; 123 124 base::AutoLock lock(surface_textures_lock_); 125 SurfaceTextureMapKey key(surface_texture_id, child_process_id); 126 DCHECK(surface_textures_.find(key) == surface_textures_.end()); 127 surface_textures_[key] = surface_texture; 128 content::RegisterChildProcessSurfaceTexture( 129 surface_texture_id, 130 child_process_id, 131 surface_texture->j_surface_texture().obj()); 132 return surface_texture_id; 133 } 134 135 void RemoveAllSurfaceTextures(int child_process_id) { 136 DCHECK(thread_checker_.CalledOnValidThread()); 137 base::AutoLock lock(surface_textures_lock_); 138 SurfaceTextureMap::iterator it = surface_textures_.begin(); 139 while (it != surface_textures_.end()) { 140 if (it->first.second == child_process_id) { 141 content::UnregisterChildProcessSurfaceTexture(it->first.first, 142 it->first.second); 143 surface_textures_.erase(it++); 144 } else { 145 ++it; 146 } 147 } 148 } 149 150 private: 151 typedef std::pair<int, int> SurfaceTextureMapKey; 152 typedef base::hash_map<SurfaceTextureMapKey, 153 scoped_refptr<gfx::SurfaceTexture> > 154 SurfaceTextureMap; 155 SurfaceTextureMap surface_textures_; 156 mutable base::Lock surface_textures_lock_; 157 int next_surface_texture_id_; 158 base::ThreadChecker thread_checker_; 159 }; 160 base::LazyInstance<SurfaceTextureTrackerImpl> g_surface_texture_tracker = 161 LAZY_INSTANCE_INITIALIZER; 162 163 static bool g_initialized = false; 164 165 } // anonymous namespace 166 167 namespace content { 168 169 // static 170 Compositor* Compositor::Create(CompositorClient* client, 171 gfx::NativeWindow root_window) { 172 return client ? new CompositorImpl(client, root_window) : NULL; 173 } 174 175 // static 176 void Compositor::Initialize() { 177 DCHECK(!CompositorImpl::IsInitialized()); 178 // SurfaceTextureTracker instance must be set before we create a GPU thread 179 // that could be using it to initialize GLImage instances. 180 gfx::SurfaceTextureTracker::InitInstance(g_surface_texture_tracker.Pointer()); 181 g_initialized = true; 182 } 183 184 // static 185 bool CompositorImpl::IsInitialized() { 186 return g_initialized; 187 } 188 189 // static 190 int CompositorImpl::CreateSurfaceTexture(int child_process_id) { 191 // Note: this needs to be 0 as the surface texture implemenation will take 192 // ownership of the texture and call glDeleteTextures when the GPU service 193 // attaches the surface texture to a real texture id. glDeleteTextures 194 // silently ignores 0. 195 const int kDummyTextureId = 0; 196 scoped_refptr<gfx::SurfaceTexture> surface_texture = 197 gfx::SurfaceTexture::Create(kDummyTextureId); 198 return g_surface_texture_tracker.Pointer()->AddSurfaceTexture( 199 surface_texture.get(), child_process_id); 200 } 201 202 // static 203 void CompositorImpl::DestroyAllSurfaceTextures(int child_process_id) { 204 g_surface_texture_tracker.Pointer()->RemoveAllSurfaceTextures( 205 child_process_id); 206 } 207 208 CompositorImpl::CompositorImpl(CompositorClient* client, 209 gfx::NativeWindow root_window) 210 : root_layer_(cc::Layer::Create()), 211 has_transparent_background_(false), 212 device_scale_factor_(1), 213 window_(NULL), 214 surface_id_(0), 215 client_(client), 216 root_window_(root_window), 217 did_post_swapbuffers_(false), 218 ignore_schedule_composite_(false), 219 needs_composite_(false), 220 needs_animate_(false), 221 will_composite_immediately_(false), 222 composite_on_vsync_trigger_(DO_NOT_COMPOSITE), 223 pending_swapbuffers_(0U), 224 weak_factory_(this) { 225 DCHECK(client); 226 DCHECK(root_window); 227 ImageTransportFactoryAndroid::AddObserver(this); 228 root_window->AttachCompositor(this); 229 } 230 231 CompositorImpl::~CompositorImpl() { 232 root_window_->DetachCompositor(); 233 ImageTransportFactoryAndroid::RemoveObserver(this); 234 // Clean-up any surface references. 235 SetSurface(NULL); 236 } 237 238 void CompositorImpl::PostComposite(CompositingTrigger trigger) { 239 DCHECK(needs_composite_); 240 DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY); 241 242 if (will_composite_immediately_ || 243 (trigger == COMPOSITE_EVENTUALLY && WillComposite())) { 244 // We will already composite soon enough. 245 DCHECK(WillComposite()); 246 return; 247 } 248 249 if (DidCompositeThisFrame()) { 250 DCHECK(!WillCompositeThisFrame()); 251 if (composite_on_vsync_trigger_ != COMPOSITE_IMMEDIATELY) { 252 composite_on_vsync_trigger_ = trigger; 253 root_window_->RequestVSyncUpdate(); 254 } 255 DCHECK(WillComposite()); 256 return; 257 } 258 259 base::TimeDelta delay; 260 if (trigger == COMPOSITE_IMMEDIATELY) { 261 will_composite_immediately_ = true; 262 composite_on_vsync_trigger_ = DO_NOT_COMPOSITE; 263 } else { 264 DCHECK(!WillComposite()); 265 const base::TimeDelta estimated_composite_time = vsync_period_ / 4; 266 const base::TimeTicks now = base::TimeTicks::Now(); 267 268 if (!last_vsync_.is_null() && (now - last_vsync_) < vsync_period_) { 269 base::TimeTicks next_composite = 270 last_vsync_ + vsync_period_ - estimated_composite_time; 271 if (next_composite < now) { 272 // It's too late, we will reschedule composite as needed on the next 273 // vsync. 274 composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY; 275 root_window_->RequestVSyncUpdate(); 276 DCHECK(WillComposite()); 277 return; 278 } 279 280 delay = next_composite - now; 281 } 282 } 283 TRACE_EVENT2("cc", "CompositorImpl::PostComposite", 284 "trigger", trigger, 285 "delay", delay.InMillisecondsF()); 286 287 DCHECK(composite_on_vsync_trigger_ == DO_NOT_COMPOSITE); 288 if (current_composite_task_) 289 current_composite_task_->Cancel(); 290 291 // Unretained because we cancel the task on shutdown. 292 current_composite_task_.reset(new base::CancelableClosure( 293 base::Bind(&CompositorImpl::Composite, base::Unretained(this), trigger))); 294 base::MessageLoop::current()->PostDelayedTask( 295 FROM_HERE, current_composite_task_->callback(), delay); 296 } 297 298 void CompositorImpl::Composite(CompositingTrigger trigger) { 299 BrowserGpuChannelHostFactory* factory = 300 BrowserGpuChannelHostFactory::instance(); 301 if (!factory->GetGpuChannel() || factory->GetGpuChannel()->IsLost()) { 302 CauseForGpuLaunch cause = 303 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; 304 factory->EstablishGpuChannel(cause, 305 base::Bind(&CompositorImpl::ScheduleComposite, 306 weak_factory_.GetWeakPtr())); 307 return; 308 } 309 310 DCHECK(host_); 311 DCHECK(trigger == COMPOSITE_IMMEDIATELY || trigger == COMPOSITE_EVENTUALLY); 312 DCHECK(needs_composite_); 313 DCHECK(!DidCompositeThisFrame()); 314 315 if (trigger == COMPOSITE_IMMEDIATELY) 316 will_composite_immediately_ = false; 317 318 DCHECK_LE(pending_swapbuffers_, kMaxSwapBuffers); 319 if (pending_swapbuffers_ == kMaxSwapBuffers) { 320 TRACE_EVENT0("compositor", "CompositorImpl_SwapLimit"); 321 return; 322 } 323 324 // Reset state before Layout+Composite since that might create more 325 // requests to Composite that we need to respect. 326 needs_composite_ = false; 327 328 // Only allow compositing once per vsync. 329 current_composite_task_->Cancel(); 330 DCHECK(DidCompositeThisFrame() && !WillComposite()); 331 332 // Ignore ScheduleComposite() from layer tree changes during layout and 333 // animation updates that will already be reflected in the current frame 334 // we are about to draw. 335 ignore_schedule_composite_ = true; 336 337 const base::TimeTicks frame_time = gfx::FrameTime::Now(); 338 if (needs_animate_) { 339 needs_animate_ = false; 340 root_window_->Animate(frame_time); 341 } 342 ignore_schedule_composite_ = false; 343 344 did_post_swapbuffers_ = false; 345 host_->Composite(frame_time); 346 if (did_post_swapbuffers_) 347 pending_swapbuffers_++; 348 349 // Need to track vsync to avoid compositing more than once per frame. 350 root_window_->RequestVSyncUpdate(); 351 } 352 353 UIResourceProvider& CompositorImpl::GetUIResourceProvider() { 354 return ui_resource_provider_; 355 } 356 357 ui::SystemUIResourceManager& CompositorImpl::GetSystemUIResourceManager() { 358 return ui_resource_provider_.GetSystemUIResourceManager(); 359 } 360 361 void CompositorImpl::SetRootLayer(scoped_refptr<cc::Layer> root_layer) { 362 if (subroot_layer_) { 363 subroot_layer_->RemoveFromParent(); 364 subroot_layer_ = NULL; 365 } 366 if (root_layer) { 367 subroot_layer_ = root_layer; 368 root_layer_->AddChild(root_layer); 369 } 370 } 371 372 void CompositorImpl::SetWindowSurface(ANativeWindow* window) { 373 GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get(); 374 375 if (window_) { 376 tracker->RemoveSurface(surface_id_); 377 ANativeWindow_release(window_); 378 window_ = NULL; 379 surface_id_ = 0; 380 SetVisible(false); 381 } 382 383 if (window) { 384 window_ = window; 385 ANativeWindow_acquire(window); 386 surface_id_ = tracker->AddSurfaceForNativeWidget(window); 387 tracker->SetSurfaceHandle( 388 surface_id_, 389 gfx::GLSurfaceHandle(gfx::kNullPluginWindow, gfx::NATIVE_DIRECT)); 390 SetVisible(true); 391 } 392 } 393 394 void CompositorImpl::SetSurface(jobject surface) { 395 JNIEnv* env = base::android::AttachCurrentThread(); 396 base::android::ScopedJavaLocalRef<jobject> j_surface(env, surface); 397 398 // First, cleanup any existing surface references. 399 if (surface_id_) 400 content::UnregisterViewSurface(surface_id_); 401 SetWindowSurface(NULL); 402 403 // Now, set the new surface if we have one. 404 ANativeWindow* window = NULL; 405 if (surface) { 406 // Note: This ensures that any local references used by 407 // ANativeWindow_fromSurface are released immediately. This is needed as a 408 // workaround for https://code.google.com/p/android/issues/detail?id=68174 409 base::android::ScopedJavaLocalFrame scoped_local_reference_frame(env); 410 window = ANativeWindow_fromSurface(env, surface); 411 } 412 if (window) { 413 SetWindowSurface(window); 414 ANativeWindow_release(window); 415 content::RegisterViewSurface(surface_id_, j_surface.obj()); 416 } 417 } 418 419 void CompositorImpl::SetVisible(bool visible) { 420 if (!visible) { 421 DCHECK(host_); 422 // Look for any layers that were attached to the root for readback 423 // and are waiting for Composite() to happen. 424 bool readback_pending = false; 425 for (size_t i = 0; i < root_layer_->children().size(); ++i) { 426 if (root_layer_->children()[i]->HasCopyRequest()) { 427 readback_pending = true; 428 break; 429 } 430 } 431 if (readback_pending) { 432 ignore_schedule_composite_ = true; 433 host_->Composite(base::TimeTicks::Now()); 434 ignore_schedule_composite_ = false; 435 } 436 if (WillComposite()) 437 CancelComposite(); 438 ui_resource_provider_.SetLayerTreeHost(NULL); 439 host_.reset(); 440 } else if (!host_) { 441 DCHECK(!WillComposite()); 442 needs_composite_ = false; 443 pending_swapbuffers_ = 0; 444 cc::LayerTreeSettings settings; 445 settings.refresh_rate = 60.0; 446 settings.impl_side_painting = false; 447 settings.allow_antialiasing = false; 448 settings.calculate_top_controls_position = false; 449 settings.top_controls_height = 0.f; 450 settings.highp_threshold_min = 2048; 451 452 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); 453 settings.initial_debug_state.SetRecordRenderingStats( 454 command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking)); 455 settings.initial_debug_state.show_fps_counter = 456 command_line->HasSwitch(cc::switches::kUIShowFPSCounter); 457 // TODO(enne): Update this this compositor to use the scheduler. 458 settings.single_thread_proxy_scheduler = false; 459 460 host_ = cc::LayerTreeHost::CreateSingleThreaded( 461 this, 462 this, 463 HostSharedBitmapManager::current(), 464 settings, 465 base::MessageLoopProxy::current()); 466 host_->SetRootLayer(root_layer_); 467 468 host_->SetVisible(true); 469 host_->SetLayerTreeHostClientReady(); 470 host_->SetViewportSize(size_); 471 host_->set_has_transparent_background(has_transparent_background_); 472 host_->SetDeviceScaleFactor(device_scale_factor_); 473 ui_resource_provider_.SetLayerTreeHost(host_.get()); 474 } 475 } 476 477 void CompositorImpl::setDeviceScaleFactor(float factor) { 478 device_scale_factor_ = factor; 479 if (host_) 480 host_->SetDeviceScaleFactor(factor); 481 } 482 483 void CompositorImpl::SetWindowBounds(const gfx::Size& size) { 484 if (size_ == size) 485 return; 486 487 size_ = size; 488 if (host_) 489 host_->SetViewportSize(size); 490 root_layer_->SetBounds(size); 491 } 492 493 void CompositorImpl::SetHasTransparentBackground(bool flag) { 494 has_transparent_background_ = flag; 495 if (host_) 496 host_->set_has_transparent_background(flag); 497 } 498 499 void CompositorImpl::SetNeedsComposite() { 500 if (!host_.get()) 501 return; 502 DCHECK(!needs_composite_ || WillComposite()); 503 504 needs_composite_ = true; 505 PostComposite(COMPOSITE_IMMEDIATELY); 506 } 507 508 static scoped_ptr<WebGraphicsContext3DCommandBufferImpl> 509 CreateGpuProcessViewContext( 510 const scoped_refptr<GpuChannelHost>& gpu_channel_host, 511 const blink::WebGraphicsContext3D::Attributes attributes, 512 int surface_id) { 513 DCHECK(gpu_channel_host); 514 515 GURL url("chrome://gpu/Compositor::createContext3D"); 516 static const size_t kBytesPerPixel = 4; 517 gfx::DeviceDisplayInfo display_info; 518 size_t full_screen_texture_size_in_bytes = 519 display_info.GetDisplayHeight() * 520 display_info.GetDisplayWidth() * 521 kBytesPerPixel; 522 WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits; 523 limits.command_buffer_size = 64 * 1024; 524 limits.start_transfer_buffer_size = 64 * 1024; 525 limits.min_transfer_buffer_size = 64 * 1024; 526 limits.max_transfer_buffer_size = std::min( 527 3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize); 528 limits.mapped_memory_reclaim_limit = 2 * 1024 * 1024; 529 bool lose_context_when_out_of_memory = true; 530 return make_scoped_ptr( 531 new WebGraphicsContext3DCommandBufferImpl(surface_id, 532 url, 533 gpu_channel_host.get(), 534 attributes, 535 lose_context_when_out_of_memory, 536 limits, 537 NULL)); 538 } 539 540 void CompositorImpl::Layout() { 541 ignore_schedule_composite_ = true; 542 client_->Layout(); 543 ignore_schedule_composite_ = false; 544 } 545 546 void CompositorImpl::RequestNewOutputSurface(bool fallback) { 547 BrowserGpuChannelHostFactory* factory = 548 BrowserGpuChannelHostFactory::instance(); 549 if (!factory->GetGpuChannel() || factory->GetGpuChannel()->IsLost()) { 550 CauseForGpuLaunch cause = 551 CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE; 552 factory->EstablishGpuChannel( 553 cause, 554 base::Bind(&CompositorImpl::CreateOutputSurface, 555 weak_factory_.GetWeakPtr(), 556 fallback)); 557 return; 558 } 559 560 CreateOutputSurface(fallback); 561 } 562 563 void CompositorImpl::CreateOutputSurface(bool fallback) { 564 blink::WebGraphicsContext3D::Attributes attrs; 565 attrs.shareResources = true; 566 attrs.noAutomaticFlushes = true; 567 pending_swapbuffers_ = 0; 568 569 DCHECK(window_); 570 DCHECK(surface_id_); 571 572 scoped_refptr<ContextProviderCommandBuffer> context_provider; 573 BrowserGpuChannelHostFactory* factory = 574 BrowserGpuChannelHostFactory::instance(); 575 scoped_refptr<GpuChannelHost> gpu_channel_host = factory->GetGpuChannel(); 576 if (gpu_channel_host && !gpu_channel_host->IsLost()) { 577 context_provider = ContextProviderCommandBuffer::Create( 578 CreateGpuProcessViewContext(gpu_channel_host, attrs, surface_id_), 579 "BrowserCompositor"); 580 } 581 if (!context_provider.get()) { 582 LOG(ERROR) << "Failed to create 3D context for compositor."; 583 host_->SetOutputSurface(scoped_ptr<cc::OutputSurface>()); 584 return; 585 } 586 587 host_->SetOutputSurface( 588 scoped_ptr<cc::OutputSurface>(new OutputSurfaceWithoutParent( 589 context_provider, weak_factory_.GetWeakPtr()))); 590 } 591 592 void CompositorImpl::PopulateGpuCapabilities( 593 gpu::Capabilities gpu_capabilities) { 594 ui_resource_provider_.SetSupportsETC1NonPowerOfTwo( 595 gpu_capabilities.texture_format_etc1_npot); 596 } 597 598 void CompositorImpl::OnLostResources() { 599 client_->DidLoseResources(); 600 } 601 602 void CompositorImpl::ScheduleComposite() { 603 DCHECK(!needs_composite_ || WillComposite()); 604 if (ignore_schedule_composite_) 605 return; 606 607 needs_composite_ = true; 608 // We currently expect layer tree invalidations at most once per frame 609 // during normal operation and therefore try to composite immediately 610 // to minimize latency. 611 PostComposite(COMPOSITE_IMMEDIATELY); 612 } 613 614 void CompositorImpl::ScheduleAnimation() { 615 DCHECK(!needs_composite_ || WillComposite()); 616 needs_animate_ = true; 617 618 if (needs_composite_) 619 return; 620 621 TRACE_EVENT0("cc", "CompositorImpl::ScheduleAnimation"); 622 needs_composite_ = true; 623 PostComposite(COMPOSITE_EVENTUALLY); 624 } 625 626 void CompositorImpl::DidPostSwapBuffers() { 627 TRACE_EVENT0("compositor", "CompositorImpl::DidPostSwapBuffers"); 628 did_post_swapbuffers_ = true; 629 } 630 631 void CompositorImpl::DidCompleteSwapBuffers() { 632 TRACE_EVENT0("compositor", "CompositorImpl::DidCompleteSwapBuffers"); 633 DCHECK_GT(pending_swapbuffers_, 0U); 634 if (pending_swapbuffers_-- == kMaxSwapBuffers && needs_composite_) 635 PostComposite(COMPOSITE_IMMEDIATELY); 636 client_->OnSwapBuffersCompleted(pending_swapbuffers_); 637 } 638 639 void CompositorImpl::DidAbortSwapBuffers() { 640 TRACE_EVENT0("compositor", "CompositorImpl::DidAbortSwapBuffers"); 641 // This really gets called only once from 642 // SingleThreadProxy::DidLoseOutputSurfaceOnImplThread() when the 643 // context was lost. 644 ScheduleComposite(); 645 client_->OnSwapBuffersCompleted(0); 646 } 647 648 void CompositorImpl::DidCommit() { 649 root_window_->OnCompositingDidCommit(); 650 } 651 652 void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) { 653 root_layer_->AddChild(layer); 654 } 655 656 void CompositorImpl::RequestCopyOfOutputOnRootLayer( 657 scoped_ptr<cc::CopyOutputRequest> request) { 658 root_layer_->RequestCopyOfOutput(request.Pass()); 659 } 660 661 void CompositorImpl::OnVSync(base::TimeTicks frame_time, 662 base::TimeDelta vsync_period) { 663 vsync_period_ = vsync_period; 664 last_vsync_ = frame_time; 665 666 if (WillCompositeThisFrame()) { 667 // We somehow missed the last vsync interval, so reschedule for deadline. 668 // We cannot schedule immediately, or will get us out-of-phase with new 669 // renderer frames. 670 CancelComposite(); 671 composite_on_vsync_trigger_ = COMPOSITE_EVENTUALLY; 672 } else { 673 current_composite_task_.reset(); 674 } 675 676 DCHECK(!DidCompositeThisFrame() && !WillCompositeThisFrame()); 677 if (composite_on_vsync_trigger_ != DO_NOT_COMPOSITE) { 678 CompositingTrigger trigger = composite_on_vsync_trigger_; 679 composite_on_vsync_trigger_ = DO_NOT_COMPOSITE; 680 PostComposite(trigger); 681 } 682 } 683 684 void CompositorImpl::SetNeedsAnimate() { 685 if (!host_) 686 return; 687 688 host_->SetNeedsAnimate(); 689 } 690 691 } // namespace content 692