mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 816173 - Split out WebGLFramebuffer into separate files
This commit is contained in:
parent
34b6e285e3
commit
c830bece19
@ -12,6 +12,7 @@
|
||||
#include "WebGLBuffer.h"
|
||||
#include "WebGLProgram.h"
|
||||
#include "WebGLUniformLocation.h"
|
||||
#include "WebGLFramebuffer.h"
|
||||
#include "WebGLRenderbuffer.h"
|
||||
#include "WebGLTexture.h"
|
||||
#include "WebGLVertexAttribData.h"
|
||||
@ -71,7 +72,6 @@ class nsIPropertyBag;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class WebGLFramebuffer;
|
||||
class WebGLMemoryPressureObserver;
|
||||
class WebGLContextBoundObject;
|
||||
class WebGLActiveInfo;
|
||||
@ -1159,468 +1159,6 @@ ToSupports(WebGLContext* context)
|
||||
return static_cast<nsICanvasRenderingContextInternal*>(context);
|
||||
}
|
||||
|
||||
class WebGLFramebufferAttachment
|
||||
{
|
||||
// deleting a texture or renderbuffer immediately detaches it
|
||||
WebGLRefPtr<WebGLTexture> mTexturePtr;
|
||||
WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
|
||||
WebGLenum mAttachmentPoint;
|
||||
WebGLint mTextureLevel;
|
||||
WebGLenum mTextureCubeMapFace;
|
||||
|
||||
friend class WebGLFramebuffer;
|
||||
|
||||
public:
|
||||
WebGLFramebufferAttachment(WebGLenum aAttachmentPoint)
|
||||
: mAttachmentPoint(aAttachmentPoint)
|
||||
{}
|
||||
|
||||
bool IsDefined() const {
|
||||
return Texture() || Renderbuffer();
|
||||
}
|
||||
|
||||
bool IsDeleteRequested() const {
|
||||
return Texture() ? Texture()->IsDeleteRequested()
|
||||
: Renderbuffer() ? Renderbuffer()->IsDeleteRequested()
|
||||
: false;
|
||||
}
|
||||
|
||||
bool HasAlpha() const {
|
||||
WebGLenum format = 0;
|
||||
if (Texture() && Texture()->HasImageInfoAt(mTextureLevel, mTextureCubeMapFace))
|
||||
format = Texture()->ImageInfoAt(mTextureLevel, mTextureCubeMapFace).Format();
|
||||
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 SetTexture(WebGLTexture *tex, WebGLint level, WebGLenum face) {
|
||||
mTexturePtr = tex;
|
||||
mRenderbufferPtr = nullptr;
|
||||
mTextureLevel = level;
|
||||
mTextureCubeMapFace = face;
|
||||
}
|
||||
void SetRenderbuffer(WebGLRenderbuffer *rb) {
|
||||
mTexturePtr = nullptr;
|
||||
mRenderbufferPtr = rb;
|
||||
}
|
||||
const WebGLTexture *Texture() const {
|
||||
return mTexturePtr;
|
||||
}
|
||||
WebGLTexture *Texture() {
|
||||
return mTexturePtr;
|
||||
}
|
||||
const WebGLRenderbuffer *Renderbuffer() const {
|
||||
return mRenderbufferPtr;
|
||||
}
|
||||
WebGLRenderbuffer *Renderbuffer() {
|
||||
return mRenderbufferPtr;
|
||||
}
|
||||
WebGLint TextureLevel() const {
|
||||
return mTextureLevel;
|
||||
}
|
||||
WebGLenum TextureCubeMapFace() const {
|
||||
return mTextureCubeMapFace;
|
||||
}
|
||||
|
||||
bool HasUninitializedRenderbuffer() const {
|
||||
return mRenderbufferPtr && !mRenderbufferPtr->Initialized();
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
mTexturePtr = nullptr;
|
||||
mRenderbufferPtr = nullptr;
|
||||
}
|
||||
|
||||
const WebGLRectangleObject* RectangleObject() const {
|
||||
if (Texture() && Texture()->HasImageInfoAt(mTextureLevel, mTextureCubeMapFace))
|
||||
return &Texture()->ImageInfoAt(mTextureLevel, mTextureCubeMapFace);
|
||||
else if (Renderbuffer())
|
||||
return Renderbuffer();
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
bool HasSameDimensionsAs(const WebGLFramebufferAttachment& other) const {
|
||||
const WebGLRectangleObject *thisRect = RectangleObject();
|
||||
const WebGLRectangleObject *otherRect = other.RectangleObject();
|
||||
return thisRect &&
|
||||
otherRect &&
|
||||
thisRect->HasSameDimensionsAs(*otherRect);
|
||||
}
|
||||
|
||||
bool IsComplete() const {
|
||||
const WebGLRectangleObject *thisRect = RectangleObject();
|
||||
|
||||
if (!thisRect ||
|
||||
!thisRect->Width() ||
|
||||
!thisRect->Height())
|
||||
return false;
|
||||
|
||||
if (mTexturePtr) {
|
||||
if (!mTexturePtr->HasImageInfoAt(0, 0))
|
||||
return false;
|
||||
|
||||
WebGLenum format = mTexturePtr->ImageInfoAt(0).Format();
|
||||
switch (mAttachmentPoint)
|
||||
{
|
||||
case LOCAL_GL_COLOR_ATTACHMENT0:
|
||||
return format == LOCAL_GL_ALPHA ||
|
||||
format == LOCAL_GL_LUMINANCE ||
|
||||
format == LOCAL_GL_LUMINANCE_ALPHA ||
|
||||
format == LOCAL_GL_RGB ||
|
||||
format == LOCAL_GL_RGBA;
|
||||
case LOCAL_GL_DEPTH_ATTACHMENT:
|
||||
return format == LOCAL_GL_DEPTH_COMPONENT;
|
||||
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
return format == LOCAL_GL_DEPTH_STENCIL;
|
||||
|
||||
default:
|
||||
MOZ_NOT_REACHED("Invalid WebGL texture format?");
|
||||
}
|
||||
}
|
||||
|
||||
if (mRenderbufferPtr) {
|
||||
WebGLenum format = mRenderbufferPtr->InternalFormat();
|
||||
switch (mAttachmentPoint) {
|
||||
case LOCAL_GL_COLOR_ATTACHMENT0:
|
||||
return format == LOCAL_GL_RGB565 ||
|
||||
format == LOCAL_GL_RGB5_A1 ||
|
||||
format == LOCAL_GL_RGBA4;
|
||||
case LOCAL_GL_DEPTH_ATTACHMENT:
|
||||
return format == LOCAL_GL_DEPTH_COMPONENT16;
|
||||
case LOCAL_GL_STENCIL_ATTACHMENT:
|
||||
return format == LOCAL_GL_STENCIL_INDEX8;
|
||||
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
return format == LOCAL_GL_DEPTH_STENCIL;
|
||||
default:
|
||||
NS_ABORT(); // should have been validated earlier
|
||||
}
|
||||
}
|
||||
|
||||
NS_ABORT(); // should never get there
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class WebGLFramebuffer MOZ_FINAL
|
||||
: public nsISupports
|
||||
, public WebGLRefCountedObject<WebGLFramebuffer>
|
||||
, public LinkedListElement<WebGLFramebuffer>
|
||||
, public WebGLContextBoundObject
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
WebGLFramebuffer(WebGLContext *context)
|
||||
: WebGLContextBoundObject(context)
|
||||
, mHasEverBeenBound(false)
|
||||
, mColorAttachment(LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
, 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);
|
||||
}
|
||||
|
||||
~WebGLFramebuffer() {
|
||||
DeleteOnce();
|
||||
}
|
||||
|
||||
void Delete() {
|
||||
mColorAttachment.Reset();
|
||||
mDepthAttachment.Reset();
|
||||
mStencilAttachment.Reset();
|
||||
mDepthStencilAttachment.Reset();
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fDeleteFramebuffers(1, &mGLName);
|
||||
LinkedListElement<WebGLFramebuffer>::removeFrom(mContext->mFramebuffers);
|
||||
}
|
||||
|
||||
bool HasEverBeenBound() { return mHasEverBeenBound; }
|
||||
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
|
||||
WebGLuint GLName() { return mGLName; }
|
||||
|
||||
void FramebufferRenderbuffer(WebGLenum target,
|
||||
WebGLenum attachment,
|
||||
WebGLenum rbtarget,
|
||||
WebGLRenderbuffer *wrb)
|
||||
{
|
||||
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
|
||||
if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: attachment", attachment);
|
||||
|
||||
mColorAttachment.SetRenderbuffer(wrb);
|
||||
break;
|
||||
}
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
WebGLuint parambuffername = wrb ? wrb->GLName() : 0;
|
||||
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
WebGLuint depthbuffername = parambuffername;
|
||||
WebGLuint stencilbuffername = parambuffername;
|
||||
if (!parambuffername){
|
||||
depthbuffername = mDepthAttachment.Renderbuffer() ? mDepthAttachment.Renderbuffer()->GLName() : 0;
|
||||
stencilbuffername = mStencilAttachment.Renderbuffer() ? mStencilAttachment.Renderbuffer()->GLName() : 0;
|
||||
}
|
||||
mContext->gl->fFramebufferRenderbuffer(target, LOCAL_GL_DEPTH_ATTACHMENT, rbtarget, depthbuffername);
|
||||
mContext->gl->fFramebufferRenderbuffer(target, LOCAL_GL_STENCIL_ATTACHMENT, rbtarget, stencilbuffername);
|
||||
} else {
|
||||
WebGLuint renderbuffername = parambuffername;
|
||||
if(!parambuffername && (attachment == LOCAL_GL_DEPTH_ATTACHMENT || attachment == LOCAL_GL_STENCIL_ATTACHMENT)){
|
||||
renderbuffername = mDepthStencilAttachment.Renderbuffer() ? mDepthStencilAttachment.Renderbuffer()->GLName() : 0;
|
||||
}
|
||||
mContext->gl->fFramebufferRenderbuffer(target, attachment, rbtarget, renderbuffername);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferTexture2D(WebGLenum target,
|
||||
WebGLenum attachment,
|
||||
WebGLenum textarget,
|
||||
WebGLTexture *wtex,
|
||||
WebGLint level)
|
||||
{
|
||||
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");
|
||||
|
||||
size_t face = WebGLTexture::FaceForTarget(textarget);
|
||||
switch (attachment) {
|
||||
case LOCAL_GL_DEPTH_ATTACHMENT:
|
||||
mDepthAttachment.SetTexture(wtex, level, face);
|
||||
break;
|
||||
case LOCAL_GL_STENCIL_ATTACHMENT:
|
||||
mStencilAttachment.SetTexture(wtex, level, face);
|
||||
break;
|
||||
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
mDepthStencilAttachment.SetTexture(wtex, level, face);
|
||||
break;
|
||||
default:
|
||||
if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: attachment", attachment);
|
||||
|
||||
mColorAttachment.SetTexture(wtex, level, face);
|
||||
break;
|
||||
}
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
WebGLuint paramtexturename = wtex ? wtex->GLName() : 0;
|
||||
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
WebGLuint depthtexturename = paramtexturename;
|
||||
WebGLuint stenciltexturename = paramtexturename;
|
||||
if(!paramtexturename){
|
||||
depthtexturename = mDepthAttachment.Texture() ? mDepthAttachment.Texture()->GLName() : 0;
|
||||
stenciltexturename = mStencilAttachment.Texture() ? mStencilAttachment.Texture()->GLName() : 0;
|
||||
}
|
||||
mContext->gl->fFramebufferTexture2D(target, LOCAL_GL_DEPTH_ATTACHMENT, textarget, depthtexturename, level);
|
||||
mContext->gl->fFramebufferTexture2D(target, LOCAL_GL_STENCIL_ATTACHMENT, textarget, stenciltexturename, level);
|
||||
} else {
|
||||
WebGLuint texturename = paramtexturename;
|
||||
if(!paramtexturename && (attachment == LOCAL_GL_DEPTH_ATTACHMENT || attachment == LOCAL_GL_STENCIL_ATTACHMENT)){
|
||||
texturename = mDepthStencilAttachment.Texture() ? mDepthStencilAttachment.Texture()->GLName() : 0;
|
||||
}
|
||||
mContext->gl->fFramebufferTexture2D(target, attachment, textarget, texturename, level);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
bool HasIncompleteAttachment() const {
|
||||
return (mColorAttachment.IsDefined() && !mColorAttachment.IsComplete()) ||
|
||||
(mDepthAttachment.IsDefined() && !mDepthAttachment.IsComplete()) ||
|
||||
(mStencilAttachment.IsDefined() && !mStencilAttachment.IsComplete()) ||
|
||||
(mDepthStencilAttachment.IsDefined() && !mDepthStencilAttachment.IsComplete());
|
||||
}
|
||||
|
||||
bool HasDepthStencilConflict() const {
|
||||
return int(mDepthAttachment.IsDefined()) +
|
||||
int(mStencilAttachment.IsDefined()) +
|
||||
int(mDepthStencilAttachment.IsDefined()) >= 2;
|
||||
}
|
||||
|
||||
bool HasAttachmentsOfMismatchedDimensions() const {
|
||||
return (mDepthAttachment.IsDefined() && !mDepthAttachment.HasSameDimensionsAs(mColorAttachment)) ||
|
||||
(mStencilAttachment.IsDefined() && !mStencilAttachment.HasSameDimensionsAs(mColorAttachment)) ||
|
||||
(mDepthStencilAttachment.IsDefined() && !mDepthStencilAttachment.HasSameDimensionsAs(mColorAttachment));
|
||||
}
|
||||
|
||||
const WebGLFramebufferAttachment& ColorAttachment() const {
|
||||
return mColorAttachment;
|
||||
}
|
||||
|
||||
const WebGLFramebufferAttachment& DepthAttachment() const {
|
||||
return mDepthAttachment;
|
||||
}
|
||||
|
||||
const WebGLFramebufferAttachment& StencilAttachment() const {
|
||||
return mStencilAttachment;
|
||||
}
|
||||
|
||||
const WebGLFramebufferAttachment& DepthStencilAttachment() const {
|
||||
return mDepthStencilAttachment;
|
||||
}
|
||||
|
||||
const WebGLFramebufferAttachment& GetAttachment(WebGLenum attachment) const {
|
||||
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;
|
||||
|
||||
NS_ASSERTION(attachment == LOCAL_GL_COLOR_ATTACHMENT0, "bad attachment!");
|
||||
return mColorAttachment;
|
||||
}
|
||||
|
||||
void DetachTexture(const WebGLTexture *tex) {
|
||||
if (mColorAttachment.Texture() == tex)
|
||||
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_TEXTURE_2D, nullptr, 0);
|
||||
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 DetachRenderbuffer(const WebGLRenderbuffer *rb) {
|
||||
if (mColorAttachment.Renderbuffer() == rb)
|
||||
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_RENDERBUFFER, nullptr);
|
||||
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);
|
||||
}
|
||||
|
||||
const WebGLRectangleObject *RectangleObject() {
|
||||
return mColorAttachment.RectangleObject();
|
||||
}
|
||||
|
||||
WebGLContext *GetParentObject() const {
|
||||
return Context();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebGLFramebuffer)
|
||||
|
||||
bool CheckAndInitializeRenderbuffers()
|
||||
{
|
||||
// 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;
|
||||
|
||||
if (!mColorAttachment.HasUninitializedRenderbuffer() &&
|
||||
!mDepthAttachment.HasUninitializedRenderbuffer() &&
|
||||
!mStencilAttachment.HasUninitializedRenderbuffer() &&
|
||||
!mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
return true;
|
||||
|
||||
// ensure INVALID_FRAMEBUFFER_OPERATION in zero-size case
|
||||
const WebGLRectangleObject *rect = mColorAttachment.RectangleObject();
|
||||
if (!rect ||
|
||||
!rect->Width() ||
|
||||
!rect->Height())
|
||||
return false;
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
|
||||
WebGLenum status = mContext->CheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
return false;
|
||||
|
||||
uint32_t mask = 0;
|
||||
|
||||
if (mColorAttachment.HasUninitializedRenderbuffer())
|
||||
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
|
||||
|
||||
if (mDepthAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
{
|
||||
mask |= LOCAL_GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if (mStencilAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
{
|
||||
mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
|
||||
mContext->ForceClearFramebufferWithDefaultValues(mask, nsIntRect(0, 0, rect->Width(), rect->Height()));
|
||||
|
||||
if (mColorAttachment.HasUninitializedRenderbuffer())
|
||||
mColorAttachment.Renderbuffer()->SetInitialized(true);
|
||||
|
||||
if (mDepthAttachment.HasUninitializedRenderbuffer())
|
||||
mDepthAttachment.Renderbuffer()->SetInitialized(true);
|
||||
|
||||
if (mStencilAttachment.HasUninitializedRenderbuffer())
|
||||
mStencilAttachment.Renderbuffer()->SetInitialized(true);
|
||||
|
||||
if (mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
mDepthStencilAttachment.Renderbuffer()->SetInitialized(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
WebGLuint mGLName;
|
||||
bool mHasEverBeenBound;
|
||||
|
||||
// we only store pointers to attached renderbuffers, not to attached textures, because
|
||||
// we will only need to initialize renderbuffers. Textures are already initialized.
|
||||
WebGLFramebufferAttachment mColorAttachment,
|
||||
mDepthAttachment,
|
||||
mStencilAttachment,
|
||||
mDepthStencilAttachment;
|
||||
};
|
||||
|
||||
class WebGLActiveInfo MOZ_FINAL
|
||||
: public nsISupports
|
||||
{
|
||||
|
@ -2251,7 +2251,7 @@ WebGLContext::GetFramebufferAttachmentParameter(JSContext* cx,
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
const WebGLFramebufferAttachment& fba = mBoundFramebuffer->GetAttachment(attachment);
|
||||
const WebGLFramebuffer::Attachment& fba = mBoundFramebuffer->GetAttachment(attachment);
|
||||
|
||||
if (fba.Renderbuffer()) {
|
||||
switch (pname) {
|
||||
|
@ -4,6 +4,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "WebGLContext.h"
|
||||
#include "WebGLFramebuffer.h"
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -13,6 +14,360 @@ WebGLFramebuffer::WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap)
|
||||
return dom::WebGLFramebufferBinding::Wrap(cx, scope, this, triedToWrap);
|
||||
}
|
||||
|
||||
WebGLFramebuffer::WebGLFramebuffer(WebGLContext *context)
|
||||
: WebGLContextBoundObject(context)
|
||||
, mHasEverBeenBound(false)
|
||||
, mColorAttachment(LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
, 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);
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::Attachment::IsDeleteRequested() const {
|
||||
return Texture() ? Texture()->IsDeleteRequested()
|
||||
: Renderbuffer() ? Renderbuffer()->IsDeleteRequested()
|
||||
: false;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::Attachment::HasAlpha() const {
|
||||
WebGLenum format = 0;
|
||||
if (Texture() && Texture()->HasImageInfoAt(mTextureLevel, mTextureCubeMapFace))
|
||||
format = Texture()->ImageInfoAt(mTextureLevel, mTextureCubeMapFace).Format();
|
||||
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
|
||||
WebGLFramebuffer::Attachment::SetTexture(WebGLTexture *tex, WebGLint level, WebGLenum face) {
|
||||
mTexturePtr = tex;
|
||||
mRenderbufferPtr = nullptr;
|
||||
mTextureLevel = level;
|
||||
mTextureCubeMapFace = face;
|
||||
}
|
||||
|
||||
bool
|
||||
WebGLFramebuffer::Attachment::HasUninitializedRenderbuffer() const {
|
||||
return mRenderbufferPtr && !mRenderbufferPtr->Initialized();
|
||||
}
|
||||
|
||||
const WebGLRectangleObject*
|
||||
WebGLFramebuffer::Attachment::RectangleObject() const {
|
||||
if (Texture() && Texture()->HasImageInfoAt(mTextureLevel, mTextureCubeMapFace))
|
||||
return &Texture()->ImageInfoAt(mTextureLevel, mTextureCubeMapFace);
|
||||
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) {
|
||||
if (!mTexturePtr->HasImageInfoAt(0, 0))
|
||||
return false;
|
||||
|
||||
WebGLenum format = mTexturePtr->ImageInfoAt(0).Format();
|
||||
switch (mAttachmentPoint)
|
||||
{
|
||||
case LOCAL_GL_COLOR_ATTACHMENT0:
|
||||
return format == LOCAL_GL_ALPHA ||
|
||||
format == LOCAL_GL_LUMINANCE ||
|
||||
format == LOCAL_GL_LUMINANCE_ALPHA ||
|
||||
format == LOCAL_GL_RGB ||
|
||||
format == LOCAL_GL_RGBA;
|
||||
case LOCAL_GL_DEPTH_ATTACHMENT:
|
||||
return format == LOCAL_GL_DEPTH_COMPONENT;
|
||||
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
return format == LOCAL_GL_DEPTH_STENCIL;
|
||||
|
||||
default:
|
||||
MOZ_NOT_REACHED("Invalid WebGL texture format?");
|
||||
}
|
||||
}
|
||||
|
||||
if (mRenderbufferPtr) {
|
||||
WebGLenum format = mRenderbufferPtr->InternalFormat();
|
||||
switch (mAttachmentPoint) {
|
||||
case LOCAL_GL_COLOR_ATTACHMENT0:
|
||||
return format == LOCAL_GL_RGB565 ||
|
||||
format == LOCAL_GL_RGB5_A1 ||
|
||||
format == LOCAL_GL_RGBA4;
|
||||
case LOCAL_GL_DEPTH_ATTACHMENT:
|
||||
return format == LOCAL_GL_DEPTH_COMPONENT16;
|
||||
case LOCAL_GL_STENCIL_ATTACHMENT:
|
||||
return format == LOCAL_GL_STENCIL_INDEX8;
|
||||
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
return format == LOCAL_GL_DEPTH_STENCIL;
|
||||
default:
|
||||
NS_ABORT(); // should have been validated earlier
|
||||
}
|
||||
}
|
||||
|
||||
NS_ABORT(); // should never get there
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::Delete() {
|
||||
mColorAttachment.Reset();
|
||||
mDepthAttachment.Reset();
|
||||
mStencilAttachment.Reset();
|
||||
mDepthStencilAttachment.Reset();
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fDeleteFramebuffers(1, &mGLName);
|
||||
LinkedListElement<WebGLFramebuffer>::removeFrom(mContext->mFramebuffers);
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::FramebufferRenderbuffer(WebGLenum target,
|
||||
WebGLenum attachment,
|
||||
WebGLenum rbtarget,
|
||||
WebGLRenderbuffer *wrb)
|
||||
{
|
||||
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
|
||||
if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: attachment", attachment);
|
||||
|
||||
mColorAttachment.SetRenderbuffer(wrb);
|
||||
break;
|
||||
}
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
WebGLuint parambuffername = wrb ? wrb->GLName() : 0;
|
||||
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
WebGLuint depthbuffername = parambuffername;
|
||||
WebGLuint stencilbuffername = parambuffername;
|
||||
if (!parambuffername){
|
||||
depthbuffername = mDepthAttachment.Renderbuffer() ? mDepthAttachment.Renderbuffer()->GLName() : 0;
|
||||
stencilbuffername = mStencilAttachment.Renderbuffer() ? mStencilAttachment.Renderbuffer()->GLName() : 0;
|
||||
}
|
||||
mContext->gl->fFramebufferRenderbuffer(target, LOCAL_GL_DEPTH_ATTACHMENT, rbtarget, depthbuffername);
|
||||
mContext->gl->fFramebufferRenderbuffer(target, LOCAL_GL_STENCIL_ATTACHMENT, rbtarget, stencilbuffername);
|
||||
} else {
|
||||
WebGLuint renderbuffername = parambuffername;
|
||||
if(!parambuffername && (attachment == LOCAL_GL_DEPTH_ATTACHMENT || attachment == LOCAL_GL_STENCIL_ATTACHMENT)){
|
||||
renderbuffername = mDepthStencilAttachment.Renderbuffer() ? mDepthStencilAttachment.Renderbuffer()->GLName() : 0;
|
||||
}
|
||||
mContext->gl->fFramebufferRenderbuffer(target, attachment, rbtarget, renderbuffername);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::FramebufferTexture2D(WebGLenum target,
|
||||
WebGLenum attachment,
|
||||
WebGLenum textarget,
|
||||
WebGLTexture *wtex,
|
||||
WebGLint level)
|
||||
{
|
||||
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");
|
||||
|
||||
size_t face = WebGLTexture::FaceForTarget(textarget);
|
||||
switch (attachment) {
|
||||
case LOCAL_GL_DEPTH_ATTACHMENT:
|
||||
mDepthAttachment.SetTexture(wtex, level, face);
|
||||
break;
|
||||
case LOCAL_GL_STENCIL_ATTACHMENT:
|
||||
mStencilAttachment.SetTexture(wtex, level, face);
|
||||
break;
|
||||
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
mDepthStencilAttachment.SetTexture(wtex, level, face);
|
||||
break;
|
||||
default:
|
||||
if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: attachment", attachment);
|
||||
|
||||
mColorAttachment.SetTexture(wtex, level, face);
|
||||
break;
|
||||
}
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
WebGLuint paramtexturename = wtex ? wtex->GLName() : 0;
|
||||
if (attachment == LOCAL_GL_DEPTH_STENCIL_ATTACHMENT) {
|
||||
WebGLuint depthtexturename = paramtexturename;
|
||||
WebGLuint stenciltexturename = paramtexturename;
|
||||
if(!paramtexturename){
|
||||
depthtexturename = mDepthAttachment.Texture() ? mDepthAttachment.Texture()->GLName() : 0;
|
||||
stenciltexturename = mStencilAttachment.Texture() ? mStencilAttachment.Texture()->GLName() : 0;
|
||||
}
|
||||
mContext->gl->fFramebufferTexture2D(target, LOCAL_GL_DEPTH_ATTACHMENT, textarget, depthtexturename, level);
|
||||
mContext->gl->fFramebufferTexture2D(target, LOCAL_GL_STENCIL_ATTACHMENT, textarget, stenciltexturename, level);
|
||||
} else {
|
||||
WebGLuint texturename = paramtexturename;
|
||||
if(!paramtexturename && (attachment == LOCAL_GL_DEPTH_ATTACHMENT || attachment == LOCAL_GL_STENCIL_ATTACHMENT)){
|
||||
texturename = mDepthStencilAttachment.Texture() ? mDepthStencilAttachment.Texture()->GLName() : 0;
|
||||
}
|
||||
mContext->gl->fFramebufferTexture2D(target, attachment, textarget, texturename, level);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const WebGLFramebuffer::Attachment&
|
||||
WebGLFramebuffer::GetAttachment(WebGLenum attachment) const {
|
||||
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;
|
||||
|
||||
NS_ASSERTION(attachment == LOCAL_GL_COLOR_ATTACHMENT0, "bad attachment!");
|
||||
return mColorAttachment;
|
||||
}
|
||||
|
||||
void
|
||||
WebGLFramebuffer::DetachTexture(const WebGLTexture *tex) {
|
||||
if (mColorAttachment.Texture() == tex)
|
||||
FramebufferTexture2D(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_TEXTURE_2D, nullptr, 0);
|
||||
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) {
|
||||
if (mColorAttachment.Renderbuffer() == rb)
|
||||
FramebufferRenderbuffer(LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0, LOCAL_GL_RENDERBUFFER, nullptr);
|
||||
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()
|
||||
{
|
||||
// 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;
|
||||
|
||||
if (!mColorAttachment.HasUninitializedRenderbuffer() &&
|
||||
!mDepthAttachment.HasUninitializedRenderbuffer() &&
|
||||
!mStencilAttachment.HasUninitializedRenderbuffer() &&
|
||||
!mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
return true;
|
||||
|
||||
// ensure INVALID_FRAMEBUFFER_OPERATION in zero-size case
|
||||
const WebGLRectangleObject *rect = mColorAttachment.RectangleObject();
|
||||
if (!rect ||
|
||||
!rect->Width() ||
|
||||
!rect->Height())
|
||||
return false;
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
|
||||
WebGLenum status = mContext->CheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER);
|
||||
if (status != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
return false;
|
||||
|
||||
uint32_t mask = 0;
|
||||
|
||||
if (mColorAttachment.HasUninitializedRenderbuffer())
|
||||
mask |= LOCAL_GL_COLOR_BUFFER_BIT;
|
||||
|
||||
if (mDepthAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
{
|
||||
mask |= LOCAL_GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if (mStencilAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
{
|
||||
mask |= LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
|
||||
mContext->ForceClearFramebufferWithDefaultValues(mask, nsIntRect(0, 0, rect->Width(), rect->Height()));
|
||||
|
||||
if (mColorAttachment.HasUninitializedRenderbuffer())
|
||||
mColorAttachment.Renderbuffer()->SetInitialized(true);
|
||||
|
||||
if (mDepthAttachment.HasUninitializedRenderbuffer())
|
||||
mDepthAttachment.Renderbuffer()->SetInitialized(true);
|
||||
|
||||
if (mStencilAttachment.HasUninitializedRenderbuffer())
|
||||
mStencilAttachment.Renderbuffer()->SetInitialized(true);
|
||||
|
||||
if (mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
mDepthStencilAttachment.Renderbuffer()->SetInitialized(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_8(WebGLFramebuffer,
|
||||
mColorAttachment.mTexturePtr,
|
||||
mColorAttachment.mRenderbufferPtr,
|
||||
|
181
content/canvas/src/WebGLFramebuffer.h
Normal file
181
content/canvas/src/WebGLFramebuffer.h
Normal file
@ -0,0 +1,181 @@
|
||||
/* -*- Mode: C++; tab-width: 4; 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/. */
|
||||
|
||||
#ifndef WEBGLFRAMEBUFFER_H_
|
||||
#define WEBGLFRAMEBUFFER_H_
|
||||
|
||||
#include "WebGLObjectModel.h"
|
||||
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
#include "mozilla/LinkedList.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class WebGLTexture;
|
||||
class WebGLRenderbuffer;
|
||||
|
||||
class WebGLFramebuffer MOZ_FINAL
|
||||
: public nsISupports
|
||||
, public WebGLRefCountedObject<WebGLFramebuffer>
|
||||
, public LinkedListElement<WebGLFramebuffer>
|
||||
, public WebGLContextBoundObject
|
||||
, public nsWrapperCache
|
||||
{
|
||||
public:
|
||||
WebGLFramebuffer(WebGLContext *context);
|
||||
|
||||
~WebGLFramebuffer() {
|
||||
DeleteOnce();
|
||||
}
|
||||
|
||||
class Attachment
|
||||
{
|
||||
// deleting a texture or renderbuffer immediately detaches it
|
||||
WebGLRefPtr<WebGLTexture> mTexturePtr;
|
||||
WebGLRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
|
||||
WebGLenum mAttachmentPoint;
|
||||
WebGLint mTextureLevel;
|
||||
WebGLenum mTextureCubeMapFace;
|
||||
|
||||
friend class WebGLFramebuffer;
|
||||
|
||||
public:
|
||||
Attachment(WebGLenum aAttachmentPoint)
|
||||
: mAttachmentPoint(aAttachmentPoint)
|
||||
{}
|
||||
|
||||
bool IsDefined() const {
|
||||
return Texture() || Renderbuffer();
|
||||
}
|
||||
|
||||
bool IsDeleteRequested() const;
|
||||
|
||||
bool HasAlpha() const;
|
||||
|
||||
void SetTexture(WebGLTexture *tex, WebGLint level, WebGLenum face);
|
||||
void SetRenderbuffer(WebGLRenderbuffer *rb) {
|
||||
mTexturePtr = nullptr;
|
||||
mRenderbufferPtr = rb;
|
||||
}
|
||||
const WebGLTexture *Texture() const {
|
||||
return mTexturePtr;
|
||||
}
|
||||
WebGLTexture *Texture() {
|
||||
return mTexturePtr;
|
||||
}
|
||||
const WebGLRenderbuffer *Renderbuffer() const {
|
||||
return mRenderbufferPtr;
|
||||
}
|
||||
WebGLRenderbuffer *Renderbuffer() {
|
||||
return mRenderbufferPtr;
|
||||
}
|
||||
WebGLint TextureLevel() const {
|
||||
return mTextureLevel;
|
||||
}
|
||||
WebGLenum TextureCubeMapFace() const {
|
||||
return mTextureCubeMapFace;
|
||||
}
|
||||
|
||||
bool HasUninitializedRenderbuffer() const;
|
||||
|
||||
void Reset() {
|
||||
mTexturePtr = nullptr;
|
||||
mRenderbufferPtr = nullptr;
|
||||
}
|
||||
|
||||
const WebGLRectangleObject* RectangleObject() const;
|
||||
bool HasSameDimensionsAs(const Attachment& other) const;
|
||||
|
||||
bool IsComplete() const;
|
||||
};
|
||||
|
||||
void Delete();
|
||||
|
||||
bool HasEverBeenBound() { return mHasEverBeenBound; }
|
||||
void SetHasEverBeenBound(bool x) { mHasEverBeenBound = x; }
|
||||
WebGLuint GLName() { return mGLName; }
|
||||
|
||||
void FramebufferRenderbuffer(WebGLenum target,
|
||||
WebGLenum attachment,
|
||||
WebGLenum rbtarget,
|
||||
WebGLRenderbuffer *wrb);
|
||||
|
||||
void FramebufferTexture2D(WebGLenum target,
|
||||
WebGLenum attachment,
|
||||
WebGLenum textarget,
|
||||
WebGLTexture *wtex,
|
||||
WebGLint level);
|
||||
|
||||
bool HasIncompleteAttachment() const {
|
||||
return (mColorAttachment.IsDefined() && !mColorAttachment.IsComplete()) ||
|
||||
(mDepthAttachment.IsDefined() && !mDepthAttachment.IsComplete()) ||
|
||||
(mStencilAttachment.IsDefined() && !mStencilAttachment.IsComplete()) ||
|
||||
(mDepthStencilAttachment.IsDefined() && !mDepthStencilAttachment.IsComplete());
|
||||
}
|
||||
|
||||
bool HasDepthStencilConflict() const {
|
||||
return int(mDepthAttachment.IsDefined()) +
|
||||
int(mStencilAttachment.IsDefined()) +
|
||||
int(mDepthStencilAttachment.IsDefined()) >= 2;
|
||||
}
|
||||
|
||||
bool HasAttachmentsOfMismatchedDimensions() const {
|
||||
return (mDepthAttachment.IsDefined() && !mDepthAttachment.HasSameDimensionsAs(mColorAttachment)) ||
|
||||
(mStencilAttachment.IsDefined() && !mStencilAttachment.HasSameDimensionsAs(mColorAttachment)) ||
|
||||
(mDepthStencilAttachment.IsDefined() && !mDepthStencilAttachment.HasSameDimensionsAs(mColorAttachment));
|
||||
}
|
||||
|
||||
const Attachment& ColorAttachment() const {
|
||||
return mColorAttachment;
|
||||
}
|
||||
|
||||
const Attachment& DepthAttachment() const {
|
||||
return mDepthAttachment;
|
||||
}
|
||||
|
||||
const Attachment& StencilAttachment() const {
|
||||
return mStencilAttachment;
|
||||
}
|
||||
|
||||
const Attachment& DepthStencilAttachment() const {
|
||||
return mDepthStencilAttachment;
|
||||
}
|
||||
|
||||
const Attachment& GetAttachment(WebGLenum attachment) const;
|
||||
|
||||
void DetachTexture(const WebGLTexture *tex);
|
||||
|
||||
void DetachRenderbuffer(const WebGLRenderbuffer *rb);
|
||||
|
||||
const WebGLRectangleObject *RectangleObject() {
|
||||
return mColorAttachment.RectangleObject();
|
||||
}
|
||||
|
||||
WebGLContext *GetParentObject() const {
|
||||
return Context();
|
||||
}
|
||||
|
||||
virtual JSObject* WrapObject(JSContext *cx, JSObject *scope, bool *triedToWrap);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(WebGLFramebuffer)
|
||||
|
||||
bool CheckAndInitializeRenderbuffers();
|
||||
|
||||
WebGLuint mGLName;
|
||||
bool mHasEverBeenBound;
|
||||
|
||||
// we only store pointers to attached renderbuffers, not to attached textures, because
|
||||
// we will only need to initialize renderbuffers. Textures are already initialized.
|
||||
Attachment mColorAttachment,
|
||||
mDepthAttachment,
|
||||
mStencilAttachment,
|
||||
mDepthStencilAttachment;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user