Refactor glReadPixels validation.
Bug swiftshader:104
Change-Id: I2e5ab18f400035ec3f2125fb001643ca1125c565
Reviewed-on: https://swiftshader-review.googlesource.com/18148
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/common/Image.cpp b/src/OpenGL/common/Image.cpp
index 988b532..cdded3a 100644
--- a/src/OpenGL/common/Image.cpp
+++ b/src/OpenGL/common/Image.cpp
@@ -155,8 +155,7 @@
switch(type)
{
case GL_UNSIGNED_SHORT: return sw::FORMAT_D16;
- case GL_UNSIGNED_INT_24_8_OES: return sw::FORMAT_D24S8;
- case GL_UNSIGNED_INT: return sw::FORMAT_D32;
+ case GL_UNSIGNED_INT_24_8_OES: return sw::FORMAT_D24X8;
case GL_FLOAT: return sw::FORMAT_D32F_LOCKABLE;
default: UNREACHABLE(type);
}
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index e257174..fbbb356 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -3298,9 +3298,9 @@
return error(GL_INVALID_OPERATION);
}
- if(!IsValidReadPixelsFormatType(framebuffer, format, type))
+ if(!ValidateReadPixelsFormatType(framebuffer, format, type))
{
- return error(GL_INVALID_OPERATION);
+ return;
}
GLsizei outputWidth = (mState.packParameters.rowLength > 0) ? mState.packParameters.rowLength : width;
@@ -3335,14 +3335,12 @@
return error(GL_INVALID_OPERATION);
}
- sw::RectF rect((float)x, (float)y, (float)(x + width), (float)(y + height));
- sw::Rect dstRect(0, 0, width, height);
- rect.clip(0.0f, 0.0f, (float)renderTarget->getWidth(), (float)renderTarget->getHeight());
+ sw::SliceRectF srcRect((float)x, (float)y, (float)(x + width), (float)(y + height), 0);
+ sw::SliceRect dstRect(0, 0, width, height, 0);
+ srcRect.clip(0.0f, 0.0f, (float)renderTarget->getWidth(), (float)renderTarget->getHeight());
- sw::Surface *externalSurface = sw::Surface::create(width, height, 1, gl::ConvertReadFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight);
- sw::SliceRectF sliceRect(rect);
- sw::SliceRect dstSliceRect(dstRect);
- device->blit(renderTarget, sliceRect, externalSurface, dstSliceRect, false, false, false);
+ sw::Surface *externalSurface = sw::Surface::create(width, height, 1, gl::ConvertReadFormatType(format, type), pixels, outputPitch, outputPitch * outputHeight);
+ device->blit(renderTarget, srcRect, externalSurface, dstRect, false, false, false);
externalSurface->lockExternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);
externalSurface->unlockExternal();
delete externalSurface;
diff --git a/src/OpenGL/libGLESv2/Framebuffer.cpp b/src/OpenGL/libGLESv2/Framebuffer.cpp
index 4a9be7b..fd9cd10 100644
--- a/src/OpenGL/libGLESv2/Framebuffer.cpp
+++ b/src/OpenGL/libGLESv2/Framebuffer.cpp
@@ -354,7 +354,7 @@
}
else if(IsTextureTarget(mColorbufferType[i]))
{
- GLenum format = colorbuffer->getFormat();
+ GLint format = colorbuffer->getFormat();
if(!IsColorRenderable(format))
{
@@ -668,7 +668,7 @@
case GL_DEPTH_COMPONENT32_OES: return GL_UNSIGNED_INT;
case GL_DEPTH_COMPONENT32F: return GL_FLOAT;
case GL_DEPTH24_STENCIL8: return GL_UNSIGNED_INT_24_8_OES;
- case GL_DEPTH32F_STENCIL8: return GL_FLOAT;
+ case GL_DEPTH32F_STENCIL8: return GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
default:
UNREACHABLE(depthbuffer->getFormat());
}
diff --git a/src/OpenGL/libGLESv2/utilities.cpp b/src/OpenGL/libGLESv2/utilities.cpp
index 246b71c..4108a79 100644
--- a/src/OpenGL/libGLESv2/utilities.cpp
+++ b/src/OpenGL/libGLESv2/utilities.cpp
@@ -623,7 +623,7 @@
return true;
}
- bool IsValidReadPixelsFormatType(const Framebuffer *framebuffer, GLenum format, GLenum type)
+ bool ValidateReadPixelsFormatType(const Framebuffer *framebuffer, GLenum format, GLenum type)
{
// GL_NV_read_depth
if(format == GL_DEPTH_COMPONENT)
@@ -632,25 +632,56 @@
if(!depthbuffer)
{
- return false;
+ return error(GL_INVALID_OPERATION, false);
}
+ GLint internalformat = depthbuffer->getFormat();
+
switch(type)
{
case GL_UNSIGNED_SHORT:
+ case GL_UNSIGNED_INT_24_8_OES:
+ switch(internalformat)
+ {
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32_OES:
+ case GL_DEPTH24_STENCIL8:
+ break;
+ case GL_DEPTH_COMPONENT32F:
+ case GL_DEPTH32F_STENCIL8:
+ return error(GL_INVALID_OPERATION, false);
+ default:
+ UNREACHABLE(internalformat);
+ return error(GL_INVALID_OPERATION, false);
+ }
case GL_FLOAT:
- return true;
+ switch(internalformat)
+ {
+ case GL_DEPTH_COMPONENT32F:
+ case GL_DEPTH32F_STENCIL8:
+ break;
+ case GL_DEPTH_COMPONENT16:
+ case GL_DEPTH_COMPONENT24:
+ case GL_DEPTH_COMPONENT32_OES:
+ case GL_DEPTH24_STENCIL8:
+ return error(GL_INVALID_OPERATION, false);
+ default:
+ UNREACHABLE(internalformat);
+ return error(GL_INVALID_OPERATION, false);
+ }
default:
- UNIMPLEMENTED();
- return false;
+ return error(GL_INVALID_ENUM, false);
}
+
+ return true;
}
Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer();
if(!colorbuffer)
{
- return false;
+ return error(GL_INVALID_OPERATION, false);
}
GLint internalformat = colorbuffer->getFormat();
@@ -730,14 +761,12 @@
}
}
- return false;
+ return error(GL_INVALID_OPERATION, false);
}
- bool IsDepthTexture(GLenum format)
+ bool IsDepthTexture(GLint format)
{
- return format == GL_DEPTH_COMPONENT ||
- format == GL_DEPTH_STENCIL_OES ||
- format == GL_DEPTH_COMPONENT16 ||
+ return format == GL_DEPTH_COMPONENT16 ||
format == GL_DEPTH_COMPONENT24 ||
format == GL_DEPTH_COMPONENT32_OES ||
format == GL_DEPTH_COMPONENT32F ||
@@ -745,12 +774,11 @@
format == GL_DEPTH32F_STENCIL8;
}
- bool IsStencilTexture(GLenum format)
+ bool IsStencilTexture(GLint format)
{
- return format == GL_STENCIL_INDEX_OES ||
- format == GL_DEPTH_STENCIL_OES ||
- format == GL_DEPTH24_STENCIL8 ||
- format == GL_DEPTH32F_STENCIL8;
+ return format == GL_DEPTH24_STENCIL8 ||
+ format == GL_DEPTH32F_STENCIL8 ||
+ format == GL_STENCIL_INDEX8;
}
bool IsCubemapTextureTarget(GLenum target)
@@ -1142,8 +1170,9 @@
case GL_UNSIGNED_INT_2_10_10_10_REV:
case GL_UNSIGNED_INT_10F_11F_11F_REV:
case GL_UNSIGNED_INT_5_9_9_9_REV:
- case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
return 4;
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ return 8;
default:
UNREACHABLE(type);
break;
diff --git a/src/OpenGL/libGLESv2/utilities.h b/src/OpenGL/libGLESv2/utilities.h
index 00f577e..3b2704e 100644
--- a/src/OpenGL/libGLESv2/utilities.h
+++ b/src/OpenGL/libGLESv2/utilities.h
@@ -51,9 +51,9 @@
GLenum ValidateSubImageParams(bool compressed, bool copy, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, Texture *texture);
bool ValidateCopyFormats(GLenum textureFormat, GLenum colorbufferFormat);
- bool IsValidReadPixelsFormatType(const Framebuffer *framebuffer, GLenum format, GLenum type);
- bool IsDepthTexture(GLenum format);
- bool IsStencilTexture(GLenum format);
+ bool ValidateReadPixelsFormatType(const Framebuffer *framebuffer, GLenum format, GLenum type);
+ bool IsDepthTexture(GLint format);
+ bool IsStencilTexture(GLint format);
bool IsCubemapTextureTarget(GLenum target);
int CubeFaceIndex(GLenum cubeTarget);
bool IsTextureTarget(GLenum target);
diff --git a/src/Renderer/Blitter.cpp b/src/Renderer/Blitter.cpp
index 4245cd4..6522a13 100644
--- a/src/Renderer/Blitter.cpp
+++ b/src/Renderer/Blitter.cpp
@@ -389,7 +389,8 @@
c.x = Float(Int((*Pointer<UShort>(element))));
break;
case FORMAT_D24S8:
- c.x = Float(Int((*Pointer<UInt>(element))));
+ case FORMAT_D24X8:
+ c.x = Float(Int((*Pointer<UInt>(element) & UInt(0xFFFFFF00)) >> 8));
break;
case FORMAT_D32:
c.x = Float(Int((*Pointer<UInt>(element))));
@@ -755,7 +756,8 @@
*Pointer<UShort>(element) = UShort(RoundInt(Float(c.x)));
break;
case FORMAT_D24S8:
- *Pointer<UInt>(element) = UInt(RoundInt(Float(c.x)));
+ case FORMAT_D24X8:
+ *Pointer<UInt>(element) = UInt(RoundInt(Float(c.x)) << 8);
break;
case FORMAT_D32:
*Pointer<UInt>(element) = UInt(RoundInt(Float(c.x)));
@@ -1050,6 +1052,7 @@
scale = vector(0xFFFF, 0.0f, 0.0f, 0.0f);
break;
case FORMAT_D24S8:
+ case FORMAT_D24X8:
scale = vector(0xFFFFFF, 0.0f, 0.0f, 0.0f);
break;
case FORMAT_D32: