2012-10-05 00:35:54 +04: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 15:58:41 +04:00
|
|
|
|
#include "WebGLFramebuffer.h"
|
2013-06-22 03:44:17 +04:00
|
|
|
|
#include "WebGLExtensions.h"
|
2013-06-11 00:00:35 +04:00
|
|
|
|
#include "WebGLRenderbuffer.h"
|
|
|
|
|
#include "WebGLTexture.h"
|
2012-10-05 00:35:54 +04:00
|
|
|
|
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
2013-06-22 03:44:17 +04:00
|
|
|
|
#include "WebGLTexture.h"
|
|
|
|
|
#include "WebGLRenderbuffer.h"
|
2013-09-04 16:14:52 +04:00
|
|
|
|
#include "GLContext.h"
|
2014-01-23 07:59:34 +04:00
|
|
|
|
#include "WebGLContextUtils.h"
|
2012-10-05 00:35:54 +04:00
|
|
|
|
|
|
|
|
|
using namespace mozilla;
|
2013-10-02 04:30:05 +04:00
|
|
|
|
using namespace mozilla::gl;
|
2012-10-05 00:35:54 +04:00
|
|
|
|
|
|
|
|
|
JSObject*
|
2014-04-09 02:27:18 +04:00
|
|
|
|
WebGLFramebuffer::WrapObject(JSContext* cx)
|
2014-01-23 07:59:34 +04:00
|
|
|
|
{
|
Bug 991742 part 6. Remove the "aScope" argument of binding Wrap() methods. r=bholley
This patch was mostly generated with this command:
find . -name "*.h" -o -name "*.cpp" | xargs sed -e 's/Binding::Wrap(aCx, aScope, this/Binding::Wrap(aCx, this/' -e 's/Binding_workers::Wrap(aCx, aScope, this/Binding_workers::Wrap(aCx, this/' -e 's/Binding::Wrap(cx, scope, this/Binding::Wrap(cx, this/' -i ""
plus a few manual fixes to dom/bindings/Codegen.py, js/xpconnect/src/event_impl_gen.py, and a few C++ files that were not caught in the search-and-replace above.
2014-04-09 02:27:17 +04:00
|
|
|
|
return dom::WebGLFramebufferBinding::Wrap(cx, this);
|
2012-10-05 00:35:54 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::WebGLFramebuffer(WebGLContext* context)
|
2014-05-07 07:11:18 +04:00
|
|
|
|
: WebGLBindableName()
|
|
|
|
|
, WebGLContextBoundObject(context)
|
2014-03-04 11:14:35 +04:00
|
|
|
|
, mStatus(0)
|
2012-12-09 15:58:41 +04:00
|
|
|
|
, 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-22 03:44:17 +04:00
|
|
|
|
|
|
|
|
|
mColorAttachments.SetLength(1);
|
|
|
|
|
mColorAttachments[0].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0;
|
2012-12-09 15:58:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-07-30 23:52:07 +04:00
|
|
|
|
WebGLFramebuffer::Attachment::Attachment(GLenum aAttachmentPoint)
|
|
|
|
|
: mAttachmentPoint(aAttachmentPoint)
|
|
|
|
|
, mNeedsFinalize(false)
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
WebGLFramebuffer::Attachment::~Attachment()
|
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
WebGLFramebuffer::Attachment::Reset()
|
|
|
|
|
{
|
|
|
|
|
mTexturePtr = nullptr;
|
|
|
|
|
mRenderbufferPtr = nullptr;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-09 15:58:41 +04:00
|
|
|
|
bool
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::Attachment::IsDeleteRequested() const
|
|
|
|
|
{
|
2012-12-09 15:58:41 +04:00
|
|
|
|
return Texture() ? Texture()->IsDeleteRequested()
|
|
|
|
|
: Renderbuffer() ? Renderbuffer()->IsDeleteRequested()
|
|
|
|
|
: false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::Attachment::HasAlpha() const
|
|
|
|
|
{
|
2014-02-14 03:07:59 +04:00
|
|
|
|
MOZ_ASSERT(HasImage());
|
|
|
|
|
|
2013-09-04 16:14:43 +04:00
|
|
|
|
GLenum format = 0;
|
2013-10-02 04:30:38 +04:00
|
|
|
|
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
2014-05-02 07:15:58 +04:00
|
|
|
|
format = Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLFormat();
|
2012-12-09 15:58:41 +04:00
|
|
|
|
else if (Renderbuffer())
|
|
|
|
|
format = Renderbuffer()->InternalFormat();
|
2013-10-11 17:16:43 +04:00
|
|
|
|
return FormatHasAlpha(format);
|
2012-12-09 15:58:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-08 01:26:17 +04:00
|
|
|
|
bool
|
2014-07-21 19:17:00 +04:00
|
|
|
|
WebGLFramebuffer::Attachment::IsReadableFloat() const
|
2014-03-08 01:26:17 +04:00
|
|
|
|
{
|
2014-05-07 07:11:18 +04:00
|
|
|
|
const WebGLTexture* tex = Texture();
|
|
|
|
|
if (tex && tex->HasImageInfoAt(mTexImageTarget, mTexImageLevel)) {
|
|
|
|
|
GLenum type = tex->ImageInfoAt(mTexImageTarget, mTexImageLevel).WebGLType();
|
2014-03-08 01:26:17 +04:00
|
|
|
|
switch (type) {
|
|
|
|
|
case LOCAL_GL_FLOAT:
|
|
|
|
|
case LOCAL_GL_HALF_FLOAT_OES:
|
2014-07-21 19:17:00 +04:00
|
|
|
|
return true;
|
2014-03-08 01:26:17 +04:00
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-07 07:11:18 +04:00
|
|
|
|
const WebGLRenderbuffer* rb = Renderbuffer();
|
|
|
|
|
if (rb) {
|
|
|
|
|
GLenum format = rb->InternalFormat();
|
2014-03-08 01:26:17 +04:00
|
|
|
|
switch (format) {
|
|
|
|
|
case LOCAL_GL_RGB16F:
|
|
|
|
|
case LOCAL_GL_RGBA16F:
|
|
|
|
|
case LOCAL_GL_RGB32F:
|
|
|
|
|
case LOCAL_GL_RGBA32F:
|
2014-07-21 19:17:00 +04:00
|
|
|
|
return true;
|
2014-03-08 01:26:17 +04:00
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2014-05-07 07:11:18 +04:00
|
|
|
|
// If we arrive here Attachment isn't correct setup because it has
|
|
|
|
|
// no texture nor render buffer pointer.
|
2014-03-08 01:26:17 +04:00
|
|
|
|
MOZ_ASSERT(false, "Should not get here.");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-09 15:58:41 +04:00
|
|
|
|
void
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::Attachment::SetTexImage(WebGLTexture* tex, GLenum target, GLint level)
|
|
|
|
|
{
|
2012-12-09 15:58:41 +04:00
|
|
|
|
mTexturePtr = tex;
|
|
|
|
|
mRenderbufferPtr = nullptr;
|
2013-10-02 04:30:38 +04:00
|
|
|
|
mTexImageTarget = target;
|
|
|
|
|
mTexImageLevel = level;
|
2014-03-12 03:10:59 +04:00
|
|
|
|
|
|
|
|
|
mNeedsFinalize = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
WebGLFramebuffer::Attachment::SetRenderbuffer(WebGLRenderbuffer* rb)
|
|
|
|
|
{
|
|
|
|
|
mTexturePtr = nullptr;
|
|
|
|
|
mRenderbufferPtr = rb;
|
|
|
|
|
|
|
|
|
|
mNeedsFinalize = true;
|
2012-12-09 15:58:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::Attachment::HasUninitializedImageData() const
|
|
|
|
|
{
|
|
|
|
|
if (!HasImage())
|
2013-10-11 17:16:43 +04:00
|
|
|
|
return false;
|
2014-01-23 07:59:34 +04:00
|
|
|
|
|
|
|
|
|
if (Renderbuffer()) {
|
|
|
|
|
return Renderbuffer()->HasUninitializedImageData();
|
2014-02-14 03:07:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Texture()) {
|
2014-01-23 07:59:34 +04:00
|
|
|
|
MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
|
|
|
|
|
return Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel).HasUninitializedImageData();
|
2013-10-11 17:16:43 +04:00
|
|
|
|
}
|
2014-01-23 07:59:34 +04:00
|
|
|
|
|
|
|
|
|
MOZ_ASSERT(false, "Should not get here.");
|
|
|
|
|
return false;
|
2013-10-11 17:16:43 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::Attachment::SetImageDataStatus(WebGLImageDataStatus newStatus)
|
|
|
|
|
{
|
|
|
|
|
if (!HasImage())
|
|
|
|
|
return;
|
|
|
|
|
|
2014-02-14 03:07:59 +04:00
|
|
|
|
if (Renderbuffer()) {
|
|
|
|
|
Renderbuffer()->SetImageDataStatus(newStatus);
|
2014-01-23 07:59:34 +04:00
|
|
|
|
return;
|
2014-02-14 03:07:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Texture()) {
|
|
|
|
|
Texture()->SetImageDataStatus(mTexImageTarget, mTexImageLevel, newStatus);
|
2014-01-23 07:59:34 +04:00
|
|
|
|
return;
|
2013-10-11 17:16:43 +04:00
|
|
|
|
}
|
2014-01-23 07:59:34 +04:00
|
|
|
|
|
|
|
|
|
MOZ_ASSERT(false, "Should not get here.");
|
2012-12-09 15:58:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
bool
|
|
|
|
|
WebGLFramebuffer::Attachment::HasImage() const
|
|
|
|
|
{
|
2013-10-02 04:30:38 +04:00
|
|
|
|
if (Texture() && Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel))
|
2014-01-23 07:59:34 +04:00
|
|
|
|
return true;
|
2014-02-14 03:07:59 +04:00
|
|
|
|
|
|
|
|
|
if (Renderbuffer())
|
2014-01-23 07:59:34 +04:00
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
2012-12-09 15:58:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
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);
|
2014-02-14 03:07:59 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Renderbuffer()) {
|
2014-01-23 07:59:34 +04:00
|
|
|
|
return *Renderbuffer();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
MOZ_CRASH("Should not get here.");
|
2012-12-09 15:58:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-01-24 10:28:47 +04:00
|
|
|
|
/* The following IsValidFBOTextureXXX functions check the internal
|
|
|
|
|
format that is used by GL or GL ES texture formats. This
|
|
|
|
|
corresponds to the state that is stored in
|
|
|
|
|
WebGLTexture::ImageInfo::InternalFormat()*/
|
2013-11-05 01:05:04 +04:00
|
|
|
|
static inline bool
|
2014-01-24 07:53:53 +04:00
|
|
|
|
IsValidFBOTextureColorFormat(GLenum internalFormat)
|
2014-01-23 07:59:34 +04:00
|
|
|
|
{
|
2014-01-24 01:47:37 +04:00
|
|
|
|
/* These formats are internal formats for each texture -- the actual
|
|
|
|
|
* low level format, which we might have to do conversions for when
|
|
|
|
|
* running against desktop GL (e.g. GL_RGBA + GL_FLOAT -> GL_RGBA32F).
|
|
|
|
|
*
|
|
|
|
|
* This function just handles all of them whether desktop GL or ES.
|
|
|
|
|
*/
|
|
|
|
|
|
2013-11-05 01:05:04 +04:00
|
|
|
|
return (
|
|
|
|
|
/* linear 8-bit formats */
|
2014-01-24 07:53:53 +04:00
|
|
|
|
internalFormat == LOCAL_GL_ALPHA ||
|
|
|
|
|
internalFormat == LOCAL_GL_LUMINANCE ||
|
|
|
|
|
internalFormat == LOCAL_GL_LUMINANCE_ALPHA ||
|
|
|
|
|
internalFormat == LOCAL_GL_RGB ||
|
|
|
|
|
internalFormat == LOCAL_GL_RGBA ||
|
2013-11-05 01:05:04 +04:00
|
|
|
|
/* sRGB 8-bit formats */
|
2014-01-24 07:53:53 +04:00
|
|
|
|
internalFormat == LOCAL_GL_SRGB_EXT ||
|
|
|
|
|
internalFormat == LOCAL_GL_SRGB_ALPHA_EXT ||
|
2013-11-05 01:05:04 +04:00
|
|
|
|
/* linear float32 formats */
|
2014-01-24 07:53:53 +04:00
|
|
|
|
internalFormat == LOCAL_GL_ALPHA32F_ARB ||
|
|
|
|
|
internalFormat == LOCAL_GL_LUMINANCE32F_ARB ||
|
|
|
|
|
internalFormat == LOCAL_GL_LUMINANCE_ALPHA32F_ARB ||
|
|
|
|
|
internalFormat == LOCAL_GL_RGB32F_ARB ||
|
2014-01-24 01:47:37 +04:00
|
|
|
|
internalFormat == LOCAL_GL_RGBA32F_ARB ||
|
|
|
|
|
/* texture_half_float formats */
|
|
|
|
|
internalFormat == LOCAL_GL_ALPHA16F_ARB ||
|
|
|
|
|
internalFormat == LOCAL_GL_LUMINANCE16F_ARB ||
|
|
|
|
|
internalFormat == LOCAL_GL_LUMINANCE_ALPHA16F_ARB ||
|
|
|
|
|
internalFormat == LOCAL_GL_RGB16F_ARB ||
|
|
|
|
|
internalFormat == LOCAL_GL_RGBA16F_ARB
|
|
|
|
|
);
|
2014-01-24 07:53:53 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool
|
2014-01-24 10:28:47 +04:00
|
|
|
|
IsValidFBOTextureDepthFormat(GLenum internalFormat)
|
|
|
|
|
{
|
2014-01-24 07:53:53 +04:00
|
|
|
|
return (
|
|
|
|
|
internalFormat == LOCAL_GL_DEPTH_COMPONENT ||
|
|
|
|
|
internalFormat == LOCAL_GL_DEPTH_COMPONENT16 ||
|
|
|
|
|
internalFormat == LOCAL_GL_DEPTH_COMPONENT32);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool
|
2014-01-24 10:28:47 +04:00
|
|
|
|
IsValidFBOTextureDepthStencilFormat(GLenum internalFormat)
|
|
|
|
|
{
|
2014-01-24 07:53:53 +04:00
|
|
|
|
return (
|
|
|
|
|
internalFormat == LOCAL_GL_DEPTH_STENCIL ||
|
|
|
|
|
internalFormat == LOCAL_GL_DEPTH24_STENCIL8);
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-24 10:28:47 +04:00
|
|
|
|
/* The following IsValidFBORenderbufferXXX functions check the internal
|
|
|
|
|
format that is stored by WebGLRenderbuffer::InternalFormat(). Valid
|
|
|
|
|
values can be found in WebGLContext::RenderbufferStorage. */
|
2014-01-24 07:53:53 +04:00
|
|
|
|
static inline bool
|
2014-01-24 10:28:47 +04:00
|
|
|
|
IsValidFBORenderbufferColorFormat(GLenum internalFormat)
|
|
|
|
|
{
|
2014-01-24 07:53:53 +04:00
|
|
|
|
return (
|
|
|
|
|
internalFormat == LOCAL_GL_RGB565 ||
|
|
|
|
|
internalFormat == LOCAL_GL_RGB5_A1 ||
|
|
|
|
|
internalFormat == LOCAL_GL_RGBA4 ||
|
|
|
|
|
internalFormat == LOCAL_GL_SRGB8_ALPHA8_EXT);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool
|
2014-01-24 10:28:47 +04:00
|
|
|
|
IsValidFBORenderbufferDepthFormat(GLenum internalFormat)
|
|
|
|
|
{
|
2014-01-24 07:53:53 +04:00
|
|
|
|
return internalFormat == LOCAL_GL_DEPTH_COMPONENT16;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool
|
2014-01-24 10:28:47 +04:00
|
|
|
|
IsValidFBORenderbufferDepthStencilFormat(GLenum internalFormat)
|
|
|
|
|
{
|
|
|
|
|
return internalFormat == LOCAL_GL_DEPTH_STENCIL;
|
2014-01-24 07:53:53 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool
|
2014-01-24 10:28:47 +04:00
|
|
|
|
IsValidFBORenderbufferStencilFormat(GLenum internalFormat)
|
|
|
|
|
{
|
2014-01-24 07:53:53 +04:00
|
|
|
|
return internalFormat == LOCAL_GL_STENCIL_INDEX8;
|
2013-11-05 01:05:04 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-09 15:58:41 +04:00
|
|
|
|
bool
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::Attachment::IsComplete() const
|
|
|
|
|
{
|
|
|
|
|
if (!HasImage())
|
|
|
|
|
return false;
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
const WebGLRectangleObject& rect = RectangleObject();
|
|
|
|
|
|
|
|
|
|
if (!rect.Width() ||
|
|
|
|
|
!rect.Height())
|
|
|
|
|
{
|
2012-12-09 15:58:41 +04:00
|
|
|
|
return false;
|
2014-01-23 07:59:34 +04:00
|
|
|
|
}
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
2014-02-14 03:07:59 +04:00
|
|
|
|
if (Texture()) {
|
|
|
|
|
MOZ_ASSERT(Texture()->HasImageInfoAt(mTexImageTarget, mTexImageLevel));
|
2014-01-24 07:53:53 +04:00
|
|
|
|
const WebGLTexture::ImageInfo& imageInfo =
|
2014-02-14 03:07:59 +04:00
|
|
|
|
Texture()->ImageInfoAt(mTexImageTarget, mTexImageLevel);
|
2014-05-02 07:15:58 +04:00
|
|
|
|
GLenum webGLFormat = imageInfo.WebGLFormat();
|
2014-01-24 07:53:53 +04:00
|
|
|
|
|
|
|
|
|
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT)
|
2014-05-02 07:15:58 +04:00
|
|
|
|
return IsValidFBOTextureDepthFormat(webGLFormat);
|
2014-01-24 07:53:53 +04:00
|
|
|
|
|
|
|
|
|
if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
|
2014-05-02 07:15:58 +04:00
|
|
|
|
return IsValidFBOTextureDepthStencilFormat(webGLFormat);
|
2014-01-24 07:53:53 +04:00
|
|
|
|
|
|
|
|
|
if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
|
|
|
|
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 +
|
2014-05-01 01:30:23 +04:00
|
|
|
|
WebGLContext::kMaxColorAttachments))
|
2014-01-23 07:59:34 +04:00
|
|
|
|
{
|
2014-05-02 07:15:58 +04:00
|
|
|
|
return IsValidFBOTextureColorFormat(webGLFormat);
|
2013-06-22 03:44:17 +04:00
|
|
|
|
}
|
2014-01-23 07:59:34 +04:00
|
|
|
|
MOZ_ASSERT(false, "Invalid WebGL attachment point?");
|
|
|
|
|
return false;
|
2012-12-09 15:58:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-02-14 03:07:59 +04:00
|
|
|
|
if (Renderbuffer()) {
|
|
|
|
|
GLenum internalFormat = Renderbuffer()->InternalFormat();
|
2014-01-24 07:53:53 +04:00
|
|
|
|
|
|
|
|
|
if (mAttachmentPoint == LOCAL_GL_DEPTH_ATTACHMENT)
|
|
|
|
|
return IsValidFBORenderbufferDepthFormat(internalFormat);
|
|
|
|
|
|
|
|
|
|
if (mAttachmentPoint == LOCAL_GL_STENCIL_ATTACHMENT)
|
|
|
|
|
return IsValidFBORenderbufferStencilFormat(internalFormat);
|
|
|
|
|
|
|
|
|
|
if (mAttachmentPoint == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
|
|
|
|
|
return IsValidFBORenderbufferDepthStencilFormat(internalFormat);
|
|
|
|
|
|
|
|
|
|
if (mAttachmentPoint >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
|
|
|
|
mAttachmentPoint < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 +
|
2014-05-01 01:30:23 +04:00
|
|
|
|
WebGLContext::kMaxColorAttachments))
|
2014-01-23 07:59:34 +04:00
|
|
|
|
{
|
2014-01-24 07:53:53 +04:00
|
|
|
|
return IsValidFBORenderbufferColorFormat(internalFormat);
|
2013-06-22 03:44:17 +04:00
|
|
|
|
}
|
2014-01-23 07:59:34 +04:00
|
|
|
|
MOZ_ASSERT(false, "Invalid WebGL attachment point?");
|
|
|
|
|
return false;
|
2012-12-09 15:58:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
MOZ_ASSERT(false, "Should not get here.");
|
2012-12-09 15:58:41 +04:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-02 04:30:05 +04:00
|
|
|
|
void
|
2014-03-12 03:10:59 +04:00
|
|
|
|
WebGLFramebuffer::Attachment::FinalizeAttachment(GLContext* gl, GLenum attachmentLoc) const
|
2014-01-23 07:59:34 +04:00
|
|
|
|
{
|
2014-03-12 03:10:59 +04:00
|
|
|
|
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,
|
|
|
|
|
LOCAL_GL_RENDERBUFFER, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-01-23 07:59:34 +04:00
|
|
|
|
MOZ_ASSERT(HasImage());
|
|
|
|
|
|
2013-10-02 04:30:05 +04:00
|
|
|
|
if (Texture()) {
|
2014-03-12 03:10:59 +04:00
|
|
|
|
MOZ_ASSERT(gl == Texture()->Context()->gl);
|
|
|
|
|
|
2013-10-02 04:31:09 +04: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 04:30:05 +04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (Renderbuffer()) {
|
2013-10-02 04:31:09 +04:00
|
|
|
|
Renderbuffer()->FramebufferRenderbuffer(attachmentLoc);
|
2013-10-02 04:30:05 +04:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
MOZ_ASSERT(false, "Should not get here.");
|
2013-10-02 04:30:05 +04:00
|
|
|
|
}
|
|
|
|
|
|
2012-12-09 15:58:41 +04:00
|
|
|
|
void
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::Delete()
|
|
|
|
|
{
|
2014-06-24 11:15:44 +04:00
|
|
|
|
DetachAllAttachments();
|
2013-06-22 03:44:17 +04:00
|
|
|
|
mColorAttachments.Clear();
|
2012-12-09 15:58:41 +04:00
|
|
|
|
mDepthAttachment.Reset();
|
|
|
|
|
mStencilAttachment.Reset();
|
|
|
|
|
mDepthStencilAttachment.Reset();
|
2014-01-23 07:59:34 +04:00
|
|
|
|
|
2012-12-09 15:58:41 +04:00
|
|
|
|
mContext->MakeContextCurrent();
|
|
|
|
|
mContext->gl->fDeleteFramebuffers(1, &mGLName);
|
|
|
|
|
LinkedListElement<WebGLFramebuffer>::removeFrom(mContext->mFramebuffers);
|
|
|
|
|
}
|
|
|
|
|
|
2014-06-24 11:15:44 +04:00
|
|
|
|
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()
|
|
|
|
|
{
|
|
|
|
|
size_t count = mColorAttachments.Length();
|
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
|
|
|
|
DetachAttachment(mColorAttachments[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
DetachAttachment(mDepthAttachment);
|
|
|
|
|
DetachAttachment(mStencilAttachment);
|
|
|
|
|
DetachAttachment(mDepthStencilAttachment);
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-09 15:58:41 +04:00
|
|
|
|
void
|
2013-09-04 16:14:43 +04:00
|
|
|
|
WebGLFramebuffer::FramebufferRenderbuffer(GLenum target,
|
2014-01-23 07:59:34 +04:00
|
|
|
|
GLenum attachment,
|
|
|
|
|
GLenum rbtarget,
|
|
|
|
|
WebGLRenderbuffer* wrb)
|
2012-12-09 15:58:41 +04:00
|
|
|
|
{
|
2013-06-22 03:42:32 +04:00
|
|
|
|
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
2014-03-04 11:14:35 +04:00
|
|
|
|
|
2012-12-09 15:58:41 +04: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);
|
|
|
|
|
|
2014-03-04 11:14:35 +04:00
|
|
|
|
/* 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* a = GetAttachmentOrNull(attachment);
|
|
|
|
|
if (!a)
|
|
|
|
|
return; // Error generated internally to GetAttachmentOrNull.
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
2014-03-04 11:14:35 +04:00
|
|
|
|
/* Invalidate cached framebuffer status and inform texture of it's
|
|
|
|
|
* new attachment
|
|
|
|
|
*/
|
|
|
|
|
mStatus = 0;
|
|
|
|
|
// Detach current
|
|
|
|
|
if (a->Texture())
|
|
|
|
|
a->Texture()->DetachFrom(this, attachment);
|
|
|
|
|
else if (a->Renderbuffer())
|
|
|
|
|
a->Renderbuffer()->DetachFrom(this, attachment);
|
|
|
|
|
|
|
|
|
|
// Attach new
|
|
|
|
|
if (wrb)
|
|
|
|
|
wrb->AttachTo(this, attachment);
|
|
|
|
|
|
|
|
|
|
a->SetRenderbuffer(wrb);
|
2012-12-09 15:58:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2013-09-04 16:14:43 +04:00
|
|
|
|
WebGLFramebuffer::FramebufferTexture2D(GLenum target,
|
2014-01-23 07:59:34 +04:00
|
|
|
|
GLenum attachment,
|
|
|
|
|
GLenum textarget,
|
|
|
|
|
WebGLTexture* wtex,
|
|
|
|
|
GLint level)
|
2012-12-09 15:58:41 +04:00
|
|
|
|
{
|
2013-06-22 03:42:32 +04:00
|
|
|
|
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
2014-03-04 11:14:35 +04:00
|
|
|
|
|
|
|
|
|
if (!mContext->ValidateObjectAllowNull("framebufferTexture2D: texture", wtex))
|
2012-12-09 15:58:41 +04:00
|
|
|
|
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))
|
2014-01-23 07:59:34 +04:00
|
|
|
|
{
|
2012-12-09 15:58:41 +04:00
|
|
|
|
return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: invalid texture target", textarget);
|
2014-01-23 07:59:34 +04:00
|
|
|
|
}
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
2013-10-31 21:01:41 +04:00
|
|
|
|
if (wtex) {
|
|
|
|
|
bool isTexture2D = wtex->Target() == LOCAL_GL_TEXTURE_2D;
|
|
|
|
|
bool isTexTarget2D = textarget == LOCAL_GL_TEXTURE_2D;
|
|
|
|
|
if (isTexture2D != isTexTarget2D) {
|
|
|
|
|
return mContext->ErrorInvalidOperation("framebufferTexture2D: mismatched texture and texture target");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-09 15:58:41 +04:00
|
|
|
|
if (level != 0)
|
|
|
|
|
return mContext->ErrorInvalidValue("framebufferTexture2D: level must be 0");
|
|
|
|
|
|
2014-03-04 11:14:35 +04:00
|
|
|
|
/* 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* a = GetAttachmentOrNull(attachment);
|
|
|
|
|
if (!a)
|
|
|
|
|
return; // Error generated internally to GetAttachmentOrNull.
|
|
|
|
|
|
|
|
|
|
/* Invalidate cached framebuffer status and inform texture of it's
|
|
|
|
|
* new attachment
|
|
|
|
|
*/
|
|
|
|
|
mStatus = 0;
|
|
|
|
|
// Detach current
|
|
|
|
|
if (a->Texture())
|
|
|
|
|
a->Texture()->DetachFrom(this, attachment);
|
|
|
|
|
else if (a->Renderbuffer())
|
|
|
|
|
a->Renderbuffer()->DetachFrom(this, attachment);
|
|
|
|
|
|
|
|
|
|
// Attach new
|
|
|
|
|
if (wtex)
|
|
|
|
|
wtex->AttachTo(this, attachment);
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
2014-03-04 11:14:35 +04:00
|
|
|
|
a->SetTexImage(wtex, textarget, level);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
WebGLFramebuffer::Attachment*
|
|
|
|
|
WebGLFramebuffer::GetAttachmentOrNull(GLenum attachment)
|
|
|
|
|
{
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
if (!CheckColorAttachmentNumber(attachment, "getAttachmentOrNull"))
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
size_t colorAttachmentId = attachment - LOCAL_GL_COLOR_ATTACHMENT0;
|
|
|
|
|
EnsureColorAttachments(colorAttachmentId);
|
|
|
|
|
|
|
|
|
|
return &mColorAttachments[colorAttachmentId];
|
2012-12-09 15:58:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const WebGLFramebuffer::Attachment&
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::GetAttachment(GLenum attachment) const
|
|
|
|
|
{
|
2012-12-09 15:58:41 +04: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;
|
|
|
|
|
|
2014-01-24 07:59:33 +04:00
|
|
|
|
if (!CheckColorAttachmentNumber(attachment, "getAttachment")) {
|
2013-10-11 17:16:43 +04:00
|
|
|
|
MOZ_ASSERT(false);
|
2013-07-03 01:30:20 +04:00
|
|
|
|
return mColorAttachments[0];
|
|
|
|
|
}
|
2013-06-22 03:44:17 +04:00
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
size_t colorAttachmentId = attachment - LOCAL_GL_COLOR_ATTACHMENT0;
|
2013-06-22 03:44:17 +04:00
|
|
|
|
if (colorAttachmentId >= mColorAttachments.Length()) {
|
2013-10-11 17:16:43 +04:00
|
|
|
|
MOZ_ASSERT(false);
|
2013-06-22 03:44:17 +04:00
|
|
|
|
return mColorAttachments[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return mColorAttachments[colorAttachmentId];
|
2012-12-09 15:58:41 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::DetachTexture(const WebGLTexture* tex)
|
|
|
|
|
{
|
2014-02-14 03:07:59 +04:00
|
|
|
|
size_t count = mColorAttachments.Length();
|
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
2013-06-22 03:44:17 +04:00
|
|
|
|
if (mColorAttachments[i].Texture() == tex) {
|
2014-06-26 02:23:36 +04:00
|
|
|
|
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_TEXTURE_2D, nullptr, 0);
|
2013-06-22 03:44:17 +04:00
|
|
|
|
// a texture might be attached more that once while editing the framebuffer
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-09 15:58:41 +04: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
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::DetachRenderbuffer(const WebGLRenderbuffer* rb)
|
|
|
|
|
{
|
2014-02-14 03:07:59 +04:00
|
|
|
|
size_t count = mColorAttachments.Length();
|
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
2014-06-26 02:23:36 +04:00
|
|
|
|
if (mColorAttachments[i].Renderbuffer() == rb) {
|
|
|
|
|
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0+i, LOCAL_GL_RENDERBUFFER, nullptr);
|
2013-06-22 03:44:17 +04:00
|
|
|
|
// a renderbuffer might be attached more that once while editing the framebuffer
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-12-09 15:58:41 +04: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
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::HasDefinedAttachments() const
|
|
|
|
|
{
|
|
|
|
|
bool hasAttachments = false;
|
|
|
|
|
|
2014-02-14 03:07:59 +04:00
|
|
|
|
size_t count = mColorAttachments.Length();
|
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
2014-01-23 07:59:34 +04:00
|
|
|
|
hasAttachments |= mColorAttachments[i].IsDefined();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hasAttachments |= mDepthAttachment.IsDefined();
|
|
|
|
|
hasAttachments |= mStencilAttachment.IsDefined();
|
|
|
|
|
hasAttachments |= mDepthStencilAttachment.IsDefined();
|
|
|
|
|
|
|
|
|
|
return hasAttachments;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
IsIncomplete(const WebGLFramebuffer::Attachment& cur)
|
|
|
|
|
{
|
2014-02-14 03:07:59 +04:00
|
|
|
|
return cur.IsDefined() && !cur.IsComplete();
|
2014-01-23 07:59:34 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
WebGLFramebuffer::HasIncompleteAttachments() const
|
|
|
|
|
{
|
|
|
|
|
bool hasIncomplete = false;
|
|
|
|
|
|
2014-02-14 03:07:59 +04:00
|
|
|
|
size_t count = mColorAttachments.Length();
|
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
2014-01-23 07:59:34 +04:00
|
|
|
|
hasIncomplete |= IsIncomplete(mColorAttachments[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hasIncomplete |= IsIncomplete(mDepthAttachment);
|
|
|
|
|
hasIncomplete |= IsIncomplete(mStencilAttachment);
|
|
|
|
|
hasIncomplete |= IsIncomplete(mDepthStencilAttachment);
|
|
|
|
|
|
|
|
|
|
return hasIncomplete;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const WebGLRectangleObject&
|
|
|
|
|
WebGLFramebuffer::GetAnyRectObject() const
|
|
|
|
|
{
|
|
|
|
|
MOZ_ASSERT(HasDefinedAttachments());
|
|
|
|
|
|
2014-02-14 03:07:59 +04:00
|
|
|
|
size_t count = mColorAttachments.Length();
|
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
2014-01-23 07:59:34 +04:00
|
|
|
|
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;
|
|
|
|
|
|
2014-02-14 03:07:59 +04:00
|
|
|
|
size_t count = mColorAttachments.Length();
|
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
2014-01-23 07:59:34 +04:00
|
|
|
|
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
|
2012-12-09 15:58:41 +04:00
|
|
|
|
{
|
2013-06-22 03:42:32 +04:00
|
|
|
|
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
2014-01-23 07:59:34 +04:00
|
|
|
|
|
|
|
|
|
if (!HasDefinedAttachments())
|
|
|
|
|
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; // No attachments
|
|
|
|
|
|
|
|
|
|
if (HasIncompleteAttachments())
|
|
|
|
|
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
|
|
|
|
|
|
|
|
|
if (!AllImageRectsMatch())
|
2014-02-14 03:07:59 +04:00
|
|
|
|
return LOCAL_GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; // Inconsistent sizes
|
2014-01-23 07:59:34 +04:00
|
|
|
|
|
2012-12-09 15:58:41 +04:00
|
|
|
|
if (HasDepthStencilConflict())
|
2014-01-23 07:59:34 +04:00
|
|
|
|
return LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
return LOCAL_GL_FRAMEBUFFER_COMPLETE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GLenum
|
|
|
|
|
WebGLFramebuffer::CheckFramebufferStatus() const
|
|
|
|
|
{
|
2014-03-04 11:14:35 +04:00
|
|
|
|
if (mStatus != 0)
|
|
|
|
|
return mStatus;
|
|
|
|
|
|
|
|
|
|
mStatus = PrecheckFramebufferStatus();
|
|
|
|
|
if (mStatus != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
|
|
|
|
return mStatus;
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
// Looks good on our end. Let's ask the driver.
|
2013-10-02 04:31:37 +04:00
|
|
|
|
mContext->MakeContextCurrent();
|
|
|
|
|
|
|
|
|
|
// Ok, attach our chosen flavor of {DEPTH, STENCIL, DEPTH_STENCIL}.
|
|
|
|
|
FinalizeAttachments();
|
|
|
|
|
|
2014-03-04 11:14:35 +04:00
|
|
|
|
mStatus = mContext->gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
|
|
|
|
return mStatus;
|
2014-01-23 07:59:34 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-01 06:51:43 +04:00
|
|
|
|
bool
|
|
|
|
|
WebGLFramebuffer::HasCompletePlanes(GLbitfield mask)
|
|
|
|
|
{
|
|
|
|
|
if (CheckFramebufferStatus() != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
MOZ_ASSERT(mContext->mBoundFramebuffer == this);
|
|
|
|
|
bool hasPlanes = true;
|
|
|
|
|
if (mask & LOCAL_GL_COLOR_BUFFER_BIT) {
|
|
|
|
|
hasPlanes &= ColorAttachmentCount() &&
|
|
|
|
|
ColorAttachment(0).IsDefined();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mask & LOCAL_GL_DEPTH_BUFFER_BIT) {
|
|
|
|
|
hasPlanes &= DepthAttachment().IsDefined() ||
|
|
|
|
|
DepthStencilAttachment().IsDefined();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mask & LOCAL_GL_STENCIL_BUFFER_BIT) {
|
|
|
|
|
hasPlanes &= StencilAttachment().IsDefined() ||
|
|
|
|
|
DepthStencilAttachment().IsDefined();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return hasPlanes;
|
|
|
|
|
}
|
2014-01-23 07:59:34 +04:00
|
|
|
|
|
|
|
|
|
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.
|
2014-02-14 03:07:59 +04:00
|
|
|
|
size_t colorAttachmentCount = mColorAttachments.Length();
|
2013-06-22 03:44:17 +04:00
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
// Check if we need to initialize anything
|
2013-06-22 03:44:17 +04:00
|
|
|
|
{
|
2014-01-23 07:59:34 +04:00
|
|
|
|
bool hasUninitializedAttachments = false;
|
2013-06-22 03:44:17 +04:00
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < colorAttachmentCount; i++) {
|
2014-01-23 07:59:34 +04:00
|
|
|
|
if (mColorAttachments[i].HasImage())
|
|
|
|
|
hasUninitializedAttachments |= mColorAttachments[i].HasUninitializedImageData();
|
2013-06-22 03:44:17 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
if (mDepthAttachment.HasImage())
|
|
|
|
|
hasUninitializedAttachments |= mDepthAttachment.HasUninitializedImageData();
|
|
|
|
|
if (mStencilAttachment.HasImage())
|
|
|
|
|
hasUninitializedAttachments |= mStencilAttachment.HasUninitializedImageData();
|
|
|
|
|
if (mDepthStencilAttachment.HasImage())
|
|
|
|
|
hasUninitializedAttachments |= mDepthStencilAttachment.HasUninitializedImageData();
|
|
|
|
|
|
|
|
|
|
if (!hasUninitializedAttachments)
|
2013-06-22 03:44:17 +04:00
|
|
|
|
return true;
|
|
|
|
|
}
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
// Get buffer-bit-mask and color-attachment-mask-list
|
2012-12-09 15:58:41 +04:00
|
|
|
|
uint32_t mask = 0;
|
2014-05-01 01:30:23 +04:00
|
|
|
|
bool colorAttachmentsMask[WebGLContext::kMaxColorAttachments] = { false };
|
|
|
|
|
MOZ_ASSERT(colorAttachmentCount <= WebGLContext::kMaxColorAttachments);
|
2013-06-22 03:44:17 +04:00
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
for (size_t i = 0; i < colorAttachmentCount; i++) {
|
|
|
|
|
if (mColorAttachments[i].HasUninitializedImageData()) {
|
|
|
|
|
colorAttachmentsMask[i] = true;
|
|
|
|
|
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
|
2013-06-22 03:44:17 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
2013-10-11 17:16:43 +04:00
|
|
|
|
if (mDepthAttachment.HasUninitializedImageData() ||
|
|
|
|
|
mDepthStencilAttachment.HasUninitializedImageData())
|
2012-12-09 15:58:41 +04:00
|
|
|
|
{
|
|
|
|
|
mask |= LOCAL_GL_DEPTH_BUFFER_BIT;
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-11 17:16:43 +04:00
|
|
|
|
if (mStencilAttachment.HasUninitializedImageData() ||
|
|
|
|
|
mDepthStencilAttachment.HasUninitializedImageData())
|
2012-12-09 15:58:41 +04:00
|
|
|
|
{
|
|
|
|
|
mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
// Clear!
|
2013-06-22 03:44:17 +04:00
|
|
|
|
mContext->ForceClearFramebufferWithDefaultValues(mask, colorAttachmentsMask);
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
// Mark all the uninitialized images as initialized.
|
|
|
|
|
for (size_t i = 0; i < colorAttachmentCount; i++) {
|
2013-10-11 17:16:43 +04:00
|
|
|
|
if (mColorAttachments[i].HasUninitializedImageData())
|
|
|
|
|
mColorAttachments[i].SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
|
2013-06-22 03:44:17 +04:00
|
|
|
|
}
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
2013-10-11 17:16:43 +04:00
|
|
|
|
if (mDepthAttachment.HasUninitializedImageData())
|
|
|
|
|
mDepthAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
|
|
|
|
|
if (mStencilAttachment.HasUninitializedImageData())
|
|
|
|
|
mStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
|
|
|
|
|
if (mDepthStencilAttachment.HasUninitializedImageData())
|
|
|
|
|
mDepthStencilAttachment.SetImageDataStatus(WebGLImageDataStatus::InitializedImageData);
|
2012-12-09 15:58:41 +04:00
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-24 07:59:33 +04:00
|
|
|
|
bool WebGLFramebuffer::CheckColorAttachmentNumber(GLenum attachment, const char* functionName) const
|
2013-06-22 03:44:17 +04:00
|
|
|
|
{
|
|
|
|
|
const char* const errorFormating = "%s: attachment: invalid enum value 0x%x";
|
|
|
|
|
|
2014-04-26 06:34:07 +04:00
|
|
|
|
if (mContext->IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers)) {
|
2013-06-22 03:44:17 +04:00
|
|
|
|
if (attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
|
2013-12-07 13:23:33 +04:00
|
|
|
|
attachment >= GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + mContext->mGLMaxColorAttachments))
|
2013-06-22 03:44:17 +04:00
|
|
|
|
{
|
|
|
|
|
mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2014-01-23 07:59:34 +04:00
|
|
|
|
} else if (attachment != LOCAL_GL_COLOR_ATTACHMENT0) {
|
2013-06-22 03:44:17 +04:00
|
|
|
|
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;
|
2014-01-23 07:59:34 +04:00
|
|
|
|
} else {
|
2013-06-22 03:44:17 +04:00
|
|
|
|
mContext->ErrorInvalidEnum(errorFormating, functionName, attachment);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
void WebGLFramebuffer::EnsureColorAttachments(size_t colorAttachmentId)
|
|
|
|
|
{
|
2014-05-01 01:30:23 +04:00
|
|
|
|
MOZ_ASSERT(colorAttachmentId < WebGLContext::kMaxColorAttachments);
|
2013-06-22 03:44:17 +04:00
|
|
|
|
|
2014-01-23 07:59:34 +04:00
|
|
|
|
size_t currentAttachmentCount = mColorAttachments.Length();
|
|
|
|
|
if (colorAttachmentId < currentAttachmentCount)
|
2013-06-22 03:44:17 +04:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
mColorAttachments.SetLength(colorAttachmentId + 1);
|
|
|
|
|
|
|
|
|
|
for (size_t i = colorAttachmentId; i >= currentAttachmentCount; i--) {
|
|
|
|
|
mColorAttachments[i].mAttachmentPoint = LOCAL_GL_COLOR_ATTACHMENT0 + i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-03-04 11:14:35 +04:00
|
|
|
|
void
|
|
|
|
|
WebGLFramebuffer::NotifyAttachableChanged() const
|
|
|
|
|
{
|
|
|
|
|
// Attachment has changed, so invalidate cached status
|
|
|
|
|
mStatus = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2014-01-24 08:02:07 +04:00
|
|
|
|
static void
|
|
|
|
|
FinalizeDrawAndReadBuffers(GLContext* aGL, bool aColorBufferDefined)
|
|
|
|
|
{
|
|
|
|
|
MOZ_ASSERT(aGL, "Expected a valid GLContext ptr.");
|
|
|
|
|
// GLES don't support DrawBuffer()/ReadBuffer.
|
|
|
|
|
// According to http://www.opengl.org/wiki/Framebuffer_Object
|
|
|
|
|
//
|
|
|
|
|
// Each draw buffers must either specify color attachment points that have images
|
|
|
|
|
// attached or must be GL_NONE. (GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER when false).
|
|
|
|
|
//
|
|
|
|
|
// If the read buffer is set, then it must specify an attachment point that has an
|
|
|
|
|
// image attached. (GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER when false).
|
|
|
|
|
//
|
|
|
|
|
// Note that this test is not performed if OpenGL 4.2 or ARB_ES2_compatibility is
|
|
|
|
|
// available.
|
2014-03-31 13:10:49 +04:00
|
|
|
|
if (aGL->IsGLES() ||
|
2014-01-24 08:02:07 +04:00
|
|
|
|
aGL->IsSupported(GLFeature::ES2_compatibility) ||
|
|
|
|
|
aGL->IsAtLeast(ContextProfile::OpenGL, 420))
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// TODO(djg): Assert that fDrawBuffer/fReadBuffer is not NULL.
|
|
|
|
|
GLenum colorBufferSource = aColorBufferDefined ? LOCAL_GL_COLOR_ATTACHMENT0 : LOCAL_GL_NONE;
|
|
|
|
|
aGL->fDrawBuffer(colorBufferSource);
|
|
|
|
|
aGL->fReadBuffer(colorBufferSource);
|
|
|
|
|
}
|
|
|
|
|
|
2013-10-02 04:30:05 +04:00
|
|
|
|
void
|
2014-01-23 07:59:34 +04:00
|
|
|
|
WebGLFramebuffer::FinalizeAttachments() const
|
|
|
|
|
{
|
2014-03-12 03:10:59 +04:00
|
|
|
|
GLContext* gl = mContext->gl;
|
|
|
|
|
|
2014-02-14 03:07:59 +04:00
|
|
|
|
size_t count = ColorAttachmentCount();
|
|
|
|
|
for (size_t i = 0; i < count; i++) {
|
2014-03-12 03:10:59 +04:00
|
|
|
|
ColorAttachment(i).FinalizeAttachment(gl, LOCAL_GL_COLOR_ATTACHMENT0 + i);
|
2013-10-02 04:30:05 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-03-12 03:10:59 +04:00
|
|
|
|
DepthAttachment().FinalizeAttachment(gl, LOCAL_GL_DEPTH_ATTACHMENT);
|
|
|
|
|
StencilAttachment().FinalizeAttachment(gl, LOCAL_GL_STENCIL_ATTACHMENT);
|
|
|
|
|
DepthStencilAttachment().FinalizeAttachment(gl, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT);
|
2014-01-24 08:02:07 +04:00
|
|
|
|
|
2014-03-12 03:10:59 +04:00
|
|
|
|
FinalizeDrawAndReadBuffers(gl, ColorAttachment(0).IsDefined());
|
2013-10-02 04:30:05 +04:00
|
|
|
|
}
|
|
|
|
|
|
2013-06-22 03:44:17 +04: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 19:39:17 +04:00
|
|
|
|
CycleCollectionNoteChild(aCallback, aField.mTexturePtr.get(),
|
|
|
|
|
aName, aFlags);
|
|
|
|
|
|
|
|
|
|
CycleCollectionNoteChild(aCallback, aField.mRenderbufferPtr.get(),
|
|
|
|
|
aName, aFlags);
|
2013-06-22 03:44:17 +04:00
|
|
|
|
}
|
|
|
|
|
|
2014-04-29 12:57:00 +04:00
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(WebGLFramebuffer,
|
2013-06-22 03:44:17 +04:00
|
|
|
|
mColorAttachments,
|
2013-10-11 17:16:43 +04:00
|
|
|
|
mDepthAttachment,
|
|
|
|
|
mStencilAttachment,
|
|
|
|
|
mDepthStencilAttachment)
|
2012-10-05 00:35:54 +04:00
|
|
|
|
|
2013-08-29 19:39:17 +04:00
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(WebGLFramebuffer, AddRef)
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(WebGLFramebuffer, Release)
|