Fix conformance2/renderbuffers/invalidate-framebuffer.
draft
Fix conformance2/renderbuffers/invalidate-framebuffer.
--- a/dom/canvas/WebGL2ContextFramebuffers.cpp
+++ b/dom/canvas/WebGL2ContextFramebuffers.cpp
@@ -342,125 +342,18 @@ WebGL2Context::FramebufferTextureLayer(G
JS::Value
WebGL2Context::GetFramebufferAttachmentParameter(JSContext* cx,
GLenum target,
GLenum attachment,
GLenum pname,
ErrorResult& out_error)
{
- const char funcName[] = "getFramebufferAttachmentParameter";
-
- if (IsContextLost())
- return JS::NullValue();
-
- // OpenGL ES 3.0.4 (August 27, 2014) 6.1. QUERYING GL STATE 240
- // "getFramebufferAttachmentParamter returns information about attachments of a bound
- // framebuffer object. target must be DRAW_FRAMEBUFFER, READ_FRAMEBUFFER, or
- // FRAMEBUFFER."
-
- if (!ValidateFramebufferTarget(target, funcName))
- return JS::NullValue();
-
- // FRAMEBUFFER is equivalent to DRAW_FRAMEBUFFER.
- if (target == LOCAL_GL_FRAMEBUFFER)
- target = LOCAL_GL_DRAW_FRAMEBUFFER;
-
- WebGLFramebuffer* boundFB = nullptr;
- switch (target) {
- case LOCAL_GL_DRAW_FRAMEBUFFER: boundFB = mBoundDrawFramebuffer; break;
- case LOCAL_GL_READ_FRAMEBUFFER: boundFB = mBoundReadFramebuffer; break;
- }
-
- if (boundFB) {
- return boundFB->GetAttachmentParameter(funcName, cx, target, attachment, pname,
- &out_error);
- }
-
- ////////////////
- // Handle default FB
-
- // If the default framebuffer is bound to target, then attachment must be BACK,
- // identifying the color buffer; DEPTH, identifying the depth buffer; or STENCIL,
- // identifying the stencil buffer.
- switch (attachment) {
- case LOCAL_GL_BACK:
- case LOCAL_GL_DEPTH:
- case LOCAL_GL_STENCIL:
- case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
- break;
-
- default:
- ErrorInvalidEnum("%s: Can only query attachment BACK, DEPTH, or STENCIL from"
- " default framebuffer.",
- funcName);
- return JS::NullValue();
- }
-
- switch (pname) {
- case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
- return JS::Int32Value(LOCAL_GL_FRAMEBUFFER_DEFAULT);
-
- case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
- case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
- case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
- if (attachment != LOCAL_GL_BACK)
- return JS::Int32Value(0);
-
- return JS::Int32Value(8);
-
- case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
- if (attachment != LOCAL_GL_BACK)
- return JS::Int32Value(0);
-
- return JS::Int32Value(mOptions.alpha ? 8 : 0);
-
- case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
- if (attachment != LOCAL_GL_DEPTH &&
- attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
- {
- return JS::Int32Value(0);
- }
-
- return JS::Int32Value(mOptions.depth ? 16 : 0);
-
- case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
- if (attachment != LOCAL_GL_STENCIL &&
- attachment != LOCAL_GL_DEPTH_STENCIL_ATTACHMENT)
- {
- return JS::Int32Value(0);
- }
-
- return JS::Int32Value(mOptions.stencil ? 8 : 0);
-
- case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
- switch (attachment) {
- case LOCAL_GL_BACK: return JS::Int32Value(LOCAL_GL_UNSIGNED_NORMALIZED);
- case LOCAL_GL_DEPTH: return JS::Int32Value(LOCAL_GL_UNSIGNED_NORMALIZED);
- case LOCAL_GL_STENCIL: return JS::Int32Value(LOCAL_GL_UNSIGNED_INT);
-
- case LOCAL_GL_DEPTH_STENCIL_ATTACHMENT:
- ErrorInvalidOperation("getFramebufferAttachmentParameter: Querying "
- "FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE against "
- "DEPTH_STENCIL_ATTACHMENT is an error.");
- return JS::NullValue();
- }
- MOZ_CRASH("unreachable");
-
- case LOCAL_GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
- if (attachment != LOCAL_GL_BACK)
- return JS::Int32Value(0);
-
- return JS::Int32Value(LOCAL_GL_LINEAR);
- }
-
- // Any combinations of framebuffer type and pname not described above will generate an
- // INVALID_ENUM error.
- ErrorInvalidEnum("getFramebufferAttachmentParameter: Invalid combination of params.");
- return JS::NullValue();
+ return WebGLContext::GetFramebufferAttachmentParameter(cx, target, attachment, pname,
+ out_error);
}
// Map attachments intended for the default buffer, to attachments for a non-
// default buffer.
static bool
TranslateDefaultAttachments(const dom::Sequence<GLenum>& in, dom::Sequence<GLenum>* out)
{
for (size_t i = 0; i < in.Length(); i++) {
@@ -488,22 +381,24 @@ TranslateDefaultAttachments(const dom::S
return true;
}
void
WebGL2Context::InvalidateFramebuffer(GLenum target,
const dom::Sequence<GLenum>& attachments,
ErrorResult& rv)
{
+ const char funcName[] = "invalidateSubFramebuffer";
+
if (IsContextLost())
return;
MakeContextCurrent();
- if (!ValidateFramebufferTarget(target, "framebufferRenderbuffer"))
+ if (!ValidateFramebufferTarget(target, funcName))
return;
const WebGLFramebuffer* fb;
bool isDefaultFB;
switch (target) {
case LOCAL_GL_FRAMEBUFFER:
case LOCAL_GL_DRAW_FRAMEBUFFER:
fb = mBoundDrawFramebuffer;
@@ -514,57 +409,65 @@ WebGL2Context::InvalidateFramebuffer(GLe
fb = mBoundReadFramebuffer;
isDefaultFB = gl->Screen()->IsReadFramebufferDefault();
break;
default:
MOZ_CRASH("Bad target.");
}
+ const bool badColorAttachmentIsInvalidOp = true;
for (size_t i = 0; i < attachments.Length(); i++) {
- if (!ValidateFramebufferAttachment(fb, attachments[i],
- "invalidateFramebuffer"))
+ if (!ValidateFramebufferAttachment(fb, attachments[i], funcName,
+ badColorAttachmentIsInvalidOp))
{
return;
}
}
// InvalidateFramebuffer is a hint to the driver. Should be OK to
// skip calls if not supported, for example by OSX 10.9 GL
// drivers.
- static bool invalidateFBSupported = gl->IsSupported(gl::GLFeature::invalidate_framebuffer);
- if (!invalidateFBSupported)
+ if (!gl->IsSupported(gl::GLFeature::invalidate_framebuffer))
return;
if (!fb && !isDefaultFB) {
dom::Sequence<GLenum> tmpAttachments;
if (!TranslateDefaultAttachments(attachments, &tmpAttachments)) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
- gl->fInvalidateFramebuffer(target, tmpAttachments.Length(), tmpAttachments.Elements());
+ gl->fInvalidateFramebuffer(target, tmpAttachments.Length(),
+ tmpAttachments.Elements());
} else {
gl->fInvalidateFramebuffer(target, attachments.Length(), attachments.Elements());
}
}
void
WebGL2Context::InvalidateSubFramebuffer(GLenum target, const dom::Sequence<GLenum>& attachments,
GLint x, GLint y, GLsizei width, GLsizei height,
ErrorResult& rv)
{
+ const char funcName[] = "invalidateSubFramebuffer";
+
if (IsContextLost())
return;
MakeContextCurrent();
- if (!ValidateFramebufferTarget(target, "framebufferRenderbuffer"))
+ if (!ValidateFramebufferTarget(target, funcName))
return;
+ if (width < 0 || height < 0) {
+ ErrorInvalidValue("%s: width and height must be >= 0.", funcName);
+ return;
+ }
+
const WebGLFramebuffer* fb;
bool isDefaultFB;
switch (target) {
case LOCAL_GL_FRAMEBUFFER:
case LOCAL_GL_DRAW_FRAMEBUFFER:
fb = mBoundDrawFramebuffer;
isDefaultFB = gl->Screen()->IsDrawFramebufferDefault();
break;
@@ -573,43 +476,43 @@ WebGL2Context::InvalidateSubFramebuffer(
fb = mBoundReadFramebuffer;
isDefaultFB = gl->Screen()->IsReadFramebufferDefault();
break;
default:
MOZ_CRASH("Bad target.");
}
+ const bool badColorAttachmentIsInvalidOp = true;
for (size_t i = 0; i < attachments.Length(); i++) {
- if (!ValidateFramebufferAttachment(fb, attachments[i],
- "invalidateSubFramebuffer"))
+ if (!ValidateFramebufferAttachment(fb, attachments[i], funcName,
+ badColorAttachmentIsInvalidOp))
{
return;
}
}
// InvalidateFramebuffer is a hint to the driver. Should be OK to
// skip calls if not supported, for example by OSX 10.9 GL
// drivers.
- static bool invalidateFBSupported = gl->IsSupported(gl::GLFeature::invalidate_framebuffer);
- if (!invalidateFBSupported)
+ if (!gl->IsSupported(gl::GLFeature::invalidate_framebuffer))
return;
if (!fb && !isDefaultFB) {
dom::Sequence<GLenum> tmpAttachments;
if (!TranslateDefaultAttachments(attachments, &tmpAttachments)) {
rv.Throw(NS_ERROR_OUT_OF_MEMORY);
return;
}
- gl->fInvalidateSubFramebuffer(target, tmpAttachments.Length(), tmpAttachments.Elements(),
- x, y, width, height);
+ gl->fInvalidateSubFramebuffer(target, tmpAttachments.Length(),
+ tmpAttachments.Elements(), x, y, width, height);
} else {
- gl->fInvalidateSubFramebuffer(target, attachments.Length(), attachments.Elements(),
- x, y, width, height);
+ gl->fInvalidateSubFramebuffer(target, attachments.Length(),
+ attachments.Elements(), x, y, width, height);
}
}
void
WebGL2Context::ReadBuffer(GLenum mode)
{
if (IsContextLost())
return;
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -441,18 +441,19 @@ public:
void Finish();
void FramebufferRenderbuffer(GLenum target, GLenum attachment,
GLenum rbTarget, WebGLRenderbuffer* rb);
void FramebufferTexture2D(GLenum target, GLenum attachment,
GLenum texImageTarget, WebGLTexture* tex,
GLint level);
// Framebuffer validation
- bool ValidateFramebufferAttachment(const WebGLFramebuffer* fb,
- GLenum attachment, const char* funcName);
+ bool ValidateFramebufferAttachment(const WebGLFramebuffer* fb, GLenum attachment,
+ const char* funcName,
+ bool badColorAttachmentIsInvalidOp = false);
void FrontFace(GLenum mode);
already_AddRefed<WebGLActiveInfo> GetActiveAttrib(WebGLProgram* prog,
GLuint index);
already_AddRefed<WebGLActiveInfo> GetActiveUniform(WebGLProgram* prog,
GLuint index);
void
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -257,17 +257,18 @@ WebGLContext::ValidateDrawModeEnum(GLenu
default:
ErrorInvalidEnumInfo(info, mode);
return false;
}
}
bool
WebGLContext::ValidateFramebufferAttachment(const WebGLFramebuffer* fb, GLenum attachment,
- const char* funcName)
+ const char* funcName,
+ bool badColorAttachmentIsInvalidOp)
{
if (!fb) {
switch (attachment) {
case LOCAL_GL_COLOR:
case LOCAL_GL_DEPTH:
case LOCAL_GL_STENCIL:
return true;
@@ -286,18 +287,25 @@ WebGLContext::ValidateFramebufferAttachm
}
if (attachment >= LOCAL_GL_COLOR_ATTACHMENT0 &&
attachment <= LastColorAttachmentEnum())
{
return true;
}
- ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.", funcName,
- attachment);
+ if (badColorAttachmentIsInvalidOp &&
+ attachment >= LOCAL_GL_COLOR_ATTACHMENT0)
+ {
+ const uint32_t offset = attachment - LOCAL_GL_COLOR_ATTACHMENT0;
+ ErrorInvalidOperation("%s: Bad color attachment: COLOR_ATTACHMENT%u. (0x%04x)",
+ funcName, offset, attachment);
+ } else {
+ ErrorInvalidEnum("%s: attachment: Bad attachment 0x%x.", funcName, attachment);
+ }
return false;
}
/**
* Return true if pname is valid for GetSamplerParameter calls.
*/
bool
WebGLContext::ValidateSamplerParameterName(GLenum pname, const char* info)
--- a/dom/canvas/WebGLFramebuffer.cpp
+++ b/dom/canvas/WebGLFramebuffer.cpp
@@ -39,19 +39,22 @@ WebGLFBAttachPoint::IsDeleteRequested()
return Texture() ? Texture()->IsDeleteRequested()
: Renderbuffer() ? Renderbuffer()->IsDeleteRequested()
: false;
}
bool
WebGLFBAttachPoint::IsDefined() const
{
+ /*
return (Renderbuffer() && Renderbuffer()->IsDefined()) ||
(Texture() && Texture()->ImageInfoAt(mTexImageTarget,
mTexImageLevel).IsDefined());
+ */
+ return (Renderbuffer() || Texture());
}
const webgl::FormatUsageInfo*
WebGLFBAttachPoint::Format() const
{
MOZ_ASSERT(IsDefined());
if (Texture())
@@ -213,16 +216,18 @@ void
WebGLFBAttachPoint::OnBackingStoreRespecified() const
{
mFB->InvalidateFramebufferStatus();
}
bool
WebGLFBAttachPoint::IsComplete() const
{
+ MOZ_ASSERT(IsDefined());
+
if (!HasImage())
return false;
uint32_t width;
uint32_t height;
Size(&width, &height);
if (!width || !height)
return false;
@@ -647,34 +652,35 @@ WebGLFramebuffer::HasDefinedAttachments(
for (const auto& cur : mMoreColorAttachments) {
hasAttachments |= cur.IsDefined();
}
return hasAttachments;
}
-static bool
-IsIncomplete(const WebGLFBAttachPoint& cur)
-{
- return cur.IsDefined() && !cur.IsComplete();
-}
-
bool
WebGLFramebuffer::HasIncompleteAttachments() const
{
+ const auto fnIsIncomplete = [](const auto& cur) {
+ if (!cur.IsDefined())
+ return false; // Not defined, so can't count as incomplete.
+
+ return !cur.IsComplete();
+ };
+
bool hasIncomplete = false;
- hasIncomplete |= IsIncomplete(mColorAttachment0);
- hasIncomplete |= IsIncomplete(mDepthAttachment);
- hasIncomplete |= IsIncomplete(mStencilAttachment);
- hasIncomplete |= IsIncomplete(mDepthStencilAttachment);
+ hasIncomplete |= fnIsIncomplete(mColorAttachment0);
+ hasIncomplete |= fnIsIncomplete(mDepthAttachment);
+ hasIncomplete |= fnIsIncomplete(mStencilAttachment);
+ hasIncomplete |= fnIsIncomplete(mDepthStencilAttachment);
for (const auto& cur : mMoreColorAttachments) {
- hasIncomplete |= IsIncomplete(cur);
+ hasIncomplete |= fnIsIncomplete(cur);
}
return hasIncomplete;
}
static bool
MatchOrReplaceSize(const WebGLFBAttachPoint& cur, uint32_t* const out_width,
uint32_t* const out_height)