зеркало из https://github.com/mozilla/pjs.git
Bug 607774 - Implement the spec on Renderbuffers and Framebuffers - r=vladimir
This commit is contained in:
Родитель
2a62f5cf45
Коммит
9294c1fa05
|
@ -474,10 +474,7 @@ protected:
|
|||
WebGLObjectRefPtr<WebGLBuffer> mBoundElementArrayBuffer;
|
||||
WebGLObjectRefPtr<WebGLProgram> mCurrentProgram;
|
||||
|
||||
// XXX these 3 are wrong types, and aren't used atm (except for the length of the attachments)
|
||||
nsTArray<WebGLObjectRefPtr<WebGLTexture> > mFramebufferColorAttachments;
|
||||
nsRefPtr<WebGLFramebuffer> mFramebufferDepthAttachment;
|
||||
nsRefPtr<WebGLFramebuffer> mFramebufferStencilAttachment;
|
||||
PRUint32 mMaxFramebufferColorAttachments;
|
||||
|
||||
nsRefPtr<WebGLFramebuffer> mBoundFramebuffer;
|
||||
nsRefPtr<WebGLRenderbuffer> mBoundRenderbuffer;
|
||||
|
@ -510,6 +507,7 @@ public:
|
|||
void LogMessageIfVerbose(const char *fmt, va_list ap);
|
||||
|
||||
friend class WebGLTexture;
|
||||
friend class WebGLFramebuffer;
|
||||
};
|
||||
|
||||
// this class is a mixin for the named type wrappers, and is used
|
||||
|
@ -1236,6 +1234,7 @@ public:
|
|||
mMapUniformLocations.Clear();
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
|
||||
already_AddRefed<WebGLUniformLocation> GetUniformLocationObject(GLint glLocation);
|
||||
|
||||
|
@ -1267,6 +1266,54 @@ protected:
|
|||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLProgram, WEBGLPROGRAM_PRIVATE_IID)
|
||||
|
||||
#define WEBGLRENDERBUFFER_PRIVATE_IID \
|
||||
{0x3cbc2067, 0x5831, 0x4e3f, {0xac, 0x52, 0x7e, 0xf4, 0x5c, 0x04, 0xff, 0xae}}
|
||||
class WebGLRenderbuffer :
|
||||
public nsIWebGLRenderbuffer,
|
||||
public WebGLZeroingObject,
|
||||
public WebGLRectangleObject,
|
||||
public WebGLContextBoundObject
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLRENDERBUFFER_PRIVATE_IID)
|
||||
|
||||
WebGLRenderbuffer(WebGLContext *context, WebGLuint name, WebGLuint secondBufferName = 0) :
|
||||
WebGLContextBoundObject(context),
|
||||
mName(name),
|
||||
mInternalFormat(0),
|
||||
mDeleted(PR_FALSE), mInitialized(PR_FALSE)
|
||||
{ }
|
||||
|
||||
void Delete() {
|
||||
if (mDeleted)
|
||||
return;
|
||||
ZeroOwners();
|
||||
mDeleted = PR_TRUE;
|
||||
}
|
||||
PRBool Deleted() const { return mDeleted; }
|
||||
WebGLuint GLName() const { return mName; }
|
||||
|
||||
PRBool Initialized() const { return mInitialized; }
|
||||
void SetInitialized(PRBool aInitialized) { mInitialized = aInitialized; }
|
||||
|
||||
WebGLenum InternalFormat() const { return mInternalFormat; }
|
||||
void SetInternalFormat(WebGLenum aInternalFormat) { mInternalFormat = aInternalFormat; }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBGLRENDERBUFFER
|
||||
|
||||
protected:
|
||||
WebGLuint mName;
|
||||
WebGLenum mInternalFormat;
|
||||
|
||||
PRBool mDeleted;
|
||||
PRBool mInitialized;
|
||||
|
||||
friend class WebGLFramebuffer;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLRenderbuffer, WEBGLRENDERBUFFER_PRIVATE_IID)
|
||||
|
||||
#define WEBGLFRAMEBUFFER_PRIVATE_IID \
|
||||
{0x0052a16f, 0x4bc9, 0x4a55, {0x9d, 0xa3, 0x54, 0x95, 0xaa, 0x4e, 0x80, 0xb9}}
|
||||
class WebGLFramebuffer :
|
||||
|
@ -1280,7 +1327,10 @@ public:
|
|||
|
||||
WebGLFramebuffer(WebGLContext *context, WebGLuint name) :
|
||||
WebGLContextBoundObject(context),
|
||||
mName(name), mDeleted(PR_FALSE)
|
||||
mName(name), mDeleted(PR_FALSE),
|
||||
mHasDepthAttachment(PR_FALSE),
|
||||
mHasStencilAttachment(PR_FALSE),
|
||||
mHasDepthStencilAttachment(PR_FALSE)
|
||||
{ }
|
||||
|
||||
void Delete() {
|
||||
|
@ -1292,49 +1342,285 @@ public:
|
|||
PRBool Deleted() { return mDeleted; }
|
||||
WebGLuint GLName() { return mName; }
|
||||
|
||||
nsresult FramebufferRenderbuffer(WebGLenum target,
|
||||
WebGLenum attachment,
|
||||
WebGLenum rbtarget,
|
||||
nsIWebGLRenderbuffer *rbobj)
|
||||
{
|
||||
WebGLuint renderbuffername;
|
||||
PRBool isNull;
|
||||
WebGLRenderbuffer *wrb;
|
||||
|
||||
if (!mContext->GetConcreteObjectAndGLName("framebufferRenderbuffer: renderbuffer",
|
||||
rbobj, &wrb, &renderbuffername, &isNull))
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferRenderbuffer: target", target);
|
||||
|
||||
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;
|
||||
break;
|
||||
case LOCAL_GL_STENCIL_ATTACHMENT:
|
||||
if (!isNull) {
|
||||
if (wrb->mInternalFormat != LOCAL_GL_STENCIL_INDEX8)
|
||||
return mContext->ErrorInvalidOperation(badAttachmentFormatMsg);
|
||||
}
|
||||
mDepthOrStencilRenderbufferAttachment = wrb;
|
||||
mHasStencilAttachment = !isNull;
|
||||
break;
|
||||
case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
|
||||
if (!isNull) {
|
||||
if (wrb->mInternalFormat != LOCAL_GL_DEPTH_STENCIL)
|
||||
return mContext->ErrorInvalidOperation(badAttachmentFormatMsg);
|
||||
}
|
||||
mDepthOrStencilRenderbufferAttachment = wrb;
|
||||
mHasDepthStencilAttachment = !isNull;
|
||||
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))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
mColorRenderbufferAttachment = wrb;
|
||||
break;
|
||||
}
|
||||
|
||||
// dimensions are kept for readPixels primarily, function only uses COLOR_ATTACHMENT0
|
||||
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
setDimensions(wrb);
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fFramebufferRenderbuffer(target, attachment, rbtarget, renderbuffername);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult FramebufferTexture2D(WebGLenum target,
|
||||
WebGLenum attachment,
|
||||
WebGLenum textarget,
|
||||
nsIWebGLTexture *tobj,
|
||||
WebGLint level)
|
||||
{
|
||||
WebGLuint texturename;
|
||||
PRBool isNull;
|
||||
WebGLTexture *wtex;
|
||||
|
||||
if (!mContext->GetConcreteObjectAndGLName("framebufferTexture2D: texture",
|
||||
tobj, &wtex, &texturename, &isNull))
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: target", target);
|
||||
|
||||
if (!isNull && 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 (!isNull && level > 0)
|
||||
return mContext->ErrorInvalidValue("framebufferTexture2D: level must be 0");
|
||||
|
||||
switch (attachment) {
|
||||
case LOCAL_GL_DEPTH_ATTACHMENT:
|
||||
case LOCAL_GL_STENCIL_ATTACHMENT:
|
||||
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.");
|
||||
break;
|
||||
default:
|
||||
if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
|
||||
attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mContext->mMaxFramebufferColorAttachments))
|
||||
{
|
||||
return mContext->ErrorInvalidEnumInfo("framebufferTexture2D: attachment", attachment);
|
||||
}
|
||||
// nothing to do for color buffers. all textures have a color-renderable format.
|
||||
break;
|
||||
}
|
||||
|
||||
// dimensions are kept for readPixels primarily, function only uses COLOR_ATTACHMENT0
|
||||
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
setDimensions(wtex);
|
||||
|
||||
mContext->MakeContextCurrent();
|
||||
mContext->gl->fFramebufferTexture2D(target, attachment, textarget, texturename, level);
|
||||
|
||||
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()
|
||||
{
|
||||
if (HasConflictingAttachments()) {
|
||||
mContext->SynthesizeGLError(LOCAL_GL_INVALID_FRAMEBUFFER_OPERATION);
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
if ((mColorRenderbufferAttachment && !mColorRenderbufferAttachment->Initialized()) ||
|
||||
(mDepthOrStencilRenderbufferAttachment && !mDepthOrStencilRenderbufferAttachment->Initialized()))
|
||||
{
|
||||
InitializeRenderbuffers();
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBGLFRAMEBUFFER
|
||||
|
||||
PRBool HasConflictingAttachments() const {
|
||||
return int(mHasDepthAttachment) +
|
||||
int(mHasStencilAttachment) +
|
||||
int(mHasDepthStencilAttachment) > 1;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// protected because WebGLContext should only call InitializeRenderbuffers
|
||||
void InitializeRenderbuffers()
|
||||
{
|
||||
mContext->MakeContextCurrent();
|
||||
|
||||
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();
|
||||
|
||||
realGLboolean savedColorMask[] = {0}, savedDepthMask = 0;
|
||||
GLuint savedStencilMask = 0;
|
||||
GLfloat savedColorClearValue[] = {0.f}, savedDepthClearValue = 0.f;
|
||||
GLint savedStencilClearValue = 0;
|
||||
GLuint clearBits = 0;
|
||||
|
||||
realGLboolean wasScissorTestEnabled = mContext->gl->fIsEnabled(LOCAL_GL_SCISSOR_TEST);
|
||||
mContext->gl->fDisable(LOCAL_GL_SCISSOR_TEST);
|
||||
|
||||
realGLboolean wasDitherEnabled = mContext->gl->fIsEnabled(LOCAL_GL_DITHER);
|
||||
mContext->gl->fDisable(LOCAL_GL_DITHER);
|
||||
|
||||
mContext->gl->PushViewportRect(nsIntRect(0,0,width(),height()));
|
||||
|
||||
if (initializeColorBuffer) {
|
||||
mContext->gl->fGetBooleanv(LOCAL_GL_COLOR_WRITEMASK, savedColorMask);
|
||||
mContext->gl->fGetFloatv(LOCAL_GL_COLOR_CLEAR_VALUE, savedColorClearValue);
|
||||
mContext->gl->fColorMask(1, 1, 1, 1);
|
||||
mContext->gl->fClearColor(0.f, 0.f, 0.f, 0.f);
|
||||
clearBits |= LOCAL_GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if (initializeDepthBuffer) {
|
||||
mContext->gl->fGetBooleanv(LOCAL_GL_DEPTH_WRITEMASK, &savedDepthMask);
|
||||
mContext->gl->fGetFloatv(LOCAL_GL_DEPTH_CLEAR_VALUE, &savedDepthClearValue);
|
||||
mContext->gl->fDepthMask(1);
|
||||
mContext->gl->fClearDepth(0.f);
|
||||
clearBits |= LOCAL_GL_DEPTH_BUFFER_BIT;
|
||||
}
|
||||
|
||||
if (initializeStencilBuffer) {
|
||||
mContext->gl->fGetIntegerv(LOCAL_GL_STENCIL_WRITEMASK, reinterpret_cast<GLint*>(&savedStencilMask));
|
||||
mContext->gl->fGetIntegerv(LOCAL_GL_STENCIL_CLEAR_VALUE, &savedStencilClearValue);
|
||||
mContext->gl->fStencilMask(0xffffffff);
|
||||
mContext->gl->fClearStencil(0);
|
||||
clearBits |= LOCAL_GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
|
||||
// the one useful line of code
|
||||
mContext->gl->fClear(clearBits);
|
||||
|
||||
if (initializeColorBuffer) {
|
||||
mContext->gl->fColorMask(savedColorMask[0],
|
||||
savedColorMask[1],
|
||||
savedColorMask[2],
|
||||
savedColorMask[3]);
|
||||
mContext->gl->fClearColor(savedColorClearValue[0],
|
||||
savedColorClearValue[1],
|
||||
savedColorClearValue[2],
|
||||
savedColorClearValue[3]);
|
||||
mColorRenderbufferAttachment->SetInitialized(PR_TRUE);
|
||||
}
|
||||
|
||||
if (initializeDepthBuffer) {
|
||||
mContext->gl->fDepthMask(savedDepthMask);
|
||||
mContext->gl->fClearDepth(savedDepthClearValue);
|
||||
mDepthOrStencilRenderbufferAttachment->SetInitialized(PR_TRUE);
|
||||
}
|
||||
|
||||
if (initializeStencilBuffer) {
|
||||
mContext->gl->fStencilMask(savedStencilMask);
|
||||
mContext->gl->fClearStencil(savedStencilClearValue);
|
||||
mDepthOrStencilRenderbufferAttachment->SetInitialized(PR_TRUE);
|
||||
}
|
||||
|
||||
mContext->gl->PopViewportRect();
|
||||
|
||||
if (wasDitherEnabled)
|
||||
mContext->gl->fEnable(LOCAL_GL_DITHER);
|
||||
else
|
||||
mContext->gl->fDisable(LOCAL_GL_DITHER);
|
||||
|
||||
if (wasScissorTestEnabled)
|
||||
mContext->gl->fEnable(LOCAL_GL_DITHER);
|
||||
else
|
||||
mContext->gl->fDisable(LOCAL_GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
PRBool HasDepthBuffer() const {
|
||||
return mHasDepthAttachment || mHasDepthStencilAttachment;
|
||||
}
|
||||
|
||||
PRBool HasStencilBuffer() const {
|
||||
return mHasStencilAttachment || mHasDepthStencilAttachment;
|
||||
}
|
||||
|
||||
WebGLuint mName;
|
||||
PRBool mDeleted;
|
||||
|
||||
// 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;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLFramebuffer, WEBGLFRAMEBUFFER_PRIVATE_IID)
|
||||
|
||||
#define WEBGLRENDERBUFFER_PRIVATE_IID \
|
||||
{0x3cbc2067, 0x5831, 0x4e3f, {0xac, 0x52, 0x7e, 0xf4, 0x5c, 0x04, 0xff, 0xae}}
|
||||
class WebGLRenderbuffer :
|
||||
public nsIWebGLRenderbuffer,
|
||||
public WebGLZeroingObject,
|
||||
public WebGLRectangleObject,
|
||||
public WebGLContextBoundObject
|
||||
{
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(WEBGLRENDERBUFFER_PRIVATE_IID)
|
||||
|
||||
WebGLRenderbuffer(WebGLContext *context, WebGLuint name) :
|
||||
WebGLContextBoundObject(context),
|
||||
mName(name), mDeleted(PR_FALSE)
|
||||
{ }
|
||||
|
||||
void Delete() {
|
||||
if (mDeleted)
|
||||
return;
|
||||
ZeroOwners();
|
||||
mDeleted = PR_TRUE;
|
||||
}
|
||||
PRBool Deleted() { return mDeleted; }
|
||||
WebGLuint GLName() { return mName; }
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIWEBGLRENDERBUFFER
|
||||
protected:
|
||||
WebGLuint mName;
|
||||
PRBool mDeleted;
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(WebGLRenderbuffer, WEBGLRENDERBUFFER_PRIVATE_IID)
|
||||
|
||||
#define WEBGLUNIFORMLOCATION_PRIVATE_IID \
|
||||
{0x01a8a614, 0xb109, 0x42f1, {0xb4, 0x40, 0x8d, 0x8b, 0x87, 0x0b, 0x43, 0xa7}}
|
||||
class WebGLUniformLocation :
|
||||
|
|
|
@ -522,9 +522,13 @@ WebGLContext::CheckFramebufferStatus(WebGLenum target, WebGLenum *retval)
|
|||
|
||||
MakeContextCurrent();
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return ErrorInvalidEnum("CheckFramebufferStatus: target must be FRAMEBUFFER");
|
||||
return ErrorInvalidEnum("checkFramebufferStatus: target must be FRAMEBUFFER");
|
||||
|
||||
if (mBoundFramebuffer && mBoundFramebuffer->HasConflictingAttachments())
|
||||
*retval = LOCAL_GL_FRAMEBUFFER_UNSUPPORTED;
|
||||
else
|
||||
*retval = gl->fCheckFramebufferStatus(target);
|
||||
|
||||
*retval = gl->fCheckFramebufferStatus(target);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -532,6 +536,10 @@ NS_IMETHODIMP
|
|||
WebGLContext::Clear(PRUint32 mask)
|
||||
{
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
return NS_OK;
|
||||
|
||||
gl->fClear(mask);
|
||||
Invalidate();
|
||||
|
||||
|
@ -760,6 +768,7 @@ WebGLContext::DeleteRenderbuffer(nsIWebGLRenderbuffer *rbobj)
|
|||
*/
|
||||
|
||||
gl->fDeleteRenderbuffers(1, &rbufname);
|
||||
|
||||
rbuf->Delete();
|
||||
mMapRenderbuffers.Remove(rbufname);
|
||||
|
||||
|
@ -1047,6 +1056,9 @@ WebGLContext::DrawArrays(GLenum mode, WebGLint first, WebGLsizei count)
|
|||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
return NS_OK;
|
||||
|
||||
BindFakeBlackTextures();
|
||||
DoFakeVertexAttrib0(checked_firstPlusCount.value());
|
||||
|
||||
|
@ -1124,6 +1136,9 @@ WebGLContext::DrawElements(WebGLenum mode, WebGLsizei count, WebGLenum type, Web
|
|||
|
||||
MakeContextCurrent();
|
||||
|
||||
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
return NS_OK;
|
||||
|
||||
BindFakeBlackTextures();
|
||||
DoFakeVertexAttrib0(checked_neededCount.value());
|
||||
|
||||
|
@ -1171,43 +1186,13 @@ WebGLContext::EnableVertexAttribArray(WebGLuint index)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// XXX need to track this -- see glDeleteRenderbuffer above and man page for DeleteRenderbuffers
|
||||
NS_IMETHODIMP
|
||||
WebGLContext::FramebufferRenderbuffer(WebGLenum target, WebGLenum attachment, WebGLenum rbtarget, nsIWebGLRenderbuffer *rbobj)
|
||||
{
|
||||
WebGLuint renderbuffername;
|
||||
PRBool isNull;
|
||||
WebGLRenderbuffer *wrb;
|
||||
|
||||
if (!GetConcreteObjectAndGLName("framebufferRenderbuffer: renderbuffer", rbobj, &wrb, &renderbuffername, &isNull))
|
||||
return NS_OK;
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return ErrorInvalidEnumInfo("framebufferRenderbuffer: target", target);
|
||||
|
||||
if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
|
||||
attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mFramebufferColorAttachments.Length()) &&
|
||||
attachment != LOCAL_GL_DEPTH_ATTACHMENT &&
|
||||
attachment != LOCAL_GL_STENCIL_ATTACHMENT)
|
||||
{
|
||||
return ErrorInvalidEnumInfo("framebufferRenderbuffer: attachment", attachment);
|
||||
}
|
||||
|
||||
if (rbtarget != LOCAL_GL_RENDERBUFFER)
|
||||
return ErrorInvalidEnumInfo("framebufferRenderbuffer: renderbuffer target:", rbtarget);
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
return ErrorInvalidOperation("FramebufferRenderbuffer: cannot modify framebuffer 0");
|
||||
|
||||
// dimensions are kept for readPixels primarily, function only uses COLOR_ATTACHMENT0
|
||||
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
mBoundFramebuffer->setDimensions(wrb);
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
gl->fFramebufferRenderbuffer(target, attachment, rbtarget, renderbuffername);
|
||||
|
||||
return NS_OK;
|
||||
if (mBoundFramebuffer)
|
||||
return mBoundFramebuffer->FramebufferRenderbuffer(target, attachment, rbtarget, rbobj);
|
||||
else
|
||||
return ErrorInvalidOperation("framebufferRenderbuffer: cannot modify framebuffer 0");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -1217,44 +1202,10 @@ WebGLContext::FramebufferTexture2D(WebGLenum target,
|
|||
nsIWebGLTexture *tobj,
|
||||
WebGLint level)
|
||||
{
|
||||
WebGLuint texturename;
|
||||
PRBool isNull;
|
||||
WebGLTexture *wtex;
|
||||
|
||||
if (!GetConcreteObjectAndGLName("framebufferTexture2D: texture", tobj, &wtex, &texturename, &isNull))
|
||||
return NS_OK;
|
||||
|
||||
if (target != LOCAL_GL_FRAMEBUFFER)
|
||||
return ErrorInvalidEnumInfo("framebufferTexture2D: target", target);
|
||||
|
||||
if ((attachment < LOCAL_GL_COLOR_ATTACHMENT0 ||
|
||||
attachment >= LOCAL_GL_COLOR_ATTACHMENT0 + mFramebufferColorAttachments.Length()) &&
|
||||
attachment != LOCAL_GL_DEPTH_ATTACHMENT &&
|
||||
attachment != LOCAL_GL_STENCIL_ATTACHMENT)
|
||||
return ErrorInvalidEnumInfo("framebufferTexture2D: attachment", attachment);
|
||||
|
||||
if (textarget != LOCAL_GL_TEXTURE_2D &&
|
||||
(textarget < LOCAL_GL_TEXTURE_CUBE_MAP_POSITIVE_X ||
|
||||
textarget > LOCAL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))
|
||||
return ErrorInvalidEnumInfo("framebufferTexture2D: invalid texture target", textarget);
|
||||
|
||||
if (level != 0)
|
||||
return ErrorInvalidValue("FramebufferTexture2D: level must be 0");
|
||||
|
||||
if (!mBoundFramebuffer)
|
||||
return ErrorInvalidOperation("FramebufferTexture2D: cannot modify framebuffer 0");
|
||||
|
||||
// dimensions are kept for readPixels primarily, function only uses COLOR_ATTACHMENT0
|
||||
if (attachment == LOCAL_GL_COLOR_ATTACHMENT0)
|
||||
mBoundFramebuffer->setDimensions(wtex);
|
||||
|
||||
// XXXXX we need to store/reference this attachment!
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
gl->fFramebufferTexture2D(target, attachment, textarget, texturename, level);
|
||||
|
||||
return NS_OK;
|
||||
if (mBoundFramebuffer)
|
||||
return mBoundFramebuffer->FramebufferTexture2D(target, attachment, textarget, tobj, level);
|
||||
else
|
||||
return ErrorInvalidOperation("framebufferTexture2D: cannot modify framebuffer 0");
|
||||
}
|
||||
|
||||
GL_SAME_METHOD_0(Flush, Flush)
|
||||
|
@ -2540,8 +2491,6 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
|
|||
return ErrorInvalidEnumInfo("ReadPixels: type", type);
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
CheckedUint32 checked_plainRowSize = CheckedUint32(width) * size;
|
||||
|
||||
PRUint32 packAlignment = mPixelStorePackAlignment;
|
||||
|
@ -2559,6 +2508,12 @@ WebGLContext::ReadPixels_base(WebGLint x, WebGLint y, WebGLsizei width, WebGLsiz
|
|||
if (checked_neededByteLength.value() > byteLength)
|
||||
return ErrorInvalidOperation("ReadPixels: buffer too small");
|
||||
|
||||
MakeContextCurrent();
|
||||
|
||||
// prevent readback of arbitrary video memory through uninitialized renderbuffers!
|
||||
if (mBoundFramebuffer && !mBoundFramebuffer->CheckAndInitializeRenderbuffers())
|
||||
return NS_OK;
|
||||
|
||||
if (CanvasUtils::CheckSaneSubrectSize(x, y, width, height, boundWidth, boundHeight)) {
|
||||
// the easy case: we're not reading out-of-range pixels
|
||||
gl->fReadPixels(x, y, width, height, format, type, data);
|
||||
|
@ -2645,32 +2600,57 @@ WebGLContext::ReadPixels_buf(WebGLint x, WebGLint y, WebGLsizei width, WebGLsize
|
|||
NS_IMETHODIMP
|
||||
WebGLContext::RenderbufferStorage(WebGLenum target, WebGLenum internalformat, WebGLsizei width, WebGLsizei height)
|
||||
{
|
||||
if (target != LOCAL_GL_RENDERBUFFER)
|
||||
return ErrorInvalidEnumInfo("RenderbufferStorage: target", target);
|
||||
|
||||
switch (internalformat) {
|
||||
case LOCAL_GL_RGBA4:
|
||||
// XXX case LOCAL_GL_RGB565:
|
||||
case LOCAL_GL_RGB5_A1:
|
||||
case LOCAL_GL_DEPTH_COMPONENT:
|
||||
case LOCAL_GL_DEPTH_COMPONENT16:
|
||||
case LOCAL_GL_STENCIL_INDEX8:
|
||||
break;
|
||||
default:
|
||||
return ErrorInvalidEnumInfo("RenderbufferStorage: internalformat", internalformat);
|
||||
}
|
||||
if (!mBoundRenderbuffer || !mBoundRenderbuffer->GLName())
|
||||
return ErrorInvalidOperation("renderbufferStorage called on renderbuffer 0");
|
||||
|
||||
if (target != LOCAL_GL_RENDERBUFFER)
|
||||
return ErrorInvalidEnumInfo("renderbufferStorage: target", target);
|
||||
|
||||
if (width <= 0 || height <= 0)
|
||||
return ErrorInvalidValue("RenderbufferStorage: width and height must be > 0");
|
||||
return ErrorInvalidValue("renderbufferStorage: width and height must be > 0");
|
||||
|
||||
if (mBoundRenderbuffer)
|
||||
mBoundRenderbuffer->setDimensions(width, height);
|
||||
if (!mBoundRenderbuffer || !mBoundRenderbuffer->GLName())
|
||||
return ErrorInvalidOperation("renderbufferStorage called on renderbuffer 0");
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fRenderbufferStorage(target, internalformat, width, height);
|
||||
|
||||
// now we need to initialize the renderbuffer to 0 as per the thread "about RenderBufferStorage"
|
||||
// on the public_webgl list
|
||||
// certain OpenGL ES renderbuffer formats may not exist on desktop OpenGL
|
||||
WebGLenum internalformatForGL = internalformat;
|
||||
|
||||
switch (internalformat) {
|
||||
case LOCAL_GL_RGBA4:
|
||||
case LOCAL_GL_RGB5_A1:
|
||||
// 16-bit RGBA formats are not supported on desktop GL
|
||||
if (!gl->IsGLES2()) internalformatForGL = LOCAL_GL_RGBA8;
|
||||
break;
|
||||
case LOCAL_GL_RGB565:
|
||||
// the RGB565 format is not supported on desktop GL
|
||||
if (!gl->IsGLES2()) internalformatForGL = LOCAL_GL_RGB8;
|
||||
break;
|
||||
case LOCAL_GL_DEPTH_COMPONENT16:
|
||||
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
|
||||
// in OpenGL ES 3 (at least it will have some DEPTH_STENCIL) and is the same value that
|
||||
// is otherwise provided by EXT_packed_depth_stencil and OES_packed_depth_stencil extensions
|
||||
// which means it's supported on most GL and GL ES systems already.
|
||||
//
|
||||
// So we just use it hoping that it's available (perhaps as an extension) and if it's not available,
|
||||
// we just let the GL generate an error and don't do anything about it ourselves.
|
||||
internalformatForGL = LOCAL_GL_DEPTH24_STENCIL8;
|
||||
break;
|
||||
default:
|
||||
ErrorInvalidEnumInfo("renderbufferStorage: internalformat", internalformat);
|
||||
}
|
||||
|
||||
gl->fRenderbufferStorage(target, internalformatForGL, width, height);
|
||||
|
||||
mBoundRenderbuffer->SetInternalFormat(internalformat);
|
||||
mBoundRenderbuffer->setDimensions(width, height);
|
||||
mBoundRenderbuffer->SetInitialized(PR_FALSE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -362,10 +362,6 @@ WebGLContext::InitAndValidateGL()
|
|||
mBoundElementArrayBuffer = nsnull;
|
||||
mCurrentProgram = nsnull;
|
||||
|
||||
mFramebufferColorAttachments.Clear();
|
||||
mFramebufferDepthAttachment = nsnull;
|
||||
mFramebufferStencilAttachment = nsnull;
|
||||
|
||||
mBoundFramebuffer = nsnull;
|
||||
mBoundRenderbuffer = nsnull;
|
||||
|
||||
|
@ -433,7 +429,7 @@ WebGLContext::InitAndValidateGL()
|
|||
// Always 1 for GLES2
|
||||
val = 1;
|
||||
#endif
|
||||
mFramebufferColorAttachments.SetLength(val);
|
||||
mMaxFramebufferColorAttachments = val;
|
||||
|
||||
#if defined(DEBUG_vladimir) && defined(USE_GLES2)
|
||||
gl->fGetIntegerv(LOCAL_GL_IMPLEMENTATION_COLOR_READ_FORMAT, (GLint*) &val);
|
||||
|
|
|
@ -3,9 +3,6 @@ conformance/constants.html
|
|||
conformance/context-attributes-alpha-depth-stencil-antialias.html
|
||||
conformance/context-attributes.html
|
||||
conformance/context-type-test.html
|
||||
conformance/framebuffer-object-attachment.html
|
||||
conformance/get-active-test.html
|
||||
conformance/gl-enum-tests.html
|
||||
conformance/gl-get-calls.html
|
||||
conformance/gl-teximage.html
|
||||
conformance/glsl-conformance.html
|
||||
|
@ -13,10 +10,8 @@ conformance/methods.html
|
|||
conformance/program-test.html
|
||||
conformance/read-pixels-pack-alignment.html
|
||||
conformance/tex-image-and-sub-image-2d-with-video.html
|
||||
conformance/tex-image-with-format-and-type.html
|
||||
conformance/tex-image-with-invalid-data.html
|
||||
conformance/tex-input-validation.html
|
||||
conformance/texture-active-bind.html
|
||||
more/conformance/constants.html
|
||||
more/conformance/getContext.html
|
||||
more/conformance/quickCheckAPI.html
|
||||
|
|
|
@ -510,6 +510,7 @@ interface nsICanvasRenderingContextWebGL : nsISupports
|
|||
const unsigned long DEPTH_COMPONENT16 = 0x81A5;
|
||||
const unsigned long STENCIL_INDEX = 0x1901;
|
||||
const unsigned long STENCIL_INDEX8 = 0x8D48;
|
||||
const unsigned long DEPTH_STENCIL = 0x84F9;
|
||||
|
||||
const unsigned long RENDERBUFFER_WIDTH = 0x8D42;
|
||||
const unsigned long RENDERBUFFER_HEIGHT = 0x8D43;
|
||||
|
@ -529,6 +530,7 @@ interface nsICanvasRenderingContextWebGL : nsISupports
|
|||
const unsigned long COLOR_ATTACHMENT0 = 0x8CE0;
|
||||
const unsigned long DEPTH_ATTACHMENT = 0x8D00;
|
||||
const unsigned long STENCIL_ATTACHMENT = 0x8D20;
|
||||
const unsigned long DEPTH_STENCIL_ATTACHMENT = 0x821A;
|
||||
|
||||
const unsigned long NONE = 0;
|
||||
|
||||
|
|
|
@ -550,6 +550,7 @@ typedef ptrdiff_t GLintptr;
|
|||
#define LOCAL_GL_RGBA2 0x8055
|
||||
#define LOCAL_GL_RGBA4 0x8056
|
||||
#define LOCAL_GL_RGB5_A1 0x8057
|
||||
#define LOCAL_GL_RGB565 0x8D62
|
||||
#define LOCAL_GL_RGBA8 0x8058
|
||||
#define LOCAL_GL_RGB10_A2 0x8059
|
||||
#define LOCAL_GL_RGBA12 0x805A
|
||||
|
@ -1809,6 +1810,7 @@ typedef ptrdiff_t GLintptr;
|
|||
#define LOCAL_GL_COLOR_ATTACHMENT15 0x8CEF
|
||||
#define LOCAL_GL_DEPTH_ATTACHMENT 0x8D00
|
||||
#define LOCAL_GL_STENCIL_ATTACHMENT 0x8D20
|
||||
#define LOCAL_GL_DEPTH_STENCIL_ATTACHMENT 0x821A
|
||||
#define LOCAL_GL_FRAMEBUFFER 0x8D40
|
||||
#define LOCAL_GL_RENDERBUFFER 0x8D41
|
||||
#define LOCAL_GL_RENDERBUFFER_WIDTH 0x8D42
|
||||
|
@ -1875,6 +1877,7 @@ typedef ptrdiff_t GLintptr;
|
|||
#define LOCAL_GL_MULTISAMPLE_BIT_EXT 0x20000000
|
||||
#define LOCAL_GL_EXT_packed_depth_stencil 1
|
||||
#define LOCAL_GL_DEPTH_STENCIL_EXT 0x84F9
|
||||
#define LOCAL_GL_DEPTH_STENCIL 0x84F9
|
||||
#define LOCAL_GL_UNSIGNED_INT_24_8_EXT 0x84FA
|
||||
#define LOCAL_GL_DEPTH24_STENCIL8_EXT 0x88F0
|
||||
#define LOCAL_GL_DEPTH24_STENCIL8 0x88F0
|
||||
|
|
Загрузка…
Ссылка в новой задаче