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 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 } // namespace | 177 } // namespace |
178 | 178 |
179 // Class which holds async pixel transfers state (EGLImage). | 179 // Class which holds async pixel transfers state (EGLImage). |
180 // The EGLImage is accessed by either thread, but everything | 180 // The EGLImage is accessed by either thread, but everything |
181 // else accessed only on the main thread. | 181 // else accessed only on the main thread. |
182 class TransferStateInternal | 182 class TransferStateInternal |
183 : public base::RefCountedThreadSafe<TransferStateInternal> { | 183 : public base::RefCountedThreadSafe<TransferStateInternal> { |
184 public: | 184 public: |
185 explicit TransferStateInternal(GLuint texture_id, | 185 explicit TransferStateInternal(GLuint texture_id, |
186 bool wait_for_uploads, | 186 bool wait_for_uploads, |
| 187 bool wait_for_creation, |
187 bool use_image_preserved) | 188 bool use_image_preserved) |
188 : texture_id_(texture_id), | 189 : texture_id_(texture_id), |
189 thread_texture_id_(0), | 190 thread_texture_id_(0), |
190 needs_late_bind_(false), | 191 needs_late_bind_(false), |
191 transfer_completion_(true, true), | 192 transfer_completion_(true, true), |
192 egl_image_(EGL_NO_IMAGE_KHR), | 193 egl_image_(EGL_NO_IMAGE_KHR), |
193 wait_for_uploads_(wait_for_uploads), | 194 wait_for_uploads_(wait_for_uploads), |
| 195 wait_for_creation_(wait_for_creation), |
194 use_image_preserved_(use_image_preserved) { | 196 use_image_preserved_(use_image_preserved) { |
195 static const AsyncTexImage2DParams zero_params = {0, 0, 0, 0, 0, 0, 0, 0}; | 197 static const AsyncTexImage2DParams zero_params = {0, 0, 0, 0, 0, 0, 0, 0}; |
196 late_bind_define_params_ = zero_params; | 198 late_bind_define_params_ = zero_params; |
197 } | 199 } |
198 | 200 |
199 // Implement AsyncPixelTransferState: | 201 // Implement AsyncPixelTransferState: |
200 bool TransferIsInProgress() { | 202 bool TransferIsInProgress() { |
201 return !transfer_completion_.IsSignaled(); | 203 return !transfer_completion_.IsSignaled(); |
202 } | 204 } |
203 | 205 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 egl_attrib_list); | 249 egl_attrib_list); |
248 | 250 |
249 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); | 251 DCHECK_NE(EGL_NO_IMAGE_KHR, egl_image_); |
250 } | 252 } |
251 | 253 |
252 void CreateEglImageOnUploadThread() { | 254 void CreateEglImageOnUploadThread() { |
253 CreateEglImage(thread_texture_id_); | 255 CreateEglImage(thread_texture_id_); |
254 } | 256 } |
255 | 257 |
256 void CreateEglImageOnMainThreadIfNeeded() { | 258 void CreateEglImageOnMainThreadIfNeeded() { |
257 if (egl_image_ == EGL_NO_IMAGE_KHR) | 259 if (egl_image_ == EGL_NO_IMAGE_KHR) { |
258 CreateEglImage(texture_id_); | 260 CreateEglImage(texture_id_); |
| 261 if (wait_for_creation_) { |
| 262 TRACE_EVENT0("gpu", "glFinish creation"); |
| 263 glFinish(); |
| 264 } |
| 265 } |
259 } | 266 } |
260 | 267 |
261 void WaitForLastUpload() { | 268 void WaitForLastUpload() { |
262 // This glFinish is just a safe-guard for if uploads have some | 269 // This glFinish is just a safe-guard for if uploads have some |
263 // GPU action that needs to occur. We could use fences and try | 270 // GPU action that needs to occur. We could use fences and try |
264 // to do this less often. However, on older drivers fences are | 271 // to do this less often. However, on older drivers fences are |
265 // not always reliable (eg. Mali-400 just blocks forever). | 272 // not always reliable (eg. Mali-400 just blocks forever). |
266 if (wait_for_uploads_) { | 273 if (wait_for_uploads_) { |
267 TRACE_EVENT0("gpu", "glFinish"); | 274 TRACE_EVENT0("gpu", "glFinish"); |
268 glFinish(); | 275 glFinish(); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
316 // Indicates that an async transfer is in progress. | 323 // Indicates that an async transfer is in progress. |
317 base::WaitableEvent transfer_completion_; | 324 base::WaitableEvent transfer_completion_; |
318 | 325 |
319 // It would be nice if we could just create a new EGLImage for | 326 // It would be nice if we could just create a new EGLImage for |
320 // every upload, but I found that didn't work, so this stores | 327 // every upload, but I found that didn't work, so this stores |
321 // one for the lifetime of the texture. | 328 // one for the lifetime of the texture. |
322 EGLImageKHR egl_image_; | 329 EGLImageKHR egl_image_; |
323 | 330 |
324 // Customize when we block on fences (these are work-arounds). | 331 // Customize when we block on fences (these are work-arounds). |
325 bool wait_for_uploads_; | 332 bool wait_for_uploads_; |
| 333 bool wait_for_creation_; |
326 bool use_image_preserved_; | 334 bool use_image_preserved_; |
327 }; | 335 }; |
328 | 336 |
329 // Android needs thread-safe ref-counting, so this just wraps | 337 // Android needs thread-safe ref-counting, so this just wraps |
330 // an internal thread-safe ref-counted state object. | 338 // an internal thread-safe ref-counted state object. |
331 class AsyncTransferStateAndroid : public AsyncPixelTransferState { | 339 class AsyncTransferStateAndroid : public AsyncPixelTransferState { |
332 public: | 340 public: |
333 explicit AsyncTransferStateAndroid(GLuint texture_id, | 341 explicit AsyncTransferStateAndroid(GLuint texture_id, |
334 bool wait_for_uploads, | 342 bool wait_for_uploads, |
| 343 bool wait_for_creation, |
335 bool use_image_preserved) | 344 bool use_image_preserved) |
336 : internal_(new TransferStateInternal(texture_id, | 345 : internal_(new TransferStateInternal(texture_id, |
337 wait_for_uploads, | 346 wait_for_uploads, |
| 347 wait_for_creation, |
338 use_image_preserved)) { | 348 use_image_preserved)) { |
339 } | 349 } |
340 virtual ~AsyncTransferStateAndroid() {} | 350 virtual ~AsyncTransferStateAndroid() {} |
341 virtual bool TransferIsInProgress() OVERRIDE { | 351 virtual bool TransferIsInProgress() OVERRIDE { |
342 return internal_->TransferIsInProgress(); | 352 return internal_->TransferIsInProgress(); |
343 } | 353 } |
344 virtual void BindTransfer(AsyncTexImage2DParams* bound_params) OVERRIDE { | 354 virtual void BindTransfer(AsyncTexImage2DParams* bound_params) OVERRIDE { |
345 internal_->BindTransfer(bound_params); | 355 internal_->BindTransfer(bound_params); |
346 } | 356 } |
347 scoped_refptr<TransferStateInternal> internal_; | 357 scoped_refptr<TransferStateInternal> internal_; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
447 } | 457 } |
448 | 458 |
449 AsyncPixelTransferState* | 459 AsyncPixelTransferState* |
450 AsyncPixelTransferDelegateAndroid:: | 460 AsyncPixelTransferDelegateAndroid:: |
451 CreateRawPixelTransferState(GLuint texture_id) { | 461 CreateRawPixelTransferState(GLuint texture_id) { |
452 | 462 |
453 // We can't wait on uploads on imagination (it can take 200ms+). | 463 // We can't wait on uploads on imagination (it can take 200ms+). |
454 // In practice, they are complete when the CPU glTexSubImage2D completes. | 464 // In practice, they are complete when the CPU glTexSubImage2D completes. |
455 bool wait_for_uploads = !is_imagination_; | 465 bool wait_for_uploads = !is_imagination_; |
456 | 466 |
| 467 // Qualcomm runs into texture corruption problems if the same texture is |
| 468 // uploaded to with both async and normal uploads. Synchronize after EGLImage |
| 469 // creation on the main thread as a work-around. |
| 470 bool wait_for_creation = is_qualcomm_; |
| 471 |
457 // Qualcomm has a race when using image_preserved=FALSE, | 472 // Qualcomm has a race when using image_preserved=FALSE, |
458 // which can result in black textures even after the first upload. | 473 // which can result in black textures even after the first upload. |
459 // Since using FALSE is mainly for performance (to avoid layout changes), | 474 // Since using FALSE is mainly for performance (to avoid layout changes), |
460 // but Qualcomm itself doesn't seem to get any performance benefit, | 475 // but Qualcomm itself doesn't seem to get any performance benefit, |
461 // we just using image_preservedd=TRUE on Qualcomm as a work-around. | 476 // we just using image_preservedd=TRUE on Qualcomm as a work-around. |
462 bool use_image_preserved = is_qualcomm_ || is_imagination_; | 477 bool use_image_preserved = is_qualcomm_ || is_imagination_; |
463 | 478 |
464 return static_cast<AsyncPixelTransferState*>( | 479 return static_cast<AsyncPixelTransferState*>( |
465 new AsyncTransferStateAndroid(texture_id, | 480 new AsyncTransferStateAndroid(texture_id, |
466 wait_for_uploads, | 481 wait_for_uploads, |
| 482 wait_for_creation, |
467 use_image_preserved)); | 483 use_image_preserved)); |
468 } | 484 } |
469 | 485 |
470 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( | 486 void AsyncPixelTransferDelegateAndroid::AsyncNotifyCompletion( |
471 const AsyncMemoryParams& mem_params, | 487 const AsyncMemoryParams& mem_params, |
472 const CompletionCallback& callback) { | 488 const CompletionCallback& callback) { |
473 DCHECK(mem_params.shared_memory); | 489 DCHECK(mem_params.shared_memory); |
474 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, | 490 DCHECK_LE(mem_params.shm_data_offset + mem_params.shm_data_size, |
475 mem_params.shm_size); | 491 mem_params.shm_size); |
476 // Post a PerformNotifyCompletion task to the upload thread. This task | 492 // Post a PerformNotifyCompletion task to the upload thread. This task |
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 if (texture_upload_stats_) { | 850 if (texture_upload_stats_) { |
835 texture_upload_stats_->AddUpload( | 851 texture_upload_stats_->AddUpload( |
836 base::TimeTicks::HighResNow() - begin_time); | 852 base::TimeTicks::HighResNow() - begin_time); |
837 } | 853 } |
838 | 854 |
839 DCHECK(CHECK_GL()); | 855 DCHECK(CHECK_GL()); |
840 return true; | 856 return true; |
841 } | 857 } |
842 | 858 |
843 } // namespace gfx | 859 } // namespace gfx |
OLD | NEW |