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;

 		}