Merge "mustpass: Exclude one more test in dEQP-VK.binding_model"
diff --git a/android/cts/master/egl-master.txt b/android/cts/master/egl-master.txt
index 2b13d90..d304aeb 100644
--- a/android/cts/master/egl-master.txt
+++ b/android/cts/master/egl-master.txt
@@ -3671,3 +3671,4 @@
 dEQP-EGL.functional.wide_color.pbuffer_8888_colorspace_default
 dEQP-EGL.functional.wide_color.pbuffer_8888_colorspace_srgb
 dEQP-EGL.functional.wide_color.pbuffer_8888_colorspace_p3
+dEQP-EGL.functional.hdr_color.8888
diff --git a/android/cts/master/gles2-master.txt b/android/cts/master/gles2-master.txt
index 37db425..e007b1b 100644
--- a/android/cts/master/gles2-master.txt
+++ b/android/cts/master/gles2-master.txt
@@ -1115,6 +1115,11 @@
 dEQP-GLES2.functional.shaders.declarations.invalid_declarations.uniform_in_fragment_main
 dEQP-GLES2.functional.shaders.declarations.invalid_declarations.varying_in_vertex_main
 dEQP-GLES2.functional.shaders.declarations.invalid_declarations.varying_in_fragment_main
+dEQP-GLES2.functional.shaders.declarations.unspecified_precision.float_partially_specified_fragment
+dEQP-GLES2.functional.shaders.declarations.unspecified_precision.float_fragment
+dEQP-GLES2.functional.shaders.declarations.unspecified_precision.vec2_fragment
+dEQP-GLES2.functional.shaders.declarations.unspecified_precision.vec3_fragment
+dEQP-GLES2.functional.shaders.declarations.unspecified_precision.vec4_fragment
 dEQP-GLES2.functional.shaders.swizzles.vector_swizzles.mediump_vec2_x_vertex
 dEQP-GLES2.functional.shaders.swizzles.vector_swizzles.mediump_vec2_x_fragment
 dEQP-GLES2.functional.shaders.swizzles.vector_swizzles.mediump_vec2_xx_vertex
@@ -6869,6 +6874,10 @@
 dEQP-GLES2.functional.shaders.struct.uniform.sampler_fragment
 dEQP-GLES2.functional.shaders.struct.uniform.sampler_nested_vertex
 dEQP-GLES2.functional.shaders.struct.uniform.sampler_nested_fragment
+dEQP-GLES2.functional.shaders.struct.uniform.sampler_in_function_arg_vertex
+dEQP-GLES2.functional.shaders.struct.uniform.sampler_in_function_arg_fragment
+dEQP-GLES2.functional.shaders.struct.uniform.sampler_in_array_function_arg_vertex
+dEQP-GLES2.functional.shaders.struct.uniform.sampler_in_array_function_arg_fragment
 dEQP-GLES2.functional.shaders.struct.uniform.equal_vertex
 dEQP-GLES2.functional.shaders.struct.uniform.equal_fragment
 dEQP-GLES2.functional.shaders.struct.uniform.not_equal_vertex
diff --git a/android/cts/master/gles3-master.txt b/android/cts/master/gles3-master.txt
index 6e661fe..2ce0ce6 100644
--- a/android/cts/master/gles3-master.txt
+++ b/android/cts/master/gles3-master.txt
@@ -2832,6 +2832,37 @@
 dEQP-GLES3.functional.shaders.declarations.invalid_declarations.uniform_block_array_without_instance_name_2_fragment
 dEQP-GLES3.functional.shaders.declarations.invalid_declarations.uniform_block_in_vertex
 dEQP-GLES3.functional.shaders.declarations.invalid_declarations.uniform_block_in_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.float_partially_specified_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.float_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.vec2_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.vec3_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.vec4_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler3D_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler3D_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.samplerCubeShadow_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.samplerCubeShadow_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DShadow_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DShadow_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DArray_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DArray_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DArrayShadow_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.sampler2DArrayShadow_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler2D_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler2D_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler3D_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler3D_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isamplerCube_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isamplerCube_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler2DArray_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.isampler2DArray_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler2D_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler2D_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler3D_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler3D_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usamplerCube_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usamplerCube_fragment
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler2DArray_vertex
+dEQP-GLES3.functional.shaders.declarations.unspecified_precision.usampler2DArray_fragment
 dEQP-GLES3.functional.shaders.swizzles.vector_swizzles.mediump_vec2_x_vertex
 dEQP-GLES3.functional.shaders.swizzles.vector_swizzles.mediump_vec2_x_fragment
 dEQP-GLES3.functional.shaders.swizzles.vector_swizzles.mediump_vec2_xx_vertex
@@ -4449,6 +4480,14 @@
 dEQP-GLES3.functional.shaders.arrays.invalid.constructor_c_style3_fragment
 dEQP-GLES3.functional.shaders.arrays.invalid.constructor_c_style4_vertex
 dEQP-GLES3.functional.shaders.arrays.invalid.constructor_c_style4_fragment
+dEQP-GLES3.functional.shaders.arrays.complex_expression.and_short_circuits_vertex
+dEQP-GLES3.functional.shaders.arrays.complex_expression.and_short_circuits_fragment
+dEQP-GLES3.functional.shaders.arrays.complex_expression.or_short_circuits_vertex
+dEQP-GLES3.functional.shaders.arrays.complex_expression.or_short_circuits_fragment
+dEQP-GLES3.functional.shaders.arrays.complex_expression.ternary_only_evaluates_one_operand_vertex
+dEQP-GLES3.functional.shaders.arrays.complex_expression.ternary_only_evaluates_one_operand_fragment
+dEQP-GLES3.functional.shaders.arrays.complex_expression.sequence_side_effects_affecting_compared_array_content_vertex
+dEQP-GLES3.functional.shaders.arrays.complex_expression.sequence_side_effects_affecting_compared_array_content_fragment
 dEQP-GLES3.functional.shaders.large_constant_arrays.indexing.float_16_vertex
 dEQP-GLES3.functional.shaders.large_constant_arrays.indexing.float_16_fragment
 dEQP-GLES3.functional.shaders.large_constant_arrays.indexing.float_32_vertex
@@ -6540,6 +6579,34 @@
 dEQP-GLES3.functional.shaders.indexing.matrix_subscript.mat4_dynamic_loop_write_static_loop_read_fragment
 dEQP-GLES3.functional.shaders.indexing.matrix_subscript.mat4_dynamic_loop_write_dynamic_loop_read_vertex
 dEQP-GLES3.functional.shaders.indexing.matrix_subscript.mat4_dynamic_loop_write_dynamic_loop_read_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.matrix_twice_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.matrix_twice_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.with_value_from_indexing_expression_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.with_value_from_indexing_expression_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.lvalue_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.lvalue_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.lvalue_with_value_from_indexing_expression_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.lvalue_with_value_from_indexing_expression_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.builtin_fncall_out_parameter_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.builtin_fncall_out_parameter_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.user_defined_fncall_out_parameter_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.user_defined_fncall_out_parameter_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.user_defined_fncall_inout_parameter_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.user_defined_fncall_inout_parameter_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.with_side_effects_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.with_side_effects_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.inout_with_side_effects_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.inout_with_side_effects_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.user_defined_fncall_inout_parameter_with_index_with_side_effects_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.user_defined_fncall_inout_parameter_with_index_with_side_effects_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.lvalue_with_uint_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.lvalue_with_uint_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.uniform_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.uniform_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.sequence_vector_lvalue_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.sequence_vector_lvalue_fragment
+dEQP-GLES3.functional.shaders.indexing.moredynamic.matrix_twice_in_lvalue_vertex
+dEQP-GLES3.functional.shaders.indexing.moredynamic.matrix_twice_in_lvalue_fragment
 dEQP-GLES3.functional.shaders.loops.for_constant_iterations.basic_lowp_int_vertex
 dEQP-GLES3.functional.shaders.loops.for_constant_iterations.basic_lowp_int_fragment
 dEQP-GLES3.functional.shaders.loops.for_constant_iterations.basic_lowp_float_vertex
@@ -7111,6 +7178,14 @@
 dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.nested_tricky_dataflow_2_vertex
 dEQP-GLES3.functional.shaders.loops.do_while_dynamic_iterations.nested_tricky_dataflow_2_fragment
 dEQP-GLES3.functional.shaders.loops.custom.continue_in_fragment_for_loop
+dEQP-GLES3.functional.shaders.loops.short_circuit.while_vertex
+dEQP-GLES3.functional.shaders.loops.short_circuit.while_fragment
+dEQP-GLES3.functional.shaders.loops.short_circuit.for_vertex
+dEQP-GLES3.functional.shaders.loops.short_circuit.for_fragment
+dEQP-GLES3.functional.shaders.loops.short_circuit.do_while_vertex
+dEQP-GLES3.functional.shaders.loops.short_circuit.do_while_fragment
+dEQP-GLES3.functional.shaders.loops.short_circuit.while_sequence_vertex
+dEQP-GLES3.functional.shaders.loops.short_circuit.while_sequence_fragment
 dEQP-GLES3.functional.shaders.operator.unary_operator.plus.lowp_float_vertex
 dEQP-GLES3.functional.shaders.operator.unary_operator.plus.lowp_float_fragment
 dEQP-GLES3.functional.shaders.operator.unary_operator.plus.mediump_float_vertex
diff --git a/data/gles2/shaders/declarations.test b/data/gles2/shaders/declarations.test
index 4dfb0a4..80c513f 100644
--- a/data/gles2/shaders/declarations.test
+++ b/data/gles2/shaders/declarations.test
@@ -138,3 +138,63 @@
 	end
 
 end # invalid_declarations
+
+group unspecified_precision "Invalid declarations with unspecified precision"
+
+	case float_partially_specified_fragment
+		expect compile_fail
+		vertex ""
+			${VERTEX_DECLARATIONS}
+			void main() {}
+		""
+		fragment ""
+			// no global precision qualifier (e.g. precision mediump float)
+			void main() {
+				mediump float x = 1.0;
+				vec3 y = vec3(x);
+				mediump vec4 z = vec4(y, x);
+			}
+		""
+	end
+
+	case float_fragment
+		expect compile_fail
+		vertex ""
+			void main() {}
+		""
+		fragment ""
+			void main() { float v; }
+		""
+	end
+
+	case vec2_fragment
+		expect compile_fail
+		vertex ""
+			void main() {}
+		""
+		fragment ""
+			void main() { vec2 v; }
+		""
+	end
+
+	case vec3_fragment
+		expect compile_fail
+		vertex ""
+			void main() {}
+		""
+		fragment ""
+			void main() { vec3 v; }
+		""
+	end
+
+	case vec4_fragment
+		expect compile_fail
+		vertex ""
+			void main() {}
+		""
+		fragment ""
+			void main() { vec4 v; }
+		""
+	end
+
+end # unspecified_precision
diff --git a/data/gles3/shaders/arrays.test b/data/gles3/shaders/arrays.test
index 2144a11..4a9c5fe 100644
--- a/data/gles3/shaders/arrays.test
+++ b/data/gles3/shaders/arrays.test
@@ -1996,3 +1996,134 @@
 	end
 
 end # invalid
+
+# https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/glsl3/array-in-complex-expression.html
+group complex_expression "Arrays in complex expressions"
+
+	case and_short_circuits
+		version 300 es
+		values
+		{
+			output int g = -1;
+		}
+
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			int[2] plus() {
+				++g;
+				return int[2](g, g);
+			}
+
+			bool minus() {
+				--g;
+				return false;
+			}
+
+			void main() {
+				${SETUP}
+				g = 0;
+				int a[2] = int[2](0, 0);
+				// The plus() call must not be evaluated, since && short-circuits
+				minus() && (a == plus());
+				${OUTPUT}
+			}
+		""
+	end
+
+	case or_short_circuits
+		version 300 es
+		values
+		{
+			output int g = -1;
+		}
+
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			int[2] plus() {
+				++g;
+				return int[2](g, g);
+			}
+
+			bool minus() {
+				--g;
+				return false;
+			}
+
+			void main() {
+				${SETUP}
+				g = 0;
+				int a[2] = int[2](0, 0);
+				// The function call must not be evaluated, since && short-circuits
+				minus() && (a == plus());
+				${OUTPUT}
+			}
+		""
+	end
+
+	case ternary_only_evaluates_one_operand
+		version 300 es
+		values
+		{
+			output int g = 0;
+		}
+
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			int[2] plus() {
+				++g;
+				return int[2](g, g);
+			}
+
+			void main() {
+				${SETUP}
+				g = 0;
+				int a[2] = int[2](0, 0);
+				// The function call must not be evaluated, since the condition is true.
+				(g == 0) ? true : (a == plus());
+				${OUTPUT}
+			}
+		""
+	end
+
+	case sequence_side_effects_affecting_compared_array_content
+		version 300 es
+		values
+		{
+			output bool success = true;
+		}
+
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			int[2] func(int param) {
+				return int[2](param, param);
+			}
+
+			void main() {
+				${SETUP}
+				int a[2];
+				for (int i = 0; i < 2; ++i) {
+					a[i] = 1;
+				}
+				int j = 0;
+				// Sequence operator evaluates operands from left to right (ESSL 3.00 section 5.9).
+				// The function call that returns the array needs to be evaluated after ++j
+				// for the expression to return the correct value (true).
+				success = ((++j), (a == func(j)));
+				${OUTPUT}
+			}
+		""
+	end
+
+end # complex_expression
diff --git a/data/gles3/shaders/declarations.test b/data/gles3/shaders/declarations.test
index 86f98d9..22945c8 100644
--- a/data/gles3/shaders/declarations.test
+++ b/data/gles3/shaders/declarations.test
@@ -589,3 +589,208 @@
 	end
 
 end # invalid_declarations
+
+group unspecified_precision "Invalid declarations with unspecified precision"
+
+	case float_partially_specified_fragment
+		version 300 es
+		expect compile_fail
+		vertex ""
+			#version 300 es
+			${VERTEX_DECLARATIONS}
+			void main() {}
+		""
+		fragment ""
+			#version 300 es
+			// no global precision qualifier (e.g. precision mediump float)
+			void main() {
+				mediump float x = 1.0;
+				vec3 y = vec3(x);
+				mediump vec4 z = vec4(y, x);
+			}
+		""
+	end
+
+	case float_fragment
+		version 300 es
+		expect compile_fail
+		vertex ""
+			#version 300 es
+			void main() {}
+		""
+		fragment ""
+			#version 300 es
+			void main() { float v; }
+		""
+	end
+
+	case vec2_fragment
+		version 300 es
+		expect compile_fail
+		vertex ""
+			#version 300 es
+			void main() {}
+		""
+		fragment ""
+			#version 300 es
+			void main() { vec2 v; }
+		""
+	end
+
+	case vec3_fragment
+		version 300 es
+		expect compile_fail
+		vertex ""
+			#version 300 es
+			void main() {}
+		""
+		fragment ""
+			#version 300 es
+			void main() { vec3 v; }
+		""
+	end
+
+	case vec4_fragment
+		version 300 es
+		expect compile_fail
+		vertex ""
+			#version 300 es
+			void main() {}
+		""
+		fragment ""
+			#version 300 es
+			void main() { vec4 v; }
+		""
+	end
+
+	case sampler3D
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform sampler3D samp;
+			void main() {}
+		""
+	end
+
+	case samplerCubeShadow
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform samplerCubeShadow samp;
+			void main() {}
+		""
+	end
+
+	case sampler2DShadow
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform sampler2DShadow samp;
+			void main() {}
+		""
+	end
+
+	case sampler2DArray
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform sampler2DArray samp;
+			void main() {}
+		""
+	end
+
+	case sampler2DArrayShadow
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform sampler2DArrayShadow samp;
+			void main() {}
+		""
+	end
+
+	case isampler2D
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform isampler2D samp;
+			void main() {}
+		""
+	end
+
+	case isampler3D
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform isampler3D samp;
+			void main() {}
+		""
+	end
+
+	case isamplerCube
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform isamplerCube samp;
+			void main() {}
+		""
+	end
+
+	case isampler2DArray
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform isampler2DArray samp;
+			void main() {}
+		""
+	end
+
+	case usampler2D
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform usampler2D samp;
+			void main() {}
+		""
+	end
+
+	case usampler3D
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform usampler3D samp;
+			void main() {}
+		""
+	end
+
+	case usamplerCube
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform usamplerCube samp;
+			void main() {}
+		""
+	end
+
+	case usampler2DArray
+		version 300 es
+		expect compile_fail
+		both ""
+			#version 300 es
+			uniform usampler2DArray samp;
+			void main() {}
+		""
+	end
+
+end # unspecified_precision
diff --git a/data/gles3/shaders/indexing.test b/data/gles3/shaders/indexing.test
new file mode 100644
index 0000000..49eaa3b
--- /dev/null
+++ b/data/gles3/shaders/indexing.test
@@ -0,0 +1,304 @@
+# https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/glsl3/vector-dynamic-indexing.html
+group moredynamic "More dynamic indexing tests"
+
+	case matrix_twice
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			void main() {
+				mat2 m = mat2(0.0, 0.0, 0.0, 1.0);
+				f = m[u_zero + 1][u_zero + 1];
+				${OUTPUT}
+			}
+		""
+	end
+
+	case with_value_from_indexing_expression
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			void main() {
+				ivec2 i = ivec2(0, 2);
+				vec4 v = vec4(0.0, 0.2, 1.0, 0.4);
+				f = v[i[u_zero + 1]];
+				${OUTPUT}
+			}
+		""
+	end
+
+	case lvalue
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			void main() {
+				vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+				v[u_zero + 1] = 5.0;
+				vec4 expected = vec4(1.0, 5.0, 3.0, 4.0);
+				f = 1.0 - distance(v, expected);
+				${OUTPUT}
+			}
+		""
+	end
+
+	case lvalue_with_value_from_indexing_expression
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			void main() {
+				ivec2 i = ivec2(0, 2);
+				vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+				v[i[u_zero + 1]] = 5.0;
+				vec4 expected = vec4(1.0, 2.0, 5.0, 4.0);
+				f = 1.0 - distance(v, expected);
+				${OUTPUT}
+			}
+		""
+	end
+
+	case builtin_fncall_out_parameter
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			void main() {
+				vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+				modf(5.5, v[u_zero + 3]);
+				vec4 expected = vec4(1.0, 2.0, 3.0, 5.0);
+				f = 1.0 - distance(v, expected);
+				${OUTPUT}
+			}
+		""
+	end
+
+	case user_defined_fncall_out_parameter
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			void foo(out float f) {
+				modf(5.5, f);
+			}
+			void main() {
+				vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+				foo(v[u_zero + 3]);
+				vec4 expected = vec4(1.0, 2.0, 3.0, 5.0);
+				f = 1.0 - distance(v, expected);
+				${OUTPUT}
+			}
+		""
+	end
+
+	case user_defined_fncall_inout_parameter
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			void foo(inout float f) {
+				float g = f + 2.5;
+				modf(g, f);
+			}
+			void main() {
+				vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+				foo(v[u_zero + 2]);
+				vec4 expected = vec4(1.0, 2.0, 5.0, 4.0);
+				f = 1.0 - distance(v, expected);
+				${OUTPUT}
+			}
+		""
+	end
+
+	case with_side_effects
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			int sideEffectCounter = 0;
+			int funcWithSideEffects() {
+				sideEffectCounter++;
+				return 2;
+			}
+			void main() {
+				vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+				v[funcWithSideEffects()] = 5.0;
+				vec4 expected = vec4(1.0, 2.0, 5.0, 4.0);
+				f = 1.0 - distance(v, expected);
+				if (sideEffectCounter != 1) {
+					f = 0.0;
+				}
+				${OUTPUT}
+			}
+		""
+	end
+
+	case inout_with_side_effects
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			int sideEffectCounter = 0;
+			int funcWithSideEffects() {
+				sideEffectCounter++;
+				return 2;
+			}
+			void main() {
+				vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+				v[funcWithSideEffects()]++;
+				vec4 expected = vec4(1.0, 2.0, 4.0, 4.0);
+				f = 1.0 - distance(v, expected);
+				if (sideEffectCounter != 1) {
+					f = 0.0;
+				}
+				${OUTPUT}
+			}
+		""
+	end
+
+	case user_defined_fncall_inout_parameter_with_index_with_side_effects
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			int sideEffectCounter = 0;
+			void foo(inout float f) {
+				float g = f + 2.5;
+				modf(g, f);
+			}
+			int funcWithSideEffects() {
+				sideEffectCounter++;
+				return 2;
+			}
+			void main() {
+				vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+				foo(v[funcWithSideEffects()]);
+				vec4 expected = vec4(1.0, 2.0, 5.0, 4.0);
+				f = 1.0 - distance(v, expected);
+				if (sideEffectCounter != 1) {
+					f = 0.0;
+				}
+				${OUTPUT}
+			}
+		""
+	end
+
+	case lvalue_with_uint
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			void main() {
+				vec4 v = vec4(1.0, 2.0, 3.0, 4.0);
+				v[u_zero] = 5.0;
+				vec4 expected = vec4(5.0, 2.0, 3.0, 4.0);
+				f = 1.0 - distance(v, expected);
+				${OUTPUT}
+			}
+		""
+	end
+
+	case uniform
+		version 300 es
+		values { output float f = 0.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform vec4 u_zeroVec;
+			uniform int u_zero;
+			void main() {
+				f = u_zeroVec[u_zero];
+				${OUTPUT}
+			}
+		""
+	end
+
+	case sequence_vector_lvalue
+		version 300 es
+		values { output bool success = true; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			int sideEffectCounter = 0;
+			float func() {
+				++sideEffectCounter;
+				return -1.0;
+			}
+			void main() {
+				vec4 v = vec4(0.0, 2.0, 4.0, 6.0);
+				float f = (func(), (++v[u_zero + sideEffectCounter]));
+				success = (abs(f - 3.0) < 0.01 && abs(v[1] - 3.0) < 0.01 && sideEffectCounter == 1);
+				${OUTPUT}
+			}
+		""
+	end
+
+	case matrix_twice_in_lvalue
+		version 300 es
+		values { output float f = 1.0; }
+		both ""
+			#version 300 es
+			precision mediump float;
+			${DECLARATIONS}
+
+			uniform int u_zero;
+			void main() {
+				mat2 m = mat2(0.0, 0.0, 0.0, 0.0);
+				m[u_zero + 1][u_zero + 1] = float(u_zero + 1);
+				f = m[1][1];
+				${OUTPUT}
+			}
+		""
+	end
+
+end # moredynamic
diff --git a/data/gles3/shaders/loops.test b/data/gles3/shaders/loops.test
index a8f1e4d..619179b 100644
--- a/data/gles3/shaders/loops.test
+++ b/data/gles3/shaders/loops.test
@@ -27,3 +27,151 @@
 	end
 
 end # custom
+
+# https://github.com/KhronosGroup/WebGL/blob/master/sdk/tests/conformance2/glsl3/short-circuiting-in-loop-condition.html
+group short_circuit "Short-circuiting operator in a loop using a function call with side effects"
+
+	case while
+		version 300 es
+		values
+		{
+			input bool in0 = [ false | true ];
+			output int sideEffectCounter = [ 0 | 10 ];
+		}
+
+		both ""
+			#version 300 es
+			precision mediump float;
+			precision mediump int;
+
+			${DECLARATIONS}
+
+			bool foo() {
+				++sideEffectCounter;
+				return true;
+			}
+
+			void main()
+			{
+				${SETUP}
+				sideEffectCounter = 0;
+				int iterations = 0;
+				while (in0 && foo()) {
+					++iterations;
+					if (iterations >= 10) {
+						break;
+					}
+				}
+				${OUTPUT}
+			}
+		""
+	end
+
+	case for
+		version 300 es
+		values
+		{
+			input bool in0 = [ false | true ];
+			output int sideEffectCounter = [ 0 | 10 ];
+		}
+
+		both ""
+			#version 300 es
+			precision mediump float;
+			precision mediump int;
+
+			${DECLARATIONS}
+
+			bool foo() {
+				++sideEffectCounter;
+				return true;
+			}
+
+			void main()
+			{
+				${SETUP}
+				sideEffectCounter = 0;
+				for (int iterations = 0; true; in0 && foo()) {
+					++iterations;
+					if (iterations > 10) {
+						break;
+					}
+				}
+				${OUTPUT}
+			}
+		""
+	end
+
+	case do_while
+		version 300 es
+		values
+		{
+			input bool in0 = [ false | true ];
+			output int sideEffectCounter = [ 0 | 10 ];
+		}
+
+		both ""
+			#version 300 es
+			precision mediump float;
+			precision mediump int;
+
+			${DECLARATIONS}
+
+			bool foo() {
+				++sideEffectCounter;
+				return true;
+			}
+
+			void main()
+			{
+				${SETUP}
+				sideEffectCounter = 0;
+				int iterations = 0;
+				do {
+					++iterations;
+					if (iterations > 10) {
+						break;
+					}
+				} while (in0 && foo());
+				${OUTPUT}
+			}
+		""
+	end
+
+	case while_sequence
+		version 300 es
+		values
+		{
+			input bool in0 = [ false | true ];
+			output int sideEffectCounter = [ 0 | 10 ];
+		}
+
+		both ""
+			#version 300 es
+			precision mediump float;
+			precision mediump int;
+
+			${DECLARATIONS}
+
+			bool foo() {
+				++sideEffectCounter;
+				return true;
+			}
+
+			void main()
+			{
+				${SETUP}
+				sideEffectCounter = 0;
+				int iterations = 0;
+				while ((in0, in0 && foo())) {
+					++iterations;
+					if (iterations >= 10) {
+						break;
+					}
+				}
+				${OUTPUT}
+			}
+		""
+	end
+
+end # short_circuit
diff --git a/framework/common/tcuInterval.hpp b/framework/common/tcuInterval.hpp
index cc271a1..bbbdf3e 100644
--- a/framework/common/tcuInterval.hpp
+++ b/framework/common/tcuInterval.hpp
@@ -58,42 +58,60 @@
 {
 public:
 				// Empty interval.
-				Interval		(void)
-					: m_hasNaN	(false)
-					, m_lo		(TCU_INFINITY)
-					, m_hi		(-TCU_INFINITY) {}
+				Interval			(void)
+					: m_hasNaN		(false)
+					, m_lo			(TCU_INFINITY)
+					, m_hi			(-TCU_INFINITY)
+					, m_warningLo	(-TCU_INFINITY)
+					, m_warningHi	(TCU_INFINITY) {}
 
 				// Intentionally not explicit. Conversion from double to Interval is common
 				// and reasonable.
-				Interval		(double val)
-					: m_hasNaN	(!!deIsNaN(val))
-					, m_lo		(m_hasNaN ? TCU_INFINITY : val)
-					, m_hi		(m_hasNaN ? -TCU_INFINITY : val) {}
+				Interval			(double val)
+					: m_hasNaN		(!!deIsNaN(val))
+					, m_lo			(m_hasNaN ? TCU_INFINITY : val)
+					, m_hi			(m_hasNaN ? -TCU_INFINITY : val)
+					, m_warningLo	(-TCU_INFINITY)
+					, m_warningHi	(TCU_INFINITY) {}
 
-				Interval		(bool hasNaN_, double lo_, double hi_)
-					: m_hasNaN(hasNaN_), m_lo(lo_), m_hi(hi_) {}
+
+				Interval(bool hasNaN_, double lo_, double hi_)
+					: m_hasNaN(hasNaN_), m_lo(lo_), m_hi(hi_), m_warningLo(-TCU_INFINITY), m_warningHi(TCU_INFINITY) {}
+
+				Interval(bool hasNaN_, double lo_, double hi_, double wlo_, double whi_)
+					: m_hasNaN(hasNaN_), m_lo(lo_), m_hi(hi_), m_warningLo(wlo_), m_warningHi(whi_) {}
 
 				Interval		(const Interval& a, const Interval& b)
-					: m_hasNaN	(a.m_hasNaN || b.m_hasNaN)
-					, m_lo		(de::min(a.lo(), b.lo()))
-					, m_hi		(de::max(a.hi(), b.hi())) {}
+					: m_hasNaN		(a.m_hasNaN || b.m_hasNaN)
+					, m_lo			(de::min(a.lo(), b.lo()))
+					, m_hi			(de::max(a.hi(), b.hi()))
+					, m_warningLo	(de::min(a.warningLo(), b.warningLo()))
+					, m_warningHi	(de::max(a.warningHi(), b.warningHi())) {}
 
 	double		length			(void) const { return m_hi - m_lo; }
 	double		lo				(void) const { return m_lo; }
 	double		hi				(void) const { return m_hi; }
+	double		warningLo		(void) const { return m_warningLo; }
+	double		warningHi		(void) const { return m_warningHi; }
 	bool		hasNaN			(void) const { return m_hasNaN; }
 	Interval	nan				(void) const { return m_hasNaN ? TCU_NAN : Interval(); }
 	bool		empty			(void) const { return m_lo > m_hi; }
 	bool		isFinite		(void) const { return m_lo > -TCU_INFINITY && m_hi < TCU_INFINITY; }
 	bool		isOrdinary		(void) const { return !hasNaN() && !empty() && isFinite(); }
 
+	void		warning			(double lo, double hi)
+	{
+		m_warningLo = lo;
+		m_warningHi = hi;
+	}
 
 	Interval	operator|		(const Interval& other) const
 	{
 		return Interval(m_hasNaN || other.m_hasNaN,
 						de::min(m_lo, other.m_lo),
-						de::max(m_hi, other.m_hi));
-
+						de::max(m_hi, other.m_hi),
+						de::min(m_warningLo, other.m_warningLo),
+						de::max(m_warningHi, other.m_warningHi));
 	}
 
 	Interval&	operator|=		(const Interval& other)
@@ -105,7 +123,9 @@
 	{
 		return Interval(m_hasNaN && other.m_hasNaN,
 						de::max(m_lo, other.m_lo),
-						de::min(m_hi, other.m_hi));
+						de::min(m_hi, other.m_hi),
+						de::max(m_warningLo, other.m_warningLo),
+						de::min(m_warningHi, other.m_warningHi));
 	}
 
 	Interval&	operator&=		(const Interval& other)
@@ -119,6 +139,12 @@
 				(!other.hasNaN() || hasNaN()));
 	}
 
+	bool		containsWarning(const Interval& other) const
+	{
+		return (other.lo() >= warningLo() && other.hi() <= warningHi() &&
+			(!other.hasNaN() || hasNaN()));
+	}
+
 	bool		intersects		(const Interval& other) const
 	{
 		return ((other.hi() >= lo() && other.lo() <= hi()) ||
@@ -127,7 +153,7 @@
 
 	Interval	operator-		(void) const
 	{
-		return Interval(hasNaN(), -hi(), -lo());
+		return Interval(hasNaN(), -hi(), -lo(), -warningHi(), -warningLo());
 	}
 
 	static Interval	unbounded	(bool nan = false)
@@ -151,6 +177,8 @@
 	bool		m_hasNaN;
 	double		m_lo;
 	double		m_hi;
+	double		m_warningLo;
+	double		m_warningHi;
 } DE_WARN_UNUSED_TYPE;
 
 inline Interval	operator+	(const Interval& x) { return x; }
diff --git a/framework/egl/wrapper/eglwEnums.inl b/framework/egl/wrapper/eglwEnums.inl
index fd9831f..927ce81 100644
--- a/framework/egl/wrapper/eglwEnums.inl
+++ b/framework/egl/wrapper/eglwEnums.inl
@@ -273,7 +273,20 @@
 #define EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT					0x333B
 #define EGL_GL_COLORSPACE_BT2020_LINEAR_EXT					0x333F
 #define EGL_GL_COLORSPACE_BT2020_PQ_EXT						0x3340
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT				0x3341
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT				0x3342
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT				0x3343
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT				0x3344
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT				0x3345
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT				0x3346
+#define EGL_SMPTE2086_WHITE_POINT_X_EXT						0x3347
+#define EGL_SMPTE2086_WHITE_POINT_Y_EXT						0x3348
+#define EGL_SMPTE2086_MAX_LUMINANCE_EXT						0x3349
+#define EGL_SMPTE2086_MIN_LUMINANCE_EXT						0x334A
+#define EGL_METADATA_SCALING_EXT							50000
 #define EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT					0x3350
 #define EGL_GL_COLORSPACE_SCRGB_EXT							0x3351
+#define EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT			0x3360
+#define EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT			0x3361
 #define EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT				0x3362
 #define EGL_GL_COLORSPACE_DISPLAY_P3_EXT					0x3363
diff --git a/framework/egl/wrapper/eglwEnumsC.inl b/framework/egl/wrapper/eglwEnumsC.inl
index 2ed94bd..2778800 100644
--- a/framework/egl/wrapper/eglwEnumsC.inl
+++ b/framework/egl/wrapper/eglwEnumsC.inl
@@ -277,3 +277,16 @@
 #define EGL_GL_COLORSPACE_SCRGB_EXT							0x3351
 #define EGL_GL_COLORSPACE_DISPLAY_P3_LINEAR_EXT				0x3362
 #define EGL_GL_COLORSPACE_DISPLAY_P3_EXT					0x3363
+#define EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT			0x3360
+#define EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT			0x3361
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT				0x3341
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT				0x3342
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT				0x3343
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT				0x3344
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT				0x3345
+#define EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT				0x3346
+#define EGL_SMPTE2086_WHITE_POINT_X_EXT						0x3347
+#define EGL_SMPTE2086_WHITE_POINT_Y_EXT						0x3348
+#define EGL_SMPTE2086_MAX_LUMINANCE_EXT						0x3349
+#define EGL_SMPTE2086_MIN_LUMINANCE_EXT						0x334A
+#
\ No newline at end of file
diff --git a/modules/egl/teglTestPackage.cpp b/modules/egl/teglTestPackage.cpp
index 91e1a4c..fd8b3fa 100644
--- a/modules/egl/teglTestPackage.cpp
+++ b/modules/egl/teglTestPackage.cpp
@@ -144,6 +144,7 @@
 		addChild(createGetFrameTimestampsTests	(m_eglTestCtx));
 		addChild(createRobustnessTests			(m_eglTestCtx));
 		addChild(createWideColorTests			(m_eglTestCtx));
+		addChild(createHdrColorTests			(m_eglTestCtx));
 	}
 };
 
diff --git a/modules/egl/teglWideColorTests.cpp b/modules/egl/teglWideColorTests.cpp
index 3c50259..a54af90 100644
--- a/modules/egl/teglWideColorTests.cpp
+++ b/modules/egl/teglWideColorTests.cpp
@@ -106,6 +106,10 @@
 	void				checkFP16Support			(void);
 	void				checkSCRGBSupport			(void);
 	void				checkSCRGBLinearSupport		(void);
+	void				checkbt2020linear			(void);
+	void				checkbt2020pq				(void);
+	void				checkSMPTE2086				(void);
+	void				checkCTA861_3				(void);
 
 protected:
 	void				initEGLSurface				(EGLConfig config);
@@ -313,10 +317,42 @@
 
 void WideColorTest::checkSCRGBLinearSupport (void)
 {
+    const Library&	egl	= m_eglTestCtx.getLibrary();
+
+    if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_gl_colorspace_scrgb_linear"))
+        TCU_THROW(NotSupportedError, "EGL_EXT_gl_colorspace_scrgb_linear is not supported");
+}
+
+void WideColorTest::checkbt2020linear (void)
+{
+    const Library&	egl	= m_eglTestCtx.getLibrary();
+
+    if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_gl_colorspace_bt2020_linear"))
+        TCU_THROW(NotSupportedError, "EGL_EXT_gl_colorspace_bt2020_linear is not supported");
+}
+
+void WideColorTest::checkbt2020pq (void)
+{
+    const Library&	egl	= m_eglTestCtx.getLibrary();
+
+    if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_gl_colorspace_bt2020_pq"))
+        TCU_THROW(NotSupportedError, "EGL_EXT_gl_colorspace_bt2020_pq is not supported");
+}
+
+void WideColorTest::checkSMPTE2086 (void)
+{
+    const Library&	egl	= m_eglTestCtx.getLibrary();
+
+    if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_surface_SMPTE2086_metadata"))
+        TCU_THROW(NotSupportedError, "EGL_EXT_surface_SMPTE2086_metadata is not supported");
+}
+
+void WideColorTest::checkCTA861_3 (void)
+{
 	const Library&	egl	= m_eglTestCtx.getLibrary();
 
-	if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_gl_colorspace_scrgb_linear"))
-		TCU_THROW(NotSupportedError, "EGL_EXT_gl_colorspace_scrgb_linear is not supported");
+	if (!eglu::hasExtension(egl, m_eglDisplay, "EGL_EXT_surface_CTA861_3_metadata"))
+		TCU_THROW(NotSupportedError, "EGL_EXT_surface_CTA861_3_metadata is not supported");
 }
 
 void WideColorTest::check1010102Support (void)
@@ -528,6 +564,8 @@
 	void				init					(void);
 	void				executeTest				(void);
 	IterateResult		iterate					(void);
+	void				addWindowAttributes		(const EGLint* attributes);
+	void				addTestAttributes		(const EGLint* attributes);
 
 protected:
 	void				readPixels				(const glw::Functions& gl, float* dataPtr);
@@ -546,6 +584,8 @@
 
 private:
 	std::vector<EGLint>					m_attribList;
+	std::vector<EGLint>					m_winAttribList;
+	std::vector<EGLint>					m_testAttribList;
 	EGLConfig							m_eglConfig;
 	EGLint								m_surfaceType;
 	EGLint								m_componentType;
@@ -581,6 +621,30 @@
 	m_attribList.push_back(EGL_NONE);
 }
 
+void WideColorSurfaceTest::addWindowAttributes(const EGLint* attributes)
+{
+	deUint32 idx = 0;
+	if (attributes == DE_NULL) return;
+
+	while (attributes[idx] != EGL_NONE)
+	{
+		m_winAttribList.push_back(attributes[idx++]);
+		m_winAttribList.push_back(attributes[idx++]);
+	}
+}
+
+void WideColorSurfaceTest::addTestAttributes(const EGLint *attributes)
+{
+	deUint32 idx = 0;
+	if (attributes == DE_NULL) return;
+
+	while (attributes[idx] != EGL_NONE)
+	{
+		m_testAttribList.push_back(attributes[idx++]);
+		m_testAttribList.push_back(attributes[idx++]);
+	}
+}
+
 void WideColorSurfaceTest::init (void)
 {
 	const Library&	egl	= m_eglTestCtx.getLibrary();
@@ -617,6 +681,12 @@
 		case EGL_GL_COLORSPACE_SCRGB_LINEAR_EXT:
 			checkSCRGBLinearSupport();
 			break;
+		case EGL_GL_COLORSPACE_BT2020_LINEAR_EXT:
+			checkbt2020linear();
+			break;
+		case EGL_GL_COLORSPACE_BT2020_PQ_EXT:
+			checkbt2020pq();
+			break;
 		default:
 			break;
 	}
@@ -1117,6 +1187,10 @@
 			attribs.push_back(EGL_GL_COLORSPACE_KHR);
 			attribs.push_back(m_colorSpace);
 		}
+		for (deUint32 i = 0; i < m_winAttribList.size(); i++)
+		{
+			attribs.push_back(m_winAttribList[i]);
+		}
 		attribs.push_back(EGL_NONE);
 		attribs.push_back(EGL_NONE);
 		const EGLSurface surface = egl.createPbufferSurface(m_eglDisplay, m_eglConfig, attribs.data());
@@ -1145,6 +1219,10 @@
 			attribs.push_back(EGL_GL_COLORSPACE_KHR);
 			attribs.push_back(m_colorSpace);
 		}
+		for (deUint32 i = 0; i < m_winAttribList.size(); i++)
+		{
+			attribs.push_back(m_winAttribList[i]);
+		}
 		attribs.push_back(EGL_NONE);
 		attribs.push_back(EGL_NONE);
 
@@ -1165,6 +1243,30 @@
 
 		doClearTest(surface);
 
+		// If we have any window attributes, check that the values are correct
+		for (deUint32 i = 0; i < m_winAttribList.size(); i +=2)
+		{
+			EGLint value;
+			egl.querySurface(m_eglDisplay, surface, m_winAttribList[i], &value);
+			TCU_CHECK(value == m_winAttribList[i+1]);
+		}
+
+		if (m_testAttribList.size() > 0)
+		{
+			for (deUint32 i = 0; i < m_testAttribList.size(); i +=2)
+			{
+				if (!egl.surfaceAttrib(m_eglDisplay, surface, m_testAttribList[i], m_testAttribList[i+1])) {
+					TCU_FAIL("Unable to set HDR metadata on surface");
+				}
+			}
+			for (deUint32 i = 0; i < m_testAttribList.size(); i +=2)
+			{
+				EGLint value;
+				egl.querySurface(m_eglDisplay, surface, m_testAttribList[i], &value);
+				TCU_CHECK(value == m_testAttribList[i+1]);
+			}
+		}
+
 		egl.destroySurface(m_eglDisplay, surface);
 		EGLU_CHECK_MSG(egl, "eglDestroySurface()");
 	}
@@ -1336,5 +1438,135 @@
 	return new WideColorTests(eglTestCtx);
 }
 
+class HdrColorTest : public WideColorTest
+{
+public:
+	HdrColorTest		(EglTestContext&	eglTestCtx,
+							 const char*		name,
+							 const char*		description);
+
+	void				executeTest				(void);
+	IterateResult		iterate					(void);
+};
+
+HdrColorTest::HdrColorTest (EglTestContext& eglTestCtx, const char* name, const char* description)
+		: WideColorTest(eglTestCtx, name, description)
+{
+}
+
+#define METADATA_SCALE(x) (static_cast<EGLint>(x * EGL_METADATA_SCALING_EXT))
+
+void HdrColorTest::executeTest (void)
+{
+	tcu::TestLog&						log				= m_testCtx.getLog();
+	const Library&						egl				= m_eglTestCtx.getLibrary();
+	egl.bindAPI(EGL_OPENGL_ES_API);
+
+	log << tcu::TestLog::Message << "Test HDR Metadata on Window" << tcu::TestLog::EndMessage;
+
+	checkSMPTE2086();
+	checkCTA861_3();
+
+	// This is an increment FP16 can do between -1.0 to 1.0
+	const float fp16Increment1 = deFloatPow(2.0, -11.0);
+	// This is an increment FP16 can do between 1.0 to 2.0
+	const float fp16Increment2 = deFloatPow(2.0, -10.0);
+
+	std::vector<Iteration> int8888Iterations;
+	// -0.333251953125f ~ -1/3 as seen in fp16
+	// Negative values will be 0 on read with fixed point pixel formats
+	int8888Iterations.push_back(Iteration(-0.333251953125f, fp16Increment1, 10));
+	// test crossing 0
+	int8888Iterations.push_back(Iteration(-fp16Increment1 * 5.0f, fp16Increment1, 10));
+	// test crossing 1.0
+	// Values > 1.0 will be truncated to 1.0 with fixed point pixel formats
+	int8888Iterations.push_back(Iteration(1.0f - fp16Increment2 * 5.0f, fp16Increment2, 10));
+
+	const EGLint windowAttribList8888[] =
+	{
+		EGL_SURFACE_TYPE,				EGL_WINDOW_BIT,
+		EGL_RENDERABLE_TYPE,			EGL_OPENGL_ES2_BIT,
+		EGL_RED_SIZE,					8,
+		EGL_GREEN_SIZE,					8,
+		EGL_BLUE_SIZE,					8,
+		EGL_ALPHA_SIZE,					8,
+		EGL_NONE,						EGL_NONE
+	};
+
+	WideColorSurfaceTest testObj(m_eglTestCtx, "window_8888_colorspace_default", "8888 window surface, default (sRGB) colorspace", windowAttribList8888, EGL_NONE, int8888Iterations);
+	const EGLint attrs[] =
+	{
+		EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, METADATA_SCALE(0.640),
+		EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, METADATA_SCALE(0.330),
+		EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, METADATA_SCALE(0.290),
+		EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, METADATA_SCALE(0.600),
+		EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, METADATA_SCALE(0.150),
+		EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, METADATA_SCALE(0.060),
+		EGL_SMPTE2086_WHITE_POINT_X_EXT, METADATA_SCALE(0.3127),
+		EGL_SMPTE2086_WHITE_POINT_Y_EXT, METADATA_SCALE(0.3290),
+		EGL_SMPTE2086_MAX_LUMINANCE_EXT, METADATA_SCALE(300.0),
+		EGL_SMPTE2086_MIN_LUMINANCE_EXT, METADATA_SCALE(0.7),
+		EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT, METADATA_SCALE(300),
+		EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT, METADATA_SCALE(75),
+		EGL_NONE
+	};
+
+	testObj.addWindowAttributes(attrs);
+
+	const EGLint testAttrs[] =
+	{
+		EGL_SMPTE2086_DISPLAY_PRIMARY_RX_EXT, METADATA_SCALE(0.680),
+		EGL_SMPTE2086_DISPLAY_PRIMARY_RY_EXT, METADATA_SCALE(0.320),
+		EGL_SMPTE2086_DISPLAY_PRIMARY_GX_EXT, METADATA_SCALE(0.265),
+		EGL_SMPTE2086_DISPLAY_PRIMARY_GY_EXT, METADATA_SCALE(0.690),
+		EGL_SMPTE2086_DISPLAY_PRIMARY_BX_EXT, METADATA_SCALE(0.440),
+		EGL_SMPTE2086_DISPLAY_PRIMARY_BY_EXT, METADATA_SCALE(0.320),
+		EGL_SMPTE2086_WHITE_POINT_X_EXT, METADATA_SCALE(0.2200),
+		EGL_SMPTE2086_WHITE_POINT_Y_EXT, METADATA_SCALE(0.2578),
+		EGL_SMPTE2086_MAX_LUMINANCE_EXT, METADATA_SCALE(123.0),
+		EGL_SMPTE2086_MIN_LUMINANCE_EXT, METADATA_SCALE(0.123),
+		EGL_CTA861_3_MAX_CONTENT_LIGHT_LEVEL_EXT, METADATA_SCALE(234),
+		EGL_CTA861_3_MAX_FRAME_AVERAGE_LEVEL_EXT, METADATA_SCALE(67),
+		EGL_NONE
+	};
+	testObj.addTestAttributes(testAttrs);
+
+	testObj.init();
+	testObj.executeTest();
+}
+
+TestCase::IterateResult HdrColorTest::iterate (void)
+{
+	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+	executeTest();
+	return STOP;
+}
+
+class HdrColorTests : public TestCaseGroup
+{
+public:
+	HdrColorTests		(EglTestContext& eglTestCtx);
+	void				init				(void);
+
+private:
+	HdrColorTests		(const HdrColorTests&);
+	HdrColorTests&		operator=			(const HdrColorTests&);
+};
+
+HdrColorTests::HdrColorTests (EglTestContext& eglTestCtx)
+		: TestCaseGroup(eglTestCtx, "hdr_color", "HDR Color tests")
+{
+}
+
+void HdrColorTests::init (void)
+{
+	addChild(new HdrColorTest(m_eglTestCtx, "8888", "Verify that SMPTE 2086 extension exists"));
+}
+
+TestCaseGroup* createHdrColorTests (EglTestContext& eglTestCtx)
+{
+	return new HdrColorTests(eglTestCtx);
+}
+
 } // egl
 } // deqp
diff --git a/modules/egl/teglWideColorTests.hpp b/modules/egl/teglWideColorTests.hpp
index 5f58f58..d663db2 100644
--- a/modules/egl/teglWideColorTests.hpp
+++ b/modules/egl/teglWideColorTests.hpp
@@ -32,6 +32,7 @@
 {
 
 TestCaseGroup* createWideColorTests (EglTestContext& eglTestCtx);
+TestCaseGroup* createHdrColorTests (EglTestContext& eglTestCtx);
 
 } // egl
 } // deqp
diff --git a/modules/gles2/functional/es2fShaderStructTests.cpp b/modules/gles2/functional/es2fShaderStructTests.cpp
index 555a154..21d84c5 100644
--- a/modules/gles2/functional/es2fShaderStructTests.cpp
+++ b/modules/gles2/functional/es2fShaderStructTests.cpp
@@ -111,7 +111,7 @@
 				throw tcu::NotSupportedError("Dynamic loops not supported");
 		}
 
-		if ((m_flags && FLAG_USES_TEXTURES) && m_isVertexCase)
+		if ((m_flags & FLAG_USES_TEXTURES) && m_isVertexCase)
 		{
 			int numTextures = 0;
 			m_renderCtx.getFunctions().getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &numTextures);
@@ -1859,6 +1859,58 @@
 			c.color.xyz() = c.texture2D(TEXTURE_BRICK, c.coords.swizzle(0,1) * 0.25f + 0.5f).swizzle(0,1,2);
 		});
 
+	UNIFORM_STRUCT_CASE(sampler_in_function_arg, "Sampler in struct as function arg", FLAG_USES_TEXTURES,
+		LineStream()
+		<< "${DECLARATIONS}"
+		<< ""
+		<< "struct S {"
+		<< "	sampler2D		source;"
+		<< "};"
+		<< ""
+		<< "mediump vec4 fun(S s) {"
+		<< "	return texture2D(s.source, vec2(0.5));"
+		<< "}"
+		<< ""
+		<< "uniform S s;"
+		<< "void main (void)"
+		<< "{"
+		<< "	${DST} = fun(s);"
+		<< "	${ASSIGN_POS}"
+		<< "}",
+		{
+			DE_UNREF(constCoords);
+			setUniform(gl, programID, "s.source", 0);
+		},
+		{
+			c.color.xyz() = c.texture2D(TEXTURE_BRICK, tcu::Vec2(0.5f, 0.5f)).swizzle(0,1,2);
+		});
+
+	UNIFORM_STRUCT_CASE(sampler_in_array_function_arg, "Sampler in struct as function arg", FLAG_USES_TEXTURES,
+		LineStream()
+		<< "${DECLARATIONS}"
+		<< ""
+		<< "struct S {"
+		<< "	sampler2D		source;"
+		<< "};"
+		<< ""
+		<< "mediump vec4 fun(S s[2]) {"
+		<< "	return texture2D(s[0].source, vec2(0.5));"
+		<< "}"
+		<< ""
+		<< "uniform S s[2];"
+		<< "void main (void)"
+		<< "{"
+		<< "	${DST} = fun(s);"
+		<< "	${ASSIGN_POS}"
+		<< "}",
+		{
+			DE_UNREF(constCoords);
+			setUniform(gl, programID, "s[0].source", 0);
+		},
+		{
+			c.color.xyz() = c.texture2D(TEXTURE_BRICK, tcu::Vec2(0.5f, 0.5f)).swizzle(0,1,2);
+		});
+
 	UNIFORM_STRUCT_CASE(equal, "Struct equality", 0,
 		LineStream()
 		<< "${DECLARATIONS}"
diff --git a/modules/gles2/functional/es2fTextureSizeTests.cpp b/modules/gles2/functional/es2fTextureSizeTests.cpp
index 67a57f1..9e202ca 100644
--- a/modules/gles2/functional/es2fTextureSizeTests.cpp
+++ b/modules/gles2/functional/es2fTextureSizeTests.cpp
@@ -122,7 +122,10 @@
 	RandomViewport			viewport		(m_renderCtx.getRenderTarget(), 128, 128, deStringHash(getName()));
 	tcu::Surface			renderedFrame	(viewport.width, viewport.height);
 	tcu::Surface			referenceFrame	(viewport.width, viewport.height);
-	tcu::RGBA				threshold		= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
+	const tcu::IVec4		texBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
+	const tcu::PixelFormat&	rtFmt			= m_renderCtx.getRenderTarget().getPixelFormat();
+	const tcu::PixelFormat	thresholdFormat(std::min(texBits[0], rtFmt.redBits), std::min(texBits[1], rtFmt.greenBits), std::min(texBits[2], rtFmt.blueBits), std::min(texBits[3], rtFmt.alphaBits));
+	tcu::RGBA				threshold		= thresholdFormat.getColorThreshold() + tcu::RGBA(7,7,7,7);
 	deUint32				wrapS			= GL_CLAMP_TO_EDGE;
 	deUint32				wrapT			= GL_CLAMP_TO_EDGE;
 	// Do not minify with GL_NEAREST. A large POT texture with a small POT render target will produce
@@ -267,7 +270,10 @@
 	RandomViewport			viewport		(m_renderCtx.getRenderTarget(), 128, 128, deStringHash(getName())+(deUint32)face);
 	tcu::Surface			renderedFrame	(viewport.width, viewport.height);
 	tcu::Surface			referenceFrame	(viewport.width, viewport.height);
-	tcu::RGBA				threshold		= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
+	const tcu::IVec4		texBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
+	const tcu::PixelFormat&	rtFmt			= m_renderCtx.getRenderTarget().getPixelFormat();
+	const tcu::PixelFormat	thresholdFormat(std::min(texBits[0], rtFmt.redBits), std::min(texBits[1], rtFmt.greenBits), std::min(texBits[2], rtFmt.blueBits), std::min(texBits[3], rtFmt.alphaBits));
+	tcu::RGBA				threshold		= thresholdFormat.getColorThreshold() + tcu::RGBA(7,7,7,7);
 	deUint32				wrapS			= GL_CLAMP_TO_EDGE;
 	deUint32				wrapT			= GL_CLAMP_TO_EDGE;
 	// Do not minify with GL_NEAREST. A large POT texture with a small POT render target will produce
diff --git a/modules/gles3/functional/es3fShaderIndexingTests.cpp b/modules/gles3/functional/es3fShaderIndexingTests.cpp
index d51181e..e61bdc7 100644
--- a/modules/gles3/functional/es3fShaderIndexingTests.cpp
+++ b/modules/gles3/functional/es3fShaderIndexingTests.cpp
@@ -22,6 +22,7 @@
  *//*--------------------------------------------------------------------*/
 
 #include "es3fShaderIndexingTests.hpp"
+#include "glsShaderLibrary.hpp"
 #include "glsShaderRenderCase.hpp"
 #include "gluShaderUtil.hpp"
 #include "tcuStringTemplate.hpp"
@@ -1131,6 +1132,13 @@
 			}
 		}
 	}
+
+	{
+		const std::vector<tcu::TestNode*> children = gls::ShaderLibrary(m_testCtx, m_context.getRenderContext(), m_context.getContextInfo()).loadShaderFile("shaders/indexing.test");
+
+		for (int i = 0; i < (int)children.size(); i++)
+			addChild(children[i]);
+	}
 }
 
 } // Functional
diff --git a/modules/gles3/functional/es3fTextureSizeTests.cpp b/modules/gles3/functional/es3fTextureSizeTests.cpp
index 09cfd5a..fa0bbc5 100644
--- a/modules/gles3/functional/es3fTextureSizeTests.cpp
+++ b/modules/gles3/functional/es3fTextureSizeTests.cpp
@@ -123,7 +123,10 @@
 	RandomViewport			viewport		(m_renderCtx.getRenderTarget(), 128, 128, deStringHash(getName()));
 	tcu::Surface			renderedFrame	(viewport.width, viewport.height);
 	tcu::Surface			referenceFrame	(viewport.width, viewport.height);
-	tcu::RGBA				threshold		= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
+	const tcu::IVec4		texBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
+	const tcu::PixelFormat&	rtFmt			= m_renderCtx.getRenderTarget().getPixelFormat();
+	const tcu::PixelFormat	thresholdFormat(std::min(texBits[0], rtFmt.redBits), std::min(texBits[1], rtFmt.greenBits), std::min(texBits[2], rtFmt.blueBits), std::min(texBits[3], rtFmt.alphaBits));
+	tcu::RGBA				threshold		= thresholdFormat.getColorThreshold() + tcu::RGBA(7,7,7,7);
 	deUint32				wrapS			= GL_CLAMP_TO_EDGE;
 	deUint32				wrapT			= GL_CLAMP_TO_EDGE;
 	// Do not minify with GL_NEAREST. A large POT texture with a small POT render target will produce
@@ -268,7 +271,10 @@
 	RandomViewport			viewport		(m_renderCtx.getRenderTarget(), 128, 128, deStringHash(getName())+(deUint32)face);
 	tcu::Surface			renderedFrame	(viewport.width, viewport.height);
 	tcu::Surface			referenceFrame	(viewport.width, viewport.height);
-	tcu::RGBA				threshold		= m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
+	const tcu::IVec4		texBits			= tcu::getTextureFormatBitDepth(glu::mapGLTransferFormat(m_format, m_dataType));
+	const tcu::PixelFormat&	rtFmt			= m_renderCtx.getRenderTarget().getPixelFormat();
+	const tcu::PixelFormat	thresholdFormat(std::min(texBits[0], rtFmt.redBits), std::min(texBits[1], rtFmt.greenBits), std::min(texBits[2], rtFmt.blueBits), std::min(texBits[3], rtFmt.alphaBits));
+	tcu::RGBA				threshold		= thresholdFormat.getColorThreshold() + tcu::RGBA(7,7,7,7);
 	deUint32				wrapS			= GL_CLAMP_TO_EDGE;
 	deUint32				wrapT			= GL_CLAMP_TO_EDGE;
 	// Do not minify with GL_NEAREST. A large POT texture with a small POT render target will produce
diff --git a/modules/glshared/glsBuiltinPrecisionTests.cpp b/modules/glshared/glsBuiltinPrecisionTests.cpp
index afe990b..34171f6 100644
--- a/modules/glshared/glsBuiltinPrecisionTests.cpp
+++ b/modules/glshared/glsBuiltinPrecisionTests.cpp
@@ -244,6 +244,13 @@
 	return Traits<T>::doContains(ival, value);
 }
 
+//! Returns true iff every element of `ival` contains corresponding element of `value` within the warning interval
+template <typename T>
+bool containsWarning(const typename Traits<T>::IVal& ival, const T& value)
+{
+	return Traits<T>::doContainsWarning(ival, value);
+}
+
 //! Print out an interval with the precision of `fmt`.
 template <typename T>
 void printIVal (const FloatFormat& fmt, const typename Traits<T>::IVal& ival, ostream& os)
@@ -313,6 +320,11 @@
 		return a.contains(double(value));
 	}
 
+	static bool			doContainsWarning(const Interval& a, T value)
+	{
+		return a.containsWarning(double(value));
+	}
+
 	static Interval		doConvert		(const FloatFormat& fmt, const IVal& ival)
 	{
 		return fmt.convert(ival);
@@ -422,6 +434,15 @@
 		return true;
 	}
 
+	static bool			doContainsWarning(const IVal& ival, const T& value)
+	{
+		for (int ndx = 0; ndx < T::SIZE; ++ndx)
+			if (!containsWarning(ival[ndx], value[ndx]))
+				return false;
+
+		return true;
+	}
+
 	static void			doPrintIVal		(const FloatFormat& fmt, const IVal ival, ostream& os)
 	{
 		os << "(";
@@ -492,11 +513,12 @@
 {
 	typedef		Void			IVal;
 
-	static Void	doMakeIVal		(const Void& value)						{ return value; }
-	static Void	doUnion			(const Void&, const Void&)				{ return Void(); }
-	static bool	doContains		(const Void&, Void)						{ return true; }
-	static Void	doRound			(const FloatFormat&, const Void& value)	{ return value; }
-	static Void	doConvert		(const FloatFormat&, const Void& value)	{ return value; }
+	static Void	doMakeIVal			(const Void& value)						{ return value; }
+	static Void	doUnion				(const Void&, const Void&)				{ return Void(); }
+	static bool	doContains			(const Void&, Void)						{ return true; }
+	static bool	doContainsWarning	(const Void&, Void)						{ return true; }
+	static Void	doRound				(const FloatFormat&, const Void& value)	{ return value; }
+	static Void	doConvert			(const FloatFormat&, const Void& value)	{ return value; }
 
 	static void	doPrintValue	(const FloatFormat&, const Void&, ostream& os)
 	{
@@ -1702,8 +1724,10 @@
 	{
 		const double	exact	= this->applyExact(arg0);
 		const double	prec	= this->precision(ctx, exact, arg0);
-
-		return exact + Interval(-prec, prec);
+		const double	wprec	= this->warningPrecision(ctx, exact, arg0);
+		Interval		ioutput	= exact + Interval(-prec, prec);
+		ioutput.warning(exact - wprec, exact + wprec);
+		return ioutput;
 	}
 
 	virtual double		applyExact		(double) const
@@ -1717,6 +1741,12 @@
 	}
 
 	virtual double		precision		(const EvalContext& ctx, double, double) const = 0;
+
+	virtual double	warningPrecision		(const EvalContext& ctx, double exact, double arg0) const
+	{
+		return precision(ctx, exact, arg0);
+	}
+
 };
 
 class CFloatFunc1 : public FloatFunc1
@@ -2142,6 +2172,21 @@
 
 		return 0;
 	}
+
+	// OpenGL API Issue #57 "Clarifying the required ULP precision for GLSL built-in log()". Agreed that
+	// implementations will be allowed 4 ULPs for HIGHP Log/Log2, but CTS should generate a quality warning.
+	double		warningPrecision(const EvalContext& ctx, double ret, double x) const
+	{
+		if (ctx.floatPrecision == glu::PRECISION_HIGHP && x > 0)
+		{
+			return (0.5 <= x && x <= 2.0) ? deLdExp(1.0, -21) : ctx.format.ulp(ret, 4.0);
+		}
+		else
+		{
+			return precision(ctx, ret, x);
+		}
+	}
+
 };
 
 class Log2	: public LogFunc		{ public: Log2	(void) : LogFunc("log2", deLog2) {} };
@@ -4608,7 +4653,10 @@
 	// shader output to the reference.
 	for (size_t valueNdx = 0; valueNdx < numValues; valueNdx++)
 	{
-		bool						result		= true;
+		bool						result = true;
+		bool						inExpectedRange;
+		bool						inWarningRange;
+		const char*					failStr = "Fail";
 		typename Traits<Out0>::IVal	reference0;
 		typename Traits<Out1>::IVal	reference1;
 
@@ -4628,15 +4676,39 @@
 		switch (outCount)
 		{
 			case 2:
-				reference1 = convert<Out1>(highpFmt, env.lookup(*variables.out1));
-				if (!m_status.check(contains(reference1, outputs.out1[valueNdx]),
-									"Shader output 1 is outside acceptable range"))
+				reference1      = convert<Out1>(highpFmt, env.lookup(*variables.out1));
+				inExpectedRange = contains(reference1, outputs.out1[valueNdx]);
+				inWarningRange  = containsWarning(reference1, outputs.out1[valueNdx]);
+				if (!inExpectedRange && inWarningRange)
+				{
+					m_status.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Shader output 1 has low-quality shader precision");
+					failStr = "QualityWarning";
 					result = false;
+				}
+				else if (!inExpectedRange)
+				{
+					m_status.addResult(QP_TEST_RESULT_FAIL, "Shader output 1 is outside acceptable range");
+					failStr = "Fail";
+					result = false;
+				}
+
 			case 1:
-				reference0 = convert<Out0>(highpFmt, env.lookup(*variables.out0));
-				if (!m_status.check(contains(reference0, outputs.out0[valueNdx]),
-									"Shader output 0 is outside acceptable range"))
+				reference0      = convert<Out0>(highpFmt, env.lookup(*variables.out0));
+				inExpectedRange = contains(reference0, outputs.out0[valueNdx]);
+				inWarningRange  = containsWarning(reference0, outputs.out0[valueNdx]);
+				if (!inExpectedRange && inWarningRange)
+				{
+					m_status.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Shader output 0 has low-quality shader precision");
+					failStr = "QualityWarning";
 					result = false;
+				}
+				else if (!inExpectedRange)
+				{
+					m_status.addResult(QP_TEST_RESULT_FAIL, "Shader output 0 is outside acceptable range");
+					failStr = "Fail";
+					result = false;
+				}
+
 			default: break;
 		}
 
@@ -4647,7 +4719,7 @@
 		{
 			MessageBuilder	builder	= log().message();
 
-			builder << (result ? "Passed" : "Failed") << " sample:\n";
+			builder << (result ? "Passed" : failStr) << " sample:\n";
 
 			if (inCount > 0)
 			{
@@ -4706,7 +4778,7 @@
 	}
 	else
 	{
-		log() << TestLog::Message << numErrors << "/" << numValues << " inputs failed."
+		log() << TestLog::Message << numErrors << "/" << numValues << " inputs failed or had quality warnings."
 			  << TestLog::EndMessage;
 	}
 }
diff --git a/scripts/egl/common.py b/scripts/egl/common.py
index 6e6d4e7..d5e1342 100644
--- a/scripts/egl/common.py
+++ b/scripts/egl/common.py
@@ -75,7 +75,11 @@
 	"EGL_EXT_gl_colorspace_display_p3",
 	"EGL_EXT_gl_colorspace_display_p3_linear",
 	"EGL_EXT_gl_colorspace_scrgb",
-	"EGL_EXT_gl_colorspace_scrgb_linear"
+	"EGL_EXT_gl_colorspace_scrgb_linear",
+	"EGL_EXT_surface_SMPTE2086_metadata",
+	"EGL_EXT_surface_CTA861_3_metadata",
+	"EGL_EXT_gl_colorspace_bt2020_linear",
+	"EGL_EXT_gl_colorspace_bt2020_pq"
 ]
 PROTECTS			= [
 	"KHRONOS_SUPPORT_INT64"