Bug 1017865 - Refactor attach/detach for FB attachments. - r=kamidphish

This commit is contained in:
Jeff Gilbert 2015-03-16 18:22:17 -07:00
parent 7ab85a504c
commit d0ee5cfaea
8 changed files with 339 additions and 418 deletions

View File

@ -714,12 +714,10 @@ WebGLContext::DeleteRenderbuffer(WebGLRenderbuffer* rbuf)
if (mBoundReadFramebuffer)
mBoundReadFramebuffer->DetachRenderbuffer(rbuf);
// Invalidate framebuffer status cache
rbuf->NotifyFBsStatusChanged();
rbuf->InvalidateStatusOfAttachedFBs();
if (mBoundRenderbuffer == rbuf)
BindRenderbuffer(LOCAL_GL_RENDERBUFFER,
static_cast<WebGLRenderbuffer*>(nullptr));
BindRenderbuffer(LOCAL_GL_RENDERBUFFER, nullptr);
rbuf->RequestDelete();
}
@ -742,8 +740,7 @@ WebGLContext::DeleteTexture(WebGLTexture* tex)
if (mBoundReadFramebuffer)
mBoundReadFramebuffer->DetachTexture(tex);
// Invalidate framebuffer status cache
tex->NotifyFBsStatusChanged();
tex->InvalidateStatusOfAttachedFBs();
GLuint activeTexture = mActiveTexture;
for (int32_t i = 0; i < mGLMaxTextureUnits; i++) {
@ -752,7 +749,7 @@ WebGLContext::DeleteTexture(WebGLTexture* tex)
(mBound3DTextures[i] == tex && tex->Target() == LOCAL_GL_TEXTURE_3D))
{
ActiveTexture(LOCAL_GL_TEXTURE0 + i);
BindTexture(tex->Target().get(), static_cast<WebGLTexture*>(nullptr));
BindTexture(tex->Target().get(), nullptr);
}
}
ActiveTexture(LOCAL_GL_TEXTURE0 + activeTexture);
@ -868,11 +865,8 @@ WebGLContext::FramebufferRenderbuffer(GLenum target, GLenum attachment,
rbtarget);
}
if (!ValidateFramebufferAttachment(fb, attachment,
"framebufferRenderbuffer"))
{
if (!ValidateFramebufferAttachment(fb, attachment, "framebufferRenderbuffer"))
return;
}
fb->FramebufferRenderbuffer(attachment, rbtarget, wrb);
}
@ -1141,11 +1135,11 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
}
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
fb->EnsureColorAttachments(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
fb->EnsureColorAttachPoints(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
MakeContextCurrent();
const WebGLFramebuffer::Attachment& fba = fb->GetAttachment(attachment);
const WebGLFramebuffer::AttachPoint& fba = fb->GetAttachPoint(attachment);
if (fba.Renderbuffer()) {
switch (pname) {
@ -2324,8 +2318,6 @@ WebGLContext::RenderbufferStorage_base(const char* funcName, GLenum target,
height != mBoundRenderbuffer->Height();
if (willRealloc) {
// Invalidate framebuffer status cache
mBoundRenderbuffer->NotifyFBsStatusChanged();
GetAndFlushUnderlyingGLErrors();
mBoundRenderbuffer->RenderbufferStorage(samples, internalFormatForGL,
width, height);

View File

@ -604,6 +604,7 @@ WebGLContext::EnumName(GLenum glenum)
XX(COMPRESSED_RGB_PVRTC_2BPPV1);
XX(COMPRESSED_RGB_PVRTC_4BPPV1);
XX(COMPRESSED_RGB_S3TC_DXT1_EXT);
XX(DEPTH_ATTACHMENT);
XX(DEPTH_COMPONENT);
XX(DEPTH_COMPONENT16);
XX(DEPTH_COMPONENT32);
@ -789,6 +790,7 @@ WebGLContext::EnumName(GLenum glenum)
XX(RENDERBUFFER_SAMPLES);
XX(FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER);
XX(MAX_COLOR_ATTACHMENTS);
XX(COLOR_ATTACHMENT0);
XX(COLOR_ATTACHMENT1);
XX(COLOR_ATTACHMENT2);
XX(COLOR_ATTACHMENT3);

View File

@ -15,45 +15,21 @@
namespace mozilla {
JSObject*
WebGLFramebuffer::WrapObject(JSContext* cx)
{
return dom::WebGLFramebufferBinding::Wrap(cx, this);
}
WebGLFramebuffer::WebGLFramebuffer(WebGLContext* webgl, GLuint fbo)
: WebGLBindableName<FBTarget>(fbo)
, WebGLContextBoundObject(webgl)
, mStatus(0)
, mDepthAttachment(LOCAL_GL_DEPTH_ATTACHMENT)
, mStencilAttachment(LOCAL_GL_STENCIL_ATTACHMENT)
, mDepthStencilAttachment(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
, mReadBufferMode(LOCAL_GL_COLOR_ATTACHMENT0)
{
mContext->mFramebuffers.insertBack(this);
mColorAttachments.SetLength(1);
mColorAttachments[0].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0;
}
WebGLFramebuffer::Attachment::Attachment(FBAttachment attachmentPoint)
: mAttachmentPoint(attachmentPoint)
WebGLFramebuffer::AttachPoint::AttachPoint(WebGLFramebuffer* fb,
FBAttachment attachmentPoint)
: mFB(fb)
, mAttachmentPoint(attachmentPoint)
, mTexImageTarget(LOCAL_GL_NONE)
, mNeedsFinalize(false)
{}
WebGLFramebuffer::Attachment::~Attachment()
{}
void
WebGLFramebuffer::Attachment::Reset()
WebGLFramebuffer::AttachPoint::~AttachPoint()
{
mTexturePtr = nullptr;
mRenderbufferPtr = nullptr;
MOZ_ASSERT(!mRenderbufferPtr);
MOZ_ASSERT(!mTexturePtr);
}
bool
WebGLFramebuffer::Attachment::IsDeleteRequested() const
WebGLFramebuffer::AttachPoint::IsDeleteRequested() const
{
return Texture() ? Texture()->IsDeleteRequested()
: Renderbuffer() ? Renderbuffer()->IsDeleteRequested()
@ -61,14 +37,14 @@ WebGLFramebuffer::Attachment::IsDeleteRequested() const
}
bool
WebGLFramebuffer::Attachment::IsDefined() const
WebGLFramebuffer::AttachPoint::IsDefined() const
{
return Renderbuffer() ||
(Texture() && Texture()->HasImageInfoAt(ImageTarget(), 0));
}
bool
WebGLFramebuffer::Attachment::HasAlpha() const
WebGLFramebuffer::AttachPoint::HasAlpha() const
{
MOZ_ASSERT(HasImage());
@ -86,7 +62,7 @@ WebGLFramebuffer::Attachment::HasAlpha() const
}
GLenum
WebGLFramebuffer::GetFormatForAttachment(const WebGLFramebuffer::Attachment& attachment) const
WebGLFramebuffer::GetFormatForAttachment(const WebGLFramebuffer::AttachPoint& attachment) const
{
MOZ_ASSERT(attachment.IsDefined());
MOZ_ASSERT(attachment.Texture() || attachment.Renderbuffer());
@ -107,7 +83,7 @@ WebGLFramebuffer::GetFormatForAttachment(const WebGLFramebuffer::Attachment& att
}
TexInternalFormat
WebGLFramebuffer::Attachment::EffectiveInternalFormat() const
WebGLFramebuffer::AttachPoint::EffectiveInternalFormat() const
{
const WebGLTexture* tex = Texture();
if (tex && tex->HasImageInfoAt(mTexImageTarget, mTexImageLevel)) {
@ -123,7 +99,7 @@ WebGLFramebuffer::Attachment::EffectiveInternalFormat() const
}
bool
WebGLFramebuffer::Attachment::IsReadableFloat() const
WebGLFramebuffer::AttachPoint::IsReadableFloat() const
{
TexInternalFormat internalformat = EffectiveInternalFormat();
MOZ_ASSERT(internalformat != LOCAL_GL_NONE);
@ -133,29 +109,50 @@ WebGLFramebuffer::Attachment::IsReadableFloat() const
type == LOCAL_GL_HALF_FLOAT;
}
void
WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture* tex,
TexImageTarget target, GLint level)
static void
UnmarkAttachment(WebGLFramebuffer::AttachPoint& attachment)
{
WebGLFramebufferAttachable* maybe = attachment.Texture();
if (!maybe)
maybe = attachment.Renderbuffer();
if (maybe)
maybe->UnmarkAttachment(attachment);
}
void
WebGLFramebuffer::AttachPoint::SetTexImage(WebGLTexture* tex, TexImageTarget target,
GLint level)
{
mFB->InvalidateFramebufferStatus();
UnmarkAttachment(*this);
mTexturePtr = tex;
mRenderbufferPtr = nullptr;
mTexImageTarget = target;
mTexImageLevel = level;
mNeedsFinalize = true;
if (tex)
tex->MarkAttachment(*this);
}
void
WebGLFramebuffer::Attachment::SetRenderbuffer(WebGLRenderbuffer* rb)
WebGLFramebuffer::AttachPoint::SetRenderbuffer(WebGLRenderbuffer* rb)
{
mFB->InvalidateFramebufferStatus();
UnmarkAttachment(*this);
mTexturePtr = nullptr;
mRenderbufferPtr = rb;
mNeedsFinalize = true;
if (rb)
rb->MarkAttachment(*this);
}
bool
WebGLFramebuffer::Attachment::HasUninitializedImageData() const
WebGLFramebuffer::AttachPoint::HasUninitializedImageData() const
{
if (!HasImage())
return false;
@ -174,7 +171,7 @@ WebGLFramebuffer::Attachment::HasUninitializedImageData() const
}
void
WebGLFramebuffer::Attachment::SetImageDataStatus(WebGLImageDataStatus newStatus)
WebGLFramebuffer::AttachPoint::SetImageDataStatus(WebGLImageDataStatus newStatus)
{
if (!HasImage())
return;
@ -194,7 +191,7 @@ WebGLFramebuffer::Attachment::SetImageDataStatus(WebGLImageDataStatus newStatus)
}
bool
WebGLFramebuffer::Attachment::HasImage() const
WebGLFramebuffer::AttachPoint::HasImage() const
{
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
return true;
@ -206,7 +203,7 @@ WebGLFramebuffer::Attachment::HasImage() const
}
const WebGLRectangleObject&
WebGLFramebuffer::Attachment::RectangleObject() const
WebGLFramebuffer::AttachPoint::RectangleObject() const
{
MOZ_ASSERT(HasImage(),
"Make sure it has an image before requesting the rectangle.");
@ -288,7 +285,7 @@ WebGLContext::IsFormatValidForFB(GLenum sizedFormat) const
}
bool
WebGLFramebuffer::Attachment::IsComplete() const
WebGLFramebuffer::AttachPoint::IsComplete() const
{
if (!HasImage())
return false;
@ -356,26 +353,20 @@ WebGLFramebuffer::Attachment::IsComplete() const
}
void
WebGLFramebuffer::Attachment::FinalizeAttachment(gl::GLContext* gl,
WebGLFramebuffer::AttachPoint::FinalizeAttachment(gl::GLContext* gl,
FBAttachment attachmentLoc) const
{
if (!mNeedsFinalize)
return;
mNeedsFinalize = false;
if (!HasImage()) {
if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_DEPTH_ATTACHMENT,
LOCAL_GL_RENDERBUFFER, 0);
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_STENCIL_ATTACHMENT,
LOCAL_GL_RENDERBUFFER, 0);
} else {
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER,
attachmentLoc.get(),
switch (attachmentLoc.get()) {
case LOCAL_GL_DEPTH_ATTACHMENT:
case LOCAL_GL_STENCIL_ATTACHMENT:
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
break;
default:
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, attachmentLoc.get(),
LOCAL_GL_RENDERBUFFER, 0);
break;
}
return;
@ -390,12 +381,10 @@ WebGLFramebuffer::Attachment::FinalizeAttachment(gl::GLContext* gl,
const GLuint glName = Texture()->GLName();
if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_DEPTH_ATTACHMENT, imageTarget,
glName, mipLevel);
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER,
LOCAL_GL_STENCIL_ATTACHMENT, imageTarget,
glName, mipLevel);
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
imageTarget, glName, mipLevel);
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
imageTarget, glName, mipLevel);
} else {
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachmentLoc.get(),
imageTarget, glName, mipLevel);
@ -408,17 +397,37 @@ WebGLFramebuffer::Attachment::FinalizeAttachment(gl::GLContext* gl,
return;
}
MOZ_ASSERT(false, "Should not get here.");
MOZ_CRASH();
}
////////////////////////////////////////////////////////////////////////////////
// WebGLFramebuffer
WebGLFramebuffer::WebGLFramebuffer(WebGLContext* webgl, GLuint fbo)
: WebGLBindableName<FBTarget>(fbo)
, WebGLContextBoundObject(webgl)
, mStatus(0)
, mReadBufferMode(LOCAL_GL_COLOR_ATTACHMENT0)
, mColorAttachment0(this, LOCAL_GL_COLOR_ATTACHMENT0)
, mDepthAttachment(this, LOCAL_GL_DEPTH_ATTACHMENT)
, mStencilAttachment(this, LOCAL_GL_STENCIL_ATTACHMENT)
, mDepthStencilAttachment(this, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
{
mContext->mFramebuffers.insertBack(this);
}
void
WebGLFramebuffer::Delete()
{
DetachAllAttachments();
mColorAttachments.Clear();
mDepthAttachment.Reset();
mStencilAttachment.Reset();
mDepthStencilAttachment.Reset();
mColorAttachment0.Clear();
mDepthAttachment.Clear();
mStencilAttachment.Clear();
mDepthStencilAttachment.Clear();
const size_t moreColorAttachmentCount = mMoreColorAttachments.Length();
for (size_t i = 0; i < moreColorAttachmentCount; i++) {
mMoreColorAttachments[i].Clear();
}
mContext->MakeContextCurrent();
mContext->gl->fDeleteFramebuffers(1, &mGLName);
@ -426,84 +435,33 @@ WebGLFramebuffer::Delete()
}
void
WebGLFramebuffer::DetachAttachment(WebGLFramebuffer::Attachment& attachment)
{
if (attachment.Texture())
attachment.Texture()->DetachFrom(this, attachment.mAttachmentPoint);
if (attachment.Renderbuffer()) {
attachment.Renderbuffer()->DetachFrom(this,
attachment.mAttachmentPoint);
}
}
void
WebGLFramebuffer::DetachAllAttachments()
{
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
DetachAttachment(mColorAttachments[i]);
}
DetachAttachment(mDepthAttachment);
DetachAttachment(mStencilAttachment);
DetachAttachment(mDepthStencilAttachment);
}
void
WebGLFramebuffer::FramebufferRenderbuffer(FBAttachment attachPoint,
WebGLFramebuffer::FramebufferRenderbuffer(FBAttachment attachPointEnum,
RBTarget rbtarget,
WebGLRenderbuffer* rb)
{
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
mContext->mBoundReadFramebuffer == this);
if (!mContext->ValidateObjectAllowNull("framebufferRenderbuffer: renderbuffer",
rb))
{
if (!mContext->ValidateObjectAllowNull("framebufferRenderbuffer: renderbuffer", rb))
return;
}
/* Get the requested attachment. If result is NULL, attachment is invalid
* and an error is generated.
*
* Don't use GetAttachment(...) here because it opt builds it returns
* mColorAttachment[0] for invalid attachment, which we really don't want to
* mess with.
*/
Attachment* attachment = GetAttachmentOrNull(attachPoint);
if (!attachment)
return; // Error generated internally to GetAttachmentOrNull.
// `attachPoint` is validated by ValidateFramebufferAttachment().
AttachPoint& attachPoint = GetAttachPoint(attachPointEnum);
attachPoint.SetRenderbuffer(rb);
// Invalidate cached framebuffer status and inform texture of its new
// attachment.
mStatus = 0;
// Detach current:
if (attachment->Texture())
attachment->Texture()->DetachFrom(this, attachPoint);
else if (attachment->Renderbuffer())
attachment->Renderbuffer()->DetachFrom(this, attachPoint);
// Attach new:
if (rb)
rb->AttachTo(this, attachPoint);
attachment->SetRenderbuffer(rb);
InvalidateFramebufferStatus();
}
void
WebGLFramebuffer::FramebufferTexture2D(FBAttachment attachPoint,
WebGLFramebuffer::FramebufferTexture2D(FBAttachment attachPointEnum,
TexImageTarget texImageTarget,
WebGLTexture* tex, GLint level)
{
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
mContext->mBoundReadFramebuffer == this);
if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture",
tex))
{
if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture", tex))
return;
}
if (tex) {
bool isTexture2D = tex->Target() == LOCAL_GL_TEXTURE_2D;
@ -520,67 +478,19 @@ WebGLFramebuffer::FramebufferTexture2D(FBAttachment attachPoint,
return;
}
/* Get the requested attachment. If result is NULL, attachment is invalid
* and an error is generated.
*
* Don't use GetAttachment(...) here because it opt builds it returns
* mColorAttachment[0] for invalid attachment, which we really don't want to
* mess with.
*/
Attachment* attachment = GetAttachmentOrNull(attachPoint);
if (!attachment)
return; // Error generated internally to GetAttachmentOrNull.
AttachPoint& attachPoint = GetAttachPoint(attachPointEnum);
attachPoint.SetTexImage(tex, texImageTarget, level);
// Invalidate cached framebuffer status and inform texture of its new
// attachment.
mStatus = 0;
// Detach current:
if (attachment->Texture())
attachment->Texture()->DetachFrom(this, attachPoint);
else if (attachment->Renderbuffer())
attachment->Renderbuffer()->DetachFrom(this, attachPoint);
// Attach new:
if (tex)
tex->AttachTo(this, attachPoint);
attachment->SetTexImage(tex, texImageTarget, level);
InvalidateFramebufferStatus();
}
WebGLFramebuffer::Attachment*
WebGLFramebuffer::GetAttachmentOrNull(FBAttachment attachPoint)
WebGLFramebuffer::AttachPoint&
WebGLFramebuffer::GetAttachPoint(FBAttachment attachPoint)
{
switch (attachPoint.get()) {
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
return &mDepthStencilAttachment;
case LOCAL_GL_COLOR_ATTACHMENT0:
return mColorAttachment0;
case LOCAL_GL_DEPTH_ATTACHMENT:
return &mDepthAttachment;
case LOCAL_GL_STENCIL_ATTACHMENT:
return &mStencilAttachment;
default:
break;
}
if (!mContext->ValidateFramebufferAttachment(this, attachPoint.get(),
"getAttachmentOrNull"))
{
return nullptr;
}
size_t colorAttachmentId = attachPoint.get() - LOCAL_GL_COLOR_ATTACHMENT0;
EnsureColorAttachments(colorAttachmentId);
return &mColorAttachments[colorAttachmentId];
}
const WebGLFramebuffer::Attachment&
WebGLFramebuffer::GetAttachment(FBAttachment attachPoint) const
{
switch (attachPoint.get()) {
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
return mDepthStencilAttachment;
@ -594,69 +504,58 @@ WebGLFramebuffer::GetAttachment(FBAttachment attachPoint) const
break;
}
if (!mContext->ValidateFramebufferAttachment(this, attachPoint.get(),
"getAttachment"))
{
MOZ_ASSERT(false);
return mColorAttachments[0];
if (attachPoint >= LOCAL_GL_COLOR_ATTACHMENT1) {
size_t moreColorAttachmentId = attachPoint.get() - LOCAL_GL_COLOR_ATTACHMENT1;
if (1 + moreColorAttachmentId < WebGLContext::kMaxColorAttachments) {
EnsureColorAttachPoints(1 + moreColorAttachmentId);
return mMoreColorAttachments[moreColorAttachmentId];
}
}
size_t colorAttachmentId = attachPoint.get() - LOCAL_GL_COLOR_ATTACHMENT0;
if (colorAttachmentId >= mColorAttachments.Length()) {
MOZ_ASSERT(false);
return mColorAttachments[0];
}
return mColorAttachments[colorAttachmentId];
MOZ_CRASH("bad `attachPoint` validation");
}
void
WebGLFramebuffer::DetachTexture(const WebGLTexture* tex)
{
for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
if (mColorAttachments[i].Texture() == tex) {
FramebufferTexture2D(LOCAL_GL_COLOR_ATTACHMENT0+i,
LOCAL_GL_TEXTURE_2D, nullptr, 0);
// It might be attached in multiple places, so don't break.
}
}
if (mColorAttachment0.Texture() == tex)
mColorAttachment0.Clear();
if (mDepthAttachment.Texture() == tex) {
FramebufferTexture2D(LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_TEXTURE_2D,
nullptr, 0);
}
if (mStencilAttachment.Texture() == tex) {
FramebufferTexture2D(LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D,
nullptr, 0);
}
if (mDepthStencilAttachment.Texture() == tex) {
FramebufferTexture2D(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT,
LOCAL_GL_TEXTURE_2D, nullptr, 0);
if (mDepthAttachment.Texture() == tex)
mDepthAttachment.Clear();
if (mStencilAttachment.Texture() == tex)
mStencilAttachment.Clear();
if (mDepthStencilAttachment.Texture() == tex)
mDepthStencilAttachment.Clear();
const size_t moreColorAttachmentCount = mMoreColorAttachments.Length();
for (size_t i = 0; i < moreColorAttachmentCount; i++) {
if (mMoreColorAttachments[i].Texture() == tex)
mMoreColorAttachments[i].Clear();
}
}
void
WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer* rb)
{
for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
if (mColorAttachments[i].Renderbuffer() == rb) {
FramebufferRenderbuffer(LOCAL_GL_COLOR_ATTACHMENT0+i,
LOCAL_GL_RENDERBUFFER, nullptr);
// It might be attached in multiple places, so don't break.
}
}
if (mColorAttachment0.Renderbuffer() == rb)
mColorAttachment0.Clear();
if (mDepthAttachment.Renderbuffer() == rb) {
FramebufferRenderbuffer(LOCAL_GL_DEPTH_ATTACHMENT,
LOCAL_GL_RENDERBUFFER, nullptr);
}
if (mStencilAttachment.Renderbuffer() == rb) {
FramebufferRenderbuffer(LOCAL_GL_STENCIL_ATTACHMENT,
LOCAL_GL_RENDERBUFFER, nullptr);
}
if (mDepthStencilAttachment.Renderbuffer() == rb) {
FramebufferRenderbuffer(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT,
LOCAL_GL_RENDERBUFFER, nullptr);
if (mDepthAttachment.Renderbuffer() == rb)
mDepthAttachment.Clear();
if (mStencilAttachment.Renderbuffer() == rb)
mStencilAttachment.Clear();
if (mDepthStencilAttachment.Renderbuffer() == rb)
mDepthStencilAttachment.Clear();
const size_t moreColorAttachmentCount = mMoreColorAttachments.Length();
for (size_t i = 0; i < moreColorAttachmentCount; i++) {
if (mMoreColorAttachments[i].Renderbuffer() == rb)
mMoreColorAttachments[i].Clear();
}
}
@ -665,19 +564,21 @@ WebGLFramebuffer::HasDefinedAttachments() const
{
bool hasAttachments = false;
for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
hasAttachments |= mColorAttachments[i].IsDefined();
}
hasAttachments |= mColorAttachment0.IsDefined();
hasAttachments |= mDepthAttachment.IsDefined();
hasAttachments |= mStencilAttachment.IsDefined();
hasAttachments |= mDepthStencilAttachment.IsDefined();
const size_t moreColorAttachmentCount = mMoreColorAttachments.Length();
for (size_t i = 0; i < moreColorAttachmentCount; i++) {
hasAttachments |= mMoreColorAttachments[i].IsDefined();
}
return hasAttachments;
}
static bool
IsIncomplete(const WebGLFramebuffer::Attachment& cur)
IsIncomplete(const WebGLFramebuffer::AttachPoint& cur)
{
return cur.IsDefined() && !cur.IsComplete();
}
@ -687,14 +588,16 @@ WebGLFramebuffer::HasIncompleteAttachments() const
{
bool hasIncomplete = false;
for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
hasIncomplete |= IsIncomplete(mColorAttachments[i]);
}
hasIncomplete |= IsIncomplete(mColorAttachment0);
hasIncomplete |= IsIncomplete(mDepthAttachment);
hasIncomplete |= IsIncomplete(mStencilAttachment);
hasIncomplete |= IsIncomplete(mDepthStencilAttachment);
const size_t moreColorAttachmentCount = mMoreColorAttachments.Length();
for (size_t i = 0; i < moreColorAttachmentCount; i++) {
hasIncomplete |= IsIncomplete(mMoreColorAttachments[i]);
}
return hasIncomplete;
}
@ -703,10 +606,8 @@ WebGLFramebuffer::GetAnyRectObject() const
{
MOZ_ASSERT(HasDefinedAttachments());
for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
if (mColorAttachments[i].HasImage())
return mColorAttachments[i].RectangleObject();
}
if (mColorAttachment0.HasImage())
return mColorAttachment0.RectangleObject();
if (mDepthAttachment.HasImage())
return mDepthAttachment.RectangleObject();
@ -717,11 +618,17 @@ WebGLFramebuffer::GetAnyRectObject() const
if (mDepthStencilAttachment.HasImage())
return mDepthStencilAttachment.RectangleObject();
const size_t moreColorAttachmentCount = mMoreColorAttachments.Length();
for (size_t i = 0; i < moreColorAttachmentCount; i++) {
if (mMoreColorAttachments[i].HasImage())
return mMoreColorAttachments[i].RectangleObject();
}
MOZ_CRASH("Should not get here.");
}
static bool
RectsMatch(const WebGLFramebuffer::Attachment& attachment,
RectsMatch(const WebGLFramebuffer::AttachPoint& attachment,
const WebGLRectangleObject& rect)
{
return attachment.RectangleObject().HasSameDimensionsAs(rect);
@ -738,10 +645,8 @@ WebGLFramebuffer::AllImageRectsMatch() const
// Alright, we have *a* rect, let's check all the others.
bool imageRectsMatch = true;
for (size_t i = 0; i < (size_t)mColorAttachments.Length(); i++) {
if (mColorAttachments[i].HasImage())
imageRectsMatch &= RectsMatch(mColorAttachments[i], rect);
}
if (mColorAttachment0.HasImage())
imageRectsMatch &= RectsMatch(mColorAttachment0, rect);
if (mDepthAttachment.HasImage())
imageRectsMatch &= RectsMatch(mDepthAttachment, rect);
@ -752,6 +657,12 @@ WebGLFramebuffer::AllImageRectsMatch() const
if (mDepthStencilAttachment.HasImage())
imageRectsMatch &= RectsMatch(mDepthStencilAttachment, rect);
const size_t moreColorAttachmentCount = mMoreColorAttachments.Length();
for (size_t i = 0; i < moreColorAttachmentCount; i++) {
if (mMoreColorAttachments[i].HasImage())
imageRectsMatch &= RectsMatch(mMoreColorAttachments[i], rect);
}
return imageRectsMatch;
}
@ -816,19 +727,17 @@ WebGLFramebuffer::HasCompletePlanes(GLbitfield mask)
mContext->mBoundReadFramebuffer == this);
bool hasPlanes = true;
if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
hasPlanes &= ColorAttachmentCount() &&
ColorAttachment(0).IsDefined();
}
if (mask & LOCAL_GL_COLOR_BUFFER_BIT)
hasPlanes &= mColorAttachment0.IsDefined();
if (mask & LOCAL_GL_DEPTH_BUFFER_BIT) {
hasPlanes &= DepthAttachment().IsDefined() ||
DepthStencilAttachment().IsDefined();
hasPlanes &= mDepthAttachment.IsDefined() ||
mDepthStencilAttachment.IsDefined();
}
if (mask & LOCAL_GL_STENCIL_BUFFER_BIT) {
hasPlanes &= StencilAttachment().IsDefined() ||
DepthStencilAttachment().IsDefined();
hasPlanes &= mStencilAttachment.IsDefined() ||
mDepthStencilAttachment.IsDefined();
}
return hasPlanes;
@ -844,17 +753,14 @@ WebGLFramebuffer::CheckAndInitializeAttachments()
return false;
// Cool! We've checked out ok. Just need to initialize.
const size_t colorAttachmentCount = mColorAttachments.Length();
const size_t moreColorAttachmentCount = mMoreColorAttachments.Length();
// Check if we need to initialize anything
{
bool hasUninitializedAttachments = false;
for (size_t i = 0; i < colorAttachmentCount; i++) {
if (mColorAttachments[i].HasImage())
hasUninitializedAttachments |= mColorAttachments[i].HasUninitializedImageData();
}
if (mColorAttachment0.HasImage())
hasUninitializedAttachments |= mColorAttachment0.HasUninitializedImageData();
if (mDepthAttachment.HasImage())
hasUninitializedAttachments |= mDepthAttachment.HasUninitializedImageData();
if (mStencilAttachment.HasImage())
@ -862,6 +768,11 @@ WebGLFramebuffer::CheckAndInitializeAttachments()
if (mDepthStencilAttachment.HasImage())
hasUninitializedAttachments |= mDepthStencilAttachment.HasUninitializedImageData();
for (size_t i = 0; i < moreColorAttachmentCount; i++) {
if (mMoreColorAttachments[i].HasImage())
hasUninitializedAttachments |= mMoreColorAttachments[i].HasUninitializedImageData();
}
if (!hasUninitializedAttachments)
return true;
}
@ -869,13 +780,11 @@ WebGLFramebuffer::CheckAndInitializeAttachments()
// Get buffer-bit-mask and color-attachment-mask-list
uint32_t mask = 0;
bool colorAttachmentsMask[WebGLContext::kMaxColorAttachments] = { false };
MOZ_ASSERT(colorAttachmentCount <= WebGLContext::kMaxColorAttachments);
MOZ_ASSERT(1 + moreColorAttachmentCount <= WebGLContext::kMaxColorAttachments);
for (size_t i = 0; i < colorAttachmentCount; i++) {
if (mColorAttachments[i].HasUninitializedImageData()) {
colorAttachmentsMask[i] = true;
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
}
if (mColorAttachment0.HasUninitializedImageData()) {
colorAttachmentsMask[0] = true;
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
}
if (mDepthAttachment.HasUninitializedImageData() ||
@ -890,15 +799,19 @@ WebGLFramebuffer::CheckAndInitializeAttachments()
mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
}
for (size_t i = 0; i < moreColorAttachmentCount; i++) {
if (mMoreColorAttachments[i].HasUninitializedImageData()) {
colorAttachmentsMask[1 + i] = true;
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
}
}
// Clear!
mContext->ForceClearFramebufferWithDefaultValues(mask, colorAttachmentsMask);
// Mark all the uninitialized images as initialized.
for (size_t i = 0; i < colorAttachmentCount; i++) {
if (mColorAttachments[i].HasUninitializedImageData())
mColorAttachments[i].SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
}
if (mColorAttachment0.HasUninitializedImageData())
mColorAttachment0.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
if (mDepthAttachment.HasUninitializedImageData())
mDepthAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
if (mStencilAttachment.HasUninitializedImageData())
@ -906,29 +819,28 @@ WebGLFramebuffer::CheckAndInitializeAttachments()
if (mDepthStencilAttachment.HasUninitializedImageData())
mDepthStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
for (size_t i = 0; i < moreColorAttachmentCount; i++) {
if (mMoreColorAttachments[i].HasUninitializedImageData())
mMoreColorAttachments[i].SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
}
return true;
}
void WebGLFramebuffer::EnsureColorAttachments(size_t colorAttachmentId)
void WebGLFramebuffer::EnsureColorAttachPoints(size_t colorAttachmentId)
{
MOZ_ASSERT(colorAttachmentId < WebGLContext::kMaxColorAttachments);
size_t currentAttachmentCount = mColorAttachments.Length();
if (colorAttachmentId < currentAttachmentCount)
if (colorAttachmentId < ColorAttachmentCount())
return;
mColorAttachments.SetLength(colorAttachmentId + 1);
for (size_t i = colorAttachmentId; i >= currentAttachmentCount; i--) {
mColorAttachments[i].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0 + i;
size_t colorAttachmentCount = ColorAttachmentCount();
while (colorAttachmentCount < WebGLContext::kMaxColorAttachments) {
GLenum nextAttachPoint = LOCAL_GL_COLOR_ATTACHMENT0 + colorAttachmentCount;
mMoreColorAttachments.AppendElement(AttachPoint(this, nextAttachPoint));
}
}
void
WebGLFramebuffer::NotifyAttachableChanged() const
{
// Attachment has changed, so invalidate cached status
mStatus = 0;
MOZ_ASSERT(colorAttachmentCount == ColorAttachmentCount());
}
static void
@ -963,18 +875,32 @@ FinalizeDrawAndReadBuffers(gl::GLContext* gl, bool isColorBufferDefined)
void
WebGLFramebuffer::FinalizeAttachments() const
{
MOZ_ASSERT(mContext->mBoundDrawFramebuffer == this ||
mContext->mBoundReadFramebuffer == this);
MOZ_ASSERT(mStatus == LOCAL_GL_FRAMEBUFFER_COMPLETE);
gl::GLContext* gl = mContext->gl;
for (size_t i = 0; i < ColorAttachmentCount(); i++) {
ColorAttachment(i).FinalizeAttachment(gl, LOCAL_GL_COLOR_ATTACHMENT0+i);
// Nuke the depth and stencil attachment points.
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
LOCAL_GL_RENDERBUFFER, 0);
gl->fFramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
LOCAL_GL_RENDERBUFFER, 0);
// Call finalize.
mColorAttachment0.FinalizeAttachment(gl, LOCAL_GL_COLOR_ATTACHMENT0);
mDepthAttachment.FinalizeAttachment(gl, LOCAL_GL_DEPTH_ATTACHMENT);
mStencilAttachment.FinalizeAttachment(gl, LOCAL_GL_STENCIL_ATTACHMENT);
mDepthStencilAttachment.FinalizeAttachment(gl, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
const size_t moreColorAttachmentCount = mMoreColorAttachments.Length();
for (size_t i = 0; i < moreColorAttachmentCount; i++) {
GLenum attachPoint = LOCAL_GL_COLOR_ATTACHMENT0 + 1 + i;
mMoreColorAttachments[i].FinalizeAttachment(gl, attachPoint);
}
DepthAttachment().FinalizeAttachment(gl, LOCAL_GL_DEPTH_ATTACHMENT);
StencilAttachment().FinalizeAttachment(gl, LOCAL_GL_STENCIL_ATTACHMENT);
DepthStencilAttachment().FinalizeAttachment(gl,
LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
FinalizeDrawAndReadBuffers(gl, ColorAttachment(0).IsDefined());
FinalizeDrawAndReadBuffers(gl, mColorAttachment0.IsDefined());
}
bool
@ -986,7 +912,7 @@ WebGLFramebuffer::ValidateForRead(const char* info, TexInternalFormat* const out
return false;
}
const auto& attachment = GetAttachment(mReadBufferMode);
const auto& attachPoint = GetAttachPoint(mReadBufferMode);
if (!CheckAndInitializeAttachments()) {
mContext->ErrorInvalidFramebufferOperation("readPixels: incomplete framebuffer");
@ -1000,38 +926,46 @@ WebGLFramebuffer::ValidateForRead(const char* info, TexInternalFormat* const out
return false;
}
if (!attachment.IsDefined()) {
if (!attachPoint.IsDefined()) {
mContext->ErrorInvalidOperation("readPixels: ");
return false;
}
*out_format = attachment.EffectiveInternalFormat();
*out_format = attachPoint.EffectiveInternalFormat();
return true;
}
inline void
ImplCycleCollectionUnlink(mozilla::WebGLFramebuffer::Attachment& field)
////////////////////////////////////////////////////////////////////////////////
// Goop.
JSObject*
WebGLFramebuffer::WrapObject(JSContext* cx)
{
field.mTexturePtr = nullptr;
field.mRenderbufferPtr = nullptr;
return dom::WebGLFramebufferBinding::Wrap(cx, this);
}
inline void
ImplCycleCollectionUnlink(mozilla::WebGLFramebuffer::AttachPoint& field)
{
field.Unlink();
}
inline void
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
mozilla::WebGLFramebuffer::Attachment& field,
mozilla::WebGLFramebuffer::AttachPoint& field,
const char* name,
uint32_t flags = 0)
{
CycleCollectionNoteChild(callback, field.mTexturePtr.get(), name, flags);
CycleCollectionNoteChild(callback, field.mRenderbufferPtr.get(), name,
flags);
CycleCollectionNoteChild(callback, field.Texture(), name, flags);
CycleCollectionNoteChild(callback, field.Renderbuffer(), name, flags);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLFramebuffer,
mColorAttachments,
mColorAttachment0,
mDepthAttachment,
mStencilAttachment,
mDepthStencilAttachment)
mDepthStencilAttachment,
mMoreColorAttachments)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLFramebuffer, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLFramebuffer, Release)

View File

@ -33,20 +33,25 @@ class WebGLFramebuffer MOZ_FINAL
public:
MOZ_DECLARE_REFCOUNTED_TYPENAME(WebGLFramebuffer)
explicit WebGLFramebuffer(WebGLContext* webgl, GLuint fbo);
struct Attachment
class AttachPoint
{
// deleting a texture or renderbuffer immediately detaches it
public:
WebGLFramebuffer* const mFB;
private:
WebGLRefPtr<WebGLTexture> mTexturePtr;
WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
FBAttachment mAttachmentPoint;
TexImageTarget mTexImageTarget;
GLint mTexImageLevel;
mutable bool mNeedsFinalize;
explicit Attachment(FBAttachment attachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0);
~Attachment();
public:
AttachPoint(WebGLFramebuffer* fb, FBAttachment attachmentPoint);
~AttachPoint();
void Unlink() {
mRenderbufferPtr = nullptr;
mTexturePtr = nullptr;
}
bool IsDefined() const;
@ -57,6 +62,10 @@ public:
bool HasAlpha() const;
bool IsReadableFloat() const;
void Clear() {
SetRenderbuffer(nullptr);
}
void SetTexImage(WebGLTexture* tex, TexImageTarget target, GLint level);
void SetRenderbuffer(WebGLRenderbuffer* rb);
@ -82,8 +91,6 @@ public:
bool HasUninitializedImageData() const;
void SetImageDataStatus(WebGLImageDataStatus x);
void Reset();
const WebGLRectangleObject& RectangleObject() const;
bool HasImage() const;
@ -93,6 +100,29 @@ public:
FBAttachment attachmentLoc) const;
};
private:
mutable GLenum mStatus;
GLenum mReadBufferMode;
// No need to chase pointers for the oft-used color0.
AttachPoint mColorAttachment0;
AttachPoint mDepthAttachment;
AttachPoint mStencilAttachment;
AttachPoint mDepthStencilAttachment;
nsTArray<AttachPoint> mMoreColorAttachments;
public:
WebGLFramebuffer(WebGLContext* webgl, GLuint fbo);
private:
~WebGLFramebuffer() {
DeleteOnce();
}
const WebGLRectangleObject& GetAnyRectObject() const;
public:
void Delete();
void FramebufferRenderbuffer(FBAttachment attachment, RBTarget rbtarget,
@ -102,13 +132,6 @@ public:
TexImageTarget texImageTarget, WebGLTexture* tex,
GLint level);
private:
void DetachAttachment(WebGLFramebuffer::Attachment& attachment);
void DetachAllAttachments();
const WebGLRectangleObject& GetAnyRectObject() const;
Attachment* GetAttachmentOrNull(FBAttachment attachment);
public:
bool HasDefinedAttachments() const;
bool HasIncompleteAttachments() const;
bool AllImageRectsMatch() const;
@ -116,7 +139,7 @@ public:
FBStatus CheckFramebufferStatus() const;
GLenum
GetFormatForAttachment(const WebGLFramebuffer::Attachment& attachment) const;
GetFormatForAttachment(const WebGLFramebuffer::AttachPoint& attachment) const;
bool HasDepthStencilConflict() const {
return int(mDepthAttachment.IsDefined()) +
@ -125,25 +148,28 @@ public:
}
size_t ColorAttachmentCount() const {
return mColorAttachments.Length();
}
const Attachment& ColorAttachment(size_t colorAttachmentId) const {
return mColorAttachments[colorAttachmentId];
return 1 + mMoreColorAttachments.Length();
}
const Attachment& DepthAttachment() const {
const AttachPoint& ColorAttachment(size_t colorAttachmentId) const {
MOZ_ASSERT(colorAttachmentId < ColorAttachmentCount());
return colorAttachmentId ? mMoreColorAttachments[colorAttachmentId - 1]
: mColorAttachment0;
}
const AttachPoint& DepthAttachment() const {
return mDepthAttachment;
}
const Attachment& StencilAttachment() const {
const AttachPoint& StencilAttachment() const {
return mStencilAttachment;
}
const Attachment& DepthStencilAttachment() const {
const AttachPoint& DepthStencilAttachment() const {
return mDepthStencilAttachment;
}
const Attachment& GetAttachment(FBAttachment attachment) const;
AttachPoint& GetAttachPoint(FBAttachment attachPointEnum);
void DetachTexture(const WebGLTexture* tex);
@ -170,26 +196,13 @@ public:
bool CheckColorAttachmentNumber(FBAttachment attachment,
const char* funcName) const;
void EnsureColorAttachments(size_t colorAttachmentId);
void EnsureColorAttachPoints(size_t colorAttachmentId);
void NotifyAttachableChanged() const;
bool ValidateForRead(const char* info, TexInternalFormat* const out_format);
private:
~WebGLFramebuffer() {
DeleteOnce();
void InvalidateFramebufferStatus() const {
mStatus = 0;
}
mutable GLenum mStatus;
// we only store pointers to attached renderbuffers, not to attached textures, because
// we will only need to initialize renderbuffers. Textures are already initialized.
nsTArray<Attachment> mColorAttachments;
Attachment mDepthAttachment;
Attachment mStencilAttachment;
Attachment mDepthStencilAttachment;
GLenum mReadBufferMode;
bool ValidateForRead(const char* info, TexInternalFormat* const out_format);
};
} // namespace mozilla

View File

@ -3,35 +3,28 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLFramebufferAttachable.h"
#include "WebGLContext.h"
#include "WebGLFramebuffer.h"
#include "WebGLRenderbuffer.h"
#include "WebGLTexture.h"
using namespace mozilla;
namespace mozilla {
void
WebGLFramebufferAttachable::AttachTo(WebGLFramebuffer* fb, FBAttachment attachment)
WebGLFramebufferAttachable::MarkAttachment(const WebGLFramebuffer::AttachPoint& attachment)
{
MOZ_ASSERT(fb);
if (!fb)
return;
if (mAttachmentPoints.Contains(AttachmentPoint(fb, attachment)))
if (mAttachmentPoints.Contains(&attachment))
return; // Already attached. Ignore.
mAttachmentPoints.AppendElement(AttachmentPoint(fb, attachment));
mAttachmentPoints.AppendElement(&attachment);
}
void
WebGLFramebufferAttachable::DetachFrom(WebGLFramebuffer* fb, FBAttachment attachment)
WebGLFramebufferAttachable::UnmarkAttachment(const WebGLFramebuffer::AttachPoint& attachment)
{
MOZ_ASSERT(fb);
if (!fb)
return;
const size_t i = mAttachmentPoints.IndexOf(AttachmentPoint(fb, attachment));
const size_t i = mAttachmentPoints.IndexOf(&attachment);
if (i == mAttachmentPoints.NoIndex) {
MOZ_ASSERT(false, "Is not attached to FB");
return;
@ -41,11 +34,13 @@ WebGLFramebufferAttachable::DetachFrom(WebGLFramebuffer* fb, FBAttachment attach
}
void
WebGLFramebufferAttachable::NotifyFBsStatusChanged()
WebGLFramebufferAttachable::InvalidateStatusOfAttachedFBs() const
{
for (size_t i = 0; i < mAttachmentPoints.Length(); ++i) {
MOZ_ASSERT(mAttachmentPoints[i].mFB,
"Unexpected null pointer; seems that a WebGLFramebuffer forgot to call DetachFrom before dying");
mAttachmentPoints[i].mFB->NotifyAttachableChanged();
const size_t count = mAttachmentPoints.Length();
for (size_t i = 0; i < count; ++i) {
MOZ_ASSERT(mAttachmentPoints[i]->mFB);
mAttachmentPoints[i]->mFB->InvalidateFramebufferStatus();
}
}
} // namespace mozilla

View File

@ -3,12 +3,12 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef WEBGLFRAMEBUFFERATTACHABLE_H_
#define WEBGLFRAMEBUFFERATTACHABLE_H_
#ifndef WEBGL_FRAMEBUFFER_ATTACHABLE_H_
#define WEBGL_FRAMEBUFFER_ATTACHABLE_H_
#include "GLDefs.h"
#include "nsTArray.h"
#include "mozilla/WeakPtr.h"
#include "nsTArray.h"
#include "WebGLFramebuffer.h"
#include "WebGLStrongTypes.h"
@ -16,29 +16,13 @@ namespace mozilla {
class WebGLFramebufferAttachable
{
struct AttachmentPoint
{
AttachmentPoint(const WebGLFramebuffer* fb, FBAttachment attachment)
: mFB(fb)
, mAttachment(attachment)
{}
WeakPtr<const WebGLFramebuffer> mFB;
FBAttachment mAttachment;
bool operator==(const AttachmentPoint& o) const {
return mFB == o.mFB && mAttachment == o.mAttachment;
}
};
nsTArray<AttachmentPoint> mAttachmentPoints;
nsTArray<const WebGLFramebuffer::AttachPoint*> mAttachmentPoints;
public:
// Track FBO/Attachment combinations
void AttachTo(WebGLFramebuffer* fb, FBAttachment attachment);
void DetachFrom(WebGLFramebuffer* fb, FBAttachment attachment);
void NotifyFBsStatusChanged();
void MarkAttachment(const WebGLFramebuffer::AttachPoint& attachment);
void UnmarkAttachment(const WebGLFramebuffer::AttachPoint& attachment);
void InvalidateStatusOfAttachedFBs() const;
};
} // namespace mozilla

View File

@ -179,6 +179,8 @@ void
WebGLRenderbuffer::RenderbufferStorage(GLsizei samples, GLenum internalFormat,
GLsizei width, GLsizei height) const
{
InvalidateStatusOfAttachedFBs();
gl::GLContext* gl = mContext->gl;
MOZ_ASSERT(samples >= 0 && samples <= 256); // Sanity check.

View File

@ -181,6 +181,8 @@ WebGLTexture::SetImageInfo(TexImageTarget texImageTarget, GLint level,
MOZ_ASSERT(depth == 1 || texImageTarget == LOCAL_GL_TEXTURE_3D);
MOZ_ASSERT(TexImageTargetToTexTarget(texImageTarget) == mTarget);
InvalidateStatusOfAttachedFBs();
EnsureMaxLevelWithCustomImagesAtLeast(level);
ImageInfoAt(texImageTarget, level) = ImageInfo(width, height, depth,
@ -190,9 +192,6 @@ WebGLTexture::SetImageInfo(TexImageTarget texImageTarget, GLint level,
if (level > 0)
SetCustomMipmap();
// Invalidate framebuffer status cache.
NotifyFBsStatusChanged();
SetFakeBlackStatus(WebGLTextureFakeBlackStatus::Unknown);
}