Bug 1136508 - Detect CopyTexImage feedback loops. - r=mtseng
authorJeff Gilbert <jgilbert@mozilla.com>
Wed, 13 Jul 2016 00:48:55 -0700
changeset 304883 190fa9a5f989a43f93295d8364ac83f6e6c1e4e1
parent 304882 375d352b07414af85807421054a064e31c4db868
child 304884 13d68716249bee54c5c1e8785871557f62ebb186
push id79446
push userjgilbert@mozilla.com
push dateWed, 13 Jul 2016 18:59:50 +0000
treeherdermozilla-inbound@da8a989f65d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmtseng
bugs1136508
milestone50.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 1136508 - Detect CopyTexImage feedback loops. - r=mtseng MozReview-Commit-ID: G1RsyyYMacp
dom/canvas/WebGLTexture.h
dom/canvas/WebGLTextureUpload.cpp
--- a/dom/canvas/WebGLTexture.h
+++ b/dom/canvas/WebGLTexture.h
@@ -247,16 +247,17 @@ protected:
                                        GLint level, uint32_t width, uint32_t height,
                                        uint32_t depth,
                                        WebGLTexture::ImageInfo** const out_imageInfo);
     bool ValidateTexImageSelection(const char* funcName, TexImageTarget target,
                                    GLint level, GLint xOffset, GLint yOffset,
                                    GLint zOffset, uint32_t width, uint32_t height,
                                    uint32_t depth,
                                    WebGLTexture::ImageInfo** const out_imageInfo);
+    bool ValidateCopyTexImageForFeedback(const char* funcName, uint32_t level) const;
 
     bool ValidateUnpack(const char* funcName, const webgl::TexUnpackBlob* blob,
                         bool isFunc3D, const webgl::PackingInfo& srcPI) const;
 public:
     void TexStorage(const char* funcName, TexTarget target, GLsizei levels,
                     GLenum sizedFormat, GLsizei width, GLsizei height, GLsizei depth);
 protected:
     void TexImage(const char* funcName, TexImageTarget target, GLint level,
--- a/dom/canvas/WebGLTextureUpload.cpp
+++ b/dom/canvas/WebGLTextureUpload.cpp
@@ -1908,16 +1908,41 @@ ValidateCopyDestUsage(const char* funcNa
                                      " dest: %s)",
                                      funcName, srcFormat->name, dstFormat->name);
         return nullptr;
     }
 
     return dstUsage;
 }
 
+bool
+WebGLTexture::ValidateCopyTexImageForFeedback(const char* funcName, uint32_t level) const
+{
+    const auto& fb = mContext->mBoundReadFramebuffer;
+    if (fb) {
+        const auto readBuffer = fb->ReadBufferMode();
+        MOZ_ASSERT(readBuffer != LOCAL_GL_NONE);
+        const uint32_t colorAttachment = readBuffer - LOCAL_GL_COLOR_ATTACHMENT0;
+        const auto& attach = fb->ColorAttachment(colorAttachment);
+
+        if (attach.Texture() == this &&
+            attach.MipLevel() == uint32_t(level))
+        {
+            // Note that the TexImageTargets *don't* have to match for this to be
+            // undefined per GLES 3.0.4 p211, thus an INVALID_OP in WebGL.
+            mContext->ErrorInvalidOperation("%s: Feedback loop detected, as this texture"
+                                            " is already attached to READ_FRAMEBUFFER's"
+                                            " READ_BUFFER-selected COLOR_ATTACHMENT%u.",
+                                            funcName, colorAttachment);
+            return false;
+        }
+    }
+    return true;
+}
+
 // There is no CopyTexImage3D.
 void
 WebGLTexture::CopyTexImage2D(TexImageTarget target, GLint level, GLenum internalFormat,
                              GLint x, GLint y, GLsizei rawWidth, GLsizei rawHeight,
                              GLint border)
 {
     const char funcName[] = "CopyTexImage2D";
 
@@ -1946,16 +1971,19 @@ WebGLTexture::CopyTexImage2D(TexImageTar
     uint32_t srcWidth;
     uint32_t srcHeight;
     GLenum srcMode;
     if (!mContext->ValidateCurFBForRead(funcName, &srcUsage, &srcWidth, &srcHeight,
                                         &srcMode))
         return;
     auto srcFormat = srcUsage->format;
 
+    if (!ValidateCopyTexImageForFeedback(funcName, level))
+        return;
+
     // GLES 3.0.4 p145:
     // "Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
     //  INVALID_OPERATION error if any of the following conditions is true: READ_BUFFER
     //  is NONE"
     if (srcMode == LOCAL_GL_NONE) {
         mContext->ErrorInvalidOperation("%s: READ_BUFFER is NONE. ", funcName);
         return;
     }
@@ -2087,16 +2115,19 @@ WebGLTexture::CopyTexSubImage(const char
     uint32_t srcWidth;
     uint32_t srcHeight;
     GLenum srcMode;
     if (!mContext->ValidateCurFBForRead(funcName, &srcUsage, &srcWidth, &srcHeight,
                                         &srcMode))
         return;
     auto srcFormat = srcUsage->format;
 
+    if (!ValidateCopyTexImageForFeedback(funcName, level))
+        return;
+
     // GLES 3.0.4 p145:
     // "Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
     //  INVALID_OPERATION error if any of the following conditions is true: READ_BUFFER
     //  is NONE"
     if (srcMode == LOCAL_GL_NONE) {
         mContext->ErrorInvalidOperation("%s: READ_BUFFER is NONE. ", funcName);
         return;
     }