blob: f37be67c53c6ee717bc2f3878bc3fea249ed68ab [file] [log] [blame]
[email protected]1920930592012-01-11 14:54:481// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]c797cd42011-03-15 02:18:362// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]116302fc2012-05-05 21:45:415#include "ui/compositor/compositor.h"
[email protected]ed8de92d2011-09-14 04:16:486
[email protected]cff176a2012-06-29 21:11:007#include <algorithm>
[email protected]337bd042012-11-05 23:43:438#include <deque>
[email protected]cff176a2012-06-29 21:11:009
[email protected]6b16679e2012-10-27 00:44:2810#include "base/bind.h"
[email protected]ab6627372012-01-29 21:22:1311#include "base/command_line.h"
[email protected]0a451722013-02-22 20:32:0512#include "base/memory/singleton.h"
[email protected]4e2d03e22013-07-18 04:19:5413#include "base/message_loop/message_loop.h"
[email protected]1e7565a2013-04-08 20:11:1414#include "base/run_loop.h"
[email protected]f3652ff92013-06-11 13:54:3115#include "base/strings/string_util.h"
[email protected]ec05af52012-11-21 23:07:0016#include "base/threading/thread.h"
[email protected]894e8fc2012-02-24 13:29:5017#include "base/threading/thread_restrictions.h"
[email protected]4d5e6762013-03-19 18:46:5718#include "cc/base/switches.h"
[email protected]3052b10f2013-03-18 07:41:2119#include "cc/input/input_handler.h"
[email protected]cc3cfaa2013-03-18 09:05:5220#include "cc/layers/layer.h"
[email protected]7f0d825f2013-03-18 07:24:3021#include "cc/output/context_provider.h"
22#include "cc/output/output_surface.h"
[email protected]556fd292013-03-18 08:03:0423#include "cc/trees/layer_tree_host.h"
[email protected]83afcbcc2012-07-27 03:06:2724#include "third_party/skia/include/core/SkBitmap.h"
[email protected]116302fc2012-05-05 21:45:4125#include "ui/compositor/compositor_observer.h"
26#include "ui/compositor/compositor_switches.h"
[email protected]cd9a61c72012-05-08 19:16:5927#include "ui/compositor/dip_util.h"
[email protected]116302fc2012-05-05 21:45:4128#include "ui/compositor/layer.h"
29#include "ui/compositor/test_web_graphics_context_3d.h"
[email protected]c9e2cbbb2012-05-12 21:17:2730#include "ui/gl/gl_context.h"
31#include "ui/gl/gl_implementation.h"
32#include "ui/gl/gl_surface.h"
[email protected]cc2ae012012-09-21 19:35:2533#include "ui/gl/gl_switches.h"
[email protected]1fb9e7e2013-05-26 03:23:4834#include "webkit/common/gpu/grcontext_for_webgraphicscontext3d.h"
35#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
[email protected]ab6627372012-01-29 21:22:1336
[email protected]8391a49e2012-05-26 06:31:0437#if defined(OS_CHROMEOS)
38#include "base/chromeos/chromeos_version.h"
39#endif
40
[email protected]ab6627372012-01-29 21:22:1341namespace {
42
43const double kDefaultRefreshRate = 60.0;
[email protected]7ddeaab2013-04-06 00:47:0544const double kTestRefreshRate = 200.0;
[email protected]ab6627372012-01-29 21:22:1345
[email protected]337bd042012-11-05 23:43:4346enum SwapType {
47 DRAW_SWAP,
48 READPIXELS_SWAP,
49};
50
[email protected]ec05af52012-11-21 23:07:0051base::Thread* g_compositor_thread = NULL;
[email protected]ab6627372012-01-29 21:22:1352
[email protected]8cbffc62013-01-23 22:11:0953bool g_test_compositor_enabled = false;
[email protected]ab6627372012-01-29 21:22:1354
[email protected]40034cf2013-03-13 05:05:3755ui::ContextFactory* g_implicit_factory = NULL;
[email protected]894e8fc2012-02-24 13:29:5056ui::ContextFactory* g_context_factory = NULL;
57
[email protected]6b16679e2012-10-27 00:44:2858const int kCompositorLockTimeoutMs = 67;
59
[email protected]337bd042012-11-05 23:43:4360class PendingSwap {
61 public:
62 PendingSwap(SwapType type, ui::PostedSwapQueue* posted_swaps);
63 ~PendingSwap();
64
65 SwapType type() const { return type_; }
66 bool posted() const { return posted_; }
67
68 private:
69 friend class ui::PostedSwapQueue;
70
71 SwapType type_;
72 bool posted_;
73 ui::PostedSwapQueue* posted_swaps_;
74
75 DISALLOW_COPY_AND_ASSIGN(PendingSwap);
76};
77
[email protected]40034cf2013-03-13 05:05:3778void SetupImplicitFactory() {
79 // We leak the implicit factory so that we don't race with the tear down of
80 // the gl_bindings.
81 DCHECK(!g_context_factory);
82 DCHECK(!g_implicit_factory);
83 if (g_test_compositor_enabled) {
84 g_implicit_factory = new ui::TestContextFactory;
85 } else {
86 DVLOG(1) << "Using DefaultContextFactory";
87 scoped_ptr<ui::DefaultContextFactory> instance(
88 new ui::DefaultContextFactory());
89 if (instance->Initialize())
90 g_implicit_factory = instance.release();
[email protected]0a451722013-02-22 20:32:0591 }
[email protected]40034cf2013-03-13 05:05:3792 g_context_factory = g_implicit_factory;
93}
[email protected]0a451722013-02-22 20:32:0594
[email protected]40034cf2013-03-13 05:05:3795void ResetImplicitFactory() {
96 if (!g_implicit_factory || g_context_factory != g_implicit_factory)
97 return;
98 delete g_implicit_factory;
99 g_implicit_factory = NULL;
100 g_context_factory = NULL;
101}
[email protected]0a451722013-02-22 20:32:05102
[email protected]83afcbcc2012-07-27 03:06:27103} // namespace
[email protected]c797cd42011-03-15 02:18:36104
105namespace ui {
106
[email protected]894e8fc2012-02-24 13:29:50107// static
108ContextFactory* ContextFactory::GetInstance() {
[email protected]40034cf2013-03-13 05:05:37109 if (!g_context_factory)
110 SetupImplicitFactory();
[email protected]894e8fc2012-02-24 13:29:50111 return g_context_factory;
[email protected]ca806632012-02-16 02:15:59112}
113
[email protected]58b4b6d2012-02-16 01:40:24114// static
[email protected]894e8fc2012-02-24 13:29:50115void ContextFactory::SetInstance(ContextFactory* instance) {
116 g_context_factory = instance;
[email protected]ca806632012-02-16 02:15:59117}
118
[email protected]40034cf2013-03-13 05:05:37119class ContextProviderFromContextFactory : public cc::ContextProvider {
[email protected]0a451722013-02-22 20:32:05120 public:
[email protected]e06e1122013-03-15 17:12:38121 static scoped_refptr<ContextProviderFromContextFactory> Create(
122 ContextFactory* factory) {
123 scoped_refptr<ContextProviderFromContextFactory> provider =
124 new ContextProviderFromContextFactory(factory);
125 if (!provider->InitializeOnMainThread())
126 return NULL;
127 return provider;
[email protected]0a451722013-02-22 20:32:05128 }
129
[email protected]aa3174b2013-03-15 09:12:48130 virtual bool BindToCurrentThread() OVERRIDE {
[email protected]e06e1122013-03-15 17:12:38131 DCHECK(context3d_);
132
[email protected]0a451722013-02-22 20:32:05133 return context3d_->makeContextCurrent();
134 }
135
[email protected]aa3174b2013-03-15 09:12:48136 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
[email protected]e06e1122013-03-15 17:12:38137 DCHECK(context3d_);
138
[email protected]aa3174b2013-03-15 09:12:48139 return context3d_.get();
140 }
[email protected]0a451722013-02-22 20:32:05141
[email protected]aa3174b2013-03-15 09:12:48142 virtual class GrContext* GrContext() OVERRIDE {
[email protected]e06e1122013-03-15 17:12:38143 DCHECK(context3d_);
144
[email protected]0a451722013-02-22 20:32:05145 if (!gr_context_) {
146 gr_context_.reset(
147 new webkit::gpu::GrContextForWebGraphicsContext3D(context3d_.get()));
148 }
149 return gr_context_->get();
150 }
151
152 virtual void VerifyContexts() OVERRIDE {
[email protected]e06e1122013-03-15 17:12:38153 DCHECK(context3d_);
154
155 if (context3d_->isContextLost()) {
156 base::AutoLock lock(destroyed_lock_);
157 destroyed_ = true;
158 }
[email protected]0a451722013-02-22 20:32:05159 }
160
[email protected]aa3174b2013-03-15 09:12:48161 virtual bool DestroyedOnMainThread() OVERRIDE {
[email protected]0a451722013-02-22 20:32:05162 base::AutoLock lock(destroyed_lock_);
163 return destroyed_;
164 }
165
166 protected:
[email protected]e06e1122013-03-15 17:12:38167 explicit ContextProviderFromContextFactory(ContextFactory* factory)
168 : factory_(factory),
169 destroyed_(false) {}
[email protected]40034cf2013-03-13 05:05:37170 virtual ~ContextProviderFromContextFactory() {}
[email protected]0a451722013-02-22 20:32:05171
[email protected]e06e1122013-03-15 17:12:38172 bool InitializeOnMainThread() {
173 if (context3d_)
174 return true;
[email protected]59fe2c32013-06-21 10:03:37175 context3d_ = factory_->CreateOffscreenContext();
[email protected]e06e1122013-03-15 17:12:38176 return !!context3d_;
177 }
178
[email protected]0a451722013-02-22 20:32:05179 private:
180 ContextFactory* factory_;
181 base::Lock destroyed_lock_;
182 bool destroyed_;
183 scoped_ptr<WebKit::WebGraphicsContext3D> context3d_;
184 scoped_ptr<webkit::gpu::GrContextForWebGraphicsContext3D> gr_context_;
185};
186
[email protected]40034cf2013-03-13 05:05:37187DefaultContextFactory::DefaultContextFactory() {
188}
189
190DefaultContextFactory::~DefaultContextFactory() {
191}
192
193bool DefaultContextFactory::Initialize() {
194 if (!gfx::GLSurface::InitializeOneOff() ||
195 gfx::GetGLImplementation() == gfx::kGLImplementationNone) {
196 LOG(ERROR) << "Could not load the GL bindings";
197 return false;
198 }
199 return true;
200}
201
202cc::OutputSurface* DefaultContextFactory::CreateOutputSurface(
203 Compositor* compositor) {
[email protected]59fe2c32013-06-21 10:03:37204 return new cc::OutputSurface(CreateContextCommon(compositor, false).Pass());
[email protected]40034cf2013-03-13 05:05:37205}
206
[email protected]59fe2c32013-06-21 10:03:37207scoped_ptr<WebKit::WebGraphicsContext3D>
208DefaultContextFactory::CreateOffscreenContext() {
[email protected]40034cf2013-03-13 05:05:37209 return CreateContextCommon(NULL, true);
210}
211
[email protected]57bed4d2013-06-08 20:54:18212scoped_refptr<Reflector> DefaultContextFactory::CreateReflector(
213 Compositor* mirroed_compositor,
214 Layer* mirroring_layer) {
215 return NULL;
216}
217
218void DefaultContextFactory::RemoveReflector(
219 scoped_refptr<Reflector> reflector) {
220}
221
[email protected]0a451722013-02-22 20:32:05222scoped_refptr<cc::ContextProvider>
223DefaultContextFactory::OffscreenContextProviderForMainThread() {
[email protected]d33c74412013-06-03 00:18:13224 if (!offscreen_contexts_main_thread_.get() ||
[email protected]0a451722013-02-22 20:32:05225 !offscreen_contexts_main_thread_->DestroyedOnMainThread()) {
[email protected]40034cf2013-03-13 05:05:37226 offscreen_contexts_main_thread_ =
[email protected]e06e1122013-03-15 17:12:38227 ContextProviderFromContextFactory::Create(this);
[email protected]d33c74412013-06-03 00:18:13228 if (offscreen_contexts_main_thread_.get() &&
[email protected]e06e1122013-03-15 17:12:38229 !offscreen_contexts_main_thread_->BindToCurrentThread())
230 offscreen_contexts_main_thread_ = NULL;
[email protected]0a451722013-02-22 20:32:05231 }
232 return offscreen_contexts_main_thread_;
233}
234
235scoped_refptr<cc::ContextProvider>
236DefaultContextFactory::OffscreenContextProviderForCompositorThread() {
[email protected]d33c74412013-06-03 00:18:13237 if (!offscreen_contexts_compositor_thread_.get() ||
[email protected]0a451722013-02-22 20:32:05238 !offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) {
[email protected]40034cf2013-03-13 05:05:37239 offscreen_contexts_compositor_thread_ =
[email protected]e06e1122013-03-15 17:12:38240 ContextProviderFromContextFactory::Create(this);
[email protected]0a451722013-02-22 20:32:05241 }
242 return offscreen_contexts_compositor_thread_;
243}
244
[email protected]84dba8ca2012-04-10 03:27:39245void DefaultContextFactory::RemoveCompositor(Compositor* compositor) {
246}
247
[email protected]59fe2c32013-06-21 10:03:37248scoped_ptr<WebKit::WebGraphicsContext3D>
249DefaultContextFactory::CreateContextCommon(Compositor* compositor,
250 bool offscreen) {
[email protected]b18ed0aa2012-08-22 04:20:20251 DCHECK(offscreen || compositor);
[email protected]894e8fc2012-02-24 13:29:50252 WebKit::WebGraphicsContext3D::Attributes attrs;
[email protected]b63dce52012-08-22 22:51:50253 attrs.depth = false;
254 attrs.stencil = false;
255 attrs.antialias = false;
[email protected]894e8fc2012-02-24 13:29:50256 attrs.shareResources = true;
[email protected]f1be8fc32013-04-19 20:57:33257 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
[email protected]ad97838e2013-07-12 23:21:52258 if (offscreen) {
259 return WebGraphicsContext3DInProcessCommandBufferImpl::
260 CreateOffscreenContext(attrs);
[email protected]894e8fc2012-02-24 13:29:50261 }
[email protected]ad97838e2013-07-12 23:21:52262 return WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext(
263 attrs, compositor->widget());
[email protected]ab6627372012-01-29 21:22:13264}
265
[email protected]e06e1122013-03-15 17:12:38266TestContextFactory::TestContextFactory() {}
[email protected]40034cf2013-03-13 05:05:37267
[email protected]e06e1122013-03-15 17:12:38268TestContextFactory::~TestContextFactory() {}
[email protected]40034cf2013-03-13 05:05:37269
270cc::OutputSurface* TestContextFactory::CreateOutputSurface(
271 Compositor* compositor) {
[email protected]59fe2c32013-06-21 10:03:37272 return new cc::OutputSurface(CreateOffscreenContext());
[email protected]40034cf2013-03-13 05:05:37273}
274
[email protected]59fe2c32013-06-21 10:03:37275scoped_ptr<WebKit::WebGraphicsContext3D>
276TestContextFactory::CreateOffscreenContext() {
277 scoped_ptr<ui::TestWebGraphicsContext3D> context(
278 new ui::TestWebGraphicsContext3D);
[email protected]40034cf2013-03-13 05:05:37279 context->Initialize();
[email protected]59fe2c32013-06-21 10:03:37280 return context.PassAs<WebKit::WebGraphicsContext3D>();
[email protected]40034cf2013-03-13 05:05:37281}
282
[email protected]57bed4d2013-06-08 20:54:18283scoped_refptr<Reflector> TestContextFactory::CreateReflector(
284 Compositor* mirrored_compositor,
285 Layer* mirroring_layer) {
286 return new Reflector();
287}
288
289void TestContextFactory::RemoveReflector(scoped_refptr<Reflector> reflector) {
290}
291
[email protected]40034cf2013-03-13 05:05:37292scoped_refptr<cc::ContextProvider>
293TestContextFactory::OffscreenContextProviderForMainThread() {
[email protected]d33c74412013-06-03 00:18:13294 if (!offscreen_contexts_main_thread_.get() ||
[email protected]e06e1122013-03-15 17:12:38295 offscreen_contexts_main_thread_->DestroyedOnMainThread()) {
296 offscreen_contexts_main_thread_ =
297 ContextProviderFromContextFactory::Create(this);
298 CHECK(offscreen_contexts_main_thread_->BindToCurrentThread());
299 }
[email protected]40034cf2013-03-13 05:05:37300 return offscreen_contexts_main_thread_;
301}
302
303scoped_refptr<cc::ContextProvider>
304TestContextFactory::OffscreenContextProviderForCompositorThread() {
[email protected]d33c74412013-06-03 00:18:13305 if (!offscreen_contexts_compositor_thread_.get() ||
[email protected]e06e1122013-03-15 17:12:38306 offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) {
307 offscreen_contexts_compositor_thread_ =
308 ContextProviderFromContextFactory::Create(this);
309 }
[email protected]40034cf2013-03-13 05:05:37310 return offscreen_contexts_compositor_thread_;
311}
312
313void TestContextFactory::RemoveCompositor(Compositor* compositor) {
314}
315
[email protected]d3407cdb2012-09-21 22:33:25316Texture::Texture(bool flipped, const gfx::Size& size, float device_scale_factor)
[email protected]34466d02012-12-10 18:00:34317 : size_(size),
318 flipped_(flipped),
[email protected]d3407cdb2012-09-21 22:33:25319 device_scale_factor_(device_scale_factor) {
[email protected]ab6627372012-01-29 21:22:13320}
321
322Texture::~Texture() {
323}
324
[email protected]06666c02013-03-07 19:32:30325std::string Texture::Produce() {
326 return EmptyString();
[email protected]f027ca1502012-12-21 01:42:32327}
328
[email protected]6b16679e2012-10-27 00:44:28329CompositorLock::CompositorLock(Compositor* compositor)
330 : compositor_(compositor) {
[email protected]7060d6592013-04-29 19:01:48331 base::MessageLoop::current()->PostDelayedTask(
[email protected]6b16679e2012-10-27 00:44:28332 FROM_HERE,
333 base::Bind(&CompositorLock::CancelLock, AsWeakPtr()),
334 base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs));
335}
336
337CompositorLock::~CompositorLock() {
338 CancelLock();
339}
340
341void CompositorLock::CancelLock() {
342 if (!compositor_)
343 return;
344 compositor_->UnlockCompositor();
345 compositor_ = NULL;
346}
347
[email protected]1e7565a2013-04-08 20:11:14348// static
[email protected]260c3212013-04-11 22:25:38349void DrawWaiterForTest::Wait(Compositor* compositor) {
[email protected]1e7565a2013-04-08 20:11:14350 DrawWaiterForTest waiter;
[email protected]36e5ff12013-06-11 12:19:29351 waiter.wait_for_commit_ = false;
352 waiter.WaitImpl(compositor);
353}
354
355// static
356void DrawWaiterForTest::WaitForCommit(Compositor* compositor) {
357 DrawWaiterForTest waiter;
358 waiter.wait_for_commit_ = true;
[email protected]260c3212013-04-11 22:25:38359 waiter.WaitImpl(compositor);
[email protected]1e7565a2013-04-08 20:11:14360}
361
[email protected]260c3212013-04-11 22:25:38362DrawWaiterForTest::DrawWaiterForTest() {
[email protected]1e7565a2013-04-08 20:11:14363}
364
365DrawWaiterForTest::~DrawWaiterForTest() {
366}
367
[email protected]260c3212013-04-11 22:25:38368void DrawWaiterForTest::WaitImpl(Compositor* compositor) {
[email protected]1e7565a2013-04-08 20:11:14369 compositor->AddObserver(this);
370 wait_run_loop_.reset(new base::RunLoop());
[email protected]1e7565a2013-04-08 20:11:14371 wait_run_loop_->Run();
372 compositor->RemoveObserver(this);
[email protected]1e7565a2013-04-08 20:11:14373}
374
375void DrawWaiterForTest::OnCompositingDidCommit(Compositor* compositor) {
[email protected]36e5ff12013-06-11 12:19:29376 if (wait_for_commit_)
377 wait_run_loop_->Quit();
[email protected]1e7565a2013-04-08 20:11:14378}
379
380void DrawWaiterForTest::OnCompositingStarted(Compositor* compositor,
381 base::TimeTicks start_time) {
382}
383
384void DrawWaiterForTest::OnCompositingEnded(Compositor* compositor) {
[email protected]36e5ff12013-06-11 12:19:29385 if (!wait_for_commit_)
386 wait_run_loop_->Quit();
[email protected]1e7565a2013-04-08 20:11:14387}
388
389void DrawWaiterForTest::OnCompositingAborted(Compositor* compositor) {
390}
391
392void DrawWaiterForTest::OnCompositingLockStateChanged(Compositor* compositor) {
393}
394
395void DrawWaiterForTest::OnUpdateVSyncParameters(Compositor* compositor,
396 base::TimeTicks timebase,
397 base::TimeDelta interval) {
398}
399
[email protected]337bd042012-11-05 23:43:43400class PostedSwapQueue {
401 public:
402 PostedSwapQueue() : pending_swap_(NULL) {
403 }
404
405 ~PostedSwapQueue() {
406 DCHECK(!pending_swap_);
407 }
408
409 SwapType NextPostedSwap() const {
410 return queue_.front();
411 }
412
413 bool AreSwapsPosted() const {
414 return !queue_.empty();
415 }
416
417 int NumSwapsPosted(SwapType type) const {
418 int count = 0;
419 for (std::deque<SwapType>::const_iterator it = queue_.begin();
420 it != queue_.end(); ++it) {
421 if (*it == type)
422 count++;
423 }
424 return count;
425 }
426
427 void PostSwap() {
428 DCHECK(pending_swap_);
429 queue_.push_back(pending_swap_->type());
430 pending_swap_->posted_ = true;
431 }
432
433 void EndSwap() {
434 queue_.pop_front();
435 }
436
437 private:
438 friend class ::PendingSwap;
439
440 PendingSwap* pending_swap_;
441 std::deque<SwapType> queue_;
442
443 DISALLOW_COPY_AND_ASSIGN(PostedSwapQueue);
444};
445
446} // namespace ui
447
448namespace {
449
450PendingSwap::PendingSwap(SwapType type, ui::PostedSwapQueue* posted_swaps)
451 : type_(type), posted_(false), posted_swaps_(posted_swaps) {
452 // Only one pending swap in flight.
453 DCHECK_EQ(static_cast<PendingSwap*>(NULL), posted_swaps_->pending_swap_);
454 posted_swaps_->pending_swap_ = this;
455}
456
457PendingSwap::~PendingSwap() {
458 DCHECK_EQ(this, posted_swaps_->pending_swap_);
459 posted_swaps_->pending_swap_ = NULL;
460}
461
462} // namespace
463
464namespace ui {
465
[email protected]ab6627372012-01-29 21:22:13466Compositor::Compositor(CompositorDelegate* delegate,
[email protected]cd9a61c72012-05-08 19:16:59467 gfx::AcceleratedWidget widget)
[email protected]82a01ac2011-09-08 16:00:18468 : delegate_(delegate),
[email protected]ab6627372012-01-29 21:22:13469 root_layer_(NULL),
470 widget_(widget),
[email protected]337bd042012-11-05 23:43:43471 posted_swaps_(new PostedSwapQueue()),
[email protected]d4ae80572012-06-06 23:02:06472 device_scale_factor_(0.0f),
473 last_started_frame_(0),
474 last_ended_frame_(0),
[email protected]8d9080ab2013-04-06 00:03:20475 next_draw_is_resize_(false),
[email protected]6b16679e2012-10-27 00:44:28476 disable_schedule_composite_(false),
477 compositor_lock_(NULL) {
[email protected]7aba6662013-03-12 10:17:34478 root_web_layer_ = cc::Layer::Create();
479 root_web_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f));
[email protected]ec05af52012-11-21 23:07:00480
[email protected]ab6627372012-01-29 21:22:13481 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]4d5e6762013-03-19 18:46:57482
[email protected]ec05af52012-11-21 23:07:00483 cc::LayerTreeSettings settings;
[email protected]8e0176d2013-03-21 03:14:52484 settings.refresh_rate =
[email protected]8cbffc62013-01-23 22:11:09485 g_test_compositor_enabled ? kTestRefreshRate : kDefaultRefreshRate;
[email protected]50e157272013-04-13 05:07:19486 settings.partial_swap_enabled =
487 !command_line->HasSwitch(cc::switches::kUIDisablePartialSwap);
[email protected]8e0176d2013-03-21 03:14:52488 settings.per_tile_painting_enabled =
[email protected]4d5e6762013-03-19 18:46:57489 command_line->HasSwitch(cc::switches::kUIEnablePerTilePainting);
490
491 // These flags should be mirrored by renderer versions in content/renderer/.
[email protected]8e0176d2013-03-21 03:14:52492 settings.initial_debug_state.show_debug_borders =
[email protected]4d5e6762013-03-19 18:46:57493 command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders);
[email protected]8e0176d2013-03-21 03:14:52494 settings.initial_debug_state.show_fps_counter =
[email protected]4d5e6762013-03-19 18:46:57495 command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
[email protected]8e0176d2013-03-21 03:14:52496 settings.initial_debug_state.show_paint_rects =
[email protected]4d5e6762013-03-19 18:46:57497 command_line->HasSwitch(switches::kUIShowPaintRects);
[email protected]8e0176d2013-03-21 03:14:52498 settings.initial_debug_state.show_property_changed_rects =
[email protected]4d5e6762013-03-19 18:46:57499 command_line->HasSwitch(cc::switches::kUIShowPropertyChangedRects);
[email protected]8e0176d2013-03-21 03:14:52500 settings.initial_debug_state.show_surface_damage_rects =
[email protected]4d5e6762013-03-19 18:46:57501 command_line->HasSwitch(cc::switches::kUIShowSurfaceDamageRects);
[email protected]8e0176d2013-03-21 03:14:52502 settings.initial_debug_state.show_screen_space_rects =
[email protected]4d5e6762013-03-19 18:46:57503 command_line->HasSwitch(cc::switches::kUIShowScreenSpaceRects);
[email protected]8e0176d2013-03-21 03:14:52504 settings.initial_debug_state.show_replica_screen_space_rects =
[email protected]4d5e6762013-03-19 18:46:57505 command_line->HasSwitch(cc::switches::kUIShowReplicaScreenSpaceRects);
[email protected]8e0176d2013-03-21 03:14:52506 settings.initial_debug_state.show_occluding_rects =
[email protected]4d5e6762013-03-19 18:46:57507 command_line->HasSwitch(cc::switches::kUIShowOccludingRects);
[email protected]8e0176d2013-03-21 03:14:52508 settings.initial_debug_state.show_non_occluding_rects =
[email protected]4d5e6762013-03-19 18:46:57509 command_line->HasSwitch(cc::switches::kUIShowNonOccludingRects);
[email protected]302fe422012-06-11 14:49:11510
[email protected]810d40b72013-06-20 18:26:15511 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner =
512 g_compositor_thread ? g_compositor_thread->message_loop_proxy() : NULL;
[email protected]ec05af52012-11-21 23:07:00513
[email protected]810d40b72013-06-20 18:26:15514 host_ = cc::LayerTreeHost::Create(this, settings, compositor_task_runner);
[email protected]804c8982013-03-13 16:32:21515 host_->SetRootLayer(root_web_layer_);
[email protected]14bd5542013-05-08 21:51:30516 host_->SetLayerTreeHostClientReady();
[email protected]82a01ac2011-09-08 16:00:18517}
518
519Compositor::~Compositor() {
[email protected]6b16679e2012-10-27 00:44:28520 CancelCompositorLock();
521 DCHECK(!compositor_lock_);
522
[email protected]e332a1b2012-05-10 20:32:27523 // Don't call |CompositorDelegate::ScheduleDraw| from this point.
524 delegate_ = NULL;
[email protected]7ab3f272011-11-16 00:51:56525 if (root_layer_)
526 root_layer_->SetCompositor(NULL);
[email protected]2700daddd2012-07-13 19:35:37527
528 // Stop all outstanding draws before telling the ContextFactory to tear
529 // down any contexts that the |host_| may rely upon.
530 host_.reset();
531
[email protected]40034cf2013-03-13 05:05:37532 ContextFactory::GetInstance()->RemoveCompositor(this);
[email protected]82a01ac2011-09-08 16:00:18533}
534
[email protected]44ed4bd2013-04-06 00:11:27535// static
[email protected]188df652013-04-15 14:03:39536void Compositor::Initialize() {
537#if defined(OS_CHROMEOS)
538 bool use_thread = !CommandLine::ForCurrentProcess()->HasSwitch(
539 switches::kUIDisableThreadedCompositing);
540#else
541 bool use_thread =
542 CommandLine::ForCurrentProcess()->HasSwitch(
543 switches::kUIEnableThreadedCompositing) &&
544 !CommandLine::ForCurrentProcess()->HasSwitch(
545 switches::kUIDisableThreadedCompositing);
546#endif
[email protected]ec05af52012-11-21 23:07:00547 if (use_thread) {
548 g_compositor_thread = new base::Thread("Browser Compositor");
549 g_compositor_thread->Start();
550 }
[email protected]ab6627372012-01-29 21:22:13551}
552
[email protected]44ed4bd2013-04-06 00:11:27553// static
554bool Compositor::WasInitializedWithThread() {
555 return !!g_compositor_thread;
556}
557
558// static
[email protected]c7abcfd82013-06-01 04:02:12559scoped_refptr<base::MessageLoopProxy> Compositor::GetCompositorMessageLoop() {
560 scoped_refptr<base::MessageLoopProxy> proxy;
561 if (g_compositor_thread)
562 proxy = g_compositor_thread->message_loop_proxy();
563 return proxy;
564}
565
566// static
[email protected]ab6627372012-01-29 21:22:13567void Compositor::Terminate() {
[email protected]ab6627372012-01-29 21:22:13568 if (g_compositor_thread) {
[email protected]ec05af52012-11-21 23:07:00569 g_compositor_thread->Stop();
[email protected]ab6627372012-01-29 21:22:13570 delete g_compositor_thread;
571 g_compositor_thread = NULL;
572 }
573}
574
[email protected]332749032011-10-22 00:32:46575void Compositor::ScheduleDraw() {
[email protected]4ea4e2d2012-11-20 15:17:09576 if (g_compositor_thread)
[email protected]f0c2a242013-03-15 19:34:52577 host_->Composite(base::TimeTicks::Now());
[email protected]4ea4e2d2012-11-20 15:17:09578 else if (delegate_)
[email protected]ab6627372012-01-29 21:22:13579 delegate_->ScheduleDraw();
[email protected]332749032011-10-22 00:32:46580}
581
[email protected]993d6b322011-09-27 19:14:38582void Compositor::SetRootLayer(Layer* root_layer) {
[email protected]12233c362011-11-21 16:09:25583 if (root_layer_ == root_layer)
584 return;
[email protected]7ab3f272011-11-16 00:51:56585 if (root_layer_)
586 root_layer_->SetCompositor(NULL);
[email protected]993d6b322011-09-27 19:14:38587 root_layer_ = root_layer;
[email protected]7ab3f272011-11-16 00:51:56588 if (root_layer_ && !root_layer_->GetCompositor())
[email protected]993d6b322011-09-27 19:14:38589 root_layer_->SetCompositor(this);
[email protected]7aba6662013-03-12 10:17:34590 root_web_layer_->RemoveAllChildren();
[email protected]66efabe2012-08-18 03:06:06591 if (root_layer_)
[email protected]7aba6662013-03-12 10:17:34592 root_web_layer_->AddChild(root_layer_->cc_layer());
[email protected]993d6b322011-09-27 19:14:38593}
594
[email protected]ebd52522012-10-04 15:49:40595void Compositor::SetHostHasTransparentBackground(
596 bool host_has_transparent_background) {
[email protected]804c8982013-03-13 16:32:21597 host_->set_has_transparent_background(host_has_transparent_background);
[email protected]ebd52522012-10-04 15:49:40598}
599
[email protected]878705be2013-04-15 22:44:02600void Compositor::Draw() {
[email protected]337bd042012-11-05 23:43:43601 DCHECK(!g_compositor_thread);
602
[email protected]ed8de92d2011-09-14 04:16:48603 if (!root_layer_)
604 return;
605
[email protected]d4ae80572012-06-06 23:02:06606 last_started_frame_++;
[email protected]337bd042012-11-05 23:43:43607 PendingSwap pending_swap(DRAW_SWAP, posted_swaps_.get());
608 if (!IsLocked()) {
[email protected]6b16679e2012-10-27 00:44:28609 // TODO(nduca): Temporary while compositor calls
610 // compositeImmediately() directly.
[email protected]408b5e22013-03-19 09:48:09611 Layout();
[email protected]f0c2a242013-03-15 19:34:52612 host_->Composite(base::TimeTicks::Now());
[email protected]8d9080ab2013-04-06 00:03:20613
614#if defined(OS_WIN)
615 // While we resize, we are usually a few frames behind. By blocking
616 // the UI thread here we minize the area that is mis-painted, specially
617 // in the non-client area. See RenderWidgetHostViewAura::SetBounds for
618 // more details and bug 177115.
619 if (next_draw_is_resize_ && (last_ended_frame_ > 1)) {
620 next_draw_is_resize_ = false;
621 host_->FinishAllRendering();
622 }
623#endif
624
[email protected]6b16679e2012-10-27 00:44:28625 }
[email protected]337bd042012-11-05 23:43:43626 if (!pending_swap.posted())
[email protected]1920930592012-01-11 14:54:48627 NotifyEnd();
[email protected]ab6627372012-01-29 21:22:13628}
629
[email protected]878705be2013-04-15 22:44:02630void Compositor::ScheduleFullRedraw() {
[email protected]804c8982013-03-13 16:32:21631 host_->SetNeedsRedraw();
[email protected]7df588fbd2012-02-10 14:15:56632}
633
[email protected]878705be2013-04-15 22:44:02634void Compositor::ScheduleRedrawRect(const gfx::Rect& damage_rect) {
635 host_->SetNeedsRedrawRect(damage_rect);
636}
637
[email protected]66239a22013-06-05 03:38:26638void Compositor::SetLatencyInfo(const ui::LatencyInfo& latency_info) {
639 host_->SetLatencyInfo(latency_info);
640}
641
[email protected]cd9a61c72012-05-08 19:16:59642bool Compositor::ReadPixels(SkBitmap* bitmap,
643 const gfx::Rect& bounds_in_pixel) {
644 if (bounds_in_pixel.right() > size().width() ||
645 bounds_in_pixel.bottom() > size().height())
[email protected]ab6627372012-01-29 21:22:13646 return false;
[email protected]ab6627372012-01-29 21:22:13647 bitmap->setConfig(SkBitmap::kARGB_8888_Config,
[email protected]cd9a61c72012-05-08 19:16:59648 bounds_in_pixel.width(), bounds_in_pixel.height());
[email protected]ab6627372012-01-29 21:22:13649 bitmap->allocPixels();
650 SkAutoLockPixels lock_image(*bitmap);
651 unsigned char* pixels = static_cast<unsigned char*>(bitmap->getPixels());
[email protected]6b16679e2012-10-27 00:44:28652 CancelCompositorLock();
[email protected]337bd042012-11-05 23:43:43653 PendingSwap pending_swap(READPIXELS_SWAP, posted_swaps_.get());
[email protected]804c8982013-03-13 16:32:21654 return host_->CompositeAndReadback(pixels, bounds_in_pixel);
[email protected]ab6627372012-01-29 21:22:13655}
656
[email protected]cd9a61c72012-05-08 19:16:59657void Compositor::SetScaleAndSize(float scale, const gfx::Size& size_in_pixel) {
[email protected]cff176a2012-06-29 21:11:00658 DCHECK_GT(scale, 0);
[email protected]351b8ce2012-11-27 23:37:16659 if (!size_in_pixel.IsEmpty()) {
660 size_ = size_in_pixel;
[email protected]18ce59702013-04-09 04:58:40661 host_->SetViewportSize(size_in_pixel);
[email protected]7aba6662013-03-12 10:17:34662 root_web_layer_->SetBounds(size_in_pixel);
[email protected]8d9080ab2013-04-06 00:03:20663
664 next_draw_is_resize_ = true;
[email protected]351b8ce2012-11-27 23:37:16665 }
[email protected]2e2216e42012-05-17 15:17:00666 if (device_scale_factor_ != scale) {
[email protected]cd9a61c72012-05-08 19:16:59667 device_scale_factor_ = scale;
668 if (root_layer_)
669 root_layer_->OnDeviceScaleFactorChanged(scale);
670 }
[email protected]ed8de92d2011-09-14 04:16:48671}
672
[email protected]87601922013-04-02 03:56:42673void Compositor::SetBackgroundColor(SkColor color) {
674 host_->set_background_color(color);
675 ScheduleDraw();
676}
677
[email protected]ed8de92d2011-09-14 04:16:48678void Compositor::AddObserver(CompositorObserver* observer) {
679 observer_list_.AddObserver(observer);
680}
681
682void Compositor::RemoveObserver(CompositorObserver* observer) {
683 observer_list_.RemoveObserver(observer);
684}
685
[email protected]3ce2feb2011-09-19 18:44:23686bool Compositor::HasObserver(CompositorObserver* observer) {
687 return observer_list_.HasObserver(observer);
688}
689
[email protected]894e8fc2012-02-24 13:29:50690void Compositor::OnSwapBuffersPosted() {
[email protected]337bd042012-11-05 23:43:43691 DCHECK(!g_compositor_thread);
692 posted_swaps_->PostSwap();
[email protected]894e8fc2012-02-24 13:29:50693}
694
695void Compositor::OnSwapBuffersComplete() {
[email protected]337bd042012-11-05 23:43:43696 DCHECK(!g_compositor_thread);
697 DCHECK(posted_swaps_->AreSwapsPosted());
698 DCHECK_GE(1, posted_swaps_->NumSwapsPosted(DRAW_SWAP));
699 if (posted_swaps_->NextPostedSwap() == DRAW_SWAP)
700 NotifyEnd();
701 posted_swaps_->EndSwap();
[email protected]894e8fc2012-02-24 13:29:50702}
703
704void Compositor::OnSwapBuffersAborted() {
[email protected]f79729062013-04-03 20:01:50705 if (!g_compositor_thread) {
706 DCHECK_GE(1, posted_swaps_->NumSwapsPosted(DRAW_SWAP));
[email protected]337bd042012-11-05 23:43:43707
[email protected]f79729062013-04-03 20:01:50708 // We've just lost the context, so unwind all posted_swaps.
709 while (posted_swaps_->AreSwapsPosted()) {
710 if (posted_swaps_->NextPostedSwap() == DRAW_SWAP)
711 NotifyEnd();
712 posted_swaps_->EndSwap();
713 }
[email protected]d912f8c2012-11-03 02:35:01714 }
[email protected]337bd042012-11-05 23:43:43715
[email protected]91f4c792012-06-06 02:21:19716 FOR_EACH_OBSERVER(CompositorObserver,
717 observer_list_,
718 OnCompositingAborted(this));
[email protected]894e8fc2012-02-24 13:29:50719}
[email protected]ab6627372012-01-29 21:22:13720
[email protected]3b6085512013-02-21 01:26:20721void Compositor::OnUpdateVSyncParameters(base::TimeTicks timebase,
722 base::TimeDelta interval) {
723 FOR_EACH_OBSERVER(CompositorObserver,
724 observer_list_,
725 OnUpdateVSyncParameters(this, timebase, interval));
726}
727
[email protected]408b5e22013-03-19 09:48:09728void Compositor::Layout() {
[email protected]d4ae80572012-06-06 23:02:06729 // We're sending damage that will be addressed during this composite
730 // cycle, so we don't need to schedule another composite to address it.
731 disable_schedule_composite_ = true;
[email protected]f78649ea2012-02-23 18:39:04732 if (root_layer_)
[email protected]cedc3952012-03-06 06:15:55733 root_layer_->SendDamagedRects();
[email protected]d4ae80572012-06-06 23:02:06734 disable_schedule_composite_ = false;
[email protected]ab6627372012-01-29 21:22:13735}
736
[email protected]408b5e22013-03-19 09:48:09737scoped_ptr<cc::OutputSurface> Compositor::CreateOutputSurface() {
[email protected]40034cf2013-03-13 05:05:37738 return make_scoped_ptr(
739 ContextFactory::GetInstance()->CreateOutputSurface(this));
[email protected]ab6627372012-01-29 21:22:13740}
741
[email protected]408b5e22013-03-19 09:48:09742void Compositor::DidCommit() {
[email protected]6b16679e2012-10-27 00:44:28743 DCHECK(!IsLocked());
[email protected]2700daddd2012-07-13 19:35:37744 FOR_EACH_OBSERVER(CompositorObserver,
745 observer_list_,
746 OnCompositingDidCommit(this));
747}
748
[email protected]408b5e22013-03-19 09:48:09749void Compositor::DidCommitAndDrawFrame() {
[email protected]3b6085512013-02-21 01:26:20750 base::TimeTicks start_time = base::TimeTicks::Now();
[email protected]a8f677c2012-03-23 01:36:06751 FOR_EACH_OBSERVER(CompositorObserver,
752 observer_list_,
[email protected]3b6085512013-02-21 01:26:20753 OnCompositingStarted(this, start_time));
[email protected]ba7aeb82012-02-24 23:36:13754}
755
[email protected]408b5e22013-03-19 09:48:09756void Compositor::DidCompleteSwapBuffers() {
[email protected]337bd042012-11-05 23:43:43757 DCHECK(g_compositor_thread);
[email protected]ba7aeb82012-02-24 23:36:13758 NotifyEnd();
[email protected]ab6627372012-01-29 21:22:13759}
760
[email protected]408b5e22013-03-19 09:48:09761void Compositor::ScheduleComposite() {
[email protected]d4ae80572012-06-06 23:02:06762 if (!disable_schedule_composite_)
763 ScheduleDraw();
[email protected]332749032011-10-22 00:32:46764}
765
[email protected]0a451722013-02-22 20:32:05766scoped_refptr<cc::ContextProvider>
767Compositor::OffscreenContextProviderForMainThread() {
[email protected]0a451722013-02-22 20:32:05768 return ContextFactory::GetInstance()->OffscreenContextProviderForMainThread();
769}
770
771scoped_refptr<cc::ContextProvider>
772Compositor::OffscreenContextProviderForCompositorThread() {
[email protected]0a451722013-02-22 20:32:05773 return ContextFactory::GetInstance()->
774 OffscreenContextProviderForCompositorThread();
775}
776
[email protected]2e77cdbb2013-04-29 13:59:14777const cc::LayerTreeDebugState& Compositor::GetLayerTreeDebugState() const {
778 return host_->debug_state();
[email protected]918f8db42013-04-27 01:53:40779}
780
[email protected]2e77cdbb2013-04-29 13:59:14781void Compositor::SetLayerTreeDebugState(
782 const cc::LayerTreeDebugState& debug_state) {
[email protected]918f8db42013-04-27 01:53:40783 host_->SetDebugState(debug_state);
784}
785
[email protected]6b16679e2012-10-27 00:44:28786scoped_refptr<CompositorLock> Compositor::GetCompositorLock() {
787 if (!compositor_lock_) {
788 compositor_lock_ = new CompositorLock(this);
789 if (g_compositor_thread)
[email protected]804c8982013-03-13 16:32:21790 host_->SetDeferCommits(true);
[email protected]6b16679e2012-10-27 00:44:28791 FOR_EACH_OBSERVER(CompositorObserver,
792 observer_list_,
793 OnCompositingLockStateChanged(this));
794 }
795 return compositor_lock_;
796}
797
798void Compositor::UnlockCompositor() {
799 DCHECK(compositor_lock_);
800 compositor_lock_ = NULL;
801 if (g_compositor_thread)
[email protected]804c8982013-03-13 16:32:21802 host_->SetDeferCommits(false);
[email protected]6b16679e2012-10-27 00:44:28803 FOR_EACH_OBSERVER(CompositorObserver,
804 observer_list_,
805 OnCompositingLockStateChanged(this));
806}
807
808void Compositor::CancelCompositorLock() {
809 if (compositor_lock_)
810 compositor_lock_->CancelLock();
811}
812
[email protected]a8f21152011-09-08 15:30:02813void Compositor::NotifyEnd() {
[email protected]d4ae80572012-06-06 23:02:06814 last_ended_frame_++;
[email protected]a8f21152011-09-08 15:30:02815 FOR_EACH_OBSERVER(CompositorObserver,
816 observer_list_,
[email protected]3ce2feb2011-09-19 18:44:23817 OnCompositingEnded(this));
[email protected]a8f21152011-09-08 15:30:02818}
819
[email protected]ab6627372012-01-29 21:22:13820COMPOSITOR_EXPORT void SetupTestCompositor() {
821 if (!CommandLine::ForCurrentProcess()->HasSwitch(
822 switches::kDisableTestCompositor)) {
[email protected]8cbffc62013-01-23 22:11:09823 g_test_compositor_enabled = true;
[email protected]ab6627372012-01-29 21:22:13824 }
[email protected]8391a49e2012-05-26 06:31:04825#if defined(OS_CHROMEOS)
826 // If the test is running on the chromeos envrionment (such as
827 // device or vm bots), use the real compositor.
828 if (base::chromeos::IsRunningOnChromeOS())
[email protected]8cbffc62013-01-23 22:11:09829 g_test_compositor_enabled = false;
[email protected]8391a49e2012-05-26 06:31:04830#endif
[email protected]40034cf2013-03-13 05:05:37831 ResetImplicitFactory();
[email protected]ab6627372012-01-29 21:22:13832}
833
834COMPOSITOR_EXPORT void DisableTestCompositor() {
[email protected]40034cf2013-03-13 05:05:37835 ResetImplicitFactory();
[email protected]8cbffc62013-01-23 22:11:09836 g_test_compositor_enabled = false;
[email protected]1920930592012-01-11 14:54:48837}
838
[email protected]894e8fc2012-02-24 13:29:50839COMPOSITOR_EXPORT bool IsTestCompositorEnabled() {
[email protected]8cbffc62013-01-23 22:11:09840 return g_test_compositor_enabled;
[email protected]894e8fc2012-02-24 13:29:50841}
842
[email protected]c797cd42011-03-15 02:18:36843} // namespace ui