Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: ui/compositor/compositor.cc

Issue 851853002: It is time. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: Trying to reup because the last upload failed. Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « ui/compositor/compositor.h ('k') | ui/compositor/compositor.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "ui/compositor/compositor.h"
6
7 #include <algorithm>
8 #include <deque>
9
10 #include "base/bind.h"
11 #include "base/command_line.h"
12 #include "base/debug/trace_event.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/metrics/histogram.h"
15 #include "base/strings/string_util.h"
16 #include "base/sys_info.h"
17 #include "cc/base/latency_info_swap_promise.h"
18 #include "cc/base/switches.h"
19 #include "cc/input/input_handler.h"
20 #include "cc/layers/layer.h"
21 #include "cc/scheduler/begin_frame_source.h"
22 #include "cc/output/begin_frame_args.h"
23 #include "cc/output/context_provider.h"
24 #include "cc/surfaces/surface_id_allocator.h"
25 #include "cc/trees/layer_tree_host.h"
26 #include "third_party/skia/include/core/SkBitmap.h"
27 #include "ui/compositor/compositor_observer.h"
28 #include "ui/compositor/compositor_switches.h"
29 #include "ui/compositor/compositor_vsync_manager.h"
30 #include "ui/compositor/dip_util.h"
31 #include "ui/compositor/layer.h"
32 #include "ui/compositor/layer_animator_collection.h"
33 #include "ui/gfx/frame_time.h"
34 #include "ui/gl/gl_context.h"
35 #include "ui/gl/gl_switches.h"
36
37 namespace {
38
39 const double kDefaultRefreshRate = 60.0;
40 const double kTestRefreshRate = 200.0;
41
42 const int kCompositorLockTimeoutMs = 67;
43
44 } // namespace
45
46 namespace ui {
47
48 CompositorLock::CompositorLock(Compositor* compositor)
49 : compositor_(compositor) {
50 compositor_->task_runner_->PostDelayedTask(
51 FROM_HERE,
52 base::Bind(&CompositorLock::CancelLock, AsWeakPtr()),
53 base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs));
54 }
55
56 CompositorLock::~CompositorLock() {
57 CancelLock();
58 }
59
60 void CompositorLock::CancelLock() {
61 if (!compositor_)
62 return;
63 compositor_->UnlockCompositor();
64 compositor_ = NULL;
65 }
66
67 } // namespace ui
68
69 namespace {} // namespace
70
71 namespace ui {
72
73 class SatisfySwapPromise : public cc::SwapPromise {
74 public:
75 explicit SatisfySwapPromise(uint32_t id) : id_(id) {}
76
77 private:
78 void DidSwap(cc::CompositorFrameMetadata* metadata) override {
79 metadata->satisfies_sequences.push_back(id_);
80 }
81
82 void DidNotSwap(DidNotSwapReason reason) override {
83 // TODO(jbauman): Send to the SurfaceManager immediately.
84 DCHECK(false);
85 }
86 int64 TraceId() const override { return 0; }
87 uint32_t id_;
88 };
89
90 Compositor::Compositor(gfx::AcceleratedWidget widget,
91 ui::ContextFactory* context_factory,
92 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
93 : context_factory_(context_factory),
94 root_layer_(NULL),
95 widget_(widget),
96 surface_id_allocator_(context_factory->CreateSurfaceIdAllocator()),
97 surface_sequence_number_(0),
98 compositor_thread_loop_(context_factory->GetCompositorMessageLoop()),
99 task_runner_(task_runner),
100 vsync_manager_(new CompositorVSyncManager()),
101 device_scale_factor_(0.0f),
102 last_started_frame_(0),
103 last_ended_frame_(0),
104 disable_schedule_composite_(false),
105 compositor_lock_(NULL),
106 defer_draw_scheduling_(false),
107 waiting_on_compositing_end_(false),
108 draw_on_compositing_end_(false),
109 swap_state_(SWAP_NONE),
110 layer_animator_collection_(this),
111 weak_ptr_factory_(this) {
112 root_web_layer_ = cc::Layer::Create();
113
114 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
115
116 cc::LayerTreeSettings settings;
117 settings.renderer_settings.refresh_rate =
118 context_factory_->DoesCreateTestContexts()
119 ? kTestRefreshRate
120 : kDefaultRefreshRate;
121 settings.main_frame_before_activation_enabled = false;
122 settings.throttle_frame_production =
123 !command_line->HasSwitch(switches::kDisableGpuVsync);
124 #if !defined(OS_MACOSX)
125 settings.renderer_settings.partial_swap_enabled =
126 !command_line->HasSwitch(cc::switches::kUIDisablePartialSwap);
127 #endif
128 #if defined(OS_CHROMEOS)
129 settings.per_tile_painting_enabled = true;
130 #endif
131 #if defined(OS_WIN)
132 settings.disable_hi_res_timer_tasks_on_battery = true;
133 #endif
134
135 // These flags should be mirrored by renderer versions in content/renderer/.
136 settings.initial_debug_state.show_debug_borders =
137 command_line->HasSwitch(cc::switches::kUIShowCompositedLayerBorders);
138 settings.initial_debug_state.show_fps_counter =
139 command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
140 settings.initial_debug_state.show_layer_animation_bounds_rects =
141 command_line->HasSwitch(cc::switches::kUIShowLayerAnimationBounds);
142 settings.initial_debug_state.show_paint_rects =
143 command_line->HasSwitch(switches::kUIShowPaintRects);
144 settings.initial_debug_state.show_property_changed_rects =
145 command_line->HasSwitch(cc::switches::kUIShowPropertyChangedRects);
146 settings.initial_debug_state.show_surface_damage_rects =
147 command_line->HasSwitch(cc::switches::kUIShowSurfaceDamageRects);
148 settings.initial_debug_state.show_screen_space_rects =
149 command_line->HasSwitch(cc::switches::kUIShowScreenSpaceRects);
150 settings.initial_debug_state.show_replica_screen_space_rects =
151 command_line->HasSwitch(cc::switches::kUIShowReplicaScreenSpaceRects);
152 settings.initial_debug_state.show_occluding_rects =
153 command_line->HasSwitch(cc::switches::kUIShowOccludingRects);
154 settings.initial_debug_state.show_non_occluding_rects =
155 command_line->HasSwitch(cc::switches::kUIShowNonOccludingRects);
156
157 settings.initial_debug_state.SetRecordRenderingStats(
158 command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking));
159
160 settings.impl_side_painting = IsUIImplSidePaintingEnabled();
161 settings.use_zero_copy = IsUIZeroCopyEnabled();
162 settings.single_thread_proxy_scheduler = false;
163
164 base::TimeTicks before_create = base::TimeTicks::Now();
165 if (compositor_thread_loop_.get()) {
166 host_ = cc::LayerTreeHost::CreateThreaded(
167 this,
168 context_factory_->GetSharedBitmapManager(),
169 context_factory_->GetGpuMemoryBufferManager(),
170 settings,
171 task_runner_,
172 compositor_thread_loop_,
173 nullptr);
174 } else {
175 host_ = cc::LayerTreeHost::CreateSingleThreaded(
176 this,
177 this,
178 context_factory_->GetSharedBitmapManager(),
179 context_factory_->GetGpuMemoryBufferManager(),
180 settings,
181 task_runner_,
182 nullptr);
183 }
184 UMA_HISTOGRAM_TIMES("GPU.CreateBrowserCompositor",
185 base::TimeTicks::Now() - before_create);
186 host_->SetRootLayer(root_web_layer_);
187 host_->SetLayerTreeHostClientReady();
188 }
189
190 Compositor::~Compositor() {
191 TRACE_EVENT0("shutdown", "Compositor::destructor");
192
193 CancelCompositorLock();
194 DCHECK(!compositor_lock_);
195
196 if (root_layer_)
197 root_layer_->SetCompositor(NULL);
198
199 // Stop all outstanding draws before telling the ContextFactory to tear
200 // down any contexts that the |host_| may rely upon.
201 host_.reset();
202
203 context_factory_->RemoveCompositor(this);
204 }
205
206 void Compositor::SetOutputSurface(scoped_ptr<cc::OutputSurface> surface) {
207 host_->SetOutputSurface(surface.Pass());
208 }
209
210 void Compositor::ScheduleDraw() {
211 if (compositor_thread_loop_.get()) {
212 host_->SetNeedsCommit();
213 } else if (!defer_draw_scheduling_) {
214 defer_draw_scheduling_ = true;
215 task_runner_->PostTask(
216 FROM_HERE,
217 base::Bind(&Compositor::Draw, weak_ptr_factory_.GetWeakPtr()));
218 }
219 }
220
221 void Compositor::DidInitializeOutputSurface() {
222 }
223
224 void Compositor::DidFailToInitializeOutputSurface() {
225 NOTREACHED() << "We don't support fallback";
226 }
227
228 void Compositor::SetRootLayer(Layer* root_layer) {
229 if (root_layer_ == root_layer)
230 return;
231 if (root_layer_)
232 root_layer_->SetCompositor(NULL);
233 root_layer_ = root_layer;
234 if (root_layer_ && !root_layer_->GetCompositor())
235 root_layer_->SetCompositor(this);
236 root_web_layer_->RemoveAllChildren();
237 if (root_layer_)
238 root_web_layer_->AddChild(root_layer_->cc_layer());
239 }
240
241 void Compositor::SetHostHasTransparentBackground(
242 bool host_has_transparent_background) {
243 host_->set_has_transparent_background(host_has_transparent_background);
244 }
245
246 void Compositor::Draw() {
247 DCHECK(!compositor_thread_loop_.get());
248
249 defer_draw_scheduling_ = false;
250 if (waiting_on_compositing_end_) {
251 draw_on_compositing_end_ = true;
252 return;
253 }
254 if (!root_layer_)
255 return;
256
257 TRACE_EVENT_ASYNC_BEGIN0("ui", "Compositor::Draw", last_started_frame_ + 1);
258
259 DCHECK_NE(swap_state_, SWAP_POSTED);
260 swap_state_ = SWAP_NONE;
261
262 waiting_on_compositing_end_ = true;
263 last_started_frame_++;
264 if (!IsLocked()) {
265 // TODO(nduca): Temporary while compositor calls
266 // compositeImmediately() directly.
267 cc::BeginFrameArgs args = cc::BeginFrameArgs::Create(
268 BEGINFRAME_FROM_HERE, gfx::FrameTime::Now(), base::TimeTicks(),
269 cc::BeginFrameArgs::DefaultInterval(), cc::BeginFrameArgs::SYNCHRONOUS);
270 BeginMainFrame(args);
271 host_->Composite(args.frame_time);
272 }
273 if (swap_state_ == SWAP_NONE)
274 NotifyEnd();
275 }
276
277 void Compositor::ScheduleFullRedraw() {
278 host_->SetNeedsRedraw();
279 }
280
281 void Compositor::ScheduleRedrawRect(const gfx::Rect& damage_rect) {
282 host_->SetNeedsRedrawRect(damage_rect);
283 }
284
285 void Compositor::FinishAllRendering() {
286 host_->FinishAllRendering();
287 }
288
289 void Compositor::SetLatencyInfo(const ui::LatencyInfo& latency_info) {
290 scoped_ptr<cc::SwapPromise> swap_promise(
291 new cc::LatencyInfoSwapPromise(latency_info));
292 host_->QueueSwapPromise(swap_promise.Pass());
293 }
294
295 void Compositor::SetScaleAndSize(float scale, const gfx::Size& size_in_pixel) {
296 DCHECK_GT(scale, 0);
297 if (!size_in_pixel.IsEmpty()) {
298 size_ = size_in_pixel;
299 host_->SetViewportSize(size_in_pixel);
300 root_web_layer_->SetBounds(size_in_pixel);
301 }
302 if (device_scale_factor_ != scale) {
303 device_scale_factor_ = scale;
304 host_->SetDeviceScaleFactor(scale);
305 if (root_layer_)
306 root_layer_->OnDeviceScaleFactorChanged(scale);
307 }
308 }
309
310 void Compositor::SetBackgroundColor(SkColor color) {
311 host_->set_background_color(color);
312 ScheduleDraw();
313 }
314
315 void Compositor::SetVisible(bool visible) {
316 host_->SetVisible(visible);
317 }
318
319 scoped_refptr<CompositorVSyncManager> Compositor::vsync_manager() const {
320 return vsync_manager_;
321 }
322
323 void Compositor::AddObserver(CompositorObserver* observer) {
324 #if defined(OS_MACOSX)
325 // Debugging instrumentation for crbug.com/401630.
326 // TODO(ccameron): remove this.
327 CHECK(observer);
328 if (!observer_list_.HasObserver(observer))
329 observer->observing_count_ += 1;
330 #endif
331
332 observer_list_.AddObserver(observer);
333 }
334
335 void Compositor::RemoveObserver(CompositorObserver* observer) {
336 #if defined(OS_MACOSX)
337 // Debugging instrumentation for crbug.com/401630.
338 // TODO(ccameron): remove this.
339 if (observer_list_.HasObserver(observer))
340 observer->observing_count_ -= 1;
341 #endif
342
343 observer_list_.RemoveObserver(observer);
344 }
345
346 bool Compositor::HasObserver(CompositorObserver* observer) {
347 return observer_list_.HasObserver(observer);
348 }
349
350 void Compositor::AddAnimationObserver(CompositorAnimationObserver* observer) {
351 animation_observer_list_.AddObserver(observer);
352 host_->SetNeedsAnimate();
353 }
354
355 void Compositor::RemoveAnimationObserver(
356 CompositorAnimationObserver* observer) {
357 animation_observer_list_.RemoveObserver(observer);
358 }
359
360 bool Compositor::HasAnimationObserver(CompositorAnimationObserver* observer) {
361 return animation_observer_list_.HasObserver(observer);
362 }
363
364 void Compositor::BeginMainFrame(const cc::BeginFrameArgs& args) {
365 FOR_EACH_OBSERVER(CompositorAnimationObserver,
366 animation_observer_list_,
367 OnAnimationStep(args.frame_time));
368 if (animation_observer_list_.might_have_observers())
369 host_->SetNeedsAnimate();
370 }
371
372 void Compositor::Layout() {
373 // We're sending damage that will be addressed during this composite
374 // cycle, so we don't need to schedule another composite to address it.
375 disable_schedule_composite_ = true;
376 if (root_layer_)
377 root_layer_->SendDamagedRects();
378 disable_schedule_composite_ = false;
379 }
380
381 void Compositor::RequestNewOutputSurface() {
382 bool fallback = false;
383 context_factory_->CreateOutputSurface(weak_ptr_factory_.GetWeakPtr(),
384 fallback);
385 }
386
387 void Compositor::DidCommit() {
388 DCHECK(!IsLocked());
389 FOR_EACH_OBSERVER(CompositorObserver,
390 observer_list_,
391 OnCompositingDidCommit(this));
392 }
393
394 void Compositor::DidCommitAndDrawFrame() {
395 base::TimeTicks start_time = gfx::FrameTime::Now();
396 FOR_EACH_OBSERVER(CompositorObserver,
397 observer_list_,
398 OnCompositingStarted(this, start_time));
399 }
400
401 void Compositor::DidCompleteSwapBuffers() {
402 if (compositor_thread_loop_.get()) {
403 NotifyEnd();
404 } else {
405 DCHECK_EQ(swap_state_, SWAP_POSTED);
406 NotifyEnd();
407 swap_state_ = SWAP_COMPLETED;
408 }
409 }
410
411 void Compositor::ScheduleComposite() {
412 if (!disable_schedule_composite_)
413 ScheduleDraw();
414 }
415
416 void Compositor::ScheduleAnimation() {
417 ScheduleComposite();
418 }
419
420 void Compositor::DidPostSwapBuffers() {
421 DCHECK(!compositor_thread_loop_.get());
422 DCHECK_EQ(swap_state_, SWAP_NONE);
423 swap_state_ = SWAP_POSTED;
424 }
425
426 void Compositor::DidAbortSwapBuffers() {
427 if (!compositor_thread_loop_.get()) {
428 if (swap_state_ == SWAP_POSTED) {
429 NotifyEnd();
430 swap_state_ = SWAP_COMPLETED;
431 }
432 }
433
434 FOR_EACH_OBSERVER(CompositorObserver,
435 observer_list_,
436 OnCompositingAborted(this));
437 }
438
439 const cc::LayerTreeDebugState& Compositor::GetLayerTreeDebugState() const {
440 return host_->debug_state();
441 }
442
443 void Compositor::SetLayerTreeDebugState(
444 const cc::LayerTreeDebugState& debug_state) {
445 host_->SetDebugState(debug_state);
446 }
447
448 cc::SurfaceSequence Compositor::InsertSurfaceSequenceForNextFrame() {
449 cc::SurfaceSequence sequence;
450 sequence.id_namespace = surface_id_allocator_->id_namespace();
451 sequence.sequence = ++surface_sequence_number_;
452 scoped_ptr<cc::SwapPromise> promise(
453 new SatisfySwapPromise(surface_sequence_number_));
454 host_->QueueSwapPromise(promise.Pass());
455 return sequence;
456 }
457
458 scoped_refptr<CompositorLock> Compositor::GetCompositorLock() {
459 if (!compositor_lock_) {
460 compositor_lock_ = new CompositorLock(this);
461 if (compositor_thread_loop_.get())
462 host_->SetDeferCommits(true);
463 FOR_EACH_OBSERVER(CompositorObserver,
464 observer_list_,
465 OnCompositingLockStateChanged(this));
466 }
467 return compositor_lock_;
468 }
469
470 void Compositor::UnlockCompositor() {
471 DCHECK(compositor_lock_);
472 compositor_lock_ = NULL;
473 if (compositor_thread_loop_.get())
474 host_->SetDeferCommits(false);
475 FOR_EACH_OBSERVER(CompositorObserver,
476 observer_list_,
477 OnCompositingLockStateChanged(this));
478 }
479
480 void Compositor::CancelCompositorLock() {
481 if (compositor_lock_)
482 compositor_lock_->CancelLock();
483 }
484
485 void Compositor::NotifyEnd() {
486 last_ended_frame_++;
487 TRACE_EVENT_ASYNC_END0("ui", "Compositor::Draw", last_ended_frame_);
488 waiting_on_compositing_end_ = false;
489 if (draw_on_compositing_end_) {
490 draw_on_compositing_end_ = false;
491
492 // Call ScheduleDraw() instead of Draw() in order to allow other
493 // CompositorObservers to be notified before starting another
494 // draw cycle.
495 ScheduleDraw();
496 }
497 FOR_EACH_OBSERVER(
498 CompositorObserver, observer_list_, OnCompositingEnded(this));
499 }
500
501 } // namespace ui
OLDNEW
« no previous file with comments | « ui/compositor/compositor.h ('k') | ui/compositor/compositor.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698