EXT_multisampled_render_to_texture test

Detects a bug where ReadPixels fails on multisampled textures.
See http://crbug.com/890002

Cherry pick from AOSP.

Original commit:
https://android.googlesource.com/platform/external/deqp/+/accf1be52e32153c757cd84864607ee9c47dfe9a
https://android-review.googlesource.com/c/platform/external/deqp/+/796566
Submitted on behalf of a third-party: jdarpinian@chromium.org

Components: OpenGL

New test:
dEQP-GLES2.functional.multisampled_render_to_texture.readpixels

Bug: chromium:890002
Change-Id: I6e5e5d1fa3aa15daee69271339962a0b3ffc1927
diff --git a/AndroidGen.mk b/AndroidGen.mk
index c0d6e92..e2cd996 100644
--- a/AndroidGen.mk
+++ b/AndroidGen.mk
@@ -837,6 +837,7 @@
 	modules/gles2/functional/es2fLifetimeTests.cpp \
 	modules/gles2/functional/es2fLightAmountTest.cpp \
 	modules/gles2/functional/es2fMultisampleTests.cpp \
+	modules/gles2/functional/es2fMultisampledRenderToTextureTests.cpp \
 	modules/gles2/functional/es2fNegativeBufferApiTests.cpp \
 	modules/gles2/functional/es2fNegativeFragmentApiTests.cpp \
 	modules/gles2/functional/es2fNegativeShaderApiTests.cpp \
diff --git a/android/cts/master/gles2-master-2021-03-01.txt b/android/cts/master/gles2-master-2021-03-01.txt
index 3afd288..2d83140 100644
--- a/android/cts/master/gles2-master-2021-03-01.txt
+++ b/android/cts/master/gles2-master-2021-03-01.txt
@@ -1,3 +1,4 @@
+dEQP-GLES2.functional.multisampled_render_to_texture.readpixels
 dEQP-GLES2.functional.shaders.indexing.tmp_array.float_const_write_static_read_vertex
 dEQP-GLES2.functional.shaders.indexing.tmp_array.float_const_write_static_read_fragment
 dEQP-GLES2.functional.shaders.indexing.tmp_array.float_const_write_dynamic_read_vertex
diff --git a/android/cts/master/gles2-master.txt b/android/cts/master/gles2-master.txt
index b5ac710..710c688 100644
--- a/android/cts/master/gles2-master.txt
+++ b/android/cts/master/gles2-master.txt
@@ -124,6 +124,7 @@
 dEQP-GLES2.functional.light_amount.12omni
 dEQP-GLES2.functional.light_amount.14omni
 dEQP-GLES2.functional.light_amount.16omni
+dEQP-GLES2.functional.multisampled_render_to_texture.readpixels
 dEQP-GLES2.functional.shaders.preprocessor.basic.correct_phases_vertex
 dEQP-GLES2.functional.shaders.preprocessor.basic.correct_phases_fragment
 dEQP-GLES2.functional.shaders.preprocessor.basic.invalid_identifier_vertex
diff --git a/external/openglcts/data/mustpass/gles/aosp_mustpass/3.2.5.x/gles2-master.txt b/external/openglcts/data/mustpass/gles/aosp_mustpass/3.2.5.x/gles2-master.txt
index c63235c..1662414 100644
--- a/external/openglcts/data/mustpass/gles/aosp_mustpass/3.2.5.x/gles2-master.txt
+++ b/external/openglcts/data/mustpass/gles/aosp_mustpass/3.2.5.x/gles2-master.txt
@@ -129,6 +129,7 @@
 dEQP-GLES2.functional.light_amount.12omni
 dEQP-GLES2.functional.light_amount.14omni
 dEQP-GLES2.functional.light_amount.16omni
+dEQP-GLES2.functional.multisampled_render_to_texture.readpixels
 dEQP-GLES2.functional.shaders.preprocessor.basic.correct_phases_vertex
 dEQP-GLES2.functional.shaders.preprocessor.basic.correct_phases_fragment
 dEQP-GLES2.functional.shaders.preprocessor.basic.invalid_identifier_vertex
diff --git a/external/openglcts/data/mustpass/gles/aosp_mustpass/3.2.6.x/gles2-master.txt b/external/openglcts/data/mustpass/gles/aosp_mustpass/3.2.6.x/gles2-master.txt
index c63235c..1662414 100644
--- a/external/openglcts/data/mustpass/gles/aosp_mustpass/3.2.6.x/gles2-master.txt
+++ b/external/openglcts/data/mustpass/gles/aosp_mustpass/3.2.6.x/gles2-master.txt
@@ -129,6 +129,7 @@
 dEQP-GLES2.functional.light_amount.12omni
 dEQP-GLES2.functional.light_amount.14omni
 dEQP-GLES2.functional.light_amount.16omni
+dEQP-GLES2.functional.multisampled_render_to_texture.readpixels
 dEQP-GLES2.functional.shaders.preprocessor.basic.correct_phases_vertex
 dEQP-GLES2.functional.shaders.preprocessor.basic.correct_phases_fragment
 dEQP-GLES2.functional.shaders.preprocessor.basic.invalid_identifier_vertex
diff --git a/external/openglcts/data/mustpass/gles/aosp_mustpass/master/gles2-master.txt b/external/openglcts/data/mustpass/gles/aosp_mustpass/master/gles2-master.txt
index c63235c..1662414 100644
--- a/external/openglcts/data/mustpass/gles/aosp_mustpass/master/gles2-master.txt
+++ b/external/openglcts/data/mustpass/gles/aosp_mustpass/master/gles2-master.txt
@@ -129,6 +129,7 @@
 dEQP-GLES2.functional.light_amount.12omni
 dEQP-GLES2.functional.light_amount.14omni
 dEQP-GLES2.functional.light_amount.16omni
+dEQP-GLES2.functional.multisampled_render_to_texture.readpixels
 dEQP-GLES2.functional.shaders.preprocessor.basic.correct_phases_vertex
 dEQP-GLES2.functional.shaders.preprocessor.basic.correct_phases_fragment
 dEQP-GLES2.functional.shaders.preprocessor.basic.invalid_identifier_vertex
diff --git a/modules/gles2/functional/CMakeLists.txt b/modules/gles2/functional/CMakeLists.txt
index 43f513f..d9cfcb5 100644
--- a/modules/gles2/functional/CMakeLists.txt
+++ b/modules/gles2/functional/CMakeLists.txt
@@ -29,6 +29,8 @@
 	es2fLifetimeTests.hpp
 	es2fLightAmountTest.cpp
 	es2fLightAmountTest.hpp
+	es2fMultisampledRenderToTextureTests.cpp
+	es2fMultisampledRenderToTextureTests.hpp
 	es2fNegativeBufferApiTests.cpp
 	es2fNegativeBufferApiTests.hpp
 	es2fNegativeFragmentApiTests.cpp
diff --git a/modules/gles2/functional/es2fFunctionalTests.cpp b/modules/gles2/functional/es2fFunctionalTests.cpp
index 7a169db..f62916d 100644
--- a/modules/gles2/functional/es2fFunctionalTests.cpp
+++ b/modules/gles2/functional/es2fFunctionalTests.cpp
@@ -25,6 +25,7 @@
 
 #include "es2fColorClearTest.hpp"
 #include "es2fLightAmountTest.hpp"
+#include "es2fMultisampledRenderToTextureTests.hpp"
 #include "es2fShaderExecuteTest.hpp"
 #include "es2fFboApiTest.hpp"
 #include "es2fFboRenderTest.hpp"
@@ -310,35 +311,36 @@
 
 void FunctionalTests::init (void)
 {
-	addChild(new PrerequisiteTests			(m_context));
-	addChild(new ImplementationLimitTests	(m_context));
-	addChild(new ClipControlTests			(m_context));
-	addChild(new ColorClearTest				(m_context));
-	addChild(new DepthStencilClearTests		(m_context));
-	addChild(new BufferTests				(m_context));
-	addChild(new LightAmountTest			(m_context));
-	addChild(new ShadersTestGroup			(m_context));
-	addChild(new TextureTestGroup			(m_context));
-	addChild(new FragmentOpTests			(m_context));
-	addChild(new FboTestGroup				(m_context));
-	addChild(new VertexArrayTestGroup		(m_context));
-	addChild(new ShaderApiTests				(m_context));
-	addChild(new NegativeApiTestGroup		(m_context));
-	addChild(new RasterizationTests			(m_context));
-	addChild(createAttributeLocationTests	(m_context));
-	addChild(new MultisampleTests			(m_context));
-	addChild(new UniformApiTests			(m_context));
-	addChild(new ReadPixelsTests			(m_context));
-	addChild(new DepthRangeTests			(m_context));
-	addChild(new DitheringTests				(m_context));
-	addChild(new StateQueryTests			(m_context));
-	addChild(new ClippingTests				(m_context));
-	addChild(new PolygonOffsetTests			(m_context));
-	addChild(new DrawTests					(m_context));
-	addChild(new FlushFinishTests			(m_context));
-	addChild(new DefaultVertexAttributeTests(m_context));
-	addChild(createLifetimeTests			(m_context));
-	addChild(createDebugMarkerTests			(m_context));
+	addChild(new PrerequisiteTests					(m_context));
+	addChild(new ImplementationLimitTests			(m_context));
+	addChild(new ClipControlTests					(m_context));
+	addChild(new ColorClearTest						(m_context));
+	addChild(new DepthStencilClearTests				(m_context));
+	addChild(new BufferTests						(m_context));
+	addChild(new LightAmountTest					(m_context));
+	addChild(new MultisampledRenderToTextureTests	(m_context));
+	addChild(new ShadersTestGroup					(m_context));
+	addChild(new TextureTestGroup					(m_context));
+	addChild(new FragmentOpTests					(m_context));
+	addChild(new FboTestGroup						(m_context));
+	addChild(new VertexArrayTestGroup				(m_context));
+	addChild(new ShaderApiTests						(m_context));
+	addChild(new NegativeApiTestGroup				(m_context));
+	addChild(new RasterizationTests					(m_context));
+	addChild(createAttributeLocationTests			(m_context));
+	addChild(new MultisampleTests					(m_context));
+	addChild(new UniformApiTests					(m_context));
+	addChild(new ReadPixelsTests					(m_context));
+	addChild(new DepthRangeTests					(m_context));
+	addChild(new DitheringTests						(m_context));
+	addChild(new StateQueryTests					(m_context));
+	addChild(new ClippingTests						(m_context));
+	addChild(new PolygonOffsetTests					(m_context));
+	addChild(new DrawTests							(m_context));
+	addChild(new FlushFinishTests					(m_context));
+	addChild(new DefaultVertexAttributeTests		(m_context));
+	addChild(createLifetimeTests					(m_context));
+	addChild(createDebugMarkerTests					(m_context));
 }
 
 } // Functional
diff --git a/modules/gles2/functional/es2fMultisampledRenderToTextureTests.cpp b/modules/gles2/functional/es2fMultisampledRenderToTextureTests.cpp
new file mode 100644
index 0000000..9a0582d
--- /dev/null
+++ b/modules/gles2/functional/es2fMultisampledRenderToTextureTests.cpp
@@ -0,0 +1,152 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 2.0 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */ /*!
+ * \file
+ * \brief GL_EXT_multisample_render_to_texture tests.
+ */ /*--------------------------------------------------------------------*/
+
+#include "es2fMultisampledRenderToTextureTests.hpp"
+
+#include "deString.h"
+#include "deStringUtil.hpp"
+#include "gluContextInfo.hpp"
+#include "gluPixelTransfer.hpp"
+#include "gluShaderProgram.hpp"
+#include "glw.h"
+#include "glwEnums.hpp"
+#include "glwFunctions.hpp"
+#include "tcuRenderTarget.hpp"
+#include "tcuSurface.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuVector.hpp"
+
+using tcu::TestLog;
+using tcu::Vec4;
+
+namespace deqp
+{
+namespace gles2
+{
+namespace Functional
+{
+
+class MultisampledRenderToTextureReadPixelsCase : public TestCase
+{
+public:
+	MultisampledRenderToTextureReadPixelsCase(Context& context, const char* name, const char* description);
+	~MultisampledRenderToTextureReadPixelsCase();
+	void init();
+	IterateResult iterate();
+
+private:
+	MultisampledRenderToTextureReadPixelsCase(const MultisampledRenderToTextureReadPixelsCase& other);
+	MultisampledRenderToTextureReadPixelsCase& operator=(const MultisampledRenderToTextureReadPixelsCase& other);
+};
+
+MultisampledRenderToTextureReadPixelsCase::MultisampledRenderToTextureReadPixelsCase(Context& context, const char* name, const char* description)
+	: TestCase(context, name, description)
+{
+}
+
+MultisampledRenderToTextureReadPixelsCase::~MultisampledRenderToTextureReadPixelsCase()
+{
+}
+
+void MultisampledRenderToTextureReadPixelsCase::init()
+{
+	const glu::ContextInfo& contextInfo = m_context.getContextInfo();
+	if (!contextInfo.isExtensionSupported("GL_EXT_multisampled_render_to_texture"))
+	{
+		TCU_THROW(NotSupportedError, "EXT_multisampled_render_to_texture is not supported");
+	}
+}
+
+MultisampledRenderToTextureReadPixelsCase::IterateResult MultisampledRenderToTextureReadPixelsCase::iterate()
+{
+	// Test for a bug where ReadPixels fails on multisampled textures.
+	// See http://crbug.com/890002
+	// Note that this does not test whether multisampling is working properly,
+	// only that ReadPixels is able to read from the texture.
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+	// Create a framebuffer with a multisampled texture and a depth-stencil
+	// renderbuffer.
+	GLuint framebuffer = 0;
+	GLuint texture = 0;
+	gl.genFramebuffers(1, &framebuffer);
+	gl.genTextures(1, &texture);
+	gl.bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+	gl.bindTexture(GL_TEXTURE_2D, texture);
+	gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+	GLint max_samples = 0;
+	gl.getIntegerv(GL_MAX_SAMPLES_EXT, &max_samples);
+	gl.framebufferTexture2DMultisampleEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0, max_samples);
+	GLuint depthStencil = 0;
+	gl.genRenderbuffers(1, &depthStencil);
+	gl.bindRenderbuffer(GL_RENDERBUFFER, depthStencil);
+	gl.renderbufferStorageMultisampleEXT(GL_RENDERBUFFER, max_samples, GL_DEPTH24_STENCIL8, 1, 1);
+	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencil);
+	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencil);
+	if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
+		TCU_THROW(NotSupportedError, "Framebuffer format not supported.");
+	}
+	gl.clearColor(1, 0, 1, 0);
+	gl.clear(GL_COLOR_BUFFER_BIT);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "init");
+
+	// ReadPixels should implicitly resolve the multisampled buffer.
+	GLubyte pixel[4] = { 0, 1, 0, 1 };
+	gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &pixel);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "ReadPixels");
+
+	if (pixel[0] != 255 || pixel[1] != 0 || pixel[2] != 255 || pixel[3] != 0)
+	{
+		std::ostringstream msg;
+		msg << "ReadPixels read incorrect values: [" << (int)pixel[0] << ", " << (int)pixel[1] << ", " << (int)pixel[2] << ", " << (int)pixel[3] << "]";
+		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, msg.str().c_str());
+	}
+	else
+	{
+		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+	}
+
+	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+	gl.bindTexture(GL_TEXTURE_2D, 0);
+	gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
+	gl.deleteFramebuffers(1, &framebuffer);
+	gl.deleteRenderbuffers(1, &depthStencil);
+	gl.deleteTextures(1, &texture);
+	return STOP;
+}
+
+MultisampledRenderToTextureTests::MultisampledRenderToTextureTests(Context& context) : TestCaseGroup(context, "multisampled_render_to_texture", "EXT_multisampled_render_to_texture tests")
+{
+}
+
+MultisampledRenderToTextureTests::~MultisampledRenderToTextureTests()
+{
+}
+
+void MultisampledRenderToTextureTests::init()
+{
+	addChild(new MultisampledRenderToTextureReadPixelsCase(m_context, "readpixels", "Test ReadPixels with EXT_multisampled_render_to_texture"));
+}
+
+} // namespace Functional
+} // namespace gles2
+} // namespace deqp
diff --git a/modules/gles2/functional/es2fMultisampledRenderToTextureTests.hpp b/modules/gles2/functional/es2fMultisampledRenderToTextureTests.hpp
new file mode 100644
index 0000000..a44e2f7
--- /dev/null
+++ b/modules/gles2/functional/es2fMultisampledRenderToTextureTests.hpp
@@ -0,0 +1,53 @@
+#ifndef _ES2FMULTISAMPLEDRENDERTOTEXTURETESTS_HPP
+#define _ES2FMULTISAMPLEDRENDERTOTEXTURETESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 2.0 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */ /*!
+ * \file
+ * \brief GL_EXT_multisample_render_to_texture tests.
+*/ /*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes2TestCase.hpp"
+
+namespace deqp
+{
+namespace gles2
+{
+namespace Functional
+{
+
+class MultisampledRenderToTextureTests : public TestCaseGroup
+{
+public:
+	MultisampledRenderToTextureTests(Context& context);
+	~MultisampledRenderToTextureTests();
+
+	void init();
+
+private:
+	MultisampledRenderToTextureTests(const MultisampledRenderToTextureTests& other);
+	MultisampledRenderToTextureTests& operator=(const MultisampledRenderToTextureTests& other);
+};
+
+} // namespace Functional
+} // namespace gles2
+} // namespace deqp
+
+#endif // _ES2FMULTISAMPLEDRENDERTOTEXTURETESTS_HPP