diff options
author | epenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-12 01:59:46 +0000 |
---|---|---|
committer | epenner@chromium.org <epenner@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-02-12 01:59:46 +0000 |
commit | fa8e81e62fd329ee957e87255f9ee074b02f15a3 (patch) | |
tree | 744bfd554ad5bf6116db5a0dbcfc1b4c6c4066d9 /ui/gl | |
parent | 087e65a53ac51d0f8b89e0b55893a9be16372071 (diff) | |
download | chromium_src-fa8e81e62fd329ee957e87255f9ee074b02f15a3.zip chromium_src-fa8e81e62fd329ee957e87255f9ee074b02f15a3.tar.gz chromium_src-fa8e81e62fd329ee957e87255f9ee074b02f15a3.tar.bz2 |
gpu: Change qualcomm work-around.
The only way to keep image_preserved disabled was to use a
glFinish after EGL image creation. This is fine if we only
create EGL images on the upload thread, but we might start
doing this on either thread.
This alternative work around just doesn't use image-
preserve. The performance benefit wasn't large on Qualcomm
anyway.
No-try for Android only change.
NOTRY=true
BUG=175272
Review URL: https://chromiumcodereview.appspot.com/12218088
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@181819 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gl')
-rw-r--r-- | ui/gl/async_pixel_transfer_delegate_android.cc | 138 |
1 files changed, 60 insertions, 78 deletions
diff --git a/ui/gl/async_pixel_transfer_delegate_android.cc b/ui/gl/async_pixel_transfer_delegate_android.cc index 68c329f..fcad1eb 100644 --- a/ui/gl/async_pixel_transfer_delegate_android.cc +++ b/ui/gl/async_pixel_transfer_delegate_android.cc @@ -52,6 +52,32 @@ bool CheckErrors(const char* file, int line) { } #define CHECK_GL() CheckErrors(__FILE__, __LINE__) +// Regular glTexImage2D call. +void DoTexImage2D(const AsyncTexImage2DParams& tex_params, void* data) { + glTexImage2D( + GL_TEXTURE_2D, tex_params.level, tex_params.internal_format, + tex_params.width, tex_params.height, + tex_params.border, tex_params.format, tex_params.type, data); +} + +// Regular glTexSubImage2D call. +void DoTexSubImage2D(const AsyncTexSubImage2DParams& tex_params, void* data) { + glTexSubImage2D( + GL_TEXTURE_2D, tex_params.level, + tex_params.xoffset, tex_params.yoffset, + tex_params.width, tex_params.height, + tex_params.format, tex_params.type, data); +} + +// Full glTexSubImage2D call, from glTexImage2D params. +void DoFullTexSubImage2D(const AsyncTexImage2DParams& tex_params, void* data) { + glTexSubImage2D( + GL_TEXTURE_2D, tex_params.level, + 0, 0, tex_params.width, tex_params.height, + tex_params.format, tex_params.type, data); +} + + // We duplicate shared memory to avoid use-after-free issues. This could also // be solved by ref-counting something, or with a destruction callback. There // wasn't an obvious hook or ref-counted container, so for now we dup/mmap. @@ -138,14 +164,14 @@ class TransferStateInternal public: explicit TransferStateInternal(GLuint texture_id, bool wait_for_uploads, - bool wait_for_egl_images) + bool use_image_preserved) : texture_id_(texture_id), thread_texture_id_(0), needs_late_bind_(false), transfer_in_progress_(false), egl_image_(EGL_NO_IMAGE_KHR), wait_for_uploads_(wait_for_uploads), - wait_for_egl_images_(wait_for_egl_images) { + use_image_preserved_(use_image_preserved) { static const AsyncTexImage2DParams zero_params = {0, 0, 0, 0, 0, 0, 0, 0}; late_bind_define_params_ = zero_params; } @@ -187,9 +213,11 @@ class TransferStateInternal EGLenum egl_target = EGL_GL_TEXTURE_2D_KHR; EGLClientBuffer egl_buffer = reinterpret_cast<EGLClientBuffer>(texture_id); + + EGLint image_preserved = use_image_preserved_ ? EGL_TRUE : EGL_FALSE; EGLint egl_attrib_list[] = { - EGL_GL_TEXTURE_LEVEL_KHR, 0, // mip-level to reference. - EGL_IMAGE_PRESERVED_KHR, EGL_FALSE, // throw away texture data. + EGL_GL_TEXTURE_LEVEL_KHR, 0, // mip-level. + EGL_IMAGE_PRESERVED_KHR, image_preserved, EGL_NONE }; egl_image_ = eglCreateImageKHR( @@ -211,17 +239,6 @@ class TransferStateInternal CreateEglImage(texture_id_); } - void WaitOnEglImageCreation() { - // On Qualcomm, we need to wait on egl image creation before - // doing the first upload (or the texture remains black). - // A fence after image creation didn't always work, but glFinish - // seems to always work, and this only happens on the upload thread. - if (wait_for_egl_images_) { - TRACE_EVENT0("gpu", "glFinish"); - glFinish(); - } - } - void WaitForLastUpload() { // This glFinish is just a safe-guard for if uploads have some // GPU action that needs to occur. We could use fences and try @@ -278,7 +295,7 @@ class TransferStateInternal // Customize when we block on fences (these are work-arounds). bool wait_for_uploads_; - bool wait_for_egl_images_; + bool use_image_preserved_; }; // Android needs thread-safe ref-counting, so this just wraps @@ -287,10 +304,10 @@ class AsyncTransferStateAndroid : public AsyncPixelTransferState { public: explicit AsyncTransferStateAndroid(GLuint texture_id, bool wait_for_uploads, - bool wait_for_egl_images) + bool use_image_preserved) : internal_(new TransferStateInternal(texture_id, wait_for_uploads, - wait_for_egl_images)) { + use_image_preserved)) { } virtual ~AsyncTransferStateAndroid() {} virtual bool TransferIsInProgress() { @@ -411,15 +428,20 @@ AsyncPixelTransferState* CreateRawPixelTransferState(GLuint texture_id) { // We can't wait on uploads on imagination (it can take 200ms+). + // In practice, they are complete when the CPU glSubTexImage2D completes. bool wait_for_uploads = !is_imagination_; - // We need to wait for EGLImage creation on Qualcomm. - bool wait_for_egl_images = is_qualcomm_; + // Qualcomm has a race when using image_preserved=FALSE, + // which can result in black textures even after the first upload. + // Since using FALSE is mainly for performance (to avoid layout changes), + // but Qualcomm itself doesn't seem to get any performance benefit, + // we just using image_preservedd=TRUE on Qualcomm as a work-around. + bool use_image_preserved = is_qualcomm_ || is_imagination_; return static_cast<AsyncPixelTransferState*>( new AsyncTransferStateAndroid(texture_id, wait_for_uploads, - wait_for_egl_images)); + use_image_preserved)); } namespace { @@ -578,35 +600,24 @@ void AsyncPixelTransferDelegateAndroid::PerformAsyncTexImage2D( SetGlParametersForEglImageTexture(); - // Allocate first, so we can create the EGLImage without - // EGL_IMAGE_PRESERVED, which can be costly. - glTexImage2D( - GL_TEXTURE_2D, - tex_params.level, - tex_params.internal_format, - tex_params.width, - tex_params.height, - tex_params.border, - tex_params.format, - tex_params.type, - NULL); + // If we need to use image_preserved, we pass the data with + // the allocation. Otherwise we use a NULL allocation to + // try to avoid any costs associated with creating the EGLImage. + if (state->use_image_preserved_) + DoTexImage2D(tex_params, data); + else + DoTexImage2D(tex_params, NULL); } state->CreateEglImageOnUploadThread(); - state->WaitOnEglImageCreation(); { TRACE_EVENT0("gpu", "glTexSubImage2D with data"); - glTexSubImage2D( - GL_TEXTURE_2D, - tex_params.level, - 0, - 0, - tex_params.width, - tex_params.height, - tex_params.format, - tex_params.type, - data); + + // If we didn't use image_preserved, we haven't uploaded + // the data yet, so we do this with a full texSubImage. + if (!state->use_image_preserved_) + DoFullTexSubImage2D(tex_params, data); } state->WaitForLastUpload(); @@ -626,8 +637,6 @@ void AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D( DCHECK_NE(EGL_NO_IMAGE_KHR, state->egl_image_); DCHECK_EQ(0, tex_params.level); - state->WaitOnEglImageCreation(); - void* data = GetAddress(shared_memory, shared_memory_data_offset); base::TimeTicks begin_time(base::TimeTicks::HighResNow()); @@ -643,16 +652,7 @@ void AsyncPixelTransferDelegateAndroid::PerformAsyncTexSubImage2D( } { TRACE_EVENT0("gpu", "glTexSubImage2D"); - glTexSubImage2D( - GL_TEXTURE_2D, - tex_params.level, - tex_params.xoffset, - tex_params.yoffset, - tex_params.width, - tex_params.height, - tex_params.format, - tex_params.type, - data); + DoTexSubImage2D(tex_params, data); } state->WaitForLastUpload(); @@ -674,8 +674,8 @@ bool DimensionsSupportImgFastPath(int width, int height) { // Multiple of eight, but not a power of two. return IsMultipleOfEight(width) && IsMultipleOfEight(height) && - !IsPowerOfTwo(width) && - !IsPowerOfTwo(height); + !(IsPowerOfTwo(width) && + IsPowerOfTwo(height)); } } // namespace @@ -708,16 +708,7 @@ bool AsyncPixelTransferDelegateAndroid::WorkAroundAsyncTexImage2D( { TRACE_EVENT0("gpu", "glTexImage2D with data"); - glTexImage2D( - GL_TEXTURE_2D, - tex_params.level, - tex_params.internal_format, - tex_params.width, - tex_params.height, - tex_params.border, - tex_params.format, - tex_params.type, - data); + DoTexImage2D(tex_params, data); } // The allocation has already occured, so mark it as finished @@ -757,16 +748,7 @@ bool AsyncPixelTransferDelegateAndroid::WorkAroundAsyncTexSubImage2D( base::TimeTicks begin_time(base::TimeTicks::HighResNow()); { TRACE_EVENT0("gpu", "glTexSubImage2D"); - glTexSubImage2D( - tex_params.target, - tex_params.level, - tex_params.xoffset, - tex_params.yoffset, - tex_params.width, - tex_params.height, - tex_params.format, - tex_params.type, - data); + DoTexSubImage2D(tex_params, data); } texture_upload_count_++; total_texture_upload_time_ += base::TimeTicks::HighResNow() - begin_time; |