b=773071; use KHR_fence_sync instead of GuaranteedRsolve with EGLImage WebGL; r=jgilbert
authorVladimir Vukicevic <vladimir@pobox.com>
Tue, 17 Jul 2012 21:20:28 -0400
changeset 102732 b2def0ae47bbaadfd504c0e4c5bb17fa40a316da
parent 102731 41eb4e7896e556cf21a2db1276e8eaad2f455dd1
child 102733 6aa560d1645d6a10ef31e6aa8a86a55b61a9c777
push id1989
push userakeybl@mozilla.com
push dateTue, 28 Aug 2012 00:20:43 +0000
treeherdermozilla-aurora@a8e95ae10ea7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs773071
milestone17.0a1
b=773071; use KHR_fence_sync instead of GuaranteedRsolve with EGLImage WebGL; r=jgilbert
gfx/gl/GLContextProviderEGL.cpp
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -678,16 +678,17 @@ protected:
 
 class EGLTextureWrapper
 {
 public:
     EGLTextureWrapper(GLContext* aContext, GLuint aTexture)
         : mContext(aContext)
         , mTexture(aTexture)
         , mEGLImage(nsnull)
+        , mSyncObject(nsnull)
     {
     }
 
     bool CreateEGLImage() {
         MOZ_ASSERT(!mEGLImage && mTexture && sEGLLibrary.HasKHRImageBase());
         static const EGLint eglAttributes[] = {
             LOCAL_EGL_NONE
         };
@@ -717,20 +718,56 @@ public:
     GLContext* GetContext() {
         return mContext.get();
     }
 
     const EGLImage GetEGLImage() {
         return mEGLImage;
     }
 
+    bool MakeSync() {
+        MOZ_ASSERT(mSyncObject == nsnull);
+
+        if (sEGLLibrary.IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)) {
+            mSyncObject = sEGLLibrary.fCreateSync(EGL_DISPLAY(), LOCAL_EGL_SYNC_FENCE, nsnull);
+            // We need to flush to make sure the sync object enters the command stream;
+            // we can't use EGL_SYNC_FLUSH_COMMANDS_BIT at wait time, because the wait
+            // happens on a different thread/context.
+            mContext->fFlush();
+        }
+
+        if (mSyncObject == EGL_NO_SYNC) {
+            // we failed to create one, so just do a finish
+            mContext->fFinish();
+        }
+
+        return true;
+    }
+
+    bool WaitSync() {
+        if (!mSyncObject) {
+            // if we have no sync object, then we did a Finish() earlier
+            return true;
+        }
+
+        EGLint result = sEGLLibrary.fClientWaitSync(EGL_DISPLAY(), mSyncObject, 0, LOCAL_EGL_FOREVER);
+        sEGLLibrary.fDestroySync(EGL_DISPLAY(), mSyncObject);
+        mSyncObject = nsnull;
+
+        // we should never expire a 'forever' timeout
+        MOZ_ASSERT(result != LOCAL_EGL_TIMEOUT_EXPIRED);
+
+        return result == LOCAL_EGL_CONDITION_SATISFIED;
+    }
+
 private:
     nsRefPtr<GLContext> mContext;
     GLuint mTexture;
     EGLImage mEGLImage;
+    EGLSync mSyncObject;
 };
 
 void
 GLContextEGL::UpdateSharedHandle(TextureImage::TextureShareType aType,
                                  SharedTextureHandle aSharedHandle)
 {
     if (aType != TextureImage::ThreadShared) {
         NS_ERROR("Implementation not available for this sharing type");
@@ -822,16 +859,17 @@ bool GLContextEGL::AttachSharedHandle(Te
                                       SharedTextureHandle aSharedHandle)
 {
     if (aType != TextureImage::ThreadShared)
         return false;
 
     NS_ASSERTION(mShareWithEGLImage, "EGLImage not supported or disabled in runtime");
 
     EGLTextureWrapper* wrap = (EGLTextureWrapper*)aSharedHandle;
+    wrap->WaitSync();
     sEGLLibrary.fImageTargetTexture2DOES(LOCAL_GL_TEXTURE_2D, wrap->GetEGLImage());
     return true;
 }
 
 bool
 GLContextEGL::BindTex2DOffscreen(GLContext *aOffscreen)
 {
     if (aOffscreen->GetContextType() != ContextTypeEGL) {