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 "ui/compositor/compositor.h" | 5 #include "ui/compositor/compositor.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <deque> | 8 #include <deque> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
43 namespace { | 43 namespace { |
44 | 44 |
45 const double kDefaultRefreshRate = 60.0; | 45 const double kDefaultRefreshRate = 60.0; |
46 const double kTestRefreshRate = 200.0; | 46 const double kTestRefreshRate = 200.0; |
47 | 47 |
48 enum SwapType { | 48 enum SwapType { |
49 DRAW_SWAP, | 49 DRAW_SWAP, |
50 READPIXELS_SWAP, | 50 READPIXELS_SWAP, |
51 }; | 51 }; |
52 | 52 |
53 bool g_compositor_initialized = false; | |
53 base::Thread* g_compositor_thread = NULL; | 54 base::Thread* g_compositor_thread = NULL; |
54 | 55 |
55 bool g_test_compositor_enabled = false; | |
56 | |
57 ui::ContextFactory* g_implicit_factory = NULL; | 56 ui::ContextFactory* g_implicit_factory = NULL; |
58 ui::ContextFactory* g_context_factory = NULL; | 57 ui::ContextFactory* g_context_factory = NULL; |
59 | 58 |
60 const int kCompositorLockTimeoutMs = 67; | 59 const int kCompositorLockTimeoutMs = 67; |
61 | 60 |
62 class PendingSwap { | 61 class PendingSwap { |
63 public: | 62 public: |
64 PendingSwap(SwapType type, ui::PostedSwapQueue* posted_swaps); | 63 PendingSwap(SwapType type, ui::PostedSwapQueue* posted_swaps); |
65 ~PendingSwap(); | 64 ~PendingSwap(); |
66 | 65 |
67 SwapType type() const { return type_; } | 66 SwapType type() const { return type_; } |
68 bool posted() const { return posted_; } | 67 bool posted() const { return posted_; } |
69 | 68 |
70 private: | 69 private: |
71 friend class ui::PostedSwapQueue; | 70 friend class ui::PostedSwapQueue; |
72 | 71 |
73 SwapType type_; | 72 SwapType type_; |
74 bool posted_; | 73 bool posted_; |
75 ui::PostedSwapQueue* posted_swaps_; | 74 ui::PostedSwapQueue* posted_swaps_; |
76 | 75 |
77 DISALLOW_COPY_AND_ASSIGN(PendingSwap); | 76 DISALLOW_COPY_AND_ASSIGN(PendingSwap); |
78 }; | 77 }; |
79 | 78 |
80 void SetupImplicitFactory() { | |
81 // We leak the implicit factory so that we don't race with the tear down of | |
82 // the gl_bindings. | |
83 DCHECK(!g_context_factory); | |
84 DCHECK(!g_implicit_factory); | |
85 if (g_test_compositor_enabled) { | |
86 g_implicit_factory = new ui::TestContextFactory; | |
87 } else { | |
88 DVLOG(1) << "Using DefaultContextFactory"; | |
89 scoped_ptr<ui::DefaultContextFactory> instance( | |
90 new ui::DefaultContextFactory()); | |
91 if (instance->Initialize()) | |
92 g_implicit_factory = instance.release(); | |
93 } | |
94 g_context_factory = g_implicit_factory; | |
95 } | |
96 | |
97 void ResetImplicitFactory() { | |
98 if (!g_implicit_factory || g_context_factory != g_implicit_factory) | |
99 return; | |
100 delete g_implicit_factory; | |
101 g_implicit_factory = NULL; | |
102 g_context_factory = NULL; | |
103 } | |
104 | |
105 } // namespace | 79 } // namespace |
106 | 80 |
107 namespace ui { | 81 namespace ui { |
108 | 82 |
109 // static | 83 // static |
110 ContextFactory* ContextFactory::GetInstance() { | 84 ContextFactory* ContextFactory::GetInstance() { |
111 if (!g_context_factory) | 85 DCHECK(g_context_factory); |
112 SetupImplicitFactory(); | |
113 return g_context_factory; | 86 return g_context_factory; |
114 } | 87 } |
115 | 88 |
116 // static | 89 // static |
117 void ContextFactory::SetInstance(ContextFactory* instance) { | 90 void ContextFactory::SetInstance(ContextFactory* instance) { |
118 g_context_factory = instance; | 91 g_context_factory = instance; |
119 } | 92 } |
120 | 93 |
121 DefaultContextFactory::DefaultContextFactory() { | 94 DefaultContextFactory::DefaultContextFactory() { |
122 } | 95 } |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
173 !offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) { | 146 !offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) { |
174 offscreen_contexts_compositor_thread_ = | 147 offscreen_contexts_compositor_thread_ = |
175 ContextProviderFromContextFactory::CreateForOffscreen(this); | 148 ContextProviderFromContextFactory::CreateForOffscreen(this); |
176 } | 149 } |
177 return offscreen_contexts_compositor_thread_; | 150 return offscreen_contexts_compositor_thread_; |
178 } | 151 } |
179 | 152 |
180 void DefaultContextFactory::RemoveCompositor(Compositor* compositor) { | 153 void DefaultContextFactory::RemoveCompositor(Compositor* compositor) { |
181 } | 154 } |
182 | 155 |
156 bool DefaultContextFactory::UsesTestContexts() { return false; } | |
157 | |
183 scoped_ptr<WebKit::WebGraphicsContext3D> | 158 scoped_ptr<WebKit::WebGraphicsContext3D> |
184 DefaultContextFactory::CreateContextCommon(Compositor* compositor, | 159 DefaultContextFactory::CreateContextCommon(Compositor* compositor, |
185 bool offscreen) { | 160 bool offscreen) { |
186 DCHECK(offscreen || compositor); | 161 DCHECK(offscreen || compositor); |
187 WebKit::WebGraphicsContext3D::Attributes attrs; | 162 WebKit::WebGraphicsContext3D::Attributes attrs; |
188 attrs.depth = false; | 163 attrs.depth = false; |
189 attrs.stencil = false; | 164 attrs.stencil = false; |
190 attrs.antialias = false; | 165 attrs.antialias = false; |
191 attrs.shareResources = true; | 166 attrs.shareResources = true; |
192 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; | 167 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
241 offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) { | 216 offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) { |
242 offscreen_contexts_compositor_thread_ = | 217 offscreen_contexts_compositor_thread_ = |
243 ContextProviderFromContextFactory::CreateForOffscreen(this); | 218 ContextProviderFromContextFactory::CreateForOffscreen(this); |
244 } | 219 } |
245 return offscreen_contexts_compositor_thread_; | 220 return offscreen_contexts_compositor_thread_; |
246 } | 221 } |
247 | 222 |
248 void TestContextFactory::RemoveCompositor(Compositor* compositor) { | 223 void TestContextFactory::RemoveCompositor(Compositor* compositor) { |
249 } | 224 } |
250 | 225 |
226 bool TestContextFactory::UsesTestContexts() { return true; } | |
227 | |
251 Texture::Texture(bool flipped, const gfx::Size& size, float device_scale_factor) | 228 Texture::Texture(bool flipped, const gfx::Size& size, float device_scale_factor) |
252 : size_(size), | 229 : size_(size), |
253 flipped_(flipped), | 230 flipped_(flipped), |
254 device_scale_factor_(device_scale_factor) { | 231 device_scale_factor_(device_scale_factor) { |
255 } | 232 } |
256 | 233 |
257 Texture::~Texture() { | 234 Texture::~Texture() { |
258 } | 235 } |
259 | 236 |
260 std::string Texture::Produce() { | 237 std::string Texture::Produce() { |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
403 : delegate_(delegate), | 380 : delegate_(delegate), |
404 root_layer_(NULL), | 381 root_layer_(NULL), |
405 widget_(widget), | 382 widget_(widget), |
406 posted_swaps_(new PostedSwapQueue()), | 383 posted_swaps_(new PostedSwapQueue()), |
407 device_scale_factor_(0.0f), | 384 device_scale_factor_(0.0f), |
408 last_started_frame_(0), | 385 last_started_frame_(0), |
409 last_ended_frame_(0), | 386 last_ended_frame_(0), |
410 next_draw_is_resize_(false), | 387 next_draw_is_resize_(false), |
411 disable_schedule_composite_(false), | 388 disable_schedule_composite_(false), |
412 compositor_lock_(NULL) { | 389 compositor_lock_(NULL) { |
390 DCHECK(g_compositor_initialized) | |
391 << "Compositor::Initialize must be called before creating a Compositor"; | |
392 | |
413 root_web_layer_ = cc::Layer::Create(); | 393 root_web_layer_ = cc::Layer::Create(); |
414 root_web_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f)); | 394 root_web_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f)); |
415 | 395 |
416 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 396 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
417 | 397 |
418 cc::LayerTreeSettings settings; | 398 cc::LayerTreeSettings settings; |
419 settings.refresh_rate = | 399 settings.refresh_rate = ContextFactory::GetInstance()->UsesTestContexts() |
420 g_test_compositor_enabled ? kTestRefreshRate : kDefaultRefreshRate; | 400 ? kTestRefreshRate |
401 : kDefaultRefreshRate; | |
421 settings.partial_swap_enabled = | 402 settings.partial_swap_enabled = |
422 !command_line->HasSwitch(cc::switches::kUIDisablePartialSwap); | 403 !command_line->HasSwitch(cc::switches::kUIDisablePartialSwap); |
423 settings.per_tile_painting_enabled = | 404 settings.per_tile_painting_enabled = |
424 command_line->HasSwitch(cc::switches::kUIEnablePerTilePainting); | 405 command_line->HasSwitch(cc::switches::kUIEnablePerTilePainting); |
425 | 406 |
426 // These flags should be mirrored by renderer versions in content/renderer/. | 407 // These flags should be mirrored by renderer versions in content/renderer/. |
427 settings.initial_debug_state.show_debug_borders = | 408 settings.initial_debug_state.show_debug_borders = |
428 command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders); | 409 command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders); |
429 settings.initial_debug_state.show_fps_counter = | 410 settings.initial_debug_state.show_fps_counter = |
430 command_line->HasSwitch(cc::switches::kUIShowFPSCounter); | 411 command_line->HasSwitch(cc::switches::kUIShowFPSCounter); |
(...skipping 14 matching lines...) Expand all Loading... | |
445 | 426 |
446 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner = | 427 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner = |
447 g_compositor_thread ? g_compositor_thread->message_loop_proxy() : NULL; | 428 g_compositor_thread ? g_compositor_thread->message_loop_proxy() : NULL; |
448 | 429 |
449 host_ = cc::LayerTreeHost::Create(this, settings, compositor_task_runner); | 430 host_ = cc::LayerTreeHost::Create(this, settings, compositor_task_runner); |
450 host_->SetRootLayer(root_web_layer_); | 431 host_->SetRootLayer(root_web_layer_); |
451 host_->SetLayerTreeHostClientReady(); | 432 host_->SetLayerTreeHostClientReady(); |
452 } | 433 } |
453 | 434 |
454 Compositor::~Compositor() { | 435 Compositor::~Compositor() { |
436 DCHECK(g_compositor_initialized); | |
437 | |
455 CancelCompositorLock(); | 438 CancelCompositorLock(); |
456 DCHECK(!compositor_lock_); | 439 DCHECK(!compositor_lock_); |
457 | 440 |
458 // Don't call |CompositorDelegate::ScheduleDraw| from this point. | 441 // Don't call |CompositorDelegate::ScheduleDraw| from this point. |
459 delegate_ = NULL; | 442 delegate_ = NULL; |
460 if (root_layer_) | 443 if (root_layer_) |
461 root_layer_->SetCompositor(NULL); | 444 root_layer_->SetCompositor(NULL); |
462 | 445 |
463 // Stop all outstanding draws before telling the ContextFactory to tear | 446 // Stop all outstanding draws before telling the ContextFactory to tear |
464 // down any contexts that the |host_| may rely upon. | 447 // down any contexts that the |host_| may rely upon. |
465 host_.reset(); | 448 host_.reset(); |
466 | 449 |
467 ContextFactory::GetInstance()->RemoveCompositor(this); | 450 ContextFactory::GetInstance()->RemoveCompositor(this); |
468 } | 451 } |
469 | 452 |
470 // static | 453 // static |
454 void Compositor::InitializeContextFactoryForTests(bool allow_test_contexts) { | |
455 DCHECK(!g_context_factory) << "ContextFactory already initialized"; | |
456 DCHECK(!g_implicit_factory) << "ContextFactory for tests already initialized"; | |
457 | |
458 bool use_test_contexts = true; | |
459 | |
460 // Always use test contexts unless the disable command line flag is used. | |
461 CommandLine* command_line = CommandLine::ForCurrentProcess(); | |
462 if (command_line->HasSwitch(switches::kDisableTestCompositor)) | |
danakj
2013/07/31 01:32:51
I don't know if we really need to honor command li
piman
2013/07/31 07:01:48
The "test compositor" is an optimization for the b
| |
463 use_test_contexts = false; | |
464 | |
465 #if defined(OS_CHROMEOS) | |
466 // If the test is running on the chromeos envrionment (such as | |
467 // device or vm bots), always use real contexts. | |
468 if (base::chromeos::IsRunningOnChromeOS()) | |
469 use_test_contexts = false; | |
470 #endif | |
471 | |
472 if (!allow_test_contexts) | |
473 use_test_contexts = false; | |
474 | |
475 // We leak the implicit factory so that we don't race with the tear down of | |
476 // the gl_bindings. | |
piman
2013/07/31 07:01:48
nit: I guess we don't leak it any more...
| |
477 if (use_test_contexts) { | |
478 g_implicit_factory = new ui::TestContextFactory; | |
479 } else { | |
480 DVLOG(1) << "Using DefaultContextFactory"; | |
481 scoped_ptr<ui::DefaultContextFactory> instance( | |
482 new ui::DefaultContextFactory()); | |
483 if (instance->Initialize()) | |
484 g_implicit_factory = instance.release(); | |
485 } | |
486 g_context_factory = g_implicit_factory; | |
487 } | |
488 | |
489 // static | |
471 void Compositor::Initialize() { | 490 void Compositor::Initialize() { |
472 #if defined(OS_CHROMEOS) | 491 #if defined(OS_CHROMEOS) |
473 bool use_thread = !CommandLine::ForCurrentProcess()->HasSwitch( | 492 bool use_thread = !CommandLine::ForCurrentProcess()->HasSwitch( |
474 switches::kUIDisableThreadedCompositing); | 493 switches::kUIDisableThreadedCompositing); |
475 #else | 494 #else |
476 bool use_thread = | 495 bool use_thread = |
477 CommandLine::ForCurrentProcess()->HasSwitch( | 496 CommandLine::ForCurrentProcess()->HasSwitch( |
478 switches::kUIEnableThreadedCompositing) && | 497 switches::kUIEnableThreadedCompositing) && |
479 !CommandLine::ForCurrentProcess()->HasSwitch( | 498 !CommandLine::ForCurrentProcess()->HasSwitch( |
480 switches::kUIDisableThreadedCompositing); | 499 switches::kUIDisableThreadedCompositing); |
481 #endif | 500 #endif |
482 if (use_thread) { | 501 if (use_thread) { |
483 g_compositor_thread = new base::Thread("Browser Compositor"); | 502 g_compositor_thread = new base::Thread("Browser Compositor"); |
484 g_compositor_thread->Start(); | 503 g_compositor_thread->Start(); |
485 } | 504 } |
505 | |
506 DCHECK(!g_compositor_initialized) << "Compositor initialized twice."; | |
507 g_compositor_initialized = true; | |
486 } | 508 } |
487 | 509 |
488 // static | 510 // static |
489 bool Compositor::WasInitializedWithThread() { | 511 bool Compositor::WasInitializedWithThread() { |
490 return !!g_compositor_thread; | 512 return !!g_compositor_thread; |
491 } | 513 } |
492 | 514 |
493 // static | 515 // static |
494 scoped_refptr<base::MessageLoopProxy> Compositor::GetCompositorMessageLoop() { | 516 scoped_refptr<base::MessageLoopProxy> Compositor::GetCompositorMessageLoop() { |
495 scoped_refptr<base::MessageLoopProxy> proxy; | 517 scoped_refptr<base::MessageLoopProxy> proxy; |
496 if (g_compositor_thread) | 518 if (g_compositor_thread) |
497 proxy = g_compositor_thread->message_loop_proxy(); | 519 proxy = g_compositor_thread->message_loop_proxy(); |
498 return proxy; | 520 return proxy; |
499 } | 521 } |
500 | 522 |
501 // static | 523 // static |
502 void Compositor::Terminate() { | 524 void Compositor::Terminate() { |
525 if (g_context_factory) { | |
526 if (g_implicit_factory) { | |
527 delete g_implicit_factory; | |
528 g_implicit_factory = NULL; | |
529 } | |
530 g_context_factory = NULL; | |
531 } | |
532 | |
503 if (g_compositor_thread) { | 533 if (g_compositor_thread) { |
534 DCHECK(!g_context_factory) | |
535 << "The ContextFactory should not outlive the compositor thread."; | |
504 g_compositor_thread->Stop(); | 536 g_compositor_thread->Stop(); |
505 delete g_compositor_thread; | 537 delete g_compositor_thread; |
506 g_compositor_thread = NULL; | 538 g_compositor_thread = NULL; |
507 } | 539 } |
540 | |
541 DCHECK(g_compositor_initialized) << "Compositor::Initialize() didn't happen"; | |
542 g_compositor_initialized = false; | |
508 } | 543 } |
509 | 544 |
510 void Compositor::ScheduleDraw() { | 545 void Compositor::ScheduleDraw() { |
511 if (g_compositor_thread) | 546 if (g_compositor_thread) |
512 host_->Composite(base::TimeTicks::Now()); | 547 host_->Composite(base::TimeTicks::Now()); |
513 else if (delegate_) | 548 else if (delegate_) |
514 delegate_->ScheduleDraw(); | 549 delegate_->ScheduleDraw(); |
515 } | 550 } |
516 | 551 |
517 void Compositor::SetRootLayer(Layer* root_layer) { | 552 void Compositor::SetRootLayer(Layer* root_layer) { |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
744 compositor_lock_->CancelLock(); | 779 compositor_lock_->CancelLock(); |
745 } | 780 } |
746 | 781 |
747 void Compositor::NotifyEnd() { | 782 void Compositor::NotifyEnd() { |
748 last_ended_frame_++; | 783 last_ended_frame_++; |
749 FOR_EACH_OBSERVER(CompositorObserver, | 784 FOR_EACH_OBSERVER(CompositorObserver, |
750 observer_list_, | 785 observer_list_, |
751 OnCompositingEnded(this)); | 786 OnCompositingEnded(this)); |
752 } | 787 } |
753 | 788 |
754 COMPOSITOR_EXPORT void SetupTestCompositor() { | |
755 if (!CommandLine::ForCurrentProcess()->HasSwitch( | |
756 switches::kDisableTestCompositor)) { | |
757 g_test_compositor_enabled = true; | |
758 } | |
759 #if defined(OS_CHROMEOS) | |
760 // If the test is running on the chromeos envrionment (such as | |
761 // device or vm bots), use the real compositor. | |
762 if (base::chromeos::IsRunningOnChromeOS()) | |
763 g_test_compositor_enabled = false; | |
764 #endif | |
765 ResetImplicitFactory(); | |
766 } | |
767 | |
768 COMPOSITOR_EXPORT void DisableTestCompositor() { | |
769 ResetImplicitFactory(); | |
770 g_test_compositor_enabled = false; | |
771 } | |
772 | |
773 COMPOSITOR_EXPORT bool IsTestCompositorEnabled() { | |
774 return g_test_compositor_enabled; | |
775 } | |
776 | |
777 } // namespace ui | 789 } // namespace ui |
OLD | NEW |