Bug 607774 - Implement the spec on Renderbuffers and Framebuffers - r=vladimir

This commit is contained in:
Benoit Jacob 2010-11-05 15:57:58 -04:00
Родитель 2a62f5cf45
Коммит 9294c1fa05
6 изменённых файлов: 406 добавлений и 144 удалений

Просмотреть файл

@ -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