blob: d3b801cbc84f248602213fc97e1b54f652b7cbc1 [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]6b16679e2012-10-27 00:44:2813#include "base/message_loop.h"
[email protected]06666c02013-03-07 19:32:3014#include "base/string_util.h"
[email protected]ec05af52012-11-21 23:07:0015#include "base/threading/thread.h"
[email protected]894e8fc2012-02-24 13:29:5016#include "base/threading/thread_restrictions.h"
[email protected]4d5e6762013-03-19 18:46:5717#include "cc/base/switches.h"
[email protected]681ccff2013-03-18 06:13:5218#include "cc/base/thread_impl.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]0a451722013-02-22 20:32:0534#include "webkit/gpu/grcontext_for_webgraphicscontext3d.h"
[email protected]ab6627372012-01-29 21:22:1335#include "webkit/gpu/webgraphicscontext3d_in_process_impl.h"
36
[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;
175 context3d_.reset(factory_->CreateOffscreenContext());
176 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) {
204 return new cc::OutputSurface(
205 make_scoped_ptr(CreateContextCommon(compositor, false)));
206}
207
208WebKit::WebGraphicsContext3D* DefaultContextFactory::CreateOffscreenContext() {
209 return CreateContextCommon(NULL, true);
210}
211
[email protected]0a451722013-02-22 20:32:05212scoped_refptr<cc::ContextProvider>
213DefaultContextFactory::OffscreenContextProviderForMainThread() {
214 if (!offscreen_contexts_main_thread_ ||
215 !offscreen_contexts_main_thread_->DestroyedOnMainThread()) {
[email protected]40034cf2013-03-13 05:05:37216 offscreen_contexts_main_thread_ =
[email protected]e06e1122013-03-15 17:12:38217 ContextProviderFromContextFactory::Create(this);
218 if (offscreen_contexts_main_thread_ &&
219 !offscreen_contexts_main_thread_->BindToCurrentThread())
220 offscreen_contexts_main_thread_ = NULL;
[email protected]0a451722013-02-22 20:32:05221 }
222 return offscreen_contexts_main_thread_;
223}
224
225scoped_refptr<cc::ContextProvider>
226DefaultContextFactory::OffscreenContextProviderForCompositorThread() {
227 if (!offscreen_contexts_compositor_thread_ ||
228 !offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) {
[email protected]40034cf2013-03-13 05:05:37229 offscreen_contexts_compositor_thread_ =
[email protected]e06e1122013-03-15 17:12:38230 ContextProviderFromContextFactory::Create(this);
[email protected]0a451722013-02-22 20:32:05231 }
232 return offscreen_contexts_compositor_thread_;
233}
234
[email protected]84dba8ca2012-04-10 03:27:39235void DefaultContextFactory::RemoveCompositor(Compositor* compositor) {
236}
237
238WebKit::WebGraphicsContext3D* DefaultContextFactory::CreateContextCommon(
239 Compositor* compositor,
240 bool offscreen) {
[email protected]b18ed0aa2012-08-22 04:20:20241 DCHECK(offscreen || compositor);
[email protected]894e8fc2012-02-24 13:29:50242 WebKit::WebGraphicsContext3D::Attributes attrs;
[email protected]b63dce52012-08-22 22:51:50243 attrs.depth = false;
244 attrs.stencil = false;
245 attrs.antialias = false;
[email protected]894e8fc2012-02-24 13:29:50246 attrs.shareResources = true;
247 WebKit::WebGraphicsContext3D* context =
[email protected]84dba8ca2012-04-10 03:27:39248 offscreen ?
249 webkit::gpu::WebGraphicsContext3DInProcessImpl::CreateForWebView(
250 attrs, false) :
[email protected]894e8fc2012-02-24 13:29:50251 webkit::gpu::WebGraphicsContext3DInProcessImpl::CreateForWindow(
[email protected]40034cf2013-03-13 05:05:37252 attrs, compositor->widget(), NULL);
[email protected]69b8e8f2012-06-18 02:42:59253 if (!context)
254 return NULL;
255
[email protected]894e8fc2012-02-24 13:29:50256 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]8fcaffb2012-05-25 23:19:00257 if (!offscreen) {
[email protected]894e8fc2012-02-24 13:29:50258 context->makeContextCurrent();
259 gfx::GLContext* gl_context = gfx::GLContext::GetCurrent();
[email protected]cc2ae012012-09-21 19:35:25260 bool vsync = !command_line->HasSwitch(switches::kDisableGpuVsync);
[email protected]8fcaffb2012-05-25 23:19:00261 gl_context->SetSwapInterval(vsync ? 1 : 0);
[email protected]894e8fc2012-02-24 13:29:50262 gl_context->ReleaseCurrent(NULL);
263 }
264 return context;
[email protected]ab6627372012-01-29 21:22:13265}
266
[email protected]e06e1122013-03-15 17:12:38267TestContextFactory::TestContextFactory() {}
[email protected]40034cf2013-03-13 05:05:37268
[email protected]e06e1122013-03-15 17:12:38269TestContextFactory::~TestContextFactory() {}
[email protected]40034cf2013-03-13 05:05:37270
271cc::OutputSurface* TestContextFactory::CreateOutputSurface(
272 Compositor* compositor) {
273 return new cc::OutputSurface(make_scoped_ptr(CreateOffscreenContext()));
274}
275
276WebKit::WebGraphicsContext3D* TestContextFactory::CreateOffscreenContext() {
277 ui::TestWebGraphicsContext3D* context = new ui::TestWebGraphicsContext3D;
278 context->Initialize();
279 return context;
280}
281
282scoped_refptr<cc::ContextProvider>
283TestContextFactory::OffscreenContextProviderForMainThread() {
[email protected]e06e1122013-03-15 17:12:38284 if (!offscreen_contexts_main_thread_ ||
285 offscreen_contexts_main_thread_->DestroyedOnMainThread()) {
286 offscreen_contexts_main_thread_ =
287 ContextProviderFromContextFactory::Create(this);
288 CHECK(offscreen_contexts_main_thread_->BindToCurrentThread());
289 }
[email protected]40034cf2013-03-13 05:05:37290 return offscreen_contexts_main_thread_;
291}
292
293scoped_refptr<cc::ContextProvider>
294TestContextFactory::OffscreenContextProviderForCompositorThread() {
[email protected]e06e1122013-03-15 17:12:38295 if (!offscreen_contexts_compositor_thread_ ||
296 offscreen_contexts_compositor_thread_->DestroyedOnMainThread()) {
297 offscreen_contexts_compositor_thread_ =
298 ContextProviderFromContextFactory::Create(this);
299 }
[email protected]40034cf2013-03-13 05:05:37300 return offscreen_contexts_compositor_thread_;
301}
302
303void TestContextFactory::RemoveCompositor(Compositor* compositor) {
304}
305
[email protected]d3407cdb2012-09-21 22:33:25306Texture::Texture(bool flipped, const gfx::Size& size, float device_scale_factor)
[email protected]34466d02012-12-10 18:00:34307 : size_(size),
308 flipped_(flipped),
[email protected]d3407cdb2012-09-21 22:33:25309 device_scale_factor_(device_scale_factor) {
[email protected]ab6627372012-01-29 21:22:13310}
311
312Texture::~Texture() {
313}
314
[email protected]06666c02013-03-07 19:32:30315std::string Texture::Produce() {
316 return EmptyString();
[email protected]f027ca1502012-12-21 01:42:32317}
318
[email protected]6b16679e2012-10-27 00:44:28319CompositorLock::CompositorLock(Compositor* compositor)
320 : compositor_(compositor) {
321 MessageLoop::current()->PostDelayedTask(
322 FROM_HERE,
323 base::Bind(&CompositorLock::CancelLock, AsWeakPtr()),
324 base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs));
325}
326
327CompositorLock::~CompositorLock() {
328 CancelLock();
329}
330
331void CompositorLock::CancelLock() {
332 if (!compositor_)
333 return;
334 compositor_->UnlockCompositor();
335 compositor_ = NULL;
336}
337
[email protected]337bd042012-11-05 23:43:43338class PostedSwapQueue {
339 public:
340 PostedSwapQueue() : pending_swap_(NULL) {
341 }
342
343 ~PostedSwapQueue() {
344 DCHECK(!pending_swap_);
345 }
346
347 SwapType NextPostedSwap() const {
348 return queue_.front();
349 }
350
351 bool AreSwapsPosted() const {
352 return !queue_.empty();
353 }
354
355 int NumSwapsPosted(SwapType type) const {
356 int count = 0;
357 for (std::deque<SwapType>::const_iterator it = queue_.begin();
358 it != queue_.end(); ++it) {
359 if (*it == type)
360 count++;
361 }
362 return count;
363 }
364
365 void PostSwap() {
366 DCHECK(pending_swap_);
367 queue_.push_back(pending_swap_->type());
368 pending_swap_->posted_ = true;
369 }
370
371 void EndSwap() {
372 queue_.pop_front();
373 }
374
375 private:
376 friend class ::PendingSwap;
377
378 PendingSwap* pending_swap_;
379 std::deque<SwapType> queue_;
380
381 DISALLOW_COPY_AND_ASSIGN(PostedSwapQueue);
382};
383
384} // namespace ui
385
386namespace {
387
388PendingSwap::PendingSwap(SwapType type, ui::PostedSwapQueue* posted_swaps)
389 : type_(type), posted_(false), posted_swaps_(posted_swaps) {
390 // Only one pending swap in flight.
391 DCHECK_EQ(static_cast<PendingSwap*>(NULL), posted_swaps_->pending_swap_);
392 posted_swaps_->pending_swap_ = this;
393}
394
395PendingSwap::~PendingSwap() {
396 DCHECK_EQ(this, posted_swaps_->pending_swap_);
397 posted_swaps_->pending_swap_ = NULL;
398}
399
400} // namespace
401
402namespace ui {
403
[email protected]ab6627372012-01-29 21:22:13404Compositor::Compositor(CompositorDelegate* delegate,
[email protected]cd9a61c72012-05-08 19:16:59405 gfx::AcceleratedWidget widget)
[email protected]82a01ac2011-09-08 16:00:18406 : delegate_(delegate),
[email protected]ab6627372012-01-29 21:22:13407 root_layer_(NULL),
408 widget_(widget),
[email protected]337bd042012-11-05 23:43:43409 posted_swaps_(new PostedSwapQueue()),
[email protected]d4ae80572012-06-06 23:02:06410 device_scale_factor_(0.0f),
411 last_started_frame_(0),
412 last_ended_frame_(0),
[email protected]8d9080ab2013-04-06 00:03:20413 next_draw_is_resize_(false),
[email protected]6b16679e2012-10-27 00:44:28414 disable_schedule_composite_(false),
415 compositor_lock_(NULL) {
[email protected]7aba6662013-03-12 10:17:34416 root_web_layer_ = cc::Layer::Create();
417 root_web_layer_->SetAnchorPoint(gfx::PointF(0.f, 0.f));
[email protected]ec05af52012-11-21 23:07:00418
[email protected]ab6627372012-01-29 21:22:13419 CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]4d5e6762013-03-19 18:46:57420
[email protected]ec05af52012-11-21 23:07:00421 cc::LayerTreeSettings settings;
[email protected]8e0176d2013-03-21 03:14:52422 settings.refresh_rate =
[email protected]8cbffc62013-01-23 22:11:09423 g_test_compositor_enabled ? kTestRefreshRate : kDefaultRefreshRate;
[email protected]8e0176d2013-03-21 03:14:52424 settings.partial_swap_enabled =
[email protected]4d5e6762013-03-19 18:46:57425 command_line->HasSwitch(cc::switches::kUIEnablePartialSwap);
[email protected]8e0176d2013-03-21 03:14:52426 settings.per_tile_painting_enabled =
[email protected]4d5e6762013-03-19 18:46:57427 command_line->HasSwitch(cc::switches::kUIEnablePerTilePainting);
428
429 // These flags should be mirrored by renderer versions in content/renderer/.
[email protected]8e0176d2013-03-21 03:14:52430 settings.initial_debug_state.show_debug_borders =
[email protected]4d5e6762013-03-19 18:46:57431 command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders);
[email protected]8e0176d2013-03-21 03:14:52432 settings.initial_debug_state.show_fps_counter =
[email protected]4d5e6762013-03-19 18:46:57433 command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
[email protected]8e0176d2013-03-21 03:14:52434 settings.initial_debug_state.show_paint_rects =
[email protected]4d5e6762013-03-19 18:46:57435 command_line->HasSwitch(switches::kUIShowPaintRects);
[email protected]8e0176d2013-03-21 03:14:52436 settings.initial_debug_state.show_platform_layer_tree =
[email protected]4d5e6762013-03-19 18:46:57437 command_line->HasSwitch(cc::switches::kUIShowCompositedLayerTree);
[email protected]8e0176d2013-03-21 03:14:52438 settings.initial_debug_state.show_property_changed_rects =
[email protected]4d5e6762013-03-19 18:46:57439 command_line->HasSwitch(cc::switches::kUIShowPropertyChangedRects);
[email protected]8e0176d2013-03-21 03:14:52440 settings.initial_debug_state.show_surface_damage_rects =
[email protected]4d5e6762013-03-19 18:46:57441 command_line->HasSwitch(cc::switches::kUIShowSurfaceDamageRects);
[email protected]8e0176d2013-03-21 03:14:52442 settings.initial_debug_state.show_screen_space_rects =
[email protected]4d5e6762013-03-19 18:46:57443 command_line->HasSwitch(cc::switches::kUIShowScreenSpaceRects);
[email protected]8e0176d2013-03-21 03:14:52444 settings.initial_debug_state.show_replica_screen_space_rects =
[email protected]4d5e6762013-03-19 18:46:57445 command_line->HasSwitch(cc::switches::kUIShowReplicaScreenSpaceRects);
[email protected]8e0176d2013-03-21 03:14:52446 settings.initial_debug_state.show_occluding_rects =
[email protected]4d5e6762013-03-19 18:46:57447 command_line->HasSwitch(cc::switches::kUIShowOccludingRects);
[email protected]8e0176d2013-03-21 03:14:52448 settings.initial_debug_state.show_non_occluding_rects =
[email protected]4d5e6762013-03-19 18:46:57449 command_line->HasSwitch(cc::switches::kUIShowNonOccludingRects);
[email protected]302fe422012-06-11 14:49:11450
[email protected]ec05af52012-11-21 23:07:00451 scoped_ptr<cc::Thread> thread;
452 if (g_compositor_thread) {
[email protected]a5069b572013-03-17 21:50:42453 thread = cc::ThreadImpl::CreateForDifferentThread(
[email protected]ec05af52012-11-21 23:07:00454 g_compositor_thread->message_loop_proxy());
455 }
456
[email protected]804c8982013-03-13 16:32:21457 host_ = cc::LayerTreeHost::Create(this, settings, thread.Pass());
458 host_->SetRootLayer(root_web_layer_);
459 host_->SetSurfaceReady();
[email protected]82a01ac2011-09-08 16:00:18460}
461
462Compositor::~Compositor() {
[email protected]6b16679e2012-10-27 00:44:28463 CancelCompositorLock();
464 DCHECK(!compositor_lock_);
465
[email protected]e332a1b2012-05-10 20:32:27466 // Don't call |CompositorDelegate::ScheduleDraw| from this point.
467 delegate_ = NULL;
[email protected]7ab3f272011-11-16 00:51:56468 if (root_layer_)
469 root_layer_->SetCompositor(NULL);
[email protected]2700daddd2012-07-13 19:35:37470
471 // Stop all outstanding draws before telling the ContextFactory to tear
472 // down any contexts that the |host_| may rely upon.
473 host_.reset();
474
[email protected]40034cf2013-03-13 05:05:37475 ContextFactory::GetInstance()->RemoveCompositor(this);
[email protected]82a01ac2011-09-08 16:00:18476}
477
[email protected]44ed4bd2013-04-06 00:11:27478// static
[email protected]ab6627372012-01-29 21:22:13479void Compositor::Initialize(bool use_thread) {
[email protected]ec05af52012-11-21 23:07:00480 if (use_thread) {
481 g_compositor_thread = new base::Thread("Browser Compositor");
482 g_compositor_thread->Start();
483 }
[email protected]ab6627372012-01-29 21:22:13484}
485
[email protected]44ed4bd2013-04-06 00:11:27486// static
487bool Compositor::WasInitializedWithThread() {
488 return !!g_compositor_thread;
489}
490
491// static
[email protected]ab6627372012-01-29 21:22:13492void Compositor::Terminate() {
[email protected]ab6627372012-01-29 21:22:13493 if (g_compositor_thread) {
[email protected]ec05af52012-11-21 23:07:00494 g_compositor_thread->Stop();
[email protected]ab6627372012-01-29 21:22:13495 delete g_compositor_thread;
496 g_compositor_thread = NULL;
497 }
498}
499
[email protected]332749032011-10-22 00:32:46500void Compositor::ScheduleDraw() {
[email protected]4ea4e2d2012-11-20 15:17:09501 if (g_compositor_thread)
[email protected]f0c2a242013-03-15 19:34:52502 host_->Composite(base::TimeTicks::Now());
[email protected]4ea4e2d2012-11-20 15:17:09503 else if (delegate_)
[email protected]ab6627372012-01-29 21:22:13504 delegate_->ScheduleDraw();
[email protected]332749032011-10-22 00:32:46505}
506
[email protected]993d6b322011-09-27 19:14:38507void Compositor::SetRootLayer(Layer* root_layer) {
[email protected]12233c362011-11-21 16:09:25508 if (root_layer_ == root_layer)
509 return;
[email protected]7ab3f272011-11-16 00:51:56510 if (root_layer_)
511 root_layer_->SetCompositor(NULL);
[email protected]993d6b322011-09-27 19:14:38512 root_layer_ = root_layer;
[email protected]7ab3f272011-11-16 00:51:56513 if (root_layer_ && !root_layer_->GetCompositor())
[email protected]993d6b322011-09-27 19:14:38514 root_layer_->SetCompositor(this);
[email protected]7aba6662013-03-12 10:17:34515 root_web_layer_->RemoveAllChildren();
[email protected]66efabe2012-08-18 03:06:06516 if (root_layer_)
[email protected]7aba6662013-03-12 10:17:34517 root_web_layer_->AddChild(root_layer_->cc_layer());
[email protected]993d6b322011-09-27 19:14:38518}
519
[email protected]ebd52522012-10-04 15:49:40520void Compositor::SetHostHasTransparentBackground(
521 bool host_has_transparent_background) {
[email protected]804c8982013-03-13 16:32:21522 host_->set_has_transparent_background(host_has_transparent_background);
[email protected]ebd52522012-10-04 15:49:40523}
524
[email protected]ed8de92d2011-09-14 04:16:48525void Compositor::Draw(bool force_clear) {
[email protected]337bd042012-11-05 23:43:43526 DCHECK(!g_compositor_thread);
527
[email protected]ed8de92d2011-09-14 04:16:48528 if (!root_layer_)
529 return;
530
[email protected]d4ae80572012-06-06 23:02:06531 last_started_frame_++;
[email protected]337bd042012-11-05 23:43:43532 PendingSwap pending_swap(DRAW_SWAP, posted_swaps_.get());
533 if (!IsLocked()) {
[email protected]6b16679e2012-10-27 00:44:28534 // TODO(nduca): Temporary while compositor calls
535 // compositeImmediately() directly.
[email protected]408b5e22013-03-19 09:48:09536 Layout();
[email protected]f0c2a242013-03-15 19:34:52537 host_->Composite(base::TimeTicks::Now());
[email protected]8d9080ab2013-04-06 00:03:20538
539#if defined(OS_WIN)
540 // While we resize, we are usually a few frames behind. By blocking
541 // the UI thread here we minize the area that is mis-painted, specially
542 // in the non-client area. See RenderWidgetHostViewAura::SetBounds for
543 // more details and bug 177115.
544 if (next_draw_is_resize_ && (last_ended_frame_ > 1)) {
545 next_draw_is_resize_ = false;
546 host_->FinishAllRendering();
547 }
548#endif
549
[email protected]6b16679e2012-10-27 00:44:28550 }
[email protected]337bd042012-11-05 23:43:43551 if (!pending_swap.posted())
[email protected]1920930592012-01-11 14:54:48552 NotifyEnd();
[email protected]ab6627372012-01-29 21:22:13553}
554
[email protected]7df588fbd2012-02-10 14:15:56555void Compositor::ScheduleFullDraw() {
[email protected]804c8982013-03-13 16:32:21556 host_->SetNeedsRedraw();
[email protected]7df588fbd2012-02-10 14:15:56557}
558
[email protected]cd9a61c72012-05-08 19:16:59559bool Compositor::ReadPixels(SkBitmap* bitmap,
560 const gfx::Rect& bounds_in_pixel) {
561 if (bounds_in_pixel.right() > size().width() ||
562 bounds_in_pixel.bottom() > size().height())
[email protected]ab6627372012-01-29 21:22:13563 return false;
[email protected]ab6627372012-01-29 21:22:13564 bitmap->setConfig(SkBitmap::kARGB_8888_Config,
[email protected]cd9a61c72012-05-08 19:16:59565 bounds_in_pixel.width(), bounds_in_pixel.height());
[email protected]ab6627372012-01-29 21:22:13566 bitmap->allocPixels();
567 SkAutoLockPixels lock_image(*bitmap);
568 unsigned char* pixels = static_cast<unsigned char*>(bitmap->getPixels());
[email protected]6b16679e2012-10-27 00:44:28569 CancelCompositorLock();
[email protected]337bd042012-11-05 23:43:43570 PendingSwap pending_swap(READPIXELS_SWAP, posted_swaps_.get());
[email protected]804c8982013-03-13 16:32:21571 return host_->CompositeAndReadback(pixels, bounds_in_pixel);
[email protected]ab6627372012-01-29 21:22:13572}
573
[email protected]cd9a61c72012-05-08 19:16:59574void Compositor::SetScaleAndSize(float scale, const gfx::Size& size_in_pixel) {
[email protected]cff176a2012-06-29 21:11:00575 DCHECK_GT(scale, 0);
[email protected]351b8ce2012-11-27 23:37:16576 if (!size_in_pixel.IsEmpty()) {
577 size_ = size_in_pixel;
[email protected]804c8982013-03-13 16:32:21578 host_->SetViewportSize(size_in_pixel, size_in_pixel);
[email protected]7aba6662013-03-12 10:17:34579 root_web_layer_->SetBounds(size_in_pixel);
[email protected]8d9080ab2013-04-06 00:03:20580
581 next_draw_is_resize_ = true;
[email protected]351b8ce2012-11-27 23:37:16582 }
[email protected]2e2216e42012-05-17 15:17:00583 if (device_scale_factor_ != scale) {
[email protected]cd9a61c72012-05-08 19:16:59584 device_scale_factor_ = scale;
585 if (root_layer_)
586 root_layer_->OnDeviceScaleFactorChanged(scale);
587 }
[email protected]ed8de92d2011-09-14 04:16:48588}
589
[email protected]87601922013-04-02 03:56:42590void Compositor::SetBackgroundColor(SkColor color) {
591 host_->set_background_color(color);
592 ScheduleDraw();
593}
594
[email protected]ed8de92d2011-09-14 04:16:48595void Compositor::AddObserver(CompositorObserver* observer) {
596 observer_list_.AddObserver(observer);
597}
598
599void Compositor::RemoveObserver(CompositorObserver* observer) {
600 observer_list_.RemoveObserver(observer);
601}
602
[email protected]3ce2feb2011-09-19 18:44:23603bool Compositor::HasObserver(CompositorObserver* observer) {
604 return observer_list_.HasObserver(observer);
605}
606
[email protected]894e8fc2012-02-24 13:29:50607void Compositor::OnSwapBuffersPosted() {
[email protected]337bd042012-11-05 23:43:43608 DCHECK(!g_compositor_thread);
609 posted_swaps_->PostSwap();
[email protected]894e8fc2012-02-24 13:29:50610}
611
612void Compositor::OnSwapBuffersComplete() {
[email protected]337bd042012-11-05 23:43:43613 DCHECK(!g_compositor_thread);
614 DCHECK(posted_swaps_->AreSwapsPosted());
615 DCHECK_GE(1, posted_swaps_->NumSwapsPosted(DRAW_SWAP));
616 if (posted_swaps_->NextPostedSwap() == DRAW_SWAP)
617 NotifyEnd();
618 posted_swaps_->EndSwap();
[email protected]894e8fc2012-02-24 13:29:50619}
620
621void Compositor::OnSwapBuffersAborted() {
[email protected]f79729062013-04-03 20:01:50622 if (!g_compositor_thread) {
623 DCHECK_GE(1, posted_swaps_->NumSwapsPosted(DRAW_SWAP));
[email protected]337bd042012-11-05 23:43:43624
[email protected]f79729062013-04-03 20:01:50625 // We've just lost the context, so unwind all posted_swaps.
626 while (posted_swaps_->AreSwapsPosted()) {
627 if (posted_swaps_->NextPostedSwap() == DRAW_SWAP)
628 NotifyEnd();
629 posted_swaps_->EndSwap();
630 }
[email protected]d912f8c2012-11-03 02:35:01631 }
[email protected]337bd042012-11-05 23:43:43632
[email protected]91f4c792012-06-06 02:21:19633 FOR_EACH_OBSERVER(CompositorObserver,
634 observer_list_,
635 OnCompositingAborted(this));
[email protected]894e8fc2012-02-24 13:29:50636}
[email protected]ab6627372012-01-29 21:22:13637
[email protected]3b6085512013-02-21 01:26:20638void Compositor::OnUpdateVSyncParameters(base::TimeTicks timebase,
639 base::TimeDelta interval) {
640 FOR_EACH_OBSERVER(CompositorObserver,
641 observer_list_,
642 OnUpdateVSyncParameters(this, timebase, interval));
643}
644
[email protected]408b5e22013-03-19 09:48:09645void Compositor::Layout() {
[email protected]d4ae80572012-06-06 23:02:06646 // We're sending damage that will be addressed during this composite
647 // cycle, so we don't need to schedule another composite to address it.
648 disable_schedule_composite_ = true;
[email protected]f78649ea2012-02-23 18:39:04649 if (root_layer_)
[email protected]cedc3952012-03-06 06:15:55650 root_layer_->SendDamagedRects();
[email protected]d4ae80572012-06-06 23:02:06651 disable_schedule_composite_ = false;
[email protected]ab6627372012-01-29 21:22:13652}
653
[email protected]408b5e22013-03-19 09:48:09654scoped_ptr<cc::OutputSurface> Compositor::CreateOutputSurface() {
[email protected]40034cf2013-03-13 05:05:37655 return make_scoped_ptr(
656 ContextFactory::GetInstance()->CreateOutputSurface(this));
[email protected]ab6627372012-01-29 21:22:13657}
658
[email protected]408b5e22013-03-19 09:48:09659scoped_ptr<cc::InputHandler> Compositor::CreateInputHandler() {
[email protected]ec05af52012-11-21 23:07:00660 return scoped_ptr<cc::InputHandler>();
661}
662
[email protected]408b5e22013-03-19 09:48:09663void Compositor::DidCommit() {
[email protected]6b16679e2012-10-27 00:44:28664 DCHECK(!IsLocked());
[email protected]2700daddd2012-07-13 19:35:37665 FOR_EACH_OBSERVER(CompositorObserver,
666 observer_list_,
667 OnCompositingDidCommit(this));
668}
669
[email protected]408b5e22013-03-19 09:48:09670void Compositor::DidCommitAndDrawFrame() {
[email protected]3b6085512013-02-21 01:26:20671 base::TimeTicks start_time = base::TimeTicks::Now();
[email protected]a8f677c2012-03-23 01:36:06672 FOR_EACH_OBSERVER(CompositorObserver,
673 observer_list_,
[email protected]3b6085512013-02-21 01:26:20674 OnCompositingStarted(this, start_time));
[email protected]f79729062013-04-03 20:01:50675 // If we're threaded without a swap complete callback, we have to
676 // call DidCompleteSwapBuffersManually.
677 if (g_compositor_thread &&
678 !host_->GetRendererCapabilities().using_swap_complete_callback)
679 DidCompleteSwapBuffers();
[email protected]ba7aeb82012-02-24 23:36:13680}
681
[email protected]408b5e22013-03-19 09:48:09682void Compositor::DidCompleteSwapBuffers() {
[email protected]337bd042012-11-05 23:43:43683 DCHECK(g_compositor_thread);
[email protected]ba7aeb82012-02-24 23:36:13684 NotifyEnd();
[email protected]ab6627372012-01-29 21:22:13685}
686
[email protected]408b5e22013-03-19 09:48:09687void Compositor::ScheduleComposite() {
[email protected]d4ae80572012-06-06 23:02:06688 if (!disable_schedule_composite_)
689 ScheduleDraw();
[email protected]332749032011-10-22 00:32:46690}
691
[email protected]0a451722013-02-22 20:32:05692scoped_refptr<cc::ContextProvider>
693Compositor::OffscreenContextProviderForMainThread() {
[email protected]0a451722013-02-22 20:32:05694 return ContextFactory::GetInstance()->OffscreenContextProviderForMainThread();
695}
696
697scoped_refptr<cc::ContextProvider>
698Compositor::OffscreenContextProviderForCompositorThread() {
[email protected]0a451722013-02-22 20:32:05699 return ContextFactory::GetInstance()->
700 OffscreenContextProviderForCompositorThread();
701}
702
[email protected]6b16679e2012-10-27 00:44:28703scoped_refptr<CompositorLock> Compositor::GetCompositorLock() {
704 if (!compositor_lock_) {
705 compositor_lock_ = new CompositorLock(this);
706 if (g_compositor_thread)
[email protected]804c8982013-03-13 16:32:21707 host_->SetDeferCommits(true);
[email protected]6b16679e2012-10-27 00:44:28708 FOR_EACH_OBSERVER(CompositorObserver,
709 observer_list_,
710 OnCompositingLockStateChanged(this));
711 }
712 return compositor_lock_;
713}
714
715void Compositor::UnlockCompositor() {
716 DCHECK(compositor_lock_);
717 compositor_lock_ = NULL;
718 if (g_compositor_thread)
[email protected]804c8982013-03-13 16:32:21719 host_->SetDeferCommits(false);
[email protected]6b16679e2012-10-27 00:44:28720 FOR_EACH_OBSERVER(CompositorObserver,
721 observer_list_,
722 OnCompositingLockStateChanged(this));
723}
724
725void Compositor::CancelCompositorLock() {
726 if (compositor_lock_)
727 compositor_lock_->CancelLock();
728}
729
[email protected]a8f21152011-09-08 15:30:02730void Compositor::NotifyEnd() {
[email protected]d4ae80572012-06-06 23:02:06731 last_ended_frame_++;
[email protected]a8f21152011-09-08 15:30:02732 FOR_EACH_OBSERVER(CompositorObserver,
733 observer_list_,
[email protected]3ce2feb2011-09-19 18:44:23734 OnCompositingEnded(this));
[email protected]a8f21152011-09-08 15:30:02735}
736
[email protected]ab6627372012-01-29 21:22:13737COMPOSITOR_EXPORT void SetupTestCompositor() {
738 if (!CommandLine::ForCurrentProcess()->HasSwitch(
739 switches::kDisableTestCompositor)) {
[email protected]8cbffc62013-01-23 22:11:09740 g_test_compositor_enabled = true;
[email protected]ab6627372012-01-29 21:22:13741 }
[email protected]8391a49e2012-05-26 06:31:04742#if defined(OS_CHROMEOS)
743 // If the test is running on the chromeos envrionment (such as
744 // device or vm bots), use the real compositor.
745 if (base::chromeos::IsRunningOnChromeOS())
[email protected]8cbffc62013-01-23 22:11:09746 g_test_compositor_enabled = false;
[email protected]8391a49e2012-05-26 06:31:04747#endif
[email protected]40034cf2013-03-13 05:05:37748 ResetImplicitFactory();
[email protected]ab6627372012-01-29 21:22:13749}
750
751COMPOSITOR_EXPORT void DisableTestCompositor() {
[email protected]40034cf2013-03-13 05:05:37752 ResetImplicitFactory();
[email protected]8cbffc62013-01-23 22:11:09753 g_test_compositor_enabled = false;
[email protected]1920930592012-01-11 14:54:48754}
755
[email protected]894e8fc2012-02-24 13:29:50756COMPOSITOR_EXPORT bool IsTestCompositorEnabled() {
[email protected]8cbffc62013-01-23 22:11:09757 return g_test_compositor_enabled;
[email protected]894e8fc2012-02-24 13:29:50758}
759
[email protected]c797cd42011-03-15 02:18:36760} // namespace ui