Bug 706674 - WebGLFramebufferAttachment's are not WebGLRectangleObject's - r=jgilbert
authorBenoit Jacob <jacob.benoit.1@gmail.com>
Tue, 24 Jan 2012 16:12:31 -0500
changeset 85252 f9a4b9014002e80aefb0c1e6dc47941db66f965c
parent 85251 bdc686b071bb16499120c8b679f113ea51530c8d
child 85253 a4e932fb3c3d893e60d34ad925ec48f1e54dab1c
push id5249
push userbjacob@mozilla.com
push dateTue, 24 Jan 2012 21:13:03 +0000
treeherdermozilla-inbound@23ec123586ba [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert
bugs706674
milestone12.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 706674 - WebGLFramebufferAttachment's are not WebGLRectangleObject's - r=jgilbert The main change is: remove the WebGLRectangleObject inheritance from WebGLFramebufferAttachment, and instead have WebGLFramebufferAttachment query its texture or renderbuffer for their dimensions, when needed. In the course of doing this, a couple other needed changes appeared: - let WebGLTexture::ImageInfo inherit WebGLRectangleObject, so that WebGLFramebufferAttachment can return a pointer to it right away in the texture case - add a FramebufferRectangleObject() method to WebGLContext, that will return the dimensions of the bound FBO if there is one, otherwise will just return the contexts' own dimensions. - in order to do that, it was very convenient to let WebGLContext inherit WebGLRectangleObject so that FramebufferRectangleObject() could just return a pointer to that in the no-bound-FBO case. - move WebGLRectangleObject up in the file, above WebGLContext - there was a plain bug in WebGLFramebufferAttachment::HasAlpha(), we were not using the right image info within the texture.
content/canvas/src/WebGLContext.cpp
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
content/canvas/test/webgl/failing_tests_linux.txt
content/canvas/test/webgl/failing_tests_mac.txt
content/canvas/test/webgl/failing_tests_windows.txt
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -216,17 +216,16 @@ NS_NewCanvasRenderingContextWebGL(nsIDOM
     NS_ADDREF(*aResult = ctx);
     return NS_OK;
 }
 
 WebGLContext::WebGLContext()
     : mCanvasElement(nsnull),
       gl(nsnull)
 {
-    mWidth = mHeight = 0;
     mGeneration = 0;
     mInvalidated = false;
     mResetLayer = true;
     mVerbose = false;
     mOptionsFrozen = false;
 
     mActiveTexture = 0;
     mWebGLError = LOCAL_GL_NO_ERROR;
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -92,16 +92,17 @@ class WebGLBuffer;
 class WebGLProgram;
 class WebGLShader;
 class WebGLFramebuffer;
 class WebGLRenderbuffer;
 class WebGLUniformLocation;
 class WebGLExtension;
 struct WebGLVertexAttribData;
 
+class WebGLRectangleObject;
 class WebGLContextBoundObject;
 
 enum FakeBlackStatus { DoNotNeedFakeBlack, DoNeedFakeBlack, DontKnowIfNeedFakeBlack };
 
 struct VertexAttrib0Status {
     enum { Default, EmulatedUninitializedArray, EmulatedInitializedArray };
 };
 
@@ -430,16 +431,57 @@ private:
             NS_RUNTIMEABORT("ran out of monotonic ids!");
         return mCurrentMonotonicHandle.value();
     }
 
     nsTArray<Entry> mArray;
     CheckedInt<WebGLMonotonicHandle> mCurrentMonotonicHandle;
 };
 
+// this class is a mixin for GL objects that have dimensions
+// that we need to track.
+class WebGLRectangleObject
+{
+public:
+    WebGLRectangleObject()
+        : mWidth(0), mHeight(0) { }
+
+    WebGLRectangleObject(WebGLsizei width, WebGLsizei height)
+        : mWidth(width), mHeight(height) { }
+
+    WebGLsizei Width() const { return mWidth; }
+    void width(WebGLsizei value) { mWidth = value; }
+
+    WebGLsizei Height() const { return mHeight; }
+    void height(WebGLsizei value) { mHeight = value; }
+
+    void setDimensions(WebGLsizei width, WebGLsizei height) {
+        mWidth = width;
+        mHeight = height;
+    }
+
+    void setDimensions(WebGLRectangleObject *rect) {
+        if (rect) {
+            mWidth = rect->Width();
+            mHeight = rect->Height();
+        } else {
+            mWidth = 0;
+            mHeight = 0;
+        }
+    }
+
+    bool HasSameDimensionsAs(const WebGLRectangleObject& other) const {
+        return Width() == other.Width() && Height() == other.Height(); 
+    }
+
+protected:
+    WebGLsizei mWidth;
+    WebGLsizei mHeight;
+};
+
 struct WebGLContextOptions {
     // these are defaults
     WebGLContextOptions()
         : alpha(true), depth(true), stencil(false),
           premultipliedAlpha(true), antialias(true),
           preserveDrawingBuffer(false)
     { }
 
@@ -464,17 +506,18 @@ struct WebGLContextOptions {
     bool antialias;
     bool preserveDrawingBuffer;
 };
 
 class WebGLContext :
     public nsIDOMWebGLRenderingContext,
     public nsICanvasRenderingContextInternal,
     public nsSupportsWeakReference,
-    public nsITimerCallback
+    public nsITimerCallback,
+    public WebGLRectangleObject
 {
     friend class WebGLMemoryReporter;
     friend class WebGLExtensionLoseContext;
     friend class WebGLContextUserData;
 
 public:
     WebGLContext();
     virtual ~WebGLContext();
@@ -539,16 +582,18 @@ public:
                                                  CanvasLayer *aOldLayer,
                                                  LayerManager *aManager);
     void MarkContextClean() { mInvalidated = false; }
 
     // a number that increments every time we have an event that causes
     // all context resources to be lost.
     PRUint32 Generation() { return mGeneration.value(); }
 
+    const WebGLRectangleObject *FramebufferRectangleObject() const;
+
     // this is similar to GLContext::ClearSafely, but is more comprehensive
     // (takes care of scissor, stencil write mask, dithering, viewport...)
     // WebGL has more complex needs than GLContext as content controls GL state.
     void ForceClearFramebufferWithDefaultValues(PRUint32 mask, const nsIntRect& viewportRect);
 
     // if the preserveDrawingBuffer context option is false, we need to clear the back buffer
     // after it's been presented to the compositor. This function does that if needed.
     // See section 2.2 in the WebGL spec.
@@ -637,17 +682,16 @@ protected:
 
     nsCOMPtr<nsIDOMHTMLCanvasElement> mCanvasElement;
     nsHTMLCanvasElement *HTMLCanvasElement() {
         return static_cast<nsHTMLCanvasElement*>(mCanvasElement.get());
     }
 
     nsRefPtr<gl::GLContext> gl;
 
-    PRInt32 mWidth, mHeight;
     CheckedUint32 mGeneration;
 
     WebGLContextOptions mOptions;
 
     bool mInvalidated;
     bool mResetLayer;
     bool mVerbose;
     bool mOptionsFrozen;
@@ -906,55 +950,16 @@ public:
     friend class WebGLFramebuffer;
     friend class WebGLRenderbuffer;
     friend class WebGLProgram;
     friend class WebGLBuffer;
     friend class WebGLShader;
     friend class WebGLUniformLocation;
 };
 
-// this class is a mixin for GL objects that have dimensions
-// that we need to track.
-class WebGLRectangleObject
-{
-protected:
-    WebGLRectangleObject()
-        : mWidth(0), mHeight(0) { }
-
-public:
-    WebGLsizei width() const { return mWidth; }
-    void width(WebGLsizei value) { mWidth = value; }
-
-    WebGLsizei height() const { return mHeight; }
-    void height(WebGLsizei value) { mHeight = value; }
-
-    void setDimensions(WebGLsizei width, WebGLsizei height) {
-        mWidth = width;
-        mHeight = height;
-    }
-
-    void setDimensions(WebGLRectangleObject *rect) {
-        if (rect) {
-            mWidth = rect->width();
-            mHeight = rect->height();
-        } else {
-            mWidth = 0;
-            mHeight = 0;
-        }
-    }
-
-    bool HasSameDimensionsAs(const WebGLRectangleObject& other) const {
-        return width() == other.width() && height() == other.height(); 
-    }
-
-protected:
-    WebGLsizei mWidth;
-    WebGLsizei mHeight;
-};
-
 // This class is a mixin for objects that are tied to a specific
 // context (which is to say, all of them).  They provide initialization
 // as well as comparison with the current context.
 class WebGLContextBoundObject
 {
 public:
     WebGLContextBoundObject(WebGLContext *context) {
         mContext = context;
@@ -1201,21 +1206,22 @@ protected:
     bool mHasEverBeenBound;
     WebGLuint mGLName;
 
     // we store information about the various images that are part of
     // this texture (cubemap faces, mipmap levels)
 
 public:
 
-    struct ImageInfo {
-        ImageInfo() : mWidth(0), mHeight(0), mFormat(0), mType(0), mIsDefined(false) {}
+    class ImageInfo : public WebGLRectangleObject {
+    public:
+        ImageInfo() : mFormat(0), mType(0), mIsDefined(false) {}
         ImageInfo(WebGLsizei width, WebGLsizei height,
                   WebGLenum format, WebGLenum type)
-            : mWidth(width), mHeight(height), mFormat(format), mType(type), mIsDefined(true) {}
+            : WebGLRectangleObject(width, height), mFormat(format), mType(type), mIsDefined(true) {}
 
         bool operator==(const ImageInfo& a) const {
             return mWidth == a.mWidth && mHeight == a.mHeight &&
                    mFormat == a.mFormat && mType == a.mType;
         }
         bool operator!=(const ImageInfo& a) const {
             return !(*this == a);
         }
@@ -1230,19 +1236,23 @@ public:
                    is_pot_assuming_nonnegative(mHeight); // negative sizes should never happen (caught in texImage2D...)
         }
         PRInt64 MemoryUsage() const {
             if (!mIsDefined)
                 return 0;
             PRInt64 texelSize = WebGLContext::GetTexelSize(mFormat, mType);
             return PRInt64(mWidth) * PRInt64(mHeight) * texelSize;
         }
-        WebGLsizei mWidth, mHeight;
+        WebGLenum Format() const { return mFormat; }
+        WebGLenum Type() const { return mType; }
+    protected:
         WebGLenum mFormat, mType;
         bool mIsDefined;
+
+        friend class WebGLTexture;
     };
 
     ImageInfo& ImageInfoAt(size_t level, size_t face = 0) {
 #ifdef DEBUG
         if (face >= mFacesCount)
             NS_ERROR("wrong face index, must be 0 for TEXTURE_2D and at most 5 for cube maps");
 #endif
         // no need to check level as a wrong value would be caught by ElementAt().
@@ -1821,17 +1831,17 @@ public:
 
     WebGLenum InternalFormat() const { return mInternalFormat; }
     void SetInternalFormat(WebGLenum aInternalFormat) { mInternalFormat = aInternalFormat; }
     
     WebGLenum InternalFormatForGL() const { return mInternalFormatForGL; }
     void SetInternalFormatForGL(WebGLenum aInternalFormatForGL) { mInternalFormatForGL = aInternalFormatForGL; }
     
     PRInt64 MemoryUsage() const {
-        PRInt64 pixels = PRInt64(width()) * PRInt64(height());
+        PRInt64 pixels = PRInt64(Width()) * PRInt64(Height());
         switch (mInternalFormatForGL) {
             case LOCAL_GL_STENCIL_INDEX8:
                 return pixels;
             case LOCAL_GL_RGBA4:
             case LOCAL_GL_RGB5_A1:
             case LOCAL_GL_RGB565:
             case LOCAL_GL_DEPTH_COMPONENT16:
                 return 2 * pixels;
@@ -1859,17 +1869,16 @@ protected:
     WebGLMonotonicHandle mMonotonicHandle;
     bool mHasEverBeenBound;
     bool mInitialized;
 
     friend class WebGLFramebuffer;
 };
 
 class WebGLFramebufferAttachment
-    : public WebGLRectangleObject
 {
     // deleting a texture or renderbuffer immediately detaches it
     WebGLRefPtr<WebGLTexture> mTexturePtr;
     WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
     WebGLenum mAttachmentPoint;
     WebGLint mTextureLevel;
     WebGLenum mTextureCubeMapFace;
 
@@ -1885,49 +1894,48 @@ public:
     bool IsDeleteRequested() const {
         return Texture() ? Texture()->IsDeleteRequested()
              : Renderbuffer() ? Renderbuffer()->IsDeleteRequested()
              : false;
     }
 
     bool HasAlpha() const {
         WebGLenum format = 0;
-        if (Texture() && Texture()->HasImageInfoAt(0,0))
-            format = mTexturePtr->ImageInfoAt(0,0).mFormat;
+        if (Texture() && Texture()->HasImageInfoAt(mTextureLevel, mTextureCubeMapFace))
+            format = Texture()->ImageInfoAt(mTextureLevel, mTextureCubeMapFace).Format();
         else if (Renderbuffer())
-            format = mRenderbufferPtr->InternalFormat();
+            format = Renderbuffer()->InternalFormat();
         return format == LOCAL_GL_RGBA ||
                format == LOCAL_GL_LUMINANCE_ALPHA ||
                format == LOCAL_GL_ALPHA ||
                format == LOCAL_GL_RGBA4 ||
                format == LOCAL_GL_RGB5_A1;
     }
 
     void SetTexture(WebGLTexture *tex, WebGLint level, WebGLenum face) {
         mTexturePtr = tex;
         mRenderbufferPtr = nsnull;
         mTextureLevel = level;
         mTextureCubeMapFace = face;
-        if (tex) {
-            const WebGLTexture::ImageInfo &imageInfo = tex->ImageInfoAt(level, face);
-            setDimensions(imageInfo.mWidth, imageInfo.mHeight);
-        } else {
-            setDimensions(0, 0);
-        }
     }
     void SetRenderbuffer(WebGLRenderbuffer *rb) {
         mTexturePtr = nsnull;
         mRenderbufferPtr = rb;
-        setDimensions(rb);
+    }
+    const WebGLTexture *Texture() const {
+        return mTexturePtr;
     }
-    WebGLTexture *Texture() const {
-        return mTexturePtr.get();
+    WebGLTexture *Texture() {
+        return mTexturePtr;
     }
-    WebGLRenderbuffer *Renderbuffer() const {
-        return mRenderbufferPtr.get();
+    const WebGLRenderbuffer *Renderbuffer() const {
+        return mRenderbufferPtr;
+    }
+    WebGLRenderbuffer *Renderbuffer() {
+        return mRenderbufferPtr;
     }
     WebGLint TextureLevel() const {
         return mTextureLevel;
     }
     WebGLenum TextureCubeMapFace() const {
         return mTextureCubeMapFace;
     }
 
@@ -1959,16 +1967,32 @@ public:
     bool HasUninitializedRenderbuffer() const {
         return mRenderbufferPtr && !mRenderbufferPtr->Initialized();
     }
 
     void Reset() {
         mTexturePtr = nsnull;
         mRenderbufferPtr = nsnull;
     }
+
+    const WebGLRectangleObject* RectangleObject() const {
+        if (Texture() && Texture()->HasImageInfoAt(mTextureLevel, mTextureCubeMapFace))
+            return &Texture()->ImageInfoAt(mTextureLevel, mTextureCubeMapFace);
+        else if (Renderbuffer())
+            return Renderbuffer();
+        else
+            return nsnull;
+    }
+    bool HasSameDimensionsAs(const WebGLFramebufferAttachment& other) const {
+        const WebGLRectangleObject *thisRect = RectangleObject();
+        const WebGLRectangleObject *otherRect = other.RectangleObject();
+        return thisRect &&
+               otherRect &&
+               thisRect->HasSameDimensionsAs(*otherRect);
+    }
 };
 
 class WebGLFramebuffer
     : public nsIWebGLFramebuffer
     , public WebGLRefCountedObject<WebGLFramebuffer>
     , public WebGLContextBoundObject
 {
 public:
@@ -1998,19 +2022,16 @@ public:
         mContext->gl->fDeleteFramebuffers(1, &mGLName);
         mContext->mFramebuffers.RemoveElement(mMonotonicHandle);
     }
 
     bool HasEverBeenBound() { return mHasEverBeenBound; }
     void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
     WebGLuint GLName() { return mGLName; }
 
-    WebGLsizei width() { return mColorAttachment.width(); }
-    WebGLsizei height() { return mColorAttachment.height(); }
-
     nsresult FramebufferRenderbuffer(WebGLenum target,
                                      WebGLenum attachment,
                                      WebGLenum rbtarget,
                                      nsIWebGLRenderbuffer *rbobj)
     {
         WebGLuint renderbuffername;
         bool isNull;
         WebGLRenderbuffer *wrb;
@@ -2205,16 +2226,20 @@ public:
         if (mDepthAttachment.Renderbuffer() == rb)
             FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nsnull);
         if (mStencilAttachment.Renderbuffer() == rb)
             FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nsnull);
         if (mDepthStencilAttachment.Renderbuffer() == rb)
             FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nsnull);
     }
 
+    const WebGLRectangleObject *RectangleObject() {
+        return mColorAttachment.RectangleObject();
+    }
+
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLFRAMEBUFFER
 
 protected:
 
     // protected because WebGLContext should only call InitializeRenderbuffers
     void InitializeRenderbuffers()
     {
@@ -2235,18 +2260,18 @@ protected:
         }
 
         if (mStencilAttachment.HasUninitializedRenderbuffer() ||
             mDepthStencilAttachment.HasUninitializedRenderbuffer())
         {
             mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
         }
 
-        // the one useful line of code
-        mContext->ForceClearFramebufferWithDefaultValues(mask, nsIntRect(0,0,width(),height()));
+        const WebGLRectangleObject *rect = mColorAttachment.RectangleObject();
+        mContext->ForceClearFramebufferWithDefaultValues(mask, nsIntRect(0, 0, rect->Width(), rect->Height()));
 
         if (mColorAttachment.HasUninitializedRenderbuffer())
             mColorAttachment.Renderbuffer()->SetInitialized(true);
 
         if (mDepthAttachment.HasUninitializedRenderbuffer())
             mDepthAttachment.Renderbuffer()->SetInitialized(true);
 
         if (mStencilAttachment.HasUninitializedRenderbuffer())
@@ -2358,16 +2383,21 @@ public:
     WebGLExtension(WebGLContext *baseContext)
         : WebGLContextBoundObject(baseContext)
     {}
 
     NS_DECL_ISUPPORTS
     NS_DECL_NSIWEBGLEXTENSION
 };
 
+inline const WebGLRectangleObject *WebGLContext::FramebufferRectangleObject() const {
+    return mBoundFramebuffer ? mBoundFramebuffer->RectangleObject()
+                             : static_cast<const WebGLRectangleObject*>(this);
+}
+
 /**
  ** Template implementations
  **/
 
 /* Helper function taking a BaseInterfaceType pointer, casting it to
  * ConcreteObjectType and performing some checks along the way.
  *
  * By default, null (respectively: deleted) aInterface pointers are
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -797,19 +797,19 @@ WebGLContext::CopyTexSubImage2D_base(Web
                                      WebGLint xoffset,
                                      WebGLint yoffset,
                                      WebGLint x,
                                      WebGLint y,
                                      WebGLsizei width,
                                      WebGLsizei height,
                                      bool sub)
 {
-
-    WebGLsizei framebufferWidth =  mBoundFramebuffer ? mBoundFramebuffer->width() : mWidth;
-    WebGLsizei framebufferHeight = mBoundFramebuffer ? mBoundFramebuffer->height() : mHeight;
+    const WebGLRectangleObject *framebufferRect = FramebufferRectangleObject();
+    WebGLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
+    WebGLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
 
     const char *info = sub ? "copyTexSubImage2D" : "copyTexImage2D";
 
     MakeContextCurrent();
 
     if (CanvasUtils::CheckSaneSubrectSize(x, y, width, height, framebufferWidth, framebufferHeight)) {
         if (sub)
             gl->fCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
@@ -957,20 +957,20 @@ WebGLContext::CopyTexImage2D(WebGLenum t
     GLenum type = LOCAL_GL_UNSIGNED_BYTE;
 
     // check if the memory size of this texture may change with this call
     bool sizeMayChange = true;
     size_t face = WebGLTexture::FaceForTarget(target);
     if (tex->HasImageInfoAt(level, face)) {
         const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(level, face);
 
-        sizeMayChange = width != imageInfo.mWidth ||
-                        height != imageInfo.mHeight ||
-                        internalformat != imageInfo.mFormat ||
-                        type != imageInfo.mType;
+        sizeMayChange = width != imageInfo.Width() ||
+                        height != imageInfo.Height() ||
+                        internalformat != imageInfo.Format() ||
+                        type != imageInfo.Type();
     }
 
     if (sizeMayChange) {
         UpdateWebGLErrorAndClearGLError();
         CopyTexSubImage2D_base(target, level, internalformat, 0, 0, x, y, width, height, false);
         GLenum error = LOCAL_GL_NO_ERROR;
         UpdateWebGLErrorAndClearGLError(&error);
         if (error) {
@@ -1027,29 +1027,30 @@ WebGLContext::CopyTexSubImage2D(WebGLenu
     WebGLTexture *tex = activeBoundTextureForTarget(target);
     if (!tex)
         return ErrorInvalidOperation("copyTexSubImage2D: no texture bound to this target");
 
     WebGLint face = WebGLTexture::FaceForTarget(target);
     if (!tex->HasImageInfoAt(level, face))
         return ErrorInvalidOperation("copyTexSubImage2D: no texture image previously defined for this level and face");
 
-    WebGLsizei texWidth = tex->ImageInfoAt(level, face).mWidth;
-    WebGLsizei texHeight = tex->ImageInfoAt(level, face).mHeight;
+    const WebGLTexture::ImageInfo &imageInfo = tex->ImageInfoAt(level, face);
+    WebGLsizei texWidth = imageInfo.Width();
+    WebGLsizei texHeight = imageInfo.Height();
 
     if (xoffset + width > texWidth || xoffset + width < 0)
       return ErrorInvalidValue("copyTexSubImage2D: xoffset+width is too large");
 
     if (yoffset + height > texHeight || yoffset + height < 0)
       return ErrorInvalidValue("copyTexSubImage2D: yoffset+height is too large");
 
-    WebGLenum format = tex->ImageInfoAt(level, face).mFormat;
+    WebGLenum format = imageInfo.Format();
     bool texFormatRequiresAlpha = format == LOCAL_GL_RGBA ||
-                                    format == LOCAL_GL_ALPHA ||
-                                    format == LOCAL_GL_LUMINANCE_ALPHA;
+                                  format == LOCAL_GL_ALPHA ||
+                                  format == LOCAL_GL_LUMINANCE_ALPHA;
     bool fboFormatHasAlpha = mBoundFramebuffer ? mBoundFramebuffer->ColorAttachment().HasAlpha()
                                                  : bool(gl->ActualFormat().alpha > 0);
 
     if (texFormatRequiresAlpha && !fboFormatHasAlpha)
         return ErrorInvalidOperation("copyTexSubImage2D: texture format requires an alpha channel "
                                      "but the framebuffer doesn't have one");
 
     if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers())
@@ -2401,30 +2402,30 @@ WebGLContext::GetFramebufferAttachmentPa
 
     if (fba.Renderbuffer()) {
         switch (pname) {
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
                 wrval->SetAsInt32(LOCAL_GL_RENDERBUFFER);
                 break;
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
-                wrval->SetAsISupports(fba.Renderbuffer());
+                wrval->SetAsISupports(const_cast<WebGLRenderbuffer*>(fba.Renderbuffer()));
                 break;
 
             default:
                 return ErrorInvalidEnumInfo("GetFramebufferAttachmentParameter: pname", pname);
         }
     } else if (fba.Texture()) {
         switch (pname) {
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
                 wrval->SetAsInt32(LOCAL_GL_TEXTURE);
                 break;
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
-                wrval->SetAsISupports(fba.Texture());
+                wrval->SetAsISupports(const_cast<WebGLTexture*>(fba.Texture()));
                 break;
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
                 wrval->SetAsInt32(fba.TextureLevel());
                 break;
 
             case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
                 wrval->SetAsInt32(fba.TextureCubeMapFace());
@@ -3283,18 +3284,19 @@ WebGLContext::ReadPixels_base(WebGLint x
     }
 
     if (width < 0 || height < 0)
         return ErrorInvalidValue("ReadPixels: negative size passed");
 
     if (!pixels)
         return ErrorInvalidValue("ReadPixels: null array passed");
 
-    WebGLsizei boundWidth = mBoundFramebuffer ? mBoundFramebuffer->width() : mWidth;
-    WebGLsizei boundHeight = mBoundFramebuffer ? mBoundFramebuffer->height() : mHeight;
+    const WebGLRectangleObject *framebufferRect = FramebufferRectangleObject();
+    WebGLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
+    WebGLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
 
     void* data = JS_GetTypedArrayData(pixels);
     PRUint32 dataByteLen = JS_GetTypedArrayByteLength(pixels);
     int dataType = JS_GetTypedArrayType(pixels);
 
     PRUint32 channels = 0;
 
     // Check the format param
@@ -3375,47 +3377,47 @@ WebGLContext::ReadPixels_base(WebGLint x
         EnsureBackbufferClearedAsNeeded();
     }
     // Now that the errors are out of the way, on to actually reading
 
     // If we won't be reading any pixels anyways, just skip the actual reading
     if (width == 0 || height == 0)
         return NS_OK;
 
-    if (CanvasUtils::CheckSaneSubrectSize(x, y, width, height, boundWidth, boundHeight)) {
+    if (CanvasUtils::CheckSaneSubrectSize(x, y, width, height, framebufferWidth, framebufferHeight)) {
         // the easy case: we're not reading out-of-range pixels
         gl->fReadPixels(x, y, width, height, format, type, data);
     } else {
         // the rectangle doesn't fit entirely in the bound buffer. We then have to set to zero the part
         // of the buffer that correspond to out-of-range pixels. We don't want to rely on system OpenGL
         // to do that for us, because passing out of range parameters to a buggy OpenGL implementation
         // could conceivably allow to read memory we shouldn't be allowed to read. So we manually initialize
         // the buffer to zero and compute the parameters to pass to OpenGL. We have to use an intermediate buffer
         // to accomodate the potentially different strides (widths).
 
         // zero the whole destination buffer. Too bad for the part that's going to be overwritten, we're not
         // 100% efficient here, but in practice this is a quite rare case anyway.
         memset(data, 0, dataByteLen);
 
-        if (   x >= boundWidth
+        if (   x >= framebufferWidth
             || x+width <= 0
-            || y >= boundHeight
+            || y >= framebufferHeight
             || y+height <= 0)
         {
             // we are completely outside of range, can exit now with buffer filled with zeros
             return NS_OK;
         }
 
         // compute the parameters of the subrect we're actually going to call glReadPixels on
         GLint   subrect_x      = NS_MAX(x, 0);
-        GLint   subrect_end_x  = NS_MIN(x+width, boundWidth);
+        GLint   subrect_end_x  = NS_MIN(x+width, framebufferWidth);
         GLsizei subrect_width  = subrect_end_x - subrect_x;
 
         GLint   subrect_y      = NS_MAX(y, 0);
-        GLint   subrect_end_y  = NS_MIN(y+height, boundHeight);
+        GLint   subrect_end_y  = NS_MIN(y+height, framebufferHeight);
         GLsizei subrect_height = subrect_end_y - subrect_y;
 
         if (subrect_width < 0 || subrect_height < 0 ||
             subrect_width > width || subrect_height > height)
             return ErrorInvalidOperation("ReadPixels: integer overflow computing clipped rect size");
 
         // now we know that subrect_width is in the [0..width] interval, and same for heights.
 
@@ -3552,18 +3554,18 @@ WebGLContext::RenderbufferStorage(WebGLe
         internalformatForGL = LOCAL_GL_DEPTH24_STENCIL8;
         break;
     default:
         return ErrorInvalidEnumInfo("renderbufferStorage: internalformat", internalformat);
     }
 
     MakeContextCurrent();
 
-    bool sizeChanges = width != mBoundRenderbuffer->width() ||
-                       height != mBoundRenderbuffer->height() ||
+    bool sizeChanges = width != mBoundRenderbuffer->Width() ||
+                       height != mBoundRenderbuffer->Height() ||
                        internalformat != mBoundRenderbuffer->InternalFormat();
     if (sizeChanges) {
         UpdateWebGLErrorAndClearGLError();
         gl->fRenderbufferStorage(target, internalformatForGL, width, height);
         GLenum error = LOCAL_GL_NO_ERROR;
         UpdateWebGLErrorAndClearGLError(&error);
         if (error) {
             LogMessageIfVerbose("bufferData generated error %s", ErrorName(error));
@@ -4727,20 +4729,20 @@ GLenum WebGLContext::CheckedTexImage2D(G
     WebGLTexture *tex = activeBoundTextureForTarget(target);
     NS_ABORT_IF_FALSE(tex != nsnull, "no texture bound");
 
     bool sizeMayChange = true;
     size_t face = WebGLTexture::FaceForTarget(target);
     
     if (tex->HasImageInfoAt(level, face)) {
         const WebGLTexture::ImageInfo& imageInfo = tex->ImageInfoAt(level, face);
-        sizeMayChange = width != imageInfo.mWidth ||
-                        height != imageInfo.mHeight ||
-                        format != imageInfo.mFormat ||
-                        type != imageInfo.mType;
+        sizeMayChange = width != imageInfo.Width() ||
+                        height != imageInfo.Height() ||
+                        format != imageInfo.Format() ||
+                        type != imageInfo.Type();
     }
     
     if (sizeMayChange) {
         UpdateWebGLErrorAndClearGLError();
         gl->fTexImage2D(target, level, internalFormat, width, height, border, format, type, data);
         GLenum error = LOCAL_GL_NO_ERROR;
         UpdateWebGLErrorAndClearGLError(&error);
         return error;
@@ -5034,21 +5036,21 @@ WebGLContext::TexSubImage2D_base(WebGLen
         return ErrorInvalidOperation("texSubImage2D: no texture is bound to this target");
 
     size_t face = WebGLTexture::FaceForTarget(target);
     
     if (!tex->HasImageInfoAt(level, face))
         return ErrorInvalidOperation("texSubImage2D: no texture image previously defined for this level and face");
     
     const WebGLTexture::ImageInfo &imageInfo = tex->ImageInfoAt(level, face);
-    if (!CanvasUtils::CheckSaneSubrectSize(xoffset, yoffset, width, height, imageInfo.mWidth, imageInfo.mHeight))
+    if (!CanvasUtils::CheckSaneSubrectSize(xoffset, yoffset, width, height, imageInfo.Width(), imageInfo.Height()))
         return ErrorInvalidValue("texSubImage2D: subtexture rectangle out of bounds");
     
     // Require the format and type in texSubImage2D to match that of the existing texture as created by texImage2D
-    if (imageInfo.mFormat != format || imageInfo.mType != type)
+    if (imageInfo.Format() != format || imageInfo.Type() != type)
         return ErrorInvalidOperation("texSubImage2D: format or type doesn't match the existing texture");
 
     MakeContextCurrent();
 
     int dstFormat = GetWebGLTexelFormat(format, type);
     int actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat;
     size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
 
--- a/content/canvas/test/webgl/failing_tests_linux.txt
+++ b/content/canvas/test/webgl/failing_tests_linux.txt
@@ -6,9 +6,8 @@ conformance/misc/uninitialized-test.html
 conformance/programs/gl-get-active-attribute.html
 conformance/textures/texture-mips.html
 conformance/uniforms/gl-uniform-bool.html
 conformance/more/conformance/quickCheckAPI-S_V.html
 conformance/more/functions/uniformfArrayLen1.html
 conformance/glsl/misc/attrib-location-length-limits.html
 conformance/glsl/misc/uniform-location-length-limits.html
 conformance/renderbuffers/framebuffer-object-attachment.html
-conformance/misc/object-deletion-behaviour.html
--- a/content/canvas/test/webgl/failing_tests_mac.txt
+++ b/content/canvas/test/webgl/failing_tests_mac.txt
@@ -2,11 +2,9 @@ conformance/context/premultiplyalpha-tes
 conformance/glsl/misc/glsl-function-nodes.html
 conformance/glsl/misc/glsl-long-variable-names.html
 conformance/glsl/misc/shader-with-256-character-identifier.frag.html
 conformance/glsl/misc/shader-with-long-line.html
 conformance/more/conformance/quickCheckAPI-S_V.html
 conformance/more/functions/uniformfBadArgs.html
 conformance/more/functions/uniformiBadArgs.html
 conformance/glsl/misc/attrib-location-length-limits.html
-conformance/glsl/misc/uniform-location-length-limits.html
-conformance/renderbuffers/framebuffer-object-attachment.html
-conformance/misc/object-deletion-behaviour.html
+conformance/glsl/misc/uniform-location-length-limits.html
\ No newline at end of file
--- a/content/canvas/test/webgl/failing_tests_windows.txt
+++ b/content/canvas/test/webgl/failing_tests_windows.txt
@@ -3,11 +3,9 @@ conformance/glsl/functions/glsl-function
 conformance/glsl/functions/glsl-function-atan-xy.html
 conformance/glsl/misc/glsl-long-variable-names.html
 conformance/glsl/misc/shader-with-256-character-identifier.frag.html
 conformance/glsl/misc/shader-with-long-line.html
 conformance/more/conformance/quickCheckAPI-S_V.html
 conformance/more/functions/uniformfArrayLen1.html
 conformance/glsl/misc/attrib-location-length-limits.html
 conformance/glsl/misc/struct-nesting-under-maximum.html
-conformance/glsl/misc/uniform-location-length-limits.html
-conformance/renderbuffers/framebuffer-object-attachment.html
-conformance/misc/object-deletion-behaviour.html
+conformance/glsl/misc/uniform-location-length-limits.html
\ No newline at end of file