From 664751db152dfee22e8698c56a60bfbd80704fbc Mon Sep 17 00:00:00 2001 From: Jeff Gilbert Date: Tue, 1 Oct 2013 17:30:05 -0700 Subject: [PATCH] Bug 685184 - Delay attachment of RBs to FBs. - r=bjacob --- content/canvas/src/WebGLContextGL.cpp | 6 +- content/canvas/src/WebGLFramebuffer.cpp | 94 +++++++++++++------------ content/canvas/src/WebGLFramebuffer.h | 16 ++++- content/canvas/src/WebGLTexture.h | 4 +- 4 files changed, 71 insertions(+), 49 deletions(-) diff --git a/content/canvas/src/WebGLContextGL.cpp b/content/canvas/src/WebGLContextGL.cpp index 8cef67c2120c..5006cc550019 100644 --- a/content/canvas/src/WebGLContextGL.cpp +++ b/content/canvas/src/WebGLContextGL.cpp @@ -325,6 +325,10 @@ WebGLContext::CheckFramebufferStatus(GLenum target) return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; if(mBoundFramebuffer->HasAttachmentsOfMismatchedDimensions()) return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; + + // Ok, attach our chosen flavor of {DEPTH, STENCIL, DEPTH_STENCIL}. + mBoundFramebuffer->FinalizeAttachments(); + return gl->fCheckFramebufferStatus(target); } @@ -2288,7 +2292,7 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width, // now, same computation as above to find the size of the intermediate buffer to allocate for the subrect // no need to check again for integer overflow here, since we already know the sizes aren't greater than before uint32_t subrect_plainRowSize = subrect_width * bytesPerPixel; - // There are checks above to ensure that this doesn't overflow. + // There are checks above to ensure that this doesn't overflow. uint32_t subrect_alignedRowSize = RoundedToNextMultipleOf(subrect_plainRowSize, mPixelStorePackAlignment).value(); uint32_t subrect_byteLength = (subrect_height-1)*subrect_alignedRowSize + subrect_plainRowSize; diff --git a/content/canvas/src/WebGLFramebuffer.cpp b/content/canvas/src/WebGLFramebuffer.cpp index 8d65e47c942f..8f51dfa1b25f 100644 --- a/content/canvas/src/WebGLFramebuffer.cpp +++ b/content/canvas/src/WebGLFramebuffer.cpp @@ -14,6 +14,7 @@ #include "GLContext.h" using namespace mozilla; +using namespace mozilla::gl; JSObject* WebGLFramebuffer::WrapObject(JSContext *cx, JS::Handle scope) { @@ -58,9 +59,10 @@ WebGLFramebuffer::Attachment::HasAlpha() const { } void -WebGLFramebuffer::Attachment::SetTexture(WebGLTexture *tex, GLint level, GLenum face) { +WebGLFramebuffer::Attachment::SetTexture(WebGLTexture *tex, GLenum target, GLint level, GLenum face) { mTexturePtr = tex; mRenderbufferPtr = nullptr; + mTextureTarget = target; mTextureLevel = level; mTextureCubeMapFace = face; } @@ -146,6 +148,26 @@ WebGLFramebuffer::Attachment::IsComplete() const { return false; } +void +WebGLFramebuffer::Attachment::FinalizeAttachment(GLenum attachmentLoc) const { + if (Texture()) { + GLContext* gl = Texture()->Context()->gl; + gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachmentLoc, + TextureTarget(), Texture()->GLName(), TextureLevel()); + return; + } + + if (Renderbuffer()) { + GLContext* gl = Renderbuffer()->Context()->gl; + gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachmentLoc, + LOCAL_GL_RENDERBUFFER, Renderbuffer()->GLName()); + return; + } + + // Neither? + MOZ_ASSERT(false, "FB attachment without a tex or RB."); +} + void WebGLFramebuffer::Delete() { mColorAttachments.Clear(); @@ -196,25 +218,6 @@ WebGLFramebuffer::FramebufferRenderbuffer(GLenum target, mColorAttachments[colorAttachmentId].SetRenderbuffer(wrb); break; } - - mContext->MakeContextCurrent(); - GLuint parambuffername = wrb ? wrb->GLName() : 0; - if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) { - GLuint depthbuffername = parambuffername; - GLuint stencilbuffername = parambuffername; - if (!parambuffername){ - depthbuffername = mDepthAttachment.Renderbuffer() ? mDepthAttachment.Renderbuffer()->GLName() : 0; - stencilbuffername = mStencilAttachment.Renderbuffer() ? mStencilAttachment.Renderbuffer()->GLName() : 0; - } - mContext->gl->fFramebufferRenderbuffer(target, LOCAL_GL_DEPTH_ATTACHMENT, rbtarget, depthbuffername); - mContext->gl->fFramebufferRenderbuffer(target, LOCAL_GL_STENCIL_ATTACHMENT, rbtarget, stencilbuffername); - } else { - GLuint renderbuffername = parambuffername; - if(!parambuffername && (attachment == LOCAL_GL_DEPTH_ATTACHMENT || attachment == LOCAL_GL_STENCIL_ATTACHMENT)){ - renderbuffername = mDepthStencilAttachment.Renderbuffer() ? mDepthStencilAttachment.Renderbuffer()->GLName() : 0; - } - mContext->gl->fFramebufferRenderbuffer(target, attachment, rbtarget, renderbuffername); - } } void @@ -245,13 +248,13 @@ WebGLFramebuffer::FramebufferTexture2D(GLenum target, size_t face = WebGLTexture::FaceForTarget(textarget); switch (attachment) { case LOCAL_GL_DEPTH_ATTACHMENT: - mDepthAttachment.SetTexture(wtex, level, face); + mDepthAttachment.SetTexture(wtex, textarget, level, face); break; case LOCAL_GL_STENCIL_ATTACHMENT: - mStencilAttachment.SetTexture(wtex, level, face); + mStencilAttachment.SetTexture(wtex, textarget, level, face); break; case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT: - mDepthStencilAttachment.SetTexture(wtex, level, face); + mDepthStencilAttachment.SetTexture(wtex, textarget, level, face); break; default: if (!CheckColorAttachementNumber(attachment, "framebufferTexture2D")){ @@ -260,30 +263,9 @@ WebGLFramebuffer::FramebufferTexture2D(GLenum target, size_t colorAttachmentId = size_t(attachment - LOCAL_GL_COLOR_ATTACHMENT0); EnsureColorAttachments(colorAttachmentId); - mColorAttachments[colorAttachmentId].SetTexture(wtex, level, face); + mColorAttachments[colorAttachmentId].SetTexture(wtex, textarget, level, face); break; } - - mContext->MakeContextCurrent(); - GLuint paramtexturename = wtex ? wtex->GLName() : 0; - if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) { - GLuint depthtexturename = paramtexturename; - GLuint stenciltexturename = paramtexturename; - if(!paramtexturename){ - depthtexturename = mDepthAttachment.Texture() ? mDepthAttachment.Texture()->GLName() : 0; - stenciltexturename = mStencilAttachment.Texture() ? mStencilAttachment.Texture()->GLName() : 0; - } - mContext->gl->fFramebufferTexture2D(target, LOCAL_GL_DEPTH_ATTACHMENT, textarget, depthtexturename, level); - mContext->gl->fFramebufferTexture2D(target, LOCAL_GL_STENCIL_ATTACHMENT, textarget, stenciltexturename, level); - } else { - GLuint texturename = paramtexturename; - if(!paramtexturename && (attachment == LOCAL_GL_DEPTH_ATTACHMENT || attachment == LOCAL_GL_STENCIL_ATTACHMENT)){ - texturename = mDepthStencilAttachment.Texture() ? mDepthStencilAttachment.Texture()->GLName() : 0; - } - mContext->gl->fFramebufferTexture2D(target, attachment, textarget, texturename, level); - } - - return; } bool @@ -421,6 +403,9 @@ WebGLFramebuffer::CheckAndInitializeRenderbuffers() mContext->MakeContextCurrent(); + // Ok, attach our chosen flavor of {DEPTH, STENCIL, DEPTH_STENCIL}. + FinalizeAttachments(); + GLenum status = mContext->CheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER); if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE) return false; @@ -520,6 +505,25 @@ void WebGLFramebuffer::EnsureColorAttachments(size_t colorAttachmentId) { } } +void +WebGLFramebuffer::FinalizeAttachments() const { + for (size_t i = 0; i < ColorAttachmentCount(); i++) { + if (ColorAttachment(i).IsDefined()) + ColorAttachment(i).FinalizeAttachment(LOCAL_GL_COLOR_ATTACHMENT0 + i); + } + + if (DepthAttachment().IsDefined()) + DepthAttachment().FinalizeAttachment(LOCAL_GL_DEPTH_ATTACHMENT); + + if (StencilAttachment().IsDefined()) + StencilAttachment().FinalizeAttachment(LOCAL_GL_STENCIL_ATTACHMENT); + + if (DepthStencilAttachment().IsDefined()) { + DepthStencilAttachment().FinalizeAttachment(LOCAL_GL_DEPTH_ATTACHMENT); + DepthStencilAttachment().FinalizeAttachment(LOCAL_GL_STENCIL_ATTACHMENT); + } +} + inline void ImplCycleCollectionUnlink(mozilla::WebGLFramebuffer::Attachment& aField) { diff --git a/content/canvas/src/WebGLFramebuffer.h b/content/canvas/src/WebGLFramebuffer.h index 86a9a2770b1c..fdc25e646677 100644 --- a/content/canvas/src/WebGLFramebuffer.h +++ b/content/canvas/src/WebGLFramebuffer.h @@ -16,6 +16,9 @@ namespace mozilla { class WebGLTexture; class WebGLRenderbuffer; +namespace gl { + class GLContext; +} class WebGLFramebuffer MOZ_FINAL : public nsWrapperCache @@ -37,6 +40,7 @@ public: WebGLRefPtr mRenderbufferPtr; GLenum mAttachmentPoint; GLint mTextureLevel; + GLenum mTextureTarget; GLenum mTextureCubeMapFace; Attachment(GLenum aAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0) @@ -51,7 +55,7 @@ public: bool HasAlpha() const; - void SetTexture(WebGLTexture *tex, GLint level, GLenum face); + void SetTexture(WebGLTexture *tex, GLenum target, GLint level, GLenum face); void SetRenderbuffer(WebGLRenderbuffer *rb) { mTexturePtr = nullptr; mRenderbufferPtr = rb; @@ -68,6 +72,9 @@ public: WebGLRenderbuffer *Renderbuffer() { return mRenderbufferPtr; } + GLenum TextureTarget() const { + return mTextureTarget; + } GLint TextureLevel() const { return mTextureLevel; } @@ -86,6 +93,8 @@ public: bool HasSameDimensionsAs(const Attachment& other) const; bool IsComplete() const; + + void FinalizeAttachment(GLenum attachmentLoc) const; }; void Delete(); @@ -115,6 +124,9 @@ public: bool HasAttachmentsOfMismatchedDimensions() const; + const size_t ColorAttachmentCount() const { + return mColorAttachments.Length(); + } const Attachment& ColorAttachment(uint32_t colorAttachmentId) const { return mColorAttachments[colorAttachmentId]; } @@ -145,6 +157,8 @@ public: return Context(); } + void FinalizeAttachments() const; + virtual JSObject* WrapObject(JSContext *cx, JS::Handle scope) MOZ_OVERRIDE; diff --git a/content/canvas/src/WebGLTexture.h b/content/canvas/src/WebGLTexture.h index 613a873ad0da..335c25805615 100644 --- a/content/canvas/src/WebGLTexture.h +++ b/content/canvas/src/WebGLTexture.h @@ -38,9 +38,9 @@ public: void Delete(); - bool HasEverBeenBound() { return mHasEverBeenBound; } + bool HasEverBeenBound() const { return mHasEverBeenBound; } void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; } - GLuint GLName() { return mGLName; } + GLuint GLName() const { return mGLName; } GLenum Target() const { return mTarget; } WebGLContext *GetParentObject() const {