Bug 1014815 - Add a delay stage for webgl on b2g to let frame resolve. r=jgilbert
☠☠ backed out by 33ff7ab025d1 ☠ ☠
authorBenoit Girard <b56girard@gmail.com>
Wed, 04 Jun 2014 14:25:18 -0400
changeset 207652 abdb3afb720884c936002d664403f4635e3744a1
parent 207651 52204412c79b5376d9c6cfa6937cb9a0b8c4d618
child 207653 63e728e2fe1ca218ad19f6e8c734dd40e3b3aca6
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs1014815
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1014815 - Add a delay stage for webgl on b2g to let frame resolve. r=jgilbert
content/canvas/src/WebGLContext.cpp
gfx/gl/GLScreenBuffer.h
gfx/gl/SurfaceStream.cpp
gfx/gl/SurfaceStream.h
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -837,16 +837,20 @@ public:
         WebGLContextUserData *userdata = static_cast<WebGLContextUserData*>(aData);
         HTMLCanvasElement *canvas = userdata->mContent;
         WebGLContext *context = static_cast<WebGLContext*>(canvas->GetContextAtIndex(0));
 
         // Mark ourselves as no longer invalidated.
         context->MarkContextClean();
 
         context->UpdateLastUseIndex();
+
+        if (context->GL()->Screen()->HasDelayedFrame()) {
+            context->Invalidate();
+        }
     }
 
 private:
     nsRefPtr<HTMLCanvasElement> mContent;
 };
 
 } // end namespace mozilla
 
--- a/gfx/gl/GLScreenBuffer.h
+++ b/gfx/gl/GLScreenBuffer.h
@@ -150,16 +150,20 @@ protected:
     typedef struct gfx::SurfaceCaps SurfaceCaps;
 
 public:
     // Infallible.
     static GLScreenBuffer* Create(GLContext* gl,
                                   const gfx::IntSize& size,
                                   const SurfaceCaps& caps);
 
+    bool HasDelayedFrame() {
+      return mStream->HasDelayedFrame();
+    }
+
 protected:
     GLContext* const mGL;         // Owns us.
     SurfaceCaps mCaps;
     SurfaceFactory_GL* mFactory;  // Owned by us.
     RefPtr<SurfaceStream> mStream;
 
     DrawBuffer* mDraw;            // Owned by us.
     ReadBuffer* mRead;            // Owned by us.
--- a/gfx/gl/SurfaceStream.cpp
+++ b/gfx/gl/SurfaceStream.cpp
@@ -26,34 +26,52 @@ SurfaceStream::ChooseGLStreamType(Surfac
     } else {
         if (preserveBuffer)
             return SurfaceStreamType::SingleBuffer;
         else
             return SurfaceStreamType::TripleBuffer;
     }
 }
 
+static bool
+ShouldDelayFrame()
+{
+#ifdef MOZ_WIDGET_GONK
+  return true;
+#else
+  return false;
+#endif
+}
+
 SurfaceStream*
 SurfaceStream::CreateForType(SurfaceStreamType type, mozilla::gl::GLContext* glContext, SurfaceStream* prevStream)
 {
     SurfaceStream* result = nullptr;
 
     switch (type) {
         case SurfaceStreamType::SingleBuffer:
             result = new SurfaceStream_SingleBuffer(prevStream);
             break;
         case SurfaceStreamType::TripleBuffer_Copy:
             result = new SurfaceStream_TripleBuffer_Copy(prevStream);
             break;
-        case SurfaceStreamType::TripleBuffer_Async:
-            result = new SurfaceStream_TripleBuffer_Async(prevStream);
+        case SurfaceStreamType::TripleBuffer_Async: {
+            result = new SurfaceStream_TripleBuffer_Async(ShouldDelayFrame(), prevStream);
             break;
-        case SurfaceStreamType::TripleBuffer:
-            result = new SurfaceStream_TripleBuffer(prevStream);
+        }
+        case SurfaceStreamType::TripleBuffer: {
+            bool delayFrame = false;
+#ifdef MOZ_WIDGET_GONK
+            // Give time for the frame to resolve instead of waiting for the
+            // fence right away.
+            delayFrame = true;
+#endif
+            result = new SurfaceStream_TripleBuffer(delayFrame, prevStream);
             break;
+        }
         default:
             MOZ_CRASH("Invalid Type.");
     }
 
     result->mGLContext = glContext;
     return result;
 }
 
@@ -386,36 +404,44 @@ void SurfaceStream_TripleBuffer::Init(Su
     if (prevConsumer == prevProducer)
         prevConsumer = nullptr;
 
     mProducer = Absorb(prevProducer);
     mConsumer = Absorb(prevConsumer);
 }
 
 
-SurfaceStream_TripleBuffer::SurfaceStream_TripleBuffer(SurfaceStreamType type, SurfaceStream* prevStream)
+SurfaceStream_TripleBuffer::SurfaceStream_TripleBuffer(bool aUseSwapDelay,
+                                                       SurfaceStreamType type,
+                                                       SurfaceStream* prevStream)
     : SurfaceStream(type, prevStream)
     , mStaging(nullptr)
     , mConsumer(nullptr)
+    , mDelay(nullptr)
+    , mUseSwapDelay(aUseSwapDelay)
 {
     SurfaceStream_TripleBuffer::Init(prevStream);
 }
 
-SurfaceStream_TripleBuffer::SurfaceStream_TripleBuffer(SurfaceStream* prevStream)
+SurfaceStream_TripleBuffer::SurfaceStream_TripleBuffer(bool aUseSwapDelay,
+                                                       SurfaceStream* prevStream)
     : SurfaceStream(SurfaceStreamType::TripleBuffer, prevStream)
     , mStaging(nullptr)
     , mConsumer(nullptr)
+    , mDelay(nullptr)
+    , mUseSwapDelay(aUseSwapDelay)
 {
     SurfaceStream_TripleBuffer::Init(prevStream);
 }
 
 SurfaceStream_TripleBuffer::~SurfaceStream_TripleBuffer()
 {
     Delete(mStaging);
     Delete(mConsumer);
+    Delete(mDelay);
 }
 
 void
 SurfaceStream_TripleBuffer::SurrenderSurfaces(SharedSurface*& producer,
                                               SharedSurface*& consumer)
 {
     mIsAlive = false;
 
@@ -455,27 +481,41 @@ SurfaceStream_TripleBuffer::SwapProducer
 
     return mProducer;
 }
 
 SharedSurface*
 SurfaceStream_TripleBuffer::SwapConsumer_NoWait()
 {
     MonitorAutoLock lock(mMonitor);
-    if (mStaging) {
+    if (mDelay) {
         Scrap(mConsumer);
-        Move(mStaging, mConsumer);
+        Move(mDelay, mConsumer);
         mMonitor.NotifyAll();
     }
 
+    if (mStaging) {
+        if (mUseSwapDelay && mConsumer) {
+            MOZ_ASSERT(!mDelay);
+            Move(mStaging, mDelay);
+        } else {
+            Scrap(mConsumer);
+            Move(mStaging, mConsumer);
+            mMonitor.NotifyAll();
+        }
+    }
+
     return mConsumer;
 }
 
-SurfaceStream_TripleBuffer_Async::SurfaceStream_TripleBuffer_Async(SurfaceStream* prevStream)
-    : SurfaceStream_TripleBuffer(SurfaceStreamType::TripleBuffer_Async, prevStream)
+SurfaceStream_TripleBuffer_Async::SurfaceStream_TripleBuffer_Async(bool aSwapDelay,
+                                                                   SurfaceStream* prevStream)
+    : SurfaceStream_TripleBuffer(aSwapDelay,
+                                 SurfaceStreamType::TripleBuffer_Async,
+                                 prevStream)
 {
 }
 
 SurfaceStream_TripleBuffer_Async::~SurfaceStream_TripleBuffer_Async()
 {
 }
 
 void
--- a/gfx/gl/SurfaceStream.h
+++ b/gfx/gl/SurfaceStream.h
@@ -48,30 +48,38 @@ public:
     static SurfaceStream* FromHandle(SurfaceStreamHandle handle) {
         return (SurfaceStream*)handle;
     }
 
     const SurfaceStreamType mType;
 
     mozilla::gl::GLContext* GLContext() const { return mGLContext; }
 
+    /**
+     * If we have a pending frame in the queue then we will need
+     * another SwapConsumer.
+     */
+    virtual bool HasDelayedFrame() const {
+      return false;
+    }
 
 protected:
     // |mProd| is owned by us, but can be ripped away when
     // creating a new GLStream from this one.
     SharedSurface* mProducer;
     std::set<SharedSurface*> mSurfaces;
     std::stack<SharedSurface*> mScraps;
-    mutable Monitor mMonitor;
-    bool mIsAlive;
 
     // Do not use this. It exists solely so we can ref it in CanvasClientWebGL::Update()
     // before sent up to the compositor. You have been warned (Bug 894405)
     mozilla::gl::GLContext* mGLContext;
 
+    mutable Monitor mMonitor;
+    bool mIsAlive;
+
     // |previous| can be null, indicating this is the first one.
     // Otherwise, we pull in |mProd| from |previous| an our initial surface.
     SurfaceStream(SurfaceStreamType type, SurfaceStream* prevStream)
         : mType(type)
         , mProducer(nullptr)
         , mMonitor("SurfaceStream monitor")
         , mIsAlive(true)
     {
@@ -185,29 +193,35 @@ public:
 
 
 class SurfaceStream_TripleBuffer
     : public SurfaceStream
 {
 protected:
     SharedSurface* mStaging;
     SharedSurface* mConsumer;
+    SharedSurface* mDelay;
+    bool mUseSwapDelay;
 
     // Returns true if we were able to wait, false if not
     virtual void WaitForCompositor() {}
 
     // To support subclasses initializing the mType.
-    SurfaceStream_TripleBuffer(SurfaceStreamType type, SurfaceStream* prevStream);
+    SurfaceStream_TripleBuffer(bool aUseSwapDelay, SurfaceStreamType type, SurfaceStream* prevStream);
 
 public:
     MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_TripleBuffer)
-    SurfaceStream_TripleBuffer(SurfaceStream* prevStream);
+    SurfaceStream_TripleBuffer(bool aUseSwapDelay, SurfaceStream* prevStream);
     virtual ~SurfaceStream_TripleBuffer();
     virtual bool CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory);
 
+    virtual bool HasDelayedFrame() const MOZ_OVERRIDE {
+      return !!mDelay;
+    }
+
 private:
     // Common constructor code.
     void Init(SurfaceStream* prevStream);
 
 public:
     // Done writing to prod, swap prod and staging
     virtual SharedSurface* SwapProducer(SurfaceFactory* factory,
                                         const gfx::IntSize& size);
@@ -219,17 +233,17 @@ public:
 
 class SurfaceStream_TripleBuffer_Async
     : public SurfaceStream_TripleBuffer
 {
 protected:
     virtual void WaitForCompositor() MOZ_OVERRIDE;
 
 public:
-    SurfaceStream_TripleBuffer_Async(SurfaceStream* prevStream);
+    SurfaceStream_TripleBuffer_Async(bool aSwapDelay, SurfaceStream* prevStream);
     virtual ~SurfaceStream_TripleBuffer_Async();
 };
 
 
 } /* namespace gfx */
 } /* namespace mozilla */
 
 #endif /* SURFACESTREAM_H_ */