mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 614867 - Fix WebGL FBOs (pass framebuffer-object-attachment.html) - r=vlad
This commit is contained in:
parent
f3d3a4229e
commit
27b8817c93
@ -750,7 +750,8 @@ public:
|
||||
mMaxLevelWithCustomImages(0),
|
||||
mHaveGeneratedMipmap(PR_FALSE),
|
||||
mFakeBlackStatus(DoNotNeedFakeBlack)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
void Delete() {
|
||||
if (mDeleted)
|
||||
@ -1352,6 +1353,66 @@ protected:
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLRenderbuffer, WEBGLRENDERBUFFER_PRIVATE_IID)
|
||||
|
||||
class WebGLFramebufferAttachment
|
||||
{
|
||||
nsRefPtr<WebGLTexture> mTexturePtr;
|
||||
nsRefPtr<WebGLRenderbuffer> mRenderbufferPtr;
|
||||
WebGLenum mAttachmentPoint;
|
||||
|
||||
public:
|
||||
WebGLFramebufferAttachment(WebGLenum aAttachmentPoint)
|
||||
: mAttachmentPoint(aAttachmentPoint)
|
||||
{}
|
||||
|
||||
PRBool IsNull() const {
|
||||
return !mTexturePtr && !mRenderbufferPtr;
|
||||
}
|
||||
|
||||
void SetTexture(WebGLTexture *tex) {
|
||||
mTexturePtr = tex;
|
||||
mRenderbufferPtr = nsnull;
|
||||
}
|
||||
void SetRenderbuffer(WebGLRenderbuffer *rb) {
|
||||
mTexturePtr = nsnull;
|
||||
mRenderbufferPtr = rb;
|
||||
}
|
||||
WebGLTexture *Texture() const {
|
||||
return mTexturePtr.get();
|
||||
}
|
||||
WebGLRenderbuffer *Renderbuffer() const {
|
||||
return mRenderbufferPtr.get();
|
||||
}
|
||||
|
||||
PRBool IsIncompatibleWithAttachmentPoint() const
|
||||
{
|
||||
// textures can only be color textures in WebGL
|
||||
if (mTexturePtr)
|
||||
return mAttachmentPoint != LOCAL_GL_COLOR_ATTACHMENT0;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_FALSE; // no attachment at all, so no incompatibility
|
||||
}
|
||||
|
||||
PRBool HasUninitializedRenderbuffer() const {
|
||||
return mRenderbufferPtr && !mRenderbufferPtr->Initialized();
|
||||
}
|
||||
};
|
||||
|
||||
#define WEBGLFRAMEBUFFER_PRIVATE_IID \
|
||||
{0x0052a16f, 0x4bc9, 0x4a55, {0x9d, 0xa3, 0x54, 0x95, 0xaa, 0x4e, 0x80, 0xb9}}
|
||||
class WebGLFramebuffer :
|
||||
@ -1366,10 +1427,11 @@ public:
|
||||
WebGLFramebuffer(WebGLContext *context, WebGLuint name) :
|
||||
WebGLContextBoundObject(context),
|
||||
mName(name), mDeleted(PR_FALSE),
|
||||
mColorAttachment0HasAlpha(PR_FALSE),
|
||||
mHasDepthAttachment(PR_FALSE),
|
||||
mHasStencilAttachment(PR_FALSE),
|
||||
mHasDepthStencilAttachment(PR_FALSE)
|
||||
mColorAttachmentHasAlpha(PR_FALSE),
|
||||
mColorAttachment(LOCAL_GL_COLOR_ATTACHMENT0),
|
||||
mDepthAttachment(LOCAL_GL_DEPTH_ATTACHMENT),
|
||||
mStencilAttachment(LOCAL_GL_STENCIL_ATTACHMENT),
|
||||
mDepthStencilAttachment(LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
|
||||
{ }
|
||||
|
||||
void Delete() {
|
||||
@ -1381,7 +1443,7 @@ public:
|
||||
PRBool Deleted() { return mDeleted; }
|
||||
WebGLuint GLName() { return mName; }
|
||||
|
||||
PRBool ColorAttachment0HasAlpha() { return mColorAttachment0HasAlpha; }
|
||||
PRBool ColorAttachmentHasAlpha() { return mColorAttachmentHasAlpha; }
|
||||
|
||||
nsresult FramebufferRenderbuffer(WebGLenum target,
|
||||
WebGLenum attachment,
|
||||
@ -1404,59 +1466,27 @@ public:
|
||||
if (rbtarget != LOCAL_GL_RENDERBUFFER)
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: renderbuffer target:", rbtarget);
|
||||
|
||||
const char *badAttachmentFormatMsg =
|
||||
"framebufferRenderbuffer: this renderbuffer does not have a suitable format for this attachment point";
|
||||
|
||||
switch (attachment) {
|
||||
case LOCAL_GL_DEPTH_ATTACHMENT:
|
||||
if (!isNull) {
|
||||
if (wrb->mInternalFormat != LOCAL_GL_DEPTH_COMPONENT16)
|
||||
return mContext->ErrorInvalidOperation(badAttachmentFormatMsg);
|
||||
}
|
||||
mDepthOrStencilRenderbufferAttachment = wrb;
|
||||
mHasDepthAttachment = !isNull;
|
||||
mDepthAttachment.SetRenderbuffer(wrb);
|
||||
break;
|
||||
case LOCAL_GL_STENCIL_ATTACHMENT:
|
||||
if (!isNull) {
|
||||
if (wrb->mInternalFormat != LOCAL_GL_STENCIL_INDEX8)
|
||||
return mContext->ErrorInvalidOperation(badAttachmentFormatMsg);
|
||||
}
|
||||
mDepthOrStencilRenderbufferAttachment = wrb;
|
||||
mHasStencilAttachment = !isNull;
|
||||
mStencilAttachment.SetRenderbuffer(wrb);
|
||||
break;
|
||||
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
if (!isNull) {
|
||||
if (wrb->mInternalFormat != LOCAL_GL_DEPTH_STENCIL)
|
||||
return mContext->ErrorInvalidOperation(badAttachmentFormatMsg);
|
||||
}
|
||||
mDepthOrStencilRenderbufferAttachment = wrb;
|
||||
mHasDepthStencilAttachment = !isNull;
|
||||
mDepthStencilAttachment.SetRenderbuffer(wrb);
|
||||
break;
|
||||
default:
|
||||
// finish checking that the 'attachment' parameter is among the allowed values
|
||||
if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
|
||||
attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mContext->mMaxFramebufferColorAttachments))
|
||||
{
|
||||
if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: attachment", attachment);
|
||||
}
|
||||
if (!isNull) {
|
||||
if (wrb->mInternalFormat != LOCAL_GL_RGBA4 &&
|
||||
wrb->mInternalFormat != LOCAL_GL_RGB565 &&
|
||||
wrb->mInternalFormat != LOCAL_GL_RGB5_A1)
|
||||
{
|
||||
return mContext->ErrorInvalidOperation(badAttachmentFormatMsg);
|
||||
}
|
||||
|
||||
// ReadPixels needs alpha and size information, but only
|
||||
// for COLOR_ATTACHMENT0
|
||||
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0) {
|
||||
setDimensions(wrb);
|
||||
mColorAttachment0HasAlpha = InternalFormatHasAlpha(wrb->mInternalFormat);
|
||||
} else {
|
||||
mColorAttachment0HasAlpha = PR_FALSE;
|
||||
mColorAttachmentHasAlpha = InternalFormatHasAlpha(wrb->mInternalFormat);
|
||||
}
|
||||
}
|
||||
mColorRenderbufferAttachment = wrb;
|
||||
mColorAttachment.SetRenderbuffer(wrb);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1495,20 +1525,19 @@ public:
|
||||
|
||||
switch (attachment) {
|
||||
case LOCAL_GL_DEPTH_ATTACHMENT:
|
||||
mDepthAttachment.SetTexture(wtex);
|
||||
break;
|
||||
case LOCAL_GL_STENCIL_ATTACHMENT:
|
||||
mStencilAttachment.SetTexture(wtex);
|
||||
break;
|
||||
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
return mContext->ErrorInvalidOperation("framebufferTexture2D: depth and stencil attachments can "
|
||||
"only be renderbuffers, not textures, as there is no suitable texture format.");
|
||||
mDepthStencilAttachment.SetTexture(wtex);
|
||||
break;
|
||||
default:
|
||||
if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
|
||||
attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mContext->mMaxFramebufferColorAttachments))
|
||||
{
|
||||
if (attachment != LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: attachment", attachment);
|
||||
}
|
||||
|
||||
// keep data for readPixels, function only uses COLOR_ATTACHMENT0
|
||||
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0) {
|
||||
setDimensions(wtex);
|
||||
|
||||
if (wtex) {
|
||||
@ -1516,13 +1545,12 @@ public:
|
||||
(level, textarget == LOCAL_GL_TEXTURE_2D
|
||||
? 0
|
||||
: textarget - LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X);
|
||||
mColorAttachment0HasAlpha = InternalFormatHasAlpha(ia.mFormat);
|
||||
mColorAttachmentHasAlpha = InternalFormatHasAlpha(ia.mFormat);
|
||||
} else {
|
||||
mColorAttachment0HasAlpha = PR_FALSE;
|
||||
}
|
||||
mColorAttachmentHasAlpha = PR_FALSE;
|
||||
}
|
||||
|
||||
// nothing else to do for color buffers. all textures have a color-renderable format.
|
||||
mColorAttachment.SetTexture(wtex);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1532,17 +1560,17 @@ public:
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// implement inline, as it's performance critical (called by draw-functions).
|
||||
// the generic case for which we're optimizing is the case where there's nothing to initialize.
|
||||
inline PRBool CheckAndInitializeRenderbuffers()
|
||||
PRBool CheckAndInitializeRenderbuffers()
|
||||
{
|
||||
if (HasConflictingAttachments()) {
|
||||
if (HasBadAttachments()) {
|
||||
mContext->SynthesizeGLError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if ((mColorRenderbufferAttachment && !mColorRenderbufferAttachment->Initialized()) ||
|
||||
(mDepthOrStencilRenderbufferAttachment && !mDepthOrStencilRenderbufferAttachment->Initialized()))
|
||||
if (mColorAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthAttachment.HasUninitializedRenderbuffer() ||
|
||||
mStencilAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer())
|
||||
{
|
||||
InitializeRenderbuffers();
|
||||
}
|
||||
@ -1550,23 +1578,37 @@ public:
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBGLFRAMEBUFFER
|
||||
|
||||
PRBool HasConflictingAttachments() const {
|
||||
return int(mHasDepthAttachment) +
|
||||
int(mHasStencilAttachment) +
|
||||
int(mHasDepthStencilAttachment) > 1;
|
||||
PRBool HasBadAttachments() const {
|
||||
if (mColorAttachment.IsIncompatibleWithAttachmentPoint() ||
|
||||
mDepthAttachment.IsIncompatibleWithAttachmentPoint() ||
|
||||
mStencilAttachment.IsIncompatibleWithAttachmentPoint() ||
|
||||
mDepthStencilAttachment.IsIncompatibleWithAttachmentPoint())
|
||||
{
|
||||
// some attachment is incompatible with its attachment point
|
||||
return PR_TRUE;
|
||||
}
|
||||
else if (int(mDepthAttachment.IsNull()) +
|
||||
int(mStencilAttachment.IsNull()) +
|
||||
int(mDepthStencilAttachment.IsNull()) <= 1)
|
||||
{
|
||||
// has at least two among Depth, Stencil, DepthStencil
|
||||
return PR_TRUE;
|
||||
}
|
||||
else return PR_FALSE;
|
||||
}
|
||||
|
||||
static PRBool InternalFormatHasAlpha(WebGLenum aInternalFormat) {
|
||||
return
|
||||
aInternalFormat == LOCAL_GL_RGBA ||
|
||||
aInternalFormat == LOCAL_GL_LUMINANCE_ALPHA ||
|
||||
aInternalFormat == LOCAL_GL_ALPHA ||
|
||||
aInternalFormat == LOCAL_GL_RGBA4 ||
|
||||
aInternalFormat == LOCAL_GL_RGB5_A1;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBGLFRAMEBUFFER
|
||||
|
||||
protected:
|
||||
|
||||
// protected because WebGLContext should only call InitializeRenderbuffers
|
||||
@ -1577,12 +1619,11 @@ protected:
|
||||
if (mContext->gl->fCheckFramebufferStatus(LOCAL_GL_FRAMEBUFFER) != LOCAL_GL_FRAMEBUFFER_COMPLETE)
|
||||
return;
|
||||
|
||||
PRBool initializeColorBuffer = mColorRenderbufferAttachment &&
|
||||
!mColorRenderbufferAttachment->Initialized();
|
||||
PRBool initializeDepthOrStencilBuffer = mDepthOrStencilRenderbufferAttachment &&
|
||||
!mDepthOrStencilRenderbufferAttachment->Initialized();
|
||||
PRBool initializeDepthBuffer = initializeDepthOrStencilBuffer && HasDepthBuffer();
|
||||
PRBool initializeStencilBuffer = initializeDepthOrStencilBuffer && HasStencilBuffer();
|
||||
PRBool initializeColorBuffer = mColorAttachment.HasUninitializedRenderbuffer();
|
||||
PRBool initializeDepthBuffer = mDepthAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer();
|
||||
PRBool initializeStencilBuffer = mStencilAttachment.HasUninitializedRenderbuffer() ||
|
||||
mDepthStencilAttachment.HasUninitializedRenderbuffer();
|
||||
|
||||
realGLboolean savedColorMask[] = {0}, savedDepthMask = 0;
|
||||
GLuint savedStencilMask = 0;
|
||||
@ -1634,19 +1675,26 @@ protected:
|
||||
savedColorClearValue[1],
|
||||
savedColorClearValue[2],
|
||||
savedColorClearValue[3]);
|
||||
mColorRenderbufferAttachment->SetInitialized(PR_TRUE);
|
||||
mColorAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
|
||||
}
|
||||
|
||||
if (initializeDepthBuffer) {
|
||||
mContext->gl->fDepthMask(savedDepthMask);
|
||||
mContext->gl->fClearDepth(savedDepthClearValue);
|
||||
mDepthOrStencilRenderbufferAttachment->SetInitialized(PR_TRUE);
|
||||
if (mDepthAttachment.Renderbuffer())
|
||||
mDepthAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
|
||||
}
|
||||
|
||||
if (initializeStencilBuffer) {
|
||||
mContext->gl->fStencilMask(savedStencilMask);
|
||||
mContext->gl->fClearStencil(savedStencilClearValue);
|
||||
mDepthOrStencilRenderbufferAttachment->SetInitialized(PR_TRUE);
|
||||
if (mStencilAttachment.Renderbuffer())
|
||||
mStencilAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
|
||||
}
|
||||
|
||||
if (initializeDepthBuffer && initializeStencilBuffer) {
|
||||
if (mDepthStencilAttachment.Renderbuffer())
|
||||
mDepthStencilAttachment.Renderbuffer()->SetInitialized(PR_TRUE);
|
||||
}
|
||||
|
||||
mContext->gl->PopViewportRect();
|
||||
@ -1662,28 +1710,17 @@ protected:
|
||||
mContext->gl->fDisable(LOCAL_GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
PRBool HasDepthBuffer() const {
|
||||
return mHasDepthAttachment || mHasDepthStencilAttachment;
|
||||
}
|
||||
|
||||
PRBool HasStencilBuffer() const {
|
||||
return mHasStencilAttachment || mHasDepthStencilAttachment;
|
||||
}
|
||||
|
||||
WebGLuint mName;
|
||||
PRPackedBool mDeleted;
|
||||
PRPackedBool mColorAttachment0HasAlpha;
|
||||
|
||||
PRBool mColorAttachmentHasAlpha;
|
||||
|
||||
// we only store pointers to attached renderbuffers, not to attached textures, because
|
||||
// we will only need to initialize renderbuffers. Textures are already initialized.
|
||||
nsRefPtr<WebGLRenderbuffer> mColorRenderbufferAttachment;
|
||||
nsRefPtr<WebGLRenderbuffer> mDepthOrStencilRenderbufferAttachment;
|
||||
|
||||
// these boolean values keep track of all attachments: renderbuffers and textures.
|
||||
// thus they are not at all redundant with the above member pointers.
|
||||
PRBool mHasDepthAttachment;
|
||||
PRBool mHasStencilAttachment;
|
||||
PRBool mHasDepthStencilAttachment;
|
||||
WebGLFramebufferAttachment mColorAttachment,
|
||||
mDepthAttachment,
|
||||
mStencilAttachment,
|
||||
mDepthStencilAttachment;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLFramebuffer, WEBGLFRAMEBUFFER_PRIVATE_IID)
|
||||
|
@ -523,7 +523,7 @@ WebGLContext::CheckFramebufferStatus(WebGLenum target, WebGLenum *retval)
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return ErrorInvalidEnum("checkFramebufferStatus: target must be FRAMEBUFFER");
|
||||
|
||||
if (mBoundFramebuffer && mBoundFramebuffer->HasConflictingAttachments())
|
||||
if (mBoundFramebuffer && mBoundFramebuffer->HasBadAttachments())
|
||||
*retval = LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
else
|
||||
*retval = gl->fCheckFramebufferStatus(target);
|
||||
@ -1794,7 +1794,6 @@ WebGLContext::GetRenderbufferParameter(WebGLenum target, WebGLenum pname, nsIVar
|
||||
switch (pname) {
|
||||
case LOCAL_GL_RENDERBUFFER_WIDTH:
|
||||
case LOCAL_GL_RENDERBUFFER_HEIGHT:
|
||||
case LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT:
|
||||
case LOCAL_GL_RENDERBUFFER_RED_SIZE:
|
||||
case LOCAL_GL_RENDERBUFFER_GREEN_SIZE:
|
||||
case LOCAL_GL_RENDERBUFFER_BLUE_SIZE:
|
||||
@ -1807,7 +1806,17 @@ WebGLContext::GetRenderbufferParameter(WebGLenum target, WebGLenum pname, nsIVar
|
||||
wrval->SetAsInt32(i);
|
||||
}
|
||||
break;
|
||||
|
||||
case LOCAL_GL_RENDERBUFFER_INTERNAL_FORMAT:
|
||||
{
|
||||
GLint i = 0;
|
||||
gl->fGetRenderbufferParameteriv(target, pname, &i);
|
||||
if (i == LOCAL_GL_DEPTH24_STENCIL8)
|
||||
{
|
||||
i = LOCAL_GL_DEPTH_STENCIL;
|
||||
}
|
||||
wrval->SetAsInt32(i);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("GetRenderbufferParameter: parameter", pname);
|
||||
}
|
||||
@ -2590,7 +2599,7 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
|
||||
{
|
||||
PRBool needAlphaFixup;
|
||||
if (mBoundFramebuffer) {
|
||||
needAlphaFixup = !mBoundFramebuffer->ColorAttachment0HasAlpha();
|
||||
needAlphaFixup = !mBoundFramebuffer->ColorAttachmentHasAlpha();
|
||||
} else {
|
||||
needAlphaFixup = gl->ActualFormat().alpha == 0;
|
||||
}
|
||||
@ -2681,8 +2690,8 @@ WebGLContext::RenderbufferStorage(WebGLenum target, WebGLenum internalformat, We
|
||||
if (!gl->IsGLES2()) internalformatForGL = LOCAL_GL_RGB8;
|
||||
break;
|
||||
case LOCAL_GL_DEPTH_COMPONENT16:
|
||||
break;
|
||||
case LOCAL_GL_STENCIL_INDEX8:
|
||||
// nothing to do for these ones
|
||||
break;
|
||||
case LOCAL_GL_DEPTH_STENCIL:
|
||||
// this one is available in newer OpenGL (at least since 3.1); will probably become available
|
||||
|
Loading…
Reference in New Issue
Block a user