Chromium Code Reviews| 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 <sys/resource.h> | 7 #include <sys/resource.h> |
| 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 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 147 } | 147 } |
| 148 | 148 |
| 149 void BindTransfer(AsyncTexImage2DParams* bound_params) { | 149 void BindTransfer(AsyncTexImage2DParams* bound_params) { |
| 150 DCHECK(bound_params); | 150 DCHECK(bound_params); |
| 151 DCHECK(needs_late_bind_); | 151 DCHECK(needs_late_bind_); |
| 152 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_); | 152 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, egl_image_); |
| 153 *bound_params = late_bind_define_params_; | 153 *bound_params = late_bind_define_params_; |
| 154 needs_late_bind_ = false; | 154 needs_late_bind_ = false; |
| 155 } | 155 } |
| 156 | 156 |
| 157 // Completion callbacks. | 157 protected: |
| 158 void TexImage2DCompleted() { | |
| 159 needs_late_bind_ = true; | |
| 160 transfer_in_progress_ = false; | |
| 161 } | |
| 162 void TexSubImage2DCompleted() { | |
| 163 transfer_in_progress_ = false; | |
| 164 } | |
| 165 | |
| 166 protected: | |
| 167 friend class base::RefCountedThreadSafe<TransferStateInternal>; | 158 friend class base::RefCountedThreadSafe<TransferStateInternal>; |
| 168 friend class AsyncPixelTransferDelegateAndroid; | 159 friend class AsyncPixelTransferDelegateAndroid; |
| 169 | 160 |
| 170 virtual ~TransferStateInternal() { | 161 virtual ~TransferStateInternal() { |
| 171 if (egl_image_) { | 162 if (egl_image_) { |
| 172 EGLDisplay display = eglGetCurrentDisplay(); | 163 EGLDisplay display = eglGetCurrentDisplay(); |
| 173 eglDestroyImageKHR(display, egl_image_); | 164 eglDestroyImageKHR(display, egl_image_); |
| 174 } | 165 } |
| 175 } | 166 } |
| 176 | 167 |
| 177 // The 'real' texture. | 168 // The 'real' texture. |
| 178 GLuint texture_id_; | 169 GLuint texture_id_; |
| 179 | 170 |
| 180 // Indicates there is a new EGLImage and the 'real' | 171 // Indicates there is a new EGLImage and the 'real' |
| 181 // texture needs to be bound to it as an EGLImage target. | 172 // texture needs to be bound to it as an EGLImage target. |
| 182 bool needs_late_bind_; | 173 bool needs_late_bind_; |
| 183 | 174 |
| 184 // Definition params for texture that needs binding. | 175 // Definition params for texture that needs binding. |
| 185 AsyncTexImage2DParams late_bind_define_params_; | 176 AsyncTexImage2DParams late_bind_define_params_; |
| 186 | 177 |
| 187 // Indicates that an async transfer is in progress. | 178 // Indicates that an async transfer is in progress. |
| 188 bool transfer_in_progress_; | 179 bool transfer_in_progress_; |
| 189 | 180 |
| 190 // It would be nice if we could just create a new EGLImage for | 181 // It would be nice if we could just create a new EGLImage for |
| 191 // every upload, but I found that didn't work, so this stores | 182 // every upload, but I found that didn't work, so this stores |
| 192 // one for the lifetime of the texture. | 183 // one for the lifetime of the texture. |
| 193 EGLImageKHR egl_image_; | 184 EGLImageKHR egl_image_; |
| 185 | |
| 186 // Time spent performing last transfer. | |
| 187 base::TimeDelta last_transfer_time_; | |
| 194 }; | 188 }; |
| 195 | 189 |
| 196 // Android needs thread-safe ref-counting, so this just wraps | 190 // Android needs thread-safe ref-counting, so this just wraps |
| 197 // an internal thread-safe ref-counted state object. | 191 // an internal thread-safe ref-counted state object. |
| 198 class AsyncTransferStateAndroid : public AsyncPixelTransferState { | 192 class AsyncTransferStateAndroid : public AsyncPixelTransferState { |
| 199 public: | 193 public: |
| 200 explicit AsyncTransferStateAndroid(GLuint texture_id) | 194 explicit AsyncTransferStateAndroid(GLuint texture_id) |
| 201 : internal_(new TransferStateInternal(texture_id)) { | 195 : internal_(new TransferStateInternal(texture_id)) { |
| 202 } | 196 } |
| 203 virtual ~AsyncTransferStateAndroid() {} | 197 virtual ~AsyncTransferStateAndroid() {} |
| 204 virtual bool TransferIsInProgress() { | 198 virtual bool TransferIsInProgress() { |
| 205 return internal_->TransferIsInProgress(); | 199 return internal_->TransferIsInProgress(); |
| 206 } | 200 } |
| 207 virtual void BindTransfer(AsyncTexImage2DParams* bound_params) { | 201 virtual void BindTransfer(AsyncTexImage2DParams* bound_params) { |
| 208 internal_->BindTransfer(bound_params); | 202 internal_->BindTransfer(bound_params); |
| 209 } | 203 } |
| 210 scoped_refptr<TransferStateInternal> internal_; | 204 scoped_refptr<TransferStateInternal> internal_; |
| 211 }; | 205 }; |
| 212 | 206 |
| 213 // Class which handles async pixel transfers on Android (using | 207 // Class which handles async pixel transfers on Android (using |
| 214 // EGLImageKHR and another upload thread) | 208 // EGLImageKHR and another upload thread) |
| 215 class AsyncPixelTransferDelegateAndroid : public AsyncPixelTransferDelegate { | 209 class AsyncPixelTransferDelegateAndroid : public AsyncPixelTransferDelegate { |
| 216 public: | 210 public: |
| 217 AsyncPixelTransferDelegateAndroid() {} | 211 AsyncPixelTransferDelegateAndroid(); |
| 218 virtual ~AsyncPixelTransferDelegateAndroid() {} | 212 virtual ~AsyncPixelTransferDelegateAndroid(); |
| 219 | 213 |
| 220 // implement AsyncPixelTransferDelegate: | 214 // implement AsyncPixelTransferDelegate: |
| 221 virtual void AsyncNotifyCompletion( | 215 virtual void AsyncNotifyCompletion( |
| 222 const base::Closure& task) OVERRIDE; | 216 const base::Closure& task) OVERRIDE; |
| 223 virtual void AsyncTexImage2D( | 217 virtual void AsyncTexImage2D( |
| 224 AsyncPixelTransferState* state, | 218 AsyncPixelTransferState* state, |
| 225 const AsyncTexImage2DParams& tex_params, | 219 const AsyncTexImage2DParams& tex_params, |
| 226 const AsyncMemoryParams& mem_params) OVERRIDE; | 220 const AsyncMemoryParams& mem_params) OVERRIDE; |
| 227 virtual void AsyncTexSubImage2D( | 221 virtual void AsyncTexSubImage2D( |
| 228 AsyncPixelTransferState* state, | 222 AsyncPixelTransferState* state, |
| 229 const AsyncTexSubImage2DParams& tex_params, | 223 const AsyncTexSubImage2DParams& tex_params, |
| 230 const AsyncMemoryParams& mem_params) OVERRIDE; | 224 const AsyncMemoryParams& mem_params) OVERRIDE; |
| 225 virtual uint32 GetTextureUploadCount() OVERRIDE; | |
| 226 virtual base::TimeDelta GetTotalTextureUploadTime() OVERRIDE; | |
| 231 | 227 |
| 232 private: | 228 private: |
| 233 // implement AsyncPixelTransferDelegate: | 229 // implement AsyncPixelTransferDelegate: |
| 234 virtual AsyncPixelTransferState* | 230 virtual AsyncPixelTransferState* |
| 235 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; | 231 CreateRawPixelTransferState(GLuint texture_id) OVERRIDE; |
| 236 | 232 |
| 237 base::MessageLoopProxy* transfer_message_loop_proxy() { | 233 base::MessageLoopProxy* transfer_message_loop_proxy() { |
| 238 return g_transfer_thread.Pointer()->message_loop_proxy(); | 234 return g_transfer_thread.Pointer()->message_loop_proxy(); |
| 239 } | 235 } |
| 236 | |
| 237 void AsyncTexImage2DCompleted(scoped_refptr<TransferStateInternal> state); | |
| 238 void AsyncTexSubImage2DCompleted(scoped_refptr<TransferStateInternal> state); | |
| 239 | |
| 240 static void PerformAsyncTexImage2D( | 240 static void PerformAsyncTexImage2D( |
| 241 TransferStateInternal* state, | 241 TransferStateInternal* state, |
| 242 AsyncTexImage2DParams tex_params, | 242 AsyncTexImage2DParams tex_params, |
| 243 AsyncMemoryParams mem_params); | 243 base::SharedMemory* shared_memory, |
|
epenner
2012/12/22 03:22:42
Is there no way to keep this as one parameter? No
epenner
2012/12/22 20:48:17
Hmm, could we just pass a "Safe" shared memory par
reveman
2012/12/22 21:56:24
I guess we could do that. I removed shared_memory_
| |
| 244 uint32 shared_memory_size, | |
| 245 uint32 shared_memory_data_offset, | |
| 246 uint32 shared_memory_data_size); | |
| 244 static void PerformAsyncTexSubImage2D( | 247 static void PerformAsyncTexSubImage2D( |
| 245 TransferStateInternal* state, | 248 TransferStateInternal* state, |
| 246 AsyncTexSubImage2DParams tex_params, | 249 AsyncTexSubImage2DParams tex_params, |
| 247 AsyncMemoryParams mem_params); | 250 base::SharedMemory* shared_memory, |
| 251 uint32 shared_memory_size, | |
| 252 uint32 shared_memory_data_offset, | |
| 253 uint32 shared_memory_data_size); | |
| 254 | |
| 255 int texture_upload_count_; | |
| 256 base::TimeDelta total_texture_upload_time_; | |
| 248 | 257 |
| 249 DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateAndroid); | 258 DISALLOW_COPY_AND_ASSIGN(AsyncPixelTransferDelegateAndroid); |
| 250 }; | 259 }; |
| 251 | 260 |
| 252 // We only used threaded uploads when we can: | 261 // We only used threaded uploads when we can: |
| 253 // - Create EGLImages out of OpenGL textures (EGL_KHR_gl_texture_2D_image) | 262 // - Create EGLImages out of OpenGL textures (EGL_KHR_gl_texture_2D_image) |
| 254 // - Bind EGLImages to OpenGL textures (GL_OES_EGL_image) | 263 // - Bind EGLImages to OpenGL textures (GL_OES_EGL_image) |
| 255 // - Use fences (to test for upload completion). | 264 // - Use fences (to test for upload completion). |
| 256 scoped_ptr<AsyncPixelTransferDelegate> | 265 scoped_ptr<AsyncPixelTransferDelegate> |
| 257 AsyncPixelTransferDelegate::Create(gfx::GLContext* context) { | 266 AsyncPixelTransferDelegate::Create(gfx::GLContext* context) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 269 static_cast<AsyncPixelTransferDelegate*>( | 278 static_cast<AsyncPixelTransferDelegate*>( |
| 270 new AsyncPixelTransferDelegateAndroid())); | 279 new AsyncPixelTransferDelegateAndroid())); |
| 271 } else { | 280 } else { |
| 272 LOG(INFO) << "Async pixel transfers not supported"; | 281 LOG(INFO) << "Async pixel transfers not supported"; |
| 273 return make_scoped_ptr( | 282 return make_scoped_ptr( |
| 274 static_cast<AsyncPixelTransferDelegate*>( | 283 static_cast<AsyncPixelTransferDelegate*>( |
| 275 new AsyncPixelTransferDelegateStub())); | 284 new AsyncPixelTransferDelegateStub())); |
| 276 } | 285 } |
| 277 } | 286 } |
| 278 | 287 |
| 288 AsyncPixelTransferDelegateAndroid::AsyncPixelTransferDelegateAndroid() | |
| 289 : texture_upload_count_(0) { | |
| 290 } | |
| 291 | |
| 292 AsyncPixelTransferDelegateAndroid::~AsyncPixelTransferDelegateAndroid() { | |
| 293 } | |
| 294 | |
| 279 AsyncPixelTransferState* | 295 AsyncPixelTransferState* |
| 280 AsyncPixelTransferDelegateAndroid:: | 296 AsyncPixelTransferDelegateAndroid:: |
| 281 CreateRawPixelTransferState(GLuint texture_id) { | 297 CreateRawPixelTransferState(GLuint texture_id) { |
| 282 return static_cast<AsyncPixelTransferState*>( | 298 return static_cast<AsyncPixelTransferState*>( |
| 283 new AsyncTransferStateAndroid(texture_id)); | 299 new AsyncTransferStateAndroid(texture_id)); |
| 284 } | 300 } |
| 285 | 301 |
| 286 namespace { | 302 namespace { |
| 287 // Dummy function to measure completion on | 303 // Dummy function to measure completion on |
| 288 // the upload thread. | 304 // the upload thread. |
| 289 void NoOp() {} | 305 void NoOp() {} |
| 290 } // namespace | 306 } // namespace |
| 291 | 307 |
| 292 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( | 308 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( |
| 293 const base::Closure& task) { | 309 const base::Closure& task) { |
| 294 // Post a no-op task to the upload thread followed | 310 // Post a no-op task to the upload thread followed |
| 295 // by a reply to the callback. The reply will then occur after | 311 // by a reply to the callback. The reply will then occur after |
| 296 // all async transfers are complete. | 312 // all async transfers are complete. |
| 297 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, | 313 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, |
| 298 base::Bind(&NoOp), task); | 314 base::Bind(&NoOp), task); |
| 299 } | 315 } |
| 300 | 316 |
| 301 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( | 317 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2D( |
| 302 AsyncPixelTransferState* transfer_state, | 318 AsyncPixelTransferState* transfer_state, |
| 303 const AsyncTexImage2DParams& tex_params, | 319 const AsyncTexImage2DParams& tex_params, |
| 304 const AsyncMemoryParams& mem_params) { | 320 const AsyncMemoryParams& mem_params) { |
| 305 TransferStateInternal* state = | 321 scoped_refptr<TransferStateInternal> state = |
| 306 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); | 322 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
| 307 DCHECK(mem_params.shared_memory); | 323 DCHECK(mem_params.shared_memory); |
| 308 DCHECK(state); | 324 DCHECK(state); |
| 309 DCHECK(state->texture_id_); | 325 DCHECK(state->texture_id_); |
| 310 DCHECK(!state->needs_late_bind_); | 326 DCHECK(!state->needs_late_bind_); |
| 311 DCHECK(!state->transfer_in_progress_); | 327 DCHECK(!state->transfer_in_progress_); |
| 312 DCHECK_EQ(state->egl_image_, EGL_NO_IMAGE_KHR); | 328 DCHECK_EQ(state->egl_image_, EGL_NO_IMAGE_KHR); |
| 313 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 329 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
| 314 DCHECK_EQ(tex_params.level, 0); | 330 DCHECK_EQ(tex_params.level, 0); |
| 315 | 331 |
| 316 // Mark the transfer in progress and save define params for lazy binding. | 332 // Mark the transfer in progress and save define params for lazy binding. |
| 317 state->transfer_in_progress_ = true; | 333 state->transfer_in_progress_ = true; |
| 318 state->late_bind_define_params_ = tex_params; | 334 state->late_bind_define_params_ = tex_params; |
| 319 | 335 |
| 320 // Duplicate the shared memory so there are no way we can get | 336 // Duplicate the shared memory so there are no way we can get |
| 321 // a use-after-free of the raw pixels. | 337 // a use-after-free of the raw pixels. |
| 322 // TODO: Could we pass an own pointer of the new SharedMemory to the task? | |
| 323 AsyncMemoryParams duped_mem = mem_params; | |
| 324 duped_mem.shared_memory = DuplicateSharedMemory(mem_params.shared_memory, | |
| 325 mem_params.shm_size); | |
| 326 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, | 338 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, |
| 327 base::Bind( | 339 base::Bind( |
| 328 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D, | 340 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D, |
| 329 base::Unretained(state), // This is referenced in reply below. | 341 base::Unretained(state.get()), // This is referenced in reply below. |
| 330 tex_params, | 342 tex_params, |
| 331 duped_mem), | 343 base::Owned(DuplicateSharedMemory(mem_params.shared_memory, |
| 344 mem_params.shm_size)), | |
| 345 mem_params.shm_size, | |
| 346 mem_params.shm_data_offset, | |
| 347 mem_params.shm_data_size), | |
| 332 base::Bind( | 348 base::Bind( |
| 333 &TransferStateInternal::TexImage2DCompleted, | 349 &AsyncPixelTransferDelegateAndroid::AsyncTexImage2DCompleted, |
| 350 base::Unretained(this), | |
|
epenner
2012/12/22 03:22:42
I don't think it's safe to pass this pointer as is
reveman
2012/12/22 21:56:24
added support for weak pointer in latest patch. it
| |
| 334 state)); | 351 state)); |
| 335 } | 352 } |
| 336 | 353 |
| 337 void AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2D( | 354 void AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2D( |
| 338 AsyncPixelTransferState* transfer_state, | 355 AsyncPixelTransferState* transfer_state, |
| 339 const AsyncTexSubImage2DParams& tex_params, | 356 const AsyncTexSubImage2DParams& tex_params, |
| 340 const AsyncMemoryParams& mem_params) { | 357 const AsyncMemoryParams& mem_params) { |
| 341 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", | 358 TRACE_EVENT2("gpu", "AsyncTexSubImage2D", |
| 342 "width", tex_params.width, | 359 "width", tex_params.width, |
| 343 "height", tex_params.height); | 360 "height", tex_params.height); |
| 344 TransferStateInternal* state = | 361 scoped_refptr<TransferStateInternal> state = |
| 345 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); | 362 static_cast<AsyncTransferStateAndroid*>(transfer_state)->internal_.get(); |
| 346 DCHECK(state->texture_id_); | 363 DCHECK(state->texture_id_); |
| 347 DCHECK(!state->transfer_in_progress_); | 364 DCHECK(!state->transfer_in_progress_); |
| 348 DCHECK(mem_params.shared_memory); | 365 DCHECK(mem_params.shared_memory); |
| 349 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); | 366 DCHECK_EQ(static_cast<GLenum>(GL_TEXTURE_2D), tex_params.target); |
| 350 DCHECK_EQ(tex_params.level, 0); | 367 DCHECK_EQ(tex_params.level, 0); |
| 351 | 368 |
| 352 // Mark the transfer in progress. | 369 // Mark the transfer in progress. |
| 353 state->transfer_in_progress_ = true; | 370 state->transfer_in_progress_ = true; |
| 354 | 371 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 367 state->egl_image_ = eglCreateImageKHR( | 384 state->egl_image_ = eglCreateImageKHR( |
| 368 egl_display, | 385 egl_display, |
| 369 egl_context, | 386 egl_context, |
| 370 egl_target, | 387 egl_target, |
| 371 egl_buffer, | 388 egl_buffer, |
| 372 egl_attrib_list); | 389 egl_attrib_list); |
| 373 } | 390 } |
| 374 | 391 |
| 375 // Duplicate the shared memory so there are no way we can get | 392 // Duplicate the shared memory so there are no way we can get |
| 376 // a use-after-free of the raw pixels. | 393 // a use-after-free of the raw pixels. |
| 377 // TODO: Could we pass an own pointer of the new SharedMemory to the task? | |
| 378 AsyncMemoryParams duped_mem = mem_params; | |
| 379 duped_mem.shared_memory = DuplicateSharedMemory(mem_params.shared_memory, | |
| 380 mem_params.shm_size); | |
| 381 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, | 394 transfer_message_loop_proxy()->PostTaskAndReply(FROM_HERE, |
| 382 base::Bind( | 395 base::Bind( |
| 383 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D, | 396 &AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D, |
| 384 base::Unretained(state), // This is referenced in reply below. | 397 base::Unretained(state.get()), // This is referenced in reply below. |
| 385 tex_params, | 398 tex_params, |
| 386 duped_mem), | 399 base::Owned(DuplicateSharedMemory(mem_params.shared_memory, |
| 400 mem_params.shm_size)), | |
| 401 mem_params.shm_size, | |
| 402 mem_params.shm_data_offset, | |
| 403 mem_params.shm_data_size), | |
| 387 base::Bind( | 404 base::Bind( |
| 388 &TransferStateInternal::TexSubImage2DCompleted, | 405 &AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2DCompleted, |
| 406 base::Unretained(this), | |
| 389 state)); | 407 state)); |
| 390 } | 408 } |
| 391 | 409 |
| 410 uint32 AsyncPixelTransferDelegateAndroid::GetTextureUploadCount() { | |
| 411 return texture_upload_count_; | |
| 412 } | |
| 413 | |
| 414 base::TimeDelta AsyncPixelTransferDelegateAndroid::GetTotalTextureUploadTime() { | |
| 415 return total_texture_upload_time_; | |
| 416 } | |
| 417 | |
| 418 void AsyncPixelTransferDelegateAndroid::AsyncTexImage2DCompleted( | |
| 419 scoped_refptr<TransferStateInternal> state) { | |
| 420 state->needs_late_bind_ = true; | |
| 421 state->transfer_in_progress_ = false; | |
| 422 } | |
| 423 | |
| 424 void AsyncPixelTransferDelegateAndroid::AsyncTexSubImage2DCompleted( | |
| 425 scoped_refptr<TransferStateInternal> state) { | |
| 426 state->transfer_in_progress_ = false; | |
| 427 texture_upload_count_++; | |
| 428 total_texture_upload_time_ += state->last_transfer_time_; | |
| 429 } | |
| 430 | |
| 392 namespace { | 431 namespace { |
| 393 void WaitForGlFence() { | 432 void WaitForGlFence() { |
| 394 // Uploads usually finish on the CPU, but just in case add a fence | 433 // Uploads usually finish on the CPU, but just in case add a fence |
| 395 // and guarantee the upload has completed. The flush bit is set to | 434 // and guarantee the upload has completed. The flush bit is set to |
| 396 // insure we don't wait forever. | 435 // insure we don't wait forever. |
| 397 | 436 |
| 398 EGLDisplay display = eglGetCurrentDisplay(); | 437 EGLDisplay display = eglGetCurrentDisplay(); |
| 399 EGLSyncKHR fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL); | 438 EGLSyncKHR fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL); |
| 400 EGLint flags = EGL_SYNC_FLUSH_COMMANDS_BIT_KHR; | 439 EGLint flags = EGL_SYNC_FLUSH_COMMANDS_BIT_KHR; |
| 401 EGLTimeKHR time = EGL_FOREVER_KHR; | 440 EGLTimeKHR time = EGL_FOREVER_KHR; |
| 402 | 441 |
| 403 // This fence is basically like calling glFinish, which is fine if | 442 // This fence is basically like calling glFinish, which is fine if |
| 404 // uploads occur on the CPU. If some upload work occurs on the GPU, | 443 // uploads occur on the CPU. If some upload work occurs on the GPU, |
| 405 // we may want to delay blocking on the fence. | 444 // we may want to delay blocking on the fence. |
| 406 eglClientWaitSyncKHR(display, fence, flags, time); | 445 eglClientWaitSyncKHR(display, fence, flags, time); |
| 407 eglDestroySyncKHR(display, fence); | 446 eglDestroySyncKHR(display, fence); |
| 408 } | 447 } |
| 409 } // namespace | 448 } // namespace |
| 410 | 449 |
| 411 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D( | 450 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D( |
| 412 TransferStateInternal* state, | 451 TransferStateInternal* state, |
| 413 AsyncTexImage2DParams tex_params, | 452 AsyncTexImage2DParams tex_params, |
| 414 AsyncMemoryParams mem_params) { | 453 base::SharedMemory* shared_memory, |
| 415 // TODO(epenner): This is just to insure it is deleted. Could bind() do this? | 454 uint32 shared_memory_size, |
| 416 scoped_ptr<SharedMemory> shared_memory = | 455 uint32 shared_memory_data_offset, |
| 417 make_scoped_ptr(mem_params.shared_memory); | 456 uint32 shared_memory_data_size) { |
| 418 | 457 void* data = GetAddress(shared_memory, |
| 419 void* data = GetAddress(mem_params.shared_memory, | 458 shared_memory_size, |
| 420 mem_params.shm_size, | 459 shared_memory_data_offset, |
| 421 mem_params.shm_data_offset, | 460 shared_memory_data_size); |
| 422 mem_params.shm_data_size); | |
| 423 | 461 |
| 424 // In texImage2D, we do everything on the upload thread. This is | 462 // In texImage2D, we do everything on the upload thread. This is |
| 425 // because texImage2D can incur CPU allocation cost, and it also | 463 // because texImage2D can incur CPU allocation cost, and it also |
| 426 // 'orphans' any previous EGLImage bound to the texture. | 464 // 'orphans' any previous EGLImage bound to the texture. |
| 427 DCHECK_EQ(0, tex_params.level); | 465 DCHECK_EQ(0, tex_params.level); |
| 428 DCHECK_EQ(EGL_NO_IMAGE_KHR, state->egl_image_); | 466 DCHECK_EQ(EGL_NO_IMAGE_KHR, state->egl_image_); |
| 429 TRACE_EVENT2("gpu", "performAsyncTexImage2D", | 467 TRACE_EVENT2("gpu", "performAsyncTexImage2D", |
| 430 "width", tex_params.width, | 468 "width", tex_params.width, |
| 431 "height", tex_params.height); | 469 "height", tex_params.height); |
| 432 | 470 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 WaitForGlFence(); | 506 WaitForGlFence(); |
| 469 | 507 |
| 470 // We can delete this thread's texture as the real texture | 508 // We can delete this thread's texture as the real texture |
| 471 // now contains the data. | 509 // now contains the data. |
| 472 glDeleteTextures(1, &temp_texture); | 510 glDeleteTextures(1, &temp_texture); |
| 473 } | 511 } |
| 474 | 512 |
| 475 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D( | 513 void AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D( |
| 476 TransferStateInternal* state, | 514 TransferStateInternal* state, |
| 477 AsyncTexSubImage2DParams tex_params, | 515 AsyncTexSubImage2DParams tex_params, |
| 478 AsyncMemoryParams mem_params) { | 516 base::SharedMemory* shared_memory, |
| 479 // TODO(epenner): This is just to insure it is deleted. Could bind() do this? | 517 uint32 shared_memory_size, |
| 480 scoped_ptr<SharedMemory> shared_memory = | 518 uint32 shared_memory_data_offset, |
| 481 make_scoped_ptr(mem_params.shared_memory); | 519 uint32 shared_memory_data_size) { |
| 482 | 520 void* data = GetAddress(shared_memory, |
| 483 void* data = GetAddress(mem_params.shared_memory, | 521 shared_memory_size, |
| 484 mem_params.shm_size, | 522 shared_memory_data_offset, |
| 485 mem_params.shm_data_offset, | 523 shared_memory_data_size); |
| 486 mem_params.shm_data_size); | |
| 487 | 524 |
| 488 // For a texSubImage, the texture must already have been | 525 // For a texSubImage, the texture must already have been |
| 489 // created on the main thread, along with EGLImageKHR. | 526 // created on the main thread, along with EGLImageKHR. |
| 490 DCHECK_NE(EGL_NO_IMAGE_KHR, state->egl_image_); | 527 DCHECK_NE(EGL_NO_IMAGE_KHR, state->egl_image_); |
| 491 DCHECK_EQ(0, tex_params.level); | 528 DCHECK_EQ(0, tex_params.level); |
| 492 TRACE_EVENT2("gpu", "performAsyncTexSubImage2D", | 529 TRACE_EVENT2("gpu", "performAsyncTexSubImage2D", |
| 493 "width", tex_params.width, | 530 "width", tex_params.width, |
| 494 "height", tex_params.height); | 531 "height", tex_params.height); |
| 495 | 532 |
| 533 base::TimeTicks begin_time(base::TimeTicks::HighResNow()); | |
| 496 // Create a texture from the image and upload to it. | 534 // Create a texture from the image and upload to it. |
| 497 GLuint temp_texture = 0; | 535 GLuint temp_texture = 0; |
| 498 glGenTextures(1, &temp_texture); | 536 glGenTextures(1, &temp_texture); |
| 499 glActiveTexture(GL_TEXTURE0); | 537 glActiveTexture(GL_TEXTURE0); |
| 500 glBindTexture(GL_TEXTURE_2D, temp_texture); | 538 glBindTexture(GL_TEXTURE_2D, temp_texture); |
| 501 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, state->egl_image_); | 539 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, state->egl_image_); |
| 502 { | 540 { |
| 503 TRACE_EVENT0("gpu", "performAsyncTexSubImage2D glTexSubImage2D"); | 541 TRACE_EVENT0("gpu", "performAsyncTexSubImage2D glTexSubImage2D"); |
| 504 glTexSubImage2D( | 542 glTexSubImage2D( |
| 505 GL_TEXTURE_2D, | 543 GL_TEXTURE_2D, |
| 506 tex_params.level, | 544 tex_params.level, |
| 507 tex_params.xoffset, | 545 tex_params.xoffset, |
| 508 tex_params.yoffset, | 546 tex_params.yoffset, |
| 509 tex_params.width, | 547 tex_params.width, |
| 510 tex_params.height, | 548 tex_params.height, |
| 511 tex_params.format, | 549 tex_params.format, |
| 512 tex_params.type, | 550 tex_params.type, |
| 513 data); | 551 data); |
| 514 } | 552 } |
| 515 WaitForGlFence(); | 553 WaitForGlFence(); |
| 516 | 554 |
| 517 // We can delete this thread's texture as the real texture | 555 // We can delete this thread's texture as the real texture |
| 518 // now contains the data. | 556 // now contains the data. |
| 519 glDeleteTextures(1, &temp_texture); | 557 glDeleteTextures(1, &temp_texture); |
| 558 state->last_transfer_time_ = base::TimeTicks::HighResNow() - begin_time; | |
| 520 } | 559 } |
| 521 | 560 |
| 522 } // namespace gfx | 561 } // namespace gfx |
| OLD | NEW |