Bug 1296745 - Clean up WebGLContext
MozReview-Commit-ID: B6xazNgeJ9A
--- 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;