OLD | NEW |
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_android.h" | 5 #include "ui/gl/async_pixel_transfer_delegate_android.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
63 return NULL; | 63 return NULL; |
64 scoped_ptr<SharedMemory> duped_shared_memory( | 64 scoped_ptr<SharedMemory> duped_shared_memory( |
65 new SharedMemory(duped_shared_memory_handle, false)); | 65 new SharedMemory(duped_shared_memory_handle, false)); |
66 // Map the shared memory into this process. This validates the size. | 66 // Map the shared memory into this process. This validates the size. |
67 if (!duped_shared_memory->Map(size)) | 67 if (!duped_shared_memory->Map(size)) |
68 return NULL; | 68 return NULL; |
69 return duped_shared_memory.release(); | 69 return duped_shared_memory.release(); |
70 } | 70 } |
71 | 71 |
72 // Gets the address of the data from shared memory. | 72 // Gets the address of the data from shared memory. |
73 void* GetAddress(SharedMemory* shared_memory, | 73 void* GetAddress(SharedMemory* shared_memory, uint32 shm_data_offset) { |
74 uint32 shm_size, | |
75 uint32 shm_data_offset, | |
76 uint32 shm_data_size) { | |
77 // Memory bounds have already been validated, so there | 74 // Memory bounds have already been validated, so there |
78 // is just DCHECKS here. | 75 // is just DCHECKS here. |
79 DCHECK(shared_memory); | 76 DCHECK(shared_memory); |
80 DCHECK(shared_memory->memory()); | 77 DCHECK(shared_memory->memory()); |
81 DCHECK_LE(shm_data_offset + shm_data_size, shm_size); | |
82 return static_cast<int8*>(shared_memory->memory()) + shm_data_offset; | 78 return static_cast<int8*>(shared_memory->memory()) + shm_data_offset; |
83 } | 79 } |
84 | 80 |
85 class TransferThread : public base::Thread { | 81 class TransferThread : public base::Thread { |
86 public: | 82 public: |
87 TransferThread() : base::Thread(kAsyncTransferThreadName) { | 83 TransferThread() : base::Thread(kAsyncTransferThreadName) { |
88 Start(); | 84 Start(); |
89 } | 85 } |
90 virtual ~TransferThread() { | 86 virtual ~TransferThread() { |
91 Stop(); | 87 Stop(); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); | 152 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); |
157 // We can only change the active texture and unit 0, | 153 // We can only change the active texture and unit 0, |
158 // as that is all that will be restored. | 154 // as that is all that will be restored. |
159 glActiveTexture(GL_TEXTURE0); | 155 glActiveTexture(GL_TEXTURE0); |
160 glBindTexture(GL_TEXTURE_2D, texture_id_); | 156 glBindTexture(GL_TEXTURE_2D, texture_id_); |
161 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_); | 157 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_); |
162 *bound_params = late_bind_define_params_; | 158 *bound_params = late_bind_define_params_; |
163 needs_late_bind_ = false; | 159 needs_late_bind_ = false; |
164 } | 160 } |
165 | 161 |
166 // Completion callbacks. | 162 protected: |
167 void TexImage2DCompleted() { | |
168 needs_late_bind_ = true; | |
169 transfer_in_progress_ = false; | |
170 } | |
171 void TexSubImage2DCompleted() { | |
172 transfer_in_progress_ = false; | |
173 } | |
174 | |
175 protected: | |
176 friend class base::RefCountedThreadSafe<TransferStateInternal>; | 163 friend class base::RefCountedThreadSafe<TransferStateInternal>; |
177 friend class AsyncPixelTransferDelegateAndroid; | 164 friend class AsyncPixelTransferDelegateAndroid; |
178 | 165 |
179 static void DeleteTexture(GLuint id) { | 166 static void DeleteTexture(GLuint id) { |
180 glDeleteTextures(1, &id); | 167 glDeleteTextures(1, &id); |
181 } | 168 } |
182 | 169 |
183 virtual ~TransferStateInternal() { | 170 virtual ~TransferStateInternal() { |
184 if (egl_image_) { | 171 if (egl_image_) { |
185 EGLDisplay display = eglGetCurrentDisplay(); | 172 EGLDisplay display = eglGetCurrentDisplay(); |
(...skipping 18 matching lines...) Expand all Loading... |
204 // Definition params for texture that needs binding. | 191 // Definition params for texture that needs binding. |
205 AsyncTexImage2DParams late_bind_define_params_; | 192 AsyncTexImage2DParams late_bind_define_params_; |
206 | 193 |
207 // Indicates that an async transfer is in progress. | 194 // Indicates that an async transfer is in progress. |
208 bool transfer_in_progress_; | 195 bool transfer_in_progress_; |
209 | 196 |
210 // It would be nice if we could just create a new EGLImage for | 197 // It would be nice if we could just create a new EGLImage for |
211 // every upload, but I found that didn't work, so this stores | 198 // every upload, but I found that didn't work, so this stores |
212 // one for the lifetime of the texture. | 199 // one for the lifetime of the texture. |
213 EGLImageKHR egl_image_; | 200 EGLImageKHR egl_image_; |
| 201 |
| 202 // Time spent performing last transfer. |
| 203 base::TimeDelta last_transfer_time_; |
214 }; | 204 }; |
215 | 205 |
216 // Android needs thread-safe ref-counting, so this just wraps | 206 // Android needs thread-safe ref-counting, so this just wraps |
217 // an internal thread-safe ref-counted state object. | 207 // an internal thread-safe ref-counted state object. |
218 class AsyncTransferStateAndroid : public AsyncPixelTransferState { | 208 class AsyncTransferStateAndroid : public AsyncPixelTransferState { |
219 public: | 209 public: |
220 explicit AsyncTransferStateAndroid(GLuint texture_id) | 210 explicit AsyncTransferStateAndroid(GLuint texture_id) |
221 : internal_(new TransferStateInternal(texture_id)) { | 211 : internal_(new TransferStateInternal(texture_id)) { |
222 } | 212 } |
223 virtual ~AsyncTransferStateAndroid() {} | 213 virtual ~AsyncTransferStateAndroid() {} |
224 virtual bool TransferIsInProgress() { | 214 virtual bool TransferIsInProgress() { |
225 return internal_->TransferIsInProgress(); | 215 return internal_->TransferIsInProgress(); |
226 } | 216 } |
227 virtual void BindTransfer(AsyncTexImage2DParams* bound_params) { | 217 virtual void BindTransfer(AsyncTexImage2DParams* bound_params) { |
228 internal_->BindTransfer(bound_params); | 218 internal_->BindTransfer(bound_params); |
229 } | 219 } |
230 scoped_refptr<TransferStateInternal> internal_; | 220 scoped_refptr<TransferStateInternal> internal_; |
231 }; | 221 }; |
232 | 222 |
233 // Class which handles async pixel transfers on Android (using | 223 // Class which handles async pixel transfers on Android (using |
234 // EGLImageKHR and another upload thread) | 224 // EGLImageKHR and another upload thread) |
235 class AsyncPixelTransferDelegateAndroid : public AsyncPixelTransferDelegate { | 225 class AsyncPixelTransferDelegateAndroid |
| 226 : public AsyncPixelTransferDelegate, |
| 227 public base::SupportsWeakPtr<AsyncPixelTransferDelegateAndroid> { |
236 public: | 228 public: |
237 AsyncPixelTransferDelegateAndroid() {} | 229 AsyncPixelTransferDelegateAndroid(); |
238 virtual ~AsyncPixelTransferDelegateAndroid() {} | 230 virtual ~AsyncPixelTransferDelegateAndroid(); |
239 | 231 |
240 // implement AsyncPixelTransferDelegate: | 232 // implement AsyncPixelTransferDelegate: |
241 virtual void AsyncNotifyCompletion( | 233 virtual void AsyncNotifyCompletion( |
242 const base::Closure& task) OVERRIDE; | 234 const base::Closure& task) OVERRIDE; |
243 virtual void AsyncTexImage2D( | 235 virtual void AsyncTexImage2D( |
244 AsyncPixelTransferState* state, | 236 AsyncPixelTransferState* state, |
245 const AsyncTexImage2DParams& tex_params, | 237 const AsyncTexImage2DParams& tex_params, |
246 const AsyncMemoryParams& mem_params) OVERRIDE; | 238 const AsyncMemoryParams& mem_params) OVERRIDE; |
247 virtual void AsyncTexSubImage2D( | 239 virtual void AsyncTexSubImage2D( |
248 AsyncPixelTransferState* state, | 240 AsyncPixelTransferState* state, |
249 const AsyncTexSubImage2DParams& tex_params, | 241 const AsyncTexSubImage2DParams& tex_params, |
250 const AsyncMemoryParams& mem_params) OVERRIDE; | 242 const AsyncMemoryParams& mem_params) OVERRIDE; |
| 243 virtual uint32 GetTextureUploadCount() OVERRIDE; |
| 244 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; |
251 | 245 |
252 private: | 246 private: |
253 // implement AsyncPixelTransferDelegate: | 247 // implement AsyncPixelTransferDelegate: |
254 virtual AsyncPixelTransferState* | 248 virtual AsyncPixelTransferState* |
255 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; | 249 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; |
256 | 250 |
| 251 void AsyncTexImage2DCompleted(scoped_refptr<TransferStateInternal> state); |
| 252 void AsyncTexSubImage2DCompleted(scoped_refptr<TransferStateInternal> state); |
| 253 |
257 static void PerformAsyncTexImage2D( | 254 static void PerformAsyncTexImage2D( |
258 TransferStateInternal* state, | 255 TransferStateInternal* state, |
259 AsyncTexImage2DParams tex_params, | 256 AsyncTexImage2DParams tex_params, |
260 AsyncMemoryParams mem_params); | 257 base::SharedMemory* shared_memory, |
| 258 uint32 shared_memory_data_offset); |
261 static void PerformAsyncTexSubImage2D( | 259 static void PerformAsyncTexSubImage2D( |
262 TransferStateInternal* state, | 260 TransferStateInternal* state, |
263 AsyncTexSubImage2DParams tex_params, | 261 AsyncTexSubImage2DParams tex_params, |
264 AsyncMemoryParams mem_params); | 262 base::SharedMemory* shared_memory, |
| 263 uint32 shared_memory_data_offset); |
| 264 |
| 265 int texture_upload_count_; |
| 266 base::TimeDelta total_texture_upload_time_; |
265 | 267 |
266 DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateAndroid); | 268 DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateAndroid); |
267 }; | 269 }; |
268 | 270 |
269 namespace { | 271 namespace { |
270 // Imagination has some odd problems still. | 272 // Imagination has some odd problems still. |
271 bool IsImagination() { | 273 bool IsImagination() { |
272 std::string vendor; | 274 std::string vendor; |
273 vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); | 275 vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); |
274 return vendor.find("Imagination") != std::string::npos; | 276 return vendor.find("Imagination") != std::string::npos; |
(...skipping 17 matching lines...) Expand all Loading... |
292 static_cast<AsyncPixelTransferDelegate*>( | 294 static_cast<AsyncPixelTransferDelegate*>( |
293 new AsyncPixelTransferDelegateAndroid())); | 295 new AsyncPixelTransferDelegateAndroid())); |
294 } else { | 296 } else { |
295 LOG(INFO) << "Async pixel transfers not supported"; | 297 LOG(INFO) << "Async pixel transfers not supported"; |
296 return make_scoped_ptr( | 298 return make_scoped_ptr( |
297 static_cast<AsyncPixelTransferDelegate*>( | 299 static_cast<AsyncPixelTransferDelegate*>( |
298 new AsyncPixelTransferDelegateStub())); | 300 new AsyncPixelTransferDelegateStub())); |
299 } | 301 } |
300 } | 302 } |
301 | 303 |
| 304 AsyncPixelTransferDelegateAndroid::AsyncPixelTransferDelegateAndroid() |
| 305 : texture_upload_count_(0) { |
| 306 } |
| 307 |
| 308 AsyncPixelTransferDelegateAndroid::~AsyncPixelTransferDelegateAndroid() { |
| 309 } |
| 310 |
302 AsyncPixelTransferState* | 311 AsyncPixelTransferState* |
303 AsyncPixelTransferDelegateAndroid:: | 312 AsyncPixelTransferDelegateAndroid:: |
304 CreateRawPixelTransferState(GLuint texture_id) { | 313 CreateRawPixelTransferState(GLuint texture_id) { |
305 return static_cast<AsyncPixelTransferState*>( | 314 return static_cast<AsyncPixelTransferState*>( |
306 new AsyncTransferStateAndroid(texture_id)); | 315 new AsyncTransferStateAndroid(texture_id)); |
307 } | 316 } |
308 | 317 |
309 namespace { | 318 namespace { |
310 // Dummy function to measure completion on | 319 // Dummy function to measure completion on |
311 // the upload thread. | 320 // the upload thread. |
312 void NoOp() {} | 321 void NoOp() {} |
313 } // namespace | 322 } // namespace |
314 | 323 |
315 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( | 324 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( |
316 const base::Closure& task) { | 325 const base::Closure& task) { |
317 // Post a no-op task to the upload thread followed | 326 // Post a no-op task to the upload thread followed |
318 // by a reply to the callback. The reply will then occur after | 327 // by a reply to the callback. The reply will then occur after |
319 // all async transfers are complete. | 328 // all async transfers are complete. |
320 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, | 329 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, |
321 base::Bind(&NoOp), task); | 330 base::Bind(&NoOp), task); |
322 } | 331 } |
323 | 332 |
324 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( | 333 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( |
325 AsyncPixelTransferState* transfer_state, | 334 AsyncPixelTransferState* transfer_state, |
326 const AsyncTexImage2DParams& tex_params, | 335 const AsyncTexImage2DParams& tex_params, |
327 const AsyncMemoryParams& mem_params) { | 336 const AsyncMemoryParams& mem_params) { |
328 TransferStateInternal* state = | 337 scoped_refptr<TransferStateInternal> state = |
329 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); | 338 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
330 DCHECK(mem_params.shared_memory); | 339 DCHECK(mem_params.shared_memory); |
| 340 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
| 341 mem_params.shm_size); |
331 DCHECK(state); | 342 DCHECK(state); |
332 DCHECK(state->texture_id_); | 343 DCHECK(state->texture_id_); |
333 DCHECK(!state->needs_late_bind_); | 344 DCHECK(!state->needs_late_bind_); |
334 DCHECK(!state->transfer_in_progress_); | 345 DCHECK(!state->transfer_in_progress_); |
335 DCHECK_EQ(state->egl_image_, EGL_NO_IMAGE_KHR); | 346 DCHECK_EQ(state->egl_image_, EGL_NO_IMAGE_KHR); |
336 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 347 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
337 DCHECK_EQ(tex_params.level, 0); | 348 DCHECK_EQ(tex_params.level, 0); |
338 | 349 |
339 // Mark the transfer in progress and save define params for lazy binding. | 350 // Mark the transfer in progress and save define params for lazy binding. |
340 state->transfer_in_progress_ = true; | 351 state->transfer_in_progress_ = true; |
341 state->late_bind_define_params_ = tex_params; | 352 state->late_bind_define_params_ = tex_params; |
342 | 353 |
343 // Duplicate the shared memory so there are no way we can get | 354 // Duplicate the shared memory so there are no way we can get |
344 // a use-after-free of the raw pixels. | 355 // a use-after-free of the raw pixels. |
345 // TODO: Could we pass an own pointer of the new SharedMemory to the task? | |
346 AsyncMemoryParams duped_mem = mem_params; | |
347 duped_mem.shared_memory = DuplicateSharedMemory(mem_params.shared_memory, | |
348 mem_params.shm_size); | |
349 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, | 356 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, |
350 base::Bind( | 357 base::Bind( |
351 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D, | 358 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D, |
352 base::Unretained(state), // This is referenced in reply below. | 359 base::Unretained(state.get()), // This is referenced in reply below. |
353 tex_params, | 360 tex_params, |
354 duped_mem), | 361 base::Owned(DuplicateSharedMemory(mem_params.shared_memory, |
| 362 mem_params.shm_size)), |
| 363 mem_params.shm_data_offset), |
355 base::Bind( | 364 base::Bind( |
356 &TransferStateInternal::TexImage2DCompleted, | 365 &AsyncPixelTransferDelegateAndroid::AsyncTexImage2DCompleted, |
| 366 AsWeakPtr(), |
357 state)); | 367 state)); |
358 | 368 |
359 DCHECK(CHECK_GL()); | 369 DCHECK(CHECK_GL()); |
360 } | 370 } |
361 | 371 |
362 void AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2D( | 372 void AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2D( |
363 AsyncPixelTransferState* transfer_state, | 373 AsyncPixelTransferState* transfer_state, |
364 const AsyncTexSubImage2DParams& tex_params, | 374 const AsyncTexSubImage2DParams& tex_params, |
365 const AsyncMemoryParams& mem_params) { | 375 const AsyncMemoryParams& mem_params) { |
366 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", | 376 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", |
367 "width", tex_params.width, | 377 "width", tex_params.width, |
368 "height", tex_params.height); | 378 "height", tex_params.height); |
369 TransferStateInternal* state = | 379 scoped_refptr<TransferStateInternal> state = |
370 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); | 380 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
371 DCHECK(state->texture_id_); | 381 DCHECK(state->texture_id_); |
372 DCHECK(!state->transfer_in_progress_); | 382 DCHECK(!state->transfer_in_progress_); |
373 DCHECK(mem_params.shared_memory); | 383 DCHECK(mem_params.shared_memory); |
| 384 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
| 385 mem_params.shm_size); |
374 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 386 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
375 DCHECK_EQ(tex_params.level, 0); | 387 DCHECK_EQ(tex_params.level, 0); |
376 | 388 |
377 // Mark the transfer in progress. | 389 // Mark the transfer in progress. |
378 state->transfer_in_progress_ = true; | 390 state->transfer_in_progress_ = true; |
379 | 391 |
380 // Create the EGLImage if it hasn't already been created. | 392 // Create the EGLImage if it hasn't already been created. |
381 if (!state->egl_image_) { | 393 if (!state->egl_image_) { |
382 TRACE_EVENT0("gpu", "eglCreateImageKHR"); | 394 TRACE_EVENT0("gpu", "eglCreateImageKHR"); |
383 EGLDisplay egl_display = eglGetCurrentDisplay(); | 395 EGLDisplay egl_display = eglGetCurrentDisplay(); |
384 EGLContext egl_context = eglGetCurrentContext(); | 396 EGLContext egl_context = eglGetCurrentContext(); |
385 EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; | 397 EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; |
386 EGLClientBuffer egl_buffer = | 398 EGLClientBuffer egl_buffer = |
387 reinterpret_cast<EGLClientBuffer>(state->texture_id_); | 399 reinterpret_cast<EGLClientBuffer>(state->texture_id_); |
388 EGLint egl_attrib_list[] = { | 400 EGLint egl_attrib_list[] = { |
389 EGL_GL_TEXTURE_LEVEL_KHR, tex_params.level, // mip-level to reference. | 401 EGL_GL_TEXTURE_LEVEL_KHR, tex_params.level, // mip-level to reference. |
390 EGL_IMAGE_PRESERVED_KHR, EGL_FALSE, // throw away texture data. | 402 EGL_IMAGE_PRESERVED_KHR, EGL_FALSE, // throw away texture data. |
391 EGL_NONE | 403 EGL_NONE |
392 }; | 404 }; |
393 state->egl_image_ = eglCreateImageKHR( | 405 state->egl_image_ = eglCreateImageKHR( |
394 egl_display, | 406 egl_display, |
395 egl_context, | 407 egl_context, |
396 egl_target, | 408 egl_target, |
397 egl_buffer, | 409 egl_buffer, |
398 egl_attrib_list); | 410 egl_attrib_list); |
399 } | 411 } |
400 | 412 |
401 // Duplicate the shared memory so there are no way we can get | 413 // Duplicate the shared memory so there are no way we can get |
402 // a use-after-free of the raw pixels. | 414 // a use-after-free of the raw pixels. |
403 // TODO: Could we pass an own pointer of the new SharedMemory to the task? | |
404 AsyncMemoryParams duped_mem = mem_params; | |
405 duped_mem.shared_memory = DuplicateSharedMemory(mem_params.shared_memory, | |
406 mem_params.shm_size); | |
407 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, | 415 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, |
408 base::Bind( | 416 base::Bind( |
409 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D, | 417 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D, |
410 base::Unretained(state), // This is referenced in reply below. | 418 base::Unretained(state.get()), // This is referenced in reply below. |
411 tex_params, | 419 tex_params, |
412 duped_mem), | 420 base::Owned(DuplicateSharedMemory(mem_params.shared_memory, |
| 421 mem_params.shm_size)), |
| 422 mem_params.shm_data_offset), |
413 base::Bind( | 423 base::Bind( |
414 &TransferStateInternal::TexSubImage2DCompleted, | 424 &AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2DCompleted, |
| 425 AsWeakPtr(), |
415 state)); | 426 state)); |
416 | 427 |
417 DCHECK(CHECK_GL()); | 428 DCHECK(CHECK_GL()); |
418 } | 429 } |
419 | 430 |
| 431 uint32 AsyncPixelTransferDelegateAndroid::GetTextureUploadCount() { |
| 432 return texture_upload_count_; |
| 433 } |
| 434 |
| 435 base::TimeDelta AsyncPixelTransferDelegateAndroid::GetTotalTextureUploadTime() { |
| 436 return total_texture_upload_time_; |
| 437 } |
| 438 |
| 439 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2DCompleted( |
| 440 scoped_refptr<TransferStateInternal> state) { |
| 441 state->needs_late_bind_ = true; |
| 442 state->transfer_in_progress_ = false; |
| 443 } |
| 444 |
| 445 void AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2DCompleted( |
| 446 scoped_refptr<TransferStateInternal> state) { |
| 447 state->transfer_in_progress_ = false; |
| 448 texture_upload_count_++; |
| 449 total_texture_upload_time_ += state->last_transfer_time_; |
| 450 } |
| 451 |
420 namespace { | 452 namespace { |
421 void WaitForGl() { | 453 void WaitForGl() { |
422 TRACE_EVENT0("gpu", "eglWaitSync"); | 454 TRACE_EVENT0("gpu", "eglWaitSync"); |
423 | 455 |
424 // Uploads usually finish on the CPU, but just in case add a fence | 456 // Uploads usually finish on the CPU, but just in case add a fence |
425 // and guarantee the upload has completed. The flush bit is set to | 457 // and guarantee the upload has completed. The flush bit is set to |
426 // insure we don't wait forever. | 458 // insure we don't wait forever. |
427 EGLDisplay display = eglGetCurrentDisplay(); | 459 EGLDisplay display = eglGetCurrentDisplay(); |
428 EGLSyncKHR fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL); | 460 EGLSyncKHR fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL); |
429 EGLint flags = EGL_SYNC_FLUSH_COMMANDS_BIT_KHR; | 461 EGLint flags = EGL_SYNC_FLUSH_COMMANDS_BIT_KHR; |
430 EGLTimeKHR time = EGL_FOREVER_KHR; | 462 EGLTimeKHR time = EGL_FOREVER_KHR; |
431 | 463 |
432 // This fence is basically like calling glFinish, which is fine if | 464 // This fence is basically like calling glFinish, which is fine if |
433 // uploads occur on the CPU. If some upload work occurs on the GPU, | 465 // uploads occur on the CPU. If some upload work occurs on the GPU, |
434 // we may want to delay blocking on the fence. | 466 // we may want to delay blocking on the fence. |
435 eglClientWaitSyncKHR(display, fence, flags, time); | 467 eglClientWaitSyncKHR(display, fence, flags, time); |
436 eglDestroySyncKHR(display, fence); | 468 eglDestroySyncKHR(display, fence); |
437 } | 469 } |
438 } // namespace | 470 } // namespace |
439 | 471 |
440 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D( | 472 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D( |
441 TransferStateInternal* state, | 473 TransferStateInternal* state, |
442 AsyncTexImage2DParams tex_params, | 474 AsyncTexImage2DParams tex_params, |
443 AsyncMemoryParams mem_params) { | 475 base::SharedMemory* shared_memory, |
| 476 uint32 shared_memory_data_offset) { |
444 TRACE_EVENT2("gpu", "PerformAsyncTexImage", | 477 TRACE_EVENT2("gpu", "PerformAsyncTexImage", |
445 "width", tex_params.width, | 478 "width", tex_params.width, |
446 "height", tex_params.height); | 479 "height", tex_params.height); |
447 DCHECK(state); | 480 DCHECK(state); |
448 DCHECK(!state->thread_texture_id_); | 481 DCHECK(!state->thread_texture_id_); |
449 DCHECK_EQ(0, tex_params.level); | 482 DCHECK_EQ(0, tex_params.level); |
450 DCHECK_EQ(EGL_NO_IMAGE_KHR, state->egl_image_); | 483 DCHECK_EQ(EGL_NO_IMAGE_KHR, state->egl_image_); |
451 | 484 |
452 // TODO(epenner): This is just to insure it is deleted. Could bind() do this? | 485 void* data = GetAddress(shared_memory, shared_memory_data_offset); |
453 scoped_ptr<SharedMemory> shared_memory = | |
454 make_scoped_ptr(mem_params.shared_memory); | |
455 | |
456 void* data = GetAddress(mem_params.shared_memory, | |
457 mem_params.shm_size, | |
458 mem_params.shm_data_offset, | |
459 mem_params.shm_data_size); | |
460 { | 486 { |
461 TRACE_EVENT0("gpu", "glTexImage2D no data"); | 487 TRACE_EVENT0("gpu", "glTexImage2D no data"); |
462 glGenTextures(1, &state->thread_texture_id_); | 488 glGenTextures(1, &state->thread_texture_id_); |
463 glActiveTexture(GL_TEXTURE0); | 489 glActiveTexture(GL_TEXTURE0); |
464 glBindTexture(GL_TEXTURE_2D, state->thread_texture_id_); | 490 glBindTexture(GL_TEXTURE_2D, state->thread_texture_id_); |
465 | 491 |
466 // These params are needed for EGLImage creation to succeed on several | 492 // These params are needed for EGLImage creation to succeed on several |
467 // Android devices. I couldn't find this requirement in the EGLImage | 493 // Android devices. I couldn't find this requirement in the EGLImage |
468 // extension spec, but several devices fail without it. | 494 // extension spec, but several devices fail without it. |
469 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | 495 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 data); | 542 data); |
517 } | 543 } |
518 | 544 |
519 WaitForGl(); | 545 WaitForGl(); |
520 DCHECK(CHECK_GL()); | 546 DCHECK(CHECK_GL()); |
521 } | 547 } |
522 | 548 |
523 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D( | 549 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D( |
524 TransferStateInternal* state, | 550 TransferStateInternal* state, |
525 AsyncTexSubImage2DParams tex_params, | 551 AsyncTexSubImage2DParams tex_params, |
526 AsyncMemoryParams mem_params) { | 552 base::SharedMemory* shared_memory, |
| 553 uint32 shared_memory_data_offset) { |
527 TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D", | 554 TRACE_EVENT2("gpu", "PerformAsyncTexSubImage2D", |
528 "width", tex_params.width, | 555 "width", tex_params.width, |
529 "height", tex_params.height); | 556 "height", tex_params.height); |
530 | 557 |
531 DCHECK(state); | 558 DCHECK(state); |
532 DCHECK_NE(EGL_NO_IMAGE_KHR, state->egl_image_); | 559 DCHECK_NE(EGL_NO_IMAGE_KHR, state->egl_image_); |
533 DCHECK_EQ(0, tex_params.level); | 560 DCHECK_EQ(0, tex_params.level); |
534 | 561 |
535 // TODO(epenner): This is just to insure it is deleted. Could bind() do this? | 562 void* data = GetAddress(shared_memory, shared_memory_data_offset); |
536 scoped_ptr<SharedMemory> shared_memory = | |
537 make_scoped_ptr(mem_params.shared_memory); | |
538 | 563 |
539 void* data = GetAddress(mem_params.shared_memory, | 564 base::TimeTicks begin_time(base::TimeTicks::HighResNow()); |
540 mem_params.shm_size, | |
541 mem_params.shm_data_offset, | |
542 mem_params.shm_data_size); | |
543 | |
544 if (!state->thread_texture_id_) { | 565 if (!state->thread_texture_id_) { |
545 TRACE_EVENT0("gpu", "glEGLImageTargetTexture2DOES"); | 566 TRACE_EVENT0("gpu", "glEGLImageTargetTexture2DOES"); |
546 glGenTextures(1, &state->thread_texture_id_); | 567 glGenTextures(1, &state->thread_texture_id_); |
547 glActiveTexture(GL_TEXTURE0); | 568 glActiveTexture(GL_TEXTURE0); |
548 glBindTexture(GL_TEXTURE_2D, state->thread_texture_id_); | 569 glBindTexture(GL_TEXTURE_2D, state->thread_texture_id_); |
549 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, state->egl_image_); | 570 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, state->egl_image_); |
550 } else { | 571 } else { |
551 glActiveTexture(GL_TEXTURE0); | 572 glActiveTexture(GL_TEXTURE0); |
552 glBindTexture(GL_TEXTURE_2D, state->thread_texture_id_); | 573 glBindTexture(GL_TEXTURE_2D, state->thread_texture_id_); |
553 } | 574 } |
554 { | 575 { |
555 TRACE_EVENT0("gpu", "glTexSubImage2D"); | 576 TRACE_EVENT0("gpu", "glTexSubImage2D"); |
556 glTexSubImage2D( | 577 glTexSubImage2D( |
557 GL_TEXTURE_2D, | 578 GL_TEXTURE_2D, |
558 tex_params.level, | 579 tex_params.level, |
559 tex_params.xoffset, | 580 tex_params.xoffset, |
560 tex_params.yoffset, | 581 tex_params.yoffset, |
561 tex_params.width, | 582 tex_params.width, |
562 tex_params.height, | 583 tex_params.height, |
563 tex_params.format, | 584 tex_params.format, |
564 tex_params.type, | 585 tex_params.type, |
565 data); | 586 data); |
566 } | 587 } |
567 WaitForGl(); | 588 WaitForGl(); |
568 | 589 |
569 DCHECK(CHECK_GL()); | 590 DCHECK(CHECK_GL()); |
| 591 state->last_transfer_time_ = base::TimeTicks::HighResNow() - begin_time; |
570 } | 592 } |
571 | 593 |
572 } // namespace gfx | 594 } // namespace gfx |
OLD | NEW |