Add support for GL_NV_read_depth Change-Id: If2f96b4cc1c09cd28771740f09be5f84875033ab Reviewed-on: https://swiftshader-review.googlesource.com/5091 Reviewed-by: Nicolas Capens <capn@google.com> Tested-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/common/Image.cpp b/src/OpenGL/common/Image.cpp index 1abf389..6934787 100644 --- a/src/OpenGL/common/Image.cpp +++ b/src/OpenGL/common/Image.cpp
@@ -526,6 +526,16 @@ default: UNREACHABLE(type); } break; + case GL_DEPTH_COMPONENT: + 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_FLOAT: return sw::FORMAT_D32F; + default: UNREACHABLE(type); + } + break; default: UNREACHABLE(format); }
diff --git a/src/OpenGL/libGL/utilities.cpp b/src/OpenGL/libGL/utilities.cpp index d8b2a8b..f7feb20 100644 --- a/src/OpenGL/libGL/utilities.cpp +++ b/src/OpenGL/libGL/utilities.cpp
@@ -257,13 +257,14 @@ return sizeof(unsigned short); case GL_UNSIGNED_INT: case GL_UNSIGNED_INT_24_8_EXT: - case GL_UNSIGNED_INT_8_8_8_8_REV: + case GL_UNSIGNED_INT_8_8_8_8_REV: return sizeof(unsigned int); case GL_FLOAT: switch(format) { case GL_ALPHA: return sizeof(float); case GL_LUMINANCE: return sizeof(float); + case GL_DEPTH_COMPONENT: return sizeof(float); case GL_LUMINANCE_ALPHA: return sizeof(float) * 2; case GL_RGB: return sizeof(float) * 3; case GL_RGBA: return sizeof(float) * 4;
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp index 05626ee..4cb5303 100644 --- a/src/OpenGL/libGLESv2/Context.cpp +++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -3210,24 +3210,34 @@ } } -void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) +void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels) { - Framebuffer *framebuffer = getReadFramebuffer(); + Framebuffer *framebuffer = getReadFramebuffer(); int framebufferWidth, framebufferHeight, framebufferSamples; - if(framebuffer->completeness(framebufferWidth, framebufferHeight, framebufferSamples) != GL_FRAMEBUFFER_COMPLETE) - { - return error(GL_INVALID_FRAMEBUFFER_OPERATION); - } + if(framebuffer->completeness(framebufferWidth, framebufferHeight, framebufferSamples) != GL_FRAMEBUFFER_COMPLETE) + { + return error(GL_INVALID_FRAMEBUFFER_OPERATION); + } - if(getReadFramebufferName() != 0 && framebufferSamples != 0) - { - return error(GL_INVALID_OPERATION); - } + if(getReadFramebufferName() != 0 && framebufferSamples != 0) + { + return error(GL_INVALID_OPERATION); + } - GLenum readFormat = framebuffer->getImplementationColorReadFormat(); - GLenum readType = framebuffer->getImplementationColorReadType(); + GLenum readFormat = GL_NONE; + GLenum readType = GL_NONE; + switch(format) + { + case GL_DEPTH_COMPONENT: + readFormat = framebuffer->getDepthReadFormat(); + readType = framebuffer->getDepthReadType(); + break; + default: + readFormat = framebuffer->getImplementationColorReadFormat(); + readType = framebuffer->getImplementationColorReadType(); + break; + } if(!(readFormat == format && readType == type) && !ValidReadPixelsFormatType(readFormat, readType, format, type, clientVersion)) { @@ -3241,21 +3251,30 @@ pixels = ((char*)pixels) + egl::ComputePackingOffset(format, type, outputWidth, outputHeight, mState.packAlignment, mState.packSkipImages, mState.packSkipRows, mState.packSkipPixels); // Sized query sanity check - if(bufSize) - { - int requiredSize = outputPitch * height; - if(requiredSize > *bufSize) - { - return error(GL_INVALID_OPERATION); - } - } + if(bufSize) + { + int requiredSize = outputPitch * height; + if(requiredSize > *bufSize) + { + return error(GL_INVALID_OPERATION); + } + } - egl::Image *renderTarget = framebuffer->getReadRenderTarget(); + egl::Image *renderTarget = nullptr; + switch(format) + { + case GL_DEPTH_COMPONENT: + renderTarget = framebuffer->getDepthBuffer(); + break; + default: + renderTarget = framebuffer->getReadRenderTarget(); + break; + } - if(!renderTarget) - { - return error(GL_OUT_OF_MEMORY); - } + if(!renderTarget) + { + return error(GL_INVALID_OPERATION); + } sw::Rect rect = {x, y, x + width, y + height}; sw::Rect dstRect = { 0, 0, width, height }; @@ -4269,6 +4288,7 @@ (const GLubyte*)"GL_ANGLE_texture_compression_dxt5", #endif (const GLubyte*)"GL_NV_fence", + (const GLubyte*)"GL_NV_read_depth", (const GLubyte*)"GL_EXT_instanced_arrays", (const GLubyte*)"GL_ANGLE_instanced_arrays", };
diff --git a/src/OpenGL/libGLESv2/Framebuffer.cpp b/src/OpenGL/libGLESv2/Framebuffer.cpp index dd19870..85cbe7e 100644 --- a/src/OpenGL/libGLESv2/Framebuffer.cpp +++ b/src/OpenGL/libGLESv2/Framebuffer.cpp
@@ -602,6 +602,45 @@ return GL_UNSIGNED_BYTE; } +GLenum Framebuffer::getDepthReadFormat() +{ + Renderbuffer *depthbuffer = getDepthbuffer(); + + if (depthbuffer) + { + // There is only one depth read format. + return GL_DEPTH_COMPONENT; + } + + // If there is no depth buffer, GL_INVALID_OPERATION occurs. + return GL_NONE; +} + +GLenum Framebuffer::getDepthReadType() +{ + Renderbuffer *depthbuffer = getDepthbuffer(); + + if (depthbuffer) + { + switch (depthbuffer->getInternalFormat()) + { + case sw::FORMAT_D16: return GL_UNSIGNED_SHORT; + case sw::FORMAT_D24S8: return GL_UNSIGNED_INT_24_8_OES; + case sw::FORMAT_D32: return GL_UNSIGNED_INT; + case sw::FORMAT_D32F: + case sw::FORMAT_D32F_COMPLEMENTARY: + case sw::FORMAT_D32F_LOCKABLE: + case sw::FORMAT_D32FS8_TEXTURE: + case sw::FORMAT_D32FS8_SHADOW: return GL_FLOAT; + default: + UNREACHABLE(depthbuffer->getInternalFormat()); + } + } + + // If there is no depth buffer, GL_INVALID_OPERATION occurs. + return GL_NONE; +} + DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) { GLenum defaultRenderbufferType = egl::getClientVersion() < 3 ? GL_RENDERBUFFER : GL_FRAMEBUFFER_DEFAULT;
diff --git a/src/OpenGL/libGLESv2/Framebuffer.h b/src/OpenGL/libGLESv2/Framebuffer.h index 66f05f2..f88e883 100644 --- a/src/OpenGL/libGLESv2/Framebuffer.h +++ b/src/OpenGL/libGLESv2/Framebuffer.h
@@ -32,76 +32,78 @@ class Framebuffer { public: - Framebuffer(); + Framebuffer(); - virtual ~Framebuffer(); + virtual ~Framebuffer(); - void setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index, GLint level = 0, GLint layer = 0); - void setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level = 0, GLint layer = 0); - void setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level = 0, GLint layer = 0); + void setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index, GLint level = 0, GLint layer = 0); + void setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level = 0, GLint layer = 0); + void setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level = 0, GLint layer = 0); void setReadBuffer(GLenum buf); void setDrawBuffer(GLuint index, GLenum buf); GLenum getReadBuffer() const; GLenum getDrawBuffer(GLuint index) const; - void detachTexture(GLuint texture); - void detachRenderbuffer(GLuint renderbuffer); + void detachTexture(GLuint texture); + void detachRenderbuffer(GLuint renderbuffer); - egl::Image *getRenderTarget(GLuint index); - egl::Image *getReadRenderTarget(); + egl::Image *getRenderTarget(GLuint index); + egl::Image *getReadRenderTarget(); egl::Image *getDepthBuffer(); egl::Image *getStencilBuffer(); - Renderbuffer *getColorbuffer(GLuint index); - Renderbuffer *getReadColorbuffer(); - Renderbuffer *getDepthbuffer(); - Renderbuffer *getStencilbuffer(); + Renderbuffer *getColorbuffer(GLuint index); + Renderbuffer *getReadColorbuffer(); + Renderbuffer *getDepthbuffer(); + Renderbuffer *getStencilbuffer(); - GLenum getColorbufferType(GLuint index); - GLenum getDepthbufferType(); - GLenum getStencilbufferType(); + GLenum getColorbufferType(GLuint index); + GLenum getDepthbufferType(); + GLenum getStencilbufferType(); - GLuint getColorbufferName(GLuint index); - GLuint getDepthbufferName(); - GLuint getStencilbufferName(); + GLuint getColorbufferName(GLuint index); + GLuint getDepthbufferName(); + GLuint getStencilbufferName(); GLint getColorbufferLayer(GLuint index); GLint getDepthbufferLayer(); GLint getStencilbufferLayer(); - bool hasStencil(); + bool hasStencil(); GLenum completeness(); GLenum completeness(int &width, int &height, int &samples); GLenum getImplementationColorReadFormat(); GLenum getImplementationColorReadType(); + GLenum getDepthReadFormat(); + GLenum getDepthReadType(); virtual bool isDefaultFramebuffer() const { return false; } static bool IsRenderbuffer(GLenum type); protected: - GLenum mColorbufferType[MAX_COLOR_ATTACHMENTS]; - gl::BindingPointer<Renderbuffer> mColorbufferPointer[MAX_COLOR_ATTACHMENTS]; + GLenum mColorbufferType[MAX_COLOR_ATTACHMENTS]; + gl::BindingPointer<Renderbuffer> mColorbufferPointer[MAX_COLOR_ATTACHMENTS]; GLenum readBuffer; GLenum drawBuffer[MAX_COLOR_ATTACHMENTS]; - GLenum mDepthbufferType; - gl::BindingPointer<Renderbuffer> mDepthbufferPointer; + GLenum mDepthbufferType; + gl::BindingPointer<Renderbuffer> mDepthbufferPointer; - GLenum mStencilbufferType; - gl::BindingPointer<Renderbuffer> mStencilbufferPointer; + GLenum mStencilbufferType; + gl::BindingPointer<Renderbuffer> mStencilbufferPointer; private: - Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle, GLint level, GLint layer) const; + Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle, GLint level, GLint layer) const; }; class DefaultFramebuffer : public Framebuffer { public: - DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); + DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); bool isDefaultFramebuffer() const override { return true; } };
diff --git a/src/OpenGL/libGLESv2/Renderbuffer.cpp b/src/OpenGL/libGLESv2/Renderbuffer.cpp index 39c9a79..d297046 100644 --- a/src/OpenGL/libGLESv2/Renderbuffer.cpp +++ b/src/OpenGL/libGLESv2/Renderbuffer.cpp
@@ -632,12 +632,6 @@ Depthbuffer::Depthbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil) { - if(depthStencil) - { - format = GL_DEPTH_COMPONENT16; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in - // glRenderbufferStorage - } } Depthbuffer::Depthbuffer(int width, int height, GLenum format, GLsizei samples) : DepthStencilbuffer(width, height, format, samples) @@ -650,12 +644,6 @@ Stencilbuffer::Stencilbuffer(egl::Image *depthStencil) : DepthStencilbuffer(depthStencil) { - if(depthStencil) - { - format = GL_STENCIL_INDEX8; // If the renderbuffer parameters are queried, the calling function - // will expect one of the valid renderbuffer formats for use in - // glRenderbufferStorage - } } Stencilbuffer::Stencilbuffer(int width, int height, GLsizei samples) : DepthStencilbuffer(width, height, GL_STENCIL_INDEX8, samples)
diff --git a/src/OpenGL/libGLESv2/utilities.cpp b/src/OpenGL/libGLESv2/utilities.cpp index 79f8f32..1333ea7 100644 --- a/src/OpenGL/libGLESv2/utilities.cpp +++ b/src/OpenGL/libGLESv2/utilities.cpp
@@ -652,6 +652,24 @@ case GL_RG_EXT: case GL_RED_EXT: return (clientVersion >= 3) && (type == GL_UNSIGNED_BYTE); + case GL_DEPTH_COMPONENT: + if (internalFormat != format) + { + return false; + } + switch(type) + { + case GL_UNSIGNED_SHORT: + case GL_FLOAT: + if (internalType != type) + { + return false; + } + break; + default: + return false; + } + break; default: return false; }