Framebuffer related validity checks
Added validity checks for RenderbufferStorageMultisample
and BlitFramebuffer, mostly missing checks for using
integer types or depth/stencil framebuffers with
multisampling, which is not allowed.
Fixes all failures in:
dEQP-GLES3.functional.negative_api.buffer*
Change-Id: Ie1db21a3b9f1ca71ed660a2758d43f24846acdf1
Reviewed-on: https://swiftshader-review.googlesource.com/14048
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index 49e6ba2..ede3df6 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -4111,6 +4111,52 @@
return error(GL_INVALID_OPERATION);
}
+ // The GL ES 3.0.2 spec (pg 193) states that:
+ // 1) If the read buffer is fixed point format, the draw buffer must be as well
+ // 2) If the read buffer is an unsigned integer format, the draw buffer must be
+ // as well
+ // 3) If the read buffer is a signed integer format, the draw buffer must be as
+ // well
+ es2::Renderbuffer *readRenderbuffer = readFramebuffer->getReadColorbuffer();
+ es2::Renderbuffer *drawRenderbuffer = drawFramebuffer->getColorbuffer(0);
+ sw::Format readFormat = readRenderbuffer->getInternalFormat();
+ sw::Format drawFormat = drawRenderbuffer->getInternalFormat();
+ GLenum readComponentType = sw2es::GetComponentType(readFormat, GL_COLOR_ATTACHMENT0);
+ GLenum drawComponentType = sw2es::GetComponentType(drawFormat, GL_COLOR_ATTACHMENT0);
+ bool readFixedPoint = ((readComponentType == GL_UNSIGNED_NORMALIZED) ||
+ (readComponentType == GL_SIGNED_NORMALIZED));
+ bool drawFixedPoint = ((drawComponentType == GL_UNSIGNED_NORMALIZED) ||
+ (drawComponentType == GL_SIGNED_NORMALIZED));
+ bool readFixedOrFloat = (readFixedPoint || (readComponentType == GL_FLOAT));
+ bool drawFixedOrFloat = (drawFixedPoint || (drawComponentType == GL_FLOAT));
+
+ if(readFixedOrFloat != drawFixedOrFloat)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if((readComponentType == GL_UNSIGNED_INT) && (drawComponentType != GL_UNSIGNED_INT))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if((readComponentType == GL_INT) && (drawComponentType != GL_INT))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ // Cannot filter integer data
+ if(((readComponentType == GL_UNSIGNED_INT) || (readComponentType == GL_INT)) && filter)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
+ if((readRenderbuffer->getSamples() > 0) &&
+ (readRenderbuffer->getFormat() != drawRenderbuffer->getFormat()))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
blitRenderTarget = true;
}
@@ -4134,6 +4180,11 @@
blitDepth = true;
readDSBuffer = readFramebuffer->getDepthbuffer();
drawDSBuffer = drawFramebuffer->getDepthbuffer();
+
+ if(readDSBuffer->getInternalFormat() != drawDSBuffer->getInternalFormat())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
}
}
@@ -4152,6 +4203,11 @@
blitStencil = true;
readDSBuffer = readFramebuffer->getStencilbuffer();
drawDSBuffer = drawFramebuffer->getStencilbuffer();
+
+ if(readDSBuffer->getInternalFormat() != drawDSBuffer->getInternalFormat())
+ {
+ return error(GL_INVALID_OPERATION);
+ }
}
}
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index f16afed..c560600 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -4726,22 +4726,23 @@
return error(GL_INVALID_ENUM);
}
- if(width < 0 || height < 0 || samples < 0)
+ if(width < 0 || height < 0 || samples < 0 ||
+ width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
+ height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE)
{
return error(GL_INVALID_VALUE);
}
+ if(samples > es2::IMPLEMENTATION_MAX_SAMPLES ||
+ (sw::Surface::isNonNormalizedInteger(es2sw::ConvertRenderbufferFormat(internalformat)) && samples > 0))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
+
es2::Context *context = es2::getContext();
if(context)
{
- if(width > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
- height > es2::IMPLEMENTATION_MAX_RENDERBUFFER_SIZE ||
- samples > es2::IMPLEMENTATION_MAX_SAMPLES)
- {
- return error(GL_INVALID_VALUE);
- }
-
GLuint handle = context->getRenderbufferName();
if(handle == 0)
{
diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index 92813e2..aae9782 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -1498,7 +1498,12 @@
switch(filter)
{
case GL_NEAREST:
+ break;
case GL_LINEAR:
+ if((mask & GL_DEPTH_BUFFER_BIT) || (mask & GL_STENCIL_BUFFER_BIT))
+ {
+ return error(GL_INVALID_OPERATION);
+ }
break;
default:
return error(GL_INVALID_ENUM);
@@ -1547,7 +1552,7 @@
{
if(!textureObject)
{
- return error(GL_INVALID_VALUE);
+ return error(GL_INVALID_OPERATION);
}
textarget = textureObject->getTarget();
@@ -1575,9 +1580,17 @@
{
case GL_DRAW_FRAMEBUFFER:
case GL_FRAMEBUFFER:
+ if(context->getDrawFramebufferName() == 0)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
framebuffer = context->getDrawFramebuffer();
break;
case GL_READ_FRAMEBUFFER:
+ if(context->getReadFramebufferName() == 0)
+ {
+ return error(GL_INVALID_OPERATION);
+ }
framebuffer = context->getReadFramebuffer();
break;
default: