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

Side by Side Diff: cc/output/context_cache_controller.cc

Issue 2353033003: Idle cleanup for worker context (Closed)
Patch Set: comments + feedback Created 4 years, 3 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 | « cc/output/context_cache_controller.h ('k') | cc/output/context_cache_controller_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "cc/output/context_cache_controller.h" 5 #include "cc/output/context_cache_controller.h"
6 6
7 #include "base/bind.h"
7 #include "base/logging.h" 8 #include "base/logging.h"
8 #include "base/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
9 #include "base/single_thread_task_runner.h" 10 #include "base/single_thread_task_runner.h"
11 #include "base/synchronization/lock.h"
10 #include "gpu/command_buffer/client/context_support.h" 12 #include "gpu/command_buffer/client/context_support.h"
11 #include "third_party/skia/include/gpu/GrContext.h" 13 #include "third_party/skia/include/gpu/GrContext.h"
12 14
13 namespace cc { 15 namespace cc {
14 ContextCacheController::ScopedVisibility::ScopedVisibility() = default; 16 namespace {
17 static const int kIdleCleanupDelaySeconds = 1;
18 } // namespace
15 19
16 ContextCacheController::ScopedVisibility::~ScopedVisibility() { 20 ContextCacheController::ScopedToken::ScopedToken() = default;
21
22 ContextCacheController::ScopedToken::~ScopedToken() {
17 DCHECK(released_); 23 DCHECK(released_);
18 } 24 }
19 25
20 void ContextCacheController::ScopedVisibility::Release() { 26 void ContextCacheController::ScopedToken::Release() {
21 DCHECK(!released_); 27 DCHECK(!released_);
22 released_ = true; 28 released_ = true;
23 } 29 }
24 30
25 ContextCacheController::ContextCacheController( 31 ContextCacheController::ContextCacheController(
26 gpu::ContextSupport* context_support, 32 gpu::ContextSupport* context_support,
27 scoped_refptr<base::SingleThreadTaskRunner> task_runner) 33 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
28 : context_support_(context_support), task_runner_(std::move(task_runner)) {} 34 : context_support_(context_support),
35 task_runner_(std::move(task_runner)),
36 weak_factory_(this) {
37 // The |weak_factory_| can only be used from a single thread. We
38 // create/destroy this class and run callbacks on a single thread, but we
39 // want to be able to post callbacks from multiple threads. We need a weak
40 // ptr to post callbacks, so acquire one here, while we're on the right
41 // thread.
42 weak_ptr_ = weak_factory_.GetWeakPtr();
43 }
29 44
30 ContextCacheController::~ContextCacheController() = default; 45 ContextCacheController::~ContextCacheController() = default;
31 46
32 void ContextCacheController::SetGrContext(GrContext* gr_context) { 47 void ContextCacheController::SetGrContext(GrContext* gr_context) {
33 gr_context_ = gr_context; 48 gr_context_ = gr_context;
34 } 49 }
35 50
51 void ContextCacheController::SetLock(base::Lock* lock) {
52 context_lock_ = lock;
53 }
54
36 std::unique_ptr<ContextCacheController::ScopedVisibility> 55 std::unique_ptr<ContextCacheController::ScopedVisibility>
37 ContextCacheController::ClientBecameVisible() { 56 ContextCacheController::ClientBecameVisible() {
57 if (context_lock_)
58 context_lock_->AssertAcquired();
59
38 bool became_visible = num_clients_visible_ == 0; 60 bool became_visible = num_clients_visible_ == 0;
39 ++num_clients_visible_; 61 ++num_clients_visible_;
40 62
41 if (became_visible) 63 if (became_visible)
42 context_support_->SetAggressivelyFreeResources(false); 64 context_support_->SetAggressivelyFreeResources(false);
43 65
44 return base::WrapUnique(new ScopedVisibility()); 66 return base::WrapUnique(new ScopedVisibility());
45 } 67 }
46 68
47 void ContextCacheController::ClientBecameNotVisible( 69 void ContextCacheController::ClientBecameNotVisible(
48 std::unique_ptr<ScopedVisibility> scoped_visibility) { 70 std::unique_ptr<ScopedVisibility> scoped_visibility) {
49 DCHECK(scoped_visibility); 71 DCHECK(scoped_visibility);
50 scoped_visibility->Release(); 72 scoped_visibility->Release();
51 73
74 if (context_lock_)
75 context_lock_->AssertAcquired();
76
52 DCHECK_GT(num_clients_visible_, 0u); 77 DCHECK_GT(num_clients_visible_, 0u);
53 --num_clients_visible_; 78 --num_clients_visible_;
54 79
55 if (num_clients_visible_ == 0) { 80 if (num_clients_visible_ == 0) {
81 // We are freeing resources now - cancel any pending idle callbacks.
82 InvalidatePendingIdleCallbacks();
83
56 if (gr_context_) 84 if (gr_context_)
57 gr_context_->freeGpuResources(); 85 gr_context_->freeGpuResources();
58 context_support_->SetAggressivelyFreeResources(true); 86 context_support_->SetAggressivelyFreeResources(true);
59 } 87 }
60 } 88 }
61 89
62 std::unique_ptr<ContextCacheController::ScopedVisibility> 90 std::unique_ptr<ContextCacheController::ScopedBusy>
63 ContextCacheController::CreateScopedVisibilityForTesting() const { 91 ContextCacheController::ClientBecameBusy() {
64 return base::WrapUnique(new ScopedVisibility()); 92 if (context_lock_)
93 context_lock_->AssertAcquired();
94
95 ++num_clients_busy_;
96 // We are busy, cancel any pending idle callbacks.
97 InvalidatePendingIdleCallbacks();
98
99 return base::WrapUnique(new ScopedBusy());
65 } 100 }
66 101
67 void ContextCacheController::ReleaseScopedVisibilityForTesting( 102 void ContextCacheController::ClientBecameNotBusy(
68 std::unique_ptr<ScopedVisibility> scoped_visibility) const { 103 std::unique_ptr<ScopedBusy> scoped_busy) {
69 scoped_visibility->Release(); 104 DCHECK(scoped_busy);
105 scoped_busy->Release();
106
107 if (context_lock_)
108 context_lock_->AssertAcquired();
109
110 DCHECK_GT(num_clients_busy_, 0u);
111 --num_clients_busy_;
112
113 // If we have become idle and we are visible, queue a task to drop resources
114 // after a delay. If are not visible, we have already dropped resources.
115 if (num_clients_busy_ == 0 && num_clients_visible_ > 0 && task_runner_) {
116 // If we already have a callback pending, don't post a new one. The pending
117 // callback will handle posting a new callback itself. This prevents us from
118 // flooding the system with tasks.
119 if (!callback_pending_) {
120 {
121 base::AutoLock hold(current_idle_generation_lock_);
122 PostIdleCallback(current_idle_generation_);
123 }
124 callback_pending_ = true;
125 }
126 }
127 }
128
129 void ContextCacheController::PostIdleCallback(
130 uint32_t current_idle_generation) const {
131 task_runner_->PostDelayedTask(
132 FROM_HERE, base::Bind(&ContextCacheController::OnIdle, weak_ptr_,
133 current_idle_generation),
134 base::TimeDelta::FromSeconds(kIdleCleanupDelaySeconds));
135 }
136
137 void ContextCacheController::InvalidatePendingIdleCallbacks() {
138 base::AutoLock hold(current_idle_generation_lock_);
139 ++current_idle_generation_;
140 }
141
142 void ContextCacheController::OnIdle(uint32_t idle_generation) {
143 // First check if we should run our idle callback at all. If we have become
144 // busy since scheduling, just schedule another idle callback and return.
145 {
146 base::AutoLock hold(current_idle_generation_lock_);
147 if (current_idle_generation_ != idle_generation) {
148 PostIdleCallback(current_idle_generation_);
149 return;
150 }
151 }
152
153 // Try to acquire the context lock - if we can't acquire it then we've become
154 // busy since checking |current_idle_generation_| above. In this case, just
155 // re-post our idle callback and return.
156 if (context_lock_ && !context_lock_->Try()) {
157 base::AutoLock hold(current_idle_generation_lock_);
158 PostIdleCallback(current_idle_generation_);
159 return;
160 }
161
162 if (gr_context_)
163 gr_context_->freeGpuResources();
164
165 // Toggle SetAggressivelyFreeResources to drop command buffer data.
166 context_support_->SetAggressivelyFreeResources(true);
167 context_support_->SetAggressivelyFreeResources(false);
168
169 callback_pending_ = false;
170
171 if (context_lock_)
172 context_lock_->Release();
70 } 173 }
71 174
72 } // namespace cc 175 } // namespace cc
OLDNEW
« no previous file with comments | « cc/output/context_cache_controller.h ('k') | cc/output/context_cache_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698