2012-10-04 20:35:54 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* 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"
|
2012-12-09 11:58:41 +00:00
|
|
|
#include "WebGLFramebuffer.h"
|
2013-06-21 23:44:17 +00:00
|
|
|
#include "WebGLExtensions.h"
|
2013-06-10 20:00:35 +00:00
|
|
|
#include "WebGLRenderbuffer.h"
|
|
|
|
#include "WebGLTexture.h"
|
2012-10-04 20:35:54 +00:00
|
|
|
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
2013-06-21 23:44:17 +00:00
|
|
|
#include "WebGLTexture.h"
|
|
|
|
#include "WebGLRenderbuffer.h"
|
2013-09-04 12:14:52 +00:00
|
|
|
#include "GLContext.h"
|
2012-10-04 20:35:54 +00:00
|
|
|
|
|
|
|
using namespace mozilla;
|
2013-10-02 00:30:05 +00:00
|
|
|
using namespace mozilla::gl;
|
2012-10-04 20:35:54 +00:00
|
|
|
|
|
|
|
JSObject*
|
2013-04-25 16:29:54 +00:00
|
|
|
WebGLFramebuffer::WrapObject(JSContext *cx, JS::Handle<JSObject*> scope) {
|
2013-03-11 23:03:47 +00:00
|
|
|
return dom::WebGLFramebufferBinding::Wrap(cx, scope, this);
|
2012-10-04 20:35:54 +00:00
|
|
|
}
|
|
|
|
|
2012-12-09 11:58:41 +00:00
|
|
|
WebGLFramebuffer::WebGLFramebuffer(WebGLContext *context)
|
|
|
|
: WebGLContextBoundObject(context)
|
|
|
|
, mHasEverBeenBound(false)
|
|
|
|
, mDepthAttachment(LOCAL_GL_DEPTH_ATTACHMENT)
|
|
|
|
, mStencilAttachment(LOCAL_GL_STENCIL_ATTACHMENT)
|
|
|
|
, mDepthStencilAttachment(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
|
|
|
|
{
|
|
|
|
SetIsDOMBinding();
|
|
|
|
mContext->MakeContextCurrent();
|
|
|
|
mContext->gl->fGenFramebuffers(1, &mGLName);
|
|
|
|
mContext->mFramebuffers.insertBack(this);
|
2013-06-21 23:44:17 +00:00
|
|
|
|
|
|
|
mColorAttachments.SetLength(1);
|
|
|
|
mColorAttachments[0].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0;
|
2012-12-09 11:58:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
WebGLFramebuffer::Attachment::IsDeleteRequested() const {
|
|
|
|
return Texture() ? Texture()->IsDeleteRequested()
|
|
|
|
: Renderbuffer() ? Renderbuffer()->IsDeleteRequested()
|
|
|
|
: false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
WebGLFramebuffer::Attachment::HasAlpha() const {
|
2013-09-04 12:14:43 +00:00
|
|
|
GLenum format = 0;
|
2013-10-02 00:30:38 +00:00
|
|
|
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
|
|
|
format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).Format();
|
2012-12-09 11:58:41 +00:00
|
|
|
else if (Renderbuffer())
|
|
|
|
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
|
2013-10-02 00:30:38 +00:00
|
|
|
WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture *tex, GLenum target, GLint level) {
|
2012-12-09 11:58:41 +00:00
|
|
|
mTexturePtr = tex;
|
|
|
|
mRenderbufferPtr = nullptr;
|
2013-10-02 00:30:38 +00:00
|
|
|
mTexImageTarget = target;
|
|
|
|
mTexImageLevel = level;
|
2012-12-09 11:58:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
WebGLFramebuffer::Attachment::HasUninitializedRenderbuffer() const {
|
|
|
|
return mRenderbufferPtr && !mRenderbufferPtr->Initialized();
|
|
|
|
}
|
|
|
|
|
|
|
|
const WebGLRectangleObject*
|
|
|
|
WebGLFramebuffer::Attachment::RectangleObject() const {
|
2013-10-02 00:30:38 +00:00
|
|
|
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
|
|
|
return &Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
|
2012-12-09 11:58:41 +00:00
|
|
|
else if (Renderbuffer())
|
|
|
|
return Renderbuffer();
|
|
|
|
else
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
WebGLFramebuffer::Attachment::HasSameDimensionsAs(const Attachment& other) const {
|
|
|
|
const WebGLRectangleObject *thisRect = RectangleObject();
|
|
|
|
const WebGLRectangleObject *otherRect = other.RectangleObject();
|
|
|
|
return thisRect &&
|
|
|
|
otherRect &&
|
|
|
|
thisRect->HasSameDimensionsAs(*otherRect);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
WebGLFramebuffer::Attachment::IsComplete() const {
|
|
|
|
const WebGLRectangleObject *thisRect = RectangleObject();
|
|
|
|
|
|
|
|
if (!thisRect ||
|
|
|
|
!thisRect->Width() ||
|
|
|
|
!thisRect->Height())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (mTexturePtr) {
|
2013-10-02 00:30:38 +00:00
|
|
|
if (!mTexturePtr->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
2012-12-09 11:58:41 +00:00
|
|
|
return false;
|
|
|
|
|
2013-10-02 00:30:38 +00:00
|
|
|
GLenum format = mTexturePtr->ImageInfoAt(mTexImageTarget, mTexImageLevel).Format();
|
2013-06-21 23:44:17 +00:00
|
|
|
|
|
|
|
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT) {
|
|
|
|
return format == LOCAL_GL_DEPTH_COMPONENT;
|
|
|
|
}
|
|
|
|
else if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
|
|
|
return format == LOCAL_GL_DEPTH_STENCIL;
|
2012-12-09 11:58:41 +00:00
|
|
|
}
|
2013-06-21 23:44:17 +00:00
|
|
|
else if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
2013-09-04 12:14:43 +00:00
|
|
|
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + WebGLContext::sMaxColorAttachments)) {
|
2013-06-21 23:44:17 +00:00
|
|
|
return (format == LOCAL_GL_ALPHA ||
|
|
|
|
format == LOCAL_GL_LUMINANCE ||
|
|
|
|
format == LOCAL_GL_LUMINANCE_ALPHA ||
|
|
|
|
format == LOCAL_GL_RGB ||
|
|
|
|
format == LOCAL_GL_RGBA);
|
|
|
|
}
|
2013-06-29 01:38:30 +00:00
|
|
|
MOZ_CRASH("Invalid WebGL attachment poin?");
|
2012-12-09 11:58:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (mRenderbufferPtr) {
|
2013-09-04 12:14:43 +00:00
|
|
|
GLenum format = mRenderbufferPtr->InternalFormat();
|
2013-06-21 23:44:17 +00:00
|
|
|
|
|
|
|
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT) {
|
|
|
|
return format == LOCAL_GL_DEPTH_COMPONENT16;
|
|
|
|
}
|
|
|
|
else if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT) {
|
|
|
|
return format == LOCAL_GL_STENCIL_INDEX8;
|
2012-12-09 11:58:41 +00:00
|
|
|
}
|
2013-06-21 23:44:17 +00:00
|
|
|
else if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
|
|
|
return format == LOCAL_GL_DEPTH_STENCIL;
|
|
|
|
}
|
|
|
|
else if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
2013-09-04 12:14:43 +00:00
|
|
|
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + WebGLContext::sMaxColorAttachments)) {
|
2013-06-21 23:44:17 +00:00
|
|
|
return (format == LOCAL_GL_RGB565 ||
|
|
|
|
format == LOCAL_GL_RGB5_A1 ||
|
|
|
|
format == LOCAL_GL_RGBA4);
|
|
|
|
}
|
2013-06-29 01:38:30 +00:00
|
|
|
MOZ_CRASH("Invalid WebGL attachment poin?");
|
2012-12-09 11:58:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_ABORT(); // should never get there
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2013-10-02 00:30:05 +00:00
|
|
|
void
|
|
|
|
WebGLFramebuffer::Attachment::FinalizeAttachment(GLenum attachmentLoc) const {
|
|
|
|
if (Texture()) {
|
|
|
|
GLContext* gl = Texture()->Context()->gl;
|
2013-10-02 00:31:09 +00:00
|
|
|
if (attachmentLoc == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
|
|
|
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
|
|
|
|
TexImageTarget(), Texture()->GLName(), TexImageLevel());
|
|
|
|
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
|
|
|
|
TexImageTarget(), Texture()->GLName(), TexImageLevel());
|
|
|
|
} else {
|
|
|
|
gl->fFramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, attachmentLoc,
|
|
|
|
TexImageTarget(), Texture()->GLName(), TexImageLevel());
|
|
|
|
}
|
2013-10-02 00:30:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Renderbuffer()) {
|
2013-10-02 00:31:09 +00:00
|
|
|
Renderbuffer()->FramebufferRenderbuffer(attachmentLoc);
|
2013-10-02 00:30:05 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Neither?
|
|
|
|
MOZ_ASSERT(false, "FB attachment without a tex or RB.");
|
|
|
|
}
|
|
|
|
|
2012-12-09 11:58:41 +00:00
|
|
|
void
|
|
|
|
WebGLFramebuffer::Delete() {
|
2013-06-21 23:44:17 +00:00
|
|
|
mColorAttachments.Clear();
|
2012-12-09 11:58:41 +00:00
|
|
|
mDepthAttachment.Reset();
|
|
|
|
mStencilAttachment.Reset();
|
|
|
|
mDepthStencilAttachment.Reset();
|
|
|
|
mContext->MakeContextCurrent();
|
|
|
|
mContext->gl->fDeleteFramebuffers(1, &mGLName);
|
|
|
|
LinkedListElement<WebGLFramebuffer>::removeFrom(mContext->mFramebuffers);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-09-04 12:14:43 +00:00
|
|
|
WebGLFramebuffer::FramebufferRenderbuffer(GLenum target,
|
|
|
|
GLenum attachment,
|
|
|
|
GLenum rbtarget,
|
2012-12-09 11:58:41 +00:00
|
|
|
WebGLRenderbuffer *wrb)
|
|
|
|
{
|
2013-06-21 23:42:32 +00:00
|
|
|
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
2012-12-09 11:58:41 +00:00
|
|
|
if (!mContext->ValidateObjectAllowNull("framebufferRenderbuffer: renderbuffer", wrb))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target != LOCAL_GL_FRAMEBUFFER)
|
|
|
|
return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: target", target);
|
|
|
|
|
|
|
|
if (rbtarget != LOCAL_GL_RENDERBUFFER)
|
|
|
|
return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: renderbuffer target:", rbtarget);
|
|
|
|
|
|
|
|
switch (attachment) {
|
|
|
|
case LOCAL_GL_DEPTH_ATTACHMENT:
|
|
|
|
mDepthAttachment.SetRenderbuffer(wrb);
|
|
|
|
break;
|
|
|
|
case LOCAL_GL_STENCIL_ATTACHMENT:
|
|
|
|
mStencilAttachment.SetRenderbuffer(wrb);
|
|
|
|
break;
|
|
|
|
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
|
|
|
mDepthStencilAttachment.SetRenderbuffer(wrb);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// finish checking that the 'attachment' parameter is among the allowed values
|
2013-06-21 23:44:17 +00:00
|
|
|
if (!CheckColorAttachementNumber(attachment, "framebufferRenderbuffer")){
|
|
|
|
return;
|
|
|
|
}
|
2012-12-09 11:58:41 +00:00
|
|
|
|
2013-06-21 23:44:17 +00:00
|
|
|
size_t colorAttachmentId = size_t(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
|
|
|
|
EnsureColorAttachments(colorAttachmentId);
|
|
|
|
mColorAttachments[colorAttachmentId].SetRenderbuffer(wrb);
|
2012-12-09 11:58:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-09-04 12:14:43 +00:00
|
|
|
WebGLFramebuffer::FramebufferTexture2D(GLenum target,
|
|
|
|
GLenum attachment,
|
|
|
|
GLenum textarget,
|
2012-12-09 11:58:41 +00:00
|
|
|
WebGLTexture *wtex,
|
2013-09-04 12:14:43 +00:00
|
|
|
GLint level)
|
2012-12-09 11:58:41 +00:00
|
|
|
{
|
2013-06-21 23:42:32 +00:00
|
|
|
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
2012-12-09 11:58:41 +00:00
|
|
|
if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture",
|
|
|
|
wtex))
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (target != LOCAL_GL_FRAMEBUFFER)
|
|
|
|
return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: target", 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 (level != 0)
|
|
|
|
return mContext->ErrorInvalidValue("framebufferTexture2D: level must be 0");
|
|
|
|
|
|
|
|
switch (attachment) {
|
|
|
|
case LOCAL_GL_DEPTH_ATTACHMENT:
|
2013-10-02 00:30:38 +00:00
|
|
|
mDepthAttachment.SetTexImage(wtex, textarget, level);
|
2012-12-09 11:58:41 +00:00
|
|
|
break;
|
|
|
|
case LOCAL_GL_STENCIL_ATTACHMENT:
|
2013-10-02 00:30:38 +00:00
|
|
|
mStencilAttachment.SetTexImage(wtex, textarget, level);
|
2012-12-09 11:58:41 +00:00
|
|
|
break;
|
|
|
|
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
2013-10-02 00:30:38 +00:00
|
|
|
mDepthStencilAttachment.SetTexImage(wtex, textarget, level);
|
2012-12-09 11:58:41 +00:00
|
|
|
break;
|
|
|
|
default:
|
2013-06-21 23:44:17 +00:00
|
|
|
if (!CheckColorAttachementNumber(attachment, "framebufferTexture2D")){
|
|
|
|
return;
|
|
|
|
}
|
2012-12-09 11:58:41 +00:00
|
|
|
|
2013-06-21 23:44:17 +00:00
|
|
|
size_t colorAttachmentId = size_t(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
|
|
|
|
EnsureColorAttachments(colorAttachmentId);
|
2013-10-02 00:30:38 +00:00
|
|
|
mColorAttachments[colorAttachmentId].SetTexImage(wtex, textarget, level);
|
2012-12-09 11:58:41 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-06-21 23:44:17 +00:00
|
|
|
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])));
|
|
|
|
}
|
|
|
|
|
2012-12-09 11:58:41 +00:00
|
|
|
const WebGLFramebuffer::Attachment&
|
2013-09-04 12:14:43 +00:00
|
|
|
WebGLFramebuffer::GetAttachment(GLenum attachment) const {
|
2012-12-09 11:58:41 +00:00
|
|
|
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
|
|
|
|
return mDepthStencilAttachment;
|
|
|
|
if (attachment == LOCAL_GL_DEPTH_ATTACHMENT)
|
|
|
|
return mDepthAttachment;
|
|
|
|
if (attachment == LOCAL_GL_STENCIL_ATTACHMENT)
|
|
|
|
return mStencilAttachment;
|
|
|
|
|
2013-07-02 21:30:20 +00:00
|
|
|
if (!CheckColorAttachementNumber(attachment, "getAttachment")) {
|
|
|
|
NS_ABORT();
|
|
|
|
return mColorAttachments[0];
|
|
|
|
}
|
2013-06-21 23:44:17 +00:00
|
|
|
|
|
|
|
uint32_t colorAttachmentId = uint32_t(attachment - LOCAL_GL_COLOR_ATTACHMENT0);
|
|
|
|
|
|
|
|
if (colorAttachmentId >= mColorAttachments.Length()) {
|
|
|
|
NS_ABORT();
|
|
|
|
return mColorAttachments[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
return mColorAttachments[colorAttachmentId];
|
2012-12-09 11:58:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
WebGLFramebuffer::DetachTexture(const WebGLTexture *tex) {
|
2013-06-21 23:44:17 +00:00
|
|
|
int32_t colorAttachmentCount = mColorAttachments.Length();
|
|
|
|
|
|
|
|
for (int32_t i = 0; i < colorAttachmentCount; 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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-09 11:58:41 +00:00
|
|
|
if (mDepthAttachment.Texture() == tex)
|
|
|
|
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
|
|
|
|
if (mStencilAttachment.Texture() == tex)
|
|
|
|
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
|
|
|
|
if (mDepthStencilAttachment.Texture() == tex)
|
|
|
|
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_TEXTURE_2D, nullptr, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer *rb) {
|
2013-06-21 23:44:17 +00:00
|
|
|
int32_t colorAttachmentCount = mColorAttachments.Length();
|
|
|
|
|
|
|
|
for (int32_t i = 0; i < colorAttachmentCount; 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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-09 11:58:41 +00:00
|
|
|
if (mDepthAttachment.Renderbuffer() == rb)
|
|
|
|
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
|
|
|
|
if (mStencilAttachment.Renderbuffer() == rb)
|
|
|
|
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
|
|
|
|
if (mDepthStencilAttachment.Renderbuffer() == rb)
|
|
|
|
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT, LOCAL_GL_RENDERBUFFER, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
WebGLFramebuffer::CheckAndInitializeRenderbuffers()
|
|
|
|
{
|
2013-06-21 23:42:32 +00:00
|
|
|
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
2012-12-09 11:58:41 +00:00
|
|
|
// enforce WebGL section 6.5 which is WebGL-specific, hence OpenGL itself would not
|
|
|
|
// generate the INVALID_FRAMEBUFFER_OPERATION that we need here
|
|
|
|
if (HasDepthStencilConflict())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (HasIncompleteAttachment())
|
|
|
|
return false;
|
|
|
|
|
2013-06-21 23:44:17 +00:00
|
|
|
size_t colorAttachmentCount = size_t(mColorAttachments.Length());
|
|
|
|
|
|
|
|
{
|
|
|
|
bool hasUnitializedRenderbuffers = false;
|
|
|
|
|
|
|
|
for (size_t i = 0; i < colorAttachmentCount; i++) {
|
|
|
|
hasUnitializedRenderbuffers |= mColorAttachments[i].HasUninitializedRenderbuffer();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!hasUnitializedRenderbuffers &&
|
|
|
|
!mDepthAttachment.HasUninitializedRenderbuffer() &&
|
|
|
|
!mStencilAttachment.HasUninitializedRenderbuffer() &&
|
|
|
|
!mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2012-12-09 11:58:41 +00:00
|
|
|
|
|
|
|
// ensure INVALID_FRAMEBUFFER_OPERATION in zero-size case
|
2013-06-21 23:44:17 +00:00
|
|
|
const WebGLRectangleObject *rect = mColorAttachments[0].RectangleObject();
|
2012-12-09 11:58:41 +00:00
|
|
|
if (!rect ||
|
|
|
|
!rect->Width() ||
|
|
|
|
!rect->Height())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
mContext->MakeContextCurrent();
|
|
|
|
|
2013-10-02 00:30:05 +00:00
|
|
|
// Ok, attach our chosen flavor of {DEPTH, STENCIL, DEPTH_STENCIL}.
|
|
|
|
FinalizeAttachments();
|
|
|
|
|
2013-09-04 12:14:43 +00:00
|
|
|
GLenum status = mContext->CheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
2012-12-09 11:58:41 +00:00
|
|
|
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
uint32_t mask = 0;
|
2013-07-02 21:30:20 +00:00
|
|
|
bool colorAttachmentsMask[WebGLContext::sMaxColorAttachments] = { false };
|
2013-06-21 23:44:17 +00:00
|
|
|
|
2013-07-02 21:30:20 +00:00
|
|
|
MOZ_ASSERT( colorAttachmentCount <= WebGLContext::sMaxColorAttachments );
|
2012-12-09 11:58:41 +00:00
|
|
|
|
2013-06-21 23:44:17 +00:00
|
|
|
for (size_t i = 0; i < colorAttachmentCount; i++)
|
|
|
|
{
|
|
|
|
colorAttachmentsMask[i] = mColorAttachments[i].HasUninitializedRenderbuffer();
|
|
|
|
|
|
|
|
if (colorAttachmentsMask[i]) {
|
|
|
|
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
|
|
|
|
}
|
|
|
|
}
|
2012-12-09 11:58:41 +00:00
|
|
|
|
|
|
|
if (mDepthAttachment.HasUninitializedRenderbuffer() ||
|
|
|
|
mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
|
|
|
{
|
|
|
|
mask |= LOCAL_GL_DEPTH_BUFFER_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mStencilAttachment.HasUninitializedRenderbuffer() ||
|
|
|
|
mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
|
|
|
{
|
|
|
|
mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
|
|
|
|
}
|
|
|
|
|
2013-06-21 23:44:17 +00:00
|
|
|
mContext->ForceClearFramebufferWithDefaultValues(mask, colorAttachmentsMask);
|
2012-12-09 11:58:41 +00:00
|
|
|
|
2013-06-21 23:44:17 +00:00
|
|
|
for (size_t i = 0; i < colorAttachmentCount; i++)
|
|
|
|
{
|
|
|
|
if (colorAttachmentsMask[i]) {
|
|
|
|
mColorAttachments[i].Renderbuffer()->SetInitialized(true);
|
|
|
|
}
|
|
|
|
}
|
2012-12-09 11:58:41 +00:00
|
|
|
|
|
|
|
if (mDepthAttachment.HasUninitializedRenderbuffer())
|
|
|
|
mDepthAttachment.Renderbuffer()->SetInitialized(true);
|
|
|
|
|
|
|
|
if (mStencilAttachment.HasUninitializedRenderbuffer())
|
|
|
|
mStencilAttachment.Renderbuffer()->SetInitialized(true);
|
|
|
|
|
|
|
|
if (mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
|
|
|
mDepthStencilAttachment.Renderbuffer()->SetInitialized(true);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2013-09-04 12:14:43 +00:00
|
|
|
bool WebGLFramebuffer::CheckColorAttachementNumber(GLenum attachment, const char * functionName) const
|
2013-06-21 23:44:17 +00:00
|
|
|
{
|
|
|
|
const char* const errorFormating = "%s: attachment: invalid enum value 0x%x";
|
|
|
|
|
|
|
|
if (mContext->IsExtensionEnabled(WebGLContext::WEBGL_draw_buffers))
|
|
|
|
{
|
|
|
|
if (attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
|
2013-09-04 12:14:43 +00:00
|
|
|
attachment > GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + mContext->mGLMaxColorAttachments))
|
2013-06-21 23:44:17 +00:00
|
|
|
{
|
|
|
|
mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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
|
|
|
|
{
|
|
|
|
mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WebGLFramebuffer::EnsureColorAttachments(size_t colorAttachmentId) {
|
|
|
|
size_t currentAttachmentCount = mColorAttachments.Length();
|
|
|
|
|
|
|
|
if (mColorAttachments.Length() > colorAttachmentId) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-07-02 21:30:20 +00:00
|
|
|
MOZ_ASSERT( colorAttachmentId < WebGLContext::sMaxColorAttachments );
|
2013-06-21 23:44:17 +00:00
|
|
|
|
|
|
|
mColorAttachments.SetLength(colorAttachmentId + 1);
|
|
|
|
|
|
|
|
for (size_t i = colorAttachmentId; i >= currentAttachmentCount; i--) {
|
|
|
|
mColorAttachments[i].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0 + i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-02 00:30:05 +00:00
|
|
|
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);
|
|
|
|
|
2013-10-02 00:31:09 +00:00
|
|
|
if (DepthStencilAttachment().IsDefined())
|
|
|
|
DepthStencilAttachment().FinalizeAttachment(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
|
2013-10-02 00:30:05 +00:00
|
|
|
}
|
|
|
|
|
2013-06-21 23:44:17 +00:00
|
|
|
inline void
|
|
|
|
ImplCycleCollectionUnlink(mozilla::WebGLFramebuffer::Attachment& aField)
|
|
|
|
{
|
|
|
|
aField.mTexturePtr = nullptr;
|
|
|
|
aField.mRenderbufferPtr = nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline void
|
|
|
|
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& aCallback,
|
|
|
|
mozilla::WebGLFramebuffer::Attachment& aField,
|
|
|
|
const char* aName,
|
|
|
|
uint32_t aFlags = 0)
|
|
|
|
{
|
2013-08-29 15:39:17 +00:00
|
|
|
CycleCollectionNoteChild(aCallback, aField.mTexturePtr.get(),
|
|
|
|
aName, aFlags);
|
|
|
|
|
|
|
|
CycleCollectionNoteChild(aCallback, aField.mRenderbufferPtr.get(),
|
|
|
|
aName, aFlags);
|
2013-06-21 23:44:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_7(WebGLFramebuffer,
|
|
|
|
mColorAttachments,
|
2012-11-15 07:32:39 +00:00
|
|
|
mDepthAttachment.mTexturePtr,
|
|
|
|
mDepthAttachment.mRenderbufferPtr,
|
|
|
|
mStencilAttachment.mTexturePtr,
|
|
|
|
mStencilAttachment.mRenderbufferPtr,
|
|
|
|
mDepthStencilAttachment.mTexturePtr,
|
|
|
|
mDepthStencilAttachment.mRenderbufferPtr)
|
2012-10-04 20:35:54 +00:00
|
|
|
|
2013-08-29 15:39:17 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLFramebuffer, AddRef)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLFramebuffer, Release)
|