Bug 1325733 - Mark read/draw calls better. - r=daoshengmu draft
authorJeff Gilbert <jgilbert@mozilla.com>
Fri, 23 Dec 2016 18:54:04 -0800
changeset 453624 0651f44ec912a007ce73669ff8c6c8aa89a6439f
parent 453623 43c52534c162bbabdabf776b80aaee07b7efd075
child 453625 c77195ad565b28a619c565c591b58c0f8d13a442
push id39720
push userbmo:jgilbert@mozilla.com
push dateSat, 24 Dec 2016 03:12:22 +0000
reviewersdaoshengmu
bugs1325733
milestone53.0a1
Bug 1325733 - Mark read/draw calls better. - r=daoshengmu MozReview-Commit-ID: A6spAvpKvd7
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextGL.cpp
dom/canvas/WebGLFramebuffer.cpp
dom/canvas/WebGLTextureUpload.cpp
gfx/gl/GLContext.h
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -186,18 +186,16 @@ WebGLContext::WebGLContext()
         GenerateWarning("webgl.max-warnings-per-context size is too large (seems like a negative value wrapped)");
         mMaxWarnings = 0;
     }
 
     mLastUseIndex = 0;
 
     InvalidateBufferFetching();
 
-    mBackbufferNeedsClear = true;
-
     mDisableFragHighP = false;
 
     mDrawCallsSinceLastFlush = 0;
 }
 
 WebGLContext::~WebGLContext()
 {
     RemovePostRefreshObserver();
@@ -1117,24 +1115,16 @@ WebGLContext::SetDimensions(int32_t sign
 }
 
 void
 WebGLContext::ClearBackbufferIfNeeded()
 {
     if (!mBackbufferNeedsClear)
         return;
 
-#ifdef DEBUG
-    gl->MakeCurrent();
-
-    GLuint fb = 0;
-    gl->GetUIntegerv(LOCAL_GL_FRAMEBUFFER_BINDING, &fb);
-    MOZ_ASSERT(fb == 0);
-#endif
-
     ClearScreen();
 
     mBackbufferNeedsClear = false;
 }
 
 void
 WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
 {
@@ -2075,16 +2065,26 @@ WebGLContext::ScopedDrawCallWrapper::~Sc
 /*static*/ bool
 WebGLContext::ScopedDrawCallWrapper::HasDepthButNoStencil(const WebGLFramebuffer* fb)
 {
     const auto& depth = fb->DepthAttachment();
     const auto& stencil = fb->StencilAttachment();
     return depth.IsDefined() && !stencil.IsDefined();
 }
 
+////
+
+void
+WebGLContext::OnBeforeReadCall()
+{
+    if (!mBoundReadFramebuffer) {
+        ClearBackbufferIfNeeded();
+    }
+}
+
 ////////////////////////////////////////
 
 IndexedBufferBinding::IndexedBufferBinding()
     : mRangeStart(0)
     , mRangeSize(0)
 { }
 
 uint64_t
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1999,21 +1999,24 @@ protected:
                 HasDepthButNoStencil(webgl.mBoundDrawFramebuffer))
             {
                 return true;
             }
 
             return false;
         }
 
+        ////
+
         explicit ScopedDrawCallWrapper(WebGLContext& webgl);
-
         ~ScopedDrawCallWrapper();
     };
 
+    void OnBeforeReadCall();
+
     void LoseOldestWebGLContextIfLimitExceeded();
     void UpdateLastUseIndex();
 
     template <typename WebGLObjectType>
     JS::Value WebGLObjectAsJSValue(JSContext* cx, const WebGLObjectType*,
                                    ErrorResult& rv) const;
     template <typename WebGLObjectType>
     JSObject* WebGLObjectAsJSObject(JSContext* cx, const WebGLObjectType*,
--- a/dom/canvas/WebGLContextGL.cpp
+++ b/dom/canvas/WebGLContextGL.cpp
@@ -1542,16 +1542,18 @@ WebGLContext::ReadPixelsImpl(GLint x, GL
     if (bytesNeeded > dataLen) {
         ErrorInvalidOperation("readPixels: buffer too small");
         return;
     }
 
     ////////////////
     // Now that the errors are out of the way, on to actually reading!
 
+    OnBeforeReadCall();
+
     uint32_t readX, readY;
     uint32_t writeX, writeY;
     uint32_t rwWidth, rwHeight;
     Intersect(srcWidth, x, width, &readX, &writeX, &rwWidth);
     Intersect(srcHeight, y, height, &readY, &writeY, &rwHeight);
 
     if (rwWidth == uint32_t(width) && rwHeight == uint32_t(height)) {
         DoReadPixelsAndConvert(srcFormat->format, x, y, width, height, packFormat,
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -1863,16 +1863,17 @@ WebGLFramebuffer::BlitFramebuffer(WebGLC
     } else if (!srcFB && !dstFB) {
         webgl->ErrorInvalidOperation("%s: Feedback with default framebuffer.", funcName);
         return;
     }
 
     ////
 
     gl->MakeCurrent();
+    webgl->OnBeforeReadCall();
     WebGLContext::ScopedDrawCallWrapper wrapper(*webgl);
     gl->fBlitFramebuffer(srcX0, srcY0, srcX1, srcY1,
                          dstX0, dstY0, dstX1, dstY1,
                          mask, filter);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // Goop.
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -1982,18 +1982,17 @@ DoCopyTexOrSubImage(WebGLContext* webgl,
                     const WebGLTexture* tex, TexImageTarget target, GLint level,
                     GLint xWithinSrc, GLint yWithinSrc,
                     uint32_t srcTotalWidth, uint32_t srcTotalHeight,
                     const webgl::FormatUsageInfo* srcUsage,
                     GLint xOffset, GLint yOffset, GLint zOffset,
                     uint32_t dstWidth, uint32_t dstHeight,
                     const webgl::FormatUsageInfo* dstUsage)
 {
-    gl::GLContext* gl = webgl->gl;
-    gl->MakeCurrent();
+    const auto& gl = webgl->gl;
 
     ////
 
     uint32_t readX, readY;
     uint32_t writeX, writeY;
     uint32_t rwWidth, rwHeight;
     Intersect(srcTotalWidth, xWithinSrc, dstWidth, &readX, &writeX, &rwWidth);
     Intersect(srcTotalHeight, yWithinSrc, dstHeight, &readY, &writeY, &rwHeight);
@@ -2122,16 +2121,19 @@ WebGLTexture::CopyTexImage2D(TexImageTar
     }
 
     if (!ValidateCopyTexImageFormats(mContext, funcName, srcFormat, dstFormat))
         return;
 
     ////////////////////////////////////
     // Do the thing!
 
+    mContext->gl->MakeCurrent();
+    mContext->OnBeforeReadCall();
+
     const bool isSubImage = false;
     if (!DoCopyTexOrSubImage(mContext, funcName, isSubImage, this, target, level, x, y,
                              srcTotalWidth, srcTotalHeight, srcUsage, 0, 0, 0, width,
                              height, dstUsage))
     {
         return;
     }
 
@@ -2197,16 +2199,19 @@ WebGLTexture::CopyTexSubImage(const char
 
     auto srcFormat = srcUsage->format;
     if (!ValidateCopyTexImageFormats(mContext, funcName, srcFormat, dstFormat))
         return;
 
     ////////////////////////////////////
     // Do the thing!
 
+    mContext->gl->MakeCurrent();
+    mContext->OnBeforeReadCall();
+
     bool uploadWillInitialize;
     if (!EnsureImageDataInitializedForUpload(this, funcName, target, level, xOffset,
                                              yOffset, zOffset, width, height, depth,
                                              imageInfo, &uploadWillInitialize))
     {
         return;
     }
 
--- a/gfx/gl/GLContext.h
+++ b/gfx/gl/GLContext.h
@@ -882,27 +882,31 @@ public:
         BEFORE_GL_CALL;
         mSymbols.fBindBuffer(target, buffer);
         AFTER_GL_CALL;
     }
 
     void fBindFramebuffer(GLenum target, GLuint framebuffer);
 
     void fInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) {
+        BeforeGLDrawCall();
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fInvalidateFramebuffer);
         mSymbols.fInvalidateFramebuffer(target, numAttachments, attachments);
         AFTER_GL_CALL;
+        AfterGLDrawCall();
     }
 
     void fInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) {
+        BeforeGLDrawCall();
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fInvalidateSubFramebuffer);
         mSymbols.fInvalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height);
         AFTER_GL_CALL;
+        AfterGLDrawCall();
     }
 
     void fBindTexture(GLenum target, GLuint texture) {
         BEFORE_GL_CALL;
         mSymbols.fBindTexture(target, texture);
         AFTER_GL_CALL;
     }
 
@@ -3135,21 +3139,23 @@ public:
                                 pixels);
         AFTER_GL_CALL;
     }
 
     void fCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset,
                             GLint yoffset, GLint zoffset, GLint x,
                             GLint y, GLsizei width, GLsizei height)
     {
+        BeforeGLReadCall();
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fCopyTexSubImage3D);
         mSymbols.fCopyTexSubImage3D(target, level, xoffset, yoffset, zoffset,
                                     x, y, width, height);
         AFTER_GL_CALL;
+        AfterGLReadCall();
     }
 
     void fCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat,
                                GLsizei width, GLsizei height, GLsizei depth,
                                GLint border, GLsizei imageSize, const GLvoid* data)
     {
         BEFORE_GL_CALL;
         ASSERT_SYMBOL_PRESENT(fCompressedTexImage3D);