Implement framebuffer layer support.

This stores the layer as part of the framebuffer object, instead of the
renderbuffer, and passes it to the renderer at draw time.

Change-Id: I947f8a58ba7a119cc9d890659c99e7e05d0d1d91
Reviewed-on: https://swiftshader-review.googlesource.com/14728
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/OpenGL/common/Image.hpp b/src/OpenGL/common/Image.hpp
index 75d5249..052121c 100644
--- a/src/OpenGL/common/Image.hpp
+++ b/src/OpenGL/common/Image.hpp
@@ -53,7 +53,7 @@
 	// 2D texture image
 	Image(Texture *parentTexture, GLsizei width, GLsizei height, GLenum format, GLenum type)
 		: sw::Surface(parentTexture->getResource(), width, height, 1, 0, 1, SelectInternalFormat(format, type), true, true),
-		  width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(1),
+		  width(width), height(height), depth(1), format(format), type(type), internalFormat(SelectInternalFormat(format, type)),
 		  parentTexture(parentTexture)
 	{
 		shared = false;
@@ -64,7 +64,7 @@
 	// 3D/Cube texture image
 	Image(Texture *parentTexture, GLsizei width, GLsizei height, GLsizei depth, int border, GLenum format, GLenum type)
 		: sw::Surface(parentTexture->getResource(), width, height, depth, border, 1, SelectInternalFormat(format, type), true, true),
-		  width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(depth),
+		  width(width), height(height), depth(depth), format(format), type(type), internalFormat(SelectInternalFormat(format, type)),
 		  parentTexture(parentTexture)
 	{
 		shared = false;
@@ -75,7 +75,7 @@
 	// Native EGL image
 	Image(GLsizei width, GLsizei height, GLenum format, GLenum type, int pitchP)
 		: sw::Surface(nullptr, width, height, 1, 0, 1, SelectInternalFormat(format, type), true, true, pitchP),
-		  width(width), height(height), format(format), type(type), internalFormat(SelectInternalFormat(format, type)), depth(1),
+		  width(width), height(height), depth(1), format(format), type(type), internalFormat(SelectInternalFormat(format, type)),
 		  parentTexture(nullptr)
 	{
 		shared = true;
@@ -85,8 +85,7 @@
 	// Render target
 	Image(GLsizei width, GLsizei height, sw::Format internalFormat, int multiSampleDepth, bool lockable)
 		: sw::Surface(nullptr, width, height, 1, 0, multiSampleDepth, internalFormat, lockable, true),
-		  width(width), height(height), format(0 /*GL_NONE*/), type(0 /*GL_NONE*/), internalFormat(internalFormat),
-depth(multiSampleDepth),
+		  width(width), height(height), depth(1), format(0 /*GL_NONE*/), type(0 /*GL_NONE*/), internalFormat(internalFormat),
 		  parentTexture(nullptr)
 	{
 		shared = false;
@@ -200,10 +199,10 @@
 protected:
 	const GLsizei width;
 	const GLsizei height;
+	const int depth;
 	const GLenum format;
 	const GLenum type;
 	const sw::Format internalFormat;
-	const int depth;
 
 	bool shared;   // Used as an EGLImage
 
diff --git a/src/OpenGL/libGLESv2/Context.cpp b/src/OpenGL/libGLESv2/Context.cpp
index d8ff862..05b7eaa 100644
--- a/src/OpenGL/libGLESv2/Context.cpp
+++ b/src/OpenGL/libGLESv2/Context.cpp
@@ -2731,21 +2731,24 @@
 		if(framebuffer->getDrawBuffer(i) != GL_NONE)
 		{
 			egl::Image *renderTarget = framebuffer->getRenderTarget(i);
-			device->setRenderTarget(i, renderTarget);
+			GLint layer = framebuffer->getColorbufferLayer(i);
+			device->setRenderTarget(i, renderTarget, layer);
 			if(renderTarget) renderTarget->release();
 		}
 		else
 		{
-			device->setRenderTarget(i, nullptr);
+			device->setRenderTarget(i, nullptr, 0);
 		}
 	}
 
 	egl::Image *depthBuffer = framebuffer->getDepthBuffer();
-	device->setDepthBuffer(depthBuffer);
+	GLint dLayer = framebuffer->getDepthbufferLayer();
+	device->setDepthBuffer(depthBuffer, dLayer);
 	if(depthBuffer) depthBuffer->release();
 
 	egl::Image *stencilBuffer = framebuffer->getStencilBuffer();
-	device->setStencilBuffer(stencilBuffer);
+	GLint sLayer = framebuffer->getStencilbufferLayer();
+	device->setStencilBuffer(stencilBuffer, sLayer);
 	if(stencilBuffer) stencilBuffer->release();
 
 	Viewport viewport;
@@ -3203,7 +3206,7 @@
 				device->setTextureLevel(sampler, 0, mipmapLevel, surface, sw::TEXTURE_2D);
 			}
 		}
-		else if(baseTexture->getTarget() == GL_TEXTURE_3D_OES)
+		else if(baseTexture->getTarget() == GL_TEXTURE_3D)
 		{
 			Texture3D *texture = static_cast<Texture3D*>(baseTexture);
 
diff --git a/src/OpenGL/libGLESv2/Device.cpp b/src/OpenGL/libGLESv2/Device.cpp
index 598bd4f..1be27ff 100644
--- a/src/OpenGL/libGLESv2/Device.cpp
+++ b/src/OpenGL/libGLESv2/Device.cpp
@@ -364,7 +364,7 @@
 		scissorEnable = enable;
 	}
 
-	void Device::setRenderTarget(int index, egl::Image *renderTarget)
+	void Device::setRenderTarget(int index, egl::Image *renderTarget, unsigned int layer)
 	{
 		if(renderTarget)
 		{
@@ -378,10 +378,10 @@
 
 		this->renderTarget[index] = renderTarget;
 
-		Renderer::setRenderTarget(index, renderTarget);
+		Renderer::setRenderTarget(index, renderTarget, layer);
 	}
 
-	void Device::setDepthBuffer(egl::Image *depthBuffer)
+	void Device::setDepthBuffer(egl::Image *depthBuffer, unsigned int layer)
 	{
 		if(this->depthBuffer == depthBuffer)
 		{
@@ -400,10 +400,10 @@
 
 		this->depthBuffer = depthBuffer;
 
-		Renderer::setDepthBuffer(depthBuffer);
+		Renderer::setDepthBuffer(depthBuffer, layer);
 	}
 
-	void Device::setStencilBuffer(egl::Image *stencilBuffer)
+	void Device::setStencilBuffer(egl::Image *stencilBuffer, unsigned int layer)
 	{
 		if(this->stencilBuffer == stencilBuffer)
 		{
@@ -422,7 +422,7 @@
 
 		this->stencilBuffer = stencilBuffer;
 
-		Renderer::setStencilBuffer(stencilBuffer);
+		Renderer::setStencilBuffer(stencilBuffer, layer);
 	}
 
 	void Device::setScissorRect(const sw::Rect &rect)
diff --git a/src/OpenGL/libGLESv2/Device.hpp b/src/OpenGL/libGLESv2/Device.hpp
index 1b1492e..c197416 100644
--- a/src/OpenGL/libGLESv2/Device.hpp
+++ b/src/OpenGL/libGLESv2/Device.hpp
@@ -65,9 +65,9 @@
 		void setPixelShader(const sw::PixelShader *shader);
 		void setPixelShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count);
 		void setScissorEnable(bool enable);
-		void setRenderTarget(int index, egl::Image *renderTarget);
-		void setDepthBuffer(egl::Image *depthBuffer);
-		void setStencilBuffer(egl::Image *stencilBuffer);
+		void setRenderTarget(int index, egl::Image *renderTarget, unsigned int layer);
+		void setDepthBuffer(egl::Image *depthBuffer, unsigned int layer);
+		void setStencilBuffer(egl::Image *stencilBuffer, unsigned int layer);
 		void setScissorRect(const sw::Rect &rect);
 		void setVertexShader(const sw::VertexShader *shader);
 		void setVertexShaderConstantF(unsigned int startRegister, const float *constantData, unsigned int count);
diff --git a/src/OpenGL/libGLESv2/Framebuffer.cpp b/src/OpenGL/libGLESv2/Framebuffer.cpp
index e5a621e..ec3c321 100644
--- a/src/OpenGL/libGLESv2/Framebuffer.cpp
+++ b/src/OpenGL/libGLESv2/Framebuffer.cpp
@@ -32,19 +32,23 @@
 
 Framebuffer::Framebuffer()
 {
-	for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
-	{
-		mColorbufferType[i] = GL_NONE;
-	}
-	mDepthbufferType = GL_NONE;
-	mStencilbufferType = GL_NONE;
-
 	readBuffer = GL_COLOR_ATTACHMENT0;
 	drawBuffer[0] = GL_COLOR_ATTACHMENT0;
-	for(int i = 1; i < MAX_COLOR_ATTACHMENTS; ++i)
+	for(int i = 1; i < MAX_COLOR_ATTACHMENTS; i++)
 	{
 		drawBuffer[i] = GL_NONE;
 	}
+
+	for(int i = 0; i < MAX_COLOR_ATTACHMENTS; i++)
+	{
+		mColorbufferType[i] = GL_NONE;
+		mColorbufferLayer[i] = 0;
+	}
+
+	mDepthbufferType = GL_NONE;
+	mDepthbufferLayer = 0;
+	mStencilbufferType = GL_NONE;
+	mStencilbufferLayer = 0;
 }
 
 Framebuffer::~Framebuffer()
@@ -57,7 +61,7 @@
 	mStencilbufferPointer = nullptr;
 }
 
-Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint level, GLint layer) const
+Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint level) const
 {
 	Context *context = getContext();
 	Renderbuffer *buffer = nullptr;
@@ -72,7 +76,7 @@
 	}
 	else if(IsTextureTarget(type))
 	{
-		buffer = context->getTexture(handle)->getRenderbuffer(type, level, layer);
+		buffer = context->getTexture(handle)->getRenderbuffer(type, level);
 	}
 	else UNREACHABLE(type);
 
@@ -82,19 +86,22 @@
 void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index, GLint level, GLint layer)
 {
 	mColorbufferType[index] = (colorbuffer != 0) ? type : GL_NONE;
-	mColorbufferPointer[index] = lookupRenderbuffer(type, colorbuffer, level, layer);
+	mColorbufferPointer[index] = lookupRenderbuffer(type, colorbuffer, level);
+	mColorbufferLayer[index] = layer;
 }
 
 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
 {
 	mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
-	mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer, level, layer);
+	mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer, level);
+	mDepthbufferLayer = layer;
 }
 
 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
 {
 	mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
-	mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer, level, layer);
+	mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer, level);
+	mStencilbufferLayer = layer;
 }
 
 void Framebuffer::setReadBuffer(GLenum buf)
@@ -277,18 +284,17 @@
 
 GLint Framebuffer::getColorbufferLayer(GLuint index)
 {
-	Renderbuffer *colorbuffer = mColorbufferPointer[index];
-	return colorbuffer ? colorbuffer->getLayer() : 0;
+	return mColorbufferLayer[index];
 }
 
 GLint Framebuffer::getDepthbufferLayer()
 {
-	return mDepthbufferPointer ? mDepthbufferPointer->getLayer() : 0;
+	return mDepthbufferLayer;
 }
 
 GLint Framebuffer::getStencilbufferLayer()
 {
-	return mStencilbufferPointer ? mStencilbufferPointer->getLayer() : 0;
+	return mStencilbufferLayer;
 }
 
 bool Framebuffer::hasStencil()
@@ -332,7 +338,7 @@
 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 			}
 
-			if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0 || (colorbuffer->getDepth() <= colorbuffer->getLayer()))
+			if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0 || (colorbuffer->getDepth() <= mColorbufferLayer[i]))
 			{
 				return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 			}
@@ -373,7 +379,7 @@
 			}
 			else if(samples != colorbuffer->getSamples())
 			{
-				return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+				return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
 			}
 		}
 	}
@@ -390,7 +396,7 @@
 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 		}
 
-		if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
+		if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0 || (depthbuffer->getDepth() <= mDepthbufferLayer))
 		{
 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 		}
@@ -427,7 +433,7 @@
 		}
 		else if(samples != depthbuffer->getSamples())
 		{
-			return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+			return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
 		}
 	}
 
@@ -440,7 +446,7 @@
 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 		}
 
-		if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
+		if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0 || (stencilbuffer->getDepth() <= mStencilbufferLayer))
 		{
 			return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
 		}
@@ -479,7 +485,7 @@
 		}
 		else if(samples != stencilbuffer->getSamples())
 		{
-			return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+			return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
 		}
 	}
 
diff --git a/src/OpenGL/libGLESv2/Framebuffer.h b/src/OpenGL/libGLESv2/Framebuffer.h
index cbae1e3..e1a3611 100644
--- a/src/OpenGL/libGLESv2/Framebuffer.h
+++ b/src/OpenGL/libGLESv2/Framebuffer.h
@@ -96,15 +96,18 @@
 
 	GLenum mColorbufferType[MAX_COLOR_ATTACHMENTS];
 	gl::BindingPointer<Renderbuffer> mColorbufferPointer[MAX_COLOR_ATTACHMENTS];
+	GLint mColorbufferLayer[MAX_COLOR_ATTACHMENTS];
 
 	GLenum mDepthbufferType;
 	gl::BindingPointer<Renderbuffer> mDepthbufferPointer;
+	GLint mDepthbufferLayer;
 
 	GLenum mStencilbufferType;
 	gl::BindingPointer<Renderbuffer> mStencilbufferPointer;
+	GLint mStencilbufferLayer;
 
 private:
-	Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle, GLint level, GLint layer) const;
+	Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle, GLint level) const;
 };
 
 class DefaultFramebuffer : public Framebuffer
diff --git a/src/OpenGL/libGLESv2/Renderbuffer.cpp b/src/OpenGL/libGLESv2/Renderbuffer.cpp
index 61cc223..f68c6f3 100644
--- a/src/OpenGL/libGLESv2/Renderbuffer.cpp
+++ b/src/OpenGL/libGLESv2/Renderbuffer.cpp
@@ -129,18 +129,14 @@
 
 GLsizei RenderbufferTexture2D::getSamples() const
 {
-	return 0;
+	return 0;   // Core OpenGL ES 3.0 does not support multisample textures.
 }
 
 ///// RenderbufferTexture3D Implementation ////////
 
-RenderbufferTexture3D::RenderbufferTexture3D(Texture3D *texture, GLint level, GLint layer) : mLevel(level), mLayer(layer)
+RenderbufferTexture3D::RenderbufferTexture3D(Texture3D *texture, GLint level) : mLevel(level)
 {
 	mTexture3D = texture;
-	if(mLayer != 0)
-	{
-		UNIMPLEMENTED();
-	}
 }
 
 RenderbufferTexture3D::~RenderbufferTexture3D()
@@ -201,7 +197,7 @@
 
 GLsizei RenderbufferTexture3D::getSamples() const
 {
-	return 0;
+	return 0;   // Core OpenGL ES 3.0 does not support multisample textures.
 }
 
 ///// RenderbufferTextureCubeMap Implementation ////////
@@ -264,7 +260,7 @@
 
 GLsizei RenderbufferTextureCubeMap::getSamples() const
 {
-	return 0;
+	return 0;   // Core OpenGL ES 3.0 does not support multisample textures.
 }
 
 ////// Renderbuffer Implementation //////
@@ -330,11 +326,6 @@
 	return mInstance->getDepth();
 }
 
-GLint Renderbuffer::getLayer() const
-{
-	return mInstance->getLayer();
-}
-
 GLint Renderbuffer::getLevel() const
 {
 	return mInstance->getLevel();
@@ -380,11 +371,6 @@
 	return mInstance->getSamples();
 }
 
-void Renderbuffer::setLayer(GLint layer)
-{
-	return mInstance->setLayer(layer);
-}
-
 void Renderbuffer::setLevel(GLint level)
 {
 	return mInstance->setLevel(level);
diff --git a/src/OpenGL/libGLESv2/Renderbuffer.h b/src/OpenGL/libGLESv2/Renderbuffer.h
index c7719b5..f035d50 100644
--- a/src/OpenGL/libGLESv2/Renderbuffer.h
+++ b/src/OpenGL/libGLESv2/Renderbuffer.h
@@ -56,12 +56,10 @@
 	virtual GLsizei getWidth() const = 0;
 	virtual GLsizei getHeight() const = 0;
 	virtual GLsizei getDepth() const { return 1; }
-	virtual GLint getLayer() const { return 0; }
 	virtual GLint getLevel() const { return 0; }
 	virtual GLint getFormat() const = 0;
 	virtual GLsizei getSamples() const = 0;
 
-	virtual void setLayer(GLint) {}
 	virtual void setLevel(GLint) {}
 
 	GLuint getRedSize() const;
@@ -77,22 +75,22 @@
 public:
 	RenderbufferTexture2D(Texture2D *texture, GLint level);
 
-	virtual ~RenderbufferTexture2D();
+	~RenderbufferTexture2D() override;
 
-	virtual void addProxyRef(const Renderbuffer *proxy);
-    virtual void releaseProxy(const Renderbuffer *proxy);
+	void addProxyRef(const Renderbuffer *proxy) override;
+    void releaseProxy(const Renderbuffer *proxy) override;
 
-	virtual egl::Image *getRenderTarget();
-    virtual egl::Image *createSharedImage();
-    virtual bool isShared() const;
+	egl::Image *getRenderTarget() override;
+    egl::Image *createSharedImage() override;
+    bool isShared() const override;
 
-	virtual GLsizei getWidth() const;
-	virtual GLsizei getHeight() const;
-	virtual GLint getLevel() const { return mLevel; }
-	virtual GLint getFormat() const;
-	virtual GLsizei getSamples() const;
+	GLsizei getWidth() const override;
+	GLsizei getHeight() const override;
+	GLint getLevel() const override { return mLevel; }
+	GLint getFormat() const override;
+	GLsizei getSamples() const override;
 
-	virtual void setLevel(GLint level) { mLevel = level; }
+	void setLevel(GLint level) override { mLevel = level; }
 
 private:
 	gl::BindingPointer<Texture2D> mTexture2D;
@@ -102,32 +100,29 @@
 class RenderbufferTexture3D : public RenderbufferInterface
 {
 public:
-	RenderbufferTexture3D(Texture3D *texture, GLint level, GLint layer);
+	RenderbufferTexture3D(Texture3D *texture, GLint level);
 
-	virtual ~RenderbufferTexture3D();
+	~RenderbufferTexture3D() override;
 
-	virtual void addProxyRef(const Renderbuffer *proxy);
-	virtual void releaseProxy(const Renderbuffer *proxy);
+	void addProxyRef(const Renderbuffer *proxy) override;
+	void releaseProxy(const Renderbuffer *proxy) override;
 
-	virtual egl::Image *getRenderTarget();
-	virtual egl::Image *createSharedImage();
-	virtual bool isShared() const;
+	egl::Image *getRenderTarget() override;
+	egl::Image *createSharedImage() override;
+	bool isShared() const override;
 
-	virtual GLsizei getWidth() const;
-	virtual GLsizei getHeight() const;
-	virtual GLsizei getDepth() const;
-	virtual GLint getLayer() const { return mLayer; }
-	virtual GLint getLevel() const { return mLevel; }
-	virtual GLint getFormat() const;
-	virtual GLsizei getSamples() const;
+	GLsizei getWidth() const override;
+	GLsizei getHeight() const override;
+	GLsizei getDepth() const override;
+	GLint getLevel() const override { return mLevel; }
+	GLint getFormat() const override;
+	GLsizei getSamples() const override;
 
-	virtual void setLayer(GLint layer) { mLayer = layer; }
-	virtual void setLevel(GLint level) { mLevel = level; }
+	void setLevel(GLint level) override { mLevel = level; }
 
 private:
 	gl::BindingPointer<Texture3D> mTexture3D;
 	GLint mLevel;
-	GLint mLayer;
 };
 
 class RenderbufferTextureCubeMap : public RenderbufferInterface
@@ -135,22 +130,22 @@
 public:
 	RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target, GLint level);
 
-	virtual ~RenderbufferTextureCubeMap();
+	~RenderbufferTextureCubeMap() override;
 
-	virtual void addProxyRef(const Renderbuffer *proxy);
-    virtual void releaseProxy(const Renderbuffer *proxy);
+	void addProxyRef(const Renderbuffer *proxy) override;
+    void releaseProxy(const Renderbuffer *proxy) override;
 
-	virtual egl::Image *getRenderTarget();
-    virtual egl::Image *createSharedImage();
-    virtual bool isShared() const;
+	egl::Image *getRenderTarget() override;
+    egl::Image *createSharedImage() override;
+    bool isShared() const override;
 
-	virtual GLsizei getWidth() const;
-	virtual GLsizei getHeight() const;
-	virtual GLint getLevel() const { return mLevel; }
-	virtual GLint getFormat() const;
-	virtual GLsizei getSamples() const;
+	GLsizei getWidth() const override;
+	GLsizei getHeight() const override;
+	GLint getLevel() const override { return mLevel; }
+	GLint getFormat() const override;
+	GLsizei getSamples() const override;
 
-	virtual void setLevel(GLint level) { mLevel = level; }
+	void setLevel(GLint level) override { mLevel = level; }
 
 private:
 	gl::BindingPointer<TextureCubeMap> mTextureCubeMap;
@@ -166,16 +161,16 @@
 public:
 	RenderbufferStorage();
 
-	virtual ~RenderbufferStorage() = 0;
+	~RenderbufferStorage() override = 0;
 
-	virtual egl::Image *getRenderTarget() = 0;
-    virtual egl::Image *createSharedImage() = 0;
-    virtual bool isShared() const = 0;
+	egl::Image *getRenderTarget() override = 0;
+    egl::Image *createSharedImage() override = 0;
+    bool isShared() const override = 0;
 
-	virtual GLsizei getWidth() const;
-	virtual GLsizei getHeight() const;
-	virtual GLint getFormat() const;
-	virtual GLsizei getSamples() const;
+	GLsizei getWidth() const override;
+	GLsizei getHeight() const override;
+	GLint getFormat() const override;
+	GLsizei getSamples() const override;
 
 protected:
 	GLsizei mWidth;
@@ -192,14 +187,14 @@
 public:
 	Renderbuffer(GLuint name, RenderbufferInterface *storage);
 
-	virtual ~Renderbuffer();
+	~Renderbuffer() override;
 
 	// These functions from Object are overloaded here because
     // Textures need to maintain their own count of references to them via
     // Renderbuffers/RenderbufferTextures. These functions invoke those
     // reference counting functions on the RenderbufferInterface.
-    virtual void addRef();
-    virtual void release();
+    void addRef() override;
+    void release() override;
 
 	egl::Image *getRenderTarget();
     virtual egl::Image *createSharedImage();
@@ -208,7 +203,6 @@
 	GLsizei getWidth() const;
 	GLsizei getHeight() const;
 	GLsizei getDepth() const;
-	GLint getLayer() const;
 	GLint getLevel() const;
 	GLint getFormat() const;
 	GLuint getRedSize() const;
@@ -219,7 +213,6 @@
 	GLuint getStencilSize() const;
 	GLsizei getSamples() const;
 
-	void setLayer(GLint layer);
 	void setLevel(GLint level);
 	void setStorage(RenderbufferStorage *newStorage);
 
@@ -233,11 +226,11 @@
 	explicit Colorbuffer(egl::Image *renderTarget);
 	Colorbuffer(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
 
-	virtual ~Colorbuffer();
+	~Colorbuffer() override;
 
-	virtual egl::Image *getRenderTarget();
-    virtual egl::Image *createSharedImage();
-    virtual bool isShared() const;
+	egl::Image *getRenderTarget() override;
+    egl::Image *createSharedImage() override;
+    bool isShared() const override;
 
 private:
 	egl::Image *mRenderTarget;
@@ -251,9 +244,9 @@
 
 	~DepthStencilbuffer();
 
-	virtual egl::Image *getRenderTarget();
-    virtual egl::Image *createSharedImage();
-    virtual bool isShared() const;
+	egl::Image *getRenderTarget() override;
+    egl::Image *createSharedImage() override;
+    bool isShared() const override;
 
 protected:
 	egl::Image *mDepthStencil;
@@ -265,7 +258,7 @@
 	explicit Depthbuffer(egl::Image *depthStencil);
 	Depthbuffer(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
 
-	virtual ~Depthbuffer();
+	~Depthbuffer() override;
 };
 
 class Stencilbuffer : public DepthStencilbuffer
@@ -274,7 +267,7 @@
 	explicit Stencilbuffer(egl::Image *depthStencil);
 	Stencilbuffer(GLsizei width, GLsizei height, GLsizei samples);
 
-	virtual ~Stencilbuffer();
+	~Stencilbuffer() override;
 };
 }
 
diff --git a/src/OpenGL/libGLESv2/Texture.cpp b/src/OpenGL/libGLESv2/Texture.cpp
index 6618859..9ae1b11 100644
--- a/src/OpenGL/libGLESv2/Texture.cpp
+++ b/src/OpenGL/libGLESv2/Texture.cpp
@@ -894,7 +894,7 @@
 	return image[level];
 }
 
-Renderbuffer *Texture2D::getRenderbuffer(GLenum target, GLint level, GLint layer)
+Renderbuffer *Texture2D::getRenderbuffer(GLenum target, GLint level)
 {
 	if(target != GL_TEXTURE_2D)
 	{
@@ -1439,7 +1439,7 @@
 	}
 }
 
-Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target, GLint level, GLint layer)
+Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target, GLint level)
 {
 	if(!IsCubemapTextureTarget(target))
 	{
@@ -1878,7 +1878,7 @@
 	return image[level];
 }
 
-Renderbuffer *Texture3D::getRenderbuffer(GLenum target, GLint level, GLint layer)
+Renderbuffer *Texture3D::getRenderbuffer(GLenum target, GLint level)
 {
 	if(target != getTarget())
 	{
@@ -1887,12 +1887,11 @@
 
 	if(!mColorbufferProxy)
 	{
-		mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture3D(this, level, layer));
+		mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture3D(this, level));
 	}
 	else
 	{
 		mColorbufferProxy->setLevel(level);
-		mColorbufferProxy->setLayer(layer);
 	}
 
 	return mColorbufferProxy;
diff --git a/src/OpenGL/libGLESv2/Texture.h b/src/OpenGL/libGLESv2/Texture.h
index 6d04c53..bd34b33 100644
--- a/src/OpenGL/libGLESv2/Texture.h
+++ b/src/OpenGL/libGLESv2/Texture.h
@@ -103,7 +103,7 @@
 	virtual bool isCompressed(GLenum target, GLint level) const = 0;
 	virtual bool isDepth(GLenum target, GLint level) const = 0;
 
-	virtual Renderbuffer *getRenderbuffer(GLenum target, GLint level, GLint layer) = 0;
+	virtual Renderbuffer *getRenderbuffer(GLenum target, GLint level) = 0;
 	virtual egl::Image *getRenderTarget(GLenum target, unsigned int level) = 0;
 	egl::Image *createSharedImage(GLenum target, unsigned int level);
 	virtual bool isShared(GLenum target, unsigned int level) const = 0;
@@ -179,7 +179,7 @@
 
 	void generateMipmaps() override;
 
-	Renderbuffer *getRenderbuffer(GLenum target, GLint level, GLint layer) override;
+	Renderbuffer *getRenderbuffer(GLenum target, GLint level) override;
 	egl::Image *getRenderTarget(GLenum target, unsigned int level) override;
 	bool isShared(GLenum target, unsigned int level) const override;
 
@@ -236,7 +236,7 @@
 	void generateMipmaps() override;
 	void updateBorders(int level);
 
-	Renderbuffer *getRenderbuffer(GLenum target, GLint level, GLint layer) override;
+	Renderbuffer *getRenderbuffer(GLenum target, GLint level) override;
 	egl::Image *getRenderTarget(GLenum target, unsigned int level) override;
 	bool isShared(GLenum target, unsigned int level) const override;
 
@@ -297,7 +297,7 @@
 
 	void generateMipmaps() override;
 
-	Renderbuffer *getRenderbuffer(GLenum target, GLint level, GLint layer) override;
+	Renderbuffer *getRenderbuffer(GLenum target, GLint level) override;
 	egl::Image *getRenderTarget(GLenum target, unsigned int level) override;
 	bool isShared(GLenum target, unsigned int level) const override;
 
diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index ddc23e8..93a59a6 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -385,7 +385,7 @@
 			}
 			context->bindTexture2DArray(texture);
 			break;
-		case GL_TEXTURE_3D_OES:
+		case GL_TEXTURE_3D:
 			context->bindTexture3D(texture);
 			break;
 		default:
@@ -2273,7 +2273,7 @@
 				texture = context->getTexture2DArray();
 			}
 			break;
-		case GL_TEXTURE_3D_OES:
+		case GL_TEXTURE_3D:
 			texture = context->getTexture3D();
 			break;
 		default:
@@ -3356,7 +3356,7 @@
 		case GL_RENDERBUFFER_ALPHA_SIZE:      *params = renderbuffer->getAlphaSize();   break;
 		case GL_RENDERBUFFER_DEPTH_SIZE:      *params = renderbuffer->getDepthSize();   break;
 		case GL_RENDERBUFFER_STENCIL_SIZE:    *params = renderbuffer->getStencilSize(); break;
-		case GL_RENDERBUFFER_SAMPLES_ANGLE:   *params = renderbuffer->getSamples();     break;
+		case GL_RENDERBUFFER_SAMPLES:         *params = renderbuffer->getSamples();     break;
 		default:
 			return error(GL_INVALID_ENUM);
 		}
@@ -3576,7 +3576,7 @@
 				texture = context->getTexture2DArray();
 			}
 			break;
-		case GL_TEXTURE_3D_OES:
+		case GL_TEXTURE_3D:
 			texture = context->getTexture3D();
 			break;
 		default:
@@ -3729,7 +3729,7 @@
 				texture = context->getTexture2DArray();
 			}
 			break;
-		case GL_TEXTURE_3D_OES:
+		case GL_TEXTURE_3D:
 			texture = context->getTexture3D();
 			break;
 		default:
@@ -4189,19 +4189,23 @@
 	}
 
 	es2::Context *context = es2::getContext();
-	switch(target)
+
+	if(context)
 	{
-	case GL_GENERATE_MIPMAP_HINT:
-		if(context) context->setGenerateMipmapHint(mode);
-		break;
-	case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
-		if(context) context->setFragmentShaderDerivativeHint(mode);
-		break;
-	case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
-		if(context) context->setTextureFilteringHint(mode);
-		break;
-	default:
-		return error(GL_INVALID_ENUM);
+		switch(target)
+		{
+		case GL_GENERATE_MIPMAP_HINT:
+			context->setGenerateMipmapHint(mode);
+			break;
+		case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+			context->setFragmentShaderDerivativeHint(mode);
+			break;
+		case GL_TEXTURE_FILTERING_HINT_CHROMIUM:
+			context->setTextureFilteringHint(mode);
+			break;
+		default:
+			return error(GL_INVALID_ENUM);
+		}
 	}
 }
 
@@ -5116,7 +5120,7 @@
 				texture = context->getTexture2DArray();
 			}
 			break;
-		case GL_TEXTURE_3D_OES:
+		case GL_TEXTURE_3D:
 			texture = context->getTexture3D();
 			break;
 		case GL_TEXTURE_CUBE_MAP:
@@ -5265,7 +5269,7 @@
 				texture = context->getTexture2DArray();
 			}
 			break;
-		case GL_TEXTURE_3D_OES:
+		case GL_TEXTURE_3D:
 			texture = context->getTexture3D();
 			break;
 		case GL_TEXTURE_CUBE_MAP:
@@ -6239,7 +6243,7 @@
 
 	switch(target)
 	{
-	case GL_TEXTURE_3D_OES:
+	case GL_TEXTURE_3D:
 		switch(format)
 		{
 		case GL_DEPTH_COMPONENT:
@@ -6311,7 +6315,7 @@
 
 	switch(target)
 	{
-	case GL_TEXTURE_3D_OES:
+	case GL_TEXTURE_3D:
 		break;
 	default:
 		return error(GL_INVALID_ENUM);
@@ -6364,7 +6368,7 @@
 
 	switch(target)
 	{
-	case GL_TEXTURE_3D_OES:
+	case GL_TEXTURE_3D:
 		break;
 	default:
 		return error(GL_INVALID_ENUM);
@@ -6413,7 +6417,7 @@
 
 	switch(target)
 	{
-	case GL_TEXTURE_3D_OES:
+	case GL_TEXTURE_3D:
 		break;
 	default:
 		return error(GL_INVALID_ENUM);
@@ -6484,7 +6488,7 @@
 
 	switch(target)
 	{
-	case GL_TEXTURE_3D_OES:
+	case GL_TEXTURE_3D:
 		break;
 	default:
 		return error(GL_INVALID_ENUM);
@@ -6566,8 +6570,8 @@
 
 			switch(textarget)
 			{
-			case GL_TEXTURE_3D_OES:
-				if(tex->getTarget() != GL_TEXTURE_3D_OES)
+			case GL_TEXTURE_3D:
+				if(tex->getTarget() != GL_TEXTURE_3D)
 				{
 					return error(GL_INVALID_OPERATION);
 				}
diff --git a/src/Renderer/Surface.cpp b/src/Renderer/Surface.cpp
index b758bad..b809148 100644
--- a/src/Renderer/Surface.cpp
+++ b/src/Renderer/Surface.cpp
@@ -3338,22 +3338,22 @@
 		const bool entire = x0 == 0 && y0 == 0 && width == internal.width && height == internal.height;
 		const Lock lock = entire ? LOCK_DISCARD : LOCK_WRITEONLY;
 
-		int width2 = (internal.width + 1) & ~1;
-
 		int x1 = x0 + width;
 		int y1 = y0 + height;
 
 		if(!hasQuadLayout(internal.format))
 		{
-			float *target = (float*)lockInternal(0, 0, 0, lock, PUBLIC) + x0 + width2 * y0;
+			float *target = (float*)lockInternal(x0, y0, 0, lock, PUBLIC);
 
 			for(int z = 0; z < internal.samples; z++)
 			{
+				float *row = target;
 				for(int y = y0; y < y1; y++)
 				{
-					memfill4(target, (int&)depth, 4 * width);
-					target += width2;
+					memfill4(row, (int&)depth, width * sizeof(float));
+					row += internal.pitchP;
 				}
+				target += internal.sliceP;
 			}
 
 			unlockInternal();
@@ -3376,7 +3376,7 @@
 			{
 				for(int y = y0; y < y1; y++)
 				{
-					float *target = buffer + (y & ~1) * width2 + (y & 1) * 2;
+					float *target = buffer + (y & ~1) * internal.pitchP + (y & 1) * 2;
 
 					if((y & 1) == 0 && y + 1 < y1)   // Fill quad line at once
 					{
@@ -3458,8 +3458,6 @@
 		if(y0 < 0) {height += y0; y0 = 0;}
 		if(y0 + height > internal.height) height = internal.height - y0;
 
-		int width2 = (internal.width + 1) & ~1;
-
 		int x1 = x0 + width;
 		int y1 = y0 + height;
 
@@ -3480,7 +3478,7 @@
 		{
 			for(int y = y0; y < y1; y++)
 			{
-				char *target = buffer + (y & ~1) * width2 + (y & 1) * 2;
+				char *target = buffer + (y & ~1) * stencil.pitchP + (y & 1) * 2;
 
 				if((y & 1) == 0 && y + 1 < y1 && mask == 0xFF)   // Fill quad line at once
 				{
@@ -3502,8 +3500,9 @@
 				}
 				else
 				{
-					for(int x = x0, i = oddX0; x < x1; x++, i = (x & ~1) * 2 + (x & 1))
+					for(int x = x0; x < x1; x++)
 					{
+						int i = (x & ~1) * 2 + (x & 1);
 						target[i] = maskedS | (target[i] & invMask);
 					}
 				}