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

Side by Side Diff: ui/gl/async_pixel_transfer_delegate_stub.cc

Issue 12040049: gpu: Implement idle async pixel transfers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase and prevent starvation Created 7 years, 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 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 "ui/gl/async_pixel_transfer_delegate_stub.h" 5 #include "ui/gl/async_pixel_transfer_delegate_stub.h"
6 6
7 #include "base/bind.h"
8 #include "base/debug/trace_event.h"
9 #include "base/lazy_instance.h"
10 #include "base/message_loop.h"
11 #include "base/process_util.h"
7 #include "base/shared_memory.h" 12 #include "base/shared_memory.h"
8 #include "build/build_config.h" 13 #include "build/build_config.h"
9 #include "ui/gl/gl_bindings.h" 14 #include "ui/gl/gl_bindings.h"
15 #include "ui/gl/gl_context.h"
16 #include "ui/gl/gl_surface.h"
17 #include "ui/gl/safe_shared_memory_pool.h"
18 #include "ui/gl/scoped_make_current.h"
10 19
11 using base::SharedMemory; 20 using base::SharedMemory;
12 using base::SharedMemoryHandle; 21 using base::SharedMemoryHandle;
13 22
23 namespace gfx {
24
14 namespace { 25 namespace {
26
15 // Gets the address of the data from shared memory. 27 // Gets the address of the data from shared memory.
16 void* GetAddress(SharedMemory* shared_memory, 28 void* GetAddress(SharedMemory* shared_memory, uint32 shm_data_offset) {
17 uint32 shm_size,
18 uint32 shm_data_offset,
19 uint32 shm_data_size) {
20 // Memory bounds have already been validated, so there 29 // Memory bounds have already been validated, so there
21 // is just DCHECKS here. 30 // is just DCHECKS here.
22 DCHECK(shared_memory); 31 DCHECK(shared_memory);
23 DCHECK(shared_memory->memory()); 32 DCHECK(shared_memory->memory());
24 DCHECK_LE(shm_data_offset + shm_data_size, shm_size);
25 return static_cast<int8*>(shared_memory->memory()) + shm_data_offset; 33 return static_cast<int8*>(shared_memory->memory()) + shm_data_offset;
26 } 34 }
35
36 base::LazyInstance<SafeSharedMemoryPool> g_safe_shared_memory_pool =
37 LAZY_INSTANCE_INITIALIZER;
38
39 SafeSharedMemoryPool* safe_shared_memory_pool() {
40 return g_safe_shared_memory_pool.Pointer();
41 }
42
27 } // namespace 43 } // namespace
28 44
29 namespace gfx {
30
31 #if !defined(OS_ANDROID) 45 #if !defined(OS_ANDROID)
32 scoped_ptr<AsyncPixelTransferDelegate> 46 scoped_ptr<AsyncPixelTransferDelegate>
33 AsyncPixelTransferDelegate::Create(gfx::GLContext* context) { 47 AsyncPixelTransferDelegate::Create(gfx::GLContext* context) {
34 return AsyncPixelTransferDelegateStub::Create(context); 48 return AsyncPixelTransferDelegateStub::Create(context);
35 } 49 }
36 #endif 50 #endif
37 51
38 scoped_ptr<AsyncPixelTransferDelegate> 52 scoped_ptr<AsyncPixelTransferDelegate>
39 AsyncPixelTransferDelegateStub::Create(gfx::GLContext* context) { 53 AsyncPixelTransferDelegateStub::Create(gfx::GLContext* context) {
40 return make_scoped_ptr( 54 return make_scoped_ptr(
41 static_cast<AsyncPixelTransferDelegate*>( 55 static_cast<AsyncPixelTransferDelegate*>(
42 new AsyncPixelTransferDelegateStub())); 56 new AsyncPixelTransferDelegateStub()));
43 } 57 }
44 58
45 AsyncTransferStateStub::AsyncTransferStateStub(GLuint texture_id) { 59 // Class which holds async pixel transfers state.
46 static const AsyncTexImage2DParams zero_params = {0, 0, 0, 0, 0, 0, 0, 0}; 60 class TransferStateInternalStub
47 late_bind_define_params_ = zero_params; 61 : public base::RefCounted<TransferStateInternalStub> {
48 needs_late_bind_ = false; 62 public:
63 explicit TransferStateInternalStub(GLuint texture_id)
64 : texture_id_(texture_id),
65 needs_late_bind_(false),
66 transfer_in_progress_(false) {
67 static const AsyncTexImage2DParams zero_params = {0, 0, 0, 0, 0, 0, 0, 0};
68 late_bind_define_params_ = zero_params;
69 }
70
71 // Implement AsyncPixelTransferState:
72 bool TransferIsInProgress() {
73 return transfer_in_progress_;
74 }
75
76 void BindTransfer(AsyncTexImage2DParams* bound_params) {
77 DCHECK(bound_params);
78 DCHECK(needs_late_bind_);
79 *bound_params = late_bind_define_params_;
80 needs_late_bind_ = false;
81 }
82
83 protected:
84 friend class base::RefCounted<TransferStateInternalStub>;
85 friend class AsyncPixelTransferDelegateStub;
86
87 virtual ~TransferStateInternalStub() {}
88
89 GLuint texture_id_;
90
91 // Indicates there is a new EGLImage and the 'real'
Sami 2013/03/07 16:57:19 No EGLImages here :)
reveman 2013/03/07 20:21:04 Done.
92 // texture needs to be bound to it as an EGLImage target.
93 bool needs_late_bind_;
94
95 // Definition params for texture that needs binding.
96 AsyncTexImage2DParams late_bind_define_params_;
97
98 // Indicates that an async transfer is in progress.
99 bool transfer_in_progress_;
100 };
101
102 // This just wraps an internal ref-counted state object.
103 class AsyncTransferStateStub : public AsyncPixelTransferState {
104 public:
105 explicit AsyncTransferStateStub(GLuint texture_id)
106 : internal_(new TransferStateInternalStub(texture_id)) {
107 }
108 virtual ~AsyncTransferStateStub() {}
109 virtual bool TransferIsInProgress() {
110 return internal_->TransferIsInProgress();
Sami 2013/03/07 16:57:19 Nit: indent by 2.
reveman 2013/03/07 20:21:04 Done.
111 }
112 virtual void BindTransfer(AsyncTexImage2DParams* bound_params) {
113 internal_->BindTransfer(bound_params);
Sami 2013/03/07 16:57:19 Ditto.
reveman 2013/03/07 20:21:04 Done.
114 }
115 scoped_refptr<TransferStateInternalStub> internal_;
116 };
117
118 AsyncPixelTransferDelegateStub::Transfer::Transfer(
119 TransferStateInternalStub* state,
120 const base::Closure& task)
121 : state(state),
122 task(task) {
49 } 123 }
50 124
51 AsyncTransferStateStub::~AsyncTransferStateStub() { 125 AsyncPixelTransferDelegateStub::Transfer::~Transfer() {}
52 }
53
54 bool AsyncTransferStateStub::TransferIsInProgress() {
55 return false;
56 }
57
58 void AsyncTransferStateStub::BindTransfer(AsyncTexImage2DParams* out_params) {
59 DCHECK(out_params);
60 DCHECK(needs_late_bind_);
61 *out_params = late_bind_define_params_;
62 needs_late_bind_ = false;
63 }
64 126
65 AsyncPixelTransferDelegateStub::AsyncPixelTransferDelegateStub() 127 AsyncPixelTransferDelegateStub::AsyncPixelTransferDelegateStub()
66 : texture_upload_count_(0) { 128 : texture_upload_count_(0) {
67 } 129 }
68 130
69 AsyncPixelTransferDelegateStub::~AsyncPixelTransferDelegateStub() { 131 AsyncPixelTransferDelegateStub::~AsyncPixelTransferDelegateStub() {
70 } 132 }
71 133
72 AsyncPixelTransferState* 134 AsyncPixelTransferState*
73 AsyncPixelTransferDelegateStub::CreateRawPixelTransferState( 135 AsyncPixelTransferDelegateStub::CreateRawPixelTransferState(
74 GLuint texture_id) { 136 GLuint texture_id) {
75 return static_cast<AsyncPixelTransferState*>( 137 return static_cast<AsyncPixelTransferState*>(
76 new AsyncTransferStateStub(texture_id)); 138 new AsyncTransferStateStub(texture_id));
77 } 139 }
78 140
79 void AsyncPixelTransferDelegateStub::AsyncNotifyCompletion( 141 void AsyncPixelTransferDelegateStub::AsyncNotifyCompletion(
80 const AsyncMemoryParams& mem_params, 142 const AsyncMemoryParams& mem_params,
81 const CompletionCallback& callback) { 143 const CompletionCallback& callback) {
82 callback.Run(mem_params); 144 if (transfers_.empty()) {
145 callback.Run(mem_params);
146 return;
147 }
148
149 transfers_.back().notifications.push(
150 base::Bind(
151 &AsyncPixelTransferDelegateStub::PerformNotifyCompletion,
152 AsWeakPtr(),
153 mem_params,
154 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
155 mem_params.shared_memory,
156 mem_params.shm_size)),
157 callback));
83 } 158 }
84 159
85 void AsyncPixelTransferDelegateStub::AsyncTexImage2D( 160 void AsyncPixelTransferDelegateStub::AsyncTexImage2D(
86 AsyncPixelTransferState* transfer_state, 161 AsyncPixelTransferState* transfer_state,
87 const AsyncTexImage2DParams& tex_params, 162 const AsyncTexImage2DParams& tex_params,
88 const AsyncMemoryParams& mem_params) { 163 const AsyncMemoryParams& mem_params) {
89 // Save the define params to return later during deferred 164 scoped_refptr<TransferStateInternalStub> state =
90 // binding of the transfer texture. 165 static_cast<AsyncTransferStateStub*>(transfer_state)->internal_.get();
91 DCHECK(transfer_state); 166 DCHECK(mem_params.shared_memory);
92 AsyncTransferStateStub* state = 167 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
93 static_cast<AsyncTransferStateStub*>(transfer_state); 168 mem_params.shm_size);
94 // We don't actually need a late bind since this stub does 169 DCHECK(state);
95 // everything synchronously, but this tries to be similar 170 DCHECK(state->texture_id_);
96 // as an async implementation. 171 DCHECK(!state->needs_late_bind_);
172
173 // Mark the transfer in progress and save define params for lazy binding.
97 state->needs_late_bind_ = true; 174 state->needs_late_bind_ = true;
98 state->late_bind_define_params_ = tex_params; 175 state->late_bind_define_params_ = tex_params;
99 void* data = GetAddress(mem_params.shared_memory, 176
100 mem_params.shm_size, 177 transfers_.push_back(
101 mem_params.shm_data_offset, 178 Transfer(
102 mem_params.shm_data_size); 179 state.get(),
103 glTexImage2D( 180 base::Bind(
104 tex_params.target, 181 &AsyncPixelTransferDelegateStub::PerformAsyncTexImage2D,
105 tex_params.level, 182 AsWeakPtr(),
106 tex_params.internal_format, 183 state,
107 tex_params.width, 184 tex_params,
108 tex_params.height, 185 mem_params,
109 tex_params.border, 186 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
110 tex_params.format, 187 mem_params.shared_memory,
111 tex_params.type, 188 mem_params.shm_size)))));
112 data); 189
190 state->transfer_in_progress_ = true;
113 } 191 }
114 192
115 void AsyncPixelTransferDelegateStub::AsyncTexSubImage2D( 193 void AsyncPixelTransferDelegateStub::AsyncTexSubImage2D(
116 AsyncPixelTransferState* transfer_state, 194 AsyncPixelTransferState* transfer_state,
117 const AsyncTexSubImage2DParams& tex_params, 195 const AsyncTexSubImage2DParams& tex_params,
118 const AsyncMemoryParams& mem_params) { 196 const AsyncMemoryParams& mem_params) {
119 void* data = GetAddress(mem_params.shared_memory, 197 scoped_refptr<TransferStateInternalStub> state =
120 mem_params.shm_size, 198 static_cast<AsyncTransferStateStub*>(transfer_state)->internal_.get();
121 mem_params.shm_data_offset, 199 DCHECK(mem_params.shared_memory);
122 mem_params.shm_data_size); 200 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
123 DCHECK(transfer_state); 201 mem_params.shm_size);
124 AsyncTransferStateStub* state = 202 DCHECK(state);
125 static_cast<AsyncTransferStateStub*>(transfer_state); 203 DCHECK(state->texture_id_);
126 DCHECK(!state->needs_late_bind_); 204 DCHECK(!state->needs_late_bind_);
127 base::TimeTicks begin_time(base::TimeTicks::HighResNow()); 205
128 glTexSubImage2D( 206 transfers_.push_back(
129 tex_params.target, 207 Transfer(
130 tex_params.level, 208 state.get(),
131 tex_params.xoffset, 209 base::Bind(
132 tex_params.yoffset, 210 &AsyncPixelTransferDelegateStub::PerformAsyncTexSubImage2D,
133 tex_params.width, 211 AsWeakPtr(),
134 tex_params.height, 212 state,
135 tex_params.format, 213 tex_params,
136 tex_params.type, 214 mem_params,
137 data); 215 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
138 texture_upload_count_++; 216 mem_params.shared_memory,
139 total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time; 217 mem_params.shm_size)))));
218
219 state->transfer_in_progress_ = true;
140 } 220 }
141 221
142 void AsyncPixelTransferDelegateStub::WaitForTransferCompletion( 222 void AsyncPixelTransferDelegateStub::WaitForTransferCompletion(
143 AsyncPixelTransferState* state) { 223 AsyncPixelTransferState* transfer_state) {
144 // Already done. 224 scoped_refptr<TransferStateInternalStub> state =
225 static_cast<AsyncTransferStateStub*>(transfer_state)->internal_.get();
226
227 for (std::list<Transfer>::iterator iter = transfers_.begin();
228 iter != transfers_.end(); ++iter) {
229 if (iter->state.get() != state)
230 continue;
231
232 iter->task.Run();
Sami 2013/03/07 16:57:19 Neat! Is it worth wrapping this bit into PerformT
reveman 2013/03/07 20:21:04 Done. Added ProcessTransfer.
233 while (!iter->notifications.empty()) {
234 iter->notifications.front().Run();
235 iter->notifications.pop();
236 }
237 transfers_.erase(iter);
238 break;
239 }
145 } 240 }
146 241
147 uint32 AsyncPixelTransferDelegateStub::GetTextureUploadCount() { 242 uint32 AsyncPixelTransferDelegateStub::GetTextureUploadCount() {
148 return texture_upload_count_; 243 return texture_upload_count_;
149 } 244 }
150 245
151 base::TimeDelta AsyncPixelTransferDelegateStub::GetTotalTextureUploadTime() { 246 base::TimeDelta AsyncPixelTransferDelegateStub::GetTotalTextureUploadTime() {
152 return total_texture_upload_time_; 247 return total_texture_upload_time_;
153 } 248 }
154 249
250 void AsyncPixelTransferDelegateStub::ProcessPendingTransfers() {
251 if (transfers_.empty())
252 return;
253
254 transfers_.front().task.Run();
255 while (!transfers_.front().notifications.empty()) {
256 transfers_.front().notifications.front().Run();
257 transfers_.front().notifications.pop();
258 }
259 transfers_.pop_front();
260 }
261
262 bool AsyncPixelTransferDelegateStub::HasPendingTransfers() {
263 return !transfers_.empty();
264 }
265
266 void AsyncPixelTransferDelegateStub::PerformNotifyCompletion(
267 AsyncMemoryParams mem_params,
268 ScopedSafeSharedMemory* safe_shared_memory,
269 const CompletionCallback& callback) {
270 TRACE_EVENT0("gpu", "PerformNotifyCompletion");
271 gfx::AsyncMemoryParams safe_mem_params = mem_params;
272 safe_mem_params.shared_memory = safe_shared_memory->shared_memory();
273 callback.Run(safe_mem_params);
274 }
275
276 void AsyncPixelTransferDelegateStub::PerformAsyncTexImage2D(
277 scoped_refptr<TransferStateInternalStub> state,
278 AsyncTexImage2DParams tex_params,
279 AsyncMemoryParams mem_params,
280 ScopedSafeSharedMemory* safe_shared_memory) {
281 TRACE_EVENT2("gpu", "PerformAsyncTexImage2D",
282 "width", tex_params.width,
283 "height", tex_params.height);
284 DCHECK_EQ(0, tex_params.level);
285
286 void* data = GetAddress(safe_shared_memory->shared_memory(),
287 mem_params.shm_data_offset);
288
289 glActiveTexture(GL_TEXTURE0);
290 glBindTexture(GL_TEXTURE_2D, state->texture_id_);
291
292 {
293 TRACE_EVENT0("gpu", "glTexImage2D");
294 glTexImage2D(
295 tex_params.target,
296 tex_params.level,
297 tex_params.internal_format,
298 tex_params.width,
299 tex_params.height,
300 tex_params.border,
301 tex_params.format,
302 tex_params.type,
303 data);
304 }
305
306 state->transfer_in_progress_ = false;
307 }
308
309 void AsyncPixelTransferDelegateStub::PerformAsyncTexSubImage2D(
310 scoped_refptr<TransferStateInternalStub> state,
311 AsyncTexSubImage2DParams tex_params,
312 AsyncMemoryParams mem_params,
313 ScopedSafeSharedMemory* safe_shared_memory) {
314 TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D",
315 "width", tex_params.width,
316 "height", tex_params.height);
317 DCHECK_EQ(0, tex_params.level);
318
319 void* data = GetAddress(safe_shared_memory->shared_memory(),
320 mem_params.shm_data_offset);
321
322 base::TimeTicks begin_time(base::TimeTicks::HighResNow());
323 glActiveTexture(GL_TEXTURE0);
324 glBindTexture(GL_TEXTURE_2D, state->texture_id_);
325
326 {
327 TRACE_EVENT0("gpu", "glTexSubImage2D");
328 glTexSubImage2D(
329 GL_TEXTURE_2D,
330 tex_params.level,
331 tex_params.xoffset,
332 tex_params.yoffset,
333 tex_params.width,
334 tex_params.height,
335 tex_params.format,
336 tex_params.type,
337 data);
338 }
339
340 texture_upload_count_++;
341 total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time;
342
343 state->transfer_in_progress_ = false;
344 }
345
155 } // namespace gfx 346 } // namespace gfx
156 347
OLDNEW
« ui/gl/async_pixel_transfer_delegate_stub.h ('K') | « ui/gl/async_pixel_transfer_delegate_stub.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698