glFramebufferTextureLayer API implementation

Implemented API level of glFramebufferTextureLayer.
All functions should now be adapted to handle level
and layer, all the way to RenderbufferTexture3D,
where layer is still unimplemented.

Change-Id: Id5fe94f998ee517ae84cb0d6e60d535cc7891fe3
Reviewed-on: https://swiftshader-review.googlesource.com/3320
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <capn@google.com>
diff --git a/src/OpenGL/libGLESv2/Framebuffer.cpp b/src/OpenGL/libGLESv2/Framebuffer.cpp
index c6c30fb..451263d 100644
--- a/src/OpenGL/libGLESv2/Framebuffer.cpp
+++ b/src/OpenGL/libGLESv2/Framebuffer.cpp
@@ -42,7 +42,7 @@
 	mStencilbufferPointer = NULL;
 }
 
-Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
+Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle, GLint level, GLint layer) const
 {
 	Context *context = getContext();
 	Renderbuffer *buffer = NULL;
@@ -57,7 +57,7 @@
 	}
 	else if(IsTextureTarget(type))
 	{
-		buffer = context->getTexture(handle)->getRenderbuffer(type);
+		buffer = context->getTexture(handle)->getRenderbuffer(type, level, layer);
 	}
 	else
 	{
@@ -67,22 +67,22 @@
 	return buffer;
 }
 
-void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index)
+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);
+	mColorbufferPointer[index] = lookupRenderbuffer(type, colorbuffer, level, layer);
 }
 
-void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
+void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
 {
 	mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
-	mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer);
+	mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer, level, layer);
 }
 
-void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
+void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
 {
 	mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
-	mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer);
+	mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer, level, layer);
 }
 
 void Framebuffer::detachTexture(GLuint texture)
diff --git a/src/OpenGL/libGLESv2/Framebuffer.h b/src/OpenGL/libGLESv2/Framebuffer.h
index b423e63..8db2ad7 100644
--- a/src/OpenGL/libGLESv2/Framebuffer.h
+++ b/src/OpenGL/libGLESv2/Framebuffer.h
@@ -35,9 +35,9 @@
 

     virtual ~Framebuffer();

 

-    void setColorbuffer(GLenum type, GLuint colorbuffer, GLuint index);

-    void setDepthbuffer(GLenum type, GLuint depthbuffer);

-    void setStencilbuffer(GLenum type, GLuint stencilbuffer);

+    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 detachTexture(GLuint texture);

     void detachRenderbuffer(GLuint renderbuffer);

@@ -78,7 +78,7 @@
     gl::BindingPointer<Renderbuffer> mStencilbufferPointer;

 

 private:

-    Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const;

+    Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle, GLint level, GLint layer) const;

 };

 

 class DefaultFramebuffer : public Framebuffer

diff --git a/src/OpenGL/libGLESv2/Renderbuffer.cpp b/src/OpenGL/libGLESv2/Renderbuffer.cpp
index 2fae03f..3d8cc3e 100644
--- a/src/OpenGL/libGLESv2/Renderbuffer.cpp
+++ b/src/OpenGL/libGLESv2/Renderbuffer.cpp
@@ -68,7 +68,7 @@
 
 ///// RenderbufferTexture2D Implementation ////////
 
-RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture)
+RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLint level) : mLevel(level)
 {
 	mTexture2D = texture;
 }
@@ -94,39 +94,39 @@
 // caller must release() the returned image
 egl::Image *RenderbufferTexture2D::getRenderTarget()
 {
-	return mTexture2D->getRenderTarget(GL_TEXTURE_2D, 0);
+	return mTexture2D->getRenderTarget(GL_TEXTURE_2D, mLevel);
 }
 
 // Increments refcount on image.
 // caller must release() the returned image
 egl::Image *RenderbufferTexture2D::createSharedImage()
 {
-	return mTexture2D->createSharedImage(GL_TEXTURE_2D, 0);
+	return mTexture2D->createSharedImage(GL_TEXTURE_2D, mLevel);
 }
 
 bool RenderbufferTexture2D::isShared() const
 {
-	return mTexture2D->isShared(GL_TEXTURE_2D, 0);
+	return mTexture2D->isShared(GL_TEXTURE_2D, mLevel);
 }
 
 GLsizei RenderbufferTexture2D::getWidth() const
 {
-	return mTexture2D->getWidth(GL_TEXTURE_2D, 0);
+	return mTexture2D->getWidth(GL_TEXTURE_2D, mLevel);
 }
 
 GLsizei RenderbufferTexture2D::getHeight() const
 {
-	return mTexture2D->getHeight(GL_TEXTURE_2D, 0);
+	return mTexture2D->getHeight(GL_TEXTURE_2D, mLevel);
 }
 
 GLenum RenderbufferTexture2D::getFormat() const
 {
-	return mTexture2D->getFormat(GL_TEXTURE_2D, 0);
+	return mTexture2D->getFormat(GL_TEXTURE_2D, mLevel);
 }
 
 sw::Format RenderbufferTexture2D::getInternalFormat() const
 {
-	return mTexture2D->getInternalFormat(GL_TEXTURE_2D, 0);
+	return mTexture2D->getInternalFormat(GL_TEXTURE_2D, mLevel);
 }
 
 GLsizei RenderbufferTexture2D::getSamples() const
@@ -136,9 +136,13 @@
 
 ///// RenderbufferTexture3D Implementation ////////
 
-RenderbufferTexture3D::RenderbufferTexture3D(Texture3D *texture)
+RenderbufferTexture3D::RenderbufferTexture3D(Texture3D *texture, GLint level, GLint layer) : mLevel(level), mLayer(layer)
 {
 	mTexture3D = texture;
+	if(mLayer != 0)
+	{
+		UNIMPLEMENTED();
+	}
 }
 
 RenderbufferTexture3D::~RenderbufferTexture3D()
@@ -162,39 +166,39 @@
 // caller must release() the returned image
 egl::Image *RenderbufferTexture3D::getRenderTarget()
 {
-	return mTexture3D->getRenderTarget(mTexture3D->getTarget(), 0);
+	return mTexture3D->getRenderTarget(mTexture3D->getTarget(), mLevel);
 }
 
 // Increments refcount on image.
 // caller must release() the returned image
 egl::Image *RenderbufferTexture3D::createSharedImage()
 {
-	return mTexture3D->createSharedImage(mTexture3D->getTarget(), 0);
+	return mTexture3D->createSharedImage(mTexture3D->getTarget(), mLevel);
 }
 
 bool RenderbufferTexture3D::isShared() const
 {
-	return mTexture3D->isShared(mTexture3D->getTarget(), 0);
+	return mTexture3D->isShared(mTexture3D->getTarget(), mLevel);
 }
 
 GLsizei RenderbufferTexture3D::getWidth() const
 {
-	return mTexture3D->getWidth(mTexture3D->getTarget(), 0);
+	return mTexture3D->getWidth(mTexture3D->getTarget(), mLevel);
 }
 
 GLsizei RenderbufferTexture3D::getHeight() const
 {
-	return mTexture3D->getHeight(mTexture3D->getTarget(), 0);
+	return mTexture3D->getHeight(mTexture3D->getTarget(), mLevel);
 }
 
 GLenum RenderbufferTexture3D::getFormat() const
 {
-	return mTexture3D->getFormat(mTexture3D->getTarget(), 0);
+	return mTexture3D->getFormat(mTexture3D->getTarget(), mLevel);
 }
 
 sw::Format RenderbufferTexture3D::getInternalFormat() const
 {
-	return mTexture3D->getInternalFormat(mTexture3D->getTarget(), 0);
+	return mTexture3D->getInternalFormat(mTexture3D->getTarget(), mLevel);
 }
 
 GLsizei RenderbufferTexture3D::getSamples() const
@@ -204,7 +208,7 @@
 
 ///// RenderbufferTextureCubeMap Implementation ////////
 
-RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target) : mTarget(target)
+RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target, GLint level) : mTarget(target), mLevel(level)
 {
 	mTextureCubeMap = texture;
 }
@@ -230,39 +234,39 @@
 // caller must release() the returned image
 egl::Image *RenderbufferTextureCubeMap::getRenderTarget()
 {
-	return mTextureCubeMap->getRenderTarget(mTarget, 0);
+	return mTextureCubeMap->getRenderTarget(mTarget, mLevel);
 }
 
 // Increments refcount on image.
 // caller must release() the returned image
 egl::Image *RenderbufferTextureCubeMap::createSharedImage()
 {
-    return mTextureCubeMap->createSharedImage(mTarget, 0);
+	return mTextureCubeMap->createSharedImage(mTarget, mLevel);
 }
 
 bool RenderbufferTextureCubeMap::isShared() const
 {
-    return mTextureCubeMap->isShared(mTarget, 0);
+	return mTextureCubeMap->isShared(mTarget, mLevel);
 }
 
 GLsizei RenderbufferTextureCubeMap::getWidth() const
 {
-	return mTextureCubeMap->getWidth(mTarget, 0);
+	return mTextureCubeMap->getWidth(mTarget, mLevel);
 }
 
 GLsizei RenderbufferTextureCubeMap::getHeight() const
 {
-	return mTextureCubeMap->getHeight(mTarget, 0);
+	return mTextureCubeMap->getHeight(mTarget, mLevel);
 }
 
 GLenum RenderbufferTextureCubeMap::getFormat() const
 {
-	return mTextureCubeMap->getFormat(mTarget, 0);
+	return mTextureCubeMap->getFormat(mTarget, mLevel);
 }
 
 sw::Format RenderbufferTextureCubeMap::getInternalFormat() const
 {
-	return mTextureCubeMap->getInternalFormat(mTarget, 0);
+	return mTextureCubeMap->getInternalFormat(mTarget, mLevel);
 }
 
 GLsizei RenderbufferTextureCubeMap::getSamples() const
diff --git a/src/OpenGL/libGLESv2/Renderbuffer.h b/src/OpenGL/libGLESv2/Renderbuffer.h
index 1ab0908..0bea04f 100644
--- a/src/OpenGL/libGLESv2/Renderbuffer.h
+++ b/src/OpenGL/libGLESv2/Renderbuffer.h
@@ -62,7 +62,7 @@
 class RenderbufferTexture2D : public RenderbufferInterface

 {

 public:

-	RenderbufferTexture2D(Texture2D *texture);

+	RenderbufferTexture2D(Texture2D *texture, GLint level);

 

 	virtual ~RenderbufferTexture2D();

 

@@ -81,12 +81,13 @@
 

 private:

 	gl::BindingPointer<Texture2D> mTexture2D;

+	GLint mLevel;

 };

 

 class RenderbufferTexture3D : public RenderbufferInterface

 {

 public:

-	RenderbufferTexture3D(Texture3D *texture);

+	RenderbufferTexture3D(Texture3D *texture, GLint level, GLint layer);

 

 	virtual ~RenderbufferTexture3D();

 

@@ -105,12 +106,14 @@
 

 private:

 	gl::BindingPointer<Texture3D> mTexture3D;

+	GLint mLevel;

+	GLint mLayer;

 };

 

 class RenderbufferTextureCubeMap : public RenderbufferInterface

 {

 public:

-	RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target);

+	RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target, GLint level);

 

 	virtual ~RenderbufferTextureCubeMap();

 

@@ -130,6 +133,7 @@
 private:

 	gl::BindingPointer<TextureCubeMap> mTextureCubeMap;

 	GLenum mTarget;

+	GLint mLevel;

 };

 

 // A class derived from RenderbufferStorage is created whenever glRenderbufferStorage

diff --git a/src/OpenGL/libGLESv2/Texture.cpp b/src/OpenGL/libGLESv2/Texture.cpp
index 9c4ebce..6f686b8 100644
--- a/src/OpenGL/libGLESv2/Texture.cpp
+++ b/src/OpenGL/libGLESv2/Texture.cpp
@@ -895,7 +895,7 @@
 	return image[level];

 }

 

-Renderbuffer *Texture2D::getRenderbuffer(GLenum target)

+Renderbuffer *Texture2D::getRenderbuffer(GLenum target, GLint level, GLint layer)

 {

     if(target != GL_TEXTURE_2D)

     {

@@ -904,7 +904,7 @@
 

     if(mColorbufferProxy == NULL)

     {

-        mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture2D(this));

+        mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture2D(this, level));

     }

 

     return mColorbufferProxy;

@@ -1348,7 +1348,7 @@
 	}

 }

 

-Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target)

+Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target, GLint level, GLint layer)

 {

     if(!IsCubemapTextureTarget(target))

     {

@@ -1359,7 +1359,7 @@
 

     if(mFaceProxies[face] == NULL)

     {

-        mFaceProxies[face] = new Renderbuffer(name, new RenderbufferTextureCubeMap(this, target));

+        mFaceProxies[face] = new Renderbuffer(name, new RenderbufferTextureCubeMap(this, target, level));

     }

 

     return mFaceProxies[face];

@@ -1801,7 +1801,7 @@
 	return image[level];

 }

 

-Renderbuffer *Texture3D::getRenderbuffer(GLenum target)

+Renderbuffer *Texture3D::getRenderbuffer(GLenum target, GLint level, GLint layer)

 {

 	if(target != getTarget())

 	{

@@ -1810,7 +1810,7 @@
 

 	if(mColorbufferProxy == NULL)

 	{

-		mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture3D(this));

+		mColorbufferProxy = new Renderbuffer(name, new RenderbufferTexture3D(this, level, layer));

 	}

 

 	return mColorbufferProxy;

diff --git a/src/OpenGL/libGLESv2/Texture.h b/src/OpenGL/libGLESv2/Texture.h
index 1e4cae0..d2207e4 100644
--- a/src/OpenGL/libGLESv2/Texture.h
+++ b/src/OpenGL/libGLESv2/Texture.h
@@ -112,7 +112,7 @@
     virtual bool isCompressed(GLenum target, GLint level) const = 0;

 	virtual bool isDepth(GLenum target, GLint level) const = 0;

 

-    virtual Renderbuffer *getRenderbuffer(GLenum target) = 0;

+    virtual Renderbuffer *getRenderbuffer(GLenum target, GLint level, GLint layer) = 0;

     virtual egl::Image *getRenderTarget(GLenum target, unsigned int level) = 0;

     virtual egl::Image *createSharedImage(GLenum target, unsigned int level);

     virtual bool isShared(GLenum target, unsigned int level) const = 0;

@@ -187,7 +187,7 @@
 

     virtual void generateMipmaps();

 

-	virtual Renderbuffer *getRenderbuffer(GLenum target);

+	virtual Renderbuffer *getRenderbuffer(GLenum target, GLint level, GLint layer);

     virtual egl::Image *getRenderTarget(GLenum target, unsigned int level);

 	virtual bool isShared(GLenum target, unsigned int level) const;

 

@@ -243,7 +243,7 @@
 

     virtual void generateMipmaps();

 

-    virtual Renderbuffer *getRenderbuffer(GLenum target);

+    virtual Renderbuffer *getRenderbuffer(GLenum target, GLint level, GLint layer);

 	virtual egl::Image *getRenderTarget(GLenum target, unsigned int level);

 	virtual bool isShared(GLenum target, unsigned int level) const;

 

@@ -304,7 +304,7 @@
 

 	virtual void generateMipmaps();

 

-	virtual Renderbuffer *getRenderbuffer(GLenum target);

+	virtual Renderbuffer *getRenderbuffer(GLenum target, GLint level, GLint layer);

 	virtual egl::Image *getRenderTarget(GLenum target, unsigned int level);

 	virtual bool isShared(GLenum target, unsigned int level) const;

 

diff --git a/src/OpenGL/libGLESv2/libGLESv2.cpp b/src/OpenGL/libGLESv2/libGLESv2.cpp
index e458c43..5bb662f 100644
--- a/src/OpenGL/libGLESv2/libGLESv2.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv2.cpp
@@ -2305,7 +2305,12 @@
 				return error(GL_INVALID_ENUM);

 			}

 

-			if(level != 0)

+			if((level != 0) && (context->getClientVersion() < 3))

+			{

+				return error(GL_INVALID_VALUE);

+			}

+

+			if((level < 0) || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))

 			{

 				return error(GL_INVALID_VALUE);

 			}

@@ -2358,10 +2363,10 @@
 			{

 				return error(GL_INVALID_ENUM);

 			}

-			framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0);

+			framebuffer->setColorbuffer(textarget, texture, attachment - GL_COLOR_ATTACHMENT0, level);

 			break;

-		case GL_DEPTH_ATTACHMENT:   framebuffer->setDepthbuffer(textarget, texture);   break;

-		case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break;

+		case GL_DEPTH_ATTACHMENT:   framebuffer->setDepthbuffer(textarget, texture, level);   break;

+		case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level); break;

 		}

 	}

 }

diff --git a/src/OpenGL/libGLESv2/libGLESv3.cpp b/src/OpenGL/libGLESv2/libGLESv3.cpp
index fb61088..3e1aafd 100644
--- a/src/OpenGL/libGLESv2/libGLESv3.cpp
+++ b/src/OpenGL/libGLESv2/libGLESv3.cpp
@@ -1484,43 +1484,106 @@
 	TRACE("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %d, GLint level = %d, GLint layer = %d)",

 	      target, attachment, texture, level, layer);

 	

-	switch(target)

+	if(texture != 0 && layer < 0 || level < 0)

 	{

-	case GL_DRAW_FRAMEBUFFER:

-	case GL_READ_FRAMEBUFFER:

-	case GL_FRAMEBUFFER:

-		break;

-	default:

-		return error(GL_INVALID_ENUM);

+		return error(GL_INVALID_VALUE);

 	}

 

-	switch(attachment)

-	{

-	case GL_COLOR_ATTACHMENT0:

-	case GL_COLOR_ATTACHMENT1:

-	case GL_COLOR_ATTACHMENT2:

-	case GL_COLOR_ATTACHMENT3:

-	case GL_COLOR_ATTACHMENT4:

-	case GL_COLOR_ATTACHMENT5:

-	case GL_COLOR_ATTACHMENT6:

-	case GL_COLOR_ATTACHMENT7:

-	case GL_COLOR_ATTACHMENT8:

-	case GL_COLOR_ATTACHMENT9:

-	case GL_COLOR_ATTACHMENT10:

-	case GL_COLOR_ATTACHMENT11:

-	case GL_COLOR_ATTACHMENT12:

-	case GL_COLOR_ATTACHMENT13:

-	case GL_COLOR_ATTACHMENT14:

-	case GL_COLOR_ATTACHMENT15:

-	case GL_DEPTH_ATTACHMENT:

-	case GL_STENCIL_ATTACHMENT:

-	case GL_DEPTH_STENCIL_ATTACHMENT:

-		break;

-	default:

-		return error(GL_INVALID_ENUM);

-	}

+	es2::Context *context = es2::getContext();

 

-	UNIMPLEMENTED();

+	if(context)

+	{

+		Texture* textureObject = context->getTexture(texture);

+		if(texture != 0)

+		{

+			if(!textureObject)

+			{

+				return error(GL_INVALID_VALUE);

+			}

+

+			switch(textureObject->getTarget())

+			{

+			case GL_TEXTURE_3D:

+			case GL_TEXTURE_2D_ARRAY:

+				if(layer >= es2::IMPLEMENTATION_MAX_TEXTURE_SIZE || (level >= es2::IMPLEMENTATION_MAX_TEXTURE_LEVELS))

+				{

+					return error(GL_INVALID_VALUE);

+				}

+				break;

+			default:

+				return error(GL_INVALID_OPERATION);

+			}

+

+			if(textureObject->isCompressed(target, level))

+			{

+				return error(GL_INVALID_OPERATION);

+			}

+		}

+

+		es2::Framebuffer *framebuffer = nullptr;

+		switch(target)

+		{

+		case GL_DRAW_FRAMEBUFFER:

+		case GL_FRAMEBUFFER:

+			framebuffer = context->getDrawFramebuffer();

+			break;

+		case GL_READ_FRAMEBUFFER:

+			framebuffer = context->getReadFramebuffer();

+			break;

+		default:

+			return error(GL_INVALID_ENUM);

+		}

+

+		switch(attachment)

+		{

+		case GL_COLOR_ATTACHMENT0:

+		case GL_COLOR_ATTACHMENT1:

+		case GL_COLOR_ATTACHMENT2:

+		case GL_COLOR_ATTACHMENT3:

+		case GL_COLOR_ATTACHMENT4:

+		case GL_COLOR_ATTACHMENT5:

+		case GL_COLOR_ATTACHMENT6:

+		case GL_COLOR_ATTACHMENT7:

+		case GL_COLOR_ATTACHMENT8:

+		case GL_COLOR_ATTACHMENT9:

+		case GL_COLOR_ATTACHMENT10:

+		case GL_COLOR_ATTACHMENT11:

+		case GL_COLOR_ATTACHMENT12:

+		case GL_COLOR_ATTACHMENT13:

+		case GL_COLOR_ATTACHMENT14:

+		case GL_COLOR_ATTACHMENT15:

+			if(!framebuffer || framebuffer->getColorbufferName(attachment - GL_COLOR_ATTACHMENT0) == 0)

+			{

+				return error(GL_INVALID_OPERATION);

+			}

+			framebuffer->setColorbuffer(target, texture, attachment - GL_COLOR_ATTACHMENT0, layer, level);

+			break;

+		case GL_DEPTH_ATTACHMENT:

+			if(!framebuffer || framebuffer->getDepthbufferName() == 0)

+			{

+				return error(GL_INVALID_OPERATION);

+			}

+			framebuffer->setDepthbuffer(target, texture, layer, level);

+			break;

+		case GL_STENCIL_ATTACHMENT:

+			if(!framebuffer || framebuffer->getStencilbufferName() == 0)

+			{

+				return error(GL_INVALID_OPERATION);

+			}

+			framebuffer->setStencilbuffer(target, texture, layer, level);

+			break;

+		case GL_DEPTH_STENCIL_ATTACHMENT:

+			if(!framebuffer || framebuffer->getDepthbufferName() == 0 || framebuffer->getStencilbufferName() == 0)

+			{

+				return error(GL_INVALID_OPERATION);

+			}

+			framebuffer->setDepthbuffer(target, texture, layer, level);

+			framebuffer->setStencilbuffer(target, texture, layer, level);

+			break;

+		default:

+			return error(GL_INVALID_ENUM);

+		}

+	}

 }

 

 GL_APICALL void *GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)

diff --git a/src/OpenGL/libGLESv2/utilities.cpp b/src/OpenGL/libGLESv2/utilities.cpp
index 4f63086..e9b7e78 100644
--- a/src/OpenGL/libGLESv2/utilities.cpp
+++ b/src/OpenGL/libGLESv2/utilities.cpp
@@ -294,7 +294,7 @@
 

 	bool IsTextureTarget(GLenum target)

 	{

-		return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target);

+		return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target) || target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;

 	}

 

 	// Verify that format/type are one of the combinations from table 3.4.