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

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

Issue 12040049: gpu: Implement idle async pixel transfers. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase 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
(Empty)
1 // Copyright (c) 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.
4
5 #include "ui/gl/async_pixel_transfer_delegate_idle.h"
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"
12 #include "base/shared_memory.h"
13 #include "build/build_config.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"
19
20 using base::SharedMemory;
21 using base::SharedMemoryHandle;
22
23 namespace gfx {
24
25 namespace {
26
27 // Gets the address of the data from shared memory.
28 void* GetAddress(SharedMemory* shared_memory, uint32 shm_data_offset) {
29 // Memory bounds have already been validated, so there
30 // is just DCHECKS here.
31 DCHECK(shared_memory);
32 DCHECK(shared_memory->memory());
33 return static_cast<int8*>(shared_memory->memory()) + shm_data_offset;
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
43 } // namespace
44
45 #if !defined(OS_ANDROID)
46 scoped_ptr<AsyncPixelTransferDelegate>
47 AsyncPixelTransferDelegate::Create(gfx::GLContext* context) {
48 return AsyncPixelTransferDelegateIdle::Create(context);
49 }
50 #endif
51
52 scoped_ptr<AsyncPixelTransferDelegate>
53 AsyncPixelTransferDelegateIdle::Create(gfx::GLContext* context) {
54 return make_scoped_ptr(
55 static_cast<AsyncPixelTransferDelegate*>(
56 new AsyncPixelTransferDelegateIdle()));
57 }
58
59 // Class which holds async pixel transfers state.
60 class TransferStateInternalIdle
61 : public base::RefCounted<TransferStateInternalIdle> {
62 public:
63 explicit TransferStateInternalIdle(GLuint texture_id)
64 : texture_id_(texture_id),
65 transfer_in_progress_(false) {
66 }
67
68 // Implement AsyncPixelTransferState:
69 bool TransferIsInProgress() {
70 return transfer_in_progress_;
71 }
72
73 protected:
74 friend class base::RefCounted<TransferStateInternalIdle>;
75 friend class AsyncPixelTransferDelegateIdle;
76
77 virtual ~TransferStateInternalIdle() {}
78
79 GLuint texture_id_;
80
81 // Indicates that an async transfer is in progress.
82 bool transfer_in_progress_;
83 };
84
85 // This just wraps an internal ref-counted state object.
86 class AsyncTransferStateIdle : public AsyncPixelTransferState {
epenner 2013/03/13 18:58:01 See my comment on the transfers_ list in the heade
reveman 2013/03/14 01:12:45 Internal class gone in latest patch.
87 public:
88 explicit AsyncTransferStateIdle(GLuint texture_id)
89 : internal_(new TransferStateInternalIdle(texture_id)) {
90 }
91 virtual ~AsyncTransferStateIdle() {}
92 virtual bool TransferIsInProgress() {
93 return internal_->TransferIsInProgress();
94 }
95 scoped_refptr<TransferStateInternalIdle> internal_;
96 };
97
98 AsyncPixelTransferDelegateIdle::Transfer::Transfer(
99 TransferStateInternalIdle* state,
100 const base::Closure& task)
101 : state(state),
102 task(task) {
103 }
104
105 AsyncPixelTransferDelegateIdle::Transfer::~Transfer() {}
106
107 AsyncPixelTransferDelegateIdle::AsyncPixelTransferDelegateIdle()
108 : texture_upload_count_(0),
109 texture_dirty_(false) {
110 }
111
112 AsyncPixelTransferDelegateIdle::~AsyncPixelTransferDelegateIdle() {
113 }
114
115 AsyncPixelTransferState*
116 AsyncPixelTransferDelegateIdle::CreateRawPixelTransferState(
117 GLuint texture_id,
118 const AsyncTexImage2DParams& define_params) {
119 return static_cast<AsyncPixelTransferState*>(
120 new AsyncTransferStateIdle(texture_id));
121 }
122
123 bool AsyncPixelTransferDelegateIdle::BindCompletedAsyncTransfers() {
124 bool texture_dirty = texture_dirty_;
epenner 2013/03/13 18:58:01 This feels brittle to me and not implied from the
reveman 2013/03/14 01:12:45 I made ProcessMorePendingTransfers() have a return
125 texture_dirty_ = false;
126 return texture_dirty;
127 }
128
129 void AsyncPixelTransferDelegateIdle::AsyncNotifyCompletion(
130 const AsyncMemoryParams& mem_params,
131 const CompletionCallback& callback) {
132 if (transfers_.empty()) {
133 callback.Run(mem_params);
134 return;
135 }
136
137 transfers_.back().notifications.push(
138 base::Bind(
139 &AsyncPixelTransferDelegateIdle::PerformNotifyCompletion,
140 AsWeakPtr(),
141 mem_params,
142 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
143 mem_params.shared_memory,
144 mem_params.shm_size)),
145 callback));
146 }
147
148 void AsyncPixelTransferDelegateIdle::AsyncTexImage2D(
149 AsyncPixelTransferState* transfer_state,
150 const AsyncTexImage2DParams& tex_params,
151 const AsyncMemoryParams& mem_params,
152 const base::Closure& bind_callback) {
153 scoped_refptr<TransferStateInternalIdle> state =
154 static_cast<AsyncTransferStateIdle*>(transfer_state)->internal_.get();
155 DCHECK(mem_params.shared_memory);
156 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
157 mem_params.shm_size);
158 DCHECK(state);
159 DCHECK(state->texture_id_);
160
161 transfers_.push_back(
162 Transfer(
163 state.get(),
164 base::Bind(
165 &AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D,
166 AsWeakPtr(),
167 state,
168 tex_params,
169 mem_params,
170 bind_callback,
171 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
172 mem_params.shared_memory,
173 mem_params.shm_size)))));
174
175 state->transfer_in_progress_ = true;
176 }
177
178 void AsyncPixelTransferDelegateIdle::AsyncTexSubImage2D(
179 AsyncPixelTransferState* transfer_state,
180 const AsyncTexSubImage2DParams& tex_params,
181 const AsyncMemoryParams& mem_params) {
182 scoped_refptr<TransferStateInternalIdle> state =
183 static_cast<AsyncTransferStateIdle*>(transfer_state)->internal_.get();
184 DCHECK(mem_params.shared_memory);
185 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size,
186 mem_params.shm_size);
187 DCHECK(state);
188 DCHECK(state->texture_id_);
189
190 transfers_.push_back(
191 Transfer(
192 state.get(),
193 base::Bind(
194 &AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D,
195 AsWeakPtr(),
196 state,
197 tex_params,
198 mem_params,
199 base::Owned(new ScopedSafeSharedMemory(safe_shared_memory_pool(),
200 mem_params.shared_memory,
201 mem_params.shm_size)))));
202
203 state->transfer_in_progress_ = true;
204 }
205
206 void AsyncPixelTransferDelegateIdle::WaitForTransferCompletion(
207 AsyncPixelTransferState* transfer_state) {
208 scoped_refptr<TransferStateInternalIdle> state =
209 static_cast<AsyncTransferStateIdle*>(transfer_state)->internal_.get();
210
211 for (std::list<Transfer>::iterator iter = transfers_.begin();
212 iter != transfers_.end(); ++iter) {
213 if (iter->state.get() != state)
214 continue;
215
216 ProcessTransfer(*iter);
217 transfers_.erase(iter);
218 break;
219 }
220 }
221
222 uint32 AsyncPixelTransferDelegateIdle::GetTextureUploadCount() {
223 return texture_upload_count_;
224 }
225
226 base::TimeDelta AsyncPixelTransferDelegateIdle::GetTotalTextureUploadTime() {
227 return total_texture_upload_time_;
228 }
229
230 void AsyncPixelTransferDelegateIdle::ProcessPendingTransfers() {
231 if (transfers_.empty())
232 return;
233
234 ProcessTransfer(transfers_.front());
235 transfers_.pop_front();
236 }
237
238 bool AsyncPixelTransferDelegateIdle::NeedsProcessPendingTransfers() {
239 return !transfers_.empty();
240 }
241
242 void AsyncPixelTransferDelegateIdle::ProcessTransfer(Transfer& transfer) {
243 transfer.task.Run();
244 while (!transfer.notifications.empty()) {
245 transfer.notifications.front().Run();
246 transfer.notifications.pop();
247 }
248 }
249
250 void AsyncPixelTransferDelegateIdle::PerformNotifyCompletion(
251 AsyncMemoryParams mem_params,
252 ScopedSafeSharedMemory* safe_shared_memory,
253 const CompletionCallback& callback) {
254 TRACE_EVENT0("gpu", "PerformNotifyCompletion");
255 gfx::AsyncMemoryParams safe_mem_params = mem_params;
256 safe_mem_params.shared_memory = safe_shared_memory->shared_memory();
257 callback.Run(safe_mem_params);
258 }
259
260 void AsyncPixelTransferDelegateIdle::PerformAsyncTexImage2D(
261 scoped_refptr<TransferStateInternalIdle> state,
262 AsyncTexImage2DParams tex_params,
263 AsyncMemoryParams mem_params,
264 const base::Closure& bind_callback,
265 ScopedSafeSharedMemory* safe_shared_memory) {
266 TRACE_EVENT2("gpu", "PerformAsyncTexImage2D",
267 "width", tex_params.width,
268 "height", tex_params.height);
269 DCHECK_EQ(0, tex_params.level);
270
271 void* data = GetAddress(safe_shared_memory->shared_memory(),
272 mem_params.shm_data_offset);
273
274 glActiveTexture(GL_TEXTURE0);
275 glBindTexture(GL_TEXTURE_2D, state->texture_id_);
276 texture_dirty_ = true;
277
278 {
279 TRACE_EVENT0("gpu", "glTexImage2D");
280 glTexImage2D(
281 tex_params.target,
282 tex_params.level,
283 tex_params.internal_format,
284 tex_params.width,
285 tex_params.height,
286 tex_params.border,
287 tex_params.format,
288 tex_params.type,
289 data);
290 }
291
292 state->transfer_in_progress_ = false;
293
294 // The texture is already fully bound so just call it now.
295 bind_callback.Run();
epenner 2013/03/13 18:58:01 Same comment on possible use-after-free when invok
reveman 2013/03/14 01:12:45 Done.
296 }
297
298 void AsyncPixelTransferDelegateIdle::PerformAsyncTexSubImage2D(
299 scoped_refptr<TransferStateInternalIdle> state,
300 AsyncTexSubImage2DParams tex_params,
301 AsyncMemoryParams mem_params,
302 ScopedSafeSharedMemory* safe_shared_memory) {
303 TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D",
304 "width", tex_params.width,
305 "height", tex_params.height);
306 DCHECK_EQ(0, tex_params.level);
307
308 void* data = GetAddress(safe_shared_memory->shared_memory(),
309 mem_params.shm_data_offset);
310
311 base::TimeTicks begin_time(base::TimeTicks::HighResNow());
312 glActiveTexture(GL_TEXTURE0);
313 glBindTexture(GL_TEXTURE_2D, state->texture_id_);
314 texture_dirty_ = true;
315
316 {
317 TRACE_EVENT0("gpu", "glTexSubImage2D");
318 glTexSubImage2D(
319 GL_TEXTURE_2D,
320 tex_params.level,
321 tex_params.xoffset,
322 tex_params.yoffset,
323 tex_params.width,
324 tex_params.height,
325 tex_params.format,
326 tex_params.type,
327 data);
328 }
329
330 texture_upload_count_++;
331 total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time;
332
333 state->transfer_in_progress_ = false;
334 }
335
336 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698