Merge changes from topic "tests-dropped-from-o"

* changes:
  Reinstate excluded UBO tests
  Reinstate dEQP-VK.image.mutable.*
diff --git a/Android.mk b/Android.mk
index 68e62b8..ae8de10 100644
--- a/Android.mk
+++ b/Android.mk
@@ -712,6 +712,7 @@
 	modules/gles3/functional/es3fInternalFormatQueryTests.cpp \
 	modules/gles3/functional/es3fLifetimeTests.cpp \
 	modules/gles3/functional/es3fMultisampleTests.cpp \
+	modules/gles3/functional/es3fMultiviewTests.cpp \
 	modules/gles3/functional/es3fNegativeBufferApiTests.cpp \
 	modules/gles3/functional/es3fNegativeFragmentApiTests.cpp \
 	modules/gles3/functional/es3fNegativeShaderApiTests.cpp \
diff --git a/android/cts/master/gles3-master.txt b/android/cts/master/gles3-master.txt
index 8156022..c321527 100644
--- a/android/cts/master/gles3-master.txt
+++ b/android/cts/master/gles3-master.txt
@@ -30428,6 +30428,9 @@
 dEQP-GLES3.functional.fbo.msaa.8_samples.depth32f_stencil8
 dEQP-GLES3.functional.fbo.msaa.8_samples.depth24_stencil8
 dEQP-GLES3.functional.fbo.msaa.8_samples.stencil_index8
+dEQP-GLES3.functional.fbo.multiview.samples_1
+dEQP-GLES3.functional.fbo.multiview.samples_2
+dEQP-GLES3.functional.fbo.multiview.samples_4
 dEQP-GLES3.functional.fbo.invalidate.default.render_none
 dEQP-GLES3.functional.fbo.invalidate.default.render_color
 dEQP-GLES3.functional.fbo.invalidate.default.render_depth
diff --git a/framework/opengl/gluCallLogWrapper.inl b/framework/opengl/gluCallLogWrapper.inl
index 0743712..d9f3b5d 100644
--- a/framework/opengl/gluCallLogWrapper.inl
+++ b/framework/opengl/gluCallLogWrapper.inl
@@ -1236,6 +1236,20 @@
 	m_gl.framebufferTextureLayer(target, attachment, texture, level, layer);
 }
 
+void CallLogWrapper::glFramebufferTextureMultisampleMultiviewOVR (glw::GLenum target, glw::GLenum attachment, glw::GLuint texture, glw::GLint level, glw::GLsizei samples, glw::GLint baseViewIndex, glw::GLsizei numViews)
+{
+	if (m_enableLog)
+		m_log << TestLog::Message << "glFramebufferTextureMultisampleMultiviewOVR(" << toHex(target) << ", " << toHex(attachment) << ", " << texture << ", " << level << ", " << samples << ", " << baseViewIndex << ", " << numViews << ");" << TestLog::EndMessage;
+	m_gl.framebufferTextureMultisampleMultiviewOVR(target, attachment, texture, level, samples, baseViewIndex, numViews);
+}
+
+void CallLogWrapper::glFramebufferTextureMultiviewOVR (glw::GLenum target, glw::GLenum attachment, glw::GLuint texture, glw::GLint level, glw::GLint baseViewIndex, glw::GLsizei numViews)
+{
+	if (m_enableLog)
+		m_log << TestLog::Message << "glFramebufferTextureMultiviewOVR(" << toHex(target) << ", " << toHex(attachment) << ", " << texture << ", " << level << ", " << baseViewIndex << ", " << numViews << ");" << TestLog::EndMessage;
+	m_gl.framebufferTextureMultiviewOVR(target, attachment, texture, level, baseViewIndex, numViews);
+}
+
 void CallLogWrapper::glFrontFace (glw::GLenum mode)
 {
 	if (m_enableLog)
diff --git a/framework/opengl/gluCallLogWrapperApi.inl b/framework/opengl/gluCallLogWrapperApi.inl
index 71bddd9..9acbee0 100644
--- a/framework/opengl/gluCallLogWrapperApi.inl
+++ b/framework/opengl/gluCallLogWrapperApi.inl
@@ -176,6 +176,8 @@
 void					glFramebufferTexture2D							(glw::GLenum target, glw::GLenum attachment, glw::GLenum textarget, glw::GLuint texture, glw::GLint level);
 void					glFramebufferTexture3D							(glw::GLenum target, glw::GLenum attachment, glw::GLenum textarget, glw::GLuint texture, glw::GLint level, glw::GLint zoffset);
 void					glFramebufferTextureLayer						(glw::GLenum target, glw::GLenum attachment, glw::GLuint texture, glw::GLint level, glw::GLint layer);
+void					glFramebufferTextureMultisampleMultiviewOVR		(glw::GLenum target, glw::GLenum attachment, glw::GLuint texture, glw::GLint level, glw::GLsizei samples, glw::GLint baseViewIndex, glw::GLsizei numViews);
+void					glFramebufferTextureMultiviewOVR				(glw::GLenum target, glw::GLenum attachment, glw::GLuint texture, glw::GLint level, glw::GLint baseViewIndex, glw::GLsizei numViews);
 void					glFrontFace										(glw::GLenum mode);
 void					glGenBuffers									(glw::GLsizei n, glw::GLuint *buffers);
 void					glGenFramebuffers								(glw::GLsizei n, glw::GLuint *framebuffers);
diff --git a/framework/opengl/wrapper/glwApi.inl b/framework/opengl/wrapper/glwApi.inl
index befa4b9..4e4f520 100644
--- a/framework/opengl/wrapper/glwApi.inl
+++ b/framework/opengl/wrapper/glwApi.inl
@@ -176,6 +176,8 @@
 #define			glFramebufferTexture2D							glwFramebufferTexture2D
 #define			glFramebufferTexture3D							glwFramebufferTexture3D
 #define			glFramebufferTextureLayer						glwFramebufferTextureLayer
+#define			glFramebufferTextureMultisampleMultiviewOVR		glwFramebufferTextureMultisampleMultiviewOVR
+#define			glFramebufferTextureMultiviewOVR				glwFramebufferTextureMultiviewOVR
 #define			glFrontFace										glwFrontFace
 #define			glGenBuffers									glwGenBuffers
 #define			glGenFramebuffers								glwGenFramebuffers
@@ -836,6 +838,8 @@
 void			glwFramebufferTexture2D							(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
 void			glwFramebufferTexture3D							(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
 void			glwFramebufferTextureLayer						(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+void			glwFramebufferTextureMultisampleMultiviewOVR	(GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+void			glwFramebufferTextureMultiviewOVR				(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
 void			glwFrontFace									(GLenum mode);
 void			glwGenBuffers									(GLsizei n, GLuint *buffers);
 void			glwGenFramebuffers								(GLsizei n, GLuint *framebuffers);
diff --git a/framework/opengl/wrapper/glwEnums.inl b/framework/opengl/wrapper/glwEnums.inl
index d6e51ab..6506906 100644
--- a/framework/opengl/wrapper/glwEnums.inl
+++ b/framework/opengl/wrapper/glwEnums.inl
@@ -1644,3 +1644,7 @@
 #define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR						0x93DC
 #define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12							0x93DD
 #define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR						0x93DD
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR					0x9630
+#define GL_MAX_VIEWS_OVR												0x9631
+#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR			0x9632
+#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR						0x9633
diff --git a/framework/opengl/wrapper/glwFunctionTypes.inl b/framework/opengl/wrapper/glwFunctionTypes.inl
index 63adcec..9c0bdd9 100644
--- a/framework/opengl/wrapper/glwFunctionTypes.inl
+++ b/framework/opengl/wrapper/glwFunctionTypes.inl
@@ -176,6 +176,8 @@
 typedef GLW_APICALL void			(GLW_APIENTRY* glFramebufferTexture2DFunc)							(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
 typedef GLW_APICALL void			(GLW_APIENTRY* glFramebufferTexture3DFunc)							(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset);
 typedef GLW_APICALL void			(GLW_APIENTRY* glFramebufferTextureLayerFunc)						(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+typedef GLW_APICALL void			(GLW_APIENTRY* glFramebufferTextureMultisampleMultiviewOVRFunc)		(GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews);
+typedef GLW_APICALL void			(GLW_APIENTRY* glFramebufferTextureMultiviewOVRFunc)				(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews);
 typedef GLW_APICALL void			(GLW_APIENTRY* glFrontFaceFunc)										(GLenum mode);
 typedef GLW_APICALL void			(GLW_APIENTRY* glGenBuffersFunc)									(GLsizei n, GLuint *buffers);
 typedef GLW_APICALL void			(GLW_APIENTRY* glGenFramebuffersFunc)								(GLsizei n, GLuint *framebuffers);
diff --git a/framework/opengl/wrapper/glwFunctions.inl b/framework/opengl/wrapper/glwFunctions.inl
index 4d304eb..0895423 100644
--- a/framework/opengl/wrapper/glwFunctions.inl
+++ b/framework/opengl/wrapper/glwFunctions.inl
@@ -176,6 +176,8 @@
 glFramebufferTexture2DFunc							framebufferTexture2D;
 glFramebufferTexture3DFunc							framebufferTexture3D;
 glFramebufferTextureLayerFunc						framebufferTextureLayer;
+glFramebufferTextureMultisampleMultiviewOVRFunc		framebufferTextureMultisampleMultiviewOVR;
+glFramebufferTextureMultiviewOVRFunc				framebufferTextureMultiviewOVR;
 glFrontFaceFunc										frontFace;
 glGenBuffersFunc									genBuffers;
 glGenFramebuffersFunc								genFramebuffers;
diff --git a/framework/opengl/wrapper/glwImpl.inl b/framework/opengl/wrapper/glwImpl.inl
index ed39d82..c958017 100644
--- a/framework/opengl/wrapper/glwImpl.inl
+++ b/framework/opengl/wrapper/glwImpl.inl
@@ -1388,6 +1388,22 @@
 	gl->framebufferTextureLayer(target, attachment, texture, level, layer);
 }
 
+void glwFramebufferTextureMultisampleMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews)
+{
+	const glw::Functions* gl = glw::getCurrentThreadFunctions();
+	if (!gl)
+		return;
+	gl->framebufferTextureMultisampleMultiviewOVR(target, attachment, texture, level, samples, baseViewIndex, numViews);
+}
+
+void glwFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews)
+{
+	const glw::Functions* gl = glw::getCurrentThreadFunctions();
+	if (!gl)
+		return;
+	gl->framebufferTextureMultiviewOVR(target, attachment, texture, level, baseViewIndex, numViews);
+}
+
 void glwFrontFace (GLenum mode)
 {
 	const glw::Functions* gl = glw::getCurrentThreadFunctions();
diff --git a/framework/opengl/wrapper/glwInitExtES.inl b/framework/opengl/wrapper/glwInitExtES.inl
index fc74f3b..a167f56 100644
--- a/framework/opengl/wrapper/glwInitExtES.inl
+++ b/framework/opengl/wrapper/glwInitExtES.inl
@@ -137,3 +137,13 @@
 	gl->drawRangeElementsBaseVertex		= (glDrawRangeElementsBaseVertexFunc)		loader->get("glDrawRangeElementsBaseVertexOES");
 	gl->multiDrawElementsBaseVertex		= (glMultiDrawElementsBaseVertexFunc)		loader->get("glMultiDrawElementsBaseVertexOES");
 }
+
+if (de::contains(extSet, "GL_OVR_multiview"))
+{
+	gl->framebufferTextureMultiviewOVR	= (glFramebufferTextureMultiviewOVRFunc)	loader->get("glFramebufferTextureMultiviewOVR");
+}
+
+if (de::contains(extSet, "GL_OVR_multiview_multisampled_render_to_texture"))
+{
+	gl->framebufferTextureMultisampleMultiviewOVR	= (glFramebufferTextureMultisampleMultiviewOVRFunc)	loader->get("glFramebufferTextureMultisampleMultiviewOVR");
+}
diff --git a/framework/opengl/wrapper/glwInitExtGL.inl b/framework/opengl/wrapper/glwInitExtGL.inl
index 590ef0d..2196cdc 100644
--- a/framework/opengl/wrapper/glwInitExtGL.inl
+++ b/framework/opengl/wrapper/glwInitExtGL.inl
@@ -38,3 +38,8 @@
 	gl->getnUniformuiv			= (glGetnUniformuivFunc)			loader->get("glGetnUniformuiv");
 	gl->readnPixels				= (glReadnPixelsFunc)				loader->get("glReadnPixels");
 }
+
+if (de::contains(extSet, "GL_OVR_multiview"))
+{
+	gl->framebufferTextureMultiviewOVR	= (glFramebufferTextureMultiviewOVRFunc)	loader->get("glFramebufferTextureMultiviewOVR");
+}
diff --git a/framework/platform/null/tcuNullRenderContextFuncs.inl b/framework/platform/null/tcuNullRenderContextFuncs.inl
index 8b39a19..0f00e72 100644
--- a/framework/platform/null/tcuNullRenderContextFuncs.inl
+++ b/framework/platform/null/tcuNullRenderContextFuncs.inl
@@ -1461,6 +1461,29 @@
 
 }
 
+GLW_APICALL void GLW_APIENTRY glFramebufferTextureMultisampleMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLsizei samples, GLint baseViewIndex, GLsizei numViews)
+{
+	DE_UNREF(target);
+	DE_UNREF(attachment);
+	DE_UNREF(texture);
+	DE_UNREF(level);
+	DE_UNREF(samples);
+	DE_UNREF(baseViewIndex);
+	DE_UNREF(numViews);
+
+}
+
+GLW_APICALL void GLW_APIENTRY glFramebufferTextureMultiviewOVR (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint baseViewIndex, GLsizei numViews)
+{
+	DE_UNREF(target);
+	DE_UNREF(attachment);
+	DE_UNREF(texture);
+	DE_UNREF(level);
+	DE_UNREF(baseViewIndex);
+	DE_UNREF(numViews);
+
+}
+
 GLW_APICALL void GLW_APIENTRY glFrontFace (GLenum mode)
 {
 	DE_UNREF(mode);
diff --git a/framework/platform/null/tcuNullRenderContextInitFuncs.inl b/framework/platform/null/tcuNullRenderContextInitFuncs.inl
index a6c58fe..b6478b0 100644
--- a/framework/platform/null/tcuNullRenderContextInitFuncs.inl
+++ b/framework/platform/null/tcuNullRenderContextInitFuncs.inl
@@ -176,6 +176,8 @@
 gl->framebufferTexture2D						= glFramebufferTexture2D;
 gl->framebufferTexture3D						= glFramebufferTexture3D;
 gl->framebufferTextureLayer						= glFramebufferTextureLayer;
+gl->framebufferTextureMultisampleMultiviewOVR	= glFramebufferTextureMultisampleMultiviewOVR;
+gl->framebufferTextureMultiviewOVR				= glFramebufferTextureMultiviewOVR;
 gl->frontFace									= glFrontFace;
 gl->genBuffers									= glGenBuffers;
 gl->genFramebuffers								= glGenFramebuffers;
diff --git a/modules/gles3/functional/CMakeLists.txt b/modules/gles3/functional/CMakeLists.txt
index 1adc70e..be74b19 100644
--- a/modules/gles3/functional/CMakeLists.txt
+++ b/modules/gles3/functional/CMakeLists.txt
@@ -53,6 +53,8 @@
 	es3fFunctionalTests.hpp
 	es3fLifetimeTests.cpp
 	es3fLifetimeTests.hpp
+	es3fMultiviewTests.cpp
+	es3fMultiviewTests.hpp
 	es3fPrerequisiteTests.cpp
 	es3fPrerequisiteTests.hpp
 	es3fRasterizationTests.cpp
diff --git a/modules/gles3/functional/es3fFunctionalTests.cpp b/modules/gles3/functional/es3fFunctionalTests.cpp
index 5a57831..1e352da 100644
--- a/modules/gles3/functional/es3fFunctionalTests.cpp
+++ b/modules/gles3/functional/es3fFunctionalTests.cpp
@@ -47,6 +47,7 @@
 #include "es3fBlendTests.hpp"
 #include "es3fRandomFragmentOpTests.hpp"
 #include "es3fMultisampleTests.hpp"
+#include "es3fMultiviewTests.hpp"
 #include "es3fImplementationLimitTests.hpp"
 #include "es3fDitheringTests.hpp"
 #include "es3fClippingTests.hpp"
@@ -272,6 +273,7 @@
 		addChild(new FboStencilTests		(m_context));
 		addChild(new FramebufferBlitTests	(m_context));
 		addChild(new FboMultisampleTests	(m_context));
+		addChild(new MultiviewTests			(m_context));
 		addChild(new FboInvalidateTests		(m_context));
 	}
 };
diff --git a/modules/gles3/functional/es3fMultiviewTests.cpp b/modules/gles3/functional/es3fMultiviewTests.cpp
new file mode 100644
index 0000000..09cf487
--- /dev/null
+++ b/modules/gles3/functional/es3fMultiviewTests.cpp
@@ -0,0 +1,359 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.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 Multiview tests.
+ * Tests functionality provided by the three multiview extensions.
+ * Note that this file is formatted using external/openglcts/.clang-format
+ */ /*--------------------------------------------------------------------*/
+
+#include "es3fMultiviewTests.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 gles3
+{
+namespace Functional
+{
+
+static const int   NUM_CASE_ITERATIONS = 1;
+static const float UNIT_SQUARE[16]	 = {
+	1.0f,  1.0f,  0.05f, 1.0f, // Vertex 0
+	1.0f,  -1.0f, 0.05f, 1.0f, // Vertex 1
+	-1.0f, 1.0f,  0.05f, 1.0f, // Vertex 2
+	-1.0f, -1.0f, 0.05f, 1.0f  // Vertex 3
+};
+static const float COLOR_VALUES[] = {
+	1, 0, 0, 1, // Red for level 0
+	0, 1, 0, 1, // Green for level 1
+};
+
+class MultiviewCase : public TestCase
+{
+public:
+	MultiviewCase(Context& context, const char* name, const char* description, int numSamples);
+	~MultiviewCase();
+	void		  init();
+	void		  deinit();
+	IterateResult iterate();
+
+private:
+	MultiviewCase(const MultiviewCase& other);
+	MultiviewCase& operator=(const MultiviewCase& other);
+	void setupFramebufferObjects();
+	void deleteFramebufferObjects();
+
+	glu::ShaderProgram* m_multiviewProgram;
+	deUint32			m_multiviewFbo;
+	deUint32			m_arrayTexture;
+
+	glu::ShaderProgram* m_finalProgram;
+
+	int		  m_caseIndex;
+	const int m_numSamples;
+	const int m_width;
+	const int m_height;
+};
+
+MultiviewCase::MultiviewCase(Context& context, const char* name, const char* description, int numSamples)
+	: TestCase(context, name, description)
+	, m_multiviewProgram(DE_NULL)
+	, m_multiviewFbo(0)
+	, m_arrayTexture(0)
+	, m_finalProgram(DE_NULL)
+	, m_caseIndex(0)
+	, m_numSamples(numSamples)
+	, m_width(512)
+	, m_height(512)
+{
+}
+
+MultiviewCase::~MultiviewCase()
+{
+	MultiviewCase::deinit();
+}
+
+void MultiviewCase::setupFramebufferObjects()
+{
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+	// First create the array texture and multiview FBO.
+
+	gl.genTextures(1, &m_arrayTexture);
+	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_arrayTexture);
+	gl.texStorage3D(GL_TEXTURE_2D_ARRAY, 1 /* num mipmaps */, GL_RGBA8, m_width / 2, m_height, 2 /* num levels */);
+	gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+	gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "Create array texture");
+
+	gl.genFramebuffers(1, &m_multiviewFbo);
+	gl.bindFramebuffer(GL_FRAMEBUFFER, m_multiviewFbo);
+	if (m_numSamples == 1)
+	{
+		gl.framebufferTextureMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_arrayTexture, 0 /* mip level */,
+										  0 /* base view index */, 2 /* num views */);
+	}
+	else
+	{
+		gl.framebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_arrayTexture,
+													 0 /* mip level */, m_numSamples /* samples */,
+													 0 /* base view index */, 2 /* num views */);
+	}
+	GLU_EXPECT_NO_ERROR(gl.getError(), "Create multiview FBO");
+	deUint32 fboStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+	if (fboStatus == GL_FRAMEBUFFER_UNSUPPORTED)
+	{
+		throw tcu::NotSupportedError("Framebuffer unsupported", "", __FILE__, __LINE__);
+	}
+	else if (fboStatus != GL_FRAMEBUFFER_COMPLETE)
+	{
+		throw tcu::TestError("Failed to create framebuffer object", "", __FILE__, __LINE__);
+	}
+}
+
+void MultiviewCase::deleteFramebufferObjects()
+{
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+	gl.deleteTextures(1, &m_arrayTexture);
+	gl.deleteFramebuffers(1, &m_multiviewFbo);
+}
+
+void MultiviewCase::init()
+{
+	const glu::ContextInfo& contextInfo = m_context.getContextInfo();
+	bool					mvsupported = contextInfo.isExtensionSupported("GL_OVR_multiview");
+	if (!mvsupported)
+	{
+		TCU_THROW(NotSupportedError, "Multiview is not supported");
+	}
+
+	if (m_numSamples > 1)
+	{
+		bool msaasupported = contextInfo.isExtensionSupported("GL_OVR_multiview_multisampled_render_to_texture");
+		if (!msaasupported)
+		{
+			TCU_THROW(NotSupportedError, "Implicit MSAA multiview is not supported");
+		}
+	}
+
+	const char* multiviewVertexShader = "#version 300 es\n"
+										"#extension GL_OVR_multiview : enable\n"
+										"layout(num_views=2) in;\n"
+										"layout(location = 0) in mediump vec4 a_position;\n"
+										"uniform mediump vec4 uColor[2];\n"
+										"out mediump vec4 vColor;\n"
+										"void main() {\n"
+										"  vColor = uColor[gl_ViewID_OVR];\n"
+										"  gl_Position = a_position;\n"
+										"}\n";
+
+	const char* multiviewFragmentShader = "#version 300 es\n"
+										  "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
+										  "in mediump vec4 vColor;\n"
+										  "void main() {\n"
+										  "  dEQP_FragColor = vColor;\n"
+										  "}\n";
+
+	m_multiviewProgram = new glu::ShaderProgram(
+		m_context.getRenderContext(), glu::makeVtxFragSources(multiviewVertexShader, multiviewFragmentShader));
+	DE_ASSERT(!m_multiviewProgram);
+	if (!m_multiviewProgram->isOk())
+	{
+		m_testCtx.getLog() << *m_multiviewProgram;
+		TCU_FAIL("Failed to compile multiview shader");
+	}
+
+	// Draw the first layer on the left half of the screen and the second layer
+	// on the right half.
+	const char* finalVertexShader = "#version 300 es\n"
+									"layout(location = 0) in mediump vec4 a_position;\n"
+									"out highp vec3 vTexCoord;\n"
+									"void main() {\n"
+									"  vTexCoord.x = fract(a_position.x + 1.0);\n"
+									"  vTexCoord.y = .5 * (a_position.y + 1.0);\n"
+									"  vTexCoord.z = a_position.x;\n"
+									"  gl_Position = a_position;\n"
+									"}\n";
+
+	const char* finalFragmentShader = "#version 300 es\n"
+									  "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
+									  "uniform sampler2DArray uArrayTexture;\n"
+									  "in highp vec3 vTexCoord;\n"
+									  "void main() {\n"
+									  "  vec3 uvw = vTexCoord;\n"
+									  "  uvw.z = floor(vTexCoord.z + 1.0);\n"
+									  "  dEQP_FragColor = texture(uArrayTexture, uvw);\n"
+									  "}\n";
+
+	m_finalProgram = new glu::ShaderProgram(m_context.getRenderContext(),
+											glu::makeVtxFragSources(finalVertexShader, finalFragmentShader));
+	DE_ASSERT(!m_finalProgram);
+	if (!m_finalProgram->isOk())
+	{
+		m_testCtx.getLog() << *m_finalProgram;
+		TCU_FAIL("Failed to compile final shader");
+	}
+
+	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+	GLU_CHECK_MSG("Case initialization finished");
+}
+
+void MultiviewCase::deinit()
+{
+	deleteFramebufferObjects();
+	delete m_multiviewProgram;
+	m_multiviewProgram = DE_NULL;
+	delete m_finalProgram;
+	m_finalProgram = DE_NULL;
+}
+
+MultiviewCase::IterateResult MultiviewCase::iterate()
+{
+	TestLog&	log			 = m_testCtx.getLog();
+	deUint32	colorUniform = glGetUniformLocation(m_multiviewProgram->getProgram(), "uColor");
+	std::string header = "Case iteration " + de::toString(m_caseIndex + 1) + " / " + de::toString(NUM_CASE_ITERATIONS);
+	log << TestLog::Section(header, header);
+
+	DE_ASSERT(m_multiviewProgram);
+
+	// Create and bind the multiview FBO.
+
+	try
+	{
+		setupFramebufferObjects();
+	}
+	catch (tcu::NotSupportedError& e)
+	{
+		log << TestLog::Message << "ERROR: " << e.what() << "." << TestLog::EndMessage << TestLog::EndSection;
+		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported");
+		return STOP;
+	}
+	catch (tcu::InternalError& e)
+	{
+		log << TestLog::Message << "ERROR: " << e.what() << "." << TestLog::EndMessage << TestLog::EndSection;
+		m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
+		return STOP;
+	}
+
+	// Draw full screen quad into the multiview framebuffer.
+	// The quad should be instanced into both layers of the array texture.
+
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+	gl.bindFramebuffer(GL_FRAMEBUFFER, m_multiviewFbo);
+	gl.viewport(0, 0, m_width / 2, m_height);
+	gl.useProgram(m_multiviewProgram->getProgram());
+	gl.uniform4fv(colorUniform, 2, COLOR_VALUES);
+	gl.enableVertexAttribArray(0);
+	gl.vertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, &UNIT_SQUARE[0]);
+	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+	// Sample from the array texture to draw a quad into the backbuffer.
+
+	const int backbufferWidth  = m_context.getRenderTarget().getWidth();
+	const int backbufferHeight = m_context.getRenderTarget().getHeight();
+	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+	gl.viewport(0, 0, backbufferWidth, backbufferHeight);
+	gl.useProgram(m_finalProgram->getProgram());
+	gl.bindTexture(GL_TEXTURE_2D_ARRAY, m_arrayTexture);
+	gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
+
+	// Read back the framebuffer, ensure that the left half is red and the
+	// right half is green.
+
+	tcu::Surface pixels(backbufferWidth, backbufferHeight);
+	glu::readPixels(m_context.getRenderContext(), 0, 0, pixels.getAccess());
+	bool failed = false;
+	for (int y = 0; y < backbufferHeight; y++)
+	{
+		for (int x = 0; x < backbufferWidth; x++)
+		{
+			tcu::RGBA pixel = pixels.getPixel(x, y);
+			if (x < backbufferWidth / 2)
+			{
+				if (pixel.getRed() != 255 || pixel.getGreen() != 0 || pixel.getBlue() != 0)
+				{
+					failed = true;
+				}
+			}
+			else
+			{
+				if (pixel.getRed() != 0 || pixel.getGreen() != 255 || pixel.getBlue() != 0)
+				{
+					failed = true;
+				}
+			}
+			if (failed)
+			{
+				break;
+			}
+		}
+	}
+
+	deleteFramebufferObjects();
+
+	if (failed)
+	{
+		log << TestLog::Image("Result image", "Result image", pixels);
+	}
+
+	log << TestLog::Message << "Test result: " << (failed ? "Failed!" : "Passed!") << TestLog::EndMessage;
+
+	if (failed)
+	{
+		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
+		return STOP;
+	}
+
+	return (++m_caseIndex < NUM_CASE_ITERATIONS) ? CONTINUE : STOP;
+}
+
+MultiviewTests::MultiviewTests(Context& context) : TestCaseGroup(context, "multiview", "Multiview Tests")
+{
+}
+
+MultiviewTests::~MultiviewTests()
+{
+}
+
+void MultiviewTests::init()
+{
+	addChild(new MultiviewCase(m_context, "samples_1", "Multiview test without multisampling", 1));
+	addChild(new MultiviewCase(m_context, "samples_2", "Multiview test with MSAAx2", 2));
+	addChild(new MultiviewCase(m_context, "samples_4", "Multiview test without MSAAx4", 4));
+}
+
+} // namespace Functional
+} // namespace gles3
+} // namespace deqp
diff --git a/modules/gles3/functional/es3fMultiviewTests.hpp b/modules/gles3/functional/es3fMultiviewTests.hpp
new file mode 100644
index 0000000..e13bcba
--- /dev/null
+++ b/modules/gles3/functional/es3fMultiviewTests.hpp
@@ -0,0 +1,55 @@
+#ifndef _ES3FMULTIVIEWTESTS_HPP
+#define _ES3FMULTIVIEWTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.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 Multiview tests.
+ * Tests functionality provided by the three multiview extensions.
+ * Note that this file is formatted using external/openglcts/.clang-format
+*/ /*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes3TestCase.hpp"
+
+namespace deqp
+{
+namespace gles3
+{
+namespace Functional
+{
+
+class MultiviewTests : public TestCaseGroup
+{
+public:
+	MultiviewTests(Context& context);
+	~MultiviewTests();
+
+	void init();
+
+private:
+	MultiviewTests(const MultiviewTests& other);
+	MultiviewTests& operator=(const MultiviewTests& other);
+};
+
+} // namespace Functional
+} // namespace gles3
+} // namespace deqp
+
+#endif // _ES3FMULTIVIEWTESTS_HPP
diff --git a/scripts/opengl/src_util.py b/scripts/opengl/src_util.py
index 6494273..cfb5120 100644
--- a/scripts/opengl/src_util.py
+++ b/scripts/opengl/src_util.py
@@ -72,6 +72,8 @@
 	'GL_KHR_robustness',
 	'GL_EXT_draw_elements_base_vertex',
 	'GL_OES_draw_elements_base_vertex',
+	'GL_OVR_multiview',
+	'GL_OVR_multiview_multisampled_render_to_texture',
 ]
 
 def getGLRegistry ():