blob: 56b5eb4d9629f3efb3e452475cf08bc1902c5b69 [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]1e7565a2013-04-08 20:11:1411#include "base/cancelable_callback.h"
[email protected]ab6627372012-01-29 21:22:1312#include "base/command_line.h"
[email protected]0a451722013-02-22 20:32:0513#include "base/memory/singleton.h"
[email protected]6b16679e2012-10-27 00:44:2814#include "base/message_loop.h"
[email protected]1e7565a2013-04-08 20:11:1415#include "base/run_loop.h"
[email protected]06666c02013-03-07 19:32:3016#include "base/string_util.h"
[email protected]ec05af52012-11-21 23:07:0017#include "base/threading/thread.h"
[email protected]894e8fc2012-02-24 13:29:5018#include "base/threading/thread_restrictions.h"
[email protected]4d5e6762013-03-19 18:46:5719#include "cc/base/switches.h"
[email protected]681ccff2013-03-18 06:13:5220#include "cc/base/thread_impl.h"
[email protected]3052b10f2013-03-18 07:41:2121#include "cc/input/input_handler.h"
[email protected]cc3cfaa2013-03-18 09:05:5222#include "cc/layers/layer.h"
[email protected]7f0d825f2013-03-18 07:24:3023#include "cc/output/context_provider.h"
24#include "cc/output/output_surface.h"
[email protected]556fd292013-03-18 08:03:0425#include "cc/trees/layer_tree_host.h"
[email protected]83afcbcc2012-07-27 03:06:2726#include "third_party/skia/include/core/SkBitmap.h"
[email protected]116302fc2012-05-05 21:45:4127#include "ui/compositor/compositor_observer.h"
28#include "ui/compositor/compositor_switches.h"
[email protected]cd9a61c72012-05-08 19:16:5929#include "ui/compositor/dip_util.h"
[email protected]116302fc2012-05-05 21:45:4130#include "ui/compositor/layer.h"
31#include "ui/compositor/test_web_graphics_context_3d.h"
[email protected]c9e2cbbb2012-05-12 21:17:2732#include "ui/gl/gl_context.h"
33#include "ui/gl/gl_implementation.h"
34#include "ui/gl/gl_surface.h"
[email protected]cc2ae012012-09-21 19:35:2535#include "ui/gl/gl_switches.h"
[email protected]0a451722013-02-22 20:32:0536#include "webkit/gpu/grcontext_for_webgraphicscontext3d.h"
[email protected]ab6627372012-01-29 21:22:1337#include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"
38
[email protected]8391a49e2012-05-26 06:31:0439#if defined(OS_CHROMEOS)
40#include "base/chromeos/chromeos_version.h"
41#endif
42
[email protected]ab6627372012-01-29 21:22:1343namespace {
44
45const double kDefaultRefreshRate = 60.0;
[email protected]7ddeaab2013-04-06 00:47:0546const double kTestRefreshRate = 200.0;
[email protected]ab6627372012-01-29 21:22:1347
[email protected]337bd042012-11-05 23:43:4348enum SwapType {
49 DRAW_SWAP,
50 READPIXELS_SWAP,
51};
52
[email protected]ec05af52012-11-21 23:07:0053base::Thread* g_compositor_thread = NULL;
[email protected]ab6627372012-01-29 21:22:1354
[email protected]8cbffc62013-01-23 22:11:0955bool g_test_compositor_enabled = false;
[email protected]ab6627372012-01-29 21:22:1356
[email protected]40034cf2013-03-13 05:05:3757ui::ContextFactory* g_implicit_factory = NULL;
[email protected]894e8fc2012-02-24 13:29:5058ui::ContextFactory* g_context_factory = NULL;
59
[email protected]6b16679e2012-10-27 00:44:2860const int kCompositorLockTimeoutMs = 67;
61
[email protected]337bd042012-11-05 23:43:4362class PendingSwap {
63 public:
64 PendingSwap(SwapType type, ui::PostedSwapQueue* posted_swaps);
65 ~PendingSwap();
66
67 SwapType type() const { return type_; }
68 bool posted() const { return posted_; }
69
70 private:
71 friend class ui::PostedSwapQueue;
72
73 SwapType type_;
74 bool posted_;
75 ui::PostedSwapQueue* posted_swaps_;
76
77 DISALLOW_COPY_AND_ASSIGN(PendingSwap);
78};
79
[email protected]40034cf2013-03-13 05:05:3780void 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();
[email protected]0a451722013-02-22 20:32:0593 }
[email protected]40034cf2013-03-13 05:05:3794 g_context_factory = g_implicit_factory;
95}
[email protected]0a451722013-02-22 20:32:0596
[email protected]40034cf2013-03-13 05:05:3797void 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}
[email protected]0a451722013-02-22 20:32:05104
[email protected]83afcbcc2012-07-27 03:06:27105} // namespace
[email protected]c797cd42011-03-15 02:18:36106
107namespace ui {
108
[email protected]894e8fc2012-02-24 13:29:50109// static
110ContextFactory* ContextFactory::GetInstance() {
[email protected]40034cf2013-03-13 05:05:37111 if (!g_context_factory)
112 SetupImplicitFactory();
[email protected]894e8fc2012-02-24 13:29:50113 return g_context_factory;
[email protected]ca806632012-02-16 02:15:59114}
115
[email protected]58b4b6d2012-02-16 01:40:24116// static
[email protected]894e8fc2012-02-24 13:29:50117void ContextFactory::SetInstance(ContextFactory* instance) {
118 g_context_factory = instance;
[email protected]ca806632012-02-16 02:15:59119}
120
[email protected]40034cf2013-03-13 05:05:37121class ContextProviderFromContextFactory : public cc::ContextProvider {
[email protected]0a451722013-02-22 20:32:05122 public:
[email protected]e06e1122013-03-15 17:12:38123 static scoped_refptr<ContextProviderFromContextFactory> Create(
124 ContextFactory* factory) {
125 scoped_refptr<ContextProviderFromContextFactory> provider =
126 new ContextProviderFromContextFactory(factory);
127 if (!provider->InitializeOnMainThread())
128 return NULL;
129 return provider;
[email protected]0a451722013-02-22 20:32:05130 }
131
[email protected]aa3174b2013-03-15 09:12:48132 virtual bool BindToCurrentThread() OVERRIDE {
[email protected]e06e1122013-03-15 17:12:38133 DCHECK(context3d_);
134
[email protected]0a451722013-02-22 20:32:05135 return context3d_->makeContextCurrent();
136 }
137
[email protected]aa3174b2013-03-15 09:12:48138 virtual WebKit::WebGraphicsContext3D* Context3d() OVERRIDE {
[email protected]e06e1122013-03-15 17:12:38139 DCHECK(context3d_);
140
[email protected]aa3174b2013-03-15 09:12:48141 return context3d_.get();
142 }
[email protected]0a451722013-02-22 20:32:05143
[email protected]aa3174b2013-03-15 09:12:48144 virtual class GrContext* GrContext() OVERRIDE {
[email protected]e06e1122013-03-15 17:12:38145 DCHECK(context3d_);
146
[email protected]0a451722013-02-22 20:32:05147 if (!gr_context_) {
148 gr_context_.reset(
149 new webkit::gpu::GrContextForWebGraphicsContext3D(context3d_.get()));
150 }
151 return gr_context_->get();
152 }
153
154 virtual void VerifyContexts() OVERRIDE {
[email protected]e06e1122013-03-15 17:12:38155 DCHECK(context3d_);
156
157 if (context3d_->isContextLost()) {
158 base::AutoLock lock(destroyed_lock_);
159 destroyed_ = true;
160 }
[email protected]0a451722013-02-22 20:32:05161 }
162
[email protected]aa3174b2013-03-15 09:12:48163 virtual bool DestroyedOnMainThread() OVERRIDE {
[email protected]0a451722013-02-22 20:32:05164 base::AutoLock lock(destroyed_lock_);
165 return destroyed_;
166 }
167
168 protected:
[email protected]e06e1122013-03-15 17:12:38169 explicit ContextProviderFromContextFactory(ContextFactory* factory)
170 : factory_(factory),
171 destroyed_(false) {}
[email protected]40034cf2013-03-13 05:05:37172 virtual ~ContextProviderFromContextFactory() {}
[email protected]0a451722013-02-22 20:32:05173
[email protected]e06e1122013-03-15 17:12:38174 bool InitializeOnMainThread() {
175 if (context3d_)
176 return true;
177 context3d_.reset(factory_->CreateOffscreenContext());
178 return !!context3d_;
179 }
180
[email protected]0a451722013-02-22 20:32:05181 private:
182 ContextFactory* factory_;
183 base::Lock destroyed_lock_;
184 bool destroyed_;
185 scoped_ptr<WebKit::WebGraphicsContext3D> context3d_;
186 scoped_ptr<webkit::gpu::GrContextForWebGraphicsContext3D> gr_context_;
187};
188
[email protected]40034cf2013-03-13 05:05:37189DefaultContextFactory::DefaultContextFactory() {
190}
191
192DefaultContextFactory::~DefaultContextFactory() {
193}
194
195bool DefaultContextFactory::Initialize() {
196 if (!gfx::GLSurface::InitializeOneOff() ||
197 gfx::GetGLImplementation() == gfx::kGLImplementationNone) {
198 LOG(ERROR) << "Could not load the GL bindings";
199 return false;
200 }
201 return true;
202}
203
204cc::OutputSurface* DefaultContextFactory::CreateOutputSurface(
205 Compositor* compositor) {
206 return new cc::OutputSurface(
207 make_scoped_ptr(CreateContextCommon(compositor, false)));
208}
209
210WebKit::WebGraphicsContext3D* DefaultContextFactory::CreateOffscreenContext() {
211 return CreateContextCommon(NULL, true);
212}
213
[email protected]0a451722013-02-22 20:32:05214scoped_refptr<cc::ContextProvider>
215DefaultContextFactory::OffscreenContextProviderForMainThread() {
216 if (!offscreen_contexts_main_thread_ ||
217 !offscreen_contexts_main_thread_->DestroyedOnMainThread()) {
[email protected]40034cf2013-03-13 05:05:37218 offscreen_contexts_main_thread_ =
[email protected]e06e1122013-03-15 17:12:38219 ContextProviderFromContextFactory::Create(this);
220 if (offscreen_contexts_main_thread_ &&
221 !offscreen_contexts_main_thread_->BindToCurrentThread())
222 offscreen_contexts_main_thread_ = NULL;
[email protected]0a451722013-02-22 20:32:05223 }
224 return offscreen_contexts_main_thread_;
225}
226
227scoped_refptr<cc::ContextProvider>
228DefaultContextFactory::OffscreenContextProviderForCompositorThread() {
229 if (!offscreen_contexts_compositor_thread_ ||
230 !offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) {
[email protected]40034cf2013-03-13 05:05:37231 offscreen_contexts_compositor_thread_ =
[email protected]e06e1122013-03-15 17:12:38232 ContextProviderFromContextFactory::Create(this);
[email protected]0a451722013-02-22 20:32:05233 }
234 return offscreen_contexts_compositor_thread_;
235}
236
[email protected]84dba8ca2012-04-10 03:27:39237void DefaultContextFactory::RemoveCompositor(Compositor* compositor) {
238}
239
240WebKit::WebGraphicsContext3D* DefaultContextFactory::CreateContextCommon(
241 Compositor* compositor,
242 bool offscreen) {
[email protected]b18ed0aa2012-08-22 04:20:20243 DCHECK(offscreen || compositor);
[email protected]894e8fc2012-02-24 13:29:50244 WebKit::WebGraphicsContext3D::Attributes attrs;
[email protected]b63dce52012-08-22 22:51:50245 attrs.depth = false;
246 attrs.stencil = false;
247 attrs.antialias = false;
[email protected]894e8fc2012-02-24 13:29:50248 attrs.shareResources = true;
249 WebKit::WebGraphicsContext3D* context =
[email protected]84dba8ca2012-04-10 03:27:39250 offscreen ?
251 webkit::gpu::WebGraphicsContext3DInProcessImpl::CreateForWebView(
252 attrs, false) :
[email protected]894e8fc2012-02-24 13:29:50253 webkit::gpu::WebGraphicsContext3DInProcessImpl::CreateForWindow(
[email protected]40034cf2013-03-13 05:05:37254 attrs, compositor->widget(), NULL);
[email protected]69b8e8f2012-06-18 02:42:59255 if (!context)
256 return NULL;
257
[email protected]894e8fc2012-02-24 13:29:50258 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]8fcaffb2012-05-25 23:19:00259 if (!offscreen) {
[email protected]894e8fc2012-02-24 13:29:50260 context->makeContextCurrent();
261 gfx::GLContext* gl_context = gfx::GLContext::GetCurrent();
[email protected]cc2ae012012-09-21 19:35:25262 bool vsync = !command_line->HasSwitch(switches::kDisableGpuVsync);
[email protected]8fcaffb2012-05-25 23:19:00263 gl_context->SetSwapInterval(vsync ? 1 : 0);
[email protected]894e8fc2012-02-24 13:29:50264 gl_context->ReleaseCurrent(NULL);
265 }
266 return context;
[email protected]ab6627372012-01-29 21:22:13267}
268
[email protected]e06e1122013-03-15 17:12:38269TestContextFactory::TestContextFactory() {}
[email protected]40034cf2013-03-13 05:05:37270
[email protected]e06e1122013-03-15 17:12:38271TestContextFactory::~TestContextFactory() {}
[email protected]40034cf2013-03-13 05:05:37272
273cc::OutputSurface* TestContextFactory::CreateOutputSurface(
274 Compositor* compositor) {
275 return new cc::OutputSurface(make_scoped_ptr(CreateOffscreenContext()));
276}
277
278WebKit::WebGraphicsContext3D* TestContextFactory::CreateOffscreenContext() {
279 ui::TestWebGraphicsContext3D* context = new ui::TestWebGraphicsContext3D;
280 context->Initialize();
281 return context;
282}
283
284scoped_refptr<cc::ContextProvider>
285TestContextFactory::OffscreenContextProviderForMainThread() {
[email protected]e06e1122013-03-15 17:12:38286 if (!offscreen_contexts_main_thread_ ||
287 offscreen_contexts_main_thread_->DestroyedOnMainThread()) {
288 offscreen_contexts_main_thread_ =
289 ContextProviderFromContextFactory::Create(this);
290 CHECK(offscreen_contexts_main_thread_->BindToCurrentThread());
291 }
[email protected]40034cf2013-03-13 05:05:37292 return offscreen_contexts_main_thread_;
293}
294
295scoped_refptr<cc::ContextProvider>
296TestContextFactory::OffscreenContextProviderForCompositorThread() {
[email protected]e06e1122013-03-15 17:12:38297 if (!offscreen_contexts_compositor_thread_ ||
298 offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) {
299 offscreen_contexts_compositor_thread_ =
300 ContextProviderFromContextFactory::Create(this);
301 }
[email protected]40034cf2013-03-13 05:05:37302 return offscreen_contexts_compositor_thread_;
303}
304
305void TestContextFactory::RemoveCompositor(Compositor* compositor) {
306}
307
[email protected]d3407cdb2012-09-21 22:33:25308Texture::Texture(bool flipped, const gfx::Size& size, float device_scale_factor)
[email protected]34466d02012-12-10 18:00:34309 : size_(size),
310 flipped_(flipped),
[email protected]d3407cdb2012-09-21 22:33:25311 device_scale_factor_(device_scale_factor) {
[email protected]ab6627372012-01-29 21:22:13312}
313
314Texture::~Texture() {
315}
316
[email protected]06666c02013-03-07 19:32:30317std::string Texture::Produce() {
318 return EmptyString();
[email protected]f027ca1502012-12-21 01:42:32319}
320
[email protected]6b16679e2012-10-27 00:44:28321CompositorLock::CompositorLock(Compositor* compositor)
322 : compositor_(compositor) {
323 MessageLoop::current()->PostDelayedTask(
324 FROM_HERE,
325 base::Bind(&CompositorLock::CancelLock, AsWeakPtr()),
326 base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs));
327}
328
329CompositorLock::~CompositorLock() {
330 CancelLock();
331}
332
333void CompositorLock::CancelLock() {
334 if (!compositor_)
335 return;
336 compositor_->UnlockCompositor();
337 compositor_ = NULL;
338}
339
[email protected]1e7565a2013-04-08 20:11:14340// static
341bool DrawWaiterForTest::Wait(Compositor* compositor) {
342 DrawWaiterForTest waiter;
343 return waiter.WaitImpl(compositor);
344}
345
346DrawWaiterForTest::DrawWaiterForTest()
347 : kDrawWaitTimeOutMs(1000),
348 did_draw_(false) {
349}
350
351DrawWaiterForTest::~DrawWaiterForTest() {
352}
353
354bool DrawWaiterForTest::WaitImpl(Compositor* compositor) {
355 did_draw_ = false;
356 compositor->AddObserver(this);
357 wait_run_loop_.reset(new base::RunLoop());
358 base::CancelableClosure timeout(
359 base::Bind(&DrawWaiterForTest::TimedOutWhileWaiting,
360 base::Unretained(this)));
361 MessageLoop::current()->PostDelayedTask(
362 FROM_HERE, timeout.callback(),
363 base::TimeDelta::FromMilliseconds(kDrawWaitTimeOutMs));
364 wait_run_loop_->Run();
365 compositor->RemoveObserver(this);
366 return did_draw_;
367}
368
369void DrawWaiterForTest::TimedOutWhileWaiting() {
370 LOG(ERROR) << "Timed out waiting for draw.";
371 wait_run_loop_->Quit();
372}
373
374void DrawWaiterForTest::OnCompositingDidCommit(Compositor* compositor) {
375}
376
377void DrawWaiterForTest::OnCompositingStarted(Compositor* compositor,
378 base::TimeTicks start_time) {
379}
380
381void DrawWaiterForTest::OnCompositingEnded(Compositor* compositor) {
382 did_draw_ = true;
383 wait_run_loop_->Quit();
384}
385
386void DrawWaiterForTest::OnCompositingAborted(Compositor* compositor) {
387}
388
389void DrawWaiterForTest::OnCompositingLockStateChanged(Compositor* compositor) {
390}
391
392void DrawWaiterForTest::OnUpdateVSyncParameters(Compositor* compositor,
393 base::TimeTicks timebase,
394 base::TimeDelta interval) {
395}
396
[email protected]337bd042012-11-05 23:43:43397class PostedSwapQueue {
398 public:
399 PostedSwapQueue() : pending_swap_(NULL) {
400 }
401
402 ~PostedSwapQueue() {
403 DCHECK(!pending_swap_);
404 }
405
406 SwapType NextPostedSwap() const {
407 return queue_.front();
408 }
409
410 bool AreSwapsPosted() const {
411 return !queue_.empty();
412 }
413
414 int NumSwapsPosted(SwapType type) const {
415 int count = 0;
416 for (std::deque<SwapType>::const_iterator it = queue_.begin();
417 it != queue_.end(); ++it) {
418 if (*it == type)
419 count++;
420 }
421 return count;
422 }
423
424 void PostSwap() {
425 DCHECK(pending_swap_);
426 queue_.push_back(pending_swap_->type());
427 pending_swap_->posted_ = true;
428 }
429
430 void EndSwap() {
431 queue_.pop_front();
432 }
433
434 private:
435 friend class ::PendingSwap;
436
437 PendingSwap* pending_swap_;
438 std::deque<SwapType> queue_;
439
440 DISALLOW_COPY_AND_ASSIGN(PostedSwapQueue);
441};
442
443} // namespace ui
444
445namespace {
446
447PendingSwap::PendingSwap(SwapType type, ui::PostedSwapQueue* posted_swaps)
448 : type_(type), posted_(false), posted_swaps_(posted_swaps) {
449 // Only one pending swap in flight.
450 DCHECK_EQ(static_cast<PendingSwap*>(NULL), posted_swaps_->pending_swap_);
451 posted_swaps_->pending_swap_ = this;
452}
453
454PendingSwap::~PendingSwap() {
455 DCHECK_EQ(this, posted_swaps_->pending_swap_);
456 posted_swaps_->pending_swap_ = NULL;
457}
458
459} // namespace
460
461namespace ui {
462
[email protected]ab6627372012-01-29 21:22:13463Compositor::Compositor(CompositorDelegate* delegate,
[email protected]cd9a61c72012-05-08 19:16:59464 gfx::AcceleratedWidget widget)
[email protected]82a01ac2011-09-08 16:00:18465 : delegate_(delegate),
[email protected]ab6627372012-01-29 21:22:13466 root_layer_(NULL),
467 widget_(widget),
[email protected]337bd042012-11-05 23:43:43468 posted_swaps_(new PostedSwapQueue()),
[email protected]d4ae80572012-06-06 23:02:06469 device_scale_factor_(0.0f),
470 last_started_frame_(0),
471 last_ended_frame_(0),
[email protected]8d9080ab2013-04-06 00:03:20472 next_draw_is_resize_(false),
[email protected]6b16679e2012-10-27 00:44:28473 disable_schedule_composite_(false),
474 compositor_lock_(NULL) {
[email protected]7aba6662013-03-12 10:17:34475 root_web_layer_ = cc::Layer::Create();
476 root_web_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f));
[email protected]ec05af52012-11-21 23:07:00477
[email protected]ab6627372012-01-29 21:22:13478 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]4d5e6762013-03-19 18:46:57479
[email protected]ec05af52012-11-21 23:07:00480 cc::LayerTreeSettings settings;
[email protected]8e0176d2013-03-21 03:14:52481 settings.refresh_rate =
[email protected]8cbffc62013-01-23 22:11:09482 g_test_compositor_enabled ? kTestRefreshRate : kDefaultRefreshRate;
[email protected]8e0176d2013-03-21 03:14:52483 settings.partial_swap_enabled =
[email protected]4d5e6762013-03-19 18:46:57484 command_line->HasSwitch(cc::switches::kUIEnablePartialSwap);
[email protected]8e0176d2013-03-21 03:14:52485 settings.per_tile_painting_enabled =
[email protected]4d5e6762013-03-19 18:46:57486 command_line->HasSwitch(cc::switches::kUIEnablePerTilePainting);
487
488 // These flags should be mirrored by renderer versions in content/renderer/.
[email protected]8e0176d2013-03-21 03:14:52489 settings.initial_debug_state.show_debug_borders =
[email protected]4d5e6762013-03-19 18:46:57490 command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders);
[email protected]8e0176d2013-03-21 03:14:52491 settings.initial_debug_state.show_fps_counter =
[email protected]4d5e6762013-03-19 18:46:57492 command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
[email protected]8e0176d2013-03-21 03:14:52493 settings.initial_debug_state.show_paint_rects =
[email protected]4d5e6762013-03-19 18:46:57494 command_line->HasSwitch(switches::kUIShowPaintRects);
[email protected]8e0176d2013-03-21 03:14:52495 settings.initial_debug_state.show_platform_layer_tree =
[email protected]4d5e6762013-03-19 18:46:57496 command_line->HasSwitch(cc::switches::kUIShowCompositedLayerTree);
[email protected]8e0176d2013-03-21 03:14:52497 settings.initial_debug_state.show_property_changed_rects =
[email protected]4d5e6762013-03-19 18:46:57498 command_line->HasSwitch(cc::switches::kUIShowPropertyChangedRects);
[email protected]8e0176d2013-03-21 03:14:52499 settings.initial_debug_state.show_surface_damage_rects =
[email protected]4d5e6762013-03-19 18:46:57500 command_line->HasSwitch(cc::switches::kUIShowSurfaceDamageRects);
[email protected]8e0176d2013-03-21 03:14:52501 settings.initial_debug_state.show_screen_space_rects =
[email protected]4d5e6762013-03-19 18:46:57502 command_line->HasSwitch(cc::switches::kUIShowScreenSpaceRects);
[email protected]8e0176d2013-03-21 03:14:52503 settings.initial_debug_state.show_replica_screen_space_rects =
[email protected]4d5e6762013-03-19 18:46:57504 command_line->HasSwitch(cc::switches::kUIShowReplicaScreenSpaceRects);
[email protected]8e0176d2013-03-21 03:14:52505 settings.initial_debug_state.show_occluding_rects =
[email protected]4d5e6762013-03-19 18:46:57506 command_line->HasSwitch(cc::switches::kUIShowOccludingRects);
[email protected]8e0176d2013-03-21 03:14:52507 settings.initial_debug_state.show_non_occluding_rects =
[email protected]4d5e6762013-03-19 18:46:57508 command_line->HasSwitch(cc::switches::kUIShowNonOccludingRects);
[email protected]302fe422012-06-11 14:49:11509
[email protected]ec05af52012-11-21 23:07:00510 scoped_ptr<cc::Thread> thread;
511 if (g_compositor_thread) {
[email protected]a5069b572013-03-17 21:50:42512 thread = cc::ThreadImpl::CreateForDifferentThread(
[email protected]ec05af52012-11-21 23:07:00513 g_compositor_thread->message_loop_proxy());
514 }
515
[email protected]804c8982013-03-13 16:32:21516 host_ = cc::LayerTreeHost::Create(this, settings, thread.Pass());
517 host_->SetRootLayer(root_web_layer_);
518 host_->SetSurfaceReady();
[email protected]82a01ac2011-09-08 16:00:18519}
520
521Compositor::~Compositor() {
[email protected]6b16679e2012-10-27 00:44:28522 CancelCompositorLock();
523 DCHECK(!compositor_lock_);
524
[email protected]e332a1b2012-05-10 20:32:27525 // Don't call |CompositorDelegate::ScheduleDraw| from this point.
526 delegate_ = NULL;
[email protected]7ab3f272011-11-16 00:51:56527 if (root_layer_)
528 root_layer_->SetCompositor(NULL);
[email protected]2700daddd2012-07-13 19:35:37529
530 // Stop all outstanding draws before telling the ContextFactory to tear
531 // down any contexts that the |host_| may rely upon.
532 host_.reset();
533
[email protected]40034cf2013-03-13 05:05:37534 ContextFactory::GetInstance()->RemoveCompositor(this);
[email protected]82a01ac2011-09-08 16:00:18535}
536
[email protected]44ed4bd2013-04-06 00:11:27537// static
[email protected]ab6627372012-01-29 21:22:13538void Compositor::Initialize(bool use_thread) {
[email protected]ec05af52012-11-21 23:07:00539 if (use_thread) {
540 g_compositor_thread = new base::Thread("Browser Compositor");
541 g_compositor_thread->Start();
542 }
[email protected]ab6627372012-01-29 21:22:13543}
544
[email protected]44ed4bd2013-04-06 00:11:27545// static
546bool Compositor::WasInitializedWithThread() {
547 return !!g_compositor_thread;
548}
549
550// static
[email protected]ab6627372012-01-29 21:22:13551void Compositor::Terminate() {
[email protected]ab6627372012-01-29 21:22:13552 if (g_compositor_thread) {
[email protected]ec05af52012-11-21 23:07:00553 g_compositor_thread->Stop();
[email protected]ab6627372012-01-29 21:22:13554 delete g_compositor_thread;
555 g_compositor_thread = NULL;
556 }
557}
558
[email protected]332749032011-10-22 00:32:46559void Compositor::ScheduleDraw() {
[email protected]4ea4e2d2012-11-20 15:17:09560 if (g_compositor_thread)
[email protected]f0c2a242013-03-15 19:34:52561 host_->Composite(base::TimeTicks::Now());
[email protected]4ea4e2d2012-11-20 15:17:09562 else if (delegate_)
[email protected]ab6627372012-01-29 21:22:13563 delegate_->ScheduleDraw();
[email protected]332749032011-10-22 00:32:46564}
565
[email protected]993d6b322011-09-27 19:14:38566void Compositor::SetRootLayer(Layer* root_layer) {
[email protected]12233c362011-11-21 16:09:25567 if (root_layer_ == root_layer)
568 return;
[email protected]7ab3f272011-11-16 00:51:56569 if (root_layer_)
570 root_layer_->SetCompositor(NULL);
[email protected]993d6b322011-09-27 19:14:38571 root_layer_ = root_layer;
[email protected]7ab3f272011-11-16 00:51:56572 if (root_layer_ && !root_layer_->GetCompositor())
[email protected]993d6b322011-09-27 19:14:38573 root_layer_->SetCompositor(this);
[email protected]7aba6662013-03-12 10:17:34574 root_web_layer_->RemoveAllChildren();
[email protected]66efabe2012-08-18 03:06:06575 if (root_layer_)
[email protected]7aba6662013-03-12 10:17:34576 root_web_layer_->AddChild(root_layer_->cc_layer());
[email protected]993d6b322011-09-27 19:14:38577}
578
[email protected]ebd52522012-10-04 15:49:40579void Compositor::SetHostHasTransparentBackground(
580 bool host_has_transparent_background) {
[email protected]804c8982013-03-13 16:32:21581 host_->set_has_transparent_background(host_has_transparent_background);
[email protected]ebd52522012-10-04 15:49:40582}
583
[email protected]ed8de92d2011-09-14 04:16:48584void Compositor::Draw(bool force_clear) {
[email protected]337bd042012-11-05 23:43:43585 DCHECK(!g_compositor_thread);
586
[email protected]ed8de92d2011-09-14 04:16:48587 if (!root_layer_)
588 return;
589
[email protected]d4ae80572012-06-06 23:02:06590 last_started_frame_++;
[email protected]337bd042012-11-05 23:43:43591 PendingSwap pending_swap(DRAW_SWAP, posted_swaps_.get());
592 if (!IsLocked()) {
[email protected]6b16679e2012-10-27 00:44:28593 // TODO(nduca): Temporary while compositor calls
594 // compositeImmediately() directly.
[email protected]408b5e22013-03-19 09:48:09595 Layout();
[email protected]f0c2a242013-03-15 19:34:52596 host_->Composite(base::TimeTicks::Now());
[email protected]8d9080ab2013-04-06 00:03:20597
598#if defined(OS_WIN)
599 // While we resize, we are usually a few frames behind. By blocking
600 // the UI thread here we minize the area that is mis-painted, specially
601 // in the non-client area. See RenderWidgetHostViewAura::SetBounds for
602 // more details and bug 177115.
603 if (next_draw_is_resize_ && (last_ended_frame_ > 1)) {
604 next_draw_is_resize_ = false;
605 host_->FinishAllRendering();
606 }
607#endif
608
[email protected]6b16679e2012-10-27 00:44:28609 }
[email protected]337bd042012-11-05 23:43:43610 if (!pending_swap.posted())
[email protected]1920930592012-01-11 14:54:48611 NotifyEnd();
[email protected]ab6627372012-01-29 21:22:13612}
613
[email protected]7df588fbd2012-02-10 14:15:56614void Compositor::ScheduleFullDraw() {
[email protected]804c8982013-03-13 16:32:21615 host_->SetNeedsRedraw();
[email protected]7df588fbd2012-02-10 14:15:56616}
617
[email protected]cd9a61c72012-05-08 19:16:59618bool Compositor::ReadPixels(SkBitmap* bitmap,
619 const gfx::Rect& bounds_in_pixel) {
620 if (bounds_in_pixel.right() > size().width() ||
621 bounds_in_pixel.bottom() > size().height())
[email protected]ab6627372012-01-29 21:22:13622 return false;
[email protected]ab6627372012-01-29 21:22:13623 bitmap->setConfig(SkBitmap::kARGB_8888_Config,
[email protected]cd9a61c72012-05-08 19:16:59624 bounds_in_pixel.width(), bounds_in_pixel.height());
[email protected]ab6627372012-01-29 21:22:13625 bitmap->allocPixels();
626 SkAutoLockPixels lock_image(*bitmap);
627 unsigned char* pixels = static_cast<unsigned char*>(bitmap->getPixels());
[email protected]6b16679e2012-10-27 00:44:28628 CancelCompositorLock();
[email protected]337bd042012-11-05 23:43:43629 PendingSwap pending_swap(READPIXELS_SWAP, posted_swaps_.get());
[email protected]804c8982013-03-13 16:32:21630 return host_->CompositeAndReadback(pixels, bounds_in_pixel);
[email protected]ab6627372012-01-29 21:22:13631}
632
[email protected]cd9a61c72012-05-08 19:16:59633void Compositor::SetScaleAndSize(float scale, const gfx::Size& size_in_pixel) {
[email protected]cff176a2012-06-29 21:11:00634 DCHECK_GT(scale, 0);
[email protected]351b8ce2012-11-27 23:37:16635 if (!size_in_pixel.IsEmpty()) {
636 size_ = size_in_pixel;
[email protected]18ce59702013-04-09 04:58:40637 host_->SetViewportSize(size_in_pixel);
[email protected]7aba6662013-03-12 10:17:34638 root_web_layer_->SetBounds(size_in_pixel);
[email protected]8d9080ab2013-04-06 00:03:20639
640 next_draw_is_resize_ = true;
[email protected]351b8ce2012-11-27 23:37:16641 }
[email protected]2e2216e42012-05-17 15:17:00642 if (device_scale_factor_ != scale) {
[email protected]cd9a61c72012-05-08 19:16:59643 device_scale_factor_ = scale;
644 if (root_layer_)
645 root_layer_->OnDeviceScaleFactorChanged(scale);
646 }
[email protected]ed8de92d2011-09-14 04:16:48647}
648
[email protected]87601922013-04-02 03:56:42649void Compositor::SetBackgroundColor(SkColor color) {
650 host_->set_background_color(color);
651 ScheduleDraw();
652}
653
[email protected]ed8de92d2011-09-14 04:16:48654void Compositor::AddObserver(CompositorObserver* observer) {
655 observer_list_.AddObserver(observer);
656}
657
658void Compositor::RemoveObserver(CompositorObserver* observer) {
659 observer_list_.RemoveObserver(observer);
660}
661
[email protected]3ce2feb2011-09-19 18:44:23662bool Compositor::HasObserver(CompositorObserver* observer) {
663 return observer_list_.HasObserver(observer);
664}
665
[email protected]894e8fc2012-02-24 13:29:50666void Compositor::OnSwapBuffersPosted() {
[email protected]337bd042012-11-05 23:43:43667 DCHECK(!g_compositor_thread);
668 posted_swaps_->PostSwap();
[email protected]894e8fc2012-02-24 13:29:50669}
670
671void Compositor::OnSwapBuffersComplete() {
[email protected]337bd042012-11-05 23:43:43672 DCHECK(!g_compositor_thread);
673 DCHECK(posted_swaps_->AreSwapsPosted());
674 DCHECK_GE(1, posted_swaps_->NumSwapsPosted(DRAW_SWAP));
675 if (posted_swaps_->NextPostedSwap() == DRAW_SWAP)
676 NotifyEnd();
677 posted_swaps_->EndSwap();
[email protected]894e8fc2012-02-24 13:29:50678}
679
680void Compositor::OnSwapBuffersAborted() {
[email protected]f79729062013-04-03 20:01:50681 if (!g_compositor_thread) {
682 DCHECK_GE(1, posted_swaps_->NumSwapsPosted(DRAW_SWAP));
[email protected]337bd042012-11-05 23:43:43683
[email protected]f79729062013-04-03 20:01:50684 // We've just lost the context, so unwind all posted_swaps.
685 while (posted_swaps_->AreSwapsPosted()) {
686 if (posted_swaps_->NextPostedSwap() == DRAW_SWAP)
687 NotifyEnd();
688 posted_swaps_->EndSwap();
689 }
[email protected]d912f8c2012-11-03 02:35:01690 }
[email protected]337bd042012-11-05 23:43:43691
[email protected]91f4c792012-06-06 02:21:19692 FOR_EACH_OBSERVER(CompositorObserver,
693 observer_list_,
694 OnCompositingAborted(this));
[email protected]894e8fc2012-02-24 13:29:50695}
[email protected]ab6627372012-01-29 21:22:13696
[email protected]3b6085512013-02-21 01:26:20697void Compositor::OnUpdateVSyncParameters(base::TimeTicks timebase,
698 base::TimeDelta interval) {
699 FOR_EACH_OBSERVER(CompositorObserver,
700 observer_list_,
701 OnUpdateVSyncParameters(this, timebase, interval));
702}
703
[email protected]408b5e22013-03-19 09:48:09704void Compositor::Layout() {
[email protected]d4ae80572012-06-06 23:02:06705 // We're sending damage that will be addressed during this composite
706 // cycle, so we don't need to schedule another composite to address it.
707 disable_schedule_composite_ = true;
[email protected]f78649ea2012-02-23 18:39:04708 if (root_layer_)
[email protected]cedc3952012-03-06 06:15:55709 root_layer_->SendDamagedRects();
[email protected]d4ae80572012-06-06 23:02:06710 disable_schedule_composite_ = false;
[email protected]ab6627372012-01-29 21:22:13711}
712
[email protected]408b5e22013-03-19 09:48:09713scoped_ptr<cc::OutputSurface> Compositor::CreateOutputSurface() {
[email protected]40034cf2013-03-13 05:05:37714 return make_scoped_ptr(
715 ContextFactory::GetInstance()->CreateOutputSurface(this));
[email protected]ab6627372012-01-29 21:22:13716}
717
[email protected]408b5e22013-03-19 09:48:09718scoped_ptr<cc::InputHandler> Compositor::CreateInputHandler() {
[email protected]ec05af52012-11-21 23:07:00719 return scoped_ptr<cc::InputHandler>();
720}
721
[email protected]408b5e22013-03-19 09:48:09722void Compositor::DidCommit() {
[email protected]6b16679e2012-10-27 00:44:28723 DCHECK(!IsLocked());
[email protected]2700daddd2012-07-13 19:35:37724 FOR_EACH_OBSERVER(CompositorObserver,
725 observer_list_,
726 OnCompositingDidCommit(this));
727}
728
[email protected]408b5e22013-03-19 09:48:09729void Compositor::DidCommitAndDrawFrame() {
[email protected]3b6085512013-02-21 01:26:20730 base::TimeTicks start_time = base::TimeTicks::Now();
[email protected]a8f677c2012-03-23 01:36:06731 FOR_EACH_OBSERVER(CompositorObserver,
732 observer_list_,
[email protected]3b6085512013-02-21 01:26:20733 OnCompositingStarted(this, start_time));
[email protected]f79729062013-04-03 20:01:50734 // If we're threaded without a swap complete callback, we have to
735 // call DidCompleteSwapBuffersManually.
736 if (g_compositor_thread &&
737 !host_->GetRendererCapabilities().using_swap_complete_callback)
738 DidCompleteSwapBuffers();
[email protected]ba7aeb82012-02-24 23:36:13739}
740
[email protected]408b5e22013-03-19 09:48:09741void Compositor::DidCompleteSwapBuffers() {
[email protected]337bd042012-11-05 23:43:43742 DCHECK(g_compositor_thread);
[email protected]ba7aeb82012-02-24 23:36:13743 NotifyEnd();
[email protected]ab6627372012-01-29 21:22:13744}
745
[email protected]408b5e22013-03-19 09:48:09746void Compositor::ScheduleComposite() {
[email protected]d4ae80572012-06-06 23:02:06747 if (!disable_schedule_composite_)
748 ScheduleDraw();
[email protected]332749032011-10-22 00:32:46749}
750
[email protected]0a451722013-02-22 20:32:05751scoped_refptr<cc::ContextProvider>
752Compositor::OffscreenContextProviderForMainThread() {
[email protected]0a451722013-02-22 20:32:05753 return ContextFactory::GetInstance()->OffscreenContextProviderForMainThread();
754}
755
756scoped_refptr<cc::ContextProvider>
757Compositor::OffscreenContextProviderForCompositorThread() {
[email protected]0a451722013-02-22 20:32:05758 return ContextFactory::GetInstance()->
759 OffscreenContextProviderForCompositorThread();
760}
761
[email protected]6b16679e2012-10-27 00:44:28762scoped_refptr<CompositorLock> Compositor::GetCompositorLock() {
763 if (!compositor_lock_) {
764 compositor_lock_ = new CompositorLock(this);
765 if (g_compositor_thread)
[email protected]804c8982013-03-13 16:32:21766 host_->SetDeferCommits(true);
[email protected]6b16679e2012-10-27 00:44:28767 FOR_EACH_OBSERVER(CompositorObserver,
768 observer_list_,
769 OnCompositingLockStateChanged(this));
770 }
771 return compositor_lock_;
772}
773
774void Compositor::UnlockCompositor() {
775 DCHECK(compositor_lock_);
776 compositor_lock_ = NULL;
777 if (g_compositor_thread)
[email protected]804c8982013-03-13 16:32:21778 host_->SetDeferCommits(false);
[email protected]6b16679e2012-10-27 00:44:28779 FOR_EACH_OBSERVER(CompositorObserver,
780 observer_list_,
781 OnCompositingLockStateChanged(this));
782}
783
784void Compositor::CancelCompositorLock() {
785 if (compositor_lock_)
786 compositor_lock_->CancelLock();
787}
788
[email protected]a8f21152011-09-08 15:30:02789void Compositor::NotifyEnd() {
[email protected]d4ae80572012-06-06 23:02:06790 last_ended_frame_++;
[email protected]a8f21152011-09-08 15:30:02791 FOR_EACH_OBSERVER(CompositorObserver,
792 observer_list_,
[email protected]3ce2feb2011-09-19 18:44:23793 OnCompositingEnded(this));
[email protected]a8f21152011-09-08 15:30:02794}
795
[email protected]ab6627372012-01-29 21:22:13796COMPOSITOR_EXPORT void SetupTestCompositor() {
797 if (!CommandLine::ForCurrentProcess()->HasSwitch(
798 switches::kDisableTestCompositor)) {
[email protected]8cbffc62013-01-23 22:11:09799 g_test_compositor_enabled = true;
[email protected]ab6627372012-01-29 21:22:13800 }
[email protected]8391a49e2012-05-26 06:31:04801#if defined(OS_CHROMEOS)
802 // If the test is running on the chromeos envrionment (such as
803 // device or vm bots), use the real compositor.
804 if (base::chromeos::IsRunningOnChromeOS())
[email protected]8cbffc62013-01-23 22:11:09805 g_test_compositor_enabled = false;
[email protected]8391a49e2012-05-26 06:31:04806#endif
[email protected]40034cf2013-03-13 05:05:37807 ResetImplicitFactory();
[email protected]ab6627372012-01-29 21:22:13808}
809
810COMPOSITOR_EXPORT void DisableTestCompositor() {
[email protected]40034cf2013-03-13 05:05:37811 ResetImplicitFactory();
[email protected]8cbffc62013-01-23 22:11:09812 g_test_compositor_enabled = false;
[email protected]1920930592012-01-11 14:54:48813}
814
[email protected]894e8fc2012-02-24 13:29:50815COMPOSITOR_EXPORT bool IsTestCompositorEnabled() {
[email protected]8cbffc62013-01-23 22:11:09816 return g_test_compositor_enabled;
[email protected]894e8fc2012-02-24 13:29:50817}
818
[email protected]c797cd42011-03-15 02:18:36819} // namespace ui