blob: 5bcd1af87864e70543aa34d5cd963c9f56e535b6 [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]89af4002013-09-06 07:47:0712#include "base/debug/trace_event.h"
[email protected]0a451722013-02-22 20:32:0513#include "base/memory/singleton.h"
[email protected]4e2d03e22013-07-18 04:19:5414#include "base/message_loop/message_loop.h"
[email protected]1e7565a2013-04-08 20:11:1415#include "base/run_loop.h"
[email protected]f3652ff92013-06-11 13:54:3116#include "base/strings/string_util.h"
[email protected]49c4cf852013-09-27 19:28:2417#include "base/sys_info.h"
[email protected]ec05af52012-11-21 23:07:0018#include "base/threading/thread.h"
[email protected]894e8fc2012-02-24 13:29:5019#include "base/threading/thread_restrictions.h"
[email protected]4d5e6762013-03-19 18:46:5720#include "cc/base/switches.h"
[email protected]ff7c2e4b2013-08-13 23:47:3521#include "cc/debug/test_context_provider.h"
[email protected]95fc42142013-08-13 19:31:0522#include "cc/debug/test_web_graphics_context_3d.h"
[email protected]3052b10f2013-03-18 07:41:2123#include "cc/input/input_handler.h"
[email protected]cc3cfaa2013-03-18 09:05:5224#include "cc/layers/layer.h"
[email protected]7f0d825f2013-03-18 07:24:3025#include "cc/output/context_provider.h"
26#include "cc/output/output_surface.h"
[email protected]556fd292013-03-18 08:03:0427#include "cc/trees/layer_tree_host.h"
[email protected]83afcbcc2012-07-27 03:06:2728#include "third_party/skia/include/core/SkBitmap.h"
[email protected]116302fc2012-05-05 21:45:4129#include "ui/compositor/compositor_observer.h"
30#include "ui/compositor/compositor_switches.h"
[email protected]cd9a61c72012-05-08 19:16:5931#include "ui/compositor/dip_util.h"
[email protected]116302fc2012-05-05 21:45:4132#include "ui/compositor/layer.h"
[email protected]bc90af6b2013-07-29 20:32:3933#include "ui/compositor/reflector.h"
[email protected]c9e2cbbb2012-05-12 21:17:2734#include "ui/gl/gl_context.h"
35#include "ui/gl/gl_implementation.h"
36#include "ui/gl/gl_surface.h"
[email protected]cc2ae012012-09-21 19:35:2537#include "ui/gl/gl_switches.h"
[email protected]199b715e2013-08-13 05:18:3438#include "webkit/common/gpu/context_provider_in_process.h"
[email protected]1fb9e7e2013-05-26 03:23:4839#include "webkit/common/gpu/grcontext_for_webgraphicscontext3d.h"
40#include "webkit/common/gpu/webgraphicscontext3d_in_process_command_buffer_impl.h"
[email protected]ab6627372012-01-29 21:22:1341
42namespace {
43
44const double kDefaultRefreshRate = 60.0;
[email protected]7ddeaab2013-04-06 00:47:0545const double kTestRefreshRate = 200.0;
[email protected]ab6627372012-01-29 21:22:1346
[email protected]337bd042012-11-05 23:43:4347enum SwapType {
48 DRAW_SWAP,
49 READPIXELS_SWAP,
50};
51
[email protected]d56d3bb2013-08-12 20:58:0152bool g_compositor_initialized = false;
[email protected]ec05af52012-11-21 23:07:0053base::Thread* g_compositor_thread = NULL;
[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]83afcbcc2012-07-27 03:06:2778} // namespace
[email protected]c797cd42011-03-15 02:18:3679
80namespace ui {
81
[email protected]894e8fc2012-02-24 13:29:5082// static
83ContextFactory* ContextFactory::GetInstance() {
[email protected]d56d3bb2013-08-12 20:58:0184 DCHECK(g_context_factory);
[email protected]894e8fc2012-02-24 13:29:5085 return g_context_factory;
[email protected]ca806632012-02-16 02:15:5986}
87
[email protected]58b4b6d2012-02-16 01:40:2488// static
[email protected]894e8fc2012-02-24 13:29:5089void ContextFactory::SetInstance(ContextFactory* instance) {
90 g_context_factory = instance;
[email protected]ca806632012-02-16 02:15:5991}
92
[email protected]40034cf2013-03-13 05:05:3793DefaultContextFactory::DefaultContextFactory() {
94}
95
96DefaultContextFactory::~DefaultContextFactory() {
97}
98
99bool DefaultContextFactory::Initialize() {
100 if (!gfx::GLSurface::InitializeOneOff() ||
101 gfx::GetGLImplementation() == gfx::kGLImplementationNone) {
102 LOG(ERROR) << "Could not load the GL bindings";
103 return false;
104 }
105 return true;
106}
107
[email protected]bc90af6b2013-07-29 20:32:39108scoped_ptr<cc::OutputSurface> DefaultContextFactory::CreateOutputSurface(
[email protected]40034cf2013-03-13 05:05:37109 Compositor* compositor) {
[email protected]3a98aed92013-08-16 04:58:13110 WebKit::WebGraphicsContext3D::Attributes attrs;
111 attrs.depth = false;
112 attrs.stencil = false;
113 attrs.antialias = false;
114 attrs.shareResources = true;
115
116 using webkit::gpu::WebGraphicsContext3DInProcessCommandBufferImpl;
117 scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d(
118 WebGraphicsContext3DInProcessCommandBufferImpl::CreateViewContext(
119 attrs, compositor->widget()));
120 CHECK(context3d);
[email protected]40034cf2013-03-13 05:05:37121
[email protected]0634cdd42013-08-16 00:46:09122 using webkit::gpu::ContextProviderInProcess;
123 scoped_refptr<ContextProviderInProcess> context_provider =
[email protected]af13d832013-09-13 06:56:27124 ContextProviderInProcess::Create(context3d.Pass(),
125 "UICompositor");
[email protected]3a98aed92013-08-16 04:58:13126
[email protected]0634cdd42013-08-16 00:46:09127 return make_scoped_ptr(new cc::OutputSurface(context_provider));
[email protected]40034cf2013-03-13 05:05:37128}
129
[email protected]57bed4d2013-06-08 20:54:18130scoped_refptr<Reflector> DefaultContextFactory::CreateReflector(
131 Compositor* mirroed_compositor,
132 Layer* mirroring_layer) {
133 return NULL;
134}
135
136void DefaultContextFactory::RemoveReflector(
137 scoped_refptr<Reflector> reflector) {
138}
139
[email protected]0a451722013-02-22 20:32:05140scoped_refptr<cc::ContextProvider>
[email protected]f10dc472013-09-27 03:31:59141DefaultContextFactory::OffscreenCompositorContextProvider() {
142 if (!offscreen_compositor_contexts_.get() ||
143 !offscreen_compositor_contexts_->DestroyedOnMainThread()) {
144 offscreen_compositor_contexts_ =
[email protected]3d6b5122013-08-14 22:25:34145 webkit::gpu::ContextProviderInProcess::CreateOffscreen();
[email protected]0a451722013-02-22 20:32:05146 }
[email protected]f10dc472013-09-27 03:31:59147 return offscreen_compositor_contexts_;
[email protected]0a451722013-02-22 20:32:05148}
149
150scoped_refptr<cc::ContextProvider>
[email protected]f10dc472013-09-27 03:31:59151DefaultContextFactory::SharedMainThreadContextProvider() {
152 if (shared_main_thread_contexts_ &&
153 !shared_main_thread_contexts_->DestroyedOnMainThread())
154 return shared_main_thread_contexts_;
155
156 if (ui::Compositor::WasInitializedWithThread()) {
157 shared_main_thread_contexts_ =
[email protected]3d6b5122013-08-14 22:25:34158 webkit::gpu::ContextProviderInProcess::CreateOffscreen();
[email protected]f10dc472013-09-27 03:31:59159 } else {
160 shared_main_thread_contexts_ =
161 static_cast<webkit::gpu::ContextProviderInProcess*>(
162 OffscreenCompositorContextProvider().get());
[email protected]0a451722013-02-22 20:32:05163 }
[email protected]f10dc472013-09-27 03:31:59164 if (shared_main_thread_contexts_ &&
165 !shared_main_thread_contexts_->BindToCurrentThread())
166 shared_main_thread_contexts_ = NULL;
167
168 return shared_main_thread_contexts_;
[email protected]0a451722013-02-22 20:32:05169}
170
[email protected]84dba8ca2012-04-10 03:27:39171void DefaultContextFactory::RemoveCompositor(Compositor* compositor) {
172}
173
[email protected]d56d3bb2013-08-12 20:58:01174bool DefaultContextFactory::DoesCreateTestContexts() { return false; }
175
[email protected]e06e1122013-03-15 17:12:38176TestContextFactory::TestContextFactory() {}
[email protected]40034cf2013-03-13 05:05:37177
[email protected]e06e1122013-03-15 17:12:38178TestContextFactory::~TestContextFactory() {}
[email protected]40034cf2013-03-13 05:05:37179
[email protected]bc90af6b2013-07-29 20:32:39180scoped_ptr<cc::OutputSurface> TestContextFactory::CreateOutputSurface(
[email protected]40034cf2013-03-13 05:05:37181 Compositor* compositor) {
[email protected]0634cdd42013-08-16 00:46:09182 return make_scoped_ptr(
183 new cc::OutputSurface(cc::TestContextProvider::Create()));
[email protected]40034cf2013-03-13 05:05:37184}
185
[email protected]57bed4d2013-06-08 20:54:18186scoped_refptr<Reflector> TestContextFactory::CreateReflector(
187 Compositor* mirrored_compositor,
188 Layer* mirroring_layer) {
189 return new Reflector();
190}
191
192void TestContextFactory::RemoveReflector(scoped_refptr<Reflector> reflector) {
193}
194
[email protected]40034cf2013-03-13 05:05:37195scoped_refptr<cc::ContextProvider>
[email protected]f10dc472013-09-27 03:31:59196TestContextFactory::OffscreenCompositorContextProvider() {
197 if (!offscreen_compositor_contexts_.get() ||
198 offscreen_compositor_contexts_->DestroyedOnMainThread())
199 offscreen_compositor_contexts_ = cc::TestContextProvider::Create();
200 return offscreen_compositor_contexts_;
[email protected]40034cf2013-03-13 05:05:37201}
202
203scoped_refptr<cc::ContextProvider>
[email protected]f10dc472013-09-27 03:31:59204TestContextFactory::SharedMainThreadContextProvider() {
205 if (shared_main_thread_contexts_ &&
206 !shared_main_thread_contexts_->DestroyedOnMainThread())
207 return shared_main_thread_contexts_;
208
209 if (ui::Compositor::WasInitializedWithThread()) {
210 shared_main_thread_contexts_ = cc::TestContextProvider::Create();
211 } else {
212 shared_main_thread_contexts_ =
213 static_cast<cc::TestContextProvider*>(
214 OffscreenCompositorContextProvider().get());
[email protected]e06e1122013-03-15 17:12:38215 }
[email protected]f10dc472013-09-27 03:31:59216 if (shared_main_thread_contexts_ &&
217 !shared_main_thread_contexts_->BindToCurrentThread())
218 shared_main_thread_contexts_ = NULL;
219
220 return shared_main_thread_contexts_;
[email protected]40034cf2013-03-13 05:05:37221}
222
223void TestContextFactory::RemoveCompositor(Compositor* compositor) {
224}
225
[email protected]d56d3bb2013-08-12 20:58:01226bool TestContextFactory::DoesCreateTestContexts() { return true; }
227
[email protected]d3407cdb2012-09-21 22:33:25228Texture::Texture(bool flipped, const gfx::Size& size, float device_scale_factor)
[email protected]34466d02012-12-10 18:00:34229 : size_(size),
230 flipped_(flipped),
[email protected]d3407cdb2012-09-21 22:33:25231 device_scale_factor_(device_scale_factor) {
[email protected]ab6627372012-01-29 21:22:13232}
233
234Texture::~Texture() {
235}
236
[email protected]06666c02013-03-07 19:32:30237std::string Texture::Produce() {
238 return EmptyString();
[email protected]f027ca1502012-12-21 01:42:32239}
240
[email protected]6b16679e2012-10-27 00:44:28241CompositorLock::CompositorLock(Compositor* compositor)
242 : compositor_(compositor) {
[email protected]7060d6592013-04-29 19:01:48243 base::MessageLoop::current()->PostDelayedTask(
[email protected]6b16679e2012-10-27 00:44:28244 FROM_HERE,
245 base::Bind(&CompositorLock::CancelLock, AsWeakPtr()),
246 base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs));
247}
248
249CompositorLock::~CompositorLock() {
250 CancelLock();
251}
252
253void CompositorLock::CancelLock() {
254 if (!compositor_)
255 return;
256 compositor_->UnlockCompositor();
257 compositor_ = NULL;
258}
259
[email protected]1e7565a2013-04-08 20:11:14260// static
[email protected]260c3212013-04-11 22:25:38261void DrawWaiterForTest::Wait(Compositor* compositor) {
[email protected]1e7565a2013-04-08 20:11:14262 DrawWaiterForTest waiter;
[email protected]36e5ff12013-06-11 12:19:29263 waiter.wait_for_commit_ = false;
264 waiter.WaitImpl(compositor);
265}
266
267// static
268void DrawWaiterForTest::WaitForCommit(Compositor* compositor) {
269 DrawWaiterForTest waiter;
270 waiter.wait_for_commit_ = true;
[email protected]260c3212013-04-11 22:25:38271 waiter.WaitImpl(compositor);
[email protected]1e7565a2013-04-08 20:11:14272}
273
[email protected]260c3212013-04-11 22:25:38274DrawWaiterForTest::DrawWaiterForTest() {
[email protected]1e7565a2013-04-08 20:11:14275}
276
277DrawWaiterForTest::~DrawWaiterForTest() {
278}
279
[email protected]260c3212013-04-11 22:25:38280void DrawWaiterForTest::WaitImpl(Compositor* compositor) {
[email protected]1e7565a2013-04-08 20:11:14281 compositor->AddObserver(this);
282 wait_run_loop_.reset(new base::RunLoop());
[email protected]1e7565a2013-04-08 20:11:14283 wait_run_loop_->Run();
284 compositor->RemoveObserver(this);
[email protected]1e7565a2013-04-08 20:11:14285}
286
287void DrawWaiterForTest::OnCompositingDidCommit(Compositor* compositor) {
[email protected]36e5ff12013-06-11 12:19:29288 if (wait_for_commit_)
289 wait_run_loop_->Quit();
[email protected]1e7565a2013-04-08 20:11:14290}
291
292void DrawWaiterForTest::OnCompositingStarted(Compositor* compositor,
293 base::TimeTicks start_time) {
294}
295
296void DrawWaiterForTest::OnCompositingEnded(Compositor* compositor) {
[email protected]36e5ff12013-06-11 12:19:29297 if (!wait_for_commit_)
298 wait_run_loop_->Quit();
[email protected]1e7565a2013-04-08 20:11:14299}
300
301void DrawWaiterForTest::OnCompositingAborted(Compositor* compositor) {
302}
303
304void DrawWaiterForTest::OnCompositingLockStateChanged(Compositor* compositor) {
305}
306
307void DrawWaiterForTest::OnUpdateVSyncParameters(Compositor* compositor,
308 base::TimeTicks timebase,
309 base::TimeDelta interval) {
310}
311
[email protected]337bd042012-11-05 23:43:43312class PostedSwapQueue {
313 public:
314 PostedSwapQueue() : pending_swap_(NULL) {
315 }
316
317 ~PostedSwapQueue() {
318 DCHECK(!pending_swap_);
319 }
320
321 SwapType NextPostedSwap() const {
322 return queue_.front();
323 }
324
325 bool AreSwapsPosted() const {
326 return !queue_.empty();
327 }
328
329 int NumSwapsPosted(SwapType type) const {
330 int count = 0;
331 for (std::deque<SwapType>::const_iterator it = queue_.begin();
332 it != queue_.end(); ++it) {
333 if (*it == type)
334 count++;
335 }
336 return count;
337 }
338
339 void PostSwap() {
340 DCHECK(pending_swap_);
341 queue_.push_back(pending_swap_->type());
342 pending_swap_->posted_ = true;
343 }
344
345 void EndSwap() {
346 queue_.pop_front();
347 }
348
349 private:
350 friend class ::PendingSwap;
351
352 PendingSwap* pending_swap_;
353 std::deque<SwapType> queue_;
354
355 DISALLOW_COPY_AND_ASSIGN(PostedSwapQueue);
356};
357
358} // namespace ui
359
360namespace {
361
362PendingSwap::PendingSwap(SwapType type, ui::PostedSwapQueue* posted_swaps)
363 : type_(type), posted_(false), posted_swaps_(posted_swaps) {
364 // Only one pending swap in flight.
365 DCHECK_EQ(static_cast<PendingSwap*>(NULL), posted_swaps_->pending_swap_);
366 posted_swaps_->pending_swap_ = this;
367}
368
369PendingSwap::~PendingSwap() {
370 DCHECK_EQ(this, posted_swaps_->pending_swap_);
371 posted_swaps_->pending_swap_ = NULL;
372}
373
374} // namespace
375
376namespace ui {
377
[email protected]ab6627372012-01-29 21:22:13378Compositor::Compositor(CompositorDelegate* delegate,
[email protected]cd9a61c72012-05-08 19:16:59379 gfx::AcceleratedWidget widget)
[email protected]82a01ac2011-09-08 16:00:18380 : delegate_(delegate),
[email protected]ab6627372012-01-29 21:22:13381 root_layer_(NULL),
382 widget_(widget),
[email protected]337bd042012-11-05 23:43:43383 posted_swaps_(new PostedSwapQueue()),
[email protected]d4ae80572012-06-06 23:02:06384 device_scale_factor_(0.0f),
385 last_started_frame_(0),
386 last_ended_frame_(0),
[email protected]8d9080ab2013-04-06 00:03:20387 next_draw_is_resize_(false),
[email protected]6b16679e2012-10-27 00:44:28388 disable_schedule_composite_(false),
389 compositor_lock_(NULL) {
[email protected]d56d3bb2013-08-12 20:58:01390 DCHECK(g_compositor_initialized)
391 << "Compositor::Initialize must be called before creating a Compositor.";
392
[email protected]7aba6662013-03-12 10:17:34393 root_web_layer_ = cc::Layer::Create();
394 root_web_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f));
[email protected]ec05af52012-11-21 23:07:00395
[email protected]ab6627372012-01-29 21:22:13396 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]4d5e6762013-03-19 18:46:57397
[email protected]ec05af52012-11-21 23:07:00398 cc::LayerTreeSettings settings;
[email protected]8e0176d2013-03-21 03:14:52399 settings.refresh_rate =
[email protected]d56d3bb2013-08-12 20:58:01400 ContextFactory::GetInstance()->DoesCreateTestContexts()
401 ? kTestRefreshRate
402 : kDefaultRefreshRate;
[email protected]910b3102013-09-21 16:12:23403 settings.deadline_scheduling_enabled =
404 switches::IsUIDeadlineSchedulingEnabled();
[email protected]50e157272013-04-13 05:07:19405 settings.partial_swap_enabled =
406 !command_line->HasSwitch(cc::switches::kUIDisablePartialSwap);
[email protected]8e0176d2013-03-21 03:14:52407 settings.per_tile_painting_enabled =
[email protected]4d5e6762013-03-19 18:46:57408 command_line->HasSwitch(cc::switches::kUIEnablePerTilePainting);
409
410 // These flags should be mirrored by renderer versions in content/renderer/.
[email protected]8e0176d2013-03-21 03:14:52411 settings.initial_debug_state.show_debug_borders =
[email protected]4d5e6762013-03-19 18:46:57412 command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders);
[email protected]8e0176d2013-03-21 03:14:52413 settings.initial_debug_state.show_fps_counter =
[email protected]4d5e6762013-03-19 18:46:57414 command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
[email protected]8e0176d2013-03-21 03:14:52415 settings.initial_debug_state.show_paint_rects =
[email protected]4d5e6762013-03-19 18:46:57416 command_line->HasSwitch(switches::kUIShowPaintRects);
[email protected]8e0176d2013-03-21 03:14:52417 settings.initial_debug_state.show_property_changed_rects =
[email protected]4d5e6762013-03-19 18:46:57418 command_line->HasSwitch(cc::switches::kUIShowPropertyChangedRects);
[email protected]8e0176d2013-03-21 03:14:52419 settings.initial_debug_state.show_surface_damage_rects =
[email protected]4d5e6762013-03-19 18:46:57420 command_line->HasSwitch(cc::switches::kUIShowSurfaceDamageRects);
[email protected]8e0176d2013-03-21 03:14:52421 settings.initial_debug_state.show_screen_space_rects =
[email protected]4d5e6762013-03-19 18:46:57422 command_line->HasSwitch(cc::switches::kUIShowScreenSpaceRects);
[email protected]8e0176d2013-03-21 03:14:52423 settings.initial_debug_state.show_replica_screen_space_rects =
[email protected]4d5e6762013-03-19 18:46:57424 command_line->HasSwitch(cc::switches::kUIShowReplicaScreenSpaceRects);
[email protected]8e0176d2013-03-21 03:14:52425 settings.initial_debug_state.show_occluding_rects =
[email protected]4d5e6762013-03-19 18:46:57426 command_line->HasSwitch(cc::switches::kUIShowOccludingRects);
[email protected]8e0176d2013-03-21 03:14:52427 settings.initial_debug_state.show_non_occluding_rects =
[email protected]4d5e6762013-03-19 18:46:57428 command_line->HasSwitch(cc::switches::kUIShowNonOccludingRects);
[email protected]302fe422012-06-11 14:49:11429
[email protected]810d40b72013-06-20 18:26:15430 scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner =
431 g_compositor_thread ? g_compositor_thread->message_loop_proxy() : NULL;
[email protected]ec05af52012-11-21 23:07:00432
[email protected]810d40b72013-06-20 18:26:15433 host_ = cc::LayerTreeHost::Create(this, settings, compositor_task_runner);
[email protected]804c8982013-03-13 16:32:21434 host_->SetRootLayer(root_web_layer_);
[email protected]14bd5542013-05-08 21:51:30435 host_->SetLayerTreeHostClientReady();
[email protected]82a01ac2011-09-08 16:00:18436}
437
438Compositor::~Compositor() {
[email protected]89af4002013-09-06 07:47:07439 TRACE_EVENT0("shutdown", "Compositor::destructor");
440
[email protected]d56d3bb2013-08-12 20:58:01441 DCHECK(g_compositor_initialized);
442
[email protected]6b16679e2012-10-27 00:44:28443 CancelCompositorLock();
444 DCHECK(!compositor_lock_);
445
[email protected]e332a1b2012-05-10 20:32:27446 // Don't call |CompositorDelegate::ScheduleDraw| from this point.
447 delegate_ = NULL;
[email protected]7ab3f272011-11-16 00:51:56448 if (root_layer_)
449 root_layer_->SetCompositor(NULL);
[email protected]2700daddd2012-07-13 19:35:37450
451 // Stop all outstanding draws before telling the ContextFactory to tear
452 // down any contexts that the |host_| may rely upon.
453 host_.reset();
454
[email protected]40034cf2013-03-13 05:05:37455 ContextFactory::GetInstance()->RemoveCompositor(this);
[email protected]82a01ac2011-09-08 16:00:18456}
457
[email protected]44ed4bd2013-04-06 00:11:27458// static
[email protected]d56d3bb2013-08-12 20:58:01459void Compositor::InitializeContextFactoryForTests(bool allow_test_contexts) {
[email protected]4baecad2013-09-12 23:00:36460 // The factory may already have been initialized by the content layer, in
461 // which case, use that one.
462 if (g_context_factory)
463 return;
[email protected]d56d3bb2013-08-12 20:58:01464 DCHECK(!g_implicit_factory) <<
465 "ContextFactory for tests already initialized.";
466
467 bool use_test_contexts = true;
468
469 // Always use test contexts unless the disable command line flag is used.
470 CommandLine* command_line = CommandLine::ForCurrentProcess();
471 if (command_line->HasSwitch(switches::kDisableTestCompositor))
472 use_test_contexts = false;
473
474#if defined(OS_CHROMEOS)
475 // If the test is running on the chromeos envrionment (such as
476 // device or vm bots), always use real contexts.
[email protected]49c4cf852013-09-27 19:28:24477 if (base::SysInfo::IsRunningOnChromeOS())
[email protected]d56d3bb2013-08-12 20:58:01478 use_test_contexts = false;
479#endif
480
481 if (!allow_test_contexts)
482 use_test_contexts = false;
483
484 if (use_test_contexts) {
485 g_implicit_factory = new ui::TestContextFactory;
486 } else {
487 DVLOG(1) << "Using DefaultContextFactory";
488 scoped_ptr<ui::DefaultContextFactory> instance(
489 new ui::DefaultContextFactory());
490 if (instance->Initialize())
491 g_implicit_factory = instance.release();
492 }
493 g_context_factory = g_implicit_factory;
494}
495
496// static
[email protected]188df652013-04-15 14:03:39497void Compositor::Initialize() {
498#if defined(OS_CHROMEOS)
499 bool use_thread = !CommandLine::ForCurrentProcess()->HasSwitch(
500 switches::kUIDisableThreadedCompositing);
501#else
502 bool use_thread =
503 CommandLine::ForCurrentProcess()->HasSwitch(
504 switches::kUIEnableThreadedCompositing) &&
505 !CommandLine::ForCurrentProcess()->HasSwitch(
506 switches::kUIDisableThreadedCompositing);
507#endif
[email protected]ec05af52012-11-21 23:07:00508 if (use_thread) {
509 g_compositor_thread = new base::Thread("Browser Compositor");
[email protected]e99339f2013-09-18 22:19:27510#if defined(OS_POSIX)
511 // Workaround for crbug.com/293736
512 // On Posix, MessagePumpDefault uses system time, so delayed tasks (for
513 // compositor scheduling) work incorrectly across system time changes (e.g.
514 // tlsdate). So instead, use an IO loop, which uses libevent, that uses
515 // monotonic time (immune to these problems).
516 base::Thread::Options options;
517 options.message_loop_type = base::MessageLoop::TYPE_IO;
518 g_compositor_thread->StartWithOptions(options);
519#else
[email protected]ec05af52012-11-21 23:07:00520 g_compositor_thread->Start();
[email protected]e99339f2013-09-18 22:19:27521#endif
[email protected]ec05af52012-11-21 23:07:00522 }
[email protected]d56d3bb2013-08-12 20:58:01523
524 DCHECK(!g_compositor_initialized) << "Compositor initialized twice.";
525 g_compositor_initialized = true;
[email protected]ab6627372012-01-29 21:22:13526}
527
[email protected]44ed4bd2013-04-06 00:11:27528// static
529bool Compositor::WasInitializedWithThread() {
[email protected]f10dc472013-09-27 03:31:59530 DCHECK(g_compositor_initialized);
[email protected]44ed4bd2013-04-06 00:11:27531 return !!g_compositor_thread;
532}
533
534// static
[email protected]c7abcfd82013-06-01 04:02:12535scoped_refptr<base::MessageLoopProxy> Compositor::GetCompositorMessageLoop() {
536 scoped_refptr<base::MessageLoopProxy> proxy;
537 if (g_compositor_thread)
538 proxy = g_compositor_thread->message_loop_proxy();
539 return proxy;
540}
541
542// static
[email protected]ab6627372012-01-29 21:22:13543void Compositor::Terminate() {
[email protected]d56d3bb2013-08-12 20:58:01544 if (g_context_factory) {
545 if (g_implicit_factory) {
546 delete g_implicit_factory;
547 g_implicit_factory = NULL;
548 }
549 g_context_factory = NULL;
550 }
551
[email protected]ab6627372012-01-29 21:22:13552 if (g_compositor_thread) {
[email protected]d56d3bb2013-08-12 20:58:01553 DCHECK(!g_context_factory)
554 << "The ContextFactory should not outlive the compositor thread.";
[email protected]ec05af52012-11-21 23:07:00555 g_compositor_thread->Stop();
[email protected]ab6627372012-01-29 21:22:13556 delete g_compositor_thread;
557 g_compositor_thread = NULL;
558 }
[email protected]d56d3bb2013-08-12 20:58:01559
560 DCHECK(g_compositor_initialized) << "Compositor::Initialize() didn't happen.";
561 g_compositor_initialized = false;
[email protected]ab6627372012-01-29 21:22:13562}
563
[email protected]332749032011-10-22 00:32:46564void Compositor::ScheduleDraw() {
[email protected]4ea4e2d2012-11-20 15:17:09565 if (g_compositor_thread)
[email protected]f0c2a242013-03-15 19:34:52566 host_->Composite(base::TimeTicks::Now());
[email protected]4ea4e2d2012-11-20 15:17:09567 else if (delegate_)
[email protected]ab6627372012-01-29 21:22:13568 delegate_->ScheduleDraw();
[email protected]332749032011-10-22 00:32:46569}
570
[email protected]993d6b322011-09-27 19:14:38571void Compositor::SetRootLayer(Layer* root_layer) {
[email protected]12233c362011-11-21 16:09:25572 if (root_layer_ == root_layer)
573 return;
[email protected]7ab3f272011-11-16 00:51:56574 if (root_layer_)
575 root_layer_->SetCompositor(NULL);
[email protected]993d6b322011-09-27 19:14:38576 root_layer_ = root_layer;
[email protected]7ab3f272011-11-16 00:51:56577 if (root_layer_ && !root_layer_->GetCompositor())
[email protected]993d6b322011-09-27 19:14:38578 root_layer_->SetCompositor(this);
[email protected]7aba6662013-03-12 10:17:34579 root_web_layer_->RemoveAllChildren();
[email protected]66efabe2012-08-18 03:06:06580 if (root_layer_)
[email protected]7aba6662013-03-12 10:17:34581 root_web_layer_->AddChild(root_layer_->cc_layer());
[email protected]993d6b322011-09-27 19:14:38582}
583
[email protected]ebd52522012-10-04 15:49:40584void Compositor::SetHostHasTransparentBackground(
585 bool host_has_transparent_background) {
[email protected]804c8982013-03-13 16:32:21586 host_->set_has_transparent_background(host_has_transparent_background);
[email protected]ebd52522012-10-04 15:49:40587}
588
[email protected]878705be2013-04-15 22:44:02589void Compositor::Draw() {
[email protected]337bd042012-11-05 23:43:43590 DCHECK(!g_compositor_thread);
591
[email protected]ed8de92d2011-09-14 04:16:48592 if (!root_layer_)
593 return;
594
[email protected]d4ae80572012-06-06 23:02:06595 last_started_frame_++;
[email protected]337bd042012-11-05 23:43:43596 PendingSwap pending_swap(DRAW_SWAP, posted_swaps_.get());
597 if (!IsLocked()) {
[email protected]6b16679e2012-10-27 00:44:28598 // TODO(nduca): Temporary while compositor calls
599 // compositeImmediately() directly.
[email protected]408b5e22013-03-19 09:48:09600 Layout();
[email protected]f0c2a242013-03-15 19:34:52601 host_->Composite(base::TimeTicks::Now());
[email protected]8d9080ab2013-04-06 00:03:20602
603#if defined(OS_WIN)
604 // While we resize, we are usually a few frames behind. By blocking
605 // the UI thread here we minize the area that is mis-painted, specially
606 // in the non-client area. See RenderWidgetHostViewAura::SetBounds for
607 // more details and bug 177115.
608 if (next_draw_is_resize_ && (last_ended_frame_ > 1)) {
609 next_draw_is_resize_ = false;
610 host_->FinishAllRendering();
611 }
612#endif
613
[email protected]6b16679e2012-10-27 00:44:28614 }
[email protected]337bd042012-11-05 23:43:43615 if (!pending_swap.posted())
[email protected]1920930592012-01-11 14:54:48616 NotifyEnd();
[email protected]ab6627372012-01-29 21:22:13617}
618
[email protected]878705be2013-04-15 22:44:02619void Compositor::ScheduleFullRedraw() {
[email protected]804c8982013-03-13 16:32:21620 host_->SetNeedsRedraw();
[email protected]7df588fbd2012-02-10 14:15:56621}
622
[email protected]878705be2013-04-15 22:44:02623void Compositor::ScheduleRedrawRect(const gfx::Rect& damage_rect) {
624 host_->SetNeedsRedrawRect(damage_rect);
625}
626
[email protected]66239a22013-06-05 03:38:26627void Compositor::SetLatencyInfo(const ui::LatencyInfo& latency_info) {
628 host_->SetLatencyInfo(latency_info);
629}
630
[email protected]cd9a61c72012-05-08 19:16:59631bool Compositor::ReadPixels(SkBitmap* bitmap,
632 const gfx::Rect& bounds_in_pixel) {
633 if (bounds_in_pixel.right() > size().width() ||
634 bounds_in_pixel.bottom() > size().height())
[email protected]ab6627372012-01-29 21:22:13635 return false;
[email protected]ab6627372012-01-29 21:22:13636 bitmap->setConfig(SkBitmap::kARGB_8888_Config,
[email protected]cd9a61c72012-05-08 19:16:59637 bounds_in_pixel.width(), bounds_in_pixel.height());
[email protected]ab6627372012-01-29 21:22:13638 bitmap->allocPixels();
639 SkAutoLockPixels lock_image(*bitmap);
640 unsigned char* pixels = static_cast<unsigned char*>(bitmap->getPixels());
[email protected]6b16679e2012-10-27 00:44:28641 CancelCompositorLock();
[email protected]337bd042012-11-05 23:43:43642 PendingSwap pending_swap(READPIXELS_SWAP, posted_swaps_.get());
[email protected]804c8982013-03-13 16:32:21643 return host_->CompositeAndReadback(pixels, bounds_in_pixel);
[email protected]ab6627372012-01-29 21:22:13644}
645
[email protected]cd9a61c72012-05-08 19:16:59646void Compositor::SetScaleAndSize(float scale, const gfx::Size& size_in_pixel) {
[email protected]cff176a2012-06-29 21:11:00647 DCHECK_GT(scale, 0);
[email protected]351b8ce2012-11-27 23:37:16648 if (!size_in_pixel.IsEmpty()) {
649 size_ = size_in_pixel;
[email protected]18ce59702013-04-09 04:58:40650 host_->SetViewportSize(size_in_pixel);
[email protected]7aba6662013-03-12 10:17:34651 root_web_layer_->SetBounds(size_in_pixel);
[email protected]8d9080ab2013-04-06 00:03:20652
653 next_draw_is_resize_ = true;
[email protected]351b8ce2012-11-27 23:37:16654 }
[email protected]2e2216e42012-05-17 15:17:00655 if (device_scale_factor_ != scale) {
[email protected]cd9a61c72012-05-08 19:16:59656 device_scale_factor_ = scale;
657 if (root_layer_)
658 root_layer_->OnDeviceScaleFactorChanged(scale);
659 }
[email protected]ed8de92d2011-09-14 04:16:48660}
661
[email protected]87601922013-04-02 03:56:42662void Compositor::SetBackgroundColor(SkColor color) {
663 host_->set_background_color(color);
664 ScheduleDraw();
665}
666
[email protected]ed8de92d2011-09-14 04:16:48667void Compositor::AddObserver(CompositorObserver* observer) {
668 observer_list_.AddObserver(observer);
669}
670
671void Compositor::RemoveObserver(CompositorObserver* observer) {
672 observer_list_.RemoveObserver(observer);
673}
674
[email protected]3ce2feb2011-09-19 18:44:23675bool Compositor::HasObserver(CompositorObserver* observer) {
676 return observer_list_.HasObserver(observer);
677}
678
[email protected]894e8fc2012-02-24 13:29:50679void Compositor::OnSwapBuffersPosted() {
[email protected]337bd042012-11-05 23:43:43680 DCHECK(!g_compositor_thread);
681 posted_swaps_->PostSwap();
[email protected]894e8fc2012-02-24 13:29:50682}
683
684void Compositor::OnSwapBuffersComplete() {
[email protected]337bd042012-11-05 23:43:43685 DCHECK(!g_compositor_thread);
686 DCHECK(posted_swaps_->AreSwapsPosted());
687 DCHECK_GE(1, posted_swaps_->NumSwapsPosted(DRAW_SWAP));
688 if (posted_swaps_->NextPostedSwap() == DRAW_SWAP)
689 NotifyEnd();
690 posted_swaps_->EndSwap();
[email protected]894e8fc2012-02-24 13:29:50691}
692
693void Compositor::OnSwapBuffersAborted() {
[email protected]f79729062013-04-03 20:01:50694 if (!g_compositor_thread) {
695 DCHECK_GE(1, posted_swaps_->NumSwapsPosted(DRAW_SWAP));
[email protected]337bd042012-11-05 23:43:43696
[email protected]f79729062013-04-03 20:01:50697 // We've just lost the context, so unwind all posted_swaps.
698 while (posted_swaps_->AreSwapsPosted()) {
699 if (posted_swaps_->NextPostedSwap() == DRAW_SWAP)
700 NotifyEnd();
701 posted_swaps_->EndSwap();
702 }
[email protected]d912f8c2012-11-03 02:35:01703 }
[email protected]337bd042012-11-05 23:43:43704
[email protected]91f4c792012-06-06 02:21:19705 FOR_EACH_OBSERVER(CompositorObserver,
706 observer_list_,
707 OnCompositingAborted(this));
[email protected]894e8fc2012-02-24 13:29:50708}
[email protected]ab6627372012-01-29 21:22:13709
[email protected]3b6085512013-02-21 01:26:20710void Compositor::OnUpdateVSyncParameters(base::TimeTicks timebase,
711 base::TimeDelta interval) {
712 FOR_EACH_OBSERVER(CompositorObserver,
713 observer_list_,
714 OnUpdateVSyncParameters(this, timebase, interval));
715}
716
[email protected]408b5e22013-03-19 09:48:09717void Compositor::Layout() {
[email protected]d4ae80572012-06-06 23:02:06718 // We're sending damage that will be addressed during this composite
719 // cycle, so we don't need to schedule another composite to address it.
720 disable_schedule_composite_ = true;
[email protected]f78649ea2012-02-23 18:39:04721 if (root_layer_)
[email protected]cedc3952012-03-06 06:15:55722 root_layer_->SendDamagedRects();
[email protected]d4ae80572012-06-06 23:02:06723 disable_schedule_composite_ = false;
[email protected]ab6627372012-01-29 21:22:13724}
725
[email protected]ebc0e1df2013-08-01 02:46:22726scoped_ptr<cc::OutputSurface> Compositor::CreateOutputSurface(bool fallback) {
[email protected]bc90af6b2013-07-29 20:32:39727 return ContextFactory::GetInstance()->CreateOutputSurface(this);
[email protected]ab6627372012-01-29 21:22:13728}
729
[email protected]408b5e22013-03-19 09:48:09730void Compositor::DidCommit() {
[email protected]6b16679e2012-10-27 00:44:28731 DCHECK(!IsLocked());
[email protected]2700daddd2012-07-13 19:35:37732 FOR_EACH_OBSERVER(CompositorObserver,
733 observer_list_,
734 OnCompositingDidCommit(this));
735}
736
[email protected]408b5e22013-03-19 09:48:09737void Compositor::DidCommitAndDrawFrame() {
[email protected]3b6085512013-02-21 01:26:20738 base::TimeTicks start_time = base::TimeTicks::Now();
[email protected]a8f677c2012-03-23 01:36:06739 FOR_EACH_OBSERVER(CompositorObserver,
740 observer_list_,
[email protected]3b6085512013-02-21 01:26:20741 OnCompositingStarted(this, start_time));
[email protected]ba7aeb82012-02-24 23:36:13742}
743
[email protected]408b5e22013-03-19 09:48:09744void Compositor::DidCompleteSwapBuffers() {
[email protected]337bd042012-11-05 23:43:43745 DCHECK(g_compositor_thread);
[email protected]ba7aeb82012-02-24 23:36:13746 NotifyEnd();
[email protected]ab6627372012-01-29 21:22:13747}
748
[email protected]408b5e22013-03-19 09:48:09749void Compositor::ScheduleComposite() {
[email protected]d4ae80572012-06-06 23:02:06750 if (!disable_schedule_composite_)
751 ScheduleDraw();
[email protected]332749032011-10-22 00:32:46752}
753
[email protected]f10dc472013-09-27 03:31:59754scoped_refptr<cc::ContextProvider> Compositor::OffscreenContextProvider() {
755 return ContextFactory::GetInstance()->OffscreenCompositorContextProvider();
[email protected]0a451722013-02-22 20:32:05756}
757
[email protected]2e77cdbb2013-04-29 13:59:14758const cc::LayerTreeDebugState& Compositor::GetLayerTreeDebugState() const {
759 return host_->debug_state();
[email protected]918f8db42013-04-27 01:53:40760}
761
[email protected]2e77cdbb2013-04-29 13:59:14762void Compositor::SetLayerTreeDebugState(
763 const cc::LayerTreeDebugState& debug_state) {
[email protected]918f8db42013-04-27 01:53:40764 host_->SetDebugState(debug_state);
765}
766
[email protected]6b16679e2012-10-27 00:44:28767scoped_refptr<CompositorLock> Compositor::GetCompositorLock() {
768 if (!compositor_lock_) {
769 compositor_lock_ = new CompositorLock(this);
770 if (g_compositor_thread)
[email protected]804c8982013-03-13 16:32:21771 host_->SetDeferCommits(true);
[email protected]6b16679e2012-10-27 00:44:28772 FOR_EACH_OBSERVER(CompositorObserver,
773 observer_list_,
774 OnCompositingLockStateChanged(this));
775 }
776 return compositor_lock_;
777}
778
779void Compositor::UnlockCompositor() {
780 DCHECK(compositor_lock_);
781 compositor_lock_ = NULL;
782 if (g_compositor_thread)
[email protected]804c8982013-03-13 16:32:21783 host_->SetDeferCommits(false);
[email protected]6b16679e2012-10-27 00:44:28784 FOR_EACH_OBSERVER(CompositorObserver,
785 observer_list_,
786 OnCompositingLockStateChanged(this));
787}
788
789void Compositor::CancelCompositorLock() {
790 if (compositor_lock_)
791 compositor_lock_->CancelLock();
792}
793
[email protected]a8f21152011-09-08 15:30:02794void Compositor::NotifyEnd() {
[email protected]d4ae80572012-06-06 23:02:06795 last_ended_frame_++;
[email protected]a8f21152011-09-08 15:30:02796 FOR_EACH_OBSERVER(CompositorObserver,
797 observer_list_,
[email protected]3ce2feb2011-09-19 18:44:23798 OnCompositingEnded(this));
[email protected]a8f21152011-09-08 15:30:02799}
800
[email protected]c797cd42011-03-15 02:18:36801} // namespace ui