| 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 |