mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-27 12:50:09 +00:00
Bug 962392 - Clean up WebGLFramebuffer, particularly handling of RectangleObjects. - r=dglastonbury
This commit is contained in:
parent
49b5a372fe
commit
ece68b1952
@ -230,7 +230,8 @@ public:
|
||||
// all context resources to be lost.
|
||||
uint32_t Generation() { return mGeneration.value(); }
|
||||
|
||||
const WebGLRectangleObject *FramebufferRectangleObject() const;
|
||||
// Returns null if the current bound FB is not likely complete.
|
||||
const WebGLRectangleObject* CurValidFBRectObject() const;
|
||||
|
||||
static const size_t sMaxColorAttachments = 16;
|
||||
|
||||
|
@ -53,9 +53,22 @@ using namespace mozilla::gfx;
|
||||
static bool BaseTypeAndSizeFromUniformType(GLenum uType, GLenum *baseType, GLint *unitSize);
|
||||
static GLenum InternalFormatForFormatAndType(GLenum format, GLenum type, bool isGLES2);
|
||||
|
||||
const WebGLRectangleObject *WebGLContext::FramebufferRectangleObject() const {
|
||||
return mBoundFramebuffer ? mBoundFramebuffer->RectangleObject()
|
||||
: static_cast<const WebGLRectangleObject*>(this);
|
||||
const WebGLRectangleObject*
|
||||
WebGLContext::CurValidFBRectObject() const
|
||||
{
|
||||
const WebGLRectangleObject* rect = nullptr;
|
||||
|
||||
if (mBoundFramebuffer) {
|
||||
// We don't really need to ask the driver.
|
||||
// Use 'precheck' to just check that our internal state looks good.
|
||||
GLenum precheckStatus = mBoundFramebuffer->PrecheckFramebufferStatus();
|
||||
if (precheckStatus == LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
rect = &mBoundFramebuffer->RectangleObject();
|
||||
} else {
|
||||
rect = static_cast<const WebGLRectangleObject*>(this);
|
||||
}
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
WebGLContext::FakeBlackTexture::FakeBlackTexture(GLContext *gl, GLenum target, GLenum format)
|
||||
@ -347,11 +360,8 @@ GLenum
|
||||
WebGLContext::CheckFramebufferStatus(GLenum target)
|
||||
{
|
||||
if (IsContextLost())
|
||||
{
|
||||
return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
if (target != LOCAL_GL_FRAMEBUFFER) {
|
||||
ErrorInvalidEnum("checkFramebufferStatus: target must be FRAMEBUFFER");
|
||||
return 0;
|
||||
@ -359,42 +369,8 @@ WebGLContext::CheckFramebufferStatus(GLenum target)
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
|
||||
if(mBoundFramebuffer->HasDepthStencilConflict())
|
||||
return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
|
||||
bool hasImages = false;
|
||||
hasImages |= mBoundFramebuffer->DepthAttachment().IsDefined();
|
||||
hasImages |= mBoundFramebuffer->StencilAttachment().IsDefined();
|
||||
hasImages |= mBoundFramebuffer->DepthStencilAttachment().IsDefined();
|
||||
|
||||
if (!hasImages) {
|
||||
int32_t colorAttachmentCount = mBoundFramebuffer->mColorAttachments.Length();
|
||||
|
||||
for(int32_t i = 0; i < colorAttachmentCount; i++) {
|
||||
if (mBoundFramebuffer->ColorAttachment(i).IsDefined()) {
|
||||
hasImages = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* http://www.khronos.org/registry/gles/specs/2.0/es_full_spec_2.0.25.pdf section 4.4.5 (page 118)
|
||||
GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
|
||||
No images are attached to the framebuffer.
|
||||
*/
|
||||
if (!hasImages) {
|
||||
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
|
||||
}
|
||||
}
|
||||
|
||||
if(mBoundFramebuffer->HasIncompleteAttachment())
|
||||
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);
|
||||
return mBoundFramebuffer->CheckFramebufferStatus();
|
||||
}
|
||||
|
||||
void
|
||||
@ -409,7 +385,7 @@ WebGLContext::CopyTexSubImage2D_base(GLenum target,
|
||||
GLsizei height,
|
||||
bool sub)
|
||||
{
|
||||
const WebGLRectangleObject *framebufferRect = FramebufferRectangleObject();
|
||||
const WebGLRectangleObject* framebufferRect = CurValidFBRectObject();
|
||||
GLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
|
||||
GLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
|
||||
|
||||
@ -2269,7 +2245,7 @@ WebGLContext::ReadPixels(GLint x, GLint y, GLsizei width,
|
||||
if (pixels.IsNull())
|
||||
return ErrorInvalidValue("readPixels: null destination buffer");
|
||||
|
||||
const WebGLRectangleObject *framebufferRect = FramebufferRectangleObject();
|
||||
const WebGLRectangleObject* framebufferRect = CurValidFBRectObject();
|
||||
GLsizei framebufferWidth = framebufferRect ? framebufferRect->Width() : 0;
|
||||
GLsizei framebufferHeight = framebufferRect ? framebufferRect->Height() : 0;
|
||||
|
||||
|
@ -735,7 +735,7 @@ void WebGLContext::Draw_cleanup()
|
||||
}
|
||||
|
||||
// Let's check the viewport
|
||||
const WebGLRectangleObject* rect = FramebufferRectangleObject();
|
||||
const WebGLRectangleObject* rect = CurValidFBRectObject();
|
||||
if (rect) {
|
||||
if (mViewportWidth > rect->Width() ||
|
||||
mViewportHeight > rect->Height())
|
||||
|
@ -12,16 +12,18 @@
|
||||
#include "WebGLTexture.h"
|
||||
#include "WebGLRenderbuffer.h"
|
||||
#include "GLContext.h"
|
||||
#include "WebGLContextUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gl;
|
||||
|
||||
JSObject*
|
||||
WebGLFramebuffer::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope) {
|
||||
WebGLFramebuffer::WrapObject(JSContext* cx, JS::Handle<JSObject*> scope)
|
||||
{
|
||||
return dom::WebGLFramebufferBinding::Wrap(cx, scope, this);
|
||||
}
|
||||
|
||||
WebGLFramebuffer::WebGLFramebuffer(WebGLContext *context)
|
||||
WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context)
|
||||
: WebGLContextBoundObject(context)
|
||||
, mHasEverBeenBound(false)
|
||||
, mDepthAttachment(LOCAL_GL_DEPTH_ATTACHMENT)
|
||||
@ -38,14 +40,16 @@ WebGLFramebuffer::WebGLFramebuffer(WebGLContext *context)
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::Attachment::IsDeleteRequested() const {
|
||||
WebGLFramebuffer::Attachment::IsDeleteRequested() const
|
||||
{
|
||||
return Texture() ? Texture()->IsDeleteRequested()
|
||||
: Renderbuffer() ? Renderbuffer()->IsDeleteRequested()
|
||||
: false;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::Attachment::HasAlpha() const {
|
||||
WebGLFramebuffer::Attachment::HasAlpha() const
|
||||
{
|
||||
GLenum format = 0;
|
||||
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
||||
format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).InternalFormat();
|
||||
@ -55,7 +59,8 @@ WebGLFramebuffer::Attachment::HasAlpha() const {
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture *tex, GLenum target, GLint level) {
|
||||
WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture* tex, GLenum target, GLint level)
|
||||
{
|
||||
mTexturePtr = tex;
|
||||
mRenderbufferPtr = nullptr;
|
||||
mTexImageTarget = target;
|
||||
@ -63,50 +68,68 @@ WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture *tex, GLenum target, GLin
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::Attachment::HasUninitializedImageData() const {
|
||||
if (mRenderbufferPtr) {
|
||||
return mRenderbufferPtr->HasUninitializedImageData();
|
||||
} else if (mTexturePtr) {
|
||||
if (!mTexturePtr->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
||||
return false;
|
||||
return mTexturePtr->ImageInfoAt(mTexImageTarget, mTexImageLevel).HasUninitializedImageData();
|
||||
} else {
|
||||
WebGLFramebuffer::Attachment::HasUninitializedImageData() const
|
||||
{
|
||||
if (!HasImage())
|
||||
return false;
|
||||
|
||||
if (Renderbuffer()) {
|
||||
return Renderbuffer()->HasUninitializedImageData();
|
||||
} else if (Texture()) {
|
||||
MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
|
||||
return Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).HasUninitializedImageData();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false, "Should not get here.");
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::Attachment::SetImageDataStatus(WebGLImageDataStatus newStatus) {
|
||||
WebGLFramebuffer::Attachment::SetImageDataStatus(WebGLImageDataStatus newStatus)
|
||||
{
|
||||
if (!HasImage())
|
||||
return;
|
||||
|
||||
if (mRenderbufferPtr) {
|
||||
mRenderbufferPtr->SetImageDataStatus(newStatus);
|
||||
return;
|
||||
} else if (mTexturePtr) {
|
||||
mTexturePtr->SetImageDataStatus(mTexImageTarget, mTexImageLevel, newStatus);
|
||||
} else {
|
||||
MOZ_ASSERT(false); // should not get here, worth crashing a debug build.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const WebGLRectangleObject*
|
||||
WebGLFramebuffer::Attachment::RectangleObject() const {
|
||||
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
||||
return &Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
|
||||
else if (Renderbuffer())
|
||||
return Renderbuffer();
|
||||
else
|
||||
return nullptr;
|
||||
MOZ_ASSERT(false, "Should not get here.");
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::Attachment::HasSameDimensionsAs(const Attachment& other) const {
|
||||
const WebGLRectangleObject *thisRect = RectangleObject();
|
||||
const WebGLRectangleObject *otherRect = other.RectangleObject();
|
||||
return thisRect &&
|
||||
otherRect &&
|
||||
thisRect->HasSameDimensionsAs(*otherRect);
|
||||
WebGLFramebuffer::Attachment::HasImage() const
|
||||
{
|
||||
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
||||
return true;
|
||||
else if (Renderbuffer())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const WebGLRectangleObject&
|
||||
WebGLFramebuffer::Attachment::RectangleObject() const
|
||||
{
|
||||
MOZ_ASSERT(HasImage(), "Make sure it has an image before requesting the rectangle.");
|
||||
|
||||
if (Texture()) {
|
||||
MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
|
||||
return Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
|
||||
} else if (Renderbuffer()) {
|
||||
return *Renderbuffer();
|
||||
}
|
||||
|
||||
MOZ_CRASH("Should not get here.");
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsValidAttachedTextureColorFormat(GLenum format) {
|
||||
IsValidAttachedTextureColorFormat(GLenum format)
|
||||
{
|
||||
return (
|
||||
/* linear 8-bit formats */
|
||||
format == LOCAL_GL_ALPHA ||
|
||||
@ -126,31 +149,34 @@ IsValidAttachedTextureColorFormat(GLenum format) {
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::Attachment::IsComplete() const {
|
||||
const WebGLRectangleObject *thisRect = RectangleObject();
|
||||
|
||||
if (!thisRect ||
|
||||
!thisRect->Width() ||
|
||||
!thisRect->Height())
|
||||
WebGLFramebuffer::Attachment::IsComplete() const
|
||||
{
|
||||
if (!HasImage())
|
||||
return false;
|
||||
|
||||
if (mTexturePtr) {
|
||||
if (!mTexturePtr->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
||||
return false;
|
||||
const WebGLRectangleObject& rect = RectangleObject();
|
||||
|
||||
if (!rect.Width() ||
|
||||
!rect.Height())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mTexturePtr) {
|
||||
MOZ_ASSERT(mTexturePtr->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
|
||||
GLenum format = mTexturePtr->ImageInfoAt(mTexImageTarget, mTexImageLevel).InternalFormat();
|
||||
|
||||
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT) {
|
||||
return format == LOCAL_GL_DEPTH_COMPONENT;
|
||||
}
|
||||
else if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
} else if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
return format == LOCAL_GL_DEPTH_STENCIL;
|
||||
}
|
||||
else if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + WebGLContext::sMaxColorAttachments)) {
|
||||
} else if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + WebGLContext::sMaxColorAttachments))
|
||||
{
|
||||
return IsValidAttachedTextureColorFormat(format);
|
||||
}
|
||||
MOZ_CRASH("Invalid WebGL attachment poin?");
|
||||
MOZ_ASSERT(false, "Invalid WebGL attachment point?");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mRenderbufferPtr) {
|
||||
@ -158,29 +184,31 @@ WebGLFramebuffer::Attachment::IsComplete() const {
|
||||
|
||||
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT) {
|
||||
return format == LOCAL_GL_DEPTH_COMPONENT16;
|
||||
}
|
||||
else if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT) {
|
||||
} else if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT) {
|
||||
return format == LOCAL_GL_STENCIL_INDEX8;
|
||||
}
|
||||
else if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
} else if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
return format == LOCAL_GL_DEPTH_STENCIL;
|
||||
} else if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + WebGLContext::sMaxColorAttachments))
|
||||
{
|
||||
return format == LOCAL_GL_RGB565 ||
|
||||
format == LOCAL_GL_RGB5_A1 ||
|
||||
format == LOCAL_GL_RGBA4 ||
|
||||
format == LOCAL_GL_SRGB8_ALPHA8_EXT;
|
||||
}
|
||||
else if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + WebGLContext::sMaxColorAttachments)) {
|
||||
return (format == LOCAL_GL_RGB565 ||
|
||||
format == LOCAL_GL_RGB5_A1 ||
|
||||
format == LOCAL_GL_RGBA4 ||
|
||||
format == LOCAL_GL_SRGB8_ALPHA8_EXT);
|
||||
}
|
||||
MOZ_CRASH("Invalid WebGL attachment poin?");
|
||||
MOZ_ASSERT(false, "Invalid WebGL attachment point?");
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false); // should never get there
|
||||
MOZ_ASSERT(false, "Should not get here.");
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::Attachment::FinalizeAttachment(GLenum attachmentLoc) const {
|
||||
WebGLFramebuffer::Attachment::FinalizeAttachment(GLenum attachmentLoc) const
|
||||
{
|
||||
MOZ_ASSERT(HasImage());
|
||||
|
||||
if (Texture()) {
|
||||
GLContext* gl = Texture()->Context()->gl;
|
||||
if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
@ -200,16 +228,17 @@ WebGLFramebuffer::Attachment::FinalizeAttachment(GLenum attachmentLoc) const {
|
||||
return;
|
||||
}
|
||||
|
||||
// Neither?
|
||||
MOZ_ASSERT(false, "FB attachment without a tex or RB.");
|
||||
MOZ_ASSERT(false, "Should not get here.");
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::Delete() {
|
||||
WebGLFramebuffer::Delete()
|
||||
{
|
||||
mColorAttachments.Clear();
|
||||
mDepthAttachment.Reset();
|
||||
mStencilAttachment.Reset();
|
||||
mDepthStencilAttachment.Reset();
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fDeleteFramebuffers(1, &mGLName);
|
||||
LinkedListElement<WebGLFramebuffer>::removeFrom(mContext->mFramebuffers);
|
||||
@ -217,15 +246,13 @@ WebGLFramebuffer::Delete() {
|
||||
|
||||
void
|
||||
WebGLFramebuffer::FramebufferRenderbuffer(GLenum target,
|
||||
GLenum attachment,
|
||||
GLenum rbtarget,
|
||||
WebGLRenderbuffer *wrb)
|
||||
GLenum attachment,
|
||||
GLenum rbtarget,
|
||||
WebGLRenderbuffer* wrb)
|
||||
{
|
||||
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
||||
if (!mContext->ValidateObjectAllowNull("framebufferRenderbuffer: renderbuffer", wrb))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: target", target);
|
||||
@ -258,10 +285,10 @@ WebGLFramebuffer::FramebufferRenderbuffer(GLenum target,
|
||||
|
||||
void
|
||||
WebGLFramebuffer::FramebufferTexture2D(GLenum target,
|
||||
GLenum attachment,
|
||||
GLenum textarget,
|
||||
WebGLTexture *wtex,
|
||||
GLint level)
|
||||
GLenum attachment,
|
||||
GLenum textarget,
|
||||
WebGLTexture* wtex,
|
||||
GLint level)
|
||||
{
|
||||
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
||||
if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture",
|
||||
@ -276,7 +303,9 @@ WebGLFramebuffer::FramebufferTexture2D(GLenum target,
|
||||
if (textarget != LOCAL_GL_TEXTURE_2D &&
|
||||
(textarget < LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
|
||||
textarget > LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
|
||||
{
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: invalid texture target", textarget);
|
||||
}
|
||||
|
||||
if (wtex) {
|
||||
bool isTexture2D = wtex->Target() == LOCAL_GL_TEXTURE_2D;
|
||||
@ -300,9 +329,8 @@ WebGLFramebuffer::FramebufferTexture2D(GLenum target,
|
||||
mDepthStencilAttachment.SetTexImage(wtex, textarget, level);
|
||||
break;
|
||||
default:
|
||||
if (!CheckColorAttachementNumber(attachment, "framebufferTexture2D")){
|
||||
if (!CheckColorAttachementNumber(attachment, "framebufferTexture2D"))
|
||||
return;
|
||||
}
|
||||
|
||||
size_t colorAttachmentId = size_t(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
|
||||
EnsureColorAttachments(colorAttachmentId);
|
||||
@ -311,42 +339,9 @@ WebGLFramebuffer::FramebufferTexture2D(GLenum target,
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::HasIncompleteAttachment() const {
|
||||
int32_t colorAttachmentCount = mColorAttachments.Length();
|
||||
|
||||
for (int32_t i = 0; i < colorAttachmentCount; i++)
|
||||
{
|
||||
if (mColorAttachments[i].IsDefined() && !mColorAttachments[i].IsComplete())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return ((mDepthAttachment.IsDefined() && !mDepthAttachment.IsComplete()) ||
|
||||
(mStencilAttachment.IsDefined() && !mStencilAttachment.IsComplete()) ||
|
||||
(mDepthStencilAttachment.IsDefined() && !mDepthStencilAttachment.IsComplete()));
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::HasAttachmentsOfMismatchedDimensions() const {
|
||||
int32_t colorAttachmentCount = mColorAttachments.Length();
|
||||
|
||||
for (int32_t i = 1; i < colorAttachmentCount; i++)
|
||||
{
|
||||
if (mColorAttachments[i].IsDefined() && !mColorAttachments[i].HasSameDimensionsAs(mColorAttachments[0]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return ((mDepthAttachment.IsDefined() && !mDepthAttachment.HasSameDimensionsAs(mColorAttachments[0])) ||
|
||||
(mStencilAttachment.IsDefined() && !mStencilAttachment.HasSameDimensionsAs(mColorAttachments[0])) ||
|
||||
(mDepthStencilAttachment.IsDefined() && !mDepthStencilAttachment.HasSameDimensionsAs(mColorAttachments[0])));
|
||||
}
|
||||
|
||||
const WebGLFramebuffer::Attachment&
|
||||
WebGLFramebuffer::GetAttachment(GLenum attachment) const {
|
||||
WebGLFramebuffer::GetAttachment(GLenum attachment) const
|
||||
{
|
||||
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
|
||||
return mDepthStencilAttachment;
|
||||
if (attachment == LOCAL_GL_DEPTH_ATTACHMENT)
|
||||
@ -359,8 +354,7 @@ WebGLFramebuffer::GetAttachment(GLenum attachment) const {
|
||||
return mColorAttachments[0];
|
||||
}
|
||||
|
||||
uint32_t colorAttachmentId = uint32_t(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
|
||||
|
||||
size_t colorAttachmentId = attachment - LOCAL_GL_COLOR_ATTACHMENT0;
|
||||
if (colorAttachmentId >= mColorAttachments.Length()) {
|
||||
MOZ_ASSERT(false);
|
||||
return mColorAttachments[0];
|
||||
@ -370,10 +364,9 @@ WebGLFramebuffer::GetAttachment(GLenum attachment) const {
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::DetachTexture(const WebGLTexture *tex) {
|
||||
int32_t colorAttachmentCount = mColorAttachments.Length();
|
||||
|
||||
for (int32_t i = 0; i < colorAttachmentCount; i++) {
|
||||
WebGLFramebuffer::DetachTexture(const WebGLTexture* tex)
|
||||
{
|
||||
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
|
||||
if (mColorAttachments[i].Texture() == tex) {
|
||||
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_TEXTURE_2D, nullptr, 0);
|
||||
// a texture might be attached more that once while editing the framebuffer
|
||||
@ -389,10 +382,9 @@ WebGLFramebuffer::DetachTexture(const WebGLTexture *tex) {
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer *rb) {
|
||||
int32_t colorAttachmentCount = mColorAttachments.Length();
|
||||
|
||||
for (int32_t i = 0; i < colorAttachmentCount; i++) {
|
||||
WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer* rb)
|
||||
{
|
||||
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
|
||||
if (mColorAttachments[0].Renderbuffer() == rb) {
|
||||
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_RENDERBUFFER, nullptr);
|
||||
// a renderbuffer might be attached more that once while editing the framebuffer
|
||||
@ -408,62 +400,191 @@ WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer *rb) {
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::CheckAndInitializeAttachments()
|
||||
WebGLFramebuffer::HasDefinedAttachments() const
|
||||
{
|
||||
bool hasAttachments = false;
|
||||
|
||||
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
|
||||
hasAttachments |= mColorAttachments[i].IsDefined();
|
||||
}
|
||||
|
||||
hasAttachments |= mDepthAttachment.IsDefined();
|
||||
hasAttachments |= mStencilAttachment.IsDefined();
|
||||
hasAttachments |= mDepthStencilAttachment.IsDefined();
|
||||
|
||||
return hasAttachments;
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
IsIncomplete(const WebGLFramebuffer::Attachment& cur)
|
||||
{
|
||||
return cur.IsDefined() && !cur.IsComplete();
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::HasIncompleteAttachments() const
|
||||
{
|
||||
bool hasIncomplete = false;
|
||||
|
||||
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
|
||||
hasIncomplete |= IsIncomplete(mColorAttachments[i]);
|
||||
}
|
||||
|
||||
hasIncomplete |= IsIncomplete(mDepthAttachment);
|
||||
hasIncomplete |= IsIncomplete(mStencilAttachment);
|
||||
hasIncomplete |= IsIncomplete(mDepthStencilAttachment);
|
||||
|
||||
return hasIncomplete;
|
||||
}
|
||||
|
||||
|
||||
const WebGLRectangleObject&
|
||||
WebGLFramebuffer::GetAnyRectObject() const
|
||||
{
|
||||
MOZ_ASSERT(HasDefinedAttachments());
|
||||
|
||||
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
|
||||
if (mColorAttachments[i].HasImage())
|
||||
return mColorAttachments[i].RectangleObject();
|
||||
}
|
||||
|
||||
if (mDepthAttachment.HasImage())
|
||||
return mDepthAttachment.RectangleObject();
|
||||
|
||||
if (mStencilAttachment.HasImage())
|
||||
return mStencilAttachment.RectangleObject();
|
||||
|
||||
if (mDepthStencilAttachment.HasImage())
|
||||
return mDepthStencilAttachment.RectangleObject();
|
||||
|
||||
MOZ_CRASH("Should not get here.");
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
RectsMatch(const WebGLFramebuffer::Attachment& attachment,
|
||||
const WebGLRectangleObject& rect)
|
||||
{
|
||||
return attachment.RectangleObject().HasSameDimensionsAs(rect);
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::AllImageRectsMatch() const
|
||||
{
|
||||
MOZ_ASSERT(HasDefinedAttachments());
|
||||
MOZ_ASSERT(!HasIncompleteAttachments());
|
||||
|
||||
const WebGLRectangleObject& rect = GetAnyRectObject();
|
||||
|
||||
// Alright, we have *a* rect, let's check all the others.
|
||||
bool imageRectsMatch = true;
|
||||
|
||||
for (size_t i = 0; i < mColorAttachments.Length(); i++) {
|
||||
if (mColorAttachments[i].HasImage())
|
||||
imageRectsMatch &= RectsMatch(mColorAttachments[i], rect);
|
||||
}
|
||||
|
||||
if (mDepthAttachment.HasImage())
|
||||
imageRectsMatch &= RectsMatch(mDepthAttachment, rect);
|
||||
|
||||
if (mStencilAttachment.HasImage())
|
||||
imageRectsMatch &= RectsMatch(mStencilAttachment, rect);
|
||||
|
||||
if (mDepthStencilAttachment.HasImage())
|
||||
imageRectsMatch &= RectsMatch(mDepthStencilAttachment, rect);
|
||||
|
||||
return imageRectsMatch;
|
||||
}
|
||||
|
||||
|
||||
const WebGLRectangleObject&
|
||||
WebGLFramebuffer::RectangleObject() const
|
||||
{
|
||||
// If we're using this as the RectObj of an FB, we need to be sure the FB
|
||||
// has a consistent rect.
|
||||
MOZ_ASSERT(AllImageRectsMatch(), "Did you mean `GetAnyRectObject`?");
|
||||
return GetAnyRectObject();
|
||||
}
|
||||
|
||||
GLenum
|
||||
WebGLFramebuffer::PrecheckFramebufferStatus() const
|
||||
{
|
||||
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
||||
// enforce WebGL section 6.5 which is WebGL-specific, hence OpenGL itself would not
|
||||
// generate the INVALID_FRAMEBUFFER_OPERATION that we need here
|
||||
|
||||
if (!HasDefinedAttachments())
|
||||
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; // No attachments
|
||||
|
||||
if (HasIncompleteAttachments())
|
||||
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||
|
||||
if (!AllImageRectsMatch())
|
||||
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; // No consistent size
|
||||
|
||||
if (HasDepthStencilConflict())
|
||||
return false;
|
||||
return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
|
||||
if (HasIncompleteAttachment())
|
||||
return false;
|
||||
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
|
||||
GLenum
|
||||
WebGLFramebuffer::CheckFramebufferStatus() const
|
||||
{
|
||||
GLenum precheckStatus = PrecheckFramebufferStatus();
|
||||
if (precheckStatus != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
return precheckStatus;
|
||||
|
||||
// Looks good on our end. Let's ask the driver.
|
||||
mContext->MakeContextCurrent();
|
||||
|
||||
// Ok, attach our chosen flavor of {DEPTH, STENCIL, DEPTH_STENCIL}.
|
||||
FinalizeAttachments();
|
||||
|
||||
return mContext->gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::CheckAndInitializeAttachments()
|
||||
{
|
||||
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
||||
|
||||
if (CheckFramebufferStatus() != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
return false;
|
||||
|
||||
// Cool! We've checked out ok. Just need to initialize.
|
||||
size_t colorAttachmentCount = size_t(mColorAttachments.Length());
|
||||
|
||||
// Check if we need to initialize anything
|
||||
{
|
||||
bool hasUnitializedAttachments = false;
|
||||
bool hasUninitializedAttachments = false;
|
||||
|
||||
for (size_t i = 0; i < colorAttachmentCount; i++) {
|
||||
hasUnitializedAttachments |= mColorAttachments[i].HasUninitializedImageData();
|
||||
if (mColorAttachments[i].HasImage())
|
||||
hasUninitializedAttachments |= mColorAttachments[i].HasUninitializedImageData();
|
||||
}
|
||||
|
||||
if (!hasUnitializedAttachments &&
|
||||
!mDepthAttachment.HasUninitializedImageData() &&
|
||||
!mStencilAttachment.HasUninitializedImageData() &&
|
||||
!mDepthStencilAttachment.HasUninitializedImageData())
|
||||
{
|
||||
if (mDepthAttachment.HasImage())
|
||||
hasUninitializedAttachments |= mDepthAttachment.HasUninitializedImageData();
|
||||
if (mStencilAttachment.HasImage())
|
||||
hasUninitializedAttachments |= mStencilAttachment.HasUninitializedImageData();
|
||||
if (mDepthStencilAttachment.HasImage())
|
||||
hasUninitializedAttachments |= mDepthStencilAttachment.HasUninitializedImageData();
|
||||
|
||||
if (!hasUninitializedAttachments)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// ensure INVALID_FRAMEBUFFER_OPERATION in zero-size case
|
||||
const WebGLRectangleObject *rect = mColorAttachments[0].RectangleObject();
|
||||
if (!rect ||
|
||||
!rect->Width() ||
|
||||
!rect->Height())
|
||||
return false;
|
||||
|
||||
GLenum status = mContext->CheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
return false;
|
||||
|
||||
// Get buffer-bit-mask and color-attachment-mask-list
|
||||
uint32_t mask = 0;
|
||||
bool colorAttachmentsMask[WebGLContext::sMaxColorAttachments] = { false };
|
||||
MOZ_ASSERT(colorAttachmentCount <= WebGLContext::sMaxColorAttachments);
|
||||
|
||||
MOZ_ASSERT( colorAttachmentCount <= WebGLContext::sMaxColorAttachments );
|
||||
|
||||
for (size_t i = 0; i < colorAttachmentCount; i++)
|
||||
{
|
||||
colorAttachmentsMask[i] = mColorAttachments[i].HasUninitializedImageData();
|
||||
|
||||
if (colorAttachmentsMask[i]) {
|
||||
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
|
||||
for (size_t i = 0; i < colorAttachmentCount; i++) {
|
||||
if (mColorAttachments[i].HasUninitializedImageData()) {
|
||||
colorAttachmentsMask[i] = true;
|
||||
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,10 +600,11 @@ WebGLFramebuffer::CheckAndInitializeAttachments()
|
||||
mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
|
||||
// Clear!
|
||||
mContext->ForceClearFramebufferWithDefaultValues(mask, colorAttachmentsMask);
|
||||
|
||||
for (size_t i = 0; i < colorAttachmentCount; i++)
|
||||
{
|
||||
// Mark all the uninitialized images as initialized.
|
||||
for (size_t i = 0; i < colorAttachmentCount; i++) {
|
||||
if (mColorAttachments[i].HasUninitializedImageData())
|
||||
mColorAttachments[i].SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
|
||||
}
|
||||
@ -497,30 +619,25 @@ WebGLFramebuffer::CheckAndInitializeAttachments()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebGLFramebuffer::CheckColorAttachementNumber(GLenum attachment, const char * functionName) const
|
||||
bool WebGLFramebuffer::CheckColorAttachementNumber(GLenum attachment, const char* functionName) const
|
||||
{
|
||||
const char* const errorFormating = "%s: attachment: invalid enum value 0x%x";
|
||||
|
||||
if (mContext->IsExtensionEnabled(WebGLContext::WEBGL_draw_buffers))
|
||||
{
|
||||
if (mContext->IsExtensionEnabled(WebGLContext::WEBGL_draw_buffers)) {
|
||||
if (attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
|
||||
attachment >= GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + mContext->mGLMaxColorAttachments))
|
||||
{
|
||||
mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
{
|
||||
} else if (attachment != LOCAL_GL_COLOR_ATTACHMENT0) {
|
||||
if (attachment > LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
attachment <= LOCAL_GL_COLOR_ATTACHMENT15)
|
||||
{
|
||||
mContext->ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x. "
|
||||
"Try the WEBGL_draw_buffers extension if supported.", functionName, attachment);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
|
||||
return false;
|
||||
}
|
||||
@ -529,14 +646,13 @@ bool WebGLFramebuffer::CheckColorAttachementNumber(GLenum attachment, const char
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebGLFramebuffer::EnsureColorAttachments(size_t colorAttachmentId) {
|
||||
void WebGLFramebuffer::EnsureColorAttachments(size_t colorAttachmentId)
|
||||
{
|
||||
MOZ_ASSERT(colorAttachmentId < WebGLContext::sMaxColorAttachments);
|
||||
|
||||
size_t currentAttachmentCount = mColorAttachments.Length();
|
||||
|
||||
if (mColorAttachments.Length() > colorAttachmentId) {
|
||||
if (colorAttachmentId < currentAttachmentCount)
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT( colorAttachmentId < WebGLContext::sMaxColorAttachments );
|
||||
|
||||
mColorAttachments.SetLength(colorAttachmentId + 1);
|
||||
|
||||
@ -546,7 +662,8 @@ void WebGLFramebuffer::EnsureColorAttachments(size_t colorAttachmentId) {
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::FinalizeAttachments() const {
|
||||
WebGLFramebuffer::FinalizeAttachments() const
|
||||
{
|
||||
for (size_t i = 0; i < ColorAttachmentCount(); i++) {
|
||||
if (ColorAttachment(i).IsDefined())
|
||||
ColorAttachment(i).FinalizeAttachment(LOCAL_GL_COLOR_ATTACHMENT0 + i);
|
||||
|
@ -27,7 +27,7 @@ class WebGLFramebuffer MOZ_FINAL
|
||||
, public WebGLContextBoundObject
|
||||
{
|
||||
public:
|
||||
WebGLFramebuffer(WebGLContext *context);
|
||||
WebGLFramebuffer(WebGLContext* context);
|
||||
|
||||
~WebGLFramebuffer() {
|
||||
DeleteOnce();
|
||||
@ -54,21 +54,21 @@ public:
|
||||
|
||||
bool HasAlpha() const;
|
||||
|
||||
void SetTexImage(WebGLTexture *tex, GLenum target, GLint level);
|
||||
void SetRenderbuffer(WebGLRenderbuffer *rb) {
|
||||
void SetTexImage(WebGLTexture* tex, GLenum target, GLint level);
|
||||
void SetRenderbuffer(WebGLRenderbuffer* rb) {
|
||||
mTexturePtr = nullptr;
|
||||
mRenderbufferPtr = rb;
|
||||
}
|
||||
const WebGLTexture *Texture() const {
|
||||
const WebGLTexture* Texture() const {
|
||||
return mTexturePtr;
|
||||
}
|
||||
WebGLTexture *Texture() {
|
||||
WebGLTexture* Texture() {
|
||||
return mTexturePtr;
|
||||
}
|
||||
const WebGLRenderbuffer *Renderbuffer() const {
|
||||
const WebGLRenderbuffer* Renderbuffer() const {
|
||||
return mRenderbufferPtr;
|
||||
}
|
||||
WebGLRenderbuffer *Renderbuffer() {
|
||||
WebGLRenderbuffer* Renderbuffer() {
|
||||
return mRenderbufferPtr;
|
||||
}
|
||||
GLenum TexImageTarget() const {
|
||||
@ -86,9 +86,9 @@ public:
|
||||
mRenderbufferPtr = nullptr;
|
||||
}
|
||||
|
||||
const WebGLRectangleObject* RectangleObject() const;
|
||||
bool HasSameDimensionsAs(const Attachment& other) const;
|
||||
const WebGLRectangleObject& RectangleObject() const;
|
||||
|
||||
bool HasImage() const;
|
||||
bool IsComplete() const;
|
||||
|
||||
void FinalizeAttachment(GLenum attachmentLoc) const;
|
||||
@ -103,15 +103,23 @@ public:
|
||||
void FramebufferRenderbuffer(GLenum target,
|
||||
GLenum attachment,
|
||||
GLenum rbtarget,
|
||||
WebGLRenderbuffer *wrb);
|
||||
WebGLRenderbuffer* wrb);
|
||||
|
||||
void FramebufferTexture2D(GLenum target,
|
||||
GLenum attachment,
|
||||
GLenum textarget,
|
||||
WebGLTexture *wtex,
|
||||
WebGLTexture* wtex,
|
||||
GLint level);
|
||||
|
||||
bool HasIncompleteAttachment() const;
|
||||
private:
|
||||
const WebGLRectangleObject& GetAnyRectObject() const;
|
||||
|
||||
public:
|
||||
bool HasDefinedAttachments() const;
|
||||
bool HasIncompleteAttachments() const;
|
||||
bool AllImageRectsMatch() const;
|
||||
GLenum PrecheckFramebufferStatus() const;
|
||||
GLenum CheckFramebufferStatus() const;
|
||||
|
||||
bool HasDepthStencilConflict() const {
|
||||
return int(mDepthAttachment.IsDefined()) +
|
||||
@ -119,12 +127,10 @@ public:
|
||||
int(mDepthStencilAttachment.IsDefined()) >= 2;
|
||||
}
|
||||
|
||||
bool HasAttachmentsOfMismatchedDimensions() const;
|
||||
|
||||
const size_t ColorAttachmentCount() const {
|
||||
size_t ColorAttachmentCount() const {
|
||||
return mColorAttachments.Length();
|
||||
}
|
||||
const Attachment& ColorAttachment(uint32_t colorAttachmentId) const {
|
||||
const Attachment& ColorAttachment(size_t colorAttachmentId) const {
|
||||
return mColorAttachments[colorAttachmentId];
|
||||
}
|
||||
|
||||
@ -142,21 +148,19 @@ public:
|
||||
|
||||
const Attachment& GetAttachment(GLenum attachment) const;
|
||||
|
||||
void DetachTexture(const WebGLTexture *tex);
|
||||
void DetachTexture(const WebGLTexture* tex);
|
||||
|
||||
void DetachRenderbuffer(const WebGLRenderbuffer *rb);
|
||||
void DetachRenderbuffer(const WebGLRenderbuffer* rb);
|
||||
|
||||
const WebGLRectangleObject *RectangleObject() {
|
||||
return mColorAttachments[0].RectangleObject();
|
||||
}
|
||||
const WebGLRectangleObject& RectangleObject() const;
|
||||
|
||||
WebGLContext *GetParentObject() const {
|
||||
WebGLContext* GetParentObject() const {
|
||||
return Context();
|
||||
}
|
||||
|
||||
void FinalizeAttachments() const;
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx,
|
||||
virtual JSObject* WrapObject(JSContext* cx,
|
||||
JS::Handle<JSObject*> scope) MOZ_OVERRIDE;
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebGLFramebuffer)
|
||||
@ -164,7 +168,7 @@ public:
|
||||
|
||||
bool CheckAndInitializeAttachments();
|
||||
|
||||
bool CheckColorAttachementNumber(GLenum attachment, const char * functionName) const;
|
||||
bool CheckColorAttachementNumber(GLenum attachment, const char* functionName) const;
|
||||
|
||||
GLuint mGLName;
|
||||
bool mHasEverBeenBound;
|
||||
|
Loading…
x
Reference in New Issue
Block a user