Handle account removal correctly on all platforms.
[chromium-blink-merge.git] / gpu / command_buffer / service / async_pixel_transfer_manager_idle.cc
blob40ec87f689688e6b5941bc18dc3d704af000f480
1 // Copyright 2013 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.
5 #include "gpu/command_buffer/service/async_pixel_transfer_manager_idle.h"
7 #include "base/bind.h"
8 #include "base/debug/trace_event.h"
9 #include "base/debug/trace_event_synthetic_delay.h"
10 #include "base/lazy_instance.h"
11 #include "base/memory/weak_ptr.h"
12 #include "ui/gl/scoped_binders.h"
14 namespace gpu {
16 namespace {
18 static uint64 g_next_pixel_transfer_state_id = 1;
20 void PerformNotifyCompletion(
21 AsyncMemoryParams mem_params,
22 scoped_refptr<AsyncPixelTransferCompletionObserver> observer) {
23 TRACE_EVENT0("gpu", "PerformNotifyCompletion");
24 observer->DidComplete(mem_params);
27 } // namespace
29 // Class which handles async pixel transfers in a platform
30 // independent way.
31 class AsyncPixelTransferDelegateIdle
32 : public AsyncPixelTransferDelegate,
33 public base::SupportsWeakPtr<AsyncPixelTransferDelegateIdle> {
34 public:
35 AsyncPixelTransferDelegateIdle(
36 AsyncPixelTransferManagerIdle::SharedState* state,
37 GLuint texture_id,
38 const AsyncTexImage2DParams& define_params);
39 virtual ~AsyncPixelTransferDelegateIdle();
41 // Implement AsyncPixelTransferDelegate:
42 virtual void AsyncTexImage2D(
43 const AsyncTexImage2DParams& tex_params,
44 const AsyncMemoryParams& mem_params,
45 const base::Closure& bind_callback) OVERRIDE;
46 virtual void AsyncTexSubImage2D(
47 const AsyncTexSubImage2DParams& tex_params,
48 const AsyncMemoryParams& mem_params) OVERRIDE;
49 virtual bool TransferIsInProgress() OVERRIDE;
50 virtual void WaitForTransferCompletion() OVERRIDE;
52 private:
53 void PerformAsyncTexImage2D(AsyncTexImage2DParams tex_params,
54 AsyncMemoryParams mem_params,
55 const base::Closure& bind_callback);
56 void PerformAsyncTexSubImage2D(AsyncTexSubImage2DParams tex_params,
57 AsyncMemoryParams mem_params);
59 uint64 id_;
60 GLuint texture_id_;
61 bool transfer_in_progress_;
62 AsyncTexImage2DParams define_params_;
64 // Safe to hold a raw pointer because SharedState is owned by the Manager
65 // which owns the Delegate.
66 AsyncPixelTransferManagerIdle::SharedState* shared_state_;
68 DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateIdle);
71 AsyncPixelTransferDelegateIdle::AsyncPixelTransferDelegateIdle(
72 AsyncPixelTransferManagerIdle::SharedState* shared_state,
73 GLuint texture_id,
74 const AsyncTexImage2DParams& define_params)
75 : id_(g_next_pixel_transfer_state_id++),
76 texture_id_(texture_id),
77 transfer_in_progress_(false),
78 define_params_(define_params),
79 shared_state_(shared_state) {}
81 AsyncPixelTransferDelegateIdle::~AsyncPixelTransferDelegateIdle() {}
83 void AsyncPixelTransferDelegateIdle::AsyncTexImage2D(
84 const AsyncTexImage2DParams& tex_params,
85 const AsyncMemoryParams& mem_params,
86 const base::Closure& bind_callback) {
87 TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage");
88 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
90 shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task(
91 id_,
92 this,
93 base::Bind(&AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D,
94 AsWeakPtr(),
95 tex_params,
96 mem_params,
97 bind_callback)));
99 transfer_in_progress_ = true;
102 void AsyncPixelTransferDelegateIdle::AsyncTexSubImage2D(
103 const AsyncTexSubImage2DParams& tex_params,
104 const AsyncMemoryParams& mem_params) {
105 TRACE_EVENT_SYNTHETIC_DELAY_BEGIN("gpu.AsyncTexImage");
106 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target);
108 shared_state_->tasks.push_back(AsyncPixelTransferManagerIdle::Task(
109 id_,
110 this,
111 base::Bind(&AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D,
112 AsWeakPtr(),
113 tex_params,
114 mem_params)));
116 transfer_in_progress_ = true;
119 bool AsyncPixelTransferDelegateIdle::TransferIsInProgress() {
120 return transfer_in_progress_;
123 void AsyncPixelTransferDelegateIdle::WaitForTransferCompletion() {
124 for (std::list<AsyncPixelTransferManagerIdle::Task>::iterator iter =
125 shared_state_->tasks.begin();
126 iter != shared_state_->tasks.end();
127 ++iter) {
128 if (iter->transfer_id != id_)
129 continue;
131 (*iter).task.Run();
132 shared_state_->tasks.erase(iter);
133 break;
136 shared_state_->ProcessNotificationTasks();
139 void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D(
140 AsyncTexImage2DParams tex_params,
141 AsyncMemoryParams mem_params,
142 const base::Closure& bind_callback) {
143 TRACE_EVENT2("gpu", "PerformAsyncTexImage2D",
144 "width", tex_params.width,
145 "height", tex_params.height);
147 void* data = mem_params.GetDataAddress();
149 base::TimeTicks begin_time(base::TimeTicks::HighResNow());
150 gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_);
153 TRACE_EVENT0("gpu", "glTexImage2D");
154 glTexImage2D(
155 tex_params.target,
156 tex_params.level,
157 tex_params.internal_format,
158 tex_params.width,
159 tex_params.height,
160 tex_params.border,
161 tex_params.format,
162 tex_params.type,
163 data);
166 TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage");
167 transfer_in_progress_ = false;
168 shared_state_->texture_upload_count++;
169 shared_state_->total_texture_upload_time +=
170 base::TimeTicks::HighResNow() - begin_time;
172 // The texture is already fully bound so just call it now.
173 bind_callback.Run();
176 void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D(
177 AsyncTexSubImage2DParams tex_params,
178 AsyncMemoryParams mem_params) {
179 TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D",
180 "width", tex_params.width,
181 "height", tex_params.height);
183 void* data = mem_params.GetDataAddress();
185 base::TimeTicks begin_time(base::TimeTicks::HighResNow());
186 gfx::ScopedTextureBinder texture_binder(tex_params.target, texture_id_);
188 // If it's a full texture update, use glTexImage2D as it's faster.
189 // TODO(epenner): Make this configurable (http://crbug.com/259924)
190 if (tex_params.xoffset == 0 &&
191 tex_params.yoffset == 0 &&
192 tex_params.target == define_params_.target &&
193 tex_params.level == define_params_.level &&
194 tex_params.width == define_params_.width &&
195 tex_params.height == define_params_.height) {
196 TRACE_EVENT0("gpu", "glTexImage2D");
197 glTexImage2D(
198 define_params_.target,
199 define_params_.level,
200 define_params_.internal_format,
201 define_params_.width,
202 define_params_.height,
203 define_params_.border,
204 tex_params.format,
205 tex_params.type,
206 data);
207 } else {
208 TRACE_EVENT0("gpu", "glTexSubImage2D");
209 glTexSubImage2D(
210 tex_params.target,
211 tex_params.level,
212 tex_params.xoffset,
213 tex_params.yoffset,
214 tex_params.width,
215 tex_params.height,
216 tex_params.format,
217 tex_params.type,
218 data);
221 TRACE_EVENT_SYNTHETIC_DELAY_END("gpu.AsyncTexImage");
222 transfer_in_progress_ = false;
223 shared_state_->texture_upload_count++;
224 shared_state_->total_texture_upload_time +=
225 base::TimeTicks::HighResNow() - begin_time;
228 AsyncPixelTransferManagerIdle::Task::Task(
229 uint64 transfer_id,
230 AsyncPixelTransferDelegate* delegate,
231 const base::Closure& task)
232 : transfer_id(transfer_id),
233 delegate(delegate),
234 task(task) {
237 AsyncPixelTransferManagerIdle::Task::~Task() {}
239 AsyncPixelTransferManagerIdle::SharedState::SharedState()
240 : texture_upload_count(0) {}
242 AsyncPixelTransferManagerIdle::SharedState::~SharedState() {}
244 void AsyncPixelTransferManagerIdle::SharedState::ProcessNotificationTasks() {
245 while (!tasks.empty()) {
246 // Stop when we reach a pixel transfer task.
247 if (tasks.front().transfer_id)
248 return;
250 tasks.front().task.Run();
251 tasks.pop_front();
255 AsyncPixelTransferManagerIdle::AsyncPixelTransferManagerIdle()
256 : shared_state_() {
259 AsyncPixelTransferManagerIdle::~AsyncPixelTransferManagerIdle() {}
261 void AsyncPixelTransferManagerIdle::BindCompletedAsyncTransfers() {
262 // Everything is already bound.
265 void AsyncPixelTransferManagerIdle::AsyncNotifyCompletion(
266 const AsyncMemoryParams& mem_params,
267 AsyncPixelTransferCompletionObserver* observer) {
268 if (shared_state_.tasks.empty()) {
269 observer->DidComplete(mem_params);
270 return;
273 shared_state_.tasks.push_back(
274 Task(0, // 0 transfer_id for notification tasks.
275 NULL,
276 base::Bind(
277 &PerformNotifyCompletion,
278 mem_params,
279 make_scoped_refptr(observer))));
282 uint32 AsyncPixelTransferManagerIdle::GetTextureUploadCount() {
283 return shared_state_.texture_upload_count;
286 base::TimeDelta AsyncPixelTransferManagerIdle::GetTotalTextureUploadTime() {
287 return shared_state_.total_texture_upload_time;
290 void AsyncPixelTransferManagerIdle::ProcessMorePendingTransfers() {
291 if (shared_state_.tasks.empty())
292 return;
294 // First task should always be a pixel transfer task.
295 DCHECK(shared_state_.tasks.front().transfer_id);
296 shared_state_.tasks.front().task.Run();
297 shared_state_.tasks.pop_front();
299 shared_state_.ProcessNotificationTasks();
302 bool AsyncPixelTransferManagerIdle::NeedsProcessMorePendingTransfers() {
303 return !shared_state_.tasks.empty();
306 void AsyncPixelTransferManagerIdle::WaitAllAsyncTexImage2D() {
307 if (shared_state_.tasks.empty())
308 return;
310 const Task& task = shared_state_.tasks.back();
311 if (task.delegate)
312 task.delegate->WaitForTransferCompletion();
315 AsyncPixelTransferDelegate*
316 AsyncPixelTransferManagerIdle::CreatePixelTransferDelegateImpl(
317 gles2::TextureRef* ref,
318 const AsyncTexImage2DParams& define_params) {
319 return new AsyncPixelTransferDelegateIdle(&shared_state_,
320 ref->service_id(),
321 define_params);
324 } // namespace gpu