Bug 1296745 - Clean up WebGLContext draft
authorKearwood (Kip) Gilbert <kgilbert@mozilla.com>
Fri, 19 Aug 2016 14:44:37 -0700
changeset 403510 3db9354ee7e3e9bbb62f46458cbca95205f8aaaf
parent 403386 8ef9629d8f90d6507b1bad01146b14101de79174
child 528924 eabdcdc3ab2c149dc1ce593ac5a1b0ed2bb83c9b
push id26932
push userkgilbert@mozilla.com
push dateFri, 19 Aug 2016 22:03:03 +0000
bugs1296745
milestone51.0a1
Bug 1296745 - Clean up WebGLContext MozReview-Commit-ID: B6xazNgeJ9A
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContext.h
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -120,17 +120,16 @@ WebGLContext::WebGLContext()
     , mMaxFetchedVertices(0)
     , mMaxFetchedInstances(0)
     , mBypassShaderValidation(false)
     , mContextLossHandler(this)
     , mNeedsFakeNoAlpha(false)
     , mNeedsFakeNoDepth(false)
     , mNeedsFakeNoStencil(false)
     , mNeedsEmulatedLoneDepthStencil(false)
-    , mVRPresentationActive(false)
 {
     mGeneration = 0;
     mInvalidated = false;
     mCapturedFrameInvalidated = false;
     mShouldPresent = true;
     mResetLayer = true;
     mOptionsFrozen = false;
     mMinCapability = false;
@@ -1302,33 +1301,30 @@ public:
     /* PreTransactionCallback gets called by the Layers code every time the
      * WebGL canvas is going to be composited.
      */
     static void PreTransactionCallback(void* data) {
         WebGLContextUserData* userdata = static_cast<WebGLContextUserData*>(data);
         HTMLCanvasElement* canvas = userdata->mCanvas;
         WebGLContext* webgl = static_cast<WebGLContext*>(canvas->GetContextAtIndex(0));
 
-        // Present our screenbuffer, if needed.
-        webgl->PresentScreenBuffer();
-        webgl->mDrawCallsSinceLastFlush = 0;
+        // Prepare the context for composition
+        webgl->BeginComposition();
     }
 
     /** DidTransactionCallback gets called by the Layers code everytime the WebGL canvas gets composite,
       * so it really is the right place to put actions that have to be performed upon compositing
       */
     static void DidTransactionCallback(void* data) {
         WebGLContextUserData* userdata = static_cast<WebGLContextUserData*>(data);
         HTMLCanvasElement* canvas = userdata->mCanvas;
         WebGLContext* webgl = static_cast<WebGLContext*>(canvas->GetContextAtIndex(0));
 
-        // Mark ourselves as no longer invalidated.
-        webgl->MarkContextClean();
-
-        webgl->UpdateLastUseIndex();
+        // Clean up the context after composition
+        webgl->EndComposition();
     }
 
 private:
     RefPtr<HTMLCanvasElement> mCanvas;
 };
 
 already_AddRefed<layers::Layer>
 WebGLContext::GetCanvasLayer(nsDisplayListBuilder* builder,
@@ -1607,16 +1603,34 @@ WebGLContext::PresentScreenBuffer()
         mBackbufferNeedsClear = true;
     }
 
     mShouldPresent = false;
 
     return true;
 }
 
+// Prepare the context for capture before compositing
+void
+WebGLContext::BeginComposition()
+{
+    // Present our screenbuffer, if needed.
+    PresentScreenBuffer();
+    mDrawCallsSinceLastFlush = 0;
+}
+
+// Clean up the context after captured for compositing
+void
+WebGLContext::EndComposition()
+{
+    // Mark ourselves as no longer invalidated.
+    MarkContextClean();
+    UpdateLastUseIndex();
+}
+
 void
 WebGLContext::DummyReadFramebufferOperation(const char* funcName)
 {
     if (!mBoundReadFramebuffer)
         return; // Infallible.
 
     nsCString fbStatusInfo;
     const auto status = mBoundReadFramebuffer->CheckFramebufferStatus(&fbStatusInfo);
@@ -2335,77 +2349,79 @@ WebGLContext::GetUnpackSize(bool isFunc3
     totalBytes += usedBytesPerRow;
 
     return totalBytes;
 }
 
 already_AddRefed<layers::SharedSurfaceTextureClient>
 WebGLContext::GetVRFrame()
 {
-  VRManagerChild *vrmc = VRManagerChild::Get();
-  if (!vrmc) {
-    return nullptr;
-  }
-
-  PresentScreenBuffer();
-  mDrawCallsSinceLastFlush = 0;
-
-  MarkContextClean();
-  UpdateLastUseIndex();
-
-  gl::GLScreenBuffer* screen = gl->Screen();
-  if (!screen) {
-    return nullptr;
-  }
-
-  RefPtr<SharedSurfaceTextureClient> sharedSurface = screen->Front();
-  if (!sharedSurface) {
-    return nullptr;
-  }
-
-  if (sharedSurface && sharedSurface->GetAllocator() != vrmc) {
-    RefPtr<SharedSurfaceTextureClient> dest =
-      screen->Factory()->NewTexClient(sharedSurface->GetSize());
-    if (!dest) {
-      return nullptr;
+    VRManagerChild* vrmc = VRManagerChild::Get();
+    if (!vrmc) {
+        return nullptr;
+    }
+
+    /**
+     * Swap buffers as though composition has occurred.
+     * We will then share the resulting front buffer to be submitted to the VR
+     * compositor.
+     */
+    BeginComposition();
+    EndComposition();
+
+    gl::GLScreenBuffer* screen = gl->Screen();
+    if (!screen) {
+        return nullptr;
     }
-    gl::SharedSurface* destSurf = dest->Surf();
-    destSurf->ProducerAcquire();
-    SharedSurface::ProdCopy(sharedSurface->Surf(), dest->Surf(), screen->Factory());
-    destSurf->ProducerRelease();
-
-    return dest.forget();
-  }
+
+    RefPtr<SharedSurfaceTextureClient> sharedSurface = screen->Front();
+    if (!sharedSurface) {
+        return nullptr;
+    }
+
+    if (sharedSurface && sharedSurface->GetAllocator() != vrmc) {
+        RefPtr<SharedSurfaceTextureClient> dest =
+        screen->Factory()->NewTexClient(sharedSurface->GetSize());
+        if (!dest) {
+            return nullptr;
+        }
+        gl::SharedSurface* destSurf = dest->Surf();
+        destSurf->ProducerAcquire();
+        SharedSurface::ProdCopy(sharedSurface->Surf(), dest->Surf(),
+                                screen->Factory());
+        destSurf->ProducerRelease();
+
+        return dest.forget();
+    }
 
   return sharedSurface.forget();
 }
 
 bool
 WebGLContext::StartVRPresentation()
 {
-  VRManagerChild *vrmc = VRManagerChild::Get();
-  if (!vrmc) {
-    return false;
-  }
-  gl::GLScreenBuffer* screen = gl->Screen();
-  if (!screen) {
-    return false;
-  }
-  gl::SurfaceCaps caps = screen->mCaps;
-
-  UniquePtr<gl::SurfaceFactory> factory =
-    gl::GLScreenBuffer::CreateFactory(gl,
-      caps,
-      vrmc,
-      vrmc->GetBackendType(),
-      TextureFlags::ORIGIN_BOTTOM_LEFT);
-
-  screen->Morph(Move(factory));
-  mVRPresentationActive = true;
-  return true;
+    VRManagerChild* vrmc = VRManagerChild::Get();
+    if (!vrmc) {
+        return false;
+    }
+    gl::GLScreenBuffer* screen = gl->Screen();
+    if (!screen) {
+        return false;
+    }
+    gl::SurfaceCaps caps = screen->mCaps;
+
+    UniquePtr<gl::SurfaceFactory> factory =
+        gl::GLScreenBuffer::CreateFactory(gl,
+            caps,
+            vrmc,
+            vrmc->GetBackendType(),
+            TextureFlags::ORIGIN_BOTTOM_LEFT);
+
+    screen->Morph(Move(factory));
+    return true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // XPCOM goop
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(WebGLContext)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(WebGLContext)
 
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -350,16 +350,21 @@ public:
     gl::GLContext* GL() const { return gl; }
 
     bool IsPremultAlpha() const { return mOptions.premultipliedAlpha; }
 
     bool IsPreservingDrawingBuffer() const { return mOptions.preserveDrawingBuffer; }
 
     bool PresentScreenBuffer();
 
+    // Prepare the context for capture before compositing
+    void BeginComposition();
+    // Clean up the context after captured for compositing
+    void EndComposition();
+
     // a number that increments every time we have an event that causes
     // all context resources to be lost.
     uint32_t Generation() { return mGeneration.value(); }
 
     // This is similar to GLContext::ClearSafely, but tries to minimize the
     // amount of work it does.
     // It only clears the buffers we specify, and can reset its state without
     // first having to query anything, as WebGL knows its state at all times.
@@ -1512,17 +1517,16 @@ protected:
     bool ShouldGenerateWarnings() const;
 
     uint64_t mLastUseIndex;
 
     bool mNeedsFakeNoAlpha;
     bool mNeedsFakeNoDepth;
     bool mNeedsFakeNoStencil;
     bool mNeedsEmulatedLoneDepthStencil;
-    bool mVRPresentationActive;
 
     bool HasTimestampBits() const;
 
     struct ScopedMaskWorkaround {
         WebGLContext& mWebGL;
         const bool mFakeNoAlpha;
         const bool mFakeNoDepth;
         const bool mFakeNoStencil;