Merge Vulkan CTS 1.0.2.1 into AOSP

Change-Id: Ib0aaf12ec60902ebc31d00ad02291bd3d1cd7fae
diff --git a/Android.mk b/Android.mk
index ea13fd3..5618aa9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -270,6 +270,7 @@
 	modules/egl/teglCreateContextExtTests.cpp \
 	modules/egl/teglCreateContextTests.cpp \
 	modules/egl/teglCreateSurfaceTests.cpp \
+	modules/egl/teglGetFrameTimestampsTests.cpp \
 	modules/egl/teglGetProcAddressTests.cpp \
 	modules/egl/teglGLES1RenderUtil.cpp \
 	modules/egl/teglGLES2RenderUtil.cpp \
@@ -589,7 +590,10 @@
 	modules/gles31/functional/es31fNegativeShaderDirectiveTests.cpp \
 	modules/gles31/functional/es31fNegativeShaderFunctionTests.cpp \
 	modules/gles31/functional/es31fNegativeShaderImageLoadStoreTests.cpp \
+	modules/gles31/functional/es31fNegativeShaderStorageTests.cpp \
 	modules/gles31/functional/es31fNegativeStateApiTests.cpp \
+	modules/gles31/functional/es31fNegativeSSBOBlockTests.cpp \
+	modules/gles31/functional/es31fNegativeTessellationTests.cpp \
 	modules/gles31/functional/es31fNegativeTestShared.cpp \
 	modules/gles31/functional/es31fNegativeTextureApiTests.cpp \
 	modules/gles31/functional/es31fNegativeVertexArrayApiTests.cpp \
@@ -637,6 +641,7 @@
 	modules/gles31/functional/es31fVertexAttributeBindingTests.cpp \
 	modules/gles31/functional/es31fCopyImageTests.cpp \
 	modules/gles31/functional/es31fDrawBuffersIndexedTests.cpp \
+	modules/gles31/functional/es31fSRGBDecodeTests.cpp \
 	modules/gles31/stress/es31sDrawTests.cpp \
 	modules/gles31/stress/es31sStressTests.cpp \
 	modules/gles31/stress/es31sTessellationGeometryInteractionTests.cpp \
@@ -980,6 +985,7 @@
 	-DDEQP_GLES2_RUNTIME_LOAD=1 \
 	-DQP_SUPPORT_PNG=1 \
 	-Wconversion \
+	-fwrapv \
 	-Wno-sign-conversion
 
 LOCAL_SHARED_LIBRARIES := \
@@ -999,7 +1005,7 @@
 	$(deqp_compile_flags)
 
 LOCAL_SDK_VERSION := 22
-LOCAL_CPPFLAGS += -Wno-non-virtual-dtor -fwrapv
+LOCAL_CPPFLAGS += -Wno-non-virtual-dtor -Wno-delete-non-virtual-dtor
 LOCAL_NDK_STL_VARIANT := gnustl_static
 LOCAL_RTTI_FLAG := -frtti -fexceptions
 LOCAL_MULTILIB := both
diff --git a/android/cts/lmp-mr1/gles31-master.txt b/android/cts/lmp-mr1/gles31-master.txt
index 2baaad3..596e3d6 100644
--- a/android/cts/lmp-mr1/gles31-master.txt
+++ b/android/cts/lmp-mr1/gles31-master.txt
@@ -13000,7 +13000,6 @@
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
@@ -13016,7 +13015,6 @@
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
diff --git a/android/cts/lmp-mr1/src/es31-lmp-mr1.txt b/android/cts/lmp-mr1/src/es31-lmp-mr1.txt
index 96833a1..632afa9 100644
--- a/android/cts/lmp-mr1/src/es31-lmp-mr1.txt
+++ b/android/cts/lmp-mr1/src/es31-lmp-mr1.txt
@@ -13000,7 +13000,6 @@
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
@@ -13016,7 +13015,6 @@
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
diff --git a/android/cts/lmp/gles31-master.txt b/android/cts/lmp/gles31-master.txt
index d79324b..87fd6bc 100644
--- a/android/cts/lmp/gles31-master.txt
+++ b/android/cts/lmp/gles31-master.txt
@@ -12589,7 +12589,6 @@
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_explicit_location
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_array_element_type
@@ -12603,7 +12602,6 @@
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
diff --git a/android/cts/lmp/src/es31-lmp.txt b/android/cts/lmp/src/es31-lmp.txt
index 05e7d95..afe5c02 100644
--- a/android/cts/lmp/src/es31-lmp.txt
+++ b/android/cts/lmp/src/es31-lmp.txt
@@ -12589,7 +12589,6 @@
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_explicit_location
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_array_element_type
@@ -12603,7 +12602,6 @@
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
diff --git a/android/cts/master/egl-master.txt b/android/cts/master/egl-master.txt
index 74f28a9..ba0c55a 100644
--- a/android/cts/master/egl-master.txt
+++ b/android/cts/master/egl-master.txt
@@ -24,6 +24,7 @@
 dEQP-EGL.functional.create_context.rgba8888_depth_no_stencil
 dEQP-EGL.functional.create_context.rgba8888_depth_stencil
 dEQP-EGL.functional.create_context.other
+dEQP-EGL.functional.create_context.no_config
 dEQP-EGL.functional.query_context.simple.query_api
 dEQP-EGL.functional.query_context.get_current_context.rgb565_window
 dEQP-EGL.functional.query_context.get_current_context.rgb565_pixmap
@@ -413,6 +414,9 @@
 dEQP-EGL.functional.choose_config.random.surface_type
 dEQP-EGL.functional.choose_config.random.sample_buffers
 dEQP-EGL.functional.choose_config.random.all
+dEQP-EGL.functional.choose_config.color_component_type_ext.dont_care
+dEQP-EGL.functional.choose_config.color_component_type_ext.fixed
+dEQP-EGL.functional.choose_config.color_component_type_ext.float
 dEQP-EGL.functional.color_clears.single_context.gles1.rgb565_window
 dEQP-EGL.functional.color_clears.single_context.gles1.rgb565_pixmap
 dEQP-EGL.functional.color_clears.single_context.gles1.rgb565_pbuffer
@@ -2364,11 +2368,14 @@
 dEQP-EGL.functional.multithread.single_window_context
 dEQP-EGL.functional.multithread.pbuffer_single_window_context
 dEQP-EGL.functional.get_proc_address.extension.egl_android_blob_cache
+dEQP-EGL.functional.get_proc_address.extension.egl_android_create_native_client_buffer
 dEQP-EGL.functional.get_proc_address.extension.egl_android_native_fence_sync
+dEQP-EGL.functional.get_proc_address.extension.egl_android_presentation_time
 dEQP-EGL.functional.get_proc_address.extension.egl_angle_query_surface_pointer
 dEQP-EGL.functional.get_proc_address.extension.egl_ext_device_base
 dEQP-EGL.functional.get_proc_address.extension.egl_ext_device_enumeration
 dEQP-EGL.functional.get_proc_address.extension.egl_ext_device_query
+dEQP-EGL.functional.get_proc_address.extension.egl_ext_image_dma_buf_import_modifiers
 dEQP-EGL.functional.get_proc_address.extension.egl_ext_output_base
 dEQP-EGL.functional.get_proc_address.extension.egl_ext_platform_base
 dEQP-EGL.functional.get_proc_address.extension.egl_ext_stream_consumer_egloutput
@@ -2384,6 +2391,7 @@
 dEQP-EGL.functional.get_proc_address.extension.egl_khr_partial_update
 dEQP-EGL.functional.get_proc_address.extension.egl_khr_reusable_sync
 dEQP-EGL.functional.get_proc_address.extension.egl_khr_stream
+dEQP-EGL.functional.get_proc_address.extension.egl_khr_stream_attrib
 dEQP-EGL.functional.get_proc_address.extension.egl_khr_stream_consumer_gltexture
 dEQP-EGL.functional.get_proc_address.extension.egl_khr_stream_cross_process_fd
 dEQP-EGL.functional.get_proc_address.extension.egl_khr_stream_fifo
@@ -2398,6 +2406,7 @@
 dEQP-EGL.functional.get_proc_address.extension.egl_nv_post_sub_buffer
 dEQP-EGL.functional.get_proc_address.extension.egl_nv_stream_consumer_gltexture_yuv
 dEQP-EGL.functional.get_proc_address.extension.egl_nv_stream_metadata
+dEQP-EGL.functional.get_proc_address.extension.egl_nv_stream_reset
 dEQP-EGL.functional.get_proc_address.extension.egl_nv_stream_sync
 dEQP-EGL.functional.get_proc_address.extension.egl_nv_sync
 dEQP-EGL.functional.get_proc_address.extension.egl_nv_system_time
@@ -3540,3 +3549,24 @@
 dEQP-EGL.functional.mutable_render_buffer.querySurface
 dEQP-EGL.functional.mutable_render_buffer.negativeConfigBit
 dEQP-EGL.functional.mutable_render_buffer.basic
+dEQP-EGL.functional.get_frame_timestamps.rgb565_no_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb565_no_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb565_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb565_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb888_no_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb888_no_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb888_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgb888_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba4444_no_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba4444_no_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba4444_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba4444_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba5551_no_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba5551_no_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba5551_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba5551_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba8888_no_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba8888_no_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba8888_depth_no_stencil
+dEQP-EGL.functional.get_frame_timestamps.rgba8888_depth_stencil
+dEQP-EGL.functional.get_frame_timestamps.other
diff --git a/android/cts/master/gles31-master.txt b/android/cts/master/gles31-master.txt
index 8204cb8..b4f78d9 100644
--- a/android/cts/master/gles31-master.txt
+++ b/android/cts/master/gles31-master.txt
@@ -4089,12 +4089,17 @@
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.vertex_fragment_same_varying_name_2
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.invalid_vertex_index
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.input_non_array
+dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.output_non_array
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.input_array_size_mismatch
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.internal_array_size_mismatch
+dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.invalid_patch_in_usage
+dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.invalid_patch_out_usage
+dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.invalid_per_patch_qualifier_usage
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.per_patch_qualifier_mismatch_1
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.per_patch_qualifier_mismatch_2
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.input_block
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.input_block_non_array
+dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.output_block_non_array
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.input_block_array_size_mismatch
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.output_block
 dEQP-GLES31.functional.shaders.linkage.tessellation.varying.rules.output_block_array
@@ -4158,6 +4163,12 @@
 dEQP-GLES31.functional.shaders.linkage.tessellation.uniform.types.uvec3
 dEQP-GLES31.functional.shaders.linkage.tessellation.uniform.types.uvec4
 dEQP-GLES31.functional.shaders.linkage.tessellation.uniform.types.float_struct
+dEQP-GLES31.functional.shaders.linkage.tessellation.layout_declarations.rules.primitive_mode_mismatch
+dEQP-GLES31.functional.shaders.linkage.tessellation.layout_declarations.rules.spacing_mode_mismatch
+dEQP-GLES31.functional.shaders.linkage.tessellation.layout_declarations.rules.vertex_order_mismatch
+dEQP-GLES31.functional.shaders.linkage.tessellation.layout_declarations.rules.vertex_count_mismatch
+dEQP-GLES31.functional.shaders.linkage.tessellation.barriers.rules.invalid_barrier_usage_within_control_flow
+dEQP-GLES31.functional.shaders.linkage.tessellation.barriers.rules.invalid_barrier_usage_after_return
 dEQP-GLES31.functional.shaders.linkage.tessellation_geometry.varying.rules.type_mismatch
 dEQP-GLES31.functional.shaders.linkage.tessellation_geometry.varying.rules.different_precision
 dEQP-GLES31.functional.shaders.linkage.tessellation_geometry.varying.rules.no_output_declaration
@@ -15875,7 +15886,7 @@
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
+dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_different_struct_names
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
@@ -15897,7 +15908,7 @@
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_interpolation
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
+dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_struct_names
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
@@ -16758,11 +16769,23 @@
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.tessellation_shader
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.texture_buffer
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.texture_cube_map_array
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_directive.accessing_bounding_box_type
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.ssbo_block.ssbo_block_interface_matching_tests
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.ssbo_block.ssbo_using_shared_qualifier_tests
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.precise.precise_as_variable_name
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.precise.precise_as_function_name
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.precise.precise_as_function_argument
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.advanced_blend.blend_qualifier_mismatch
 dEQP-GLES31.functional.debug.negative_coverage.callbacks.advanced_blend.attachment_advanced_equation
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_storage.block_number_limits
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.shader_storage.max_combined_block_number_limit
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.single_tessellation_stage
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.invalid_primitive_mode
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.tessellation_not_active
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.invalid_program_state
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.get_programiv
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.invalid_program_queries
+dEQP-GLES31.functional.debug.negative_coverage.callbacks.tessellation.tessellation_control_invalid_vertex_count
 dEQP-GLES31.functional.debug.negative_coverage.log.buffer.bind_buffer
 dEQP-GLES31.functional.debug.negative_coverage.log.buffer.delete_buffers
 dEQP-GLES31.functional.debug.negative_coverage.log.buffer.gen_buffers
@@ -17204,11 +17227,23 @@
 dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.tessellation_shader
 dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.texture_buffer
 dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.texture_cube_map_array
+dEQP-GLES31.functional.debug.negative_coverage.log.shader_directive.accessing_bounding_box_type
+dEQP-GLES31.functional.debug.negative_coverage.log.ssbo_block.ssbo_block_interface_matching_tests
+dEQP-GLES31.functional.debug.negative_coverage.log.ssbo_block.ssbo_using_shared_qualifier_tests
 dEQP-GLES31.functional.debug.negative_coverage.log.precise.precise_as_variable_name
 dEQP-GLES31.functional.debug.negative_coverage.log.precise.precise_as_function_name
 dEQP-GLES31.functional.debug.negative_coverage.log.precise.precise_as_function_argument
 dEQP-GLES31.functional.debug.negative_coverage.log.advanced_blend.blend_qualifier_mismatch
 dEQP-GLES31.functional.debug.negative_coverage.log.advanced_blend.attachment_advanced_equation
+dEQP-GLES31.functional.debug.negative_coverage.log.shader_storage.block_number_limits
+dEQP-GLES31.functional.debug.negative_coverage.log.shader_storage.max_combined_block_number_limit
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.single_tessellation_stage
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.invalid_primitive_mode
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.tessellation_not_active
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.invalid_program_state
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.get_programiv
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.invalid_program_queries
+dEQP-GLES31.functional.debug.negative_coverage.log.tessellation.tessellation_control_invalid_vertex_count
 dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.bind_buffer
 dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.delete_buffers
 dEQP-GLES31.functional.debug.negative_coverage.get_error.buffer.gen_buffers
@@ -17648,11 +17683,23 @@
 dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.tessellation_shader
 dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.texture_buffer
 dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.texture_cube_map_array
+dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_directive.accessing_bounding_box_type
+dEQP-GLES31.functional.debug.negative_coverage.get_error.ssbo_block.ssbo_block_interface_matching_tests
+dEQP-GLES31.functional.debug.negative_coverage.get_error.ssbo_block.ssbo_using_shared_qualifier_tests
 dEQP-GLES31.functional.debug.negative_coverage.get_error.precise.precise_as_variable_name
 dEQP-GLES31.functional.debug.negative_coverage.get_error.precise.precise_as_function_name
 dEQP-GLES31.functional.debug.negative_coverage.get_error.precise.precise_as_function_argument
 dEQP-GLES31.functional.debug.negative_coverage.get_error.advanced_blend.blend_qualifier_mismatch
 dEQP-GLES31.functional.debug.negative_coverage.get_error.advanced_blend.attachment_advanced_equation
+dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_storage.block_number_limits
+dEQP-GLES31.functional.debug.negative_coverage.get_error.shader_storage.max_combined_block_number_limit
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.single_tessellation_stage
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.invalid_primitive_mode
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.tessellation_not_active
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.invalid_program_state
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.get_programiv
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.invalid_program_queries
+dEQP-GLES31.functional.debug.negative_coverage.get_error.tessellation.tessellation_control_invalid_vertex_count
 dEQP-GLES31.functional.debug.externally_generated.application_messages
 dEQP-GLES31.functional.debug.externally_generated.third_party_messages
 dEQP-GLES31.functional.debug.externally_generated.push_pop_stack
@@ -22658,62 +22705,110 @@
 dEQP-GLES31.functional.layout_binding.image.image3d.fragment_binding_max_array
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.vertex_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_evaluation_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.vertex_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_evaluation_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.vertex_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_evaluation_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.vertex_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.tess_evaluation_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.binding_contradictory
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler2d.binding_contradictory_array
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.vertex_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_evaluation_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.vertex_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_evaluation_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.vertex_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_evaluation_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.vertex_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.tess_evaluation_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.binding_contradictory
 dEQP-GLES31.functional.layout_binding.negative.sampler.sampler3d.binding_contradictory_array
 dEQP-GLES31.functional.layout_binding.negative.ubo.vertex_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.ubo.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_evaluation_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.ubo.vertex_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.ubo.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_evaluation_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.ubo.vertex_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.ubo.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_evaluation_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.ubo.vertex_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.ubo.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.ubo.tess_evaluation_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.ubo.binding_contradictory
 dEQP-GLES31.functional.layout_binding.negative.ubo.binding_contradictory_array
 dEQP-GLES31.functional.layout_binding.negative.ssbo.vertex_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.ssbo.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_evaluation_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.ssbo.vertex_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.ssbo.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_evaluation_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.ssbo.vertex_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.ssbo.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_evaluation_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.ssbo.vertex_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.ssbo.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.ssbo.tess_evaluation_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.ssbo.binding_contradictory
 dEQP-GLES31.functional.layout_binding.negative.ssbo.binding_contradictory_array
 dEQP-GLES31.functional.layout_binding.negative.image.image2d.vertex_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.image.image2d.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_evaluation_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.image.image2d.vertex_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.image.image2d.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_evaluation_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.image.image2d.vertex_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.image.image2d.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_evaluation_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.image.image2d.vertex_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.image.image2d.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.image.image2d.tess_evaluation_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.image.image2d.binding_contradictory
 dEQP-GLES31.functional.layout_binding.negative.image.image2d.binding_contradictory_array
 dEQP-GLES31.functional.layout_binding.negative.image.image3d.vertex_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.image.image3d.fragment_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_control_binding_over_max
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_evaluation_binding_over_max
 dEQP-GLES31.functional.layout_binding.negative.image.image3d.vertex_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.image.image3d.fragment_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_control_binding_neg
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_evaluation_binding_neg
 dEQP-GLES31.functional.layout_binding.negative.image.image3d.vertex_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.image.image3d.fragment_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_control_binding_over_max_array
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_evaluation_binding_over_max_array
 dEQP-GLES31.functional.layout_binding.negative.image.image3d.vertex_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.image.image3d.fragment_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_control_binding_neg_array
+dEQP-GLES31.functional.layout_binding.negative.image.image3d.tess_evaluation_binding_neg_array
 dEQP-GLES31.functional.layout_binding.negative.image.image3d.binding_contradictory
 dEQP-GLES31.functional.layout_binding.negative.image.image3d.binding_contradictory_array
 dEQP-GLES31.functional.primitive_bounding_box.state_query.initial_value
@@ -22761,18 +22856,39 @@
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_primitive.vertex_tessellation_fragment.fbo
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_primitive.vertex_tessellation_geometry_fragment.default_framebuffer
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_primitive.vertex_tessellation_geometry_fragment.fbo
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.fbo_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.fbo_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.fbo_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.fbo_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_smaller
@@ -22820,18 +22936,39 @@
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_primitive.vertex_tessellation_fragment.fbo
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_primitive.vertex_tessellation_geometry_fragment.default_framebuffer
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_primitive.vertex_tessellation_geometry_fragment.fbo
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.fbo_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.fbo_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.fbo_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.fbo_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.fbo_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.fbo_bbox_smaller
@@ -35413,3 +35550,17 @@
 dEQP-GLES31.functional.draw_buffers_indexed.random.max_implementation_draw_buffers.18
 dEQP-GLES31.functional.draw_buffers_indexed.random.max_implementation_draw_buffers.19
 dEQP-GLES31.functional.default_vertex_array_object.vertex_attrib_divisor
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.skipped
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.enabled
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.texel_fetch
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.conversion_gpu
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.toggled
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.multiple_textures
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.srgba8.using_sampler
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.skipped
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.enabled
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.texel_fetch
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.conversion_gpu
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.toggled
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.multiple_textures
+dEQP-GLES31.functional.srgb_texture_decode.skip_decode.sr8.using_sampler
diff --git a/android/cts/master/gles31-multisample.txt b/android/cts/master/gles31-multisample.txt
index d78f3f6..721e97b 100644
--- a/android/cts/master/gles31-multisample.txt
+++ b/android/cts/master/gles31-multisample.txt
@@ -134,6 +134,24 @@
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
@@ -152,6 +170,24 @@
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
diff --git a/android/cts/master/gles31-rotate-landscape.txt b/android/cts/master/gles31-rotate-landscape.txt
index 42f000f..c98268f 100644
--- a/android/cts/master/gles31-rotate-landscape.txt
+++ b/android/cts/master/gles31-rotate-landscape.txt
@@ -47,6 +47,24 @@
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
@@ -65,6 +83,24 @@
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
diff --git a/android/cts/master/gles31-rotate-portrait.txt b/android/cts/master/gles31-rotate-portrait.txt
index 42f000f..c98268f 100644
--- a/android/cts/master/gles31-rotate-portrait.txt
+++ b/android/cts/master/gles31-rotate-portrait.txt
@@ -47,6 +47,24 @@
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
@@ -65,6 +83,24 @@
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
diff --git a/android/cts/master/gles31-rotate-reverse-landscape.txt b/android/cts/master/gles31-rotate-reverse-landscape.txt
index 42f000f..c98268f 100644
--- a/android/cts/master/gles31-rotate-reverse-landscape.txt
+++ b/android/cts/master/gles31-rotate-reverse-landscape.txt
@@ -47,6 +47,24 @@
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
@@ -65,6 +83,24 @@
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
diff --git a/android/cts/master/gles31-rotate-reverse-portrait.txt b/android/cts/master/gles31-rotate-reverse-portrait.txt
index 42f000f..c98268f 100644
--- a/android/cts/master/gles31-rotate-reverse-portrait.txt
+++ b/android/cts/master/gles31-rotate-reverse-portrait.txt
@@ -47,6 +47,24 @@
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.triangles.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
@@ -65,6 +83,24 @@
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.points.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_fragment.default_framebuffer_bbox_smaller
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_equal
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_larger
+dEQP-GLES31.functional.primitive_bounding_box.wide_lines.tessellation_set_per_draw.vertex_tessellation_geometry_fragment.default_framebuffer_bbox_smaller
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_equal
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_larger
 dEQP-GLES31.functional.primitive_bounding_box.wide_points.global_state.vertex_fragment.default_framebuffer_bbox_smaller
diff --git a/android/cts/master/src/gles31-hw-issues.txt b/android/cts/master/src/gles31-hw-issues.txt
index 9473ba4..5d24d03 100644
--- a/android/cts/master/src/gles31-hw-issues.txt
+++ b/android/cts/master/src/gles31-hw-issues.txt
@@ -66,15 +66,6 @@
 dEQP-GLES31.functional.shaders.builtin_functions.precision.cos.mediump_*
 dEQP-GLES31.functional.shaders.builtin_functions.precision.tan.mediump_*
 
-# Bug 22713865
-dEQP-GLES31.functional.primitive_bounding_box.*lines*default_framebuffer_bbox*
-dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_equal
-dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_larger
-dEQP-GLES31.functional.primitive_bounding_box.lines.global_state.vertex_geometry_fragment.fbo_bbox_smaller
-dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_equal
-dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_larger
-dEQP-GLES31.functional.primitive_bounding_box.wide_lines.global_state.vertex_geometry_fragment.fbo_bbox_smaller
-
 # Bug 23288315
 dEQP-GLES31.functional.draw_indirect.compute_interop.large.drawelements_separate_grid_1000x1000_drawcount_1
 dEQP-GLES31.functional.draw_indirect.compute_interop.large.drawelements_separate_grid_1200x1200_drawcount_1
diff --git a/android/cts/mnc/gles31-master.txt b/android/cts/mnc/gles31-master.txt
index b2602dc..904caca 100644
--- a/android/cts/mnc/gles31-master.txt
+++ b/android/cts/mnc/gles31-master.txt
@@ -15174,7 +15174,6 @@
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
@@ -15196,7 +15195,6 @@
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_interpolation
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
diff --git a/android/cts/mnc/src/gles31-master.txt b/android/cts/mnc/src/gles31-master.txt
index b2602dc..904caca 100644
--- a/android/cts/mnc/src/gles31-master.txt
+++ b/android/cts/mnc/src/gles31-master.txt
@@ -15174,7 +15174,6 @@
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
@@ -15196,7 +15195,6 @@
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_interpolation
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
diff --git a/android/cts/nyc/gles31-master.txt b/android/cts/nyc/gles31-master.txt
index 4e6fdba..6b1aef0 100644
--- a/android/cts/nyc/gles31-master.txt
+++ b/android/cts/nyc/gles31-master.txt
@@ -15875,7 +15875,6 @@
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
@@ -15897,7 +15896,6 @@
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_interpolation
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
diff --git a/android/cts/nyc/src/gles31-master.txt b/android/cts/nyc/src/gles31-master.txt
index 4e6fdba..6b1aef0 100644
--- a/android/cts/nyc/src/gles31-master.txt
+++ b/android/cts/nyc/src/gles31-master.txt
@@ -15875,7 +15875,6 @@
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_1
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_2
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_implicit_explicit_location_3
-dEQP-GLES31.functional.separate_shader.validation.varying.match_different_struct_names
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.varying.mismatch_struct_member_precision
@@ -15897,7 +15896,6 @@
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_precision
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_different_member_interpolation
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_array_size
-dEQP-GLES31.functional.separate_shader.validation.io_blocks.match_different_member_struct_names
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_name
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_type
 dEQP-GLES31.functional.separate_shader.validation.io_blocks.mismatch_member_struct_member_precision
diff --git a/android/cts/runner/src/com/drawelements/deqp/runner/DeqpTestRunner.java b/android/cts/runner/src/com/drawelements/deqp/runner/DeqpTestRunner.java
index cbcec16..465d2da 100644
--- a/android/cts/runner/src/com/drawelements/deqp/runner/DeqpTestRunner.java
+++ b/android/cts/runner/src/com/drawelements/deqp/runner/DeqpTestRunner.java
@@ -2116,6 +2116,7 @@
         destination.mExcludeFilters = new ArrayList<>(source.mExcludeFilters);
         destination.mAbi = source.mAbi;
         destination.mLogData = source.mLogData;
+        destination.mCollectTestsOnly = source.mCollectTestsOnly;
     }
 
     /**
diff --git a/android/scripts/build.py b/android/scripts/build.py
index cfee003..a1cc086 100644
--- a/android/scripts/build.py
+++ b/android/scripts/build.py
@@ -24,7 +24,9 @@
 import re
 import sys
 import shutil
+import string
 import argparse
+import time
 
 import common
 
@@ -188,6 +190,51 @@
 		print "%-30s : %s" % (entry[0], entry[1])
 	print " "
 
+# Return NDK version as [<major>,<minor>] or None if cannot be figured out.
+def getNdkVersion (path):
+	if path == None:
+		return None
+
+	propFilePath = os.path.join(path, "source.properties")
+	try:
+		with open(propFilePath) as propFile:
+			for line in propFile:
+				keyValue = map(lambda x: string.strip(x), line.split("="))
+				if keyValue[0] == "Pkg.Revision":
+					versionParts = keyValue[1].split(".")
+					return tuple(map(int, versionParts[0:2]))
+	except:
+		print("Could not read source prop file '%s'" % propFilePath)
+
+	return None
+
+def checkConfig ():
+	HOST_OS_TO_DOWNLOAD_STRING = {
+			"linux-x86_64"		: "linux-x86_64",
+			"windows"			: "windows-x86",
+			"windows-x86_64"	: "windows-x86_64"
+		}
+
+	version = getNdkVersion(common.ANDROID_NDK_PATH)
+	# Note: NDK currently maintains compatibility between minor
+	# versions. Error out only on major version mismatch.
+	if version == None or version[0] != common.ANDROID_NDK_VERSION[0]:
+		print("**** WARNING! Deqp requires NDK version %s" % common.ANDROID_NDK_VERSION_STRING)
+		print("**** NDK Path %s does not appear to have that version." % common.ANDROID_NDK_PATH)
+
+		# Download hint will use the version encored in common.py, not
+		# the latest minor version available
+		versionString = common.ANDROID_NDK_VERSION_STRING
+		if common.ANDROID_NDK_HOST_OS in HOST_OS_TO_DOWNLOAD_STRING:
+			osString = HOST_OS_TO_DOWNLOAD_STRING[common.ANDROID_NDK_HOST_OS]
+			print("**** Please install from https://dl.google.com/android/repository/android-ndk-%s-%s.zip" % (versionString, osString))
+		else:
+			print("**** Please download version", versionString, "from https://developer.android.com/ndk/downloads/index.html")
+
+		return False
+
+	return True
+
 if __name__ == "__main__":
 	nativeBuildTypes = ['Release', 'Debug', 'MinSizeRel', 'RelWithAsserts', 'RelWithDebInfo']
 	androidBuildTypes = ['debug', 'release']
@@ -199,10 +246,15 @@
 	parser.add_argument('--dump-config', dest='dumpConfig', action='store_true', help="Print out all configurations variables")
 	parser.add_argument('--java-api', dest='javaApi', default=common.ANDROID_JAVA_API, help="Set the API signature for the java build.")
 	parser.add_argument('-p', '--parallel-build', dest='parallelBuild', action="store_true", help="Build native libraries in parallel.")
+	parser.add_argument('--skip-config-check', dest='skipConfigCheck', action="store_true", default=False, help="Skips config check. Warranty void.")
 
 	args = parser.parse_args()
 
 	if args.dumpConfig:
 		dumpConfig()
 
+	if not args.skipConfigCheck and not checkConfig():
+		print "Config check failed, exit"
+		exit(-1)
+
 	build(buildRoot=os.path.abspath(args.buildRoot), androidBuildType=args.androidBuildType, nativeBuildType=args.nativeBuildType, javaApi=args.javaApi, doParallelBuild=args.parallelBuild)
diff --git a/android/scripts/common.py b/android/scripts/common.py
index 16b5276..a158367 100644
--- a/android/scripts/common.py
+++ b/android/scripts/common.py
@@ -110,7 +110,7 @@
 	if retcode != 0:
 		raise Exception("Failed to execute '%s', got %d" % (str(args), retcode))
 
-def execArgsInDirectory (args, cwd, linePrefix=""):
+def execArgsInDirectory (args, cwd, linePrefix="", failOnNonZeroExit=True):
 
 	def readApplyPrefixAndPrint (source, prefix, sink):
 		while True:
@@ -125,7 +125,7 @@
 	stdoutJob.start()
 	stderrJob.start()
 	retcode = process.wait()
-	if retcode != 0:
+	if failOnNonZeroExit and retcode != 0:
 		raise Exception("Failed to execute '%s', got %d" % (str(args), retcode))
 
 def serialApply(f, argsList):
@@ -173,7 +173,7 @@
 	if proc.returncode != 0:
 		raise Exception("adb devices -l failed, got %d" % proc.returncode)
 
-	ptrn = re.compile(r'^([a-zA-Z0-9:]+)\s+.*product:([^\s]+)\s+model:([^\s]+)\s+device:([^\s]+)')
+	ptrn = re.compile(r'^([a-zA-Z0-9\.:]+)\s+.*product:([^\s]+)\s+model:([^\s]+)\s+device:([^\s]+)')
 	devices = []
 	for line in stdout.splitlines()[1:]:
 		if len(line.strip()) == 0:
@@ -240,10 +240,16 @@
 ANDROID_JAVA_API		= "android-22"
 NATIVE_LIB_NAME			= "libdeqp.so"
 
+def makeNdkVersionString (version):
+	minorVersionString = (chr(ord('a') + version[1]) if version[1] > 0 else "")
+	return "r%d%s" % (version[0], minorVersionString)
+
+ANDROID_NDK_VERSION			= (11,0)
+ANDROID_NDK_VERSION_STRING	= makeNdkVersionString(ANDROID_NDK_VERSION)
 def selectNDKPath ():
 	candidates =  [
-		os.path.expanduser("~/android-ndk-r11"),
-		"C:/android/android-ndk-r11",
+		os.path.expanduser("~/android-ndk-" + ANDROID_NDK_VERSION_STRING),
+		"C:/android/android-ndk-" + ANDROID_NDK_VERSION_STRING,
 		os.environ.get("ANDROID_NDK_PATH", None), # If not defined, return None
 	]
 
diff --git a/android/scripts/install.py b/android/scripts/install.py
index 6c9ff0f..5545cbb 100644
--- a/android/scripts/install.py
+++ b/android/scripts/install.py
@@ -33,7 +33,7 @@
 	common.execArgsInDirectory([common.ADB_BIN] + extraArgs + [
 			'uninstall',
 			'com.drawelements.deqp'
-		], buildRoot, printPrefix)
+		], buildRoot, printPrefix, failOnNonZeroExit=False)
 	print printPrefix + "Remove complete\n",
 
 	print printPrefix + "Installing dEQP Package from %s...\n" %(buildRoot),
diff --git a/data/gles31/shaders/linkage_tessellation.test b/data/gles31/shaders/linkage_tessellation.test
index b26dd82..bdb3dc8 100644
--- a/data/gles31/shaders/linkage_tessellation.test
+++ b/data/gles31/shaders/linkage_tessellation.test
@@ -854,6 +854,61 @@
 			""
 		end
 
+		case output_non_array
+			version 310 es
+			desc "Tessellation control output out not an array"
+			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+			expect compile_or_link_fail
+			values
+			{
+				input float in0 = 1.0;
+				output float out0 = 1.0;
+			}
+			vertex ""
+				#version 310 es
+				${VERTEX_DECLARATIONS}
+				out mediump float tc_in;
+				void main()
+				{
+					tc_in = in0;
+					${VERTEX_OUTPUT}
+				}
+			""
+			tessellation_control ""
+				#version 310 es
+				${TESSELLATION_CONTROL_DECLARATIONS}
+				in mediump float tc_in[];
+				out mediump float tc_out; // not an array
+				void main()
+				{
+					tc_out = tc_in[gl_InvocationID];
+					${TESSELLATION_CONTROL_OUTPUT}
+				}
+			""
+			tessellation_evaluation ""
+				#version 310 es
+				${TESSELLATION_EVALUATION_DECLARATIONS}
+				in mediump float tc_out[];
+				out mediump float te_out;
+				void main()
+				{
+					te_out = tc_out[2];
+					${TESSELLATION_EVALUATION_OUTPUT}
+				}
+			""
+			fragment ""
+				#version 310 es
+				precision mediump float;
+				${FRAGMENT_DECLARATIONS}
+				in mediump float te_out;
+				void main()
+				{
+					out0 = te_out;
+					${FRAGMENT_OUTPUT}
+				}
+			""
+		end
+
 		case input_array_size_mismatch
 			version 310 es
 			desc "Tessellation control input array size is not gl_MaxPatchVertices"
@@ -964,6 +1019,133 @@
 			""
 		end
 
+		case invalid_patch_in_usage
+			version 310 es
+			desc "Invalid use of the patch_in qualifier in a non-tessellation shader"
+			expect compile_or_link_fail
+			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+			values
+			{
+				input float in0 = 1.0;
+				output float out0 = 1.0;
+			}
+			vertex ""
+				#version 310 es
+				${VERTEX_DECLARATIONS}
+				out mediump float frag_in;
+				out mediump float var;
+				void main()
+				{
+					frag_in = in0;
+					var = 2.0;
+					${VERTEX_OUTPUT}
+				}
+			""
+			fragment ""
+				#version 310 es
+				precision mediump float;
+				${FRAGMENT_DECLARATIONS}
+				patch in mediump float var; // invalid use of patch_in
+				in mediump float frag_in;
+				void main()
+				{
+					out0 = frag_in * var;
+					${FRAGMENT_OUTPUT}
+				}
+			""
+		end
+
+		case invalid_patch_out_usage
+			version 310 es
+			desc "Invalid use of the patch_out qualifier in a non-tessellation shader"
+			expect compile_or_link_fail
+			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+			values
+			{
+				input float in0 = 1.0;
+				output float out0 = 1.0;
+			}
+			vertex ""
+				#version 310 es
+				${VERTEX_DECLARATIONS}
+				out mediump float frag_in;
+				patch out mediump float var;
+				void main()
+				{
+					frag_in = in0;
+					var = 2.0;
+					${VERTEX_OUTPUT}
+				}
+			""
+			fragment ""
+				#version 310 es
+				precision mediump float;
+				${FRAGMENT_DECLARATIONS}
+				in mediump float var; // invalid use of patch_out
+				in mediump float frag_in;
+				void main()
+				{
+					out0 = frag_in * var;
+					${FRAGMENT_OUTPUT}
+				}
+			""
+		end
+
+		case invalid_per_patch_qualifier_usage
+			version 310 es
+			desc "Invalid use of per-patch qualifier on input variable in tessellation control shader"
+			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+			expect compile_or_link_fail
+			values
+			{
+				input float in0 = 1.0;
+				output float out0 = 1.0;
+			}
+			vertex ""
+				#version 310 es
+				${VERTEX_DECLARATIONS}
+				out mediump float tc_in;
+				void main()
+				{
+					tc_in = in0;
+					${VERTEX_OUTPUT}
+				}
+			""
+			tessellation_control ""
+				#version 310 es
+				${TESSELLATION_CONTROL_DECLARATIONS}
+				patch in mediump float tc_in; // patch in not allowed in TCS
+				patch out mediump float tc_out;
+				void main()
+				{
+					tc_out = tc_in;
+					${TESSELLATION_CONTROL_OUTPUT}
+				}
+			""
+			tessellation_evaluation ""
+				#version 310 es
+				${TESSELLATION_EVALUATION_DECLARATIONS}
+				patch in mediump float tc_out;
+				out mediump float te_out;
+				void main()
+				{
+					te_out = tc_out;
+					${TESSELLATION_EVALUATION_OUTPUT}
+				}
+			""
+			fragment ""
+				#version 310 es
+				precision mediump float;
+				${FRAGMENT_DECLARATIONS}
+				in mediump float te_out;
+				void main()
+				{
+					out0 = te_out;
+					${FRAGMENT_OUTPUT}
+				}
+			""
+		end
+
 		case per_patch_qualifier_mismatch_1
 			version 310 es
 			desc "Tessellation control output is per-patch qualified, evaluation input is not"
@@ -1133,7 +1315,7 @@
 
 		case input_block_non_array
 			version 310 es
-			desc "Tessellation control shader input block with explicit array"
+			desc "Tessellation control shader input block without explicit array"
 			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
 			require extension { "GL_OES_shader_io_blocks" | "GL_EXT_shader_io_blocks" } in { vertex }
 			expect compile_or_link_fail
@@ -1189,6 +1371,64 @@
 			""
 		end
 
+		case output_block_non_array
+			version 310 es
+			desc "Tessellation control shader output block without explicit array"
+			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+			require extension { "GL_OES_shader_io_blocks" | "GL_EXT_shader_io_blocks" } in { vertex }
+			expect compile_or_link_fail
+			values { output float out0 = 1.0; }
+			vertex ""
+				#version 310 es
+				${VERTEX_DECLARATIONS}
+				out mediump float tc_in;
+				void main()
+				{
+					tc_in = 1.0;
+					${VERTEX_OUTPUT}
+				}
+			""
+			tessellation_control ""
+				#version 310 es
+				${TESSELLATION_CONTROL_DECLARATIONS}
+				in mediump float tc_in[];
+				out IOBlockName
+				{
+					mediump float var;
+				} outputInstanceName; // not an array
+				void main()
+				{
+					outputInstanceName.var = tc_in[gl_InvocationID];
+					${TESSELLATION_CONTROL_OUTPUT}
+				}
+			""
+			tessellation_evaluation ""
+				#version 310 es
+				${TESSELLATION_EVALUATION_DECLARATIONS}
+				in IOBlockName
+				{
+					mediump float var;
+				} outputInstanceName[];
+				out mediump float te_out;
+				void main()
+				{
+					te_out = outputInstanceName[2].var;
+					${TESSELLATION_EVALUATION_OUTPUT}
+				}
+			""
+			fragment ""
+				#version 310 es
+				precision mediump float;
+				${FRAGMENT_DECLARATIONS}
+				in mediump float te_out;
+				void main()
+				{
+					out0 = te_out;
+					${FRAGMENT_OUTPUT}
+				}
+			""
+		end
+
 		case input_block_array_size_mismatch
 			version 310 es
 			desc "Tessellation control shader input block array, size not gl_MaxPatchVertices"
@@ -2151,3 +2391,355 @@
 
 	import "linkage_tessellation_uniform_types.test"
 end
+
+group layout_declarations "Layout linkage"
+	group rules "Rules"
+
+		case primitive_mode_mismatch
+			version 310 es
+			desc "Tessellation evaluation shader primitive mode mismatch"
+			expect compile_or_link_fail
+			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+			values
+			{
+				input float in0 = 1.0;
+				output float out0 = 1.0;
+			}
+			vertex ""
+				#version 310 es
+				${VERTEX_DECLARATIONS}
+				out mediump float tc_in;
+				void main()
+				{
+					tc_in = in0;
+					${VERTEX_OUTPUT}
+				}
+			""
+			tessellation_control ""
+				#version 310 es
+				${TESSELLATION_CONTROL_DECLARATIONS}
+				in mediump float tc_in[];
+				out mediump float tc_out[];
+				void main()
+				{
+					tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+					${TESSELLATION_CONTROL_OUTPUT}
+				}
+			""
+			tessellation_evaluation ""
+				#version 310 es
+				layout (triangles) in;
+				layout (isolines) in;
+				in mediump float tc_out[];
+				out mediump float te_out;
+				void main()
+				{
+					te_out = tc_out[2];
+					${TESSELLATION_EVALUATION_OUTPUT}
+				}
+			""
+			fragment ""
+				#version 310 es
+				precision mediump float;
+				${FRAGMENT_DECLARATIONS}
+				in mediump float te_out;
+				void main()
+				{
+					out0 = te_out;
+					${FRAGMENT_OUTPUT}
+				}
+			""
+		end
+
+		case spacing_mode_mismatch
+			version 310 es
+			desc "Tessellation evaluation shader spacing mode mismatch"
+			expect compile_or_link_fail
+			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+			values
+			{
+				input float in0 = 1.0;
+				output float out0 = 1.0;
+			}
+			vertex ""
+				#version 310 es
+				${VERTEX_DECLARATIONS}
+				out mediump float tc_in;
+				void main()
+				{
+					tc_in = in0;
+					${VERTEX_OUTPUT}
+				}
+			""
+			tessellation_control ""
+				#version 310 es
+				${TESSELLATION_CONTROL_DECLARATIONS}
+				in mediump float tc_in[];
+				out mediump float tc_out[];
+				void main()
+				{
+					tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+					${TESSELLATION_CONTROL_OUTPUT}
+				}
+			""
+			tessellation_evaluation ""
+				#version 310 es
+				layout (triangles, equal_spacing) in;
+				layout (triangles, fractional_odd_spacing) in;
+				in mediump float tc_out[];
+				out mediump float te_out;
+				void main()
+				{
+					te_out = tc_out[2];
+					${TESSELLATION_EVALUATION_OUTPUT}
+				}
+			""
+			fragment ""
+				#version 310 es
+				precision mediump float;
+				${FRAGMENT_DECLARATIONS}
+				in mediump float te_out;
+				void main()
+				{
+					out0 = te_out;
+					${FRAGMENT_OUTPUT}
+				}
+			""
+		end
+
+		case vertex_order_mismatch
+			version 310 es
+			desc "Tessellation evaluation shader vertex order mismatch"
+			expect compile_or_link_fail
+			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+			values
+			{
+				input float in0 = 1.0;
+				output float out0 = 1.0;
+			}
+			vertex ""
+				#version 310 es
+				${VERTEX_DECLARATIONS}
+				out mediump float tc_in;
+				void main()
+				{
+					tc_in = in0;
+					${VERTEX_OUTPUT}
+				}
+			""
+			tessellation_control ""
+				#version 310 es
+				${TESSELLATION_CONTROL_DECLARATIONS}
+				in mediump float tc_in[];
+				out mediump float tc_out[];
+				void main()
+				{
+					tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+					${TESSELLATION_CONTROL_OUTPUT}
+				}
+			""
+			tessellation_evaluation ""
+				#version 310 es
+				layout (triangles, cw) in;
+				layout (triangles, ccw) in;
+				    in mediump float tc_out[];
+				out mediump float te_out;
+				void main()
+				{
+					te_out = tc_out[2];
+					${TESSELLATION_EVALUATION_OUTPUT}
+				}
+			""
+			fragment ""
+				#version 310 es
+				precision mediump float;
+				${FRAGMENT_DECLARATIONS}
+				in mediump float te_out;
+				void main()
+				{
+					out0 = te_out;
+					${FRAGMENT_OUTPUT}
+				}
+			""
+		end
+
+		case vertex_count_mismatch
+			version 310 es
+			desc "Tessellation control shader vertex count mismatch"
+			expect compile_or_link_fail
+			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+			values
+			{
+				input float in0 = 1.0;
+				output float out0 = 1.0;
+			}
+			vertex ""
+				#version 310 es
+				${VERTEX_DECLARATIONS}
+				out mediump float tc_in;
+				void main()
+				{
+					tc_in = in0;
+					${VERTEX_OUTPUT}
+				}
+			""
+			tessellation_control ""
+				#version 310 es
+				layout (vertices=3) out;
+				layout (vertices=4) out;
+				in mediump float tc_in[];
+				out mediump float tc_out[];
+				void main()
+				{
+					tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+					${TESSELLATION_CONTROL_OUTPUT}
+				}
+			""
+			tessellation_evaluation ""
+				#version 310 es
+				${TESSELLATION_EVALUATION_DECLARATIONS}
+				in mediump float tc_out[];
+				out mediump float te_out;
+				void main()
+				{
+					te_out = tc_out[2];
+					${TESSELLATION_EVALUATION_OUTPUT}
+				}
+			""
+			fragment ""
+				#version 310 es
+				precision mediump float;
+				${FRAGMENT_DECLARATIONS}
+				in mediump float te_out;
+				void main()
+				{
+					out0 = te_out;
+					${FRAGMENT_OUTPUT}
+				}
+			""
+		end
+	end
+end
+
+group barriers "Barriers"
+	group rules "Rules"
+
+		case invalid_barrier_usage_within_control_flow
+			version 310 es
+			desc "Tessellation control shader invalid barrier usage within control flow statement"
+			expect compile_or_link_fail
+			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+			values
+			{
+				input float in0 = 1.0;
+				output float out0 = 1.0;
+			}
+			vertex ""
+				#version 310 es
+				${VERTEX_DECLARATIONS}
+				out mediump float tc_in;
+				void main()
+				{
+					tc_in = in0;
+					${VERTEX_OUTPUT}
+				}
+			""
+			tessellation_control ""
+				#version 310 es
+				${TESSELLATION_CONTROL_DECLARATIONS}
+				in mediump float tc_in[];
+				out mediump float tc_out[];
+
+				void main()
+				{
+					if (gl_InvocationID == 0)
+						barrier(); // error: within control flow
+
+					tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+					${TESSELLATION_CONTROL_OUTPUT}
+				}
+			""
+			tessellation_evaluation ""
+				#version 310 es
+				${TESSELLATION_EVALUATION_DECLARATIONS}
+				in mediump float tc_out[];
+				out mediump float te_out;
+				void main()
+				{
+					te_out = tc_out[2];
+					${TESSELLATION_EVALUATION_OUTPUT}
+				}
+			""
+			fragment ""
+				#version 310 es
+				precision mediump float;
+				${FRAGMENT_DECLARATIONS}
+				in mediump float te_out;
+				void main()
+				{
+					out0 = te_out;
+					${FRAGMENT_OUTPUT}
+				}
+			""
+		end
+
+		case invalid_barrier_usage_after_return
+			version 310 es
+			desc "Tessellation control shader invalid barrier usage after main() returns"
+			expect compile_or_link_fail
+			require extension { "GL_OES_tessellation_shader" | "GL_EXT_tessellation_shader" } in { tessellation_control, tessellation_evaluation }
+			values
+			{
+				input float in0 = 1.0;
+				output float out0 = 1.0;
+			}
+			vertex ""
+				#version 310 es
+				${VERTEX_DECLARATIONS}
+				out mediump float tc_in;
+				void main()
+				{
+					tc_in = in0;
+					${VERTEX_OUTPUT}
+				}
+			""
+			tessellation_control ""
+				#version 310 es
+				${TESSELLATION_CONTROL_DECLARATIONS}
+				in mediump float tc_in[];
+				out mediump float tc_out[];
+
+				void main()
+				{
+					tc_out[gl_InvocationID] = tc_in[gl_InvocationID];
+					${TESSELLATION_CONTROL_OUTPUT}
+
+					return;
+					barrier(); // error: barrier() after return
+				}
+			""
+			tessellation_evaluation ""
+				#version 310 es
+				${TESSELLATION_EVALUATION_DECLARATIONS}
+				in mediump float tc_out[];
+				out mediump float te_out;
+				void main()
+				{
+					te_out = tc_out[2];
+					${TESSELLATION_EVALUATION_OUTPUT}
+				}
+			""
+			fragment ""
+				#version 310 es
+				precision mediump float;
+				${FRAGMENT_DECLARATIONS}
+				in mediump float te_out;
+				void main()
+				{
+					out0 = te_out;
+					${FRAGMENT_OUTPUT}
+				}
+			""
+		end
+	end
+end
diff --git a/data/gles31/shaders/separate_shader_validation.test b/data/gles31/shaders/separate_shader_validation.test
index b868d9d..d16d6ee 100644
--- a/data/gles31/shaders/separate_shader_validation.test
+++ b/data/gles31/shaders/separate_shader_validation.test
@@ -327,10 +327,10 @@
 		end
 	end
 
-	case match_different_struct_names
+	case mismatch_different_struct_names
 		version 310 es
 		desc "Variable struct names different but otherwise identical"
-		expect pass
+		expect validation_fail
 
 		pipeline_program
 			active_stages {vertex}
@@ -1150,10 +1150,10 @@
 		end
 	end
 
-	case match_different_member_struct_names
+	case mismatch_different_member_struct_names
 		version 310 es
 		desc "IO-blocks match with structs with different names"
-		expect pass
+		expect validation_fail
 
 		pipeline_program
 			active_stages {vertex}
diff --git a/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp b/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
index b947cb1..17ade0c 100644
--- a/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
+++ b/external/vulkancts/modules/vulkan/api/vktApiFeatureInfo.cpp
@@ -2110,12 +2110,28 @@
 				results.check(imageType != VK_IMAGE_TYPE_3D || (properties.maxExtent.width >= 1 && properties.maxExtent.height >= 1 && properties.maxExtent.depth >= 1), "Invalid dimensions for 3D image");
 				results.check(imageType != VK_IMAGE_TYPE_3D || properties.maxArrayLayers == 1, "Invalid maxArrayLayers for 3D image");
 
-				if (tiling == VK_IMAGE_TILING_OPTIMAL && imageType == VK_IMAGE_TYPE_2D && !(curCreateFlags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
-					 ((supportedFeatures & (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) ||
-					 ((supportedFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) && deviceFeatures.shaderStorageImageMultisample)))
+				if (tiling == VK_IMAGE_TILING_OPTIMAL)
 				{
-					const VkSampleCountFlags	requiredSampleCounts	= getRequiredOptimalTilingSampleCounts(deviceLimits, format, curUsageFlags);
-					results.check((properties.sampleCounts & requiredSampleCounts) == requiredSampleCounts, "Required sample counts not supported");
+					// Vulkan API specification has changed since initial Android Nougat release.
+					// For NYC CTS we need to tolerate old behavior as well and issue compatibility
+					// warning instead.
+					//
+					// See spec issues 272, 282, 302, 445 and CTS issues 369, 440.
+					const bool	requiredByNewSpec	= (imageType == VK_IMAGE_TYPE_2D && !(curCreateFlags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) &&
+													  ((supportedFeatures & (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT)) ||
+													  ((supportedFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) && deviceFeatures.shaderStorageImageMultisample)));
+
+					if (requiredByNewSpec)
+					{
+						const VkSampleCountFlags	requiredSampleCounts	= getRequiredOptimalTilingSampleCounts(deviceLimits, format, curUsageFlags);
+
+						results.check((properties.sampleCounts & requiredSampleCounts) == requiredSampleCounts, "Required sample counts not supported");
+					}
+					else if (properties.sampleCounts != VK_SAMPLE_COUNT_1_BIT)
+					{
+						results.addResult(QP_TEST_RESULT_COMPATIBILITY_WARNING,
+									      "Implementation supports more sample counts than allowed by the spec");
+					}
 				}
 				else
 					results.check(properties.sampleCounts == VK_SAMPLE_COUNT_1_BIT, "sampleCounts != VK_SAMPLE_COUNT_1_BIT");
diff --git a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
index 3887f80..c610d0c 100644
--- a/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
+++ b/external/vulkancts/modules/vulkan/spirv_assembly/vktSpvAsmInstructionTests.cpp
@@ -2531,7 +2531,7 @@
 
 	for (size_t idx = 0; idx < expectedOutput->getNumBytes() / sizeof(float); ++idx)
 	{
-		if (!isnan(output_as_float[idx]))
+		if (!deFloatIsNaN(output_as_float[idx]))
 		{
 			return false;
 		}
diff --git a/framework/egl/egluCallLogWrapper.inl b/framework/egl/egluCallLogWrapper.inl
index 57041bd..ee49459 100644
--- a/framework/egl/egluCallLogWrapper.inl
+++ b/framework/egl/egluCallLogWrapper.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 
 eglw::EGLBoolean CallLogWrapper::eglBindAPI (eglw::EGLenum api)
diff --git a/framework/egl/egluCallLogWrapperApi.inl b/framework/egl/egluCallLogWrapperApi.inl
index 69be6e9..99df24b 100644
--- a/framework/egl/egluCallLogWrapperApi.inl
+++ b/framework/egl/egluCallLogWrapperApi.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 eglw::EGLBoolean								eglBindAPI							(eglw::EGLenum api);
 eglw::EGLBoolean								eglBindTexImage						(eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint buffer);
diff --git a/framework/egl/egluConfigFilter.cpp b/framework/egl/egluConfigFilter.cpp
index c6d06ad..bd1a5c7 100644
--- a/framework/egl/egluConfigFilter.cpp
+++ b/framework/egl/egluConfigFilter.cpp
@@ -25,6 +25,7 @@
 #include "egluUtil.hpp"
 #include "egluConfigInfo.hpp"
 #include "eglwEnums.hpp"
+#include "deSTLUtil.hpp"
 
 #include <algorithm>
 
@@ -55,19 +56,32 @@
 	if (m_type == TYPE_CONFIG_INFO)
 		return m_cfg.configInfo->getAttribute(attrib);
 	else
-		return getConfigAttribInt(*m_cfg.object.egl, m_cfg.object.display, m_cfg.object.config, attrib);
+	{
+		if (attrib == EGL_COLOR_COMPONENT_TYPE_EXT)
+		{
+			const std::vector<std::string>	extensions	= getDisplayExtensions(*m_cfg.object.egl, m_cfg.object.display);
+
+			if (de::contains(extensions.begin(), extensions.end(), "EGL_EXT_pixel_format_float"))
+				return getConfigAttribInt(*m_cfg.object.egl, m_cfg.object.display, m_cfg.object.config, attrib);
+			else
+				return EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
+		}
+		else
+			return getConfigAttribInt(*m_cfg.object.egl, m_cfg.object.display, m_cfg.object.config, attrib);
+	}
 }
 
-int			CandidateConfig::id				(void) const { return get(EGL_CONFIG_ID);					}
-int			CandidateConfig::redSize		(void) const { return get(EGL_RED_SIZE);					}
-int			CandidateConfig::greenSize		(void) const { return get(EGL_GREEN_SIZE);					}
-int			CandidateConfig::blueSize		(void) const { return get(EGL_BLUE_SIZE);					}
-int			CandidateConfig::alphaSize		(void) const { return get(EGL_ALPHA_SIZE);					}
-int			CandidateConfig::depthSize		(void) const { return get(EGL_DEPTH_SIZE);					}
-int			CandidateConfig::stencilSize	(void) const { return get(EGL_STENCIL_SIZE);				}
-int			CandidateConfig::samples		(void) const { return get(EGL_SAMPLES);						}
-deUint32	CandidateConfig::renderableType	(void) const { return (deUint32)get(EGL_RENDERABLE_TYPE);	}
-deUint32	CandidateConfig::surfaceType	(void) const { return (deUint32)get(EGL_SURFACE_TYPE);		}
+int			CandidateConfig::id					(void) const { return get(EGL_CONFIG_ID);							}
+int			CandidateConfig::redSize			(void) const { return get(EGL_RED_SIZE);							}
+int			CandidateConfig::greenSize			(void) const { return get(EGL_GREEN_SIZE);							}
+int			CandidateConfig::blueSize			(void) const { return get(EGL_BLUE_SIZE);							}
+int			CandidateConfig::alphaSize			(void) const { return get(EGL_ALPHA_SIZE);							}
+int			CandidateConfig::depthSize			(void) const { return get(EGL_DEPTH_SIZE);							}
+int			CandidateConfig::stencilSize		(void) const { return get(EGL_STENCIL_SIZE);						}
+int			CandidateConfig::samples			(void) const { return get(EGL_SAMPLES);								}
+deUint32	CandidateConfig::renderableType		(void) const { return (deUint32)get(EGL_RENDERABLE_TYPE);			}
+deUint32	CandidateConfig::surfaceType		(void) const { return (deUint32)get(EGL_SURFACE_TYPE);				}
+deUint32	CandidateConfig::colorComponentType	(void) const { return (deUint32)get(EGL_COLOR_COMPONENT_TYPE_EXT);	}
 
 FilterList& FilterList::operator<< (ConfigFilter filter)
 {
diff --git a/framework/egl/egluConfigFilter.hpp b/framework/egl/egluConfigFilter.hpp
index 2f316fe..baddad5 100644
--- a/framework/egl/egluConfigFilter.hpp
+++ b/framework/egl/egluConfigFilter.hpp
@@ -59,6 +59,7 @@
 
 	deUint32		renderableType		(void) const;
 	deUint32		surfaceType			(void) const;
+	deUint32		colorComponentType	(void) const;
 
 	tcu::RGBA		colorBits			(void) const { return tcu::RGBA(redSize(), greenSize(), blueSize(), alphaSize());	}
 
diff --git a/framework/egl/egluConfigInfo.cpp b/framework/egl/egluConfigInfo.cpp
index aed08f3..ab6081c 100644
--- a/framework/egl/egluConfigInfo.cpp
+++ b/framework/egl/egluConfigInfo.cpp
@@ -77,6 +77,9 @@
 		case EGL_YUV_CSC_STANDARD_EXT:		return yuvCscStandard;
 		case EGL_YUV_PLANE_BPP_EXT:			return yuvPlaneBpp;
 
+		// EGL_EXT_pixel_format_float
+		case EGL_COLOR_COMPONENT_TYPE_EXT:	return colorComponentType;
+
 		default:							TCU_THROW(InternalError, "Unknown attribute");
 	}
 }
@@ -132,6 +135,15 @@
 
 		EGLU_CHECK_MSG(egl, "Failed to query EGL_EXT_yuv_surface config attribs");
 	}
+
+	if (de::contains(extensions.begin(), extensions.end(), "EGL_EXT_pixel_format_float"))
+	{
+		egl.getConfigAttrib(display, config, EGL_COLOR_COMPONENT_TYPE_EXT,	(EGLint*)&dst->colorComponentType);
+
+		EGLU_CHECK_MSG(egl, "Failed to query EGL_EXT_pixel_format_float config attribs");
+	}
+	else
+		dst->colorComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT;
 }
 
 } // eglu
diff --git a/framework/egl/egluConfigInfo.hpp b/framework/egl/egluConfigInfo.hpp
index 356c50a..2c0ae24 100644
--- a/framework/egl/egluConfigInfo.hpp
+++ b/framework/egl/egluConfigInfo.hpp
@@ -81,6 +81,9 @@
 	deUint32		yuvCscStandard;
 	deInt32			yuvPlaneBpp;
 
+	// EGL_EXT_pixel_format_float
+	deUint32		colorComponentType;
+
 	ConfigInfo (void)
 		: bufferSize			(0)
 		, redSize				(0)
@@ -119,6 +122,7 @@
 		, yuvDepthRange			(EGL_NONE)
 		, yuvCscStandard		(EGL_NONE)
 		, yuvPlaneBpp			(EGL_YUV_PLANE_BPP_0_EXT)
+		, colorComponentType	(EGL_NONE)
 	{
 	}
 
diff --git a/framework/egl/egluStrUtil.inl b/framework/egl/egluStrUtil.inl
index 297a00c..2c563e5 100644
--- a/framework/egl/egluStrUtil.inl
+++ b/framework/egl/egluStrUtil.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 
 const char* getBooleanName (int value)
@@ -104,6 +104,7 @@
 		case EGL_TRANSPARENT_RED_VALUE:		return "EGL_TRANSPARENT_RED_VALUE";
 		case EGL_TRANSPARENT_GREEN_VALUE:	return "EGL_TRANSPARENT_GREEN_VALUE";
 		case EGL_TRANSPARENT_BLUE_VALUE:	return "EGL_TRANSPARENT_BLUE_VALUE";
+		case EGL_COLOR_COMPONENT_TYPE_EXT:	return "EGL_COLOR_COMPONENT_TYPE_EXT";
 		default:							return DE_NULL;
 	}
 }
@@ -159,6 +160,16 @@
 	}
 }
 
+const char* getColorComponentTypeName (int value)
+{
+	switch (value)
+	{
+		case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT:	return "EGL_COLOR_COMPONENT_TYPE_FIXED_EXT";
+		case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT:	return "EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT";
+		default:									return DE_NULL;
+	}
+}
+
 const char* getSurfaceTargetName (int value)
 {
 	switch (value)
diff --git a/framework/egl/egluStrUtilPrototypes.inl b/framework/egl/egluStrUtilPrototypes.inl
index fc2093f..839837f 100644
--- a/framework/egl/egluStrUtilPrototypes.inl
+++ b/framework/egl/egluStrUtilPrototypes.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 const char*							getBooleanName				(int value);
 const char*							getBoolDontCareName			(int value);
@@ -12,6 +12,7 @@
 const char*							getSurfaceAttribName		(int value);
 const char*							getYuvOrderName				(int value);
 const char*							getYuvPlaneBppName			(int value);
+const char*							getColorComponentTypeName	(int value);
 const char*							getSurfaceTargetName		(int value);
 const char*							getColorBufferTypeName		(int value);
 const char*							getConfigCaveatName			(int value);
@@ -34,6 +35,7 @@
 inline tcu::Format::Enum<int, 2>	getSurfaceAttribStr			(int value)		{ return tcu::Format::Enum<int, 2>(getSurfaceAttribName, value); }
 inline tcu::Format::Enum<int, 2>	getYuvOrderStr				(int value)		{ return tcu::Format::Enum<int, 2>(getYuvOrderName, value); }
 inline tcu::Format::Enum<int, 2>	getYuvPlaneBppStr			(int value)		{ return tcu::Format::Enum<int, 2>(getYuvPlaneBppName, value); }
+inline tcu::Format::Enum<int, 2>	getColorComponentTypeStr	(int value)		{ return tcu::Format::Enum<int, 2>(getColorComponentTypeName, value); }
 inline tcu::Format::Enum<int, 2>	getSurfaceTargetStr			(int value)		{ return tcu::Format::Enum<int, 2>(getSurfaceTargetName, value); }
 inline tcu::Format::Enum<int, 2>	getColorBufferTypeStr		(int value)		{ return tcu::Format::Enum<int, 2>(getColorBufferTypeName, value); }
 inline tcu::Format::Enum<int, 2>	getConfigCaveatStr			(int value)		{ return tcu::Format::Enum<int, 2>(getConfigCaveatName, value); }
diff --git a/framework/egl/wrapper/eglwEnums.inl b/framework/egl/wrapper/eglwEnums.inl
index bfa267d..edb58c5 100644
--- a/framework/egl/wrapper/eglwEnums.inl
+++ b/framework/egl/wrapper/eglwEnums.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 #define EGL_PBUFFER_BIT										0x0001
 #define EGL_PIXMAP_BIT										0x0002
@@ -264,3 +264,6 @@
 #define EGL_YUV_PLANE_BPP_0_EXT								0x331B
 #define EGL_YUV_PLANE_BPP_8_EXT								0x331C
 #define EGL_YUV_PLANE_BPP_10_EXT							0x331D
+#define EGL_COLOR_COMPONENT_TYPE_EXT						0x3339
+#define EGL_COLOR_COMPONENT_TYPE_FIXED_EXT					0x333A
+#define EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT					0x333B
diff --git a/framework/egl/wrapper/eglwFuncPtrLibraryDecl.inl b/framework/egl/wrapper/eglwFuncPtrLibraryDecl.inl
index 353b6b2..e7d1327 100644
--- a/framework/egl/wrapper/eglwFuncPtrLibraryDecl.inl
+++ b/framework/egl/wrapper/eglwFuncPtrLibraryDecl.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 EGLBoolean									bindAPI							(EGLenum api) const;
 EGLBoolean									bindTexImage					(EGLDisplay dpy, EGLSurface surface, EGLint buffer) const;
diff --git a/framework/egl/wrapper/eglwFuncPtrLibraryImpl.inl b/framework/egl/wrapper/eglwFuncPtrLibraryImpl.inl
index c1140a7..1678c71 100644
--- a/framework/egl/wrapper/eglwFuncPtrLibraryImpl.inl
+++ b/framework/egl/wrapper/eglwFuncPtrLibraryImpl.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 
 EGLBoolean FuncPtrLibrary::bindAPI (EGLenum api) const
diff --git a/framework/egl/wrapper/eglwFunctionTypes.inl b/framework/egl/wrapper/eglwFunctionTypes.inl
index b66bdfd..d57105e 100644
--- a/framework/egl/wrapper/eglwFunctionTypes.inl
+++ b/framework/egl/wrapper/eglwFunctionTypes.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 typedef EGLW_APICALL EGLBoolean									(EGLW_APIENTRY* eglBindAPIFunc)							(EGLenum api);
 typedef EGLW_APICALL EGLBoolean									(EGLW_APIENTRY* eglBindTexImageFunc)					(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
diff --git a/framework/egl/wrapper/eglwFunctions.inl b/framework/egl/wrapper/eglwFunctions.inl
index 3f0ce29..af0d1b2 100644
--- a/framework/egl/wrapper/eglwFunctions.inl
+++ b/framework/egl/wrapper/eglwFunctions.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 eglBindAPIFunc							bindAPI;
 eglBindTexImageFunc						bindTexImage;
diff --git a/framework/egl/wrapper/eglwInitCore.inl b/framework/egl/wrapper/eglwInitCore.inl
index b09f990..15f941d 100644
--- a/framework/egl/wrapper/eglwInitCore.inl
+++ b/framework/egl/wrapper/eglwInitCore.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 dst->bindAPI						= (eglBindAPIFunc)							loader->get("eglBindAPI");
 dst->bindTexImage					= (eglBindTexImageFunc)						loader->get("eglBindTexImage");
diff --git a/framework/egl/wrapper/eglwInitExtensions.inl b/framework/egl/wrapper/eglwInitExtensions.inl
index 7ea82e4..90d00a1 100644
--- a/framework/egl/wrapper/eglwInitExtensions.inl
+++ b/framework/egl/wrapper/eglwInitExtensions.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 dst->clientWaitSyncKHR				= (eglClientWaitSyncKHRFunc)				loader->get("eglClientWaitSyncKHR");
 dst->createImageKHR					= (eglCreateImageKHRFunc)					loader->get("eglCreateImageKHR");
diff --git a/framework/egl/wrapper/eglwLibrary.inl b/framework/egl/wrapper/eglwLibrary.inl
index a9a42c8..a3d617d 100644
--- a/framework/egl/wrapper/eglwLibrary.inl
+++ b/framework/egl/wrapper/eglwLibrary.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 virtual EGLBoolean									bindAPI							(EGLenum api) const																								= 0;
 virtual EGLBoolean									bindTexImage					(EGLDisplay dpy, EGLSurface surface, EGLint buffer) const														= 0;
diff --git a/framework/egl/wrapper/eglwStaticLibrary14.inl b/framework/egl/wrapper/eglwStaticLibrary14.inl
index d2d5ca0..22a2c5c 100644
--- a/framework/egl/wrapper/eglwStaticLibrary14.inl
+++ b/framework/egl/wrapper/eglwStaticLibrary14.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 	{ "eglBindAPI",							(deFunctionPtr)eglBindAPI },
 	{ "eglBindTexImage",					(deFunctionPtr)eglBindTexImage },
diff --git a/framework/egl/wrapper/eglwStaticLibrary15.inl b/framework/egl/wrapper/eglwStaticLibrary15.inl
index c9fafeb..a44c589 100644
--- a/framework/egl/wrapper/eglwStaticLibrary15.inl
+++ b/framework/egl/wrapper/eglwStaticLibrary15.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 	{ "eglBindAPI",							(deFunctionPtr)eglBindAPI },
 	{ "eglBindTexImage",					(deFunctionPtr)eglBindTexImage },
diff --git a/framework/platform/X11/tcuX11.cpp b/framework/platform/X11/tcuX11.cpp
index ee24d13..75f55c7 100644
--- a/framework/platform/X11/tcuX11.cpp
+++ b/framework/platform/X11/tcuX11.cpp
@@ -86,6 +86,20 @@
 	XCloseDisplay(m_display);
 }
 
+void XlibDisplay::processEvent (XEvent& event)
+{
+	switch (event.type)
+	{
+		case ClientMessage:
+			if ((unsigned)event.xclient.data.l[0] == m_deleteAtom)
+				m_eventState.setQuitFlag(true);
+			break;
+		// note: ConfigureNotify for window is handled in setDimensions()
+		default:
+			break;
+	}
+}
+
 void XlibDisplay::processEvents (void)
 {
 	XEvent	event;
@@ -93,10 +107,7 @@
 	while (XPending(m_display))
 	{
 		XNextEvent(m_display, &event);
-
-		// \todo [2010-10-27 pyry] Handle ConfigureNotify?
-		if (event.type == ClientMessage && (unsigned)event.xclient.data.l[0] == m_deleteAtom)
-			m_eventState.setQuitFlag(true);
+		processEvent(event);
 	}
 }
 
@@ -211,7 +222,7 @@
 
 	do
 	{
-		XNextEvent(dpy, &event);
+		XWindowEvent(dpy, m_window, ExposureMask | StructureNotifyMask, &event);
 	} while (event.type != eventType);
 
 	m_visible = visible;
@@ -244,8 +255,13 @@
 	for(;;)
 	{
 		XNextEvent(dpy, &myevent);
-		if (myevent.type == ConfigureNotify)
-			break;
+		if (myevent.type == ConfigureNotify) {
+			XConfigureEvent e = myevent.xconfigure;
+			if (e.width == width && e.height == height)
+				break;
+		}
+		else
+			m_display.processEvent(myevent);
 	}
 }
 
diff --git a/framework/platform/X11/tcuX11.hpp b/framework/platform/X11/tcuX11.hpp
index 02a731b..ac2fd02 100644
--- a/framework/platform/X11/tcuX11.hpp
+++ b/framework/platform/X11/tcuX11.hpp
@@ -109,6 +109,7 @@
 	::Visual*		getVisual		(VisualID visualID);
 	bool			getVisualInfo	(VisualID visualID, XVisualInfo& dst);
 	void			processEvents	(void);
+	void			processEvent	(XEvent& event);
 
 protected:
 	::Display*		m_display;
diff --git a/framework/platform/X11/tcuX11Platform.cpp b/framework/platform/X11/tcuX11Platform.cpp
index 830a463..74c161c 100644
--- a/framework/platform/X11/tcuX11Platform.cpp
+++ b/framework/platform/X11/tcuX11Platform.cpp
@@ -89,5 +89,13 @@
 
 tcu::Platform* createPlatform (void)
 {
+	// From man:XinitThreads(3):
+	//
+	//     The XInitThreads function initializes Xlib support for concurrent
+	//     threads.  This function must be the first Xlib function
+	//     a multi-threaded program calls, and it must complete before any other
+	//     Xlib call is made.
+	DE_CHECK_RUNTIME_ERR(XInitThreads() != 0);
+
 	return new tcu::x11::X11Platform();
 }
diff --git a/modules/egl/CMakeLists.txt b/modules/egl/CMakeLists.txt
index a191391..519f15c 100644
--- a/modules/egl/CMakeLists.txt
+++ b/modules/egl/CMakeLists.txt
@@ -21,6 +21,8 @@
 	teglConfigList.hpp
 	teglCreateContextTests.cpp
 	teglCreateContextTests.hpp
+	teglGetFrameTimestampsTests.cpp
+	teglGetFrameTimestampsTests.hpp
 	teglQueryContextTests.cpp
 	teglQueryContextTests.hpp
 	teglCreateSurfaceTests.cpp
diff --git a/modules/egl/teglChooseConfigReference.cpp b/modules/egl/teglChooseConfigReference.cpp
index 50a2769..aab0156 100644
--- a/modules/egl/teglChooseConfigReference.cpp
+++ b/modules/egl/teglChooseConfigReference.cpp
@@ -142,6 +142,17 @@
 		}
 	}
 
+	static int getColorComponentTypeRank (EGLenum compType)
+	{
+		switch (compType)
+		{
+			case EGL_COLOR_COMPONENT_TYPE_FIXED_EXT:	return 0;
+			case EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT:	return 1;
+			default:
+				TCU_THROW(TestError, (std::string("Unknown color component type: ") + eglu::getColorComponentTypeStr(compType).toString()).c_str());
+		}
+	}
+
 	typedef bool (*CompareFunc) (const SurfaceConfig& a, const SurfaceConfig& b);
 
 	static bool compareCaveat (const SurfaceConfig& a, const SurfaceConfig& b)
@@ -159,6 +170,11 @@
 		return getYuvOrderRank((EGLenum)a.m_info.yuvOrder) < getYuvOrderRank((EGLenum)b.m_info.yuvOrder);
 	}
 
+	static bool compareColorComponentType (const SurfaceConfig& a, const SurfaceConfig& b)
+	{
+		return getColorComponentTypeRank((EGLenum)a.m_info.colorComponentType) < getColorComponentTypeRank((EGLenum)b.m_info.colorComponentType);
+	}
+
 	static bool compareColorBufferBits (const SurfaceConfig& a, const SurfaceConfig& b, const tcu::BVec4& specifiedRGBColors, const tcu::BVec2& specifiedLuminanceColors, bool yuvPlaneBppSpecified)
 	{
 		DE_ASSERT(a.m_info.colorBufferType == b.m_info.colorBufferType);
@@ -229,6 +245,7 @@
 		{
 			SurfaceConfig::compareCaveat,
 			SurfaceConfig::compareColorBufferType,
+			SurfaceConfig::compareColorComponentType,
 			DE_NULL, // SurfaceConfig::compareColorBufferBits,
 			SurfaceConfig::compareAttributeSmaller<EGL_BUFFER_SIZE>,
 			SurfaceConfig::compareAttributeSmaller<EGL_SAMPLE_BUFFERS>,
@@ -307,6 +324,9 @@
 		rules[EGL_YUV_CSC_STANDARD_EXT]		= AttribRule(EGL_YUV_CSC_STANDARD_EXT,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
 		rules[EGL_YUV_PLANE_BPP_EXT]		= AttribRule(EGL_YUV_PLANE_BPP_EXT,			EGL_DONT_CARE,		CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
 
+		// EGL_EXT_pixel_format_float
+		rules[EGL_COLOR_COMPONENT_TYPE_EXT]	= AttribRule(EGL_COLOR_COMPONENT_TYPE_EXT,	EGL_COLOR_COMPONENT_TYPE_FIXED_EXT,		CRITERIA_EXACT,		SORTORDER_SPECIAL);	//	2
+
 		return rules;
 	}
 private:
diff --git a/modules/egl/teglChooseConfigTests.cpp b/modules/egl/teglChooseConfigTests.cpp
index 69fc87c..b42b333 100644
--- a/modules/egl/teglChooseConfigTests.cpp
+++ b/modules/egl/teglChooseConfigTests.cpp
@@ -30,6 +30,8 @@
 #include "eglwEnums.hpp"
 #include "deRandom.hpp"
 #include "deStringUtil.hpp"
+#include "deUniquePtr.hpp"
+#include "deSTLUtil.hpp"
 
 #include <vector>
 #include <algorithm>
@@ -469,6 +471,42 @@
 	int					m_iterNdx;
 };
 
+class ColorComponentTypeCase : public ChooseConfigCase
+{
+
+public:
+	ColorComponentTypeCase (EglTestContext& eglTestCtx, const char* name, EGLenum value)
+		: ChooseConfigCase	(eglTestCtx, name, "", true /* sorting order is validated */)
+		, m_value			(value)
+	{
+	}
+
+	TestCase::IterateResult iterate (void)
+	{
+		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+
+		{
+			const std::vector<std::string>	extensions	= eglu::getDisplayExtensions(m_eglTestCtx.getLibrary(), m_display);
+
+			if (!de::contains(extensions.begin(), extensions.end(), "EGL_EXT_pixel_format_float"))
+				TCU_THROW(NotSupportedError, "EGL_EXT_pixel_format_float is not supported");
+		}
+
+		{
+			std::vector<std::pair<EGLenum, EGLint> > attributes;
+
+			attributes.push_back(std::pair<EGLenum, EGLint>(EGL_COLOR_COMPONENT_TYPE_EXT, m_value));
+			fillDontCare(attributes);
+
+			executeTest(attributes, m_checkOrder);
+		}
+
+		return STOP;
+	}
+private:
+	const EGLenum	m_value;
+};
+
 ChooseConfigTests::ChooseConfigTests (EglTestContext& eglTestCtx)
 	: TestCaseGroup(eglTestCtx, "choose_config", "eglChooseConfig() tests")
 {
@@ -631,6 +669,17 @@
 		};
 		randomGroup->addChild(new ChooseConfigRandomCase(m_eglTestCtx, "all", "All attributes", toSet(allAttribs)));
 	}
+
+	// EGL_EXT_pixel_format_float
+	{
+		de::MovePtr<tcu::TestCaseGroup>	colorComponentTypeGroup	(new tcu::TestCaseGroup(m_testCtx, "color_component_type_ext", "EGL_EXT_pixel_format_float tests"));
+
+		colorComponentTypeGroup->addChild(new ColorComponentTypeCase(m_eglTestCtx, "dont_care",	EGL_DONT_CARE));
+		colorComponentTypeGroup->addChild(new ColorComponentTypeCase(m_eglTestCtx, "fixed",		EGL_COLOR_COMPONENT_TYPE_FIXED_EXT));
+		colorComponentTypeGroup->addChild(new ColorComponentTypeCase(m_eglTestCtx, "float",		EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT));
+
+		addChild(colorComponentTypeGroup.release());
+	}
 }
 
 } // egl
diff --git a/modules/egl/teglCreateContextTests.cpp b/modules/egl/teglCreateContextTests.cpp
index 81e0c38..b107d67 100644
--- a/modules/egl/teglCreateContextTests.cpp
+++ b/modules/egl/teglCreateContextTests.cpp
@@ -25,9 +25,11 @@
 #include "teglSimpleConfigCase.hpp"
 #include "egluStrUtil.hpp"
 #include "egluUtil.hpp"
+#include "egluUnique.hpp"
 #include "eglwLibrary.hpp"
 #include "eglwEnums.hpp"
 #include "tcuTestLog.hpp"
+#include "deSTLUtil.hpp"
 
 namespace deqp
 {
@@ -38,6 +40,25 @@
 using tcu::TestLog;
 using namespace eglw;
 
+static const EGLint s_es1Attrs[] = { EGL_CONTEXT_CLIENT_VERSION,	1, EGL_NONE };
+static const EGLint s_es2Attrs[] = { EGL_CONTEXT_CLIENT_VERSION,	2, EGL_NONE };
+static const EGLint s_es3Attrs[] = { EGL_CONTEXT_MAJOR_VERSION_KHR,	3, EGL_NONE };
+
+static const struct
+{
+	const char*		name;
+	EGLenum			api;
+	EGLint			apiBit;
+	const EGLint*	ctxAttrs;
+} s_apis[] =
+{
+	{ "OpenGL",			EGL_OPENGL_API,		EGL_OPENGL_BIT,			DE_NULL		},
+	{ "OpenGL ES 1",	EGL_OPENGL_ES_API,	EGL_OPENGL_ES_BIT,		s_es1Attrs	},
+	{ "OpenGL ES 2",	EGL_OPENGL_ES_API,	EGL_OPENGL_ES2_BIT,		s_es2Attrs	},
+	{ "OpenGL ES 3",	EGL_OPENGL_ES_API,	EGL_OPENGL_ES3_BIT_KHR,	s_es3Attrs	},
+	{ "OpenVG",			EGL_OPENVG_API,		EGL_OPENVG_BIT,			DE_NULL		}
+};
+
 class CreateContextCase : public SimpleConfigCase
 {
 public:
@@ -63,36 +84,17 @@
 	EGLint			id		= eglu::getConfigAttribInt(egl, display, config, EGL_CONFIG_ID);
 	EGLint			apiBits	= eglu::getConfigAttribInt(egl, display, config, EGL_RENDERABLE_TYPE);
 
-	static const EGLint es1Attrs[] = { EGL_CONTEXT_CLIENT_VERSION,		1, EGL_NONE };
-	static const EGLint es2Attrs[] = { EGL_CONTEXT_CLIENT_VERSION,		2, EGL_NONE };
-	static const EGLint es3Attrs[] = { EGL_CONTEXT_MAJOR_VERSION_KHR,	3, EGL_NONE };
-
-	static const struct
+	for (int apiNdx = 0; apiNdx < (int)DE_LENGTH_OF_ARRAY(s_apis); apiNdx++)
 	{
-		const char*		name;
-		EGLenum			api;
-		EGLint			apiBit;
-		const EGLint*	ctxAttrs;
-	} apis[] =
-	{
-		{ "OpenGL",			EGL_OPENGL_API,		EGL_OPENGL_BIT,			DE_NULL		},
-		{ "OpenGL ES 1",	EGL_OPENGL_ES_API,	EGL_OPENGL_ES_BIT,		es1Attrs	},
-		{ "OpenGL ES 2",	EGL_OPENGL_ES_API,	EGL_OPENGL_ES2_BIT,		es2Attrs	},
-		{ "OpenGL ES 3",	EGL_OPENGL_ES_API,	EGL_OPENGL_ES3_BIT_KHR,	es3Attrs	},
-		{ "OpenVG",			EGL_OPENVG_API,		EGL_OPENVG_BIT,			DE_NULL		}
-	};
-
-	for (int apiNdx = 0; apiNdx < (int)DE_LENGTH_OF_ARRAY(apis); apiNdx++)
-	{
-		if ((apiBits & apis[apiNdx].apiBit) == 0)
+		if ((apiBits & s_apis[apiNdx].apiBit) == 0)
 			continue; // Not supported API
 
-		log << TestLog::Message << "Creating " << apis[apiNdx].name << " context with config ID " << id << TestLog::EndMessage;
+		log << TestLog::Message << "Creating " << s_apis[apiNdx].name << " context with config ID " << id << TestLog::EndMessage;
 		EGLU_CHECK_MSG(egl, "init");
 
-		EGLU_CHECK_CALL(egl, bindAPI(apis[apiNdx].api));
+		EGLU_CHECK_CALL(egl, bindAPI(s_apis[apiNdx].api));
 
-		EGLContext	context = egl.createContext(display, config, EGL_NO_CONTEXT, apis[apiNdx].ctxAttrs);
+		EGLContext	context = egl.createContext(display, config, EGL_NO_CONTEXT, s_apis[apiNdx].ctxAttrs);
 		EGLenum		err		= egl.getError();
 
 		if (context == EGL_NO_CONTEXT || err != EGL_SUCCESS)
@@ -109,6 +111,57 @@
 	}
 }
 
+class CreateContextNoConfigCase : public TestCase
+{
+public:
+	CreateContextNoConfigCase (EglTestContext& eglTestCtx)
+		: TestCase(eglTestCtx, "no_config", "EGL_KHR_no_config_context")
+	{
+	}
+
+	IterateResult iterate (void)
+	{
+		const eglw::Library&		egl		= m_eglTestCtx.getLibrary();
+		const eglu::UniqueDisplay	display	(egl, eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay(), DE_NULL));
+		tcu::TestLog&				log		= m_testCtx.getLog();
+
+		if (!eglu::hasExtension(egl, *display, "EGL_KHR_no_config_context"))
+			TCU_THROW(NotSupportedError, "EGL_KHR_no_config_context is not supported");
+
+		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "pass");
+
+		for (int apiNdx = 0; apiNdx < (int)DE_LENGTH_OF_ARRAY(s_apis); apiNdx++)
+		{
+			const EGLenum	api		= s_apis[apiNdx].api;
+
+			if (egl.bindAPI(api) == EGL_FALSE)
+			{
+				TCU_CHECK(egl.getError() == EGL_BAD_PARAMETER);
+				log << TestLog::Message << "eglBindAPI(" << eglu::getAPIStr(api) << ") failed, skipping" << TestLog::EndMessage;
+				continue;
+			}
+
+			log << TestLog::Message << "Creating " << s_apis[apiNdx].name << " context" << TestLog::EndMessage;
+
+			const EGLContext	context = egl.createContext(*display, (EGLConfig)0, EGL_NO_CONTEXT, s_apis[apiNdx].ctxAttrs);
+			const EGLenum		err		= egl.getError();
+
+			if (context == EGL_NO_CONTEXT || err != EGL_SUCCESS)
+			{
+				log << TestLog::Message << "  Fail, context: " << tcu::toHex(context) << ", error: " << eglu::getErrorName(err) << TestLog::EndMessage;
+				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Failed to create context");
+			}
+			else
+			{
+				// Destroy
+				EGLU_CHECK_CALL(egl, destroyContext(*display, context));
+				log << TestLog::Message << "  Pass" << TestLog::EndMessage;
+			}
+		}
+
+		return STOP;
+	}
+};
 
 CreateContextTests::CreateContextTests (EglTestContext& eglTestCtx)
 	: TestCaseGroup(eglTestCtx, "create_context", "Basic eglCreateContext() tests")
@@ -126,6 +179,8 @@
 
 	for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
 		addChild(new CreateContextCase(m_eglTestCtx, i->getName(), i->getDescription(), *i));
+
+	addChild(new CreateContextNoConfigCase(m_eglTestCtx));
 }
 
 } // egl
diff --git a/modules/egl/teglGetFrameTimestampsTests.cpp b/modules/egl/teglGetFrameTimestampsTests.cpp
new file mode 100644
index 0000000..ba75bba
--- /dev/null
+++ b/modules/egl/teglGetFrameTimestampsTests.cpp
@@ -0,0 +1,757 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program EGL Module
+ * ---------------------------------------
+ *
+ * Copyright 2017 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 Test the EGL_ANDROID_get_frame_timestamps extension.
+ *//*--------------------------------------------------------------------*/
+
+#include "teglGetFrameTimestampsTests.hpp"
+
+#include "teglSimpleConfigCase.hpp"
+
+#include "egluNativeWindow.hpp"
+#include "egluUtil.hpp"
+#include "egluUnique.hpp"
+#include "eglwLibrary.hpp"
+#include "eglwEnums.hpp"
+
+#include "gluDefs.hpp"
+#include "glwEnums.hpp"
+#include "glwFunctions.hpp"
+
+#include "tcuResultCollector.hpp"
+#include "tcuTestLog.hpp"
+#include "tcuSurface.hpp"
+#include "tcuTexture.hpp"
+#include "tcuTextureUtil.hpp"
+#include "tcuImageCompare.hpp"
+#include "tcuVector.hpp"
+#include "tcuVectorUtil.hpp"
+
+#include "deClock.h"
+#include "deMath.h"
+#include "deUniquePtr.hpp"
+#include "deThread.hpp"
+
+#include <algorithm>
+#include <string>
+#include <vector>
+#include <sstream>
+
+// Tentative EGL header definitions for EGL_ANDROID_get_Frame_timestamps.
+// \todo [2017-01-25 brianderson] Remove once defined in the official headers.
+#define EGL_TIMESTAMPS_ANDROID 0x314D
+#define EGL_COMPOSITE_DEADLINE_ANDROID 0x314E
+#define EGL_COMPOSITE_INTERVAL_ANDROID 0x314F
+#define EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID 0x3150
+#define EGL_REQUESTED_PRESENT_TIME_ANDROID 0x3151
+#define EGL_RENDERING_COMPLETE_TIME_ANDROID 0x3152
+#define EGL_COMPOSITION_LATCH_TIME_ANDROID 0x3153
+#define EGL_FIRST_COMPOSITION_START_TIME_ANDROID 0x3154
+#define EGL_LAST_COMPOSITION_START_TIME_ANDROID 0x3155
+#define EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID 0x3156
+#define EGL_DISPLAY_PRESENT_TIME_ANDROID 0x3157
+#define EGL_DISPLAY_RETIRE_TIME_ANDROID 0x3158
+#define EGL_DEQUEUE_READY_TIME_ANDROID 0x3159
+#define EGL_READS_DONE_TIME_ANDROID 0x315A
+typedef deInt64 EGLnsecsANDROID;
+typedef deUint64 EGLuint64KHR;
+typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetNextFrameIdANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR *frameId);
+typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint numTimestamps, const eglw::EGLint *names, EGLnsecsANDROID *values);
+typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetCompositorTimingSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint name);
+typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampsANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, EGLuint64KHR frameId, eglw::EGLint numTimestamps, const eglw::EGLint *timestamps, EGLnsecsANDROID *values);
+typedef EGLW_APICALL eglw::EGLBoolean (EGLW_APIENTRY* eglGetFrameTimestampSupportedANDROIDFunc) (eglw::EGLDisplay dpy, eglw::EGLSurface surface, eglw::EGLint timestamp);
+
+#define CHECK_NAKED_EGL_CALL(EGLW, CALL)	do { CALL; eglu::checkError((EGLW).getError(), #CALL, __FILE__, __LINE__); } while (deGetFalse())
+
+namespace deqp
+{
+namespace egl
+{
+
+using tcu::TestLog;
+using std::string;
+using std::vector;
+using namespace eglw;
+
+namespace
+{
+
+// Careful: This has microsecond precision, which can cause timestamps to
+// appear non monotonic when compared to the nanosecond precision timestamps
+// we get from the eglGetFrameTimestamps extension.
+// Current test expectations only make sure microsecond precision timestamps
+// are less than the nanosecond precision timestamps, so this is okay.
+EGLnsecsANDROID getNanoseconds (void)
+{
+	return deGetMicroseconds() * 1000;
+}
+
+struct FrameTimes
+{
+	FrameTimes (void)
+		: frameId						(-1)
+		, swapBufferBeginNs				(-1)
+		, compositeDeadline				(-1)
+		, compositeInterval				(-1)
+		, compositeToPresentLatency		(-1)
+		, requestedPresent				(-1)
+		, latch							(-1)
+		, firstCompositionStart			(-1)
+		, lastCompositionStart			(-1)
+		, dequeueReady					(-1)
+		, renderingComplete				(-1)
+		, firstCompositionGpuFinished	(-1)
+		, displayPresent				(-1)
+		, displayRetire					(-1)
+		, readsDone						(-1)
+	{
+	}
+
+	EGLuint64KHR	frameId;
+
+	// Timestamps sampled by the test.
+	EGLnsecsANDROID	swapBufferBeginNs;
+
+	// Compositor info.
+	EGLnsecsANDROID	compositeDeadline;
+	EGLnsecsANDROID	compositeInterval;
+	EGLnsecsANDROID	compositeToPresentLatency;
+
+	// CPU Timeline.
+	EGLnsecsANDROID	requestedPresent;
+	EGLnsecsANDROID	latch;
+	EGLnsecsANDROID	firstCompositionStart;
+	EGLnsecsANDROID	lastCompositionStart;
+	EGLnsecsANDROID	dequeueReady;
+
+	// GPU Timeline.
+	EGLnsecsANDROID	renderingComplete;
+	EGLnsecsANDROID	firstCompositionGpuFinished;
+	EGLnsecsANDROID	displayPresent;
+	EGLnsecsANDROID	displayRetire;
+	EGLnsecsANDROID	readsDone;
+};
+
+bool timestampExists (EGLnsecsANDROID timestamp)
+{
+	return timestamp > 0;
+}
+
+void verifySingleFrame (const FrameTimes& frameTimes, tcu::ResultCollector& result, bool verifyReadsDone)
+{
+	// Verify CPU timeline is monotonic.
+	result.check(frameTimes.swapBufferBeginNs < frameTimes.latch, "Buffer latched before it was swapped.");
+	result.check(frameTimes.latch < frameTimes.firstCompositionStart, "Buffer composited before it was latched.");
+	result.check(frameTimes.firstCompositionStart <= frameTimes.lastCompositionStart, "First composition start after last composition start.");
+	result.check(frameTimes.lastCompositionStart < frameTimes.dequeueReady, "Buffer composited after it was ready to be dequeued.");
+
+	// Verify GPU timeline is monotonic.
+	if (timestampExists(frameTimes.firstCompositionGpuFinished))
+		result.check(frameTimes.renderingComplete < frameTimes.firstCompositionGpuFinished, "Buffer rendering completed after compositor GPU work finished.");
+
+	if (timestampExists(frameTimes.displayPresent))
+		result.check(frameTimes.renderingComplete < frameTimes.displayPresent, "Buffer displayed before rendering completed.");
+
+	if (timestampExists(frameTimes.firstCompositionGpuFinished) && timestampExists(frameTimes.displayPresent))
+		result.check(frameTimes.firstCompositionGpuFinished < frameTimes.displayPresent, "Buffer displayed before compositor GPU work completed");
+
+	if (timestampExists(frameTimes.displayRetire))
+		result.check(frameTimes.renderingComplete < frameTimes.displayRetire, "Buffer retired before rendering completed.");
+
+	if (timestampExists(frameTimes.firstCompositionGpuFinished) && timestampExists(frameTimes.displayRetire))
+		result.check(frameTimes.firstCompositionGpuFinished < frameTimes.displayRetire, "Buffer retired before compositor GPU work completed.");
+
+	// Drivers may maintain shadow copies of the buffer, so the readsDone time
+	// of the real buffer may be earlier than apparent dependencies. We can only
+	// be sure that the readsDone time must be after the renderingComplete time.
+	if (verifyReadsDone)
+		result.check(frameTimes.renderingComplete < frameTimes.readsDone, "Buffer rendering completed after reads completed.");
+
+	// Verify CPU/GPU dependencies
+	result.check(frameTimes.renderingComplete < frameTimes.latch, "Buffer latched before rendering completed.");
+	if (timestampExists(frameTimes.firstCompositionGpuFinished))
+		result.check(frameTimes.firstCompositionStart < frameTimes.firstCompositionGpuFinished, "Composition CPU work started after GPU work finished.");
+
+	if (timestampExists(frameTimes.displayPresent))
+		result.check(frameTimes.firstCompositionStart < frameTimes.displayPresent, "Buffer displayed before it was composited.");
+
+	if (timestampExists(frameTimes.displayRetire))
+		result.check(frameTimes.lastCompositionStart < frameTimes.displayRetire, "Buffer retired before final composition.");
+
+	// One of Present or retire must exist.
+	result.check(timestampExists(frameTimes.displayPresent) != timestampExists(frameTimes.displayRetire), "Either present or retire must exist.");
+}
+
+void verifyNeighboringFrames (const FrameTimes& frame1, const FrameTimes& frame2, tcu::ResultCollector& result, bool verifyReadsDone)
+{
+	// CPU timeline.
+	result.check(frame1.swapBufferBeginNs < frame2.swapBufferBeginNs, "Swap begin times not monotonic.");
+	result.check(frame1.latch < frame2.latch, "Latch times not monotonic.");
+	result.check(frame1.lastCompositionStart < frame2.latch, "Old buffer composited after new buffer latched.");
+	result.check(frame1.lastCompositionStart < frame2.firstCompositionStart, "Composition times overlap.");
+	result.check(frame1.dequeueReady < frame2.dequeueReady, "Dequeue ready times not monotonic.");
+
+	// GPU timeline.
+	result.check(frame1.renderingComplete < frame2.renderingComplete, "Rendering complete times not monotonic.");
+
+	if (timestampExists(frame1.firstCompositionGpuFinished) && timestampExists(frame2.firstCompositionGpuFinished))
+		result.check(frame1.firstCompositionGpuFinished < frame2.firstCompositionGpuFinished, "Composition GPU work complete times not monotonic.");
+
+	if (timestampExists(frame1.displayPresent) && timestampExists(frame2.displayPresent))
+		result.check(frame1.displayPresent < frame2.displayPresent, "Display present times not monotonic.");
+
+	if (timestampExists(frame1.displayRetire) && timestampExists(frame2.displayRetire))
+		result.check(frame1.displayRetire < frame2.displayRetire, "Display retire times not monotonic.");
+
+	if (verifyReadsDone && timestampExists(frame1.readsDone) && timestampExists(frame2.readsDone))
+		result.check(frame1.readsDone < frame2.readsDone, "Reads done times not monotonic.");
+}
+
+EGLContext createGLES2Context (const Library& egl, EGLDisplay display, EGLConfig config)
+{
+	EGLContext		context = EGL_NO_CONTEXT;
+	const EGLint	attribList[] =
+	{
+		EGL_CONTEXT_CLIENT_VERSION, 2,
+		EGL_NONE
+	};
+
+	EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
+
+	context = egl.createContext(display, config, EGL_NO_CONTEXT, attribList);
+	EGLU_CHECK_MSG(egl, "eglCreateContext() failed");
+	TCU_CHECK(context);
+
+	return context;
+}
+
+class GetFrameTimestampTest : public SimpleConfigCase
+{
+public:
+							GetFrameTimestampTest	(EglTestContext& eglTestCtx, const NamedFilterList& filters);
+							~GetFrameTimestampTest	(void);
+
+private:
+	void					executeForConfig		(EGLDisplay display, EGLConfig config);
+	void					initializeExtension		(const Library& egl);
+
+	// Not allowed
+							GetFrameTimestampTest	(const GetFrameTimestampTest&);
+	GetFrameTimestampTest&	operator=				(const GetFrameTimestampTest&);
+
+	// TODO: Move these to eglw::Library.
+	eglGetNextFrameIdANDROIDFunc				m_eglGetNextFrameIdANDROID;
+	eglGetCompositorTimingANDROIDFunc			m_eglGetCompositorTimingANDROID;
+	eglGetCompositorTimingSupportedANDROIDFunc	m_eglGetCompositorTimingSupportedANDROID;
+	eglGetFrameTimestampsANDROIDFunc			m_eglGetFrameTimestampsANDROID;
+	eglGetFrameTimestampSupportedANDROIDFunc	m_eglGetFrameTimestampSupportedANDROID;
+
+	tcu::ResultCollector						m_result;
+};
+
+GetFrameTimestampTest::GetFrameTimestampTest (EglTestContext& eglTestCtx, const NamedFilterList& filters)
+	: SimpleConfigCase							(eglTestCtx, filters.getName(), filters.getDescription(), filters)
+	, m_eglGetNextFrameIdANDROID				(DE_NULL)
+	, m_eglGetCompositorTimingANDROID			(DE_NULL)
+	, m_eglGetCompositorTimingSupportedANDROID	(DE_NULL)
+	, m_eglGetFrameTimestampsANDROID			(DE_NULL)
+	, m_eglGetFrameTimestampSupportedANDROID	(DE_NULL)
+	, m_result									(m_testCtx.getLog())
+{
+}
+
+GetFrameTimestampTest::~GetFrameTimestampTest (void)
+{
+}
+
+void GetFrameTimestampTest::initializeExtension (const Library& egl)
+{
+	m_eglGetNextFrameIdANDROID = reinterpret_cast<eglGetNextFrameIdANDROIDFunc>(egl.getProcAddress("eglGetNextFrameIdANDROID"));
+	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetNextFrameIdANDROID failed.");
+	m_eglGetCompositorTimingANDROID = reinterpret_cast<eglGetCompositorTimingANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingANDROID"));
+	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingANDROID failed.");
+	m_eglGetCompositorTimingSupportedANDROID = reinterpret_cast<eglGetCompositorTimingSupportedANDROIDFunc>(egl.getProcAddress("eglGetCompositorTimingSupportedANDROID"));
+	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetCompositorTimingSupportedANDROID failed.");
+	m_eglGetFrameTimestampsANDROID = reinterpret_cast<eglGetFrameTimestampsANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampsANDROID"));
+	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampsANDROID failed.");
+	m_eglGetFrameTimestampSupportedANDROID = reinterpret_cast<eglGetFrameTimestampSupportedANDROIDFunc>(egl.getProcAddress("eglGetFrameTimestampSupportedANDROID"));
+	EGLU_CHECK_MSG(egl, "getProcAddress of eglGetFrameTimestampSupportedANDROID failed.");
+}
+
+
+string getConfigIdString (const Library& egl, EGLDisplay display, EGLConfig config)
+{
+	std::ostringstream	stream;
+	EGLint				id;
+
+	EGLU_CHECK_CALL(egl, getConfigAttrib(display, config , EGL_CONFIG_ID, &id));
+
+	stream << id;
+
+	return stream.str();
+}
+
+deUint32 createGLES2Program (const glw::Functions& gl, TestLog& log)
+{
+	const char* const vertexShaderSource =
+	"attribute highp vec2 a_pos;\n"
+	"void main (void)\n"
+	"{\n"
+	"\tgl_Position = vec4(a_pos, 0.0, 1.0);\n"
+	"}";
+
+	const char* const fragmentShaderSource =
+	"void main (void)\n"
+	"{\n"
+	"\tgl_FragColor = vec4(0.9, 0.1, 0.4, 1.0);\n"
+	"}";
+
+	deUint32	program			= 0;
+	deUint32	vertexShader	= 0;
+	deUint32	fragmentShader	= 0;
+
+	deInt32		vertexCompileStatus;
+	string		vertexInfoLog;
+	deInt32		fragmentCompileStatus;
+	string		fragmentInfoLog;
+	deInt32		linkStatus;
+	string		programInfoLog;
+
+	try
+	{
+		program			= gl.createProgram();
+		vertexShader	= gl.createShader(GL_VERTEX_SHADER);
+		fragmentShader	= gl.createShader(GL_FRAGMENT_SHADER);
+
+		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create shaders and program");
+
+		gl.shaderSource(vertexShader, 1, &vertexShaderSource, DE_NULL);
+		gl.compileShader(vertexShader);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup vertex shader");
+
+		gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, DE_NULL);
+		gl.compileShader(fragmentShader);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup fragment shader");
+
+		{
+			deInt32		infoLogLength = 0;
+
+			gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &vertexCompileStatus);
+			gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+			vertexInfoLog.resize(infoLogLength, '\0');
+
+			gl.getShaderInfoLog(vertexShader, (glw::GLsizei)vertexInfoLog.length(), &infoLogLength, &(vertexInfoLog[0]));
+			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get vertex shader compile info");
+
+			vertexInfoLog.resize(infoLogLength);
+		}
+
+		{
+			deInt32		infoLogLength = 0;
+
+			gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &fragmentCompileStatus);
+			gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+			fragmentInfoLog.resize(infoLogLength, '\0');
+
+			gl.getShaderInfoLog(fragmentShader, (glw::GLsizei)fragmentInfoLog.length(), &infoLogLength, &(fragmentInfoLog[0]));
+			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get fragment shader compile info");
+
+			fragmentInfoLog.resize(infoLogLength);
+		}
+
+		gl.attachShader(program, vertexShader);
+		gl.attachShader(program, fragmentShader);
+		gl.linkProgram(program);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup program");
+
+		{
+			deInt32		infoLogLength = 0;
+
+			gl.getProgramiv(program, GL_LINK_STATUS, &linkStatus);
+			gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength);
+
+			programInfoLog.resize(infoLogLength, '\0');
+
+			gl.getProgramInfoLog(program, (glw::GLsizei)programInfoLog.length(), &infoLogLength, &(programInfoLog[0]));
+			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get program link info");
+
+			programInfoLog.resize(infoLogLength);
+		}
+
+		if (linkStatus == 0 || vertexCompileStatus == 0 || fragmentCompileStatus == 0)
+		{
+
+			log.startShaderProgram(linkStatus != 0, programInfoLog.c_str());
+
+			log << TestLog::Shader(QP_SHADER_TYPE_VERTEX, vertexShaderSource, vertexCompileStatus != 0, vertexInfoLog);
+			log << TestLog::Shader(QP_SHADER_TYPE_FRAGMENT, fragmentShaderSource, fragmentCompileStatus != 0, fragmentInfoLog);
+
+			log.endShaderProgram();
+		}
+
+		gl.deleteShader(vertexShader);
+		gl.deleteShader(fragmentShader);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to delete shaders");
+
+		TCU_CHECK(linkStatus != 0 && vertexCompileStatus != 0 && fragmentCompileStatus != 0);
+	}
+	catch (...)
+	{
+		if (program)
+			gl.deleteProgram(program);
+
+		if (vertexShader)
+			gl.deleteShader(vertexShader);
+
+		if (fragmentShader)
+			gl.deleteShader(fragmentShader);
+
+		throw;
+	}
+
+	return program;
+}
+
+void GetFrameTimestampTest::executeForConfig (EGLDisplay display, EGLConfig config)
+{
+	const Library&						egl			= m_eglTestCtx.getLibrary();
+
+	if (!eglu::hasExtension(egl, display, "EGL_ANDROID_get_frame_timestamps"))
+		TCU_THROW(NotSupportedError, "EGL_ANDROID_get_frame_timestamps is not supported");
+
+	initializeExtension(egl);
+
+	const string						configIdStr	(getConfigIdString(egl, display, config));
+	tcu::ScopedLogSection				logSection	(m_testCtx.getLog(), ("Config ID " + configIdStr).c_str(), ("Config ID " + configIdStr).c_str());
+	const eglu::NativeWindowFactory&	factory		= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
+
+	{
+		TestLog& log = m_testCtx.getLog();
+
+		log << TestLog::Message << "EGL_RED_SIZE: "		<< eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE)		<< TestLog::EndMessage;
+		log << TestLog::Message << "EGL_GREEN_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE)	<< TestLog::EndMessage;
+		log << TestLog::Message << "EGL_BLUE_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE)	<< TestLog::EndMessage;
+		log << TestLog::Message << "EGL_ALPHA_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE)	<< TestLog::EndMessage;
+		log << TestLog::Message << "EGL_DEPTH_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_DEPTH_SIZE)	<< TestLog::EndMessage;
+		log << TestLog::Message << "EGL_STENCIL_SIZE: "	<< eglu::getConfigAttribInt(egl, display, config, EGL_STENCIL_SIZE)	<< TestLog::EndMessage;
+		log << TestLog::Message << "EGL_SAMPLES: "		<< eglu::getConfigAttribInt(egl, display, config, EGL_SAMPLES)		<< TestLog::EndMessage;
+	}
+
+	de::UniquePtr<eglu::NativeWindow>	window	(factory.createWindow(&m_eglTestCtx.getNativeDisplay(), display, config, DE_NULL, eglu::WindowParams(128, 128, eglu::WindowParams::VISIBILITY_VISIBLE)));
+
+	eglu::UniqueSurface					surface	(egl, display, eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, display, config, DE_NULL));
+	eglu::UniqueContext					context	(egl, display, createGLES2Context(egl, display, config));
+	glw::Functions						gl;
+	deUint32							program = 0;
+
+	EGLU_CHECK_CALL(egl, surfaceAttrib(display, *surface, EGL_TIMESTAMPS_ANDROID, EGL_TRUE));
+
+	m_eglTestCtx.initGLFunctions(&gl, glu::ApiType::es(2,0));
+
+	EGLU_CHECK_CALL(egl, makeCurrent(display, *surface, *surface, *context));
+
+	try
+	{
+		// Verify required timestamps are supported.
+		const eglw::EGLint requiredTimestamps[] =
+		{
+			EGL_REQUESTED_PRESENT_TIME_ANDROID,
+			EGL_RENDERING_COMPLETE_TIME_ANDROID,
+			EGL_COMPOSITION_LATCH_TIME_ANDROID,
+			EGL_FIRST_COMPOSITION_START_TIME_ANDROID,
+			EGL_LAST_COMPOSITION_START_TIME_ANDROID,
+			EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID,
+			EGL_DEQUEUE_READY_TIME_ANDROID,
+			EGL_READS_DONE_TIME_ANDROID,
+		};
+		const size_t requiredTimestampsCount = DE_LENGTH_OF_ARRAY(requiredTimestamps);
+
+		for (size_t i = 0; i < requiredTimestampsCount; i++)
+		{
+			const bool supported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, requiredTimestamps[i]);
+			EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
+			TCU_CHECK_MSG(supported, "Required timestamp not supported.");
+		}
+
+		// Verify either retire or present is supported.
+		const bool retireSupported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, EGL_DISPLAY_RETIRE_TIME_ANDROID);
+		EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
+		const bool presentSupported = m_eglGetFrameTimestampSupportedANDROID(display, *surface, EGL_DISPLAY_PRESENT_TIME_ANDROID);
+		EGLU_CHECK_MSG(egl, "eglGetFrameTimestampSupportedANDROID failed.");
+		TCU_CHECK_MSG(retireSupported != presentSupported, "DISPLAY_RETIRE or DISPLAY_PRESENT must be supported, but not both.");
+
+		// Verify compositor timings are supported.
+		const bool deadlineSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_DEADLINE_ANDROID);
+		EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
+		TCU_CHECK_MSG(deadlineSupported, "EGL_COMPOSITE_DEADLINE_ANDROID not supported.");
+		const bool intervalSupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_INTERVAL_ANDROID);
+		EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
+		TCU_CHECK_MSG(intervalSupported, "EGL_COMPOSITE_INTERVAL_ANDROID not supported.");
+		const bool latencySupported = m_eglGetCompositorTimingSupportedANDROID(display, *surface, EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID);
+		EGLU_CHECK_MSG(egl, "eglGetCompositorTimingSupportedANDROID failed.");
+		TCU_CHECK_MSG(latencySupported, "EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID not supported.");
+
+
+		const eglw::EGLint frameTimestampNames[] =
+		{
+			EGL_REQUESTED_PRESENT_TIME_ANDROID,
+			EGL_RENDERING_COMPLETE_TIME_ANDROID,
+			EGL_COMPOSITION_LATCH_TIME_ANDROID,
+			EGL_FIRST_COMPOSITION_START_TIME_ANDROID,
+			EGL_LAST_COMPOSITION_START_TIME_ANDROID,
+			EGL_FIRST_COMPOSITION_GPU_FINISHED_TIME_ANDROID,
+			presentSupported ? EGL_DISPLAY_PRESENT_TIME_ANDROID : EGL_DISPLAY_RETIRE_TIME_ANDROID,
+			EGL_DEQUEUE_READY_TIME_ANDROID,
+			EGL_READS_DONE_TIME_ANDROID,
+		};
+		const size_t frameTimestampCount = DE_LENGTH_OF_ARRAY(frameTimestampNames);
+
+		const float positions1[] =
+		{
+			 0.00f,  0.00f,
+			 0.75f,  0.00f,
+			 0.75f,  0.75f,
+
+			 0.75f,  0.75f,
+			 0.00f,  0.75f,
+			 0.00f,  0.00f
+		};
+
+		const float positions2[] =
+		{
+			-0.75f, -0.75f,
+			 0.00f, -0.75f,
+			 0.00f,  0.00f,
+
+			 0.00f,  0.00f,
+			-0.75f,  0.00f,
+			-0.75f, -0.75f
+		};
+
+		deUint32 posLocation;
+
+		program	= createGLES2Program(gl, m_testCtx.getLog());
+
+		gl.useProgram(program);
+		posLocation	= gl.getAttribLocation(program, "a_pos");
+		gl.enableVertexAttribArray(posLocation);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup shader program for rendering");
+
+		const size_t frameCount = 120;
+		std::vector<FrameTimes> frameTimes(frameCount);
+		for (size_t i = 0; i < frameCount; i++)
+		{
+			FrameTimes& frame = frameTimes[i];
+
+			const eglw::EGLint compositorTimingNames[] =
+			{
+				EGL_COMPOSITE_DEADLINE_ANDROID,
+				EGL_COMPOSITE_INTERVAL_ANDROID,
+				EGL_COMPOSITE_TO_PRESENT_LATENCY_ANDROID,
+			};
+			const EGLint compositorTimingCount = DE_LENGTH_OF_ARRAY(compositorTimingNames);
+			EGLnsecsANDROID compositorTimingValues[compositorTimingCount] = { -2 };
+
+			// Get the frame id.
+			EGLuint64KHR nextFrameId = 0;
+			CHECK_NAKED_EGL_CALL(egl, m_eglGetNextFrameIdANDROID(display, *surface, &nextFrameId));
+			frame.frameId				=	nextFrameId;
+
+			// Get the compositor timing.
+			CHECK_NAKED_EGL_CALL(egl, m_eglGetCompositorTimingANDROID(
+				display, *surface, compositorTimingCount,
+				compositorTimingNames, compositorTimingValues));
+			frame.compositeDeadline			=	compositorTimingValues[0];
+			frame.compositeInterval			=	compositorTimingValues[1];
+			frame.compositeToPresentLatency	=	compositorTimingValues[2];
+
+			// Verify compositor timing is sane.
+			EGLnsecsANDROID now = getNanoseconds();
+			m_result.check(1000000 < frame.compositeInterval, "Reported refresh rate greater than 1kHz.");
+			m_result.check(frame.compositeInterval < 1000000000, "Reported refresh rate less than 1Hz.");
+			m_result.check(0 < frame.compositeToPresentLatency, "Composite to present latency must be greater than 0.");
+			m_result.check(frame.compositeToPresentLatency < frame.compositeInterval * 3, "Composite to present latency is more than 3 vsyncs.");
+			const EGLnsecsANDROID minDeadline = now;
+			m_result.check(minDeadline < frame.compositeDeadline, "Next composite deadline is in the past.");
+			const EGLnsecsANDROID maxDeadline = now + frame.compositeInterval * 2;
+			m_result.check(frame.compositeDeadline < maxDeadline, "Next composite deadline over two intervals away.");
+
+			const float colorAngle = (static_cast<float>(i) / static_cast<float>(frameCount)) * 6.28318f;
+			gl.clearColor((1.0f + deFloatSin(colorAngle)) / 2.0f, 0.7f, (1.0f + deFloatCos(colorAngle)) / 2.0f, 1.0f);
+			gl.clear(GL_COLOR_BUFFER_BIT);
+			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to clear surface");
+
+			const bool posSelect  = ((i % 2) == 0);
+			gl.vertexAttribPointer(posLocation, 2, GL_FLOAT, GL_FALSE, 0, posSelect ? positions1 : positions2);
+			gl.drawArrays(GL_TRIANGLES, 0, 6);
+			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render");
+
+			frame.swapBufferBeginNs = getNanoseconds();
+			EGLU_CHECK_CALL(egl, swapBuffers(display, *surface));
+
+			// All timestamps from 5 frames ago should definitely be available.
+			const size_t frameDelay = 5;
+			if (i >= frameDelay)
+			{
+				FrameTimes&		frame5ago									=	frameTimes[i-frameDelay];
+				EGLnsecsANDROID frameTimestampValues[frameTimestampCount]	=	{ 0 };
+				// \todo [2017-01-25 brianderson] Remove this work around once reads done is fixed.
+				const bool verifyReadsDone									=	i > (frameDelay + 3);
+
+				CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
+					display, *surface, frame5ago.frameId, frameTimestampCount,
+					frameTimestampNames, frameTimestampValues));
+
+				frame5ago.requestedPresent				=	frameTimestampValues[0];
+				frame5ago.renderingComplete				=	frameTimestampValues[1];
+				frame5ago.latch							=	frameTimestampValues[2];
+				frame5ago.firstCompositionStart			=	frameTimestampValues[3];
+				frame5ago.lastCompositionStart			=	frameTimestampValues[4];
+				frame5ago.firstCompositionGpuFinished	=	frameTimestampValues[5];
+				frame5ago.dequeueReady					=	frameTimestampValues[7];
+				frame5ago.readsDone						=	frameTimestampValues[8];
+				if (presentSupported)
+					frame5ago.displayPresent			=	frameTimestampValues[6];
+				else
+					frame5ago.displayRetire			=	frameTimestampValues[6];
+
+				verifySingleFrame(frame5ago, m_result, verifyReadsDone);
+				if (i >= frameDelay + 1)
+				{
+					FrameTimes& frame6ago = frameTimes[i-frameDelay-1];
+					verifyNeighboringFrames(frame6ago, frame5ago, m_result, verifyReadsDone);
+				}
+			}
+		}
+
+		// All timestamps for the most recently swapped frame should
+		// become available by only polling eglGetFrametimestamps.
+		// No additional swaps should be necessary.
+		FrameTimes&				lastFrame				=	frameTimes.back();
+		const EGLnsecsANDROID	pollingDeadline			=	lastFrame.swapBufferBeginNs + 1000000000;
+		bool					finalTimestampAvaiable	=	false;
+
+		do
+		{
+			EGLnsecsANDROID frameTimestampValues[frameTimestampCount] = { 0 };
+			CHECK_NAKED_EGL_CALL(egl, m_eglGetFrameTimestampsANDROID(
+				display, *surface, lastFrame.frameId, frameTimestampCount,
+				frameTimestampNames, frameTimestampValues));
+
+			lastFrame.requestedPresent				=	frameTimestampValues[0];
+			lastFrame.renderingComplete				=	frameTimestampValues[1];
+			lastFrame.latch							=	frameTimestampValues[2];
+			lastFrame.firstCompositionStart			=	frameTimestampValues[3];
+			lastFrame.lastCompositionStart			=	frameTimestampValues[4];
+			lastFrame.firstCompositionGpuFinished	=	frameTimestampValues[5];
+			lastFrame.dequeueReady					=	frameTimestampValues[7];
+			lastFrame.readsDone						=	frameTimestampValues[8];
+			if (presentSupported)
+			{
+				lastFrame.displayPresent = frameTimestampValues[6];
+				if (timestampExists(lastFrame.displayPresent))
+					finalTimestampAvaiable = true;
+			}
+			else
+			{
+				lastFrame.displayRetire = frameTimestampValues[6];
+				if (timestampExists(lastFrame.firstCompositionStart))
+					finalTimestampAvaiable = true;
+			}
+
+			if (getNanoseconds() > pollingDeadline)
+				break;
+		} while (!finalTimestampAvaiable);
+
+		m_result.check(finalTimestampAvaiable, "Timed out polling for timestamps of last swap.");
+		m_result.check(timestampExists(lastFrame.requestedPresent), "Rendering complete of last swap not avaiable.");
+		m_result.check(timestampExists(lastFrame.renderingComplete), "Rendering complete of last swap not avaiable.");
+		m_result.check(timestampExists(lastFrame.latch), "Latch of last swap not avaiable.");
+		m_result.check(timestampExists(lastFrame.firstCompositionStart), "First composite time of last swap not avaiable.");
+		m_result.check(timestampExists(lastFrame.lastCompositionStart), "Last composite time of last swap not avaiable.");
+
+		window->processEvents();
+		gl.disableVertexAttribArray(posLocation);
+		gl.useProgram(0);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to release program state");
+
+		gl.deleteProgram(program);
+		program = 0;
+		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram()");
+
+		m_result.setTestContextResult(m_testCtx);
+	}
+	catch (...)
+	{
+		if (program != 0)
+			gl.deleteProgram(program);
+
+		EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+		throw;
+	}
+
+	EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
+}
+
+class GetFrameTimestampsTests : public TestCaseGroup
+{
+public:
+								GetFrameTimestampsTests	(EglTestContext& eglTestCtx);
+	void						init					(void);
+
+private:
+								GetFrameTimestampsTests	(const GetFrameTimestampsTests&);
+	GetFrameTimestampsTests&	operator=				(const GetFrameTimestampsTests&);
+};
+
+
+GetFrameTimestampsTests::GetFrameTimestampsTests (EglTestContext& eglTestCtx)
+	: TestCaseGroup(eglTestCtx, "get_frame_timestamps", "Get frame timestamp tests")
+{
+}
+
+bool isWindow (const eglu::CandidateConfig& c)
+{
+	return (c.surfaceType() & EGL_WINDOW_BIT) != 0;
+}
+
+void GetFrameTimestampsTests::init (void)
+{
+	eglu::FilterList baseFilters;
+	baseFilters << isWindow;
+
+	vector<NamedFilterList> filterLists;
+	getDefaultFilterLists(filterLists, baseFilters);
+
+	for (vector<NamedFilterList>::iterator i = filterLists.begin(); i != filterLists.end(); i++)
+		addChild(new GetFrameTimestampTest(m_eglTestCtx, *i));
+}
+
+} // anonymous
+
+TestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx)
+{
+	return new GetFrameTimestampsTests(eglTestCtx);
+}
+
+} // egl
+} // deqp
diff --git a/modules/egl/teglGetFrameTimestampsTests.hpp b/modules/egl/teglGetFrameTimestampsTests.hpp
new file mode 100644
index 0000000..d55d6a4
--- /dev/null
+++ b/modules/egl/teglGetFrameTimestampsTests.hpp
@@ -0,0 +1,39 @@
+#ifndef _TEGLGETFRAMETIMESTAMPSTESTS_HPP
+#define _TEGLGETFRAMETIMESTAMPSTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program EGL Module
+ * ---------------------------------------
+ *
+ * Copyright 2017 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 Test the EGL_ANDROID_get_frame_timestamps extension.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "teglTestCase.hpp"
+
+namespace deqp
+{
+namespace egl
+{
+
+TestCaseGroup* createGetFrameTimestampsTests (EglTestContext& eglTestCtx);
+
+} // egl
+} // deqp
+
+#endif // _TEGLGETFRAMETIMESTAMPSTESTS_HPP
diff --git a/modules/egl/teglGetProcAddressTests.inl b/modules/egl/teglGetProcAddressTests.inl
index 087ec0e..33fde9b 100644
--- a/modules/egl/teglGetProcAddressTests.inl
+++ b/modules/egl/teglGetProcAddressTests.inl
@@ -1,7 +1,7 @@
 /* WARNING: This is auto-generated file. Do not modify, since changes will
  * be lost! Modify the generating script instead.
  *
- * Generated from Khronos EGL API description (egl.xml) revision 32725.
+ * Generated from Khronos EGL API description (egl.xml) revision 33315.
  */
 
 static const char* s_EGL14[] =
@@ -449,11 +449,21 @@
 	"eglSetBlobCacheFuncsANDROID",
 };
 
+static const char* s_EGL_ANDROID_create_native_client_buffer[] =
+{
+	"eglCreateNativeClientBufferANDROID",
+};
+
 static const char* s_EGL_ANDROID_native_fence_sync[] =
 {
 	"eglDupNativeFenceFDANDROID",
 };
 
+static const char* s_EGL_ANDROID_presentation_time[] =
+{
+	"eglPresentationTimeANDROID",
+};
+
 static const char* s_EGL_ANGLE_query_surface_pointer[] =
 {
 	"eglQuerySurfacePointerANGLE",
@@ -479,6 +489,12 @@
 	"eglQueryDisplayAttribEXT",
 };
 
+static const char* s_EGL_EXT_image_dma_buf_import_modifiers[] =
+{
+	"eglQueryDmaBufFormatsEXT",
+	"eglQueryDmaBufModifiersEXT",
+};
+
 static const char* s_EGL_EXT_output_base[] =
 {
 	"eglGetOutputLayersEXT",
@@ -581,6 +597,15 @@
 	"eglStreamAttribKHR",
 };
 
+static const char* s_EGL_KHR_stream_attrib[] =
+{
+	"eglCreateStreamAttribKHR",
+	"eglQueryStreamAttribKHR",
+	"eglSetStreamAttribKHR",
+	"eglStreamConsumerAcquireAttribKHR",
+	"eglStreamConsumerReleaseAttribKHR",
+};
+
 static const char* s_EGL_KHR_stream_consumer_gltexture[] =
 {
 	"eglStreamConsumerAcquireKHR",
@@ -660,6 +685,11 @@
 	"eglSetStreamMetadataNV",
 };
 
+static const char* s_EGL_NV_stream_reset[] =
+{
+	"eglResetStreamNV",
+};
+
 static const char* s_EGL_NV_stream_sync[] =
 {
 	"eglCreateStreamSyncNV",
@@ -1553,11 +1583,14 @@
 } s_extensions[] =
 {
 	{ "EGL_ANDROID_blob_cache",							DE_LENGTH_OF_ARRAY(s_EGL_ANDROID_blob_cache),						s_EGL_ANDROID_blob_cache						},
+	{ "EGL_ANDROID_create_native_client_buffer",		DE_LENGTH_OF_ARRAY(s_EGL_ANDROID_create_native_client_buffer),		s_EGL_ANDROID_create_native_client_buffer		},
 	{ "EGL_ANDROID_native_fence_sync",					DE_LENGTH_OF_ARRAY(s_EGL_ANDROID_native_fence_sync),				s_EGL_ANDROID_native_fence_sync					},
+	{ "EGL_ANDROID_presentation_time",					DE_LENGTH_OF_ARRAY(s_EGL_ANDROID_presentation_time),				s_EGL_ANDROID_presentation_time					},
 	{ "EGL_ANGLE_query_surface_pointer",				DE_LENGTH_OF_ARRAY(s_EGL_ANGLE_query_surface_pointer),				s_EGL_ANGLE_query_surface_pointer				},
 	{ "EGL_EXT_device_base",							DE_LENGTH_OF_ARRAY(s_EGL_EXT_device_base),							s_EGL_EXT_device_base							},
 	{ "EGL_EXT_device_enumeration",						DE_LENGTH_OF_ARRAY(s_EGL_EXT_device_enumeration),					s_EGL_EXT_device_enumeration					},
 	{ "EGL_EXT_device_query",							DE_LENGTH_OF_ARRAY(s_EGL_EXT_device_query),							s_EGL_EXT_device_query							},
+	{ "EGL_EXT_image_dma_buf_import_modifiers",			DE_LENGTH_OF_ARRAY(s_EGL_EXT_image_dma_buf_import_modifiers),		s_EGL_EXT_image_dma_buf_import_modifiers		},
 	{ "EGL_EXT_output_base",							DE_LENGTH_OF_ARRAY(s_EGL_EXT_output_base),							s_EGL_EXT_output_base							},
 	{ "EGL_EXT_platform_base",							DE_LENGTH_OF_ARRAY(s_EGL_EXT_platform_base),						s_EGL_EXT_platform_base							},
 	{ "EGL_EXT_stream_consumer_egloutput",				DE_LENGTH_OF_ARRAY(s_EGL_EXT_stream_consumer_egloutput),			s_EGL_EXT_stream_consumer_egloutput				},
@@ -1573,6 +1606,7 @@
 	{ "EGL_KHR_partial_update",							DE_LENGTH_OF_ARRAY(s_EGL_KHR_partial_update),						s_EGL_KHR_partial_update						},
 	{ "EGL_KHR_reusable_sync",							DE_LENGTH_OF_ARRAY(s_EGL_KHR_reusable_sync),						s_EGL_KHR_reusable_sync							},
 	{ "EGL_KHR_stream",									DE_LENGTH_OF_ARRAY(s_EGL_KHR_stream),								s_EGL_KHR_stream								},
+	{ "EGL_KHR_stream_attrib",							DE_LENGTH_OF_ARRAY(s_EGL_KHR_stream_attrib),						s_EGL_KHR_stream_attrib							},
 	{ "EGL_KHR_stream_consumer_gltexture",				DE_LENGTH_OF_ARRAY(s_EGL_KHR_stream_consumer_gltexture),			s_EGL_KHR_stream_consumer_gltexture				},
 	{ "EGL_KHR_stream_cross_process_fd",				DE_LENGTH_OF_ARRAY(s_EGL_KHR_stream_cross_process_fd),				s_EGL_KHR_stream_cross_process_fd				},
 	{ "EGL_KHR_stream_fifo",							DE_LENGTH_OF_ARRAY(s_EGL_KHR_stream_fifo),							s_EGL_KHR_stream_fifo							},
@@ -1587,6 +1621,7 @@
 	{ "EGL_NV_post_sub_buffer",							DE_LENGTH_OF_ARRAY(s_EGL_NV_post_sub_buffer),						s_EGL_NV_post_sub_buffer						},
 	{ "EGL_NV_stream_consumer_gltexture_yuv",			DE_LENGTH_OF_ARRAY(s_EGL_NV_stream_consumer_gltexture_yuv),			s_EGL_NV_stream_consumer_gltexture_yuv			},
 	{ "EGL_NV_stream_metadata",							DE_LENGTH_OF_ARRAY(s_EGL_NV_stream_metadata),						s_EGL_NV_stream_metadata						},
+	{ "EGL_NV_stream_reset",							DE_LENGTH_OF_ARRAY(s_EGL_NV_stream_reset),							s_EGL_NV_stream_reset							},
 	{ "EGL_NV_stream_sync",								DE_LENGTH_OF_ARRAY(s_EGL_NV_stream_sync),							s_EGL_NV_stream_sync							},
 	{ "EGL_NV_sync",									DE_LENGTH_OF_ARRAY(s_EGL_NV_sync),									s_EGL_NV_sync									},
 	{ "EGL_NV_system_time",								DE_LENGTH_OF_ARRAY(s_EGL_NV_system_time),							s_EGL_NV_system_time							},
diff --git a/modules/egl/teglNegativeApiTests.cpp b/modules/egl/teglNegativeApiTests.cpp
index 8295f74..a33da58 100644
--- a/modules/egl/teglNegativeApiTests.cpp
+++ b/modules/egl/teglNegativeApiTests.cpp
@@ -122,11 +122,12 @@
 	using namespace eglw;
 	using namespace eglu;
 
-	static const EGLint s_emptyAttribList[]			= { EGL_NONE };
-	static const EGLint s_es1ContextAttribList[]	= { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE };
-	static const EGLint s_es2ContextAttribList[]	= { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
+	static const EGLint				s_emptyAttribList[]			= { EGL_NONE };
+	static const EGLint				s_es1ContextAttribList[]	= { EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE };
+	static const EGLint				s_es2ContextAttribList[]	= { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
 
-	static const EGLenum s_renderAPIs[]				= { EGL_OPENGL_API, EGL_OPENGL_ES_API, EGL_OPENVG_API };
+	static const EGLenum			s_renderAPIs[]				= { EGL_OPENGL_API, EGL_OPENGL_ES_API, EGL_OPENVG_API };
+	static const eglu::ConfigFilter	s_renderAPIFilters[]		= { renderable<EGL_OPENGL_BIT>, renderable<EGL_OPENGL_ES_BIT>, renderable<EGL_OPENVG_BIT> };
 
 	TEGL_ADD_API_CASE(bind_api, "eglBindAPI() negative tests",
 		{
@@ -144,14 +145,19 @@
 
 			log << TestLog::EndSection;
 
-			log << TestLog::Section("Test2", "EGL_BAD_PARAMETER is generated if the specified client API is not supported by the EGL implementation");
+			log << TestLog::Section("Test2", "EGL_BAD_PARAMETER is generated if the specified client API is not supported by the EGL display, or no configuration is provided for the specified API.");
 
 			for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_renderAPIs); ndx++)
 			{
 				if (!isAPISupported(s_renderAPIs[ndx]))
 				{
-					expectFalse(eglBindAPI(s_renderAPIs[ndx]));
-					expectError(EGL_BAD_PARAMETER);
+					if (!eglBindAPI(s_renderAPIs[ndx]))
+						expectError(EGL_BAD_PARAMETER);
+					else
+					{
+						EGLConfig eglConfig;
+						expectFalse(getConfig(&eglConfig, FilterList() << s_renderAPIFilters[ndx]));
+					}
 				}
 			}
 
diff --git a/modules/egl/teglRenderCase.cpp b/modules/egl/teglRenderCase.cpp
index fc30091..a0ff8ae 100644
--- a/modules/egl/teglRenderCase.cpp
+++ b/modules/egl/teglRenderCase.cpp
@@ -397,6 +397,11 @@
 	return c.get(EGL_CONFIG_CAVEAT) != EGL_NON_CONFORMANT_CONFIG;
 }
 
+static bool notFloat (const eglu::CandidateConfig& c)
+{
+	return c.colorComponentType() != EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
+}
+
 void getDefaultRenderFilterLists (vector<RenderFilterList>& filterLists, const eglu::FilterList& baseFilters)
 {
 	static const struct
@@ -450,7 +455,8 @@
 				<< notColorBits<4, 4, 4, 4>
 				<< notColorBits<5, 5, 5, 1>
 				<< notColorBits<8, 8, 8, 8>
-				<< isConformant;
+				<< isConformant
+				<< notFloat;
 
 		filterLists.push_back(filters);
 	}
diff --git a/modules/egl/teglSimpleConfigCase.cpp b/modules/egl/teglSimpleConfigCase.cpp
index c528178..fc02455 100644
--- a/modules/egl/teglSimpleConfigCase.cpp
+++ b/modules/egl/teglSimpleConfigCase.cpp
@@ -143,6 +143,11 @@
 	return c.get(EGL_CONFIG_CAVEAT) != EGL_NON_CONFORMANT_CONFIG;
 }
 
+static bool notFloat (const eglu::CandidateConfig& c)
+{
+	return c.colorComponentType() != EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT;
+}
+
 void getDefaultFilterLists (vector<NamedFilterList>& lists, const FilterList& baseFilters)
 {
 	static const struct
@@ -209,7 +214,8 @@
 				<< notColorBits<4, 4, 4, 4>
 				<< notColorBits<5, 5, 5, 1>
 				<< notColorBits<8, 8, 8, 8>
-				<< isConformant;
+				<< isConformant
+				<< notFloat;
 
 		lists.push_back(filters);
 	}
diff --git a/modules/egl/teglTestPackage.cpp b/modules/egl/teglTestPackage.cpp
index 443fad6..0c4ee77 100644
--- a/modules/egl/teglTestPackage.cpp
+++ b/modules/egl/teglTestPackage.cpp
@@ -63,6 +63,7 @@
 #include "teglMultiContextTests.hpp"
 #include "teglThreadCleanUpTests.hpp"
 #include "teglMutableRenderBufferTests.hpp"
+#include "teglGetFrameTimestampsTests.hpp"
 
 namespace deqp
 {
@@ -138,6 +139,7 @@
 		addChild(createMultiContextTests		(m_eglTestCtx));
 		addChild(createThreadCleanUpTest		(m_eglTestCtx));
 		addChild(new MutableRenderBufferTests	(m_eglTestCtx));
+		addChild(createGetFrameTimestampsTests	(m_eglTestCtx));
 	}
 };
 
diff --git a/modules/gles2/functional/es2fIntegerStateQueryTests.cpp b/modules/gles2/functional/es2fIntegerStateQueryTests.cpp
index 245cf21..2b736d7 100644
--- a/modules/gles2/functional/es2fIntegerStateQueryTests.cpp
+++ b/modules/gles2/functional/es2fIntegerStateQueryTests.cpp
@@ -869,7 +869,15 @@
 		de::Random rnd(0xabcdef);
 
 		GLint maxViewportDimensions[2] = {0};
+		GLfloat viewportBoundsRange[2] = {0.0f};
+		GLboolean hasViewportArray = false;
 		glGetIntegerv(GL_MAX_VIEWPORT_DIMS, maxViewportDimensions);
+		hasViewportArray = m_context.getContextInfo().isExtensionSupported("GL_OES_viewport_array") ||
+						   m_context.getContextInfo().isExtensionSupported("GL_NV_viewport_array");
+		if (hasViewportArray)
+		{
+			glGetFloatv(GL_VIEWPORT_BOUNDS_RANGE, viewportBoundsRange);
+		}
 
 		// verify initial value of first two values
 		m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, 0, 0, m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
@@ -884,7 +892,19 @@
 			GLsizei height	= rnd.getInt(0, maxViewportDimensions[1]);
 
 			glViewport(x, y, width, height);
-			m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, x, y, width, height);
+
+			if (hasViewportArray)
+			{
+				m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT,
+										   de::clamp(x, deFloorFloatToInt32(viewportBoundsRange[0]), deFloorFloatToInt32(viewportBoundsRange[1])),
+										   de::clamp(y, deFloorFloatToInt32(viewportBoundsRange[0]), deFloorFloatToInt32(viewportBoundsRange[1])),
+										   width, height);
+			}
+			else
+			{
+				m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, x, y, width, height);
+			}
+
 			expectError(GL_NO_ERROR);
 		}
 	}
diff --git a/modules/gles2/functional/es2fPolygonOffsetTests.cpp b/modules/gles2/functional/es2fPolygonOffsetTests.cpp
index 4a933d8..7ec850f 100644
--- a/modules/gles2/functional/es2fPolygonOffsetTests.cpp
+++ b/modules/gles2/functional/es2fPolygonOffsetTests.cpp
@@ -475,7 +475,7 @@
 
 	retVal.x() = rnd.getFloat(-1, 1);
 	retVal.y() = rnd.getFloat(-1, 1);
-	retVal.z() = rnd.getFloat(-0.9f, 0.9f);
+	retVal.z() = 0.5f;
 	retVal.w() = 1.0f + rnd.getFloat();
 
 	return retVal;
diff --git a/modules/gles3/functional/es3fASTCDecompressionCases.cpp b/modules/gles3/functional/es3fASTCDecompressionCases.cpp
index ab60b1d..af32ff2 100644
--- a/modules/gles3/functional/es3fASTCDecompressionCases.cpp
+++ b/modules/gles3/functional/es3fASTCDecompressionCases.cpp
@@ -445,9 +445,12 @@
 
 	// Create texture and render.
 
-	glu::Texture2D	texture			(renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams((m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR ? tcu::TexDecompressionParams::ASTCMODE_LDR : tcu::TexDecompressionParams::ASTCMODE_HDR)));
-	Surface			renderedFrame	(imageWidth, imageHeight);
-	Surface			referenceFrame	(imageWidth, imageHeight);
+	const tcu::TexDecompressionParams::AstcMode	decompressionMode	= (m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR || tcu::isAstcSRGBFormat(m_format))
+																	? tcu::TexDecompressionParams::ASTCMODE_LDR
+																	: tcu::TexDecompressionParams::ASTCMODE_HDR;
+	glu::Texture2D								texture				(renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams(decompressionMode));
+	Surface										renderedFrame		(imageWidth, imageHeight);
+	Surface										referenceFrame		(imageWidth, imageHeight);
 
 	m_renderer->render(referenceFrame, renderedFrame, texture, getUncompressedFormat(compressed.getFormat()));
 
@@ -565,9 +568,12 @@
 
 	// Create texture and render.
 
-	Surface			renderedFrame	(imageWidth, imageHeight);
-	Surface			referenceFrame	(imageWidth, imageHeight);
-	glu::Texture2D	texture			(renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams(m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR ? tcu::TexDecompressionParams::ASTCMODE_LDR : tcu::TexDecompressionParams::ASTCMODE_HDR));
+	const tcu::TexDecompressionParams::AstcMode	decompressionMode	= (m_renderer->getASTCSupport() == ASTCSUPPORTLEVEL_LDR || tcu::isAstcSRGBFormat(m_format))
+																	? tcu::TexDecompressionParams::ASTCMODE_LDR
+																	: tcu::TexDecompressionParams::ASTCMODE_HDR;
+	Surface										renderedFrame		(imageWidth, imageHeight);
+	Surface										referenceFrame		(imageWidth, imageHeight);
+	glu::Texture2D								texture				(renderCtx, m_context.getContextInfo(), 1, &compressed, tcu::TexDecompressionParams(decompressionMode));
 
 	m_renderer->render(referenceFrame, renderedFrame, texture, getUncompressedFormat(compressed.getFormat()));
 
diff --git a/modules/gles3/functional/es3fIntegerStateQueryTests.cpp b/modules/gles3/functional/es3fIntegerStateQueryTests.cpp
index 518d608..4837128 100644
--- a/modules/gles3/functional/es3fIntegerStateQueryTests.cpp
+++ b/modules/gles3/functional/es3fIntegerStateQueryTests.cpp
@@ -1148,7 +1148,15 @@
 		de::Random rnd(0xabcdef);
 
 		GLint maxViewportDimensions[2] = {0};
+		GLfloat viewportBoundsRange[2] = {0.0f};
+		GLboolean hasViewportArray = false;
 		glGetIntegerv(GL_MAX_VIEWPORT_DIMS, maxViewportDimensions);
+		hasViewportArray = m_context.getContextInfo().isExtensionSupported("GL_OES_viewport_array") ||
+						   m_context.getContextInfo().isExtensionSupported("GL_NV_viewport_array");
+		if (hasViewportArray)
+		{
+			glGetFloatv(GL_VIEWPORT_BOUNDS_RANGE, viewportBoundsRange);
+		}
 
 		// verify initial value of first two values
 		m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, 0, 0, m_context.getRenderTarget().getWidth(), m_context.getRenderTarget().getHeight());
@@ -1163,7 +1171,19 @@
 			GLsizei height	= rnd.getInt(0, maxViewportDimensions[1]);
 
 			glViewport(x, y, width, height);
-			m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, x, y, width, height);
+
+			if (hasViewportArray)
+			{
+				m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT,
+										   de::clamp(x, deFloorFloatToInt32(viewportBoundsRange[0]), deFloorFloatToInt32(viewportBoundsRange[1])),
+										   de::clamp(y, deFloorFloatToInt32(viewportBoundsRange[0]), deFloorFloatToInt32(viewportBoundsRange[1])),
+										   width, height);
+			}
+			else
+			{
+				m_verifier->verifyInteger4(m_testCtx, GL_VIEWPORT, x, y, width, height);
+			}
+
 			expectError(GL_NO_ERROR);
 		}
 	}
diff --git a/modules/gles3/functional/es3fNegativeTextureApiTests.cpp b/modules/gles3/functional/es3fNegativeTextureApiTests.cpp
index 93fdd5a..e14fd9d 100644
--- a/modules/gles3/functional/es3fNegativeTextureApiTests.cpp
+++ b/modules/gles3/functional/es3fNegativeTextureApiTests.cpp
@@ -2065,9 +2065,9 @@
 			m_log << TestLog::EndSection;
 
 			m_log << TestLog::Section("", "GL_INVALID_OPERATION is generated if target is GL_TEXTURE_3D and format is GL_DEPTH_COMPONENT, or GL_DEPTH_STENCIL.");
-			glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, 0);
+			glTexImage3D(GL_TEXTURE_3D, 0, GL_DEPTH_STENCIL, 1, 1, 1, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0);
 			expectError(GL_INVALID_OPERATION);
-			glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA, 1, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
+			glTexImage3D(GL_TEXTURE_3D, 0, GL_DEPTH_COMPONENT, 1, 1, 1, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, 0);
 			expectError(GL_INVALID_OPERATION);
 			m_log << TestLog::EndSection;
 
diff --git a/modules/gles3/functional/es3fPolygonOffsetTests.cpp b/modules/gles3/functional/es3fPolygonOffsetTests.cpp
index 554539d..7352ee6 100644
--- a/modules/gles3/functional/es3fPolygonOffsetTests.cpp
+++ b/modules/gles3/functional/es3fPolygonOffsetTests.cpp
@@ -478,7 +478,7 @@
 
 	retVal.x() = rnd.getFloat(-1, 1);
 	retVal.y() = rnd.getFloat(-1, 1);
-	retVal.z() = rnd.getFloat(-0.9f, 0.9f);
+	retVal.z() = 0.5f;
 	retVal.w() = 1.0f + rnd.getFloat();
 
 	return retVal;
diff --git a/modules/gles3/functional/es3fShaderPrecisionTests.cpp b/modules/gles3/functional/es3fShaderPrecisionTests.cpp
index 2ca18da..da216fc 100644
--- a/modules/gles3/functional/es3fShaderPrecisionTests.cpp
+++ b/modules/gles3/functional/es3fShaderPrecisionTests.cpp
@@ -187,28 +187,7 @@
 	IterateResult				iterate						(void);
 
 protected:
-	bool						compare						(float in0, float in1, double reference, float result)
-#if (DE_COMPILER == DE_COMPILER_GCC) && (DE_CPU == DE_CPU_ARM_64)
-#	if (__GNUC__ == 4) && (__GNUC_MINOR__ == 9) && (__GNUC_PATCHLEVEL__ == 0)
-		// Some prerelease GCC 4.9 versions have a bug in shift right when
-		// targeting ARMv8.
-		//
-		// If compiler wants to perform logical shift by variable/register
-		// in fp/vector registers it uses USHL that selects shift direction
-		// based on shift operand value. Thus for right shifts the shift
-		// operand needs to be negated.
-		//
-		// The bug is in right shift pattern; it doesn't mark shift operand
-		// as clobbered and thus later code using that same register may
-		// see the negated value.
-		//
-		// Workaround is to disable optimization for this function.
-		//
-		// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61633
-		__attribute__((optimize(0)))
-#	endif
-#endif
-	;
+	bool						compare						(float in0, float in1, double reference, float result);
 
 private:
 								ShaderFloatPrecisionCase	(const ShaderFloatPrecisionCase& other);
diff --git a/modules/gles3/functional/es3fTextureSpecificationTests.cpp b/modules/gles3/functional/es3fTextureSpecificationTests.cpp
index 8e5b0ec..3a634a8 100644
--- a/modules/gles3/functional/es3fTextureSpecificationTests.cpp
+++ b/modules/gles3/functional/es3fTextureSpecificationTests.cpp
@@ -1080,14 +1080,13 @@
 		int						pixelSize		= m_texFormat.getPixelSize();
 		int						rowLength		= m_rowLength > 0 ? m_rowLength : m_width;
 		int						rowPitch		= deAlign32(rowLength*pixelSize, m_alignment);
-		int						height			= m_height + m_skipRows;
 		deUint32				tex				= 0;
 		vector<deUint8>			data;
 
 		DE_ASSERT(m_numLevels == 1);
 
 		// Fill data with grid.
-		data.resize(rowPitch*height);
+		data.resize(pixelSize * m_skipPixels + rowPitch * (m_height + m_skipRows));
 		{
 			Vec4	cScale		= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
 			Vec4	cBias		= m_texFormatInfo.valueMin;
@@ -1157,7 +1156,7 @@
 		DE_ASSERT(m_numLevels == 1);
 
 		// Fill data with grid.
-		data.resize(slicePitch*(m_depth+m_skipImages));
+		data.resize(pixelSize * m_skipPixels + rowPitch * m_skipRows + slicePitch * (m_skipImages + m_depth));
 		{
 			Vec4	cScale		= m_texFormatInfo.valueMax-m_texFormatInfo.valueMin;
 			Vec4	cBias		= m_texFormatInfo.valueMin;
diff --git a/modules/gles3/performance/es3pBufferDataUploadTests.cpp b/modules/gles3/performance/es3pBufferDataUploadTests.cpp
index bcd79a5..b8de44d 100644
--- a/modules/gles3/performance/es3pBufferDataUploadTests.cpp
+++ b/modules/gles3/performance/es3pBufferDataUploadTests.cpp
@@ -6018,7 +6018,7 @@
 template <typename Comparer>
 static DistributionCompareResult distributionCompare (const std::vector<deUint64>& orderedObservationsA, const std::vector<deUint64>& orderedObservationsB, const Comparer& comparer)
 {
-	// Mann–Whitney U test
+	// Mann-Whitney U test
 
 	const int				n1			= (int)orderedObservationsA.size();
 	const int				n2			= (int)orderedObservationsB.size();
diff --git a/modules/gles31/functional/CMakeLists.txt b/modules/gles31/functional/CMakeLists.txt
index 1f57b59..2f2429e 100644
--- a/modules/gles31/functional/CMakeLists.txt
+++ b/modules/gles31/functional/CMakeLists.txt
@@ -43,6 +43,8 @@
 	es31fShaderAtomicOpTests.hpp
 	es31fShaderImageLoadStoreTests.cpp
 	es31fShaderImageLoadStoreTests.hpp
+	es31fSRGBDecodeTests.cpp
+	es31fSRGBDecodeTests.hpp
 	es31fSSBOLayoutCase.cpp
 	es31fSSBOLayoutCase.hpp
 	es31fSSBOLayoutTests.cpp
@@ -157,6 +159,8 @@
 	es31fNegativePreciseTests.hpp
 	es31fNegativeAdvancedBlendEquationTests.cpp
 	es31fNegativeAdvancedBlendEquationTests.hpp
+	es31fNegativeTessellationTests.cpp
+	es31fNegativeTessellationTests.hpp
 	es31fTextureGatherTests.cpp
 	es31fTextureGatherTests.hpp
 	es31fTextureFormatTests.cpp
@@ -173,6 +177,10 @@
 	es31fCopyImageTests.cpp
 	es31fDrawBuffersIndexedTests.hpp
 	es31fDrawBuffersIndexedTests.cpp
+	es31fNegativeShaderStorageTests.cpp
+	es31fNegativeShaderStorageTests.hpp
+	es31fNegativeSSBOBlockTests.cpp
+	es31fNegativeSSBOBlockTests.hpp
 	)
 
 add_library(deqp-gles31-functional STATIC ${DEQP_GLES31_FUNCTIONAL_SRCS})
diff --git a/modules/gles31/functional/es31fCopyImageTests.cpp b/modules/gles31/functional/es31fCopyImageTests.cpp
index b4e9642..4d215c2 100644
--- a/modules/gles31/functional/es31fCopyImageTests.cpp
+++ b/modules/gles31/functional/es31fCopyImageTests.cpp
@@ -63,7 +63,9 @@
 using namespace glu::TextureTestUtil;
 
 using tcu::Float;
+using tcu::IVec2;
 using tcu::IVec3;
+using tcu::IVec4;
 using tcu::Sampler;
 using tcu::ScopedLogSection;
 using tcu::TestLog;
@@ -118,6 +120,12 @@
 	VIEWCLASS_ASTC_12x12_RGBA
 };
 
+enum Verify
+{
+	VERIFY_NONE = 0,
+	VERIFY_COMPARE_REFERENCE
+};
+
 const char* viewClassToName (ViewClass viewClass)
 {
 	switch (viewClass)
@@ -249,6 +257,91 @@
 	}
 }
 
+class RandomizedRenderGrid
+{
+public:
+					RandomizedRenderGrid	(const IVec2& targetSize, const IVec2& cellSize, int maxCellCount, deUint32 seed);
+	bool			nextCell				(void);
+	IVec2			getOrigin				(void) const;
+
+	const IVec2&	getCellSize				(void) const { return m_cellSize; };
+	IVec4			getUsedAreaBoundingBox	(void) const;
+	int				getCellCount			(void) const { return m_cellCount; };
+
+private:
+	static IVec2	getRandomOffset			(deUint32 seed, IVec2 targetSize, IVec2 cellSize, IVec2 grid, int cellCount);
+
+	const IVec2		m_targetSize;
+	const IVec2		m_cellSize;
+	const IVec2		m_grid;
+	int				m_currentCell;
+	const int		m_cellCount;
+	const IVec2		m_baseRandomOffset;
+};
+
+RandomizedRenderGrid::RandomizedRenderGrid (const IVec2& targetSize, const IVec2& cellSize, int maxCellCount, deUint32 seed)
+	: m_targetSize			(targetSize)
+	, m_cellSize			(cellSize)
+	, m_grid				(targetSize / cellSize)
+	, m_currentCell			(0)
+	// If the grid exactly fits height, take one row for randomization.
+	, m_cellCount			(deMin32(maxCellCount, ((targetSize.y() % cellSize.y()) == 0) && m_grid.y() > 1 ? m_grid.x() * (m_grid.y() - 1) :  m_grid.x() * m_grid.y()))
+	, m_baseRandomOffset	(getRandomOffset(seed, targetSize, cellSize, m_grid, m_cellCount))
+{
+}
+
+IVec2 RandomizedRenderGrid::getRandomOffset (deUint32 seed, IVec2 targetSize, IVec2 cellSize, IVec2 grid, int cellCount)
+{
+	de::Random	rng			(seed);
+	IVec2		result;
+	IVec2		extraSpace = targetSize - (cellSize * grid);
+
+	// If there'll be unused rows, donate them into extra space.
+	// (Round the required rows to full cell row to find out how many rows are unused, multiply by size)
+	DE_ASSERT(deDivRoundUp32(cellCount, grid.x()) <= grid.y());
+	extraSpace.y() += (grid.y() - deDivRoundUp32(cellCount, grid.x())) * cellSize.y();
+
+	DE_ASSERT(targetSize.x() > cellSize.x() && targetSize.y() > cellSize.y());
+	// If grid fits perfectly just one row of cells, just give up on randomizing.
+	DE_ASSERT(extraSpace.x() > 0 || extraSpace.y() > 0 || grid.y() == 1);
+	DE_ASSERT(extraSpace.x() + grid.x() * cellSize.x() == targetSize.x());
+
+	// \note Putting these as ctor params would make evaluation order undefined, I think <sigh>. Hence,
+	// no direct return.
+	result.x() = rng.getInt(0, extraSpace.x());
+	result.y() = rng.getInt(0, extraSpace.y());
+	return result;
+}
+
+bool RandomizedRenderGrid::nextCell (void)
+{
+	if (m_currentCell >= getCellCount())
+		return false;
+
+	m_currentCell++;
+	return true;
+}
+
+IVec2 RandomizedRenderGrid::getOrigin (void) const
+{
+	const int	gridX		  = (m_currentCell - 1) % m_grid.x();
+	const int	gridY		  = (m_currentCell - 1) / m_grid.x();
+	const IVec2 currentOrigin = (IVec2(gridX, gridY) * m_cellSize) + m_baseRandomOffset;
+
+	DE_ASSERT(currentOrigin.x() >= 0 && (currentOrigin.x() + m_cellSize.x()) <= m_targetSize.x());
+	DE_ASSERT(currentOrigin.y() >= 0 && (currentOrigin.y() + m_cellSize.y()) <= m_targetSize.y());
+
+	return currentOrigin;
+}
+
+IVec4 RandomizedRenderGrid::getUsedAreaBoundingBox (void) const
+{
+	const IVec2 lastCell	(de::min(m_currentCell + 1, m_grid.x()), ((m_currentCell + m_grid.x() - 1) / m_grid.x()));
+	const IVec2 size		= lastCell * m_cellSize;
+
+	return IVec4(m_baseRandomOffset.x(), m_baseRandomOffset.y(), size.x(), size.y());
+}
+
 class ImageInfo
 {
 public:
@@ -309,6 +402,182 @@
 	}
 }
 
+IVec3 getLevelSize (deUint32 target, const IVec3& baseSize, int level)
+{
+	IVec3 size;
+
+	if (target != GL_TEXTURE_2D_ARRAY)
+	{
+		for (int i = 0; i < 3; i++)
+			size[i] = de::max(baseSize[i] >> level, 1);
+	}
+	else
+	{
+		for (int i = 0; i < 2; i++)
+			size[i] = de::max(baseSize[i] >> level, 1);
+
+		size[2] = baseSize[2];
+	}
+
+	return size;
+}
+
+deUint32 mapFaceNdxToFace (int ndx)
+{
+	const deUint32 cubeFaces[] =
+	{
+		GL_TEXTURE_CUBE_MAP_POSITIVE_X,
+		GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
+
+		GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
+
+		GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
+		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+	};
+
+	return de::getSizedArrayElement<6>(cubeFaces, ndx);
+}
+
+// Class for iterating over mip levels and faces/slices/... of a texture.
+class TextureImageIterator
+{
+public:
+						TextureImageIterator	(const ImageInfo info, int levelCount);
+						~TextureImageIterator	(void)							{}
+
+	// Need to call next image once, newly constructed not readable, except for getSize
+	bool				nextImage				(void);
+	bool				hasNextImage			(void) const					{ return (m_currentLevel < (m_levelCount - 1)) || m_currentImage < (m_levelImageCount - 1); }
+
+	int					getMipLevel				(void) const					{ return m_currentLevel; }
+	int					getMipLevelCount		(void) const					{ return m_levelCount; }
+	int					getCurrentImage			(void) const					{ return m_currentImage;}
+	int					getLevelImageCount		(void) const					{ return m_levelImageCount; }
+	IVec2				getSize					(void) const					{ return m_levelSize.toWidth<2>(); }	// Assume that image sizes never grow over iteration
+	deUint32			getTarget				(void) const					{ return m_info.getTarget(); }
+
+private:
+	int					m_levelImageCount;		// Need to be defined in CTOR for the hasNextImage to work!
+	const ImageInfo		m_info;
+	int					m_currentLevel;
+	IVec3				m_levelSize;
+	int					m_currentImage;
+	const int			m_levelCount;
+};
+
+TextureImageIterator::TextureImageIterator (const ImageInfo info, int levelCount)
+	: m_levelImageCount	(info.getTarget() == GL_TEXTURE_CUBE_MAP ? 6 : getLevelSize(info.getTarget(), info.getSize(), 0).z())
+	, m_info			(info)
+	, m_currentLevel	(0)
+	, m_levelSize		(getLevelSize(info.getTarget(), info.getSize(), 0))
+	, m_currentImage	(-1)
+	, m_levelCount		(levelCount)
+{
+	DE_ASSERT(m_levelCount <= getLevelCount(info));
+}
+
+bool TextureImageIterator::nextImage (void)
+{
+	if (!hasNextImage())
+		return false;
+
+	m_currentImage++;
+	if (m_currentImage == m_levelImageCount)
+	{
+		m_currentLevel++;
+		m_currentImage		= 0;
+
+		m_levelSize			= getLevelSize(m_info.getTarget(), m_info.getSize(), m_currentLevel);
+
+		if (getTarget() == GL_TEXTURE_CUBE_MAP)
+			m_levelImageCount = 6;
+		else
+			m_levelImageCount = m_levelSize.z();
+	}
+	DE_ASSERT(m_currentLevel < m_levelCount);
+	DE_ASSERT(m_currentImage < m_levelImageCount);
+	return true;
+}
+
+// Get name
+string getTextureImageName (int textureTarget, int mipLevel, int imageIndex)
+{
+	std::ostringstream result;
+	result << "Level";
+	result << mipLevel;
+	switch (textureTarget)
+	{
+		case GL_TEXTURE_2D:			break;
+		case GL_TEXTURE_3D:			result << "Slice" << imageIndex; break;
+		case GL_TEXTURE_CUBE_MAP:	result << "Face" << imageIndex; break;
+		case GL_TEXTURE_2D_ARRAY:	result << "Layer" << imageIndex; break;
+		default:
+			DE_FATAL("Unsupported texture target");
+			break;
+	}
+	return result.str();
+}
+
+// Get description
+string getTextureImageDescription (int textureTarget, int mipLevel, int imageIndex)
+{
+	std::ostringstream result;
+	result << "level ";
+	result << mipLevel;
+
+	switch (textureTarget)
+	{
+		case GL_TEXTURE_2D:			break;
+		case GL_TEXTURE_3D:			result << " and Slice " << imageIndex; break;
+		case GL_TEXTURE_CUBE_MAP:	result << " and Face " << imageIndex; break;
+		case GL_TEXTURE_2D_ARRAY:	result << " and Layer " << imageIndex; break;
+		default:
+			DE_FATAL("Unsupported texture target");
+			break;
+	}
+	return result.str();
+}
+
+// Compute texture coordinates
+void computeQuadTexCoords(vector<float>& texCoord, const TextureImageIterator& iteration)
+{
+	const int currentImage = iteration.getCurrentImage();
+	switch (iteration.getTarget())
+	{
+		case GL_TEXTURE_2D:
+			computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
+			break;
+
+		case GL_TEXTURE_3D:
+		{
+			const float r = (float(currentImage) + 0.5f) / (float)iteration.getLevelImageCount();
+			computeQuadTexCoord3D(texCoord, tcu::Vec3(0.0f, 0.0f, r), tcu::Vec3(1.0f, 1.0f, r), tcu::IVec3(0, 1, 2));
+			break;
+		}
+
+		case GL_TEXTURE_CUBE_MAP:
+			computeQuadTexCoordCube(texCoord, glu::getCubeFaceFromGL(mapFaceNdxToFace(currentImage)));
+			break;
+
+		case GL_TEXTURE_2D_ARRAY:
+			computeQuadTexCoord2DArray(texCoord, currentImage, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
+			break;
+
+		default:
+			DE_FATAL("Unsupported texture target");
+	}
+}
+
+// Struct for storing each reference image with necessary metadata.
+struct CellContents
+{
+	IVec2			origin;
+	tcu::Surface	reference;
+	std::string		name;
+	std::string		description;
+};
+
 // Return format that has more restrictions on texel data.
 deUint32 getMoreRestrictiveFormat (deUint32 formatA, deUint32 formatB)
 {
@@ -358,26 +627,6 @@
 		return IVec3(1, 1, 1);
 }
 
-IVec3 getLevelSize (deUint32 target, const IVec3& baseSize, int level)
-{
-	IVec3 size;
-
-	if (target != GL_TEXTURE_2D_ARRAY)
-	{
-		for (int i = 0; i < 3; i++)
-			size[i] = de::max(baseSize[i] >> level, 1);
-	}
-	else
-	{
-		for (int i = 0; i < 2; i++)
-			size[i] = de::max(baseSize[i] >> level, 1);
-
-		size[2] = baseSize[2];
-	}
-
-	return size;
-}
-
 bool isColorRenderable (deUint32 format)
 {
 	switch (format)
@@ -502,23 +751,6 @@
 	return res;
 }
 
-deUint32 mapFaceNdxToFace (int ndx)
-{
-	const deUint32 cubeFaces[] =
-	{
-		GL_TEXTURE_CUBE_MAP_POSITIVE_X,
-		GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
-
-		GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
-		GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
-
-		GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
-		GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
-	};
-
-	return de::getSizedArrayElement<6>(cubeFaces, ndx);
-}
-
 deUint32 getFormatForInternalFormat (deUint32 format)
 {
 	return glu::getTransferFormat(glu::mapGLInternalFormat(format)).format;
@@ -891,22 +1123,119 @@
 				  srcImageData, srcImageInfo, srcLevel, srcPos, copySize);
 }
 
-void verifyTexture2DView (tcu::TestContext&			testContext,
+template<class TextureView>
+void renderTexture (glu::RenderContext&		renderContext,
+					TextureRenderer&		renderer,
+					ReferenceParams&		renderParams,
+					tcu::ResultCollector&	results,
+					de::Random&				rng,
+					const TextureView&		refTexture,
+					const Verify			verify,
+					TextureImageIterator&	imageIterator,
+					tcu::TestLog&			log)
+{
+	const tcu::RenderTarget&	renderTarget		= renderContext.getRenderTarget();
+	const tcu::RGBA				threshold			= renderTarget.getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
+	const glw::Functions&		gl					= renderContext.getFunctions();
+	const IVec2					renderTargetSize	= IVec2(renderTarget.getWidth(), renderTarget.getHeight());
+
+	while (imageIterator.hasNextImage())
+	{
+		// \note: Reserve space upfront to avoid assigning tcu::Surface, which incurs buffer mem copy. Using a
+		// conservative estimate for simplicity
+		const int				imagesOnLevel	= imageIterator.getLevelImageCount();
+		const int				imageEstimate	= (imageIterator.getMipLevelCount() - imageIterator.getMipLevel()) * imagesOnLevel;
+		RandomizedRenderGrid	renderGrid		(renderTargetSize, imageIterator.getSize(), imageEstimate, rng.getUint32());
+		vector<CellContents>	cellContents	(renderGrid.getCellCount());
+		int						cellsUsed		= 0;
+
+		// \note: Ordering of conditions is significant. If put the other way around, the code would skip one of the
+		// images if the grid runs out of cells before the texture runs out of images. Advancing one grid cell over the
+		// needed number has no negative impact.
+		while (renderGrid.nextCell() && imageIterator.nextImage())
+		{
+			const int		level	  = imageIterator.getMipLevel();
+			const IVec2		levelSize = imageIterator.getSize();
+			const IVec2		origin	  = renderGrid.getOrigin();
+			vector<float>	texCoord;
+
+			DE_ASSERT(imageIterator.getTarget() != GL_TEXTURE_CUBE_MAP || levelSize.x() >= 4 || levelSize.y() >= 4);
+
+			renderParams.baseLevel	= level;
+			renderParams.maxLevel	= level;
+
+			gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_BASE_LEVEL, level);
+			gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_MAX_LEVEL, level);
+
+			computeQuadTexCoords(texCoord, imageIterator);
+
+			// Setup base viewport.
+			gl.viewport(origin.x(), origin.y(), levelSize.x(), levelSize.y());
+
+			// Draw.
+			renderer.renderQuad(0, &texCoord[0], renderParams);
+			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render.");
+
+			if (verify == VERIFY_COMPARE_REFERENCE)
+			{
+				const int	target					= imageIterator.getTarget();
+				const int	imageIndex				= imageIterator.getCurrentImage();
+
+				cellContents[cellsUsed].origin		= origin;
+				cellContents[cellsUsed].name		= getTextureImageName(target, level, imageIndex);
+				cellContents[cellsUsed].description	= getTextureImageDescription(target, level, imageIndex);
+
+				cellContents[cellsUsed].reference.setSize(levelSize.x(), levelSize.y());
+
+				// Compute reference.
+				sampleTexture(tcu::SurfaceAccess(cellContents[cellsUsed].reference, renderContext.getRenderTarget().getPixelFormat()), refTexture, &texCoord[0], renderParams);
+				cellsUsed++;
+			}
+		}
+
+		if (cellsUsed > 0)
+		{
+			const IVec4		boundingBox		= renderGrid.getUsedAreaBoundingBox();
+			tcu::Surface	renderedFrame	(boundingBox[2], boundingBox[3]);
+
+			glu::readPixels(renderContext, boundingBox.x(), boundingBox.y(), renderedFrame.getAccess());
+			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to read pixels.");
+
+			for (int idx = 0; idx < cellsUsed; idx++)
+			{
+				const CellContents&					cell		 (cellContents[idx]);
+				const IVec2							cellOrigin	 = cell.origin - boundingBox.toWidth<2>();
+				const tcu::ConstPixelBufferAccess	resultAccess = getSubregion(renderedFrame.getAccess(), cellOrigin.x(), cellOrigin.y(), cell.reference.getWidth(), cell.reference.getHeight());
+
+				if (!intThresholdCompare(log, cell.name.c_str(), cell.description.c_str(), cell.reference.getAccess(), resultAccess, threshold.toIVec().cast<deUint32>(), tcu::COMPARE_LOG_ON_ERROR))
+					results.fail("Image comparison of " + cell.description + " failed.");
+				else
+					log << TestLog::Message << "Image comparison of " << cell.description << " passed." << TestLog::EndMessage;;
+			}
+		}
+	}
+
+	gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_BASE_LEVEL, 0);
+	gl.texParameteri(imageIterator.getTarget(), GL_TEXTURE_MAX_LEVEL, 1000);
+}
+
+void renderTexture2DView (tcu::TestContext&			testContext,
 						  glu::RenderContext&		renderContext,
 						  TextureRenderer&			renderer,
 						  tcu::ResultCollector&		results,
 						  de::Random&				rng,
 						  deUint32					name,
 						  const ImageInfo&			info,
-						  const tcu::Texture2DView&	refTexture)
+						  const tcu::Texture2DView&	refTexture,
+						  Verify					verify)
 {
 	tcu::TestLog&					log				= testContext.getLog();
 	const glw::Functions&			gl				= renderContext.getFunctions();
-	const tcu::RGBA					threshold		= renderContext.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
 	const tcu::TextureFormat		format			= refTexture.getLevel(0).getFormat();
 	const tcu::TextureFormatInfo	spec			= tcu::getTextureFormatInfo(format);
 
 	ReferenceParams					renderParams	(TEXTURETYPE_2D);
+	TextureImageIterator			imageIterator	(info, getLevelCount(info));
 
 	renderParams.samplerType	= getSamplerType(format);
 	renderParams.sampler		= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
@@ -923,43 +1252,7 @@
 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
 
-	for (int level = 0; level < getLevelCount(info); level++)
-	{
-		const IVec3				levelSize		= getLevelSize(info.getTarget(), info.getSize(), level);
-		const RandomViewport	viewport		(renderContext.getRenderTarget(), levelSize.x(), levelSize.y(), rng.getUint32());
-
-		vector<float>			texCoord;
-		tcu::Surface			renderedFrame	(viewport.width, viewport.height);
-		tcu::Surface			referenceFrame	(viewport.width, viewport.height);
-
-		renderParams.baseLevel	= level;
-		renderParams.maxLevel	= level;
-
-		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, level);
-		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, level);
-
-		computeQuadTexCoord2D(texCoord, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
-
-		// Setup base viewport.
-		gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
-
-		// Draw.
-		renderer.renderQuad(0, &texCoord[0], renderParams);
-		glu::readPixels(renderContext, viewport.x, viewport.y, renderedFrame.getAccess());
-		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render and read pixels.");
-
-		// Compute reference.
-		sampleTexture(tcu::SurfaceAccess(referenceFrame, renderContext.getRenderTarget().getPixelFormat()), refTexture, &texCoord[0], renderParams);
-
-		// Compare and log.
-		if (!pixelThresholdCompare(log, ("Level" + de::toString(level)).c_str(), ("Render level " + de::toString(level)).c_str(), referenceFrame, renderedFrame, threshold, tcu::COMPARE_LOG_ON_ERROR))
-			results.fail("Image comparison of level " + de::toString(level) + " failed.");
-		else
-			log << TestLog::Message << "Image comparison of level " << level << " passed." << TestLog::EndMessage;
-	}
-
-	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
-	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000);
+	renderTexture<tcu::Texture2DView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
 
 	gl.bindTexture(GL_TEXTURE_2D, 0);
 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
@@ -1016,14 +1309,15 @@
 	}
 }
 
-void verifyTexture2D (tcu::TestContext&						testContext,
+void renderTexture2D (tcu::TestContext&						testContext,
 					  glu::RenderContext&					renderContext,
 					  TextureRenderer&						textureRenderer,
 					  tcu::ResultCollector&					results,
 					  de::Random&							rng,
 					  deUint32								name,
 					  const vector<ArrayBuffer<deUint8> >&	data,
-					  const ImageInfo&						info)
+					  const ImageInfo&						info,
+					  Verify								verify)
 {
 	if (glu::isCompressedFormat(info.getFormat()))
 	{
@@ -1035,7 +1329,7 @@
 		{
 			const tcu::Texture2DView refTexture((int)levelAccesses.size(), &(levelAccesses[0]));
 
-			verifyTexture2DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+			renderTexture2DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
 		}
 	}
 	else
@@ -1043,26 +1337,27 @@
 		const vector<tcu::ConstPixelBufferAccess>	levelAccesses	= getLevelAccesses(data, info);
 		const tcu::Texture2DView					refTexture		((int)levelAccesses.size(), &(levelAccesses[0]));
 
-		verifyTexture2DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+		renderTexture2DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
 	}
 }
 
-void verifyTexture3DView (tcu::TestContext&			testContext,
+void renderTexture3DView (tcu::TestContext&			testContext,
 						  glu::RenderContext&		renderContext,
 						  TextureRenderer&			renderer,
 						  tcu::ResultCollector&		results,
 						  de::Random&				rng,
 						  deUint32					name,
 						  const ImageInfo&			info,
-						  const tcu::Texture3DView&	refTexture)
+						  const tcu::Texture3DView&	refTexture,
+						  Verify					verify)
 {
 	tcu::TestLog&					log				= testContext.getLog();
 	const glw::Functions&			gl				= renderContext.getFunctions();
-	const tcu::RGBA					threshold		= renderContext.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
 	const tcu::TextureFormat		format			= refTexture.getLevel(0).getFormat();
 	const tcu::TextureFormatInfo	spec			= tcu::getTextureFormatInfo(format);
 
 	ReferenceParams					renderParams	(TEXTURETYPE_3D);
+	TextureImageIterator			imageIterator	(info, getLevelCount(info));
 
 	renderParams.samplerType	= getSamplerType(format);
 	renderParams.sampler		= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
@@ -1080,60 +1375,21 @@
 	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
 
-	for (int level = 0; level < getLevelCount(info); level++)
-	{
-		const IVec3 levelSize = getLevelSize(info.getTarget(), info.getSize(), level);
-
-		renderParams.baseLevel	= level;
-		renderParams.maxLevel	= level;
-
-		gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, level);
-		gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, level);
-
-		for (int slice = 0; slice < levelSize.z(); slice++)
-		{
-			const RandomViewport	viewport		(renderContext.getRenderTarget(), levelSize.x(), levelSize.y(), rng.getUint32());
-			const float				r				= (float(slice) + 0.5f) / (float)levelSize.z();
-			tcu::Surface			renderedFrame	(viewport.width, viewport.height);
-			tcu::Surface			referenceFrame	(viewport.width, viewport.height);
-			vector<float>			texCoord;
-
-			computeQuadTexCoord3D(texCoord, tcu::Vec3(0.0f, 0.0f, r), tcu::Vec3(1.0f, 1.0f, r), tcu::IVec3(0, 1, 2));
-
-			// Setup base viewport.
-			gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
-
-			// Draw.
-			renderer.renderQuad(0, &texCoord[0], renderParams);
-			glu::readPixels(renderContext, viewport.x, viewport.y, renderedFrame.getAccess());
-			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render and read pixels.");
-
-			// Compute reference.
-			sampleTexture(tcu::SurfaceAccess(referenceFrame, renderContext.getRenderTarget().getPixelFormat()), refTexture, &texCoord[0], renderParams);
-
-			// Compare and log.
-			if (!pixelThresholdCompare(log, ("Level" + de::toString(level) + "Slice" + de::toString(slice)).c_str(), ("Render level " + de::toString(level) + ", Slice" + de::toString(slice)).c_str(), referenceFrame, renderedFrame, threshold, tcu::COMPARE_LOG_ON_ERROR))
-				results.fail("Image comparison of level " + de::toString(level) + " and slice " + de::toString(slice) + " failed.");
-			else
-				log << TestLog::Message << "Image comparison of level " << level << " and slice " << slice << " passed." << TestLog::EndMessage;;
-		}
-	}
-
-	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_BASE_LEVEL, 0);
-	gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAX_LEVEL, 1000);
+	renderTexture<tcu::Texture3DView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
 
 	gl.bindTexture(GL_TEXTURE_3D, 0);
 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
 }
 
-void verifyTexture3D (tcu::TestContext&						testContext,
+void renderTexture3D (tcu::TestContext&						testContext,
 					  glu::RenderContext&					renderContext,
 					  TextureRenderer&						textureRenderer,
 					  tcu::ResultCollector&					results,
 					  de::Random&							rng,
 					  deUint32								name,
 					  const vector<ArrayBuffer<deUint8> >&	data,
-					  const ImageInfo&						info)
+					  const ImageInfo&						info,
+				      Verify								verify)
 {
 	if (glu::isCompressedFormat(info.getFormat()))
 	{
@@ -1145,7 +1401,7 @@
 		{
 			const tcu::Texture3DView refTexture((int)levelAccesses.size(), &(levelAccesses[0]));
 
-			verifyTexture3DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+			renderTexture3DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
 		}
 	}
 	else
@@ -1153,26 +1409,28 @@
 		const vector<tcu::ConstPixelBufferAccess>	levelAccesses	= getLevelAccesses(data, info);
 		const tcu::Texture3DView					refTexture		((int)levelAccesses.size(), &(levelAccesses[0]));
 
-		verifyTexture3DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+		renderTexture3DView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
 	}
 }
 
-void verifyTextureCubemapView (tcu::TestContext&			testContext,
+void renderTextureCubemapView (tcu::TestContext&			testContext,
 							   glu::RenderContext&			renderContext,
 							   TextureRenderer&				renderer,
 							   tcu::ResultCollector&		results,
 							   de::Random&					rng,
 							   deUint32						name,
 							   const ImageInfo&				info,
-							   const tcu::TextureCubeView&	refTexture)
+							   const tcu::TextureCubeView&	refTexture,
+							   Verify						verify)
 {
 	tcu::TestLog&					log				= testContext.getLog();
 	const glw::Functions&			gl				= renderContext.getFunctions();
-	const tcu::RGBA					threshold		= renderContext.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
 	const tcu::TextureFormat		format			= refTexture.getLevelFace(0, tcu::CUBEFACE_POSITIVE_X).getFormat();
 	const tcu::TextureFormatInfo	spec			= tcu::getTextureFormatInfo(format);
 
 	ReferenceParams					renderParams	(TEXTURETYPE_CUBE);
+    // \note It seems we can't reliably sample two smallest texture levels with cubemaps
+	TextureImageIterator			imageIterator	(info, getLevelCount(info) - 2);
 
 	renderParams.samplerType	= getSamplerType(format);
 	renderParams.sampler		= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
@@ -1189,64 +1447,21 @@
 	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
 
-	for (int level = 0; level < getLevelCount(info); level++)
-	{
-		const IVec3 levelSize = getLevelSize(info.getTarget(), info.getSize(), level);
-
-		// \note It seems we can't reliably sample two smallest texture levels with cubemaps
-		if (levelSize.x() < 4 && levelSize.y() < 4)
-			continue;
-
-		renderParams.baseLevel	= level;
-		renderParams.maxLevel	= level;
-
-		gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, level);
-		gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, level);
-
-		for (int face = 0; face < 6; face++)
-		{
-			const RandomViewport	viewport		(renderContext.getRenderTarget(), levelSize.x(), levelSize.y(), rng.getUint32());
-			const string			cubemapFaceName	= glu::getCubeMapFaceStr(mapFaceNdxToFace(face)).toString();
-			tcu::Surface			renderedFrame	(viewport.width, viewport.height);
-			tcu::Surface			referenceFrame	(viewport.width, viewport.height);
-			vector<float>			texCoord;
-
-			computeQuadTexCoordCube(texCoord, glu::getCubeFaceFromGL(mapFaceNdxToFace(face)));
-
-			// Setup base viewport.
-			gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
-
-			// Draw.
-			renderer.renderQuad(0, &texCoord[0], renderParams);
-			glu::readPixels(renderContext, viewport.x, viewport.y, renderedFrame.getAccess());
-			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render and read pixels.");
-
-			// Compute reference.
-			sampleTexture(tcu::SurfaceAccess(referenceFrame, renderContext.getRenderTarget().getPixelFormat()), refTexture, &texCoord[0], renderParams);
-
-			// Compare and log.
-			if (!pixelThresholdCompare(log, ("Level" + de::toString(level) + "Face" + cubemapFaceName).c_str(), ("Render level " + de::toString(level) + ", Face " + cubemapFaceName).c_str(), referenceFrame, renderedFrame, threshold, tcu::COMPARE_LOG_ON_ERROR))
-				results.fail("Image comparison of level " + de::toString(level) + " and face " + cubemapFaceName + " failed.");
-			else
-				log << TestLog::Message << "Image comparison of level " << level << " and face " << cubemapFaceName << " passed." << TestLog::EndMessage;
-		}
-	}
-
-	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
-	gl.texParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 1000);
+	renderTexture<tcu::TextureCubeView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
 
 	gl.bindTexture(GL_TEXTURE_CUBE_MAP, 0);
 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
 }
 
-void verifyTextureCubemap (tcu::TestContext&					testContext,
+void renderTextureCubemap (tcu::TestContext&					testContext,
 						   glu::RenderContext&					renderContext,
 						   TextureRenderer&						textureRenderer,
 						   tcu::ResultCollector&				results,
 						   de::Random&							rng,
 						   deUint32								name,
 						   const vector<ArrayBuffer<deUint8> >&	data,
-						   const ImageInfo&						info)
+						   const ImageInfo&						info,
+						   Verify								verify)
 {
 	if (glu::isCompressedFormat(info.getFormat()))
 	{
@@ -1304,7 +1519,7 @@
 		{
 			const tcu::TextureCubeView refTexture(getLevelCount(info), levels);
 
-			verifyTextureCubemapView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+			renderTextureCubemapView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
 		}
 	}
 	else
@@ -1327,27 +1542,28 @@
 		{
 			const tcu::TextureCubeView refTexture(getLevelCount(info), levels);
 
-			verifyTextureCubemapView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+			renderTextureCubemapView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
 		}
 	}
 }
 
-void verifyTexture2DArrayView (tcu::TestContext&				testContext,
+void renderTexture2DArrayView (tcu::TestContext&				testContext,
 							   glu::RenderContext&				renderContext,
 							   TextureRenderer&					renderer,
 							   tcu::ResultCollector&			results,
 							   de::Random&						rng,
 							   deUint32							name,
 							   const ImageInfo&					info,
-							   const tcu::Texture2DArrayView&	refTexture)
+							   const tcu::Texture2DArrayView&	refTexture,
+							   Verify							verify)
 {
 	tcu::TestLog&					log				= testContext.getLog();
 	const glw::Functions&			gl				= renderContext.getFunctions();
-	const tcu::RGBA					threshold		= renderContext.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(1,1,1,1);
 	const tcu::TextureFormat		format			= refTexture.getLevel(0).getFormat();
 	const tcu::TextureFormatInfo	spec			= tcu::getTextureFormatInfo(format);
 
 	ReferenceParams					renderParams	(TEXTURETYPE_2D_ARRAY);
+	TextureImageIterator			imageIterator	(info, getLevelCount(info));
 
 	renderParams.samplerType	= getSamplerType(format);
 	renderParams.sampler		= Sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::NEAREST_MIPMAP_NEAREST, Sampler::NEAREST);
@@ -1364,59 +1580,21 @@
 	gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to setup texture filtering state.");
 
-	for (int level = 0; level < getLevelCount(info); level++)
-	{
-		const IVec3 levelSize = getLevelSize(info.getTarget(), info.getSize(), level);
-
-		renderParams.baseLevel	= level;
-		renderParams.maxLevel	= level;
-
-		gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, level);
-		gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, level);
-
-		for (int layer = 0; layer < levelSize.z(); layer++)
-		{
-			const RandomViewport	viewport		(renderContext.getRenderTarget(), levelSize.x(), levelSize.y(), rng.getUint32());
-			tcu::Surface			renderedFrame	(viewport.width, viewport.height);
-			tcu::Surface			referenceFrame	(viewport.width, viewport.height);
-			vector<float>			texCoord;
-
-			computeQuadTexCoord2DArray(texCoord, layer, tcu::Vec2(0.0f, 0.0f), tcu::Vec2(1.0f, 1.0f));
-
-			// Setup base viewport.
-			gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height);
-
-			// Draw.
-			renderer.renderQuad(0, &texCoord[0], renderParams);
-			glu::readPixels(renderContext, viewport.x, viewport.y, renderedFrame.getAccess());
-			GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to render and read pixels.");
-
-			// Compute reference.
-			sampleTexture(tcu::SurfaceAccess(referenceFrame, renderContext.getRenderTarget().getPixelFormat()), refTexture, &texCoord[0], renderParams);
-
-			// Compare and log.
-			if (!pixelThresholdCompare(log, ("Level" + de::toString(level) + "Layer" + de::toString(layer)).c_str(), ("Render level " + de::toString(level) + ", Layer" + de::toString(layer)).c_str(), referenceFrame, renderedFrame, threshold, tcu::COMPARE_LOG_ON_ERROR))
-				results.fail("Image comparison of level " + de::toString(level) + " and layer " + de::toString(layer) + " failed.");
-			else
-				log << TestLog::Message << "Image comparison of level " << level << " and layer " << layer << " passed." << TestLog::EndMessage;
-		}
-	}
-
-	gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_BASE_LEVEL, 0);
-	gl.texParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_LEVEL, 1000);
+	renderTexture<tcu::Texture2DArrayView>(renderContext, renderer, renderParams, results, rng, refTexture, verify, imageIterator, log);
 
 	gl.bindTexture(GL_TEXTURE_2D_ARRAY, 0);
 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind texture.");
 }
 
-void verifyTexture2DArray (tcu::TestContext&					testContext,
+void renderTexture2DArray (tcu::TestContext&					testContext,
 						   glu::RenderContext&					renderContext,
 						   TextureRenderer&						textureRenderer,
 						   tcu::ResultCollector&				results,
 						   de::Random&							rng,
 						   deUint32								name,
 						   const vector<ArrayBuffer<deUint8> >&	data,
-						   const ImageInfo&						info)
+						   const ImageInfo&						info,
+						   Verify								verify)
 {
 	if (glu::isCompressedFormat(info.getFormat()))
 	{
@@ -1428,7 +1606,7 @@
 		{
 			const tcu::Texture2DArrayView refTexture((int)levelAccesses.size(), &(levelAccesses[0]));
 
-			verifyTexture2DArrayView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+			renderTexture2DArrayView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
 		}
 	}
 	else
@@ -1436,7 +1614,7 @@
 		const vector<tcu::ConstPixelBufferAccess>	levelAccesses	= getLevelAccesses(data, info);
 		const tcu::Texture2DArrayView				refTexture		((int)levelAccesses.size(), &(levelAccesses[0]));
 
-		verifyTexture2DArrayView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture);
+		renderTexture2DArrayView(testContext, renderContext, textureRenderer, results, rng, name, info, refTexture, verify);
 	}
 }
 
@@ -1480,12 +1658,13 @@
 	}
 }
 
-void verifyRenderbuffer (tcu::TestContext&						testContext,
+void renderRenderbuffer (tcu::TestContext&						testContext,
 						 glu::RenderContext&					renderContext,
 						 tcu::ResultCollector&					results,
 						 deUint32								name,
 						 const vector<ArrayBuffer<deUint8> >&	data,
-						 const ImageInfo&						info)
+						 const ImageInfo&						info,
+						 Verify									verify)
 {
 	const glw::Functions&				gl					= renderContext.getFunctions();
 	TestLog&							log					= testContext.getLog();
@@ -1509,71 +1688,76 @@
 		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, name);
 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind and attach renderbuffer to framebuffer.");
 
-		glu::readPixels(renderContext, 0, 0, renderbuffer.getAccess());
+		if (verify)
+			glu::readPixels(renderContext, 0, 0, renderbuffer.getAccess());
 
 		gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
 		gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to unbind renderbuffer and framebuffer.");
 	}
 
-	if (isFloatFormat(info.getFormat()))
+	if (verify == VERIFY_COMPARE_REFERENCE)
 	{
-		const tcu::UVec4 threshold (2, 2, 2, 2);
+		if (isFloatFormat(info.getFormat()))
+		{
+			const tcu::UVec4 threshold (2, 2, 2, 2);
 
-		if (!(tcu::floatUlpThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
-			results.fail("Image comparison failed.");
-		else
-			log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
-	}
-	else if (isIntFormat(info.getFormat()) || isUintFormat(info.getFormat()))
-	{
-		const tcu::UVec4 threshold (1, 1, 1, 1);
+			if (!(tcu::floatUlpThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
+				results.fail("Image comparison failed.");
+			else
+				log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
+		}
+		else if (isIntFormat(info.getFormat()) || isUintFormat(info.getFormat()))
+		{
+			const tcu::UVec4 threshold (1, 1, 1, 1);
 
-		if (!(tcu::intThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
-			results.fail("Image comparison failed.");
+			if (!(tcu::intThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
+				results.fail("Image comparison failed.");
+			else
+				log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
+		}
 		else
-			log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
-	}
-	else
-	{
-		const Vec4 threshold = calculateThreshold(format, readPixelsFormat);
+		{
+			const Vec4 threshold = calculateThreshold(format, readPixelsFormat);
 
-		if (!(tcu::floatThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
-			results.fail("Image comparison failed.");
-		else
-			log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
+			if (!(tcu::floatThresholdCompare(log, "Image comparison", "Image comparison", refRenderbuffer, renderbuffer.getAccess(), threshold, tcu::COMPARE_LOG_ON_ERROR)))
+				results.fail("Image comparison failed.");
+			else
+				log << TestLog::Message << "Image comarison passed." << TestLog::EndMessage;
+		}
 	}
 }
 
-void verify (tcu::TestContext&						testContext,
+void render (tcu::TestContext&						testContext,
 			 glu::RenderContext&					renderContext,
 			 TextureRenderer&						textureRenderer,
 			 tcu::ResultCollector&					results,
 			 de::Random&							rng,
 			 deUint32								name,
 			 const vector<ArrayBuffer<deUint8> >&	data,
-			 const ImageInfo&						info)
+			 const ImageInfo&						info,
+			 Verify									verify)
 {
 	switch (info.getTarget())
 	{
 		case GL_TEXTURE_2D:
-			verifyTexture2D(testContext, renderContext, textureRenderer, results, rng, name, data, info);
+			renderTexture2D(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
 			break;
 
 		case GL_TEXTURE_3D:
-			verifyTexture3D(testContext, renderContext, textureRenderer, results, rng, name, data, info);
+			renderTexture3D(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
 			break;
 
 		case GL_TEXTURE_CUBE_MAP:
-			verifyTextureCubemap(testContext, renderContext, textureRenderer, results, rng, name, data, info);
+			renderTextureCubemap(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
 			break;
 
 		case GL_TEXTURE_2D_ARRAY:
-			verifyTexture2DArray(testContext, renderContext, textureRenderer, results, rng, name, data, info);
+			renderTexture2DArray(testContext, renderContext, textureRenderer, results, rng, name, data, info, verify);
 			break;
 
 		case GL_RENDERBUFFER:
-			verifyRenderbuffer(testContext, renderContext, results, name, data, info);
+			renderRenderbuffer(testContext, renderContext, results, name, data, info, verify);
 			break;
 
 		default:
@@ -1626,13 +1810,30 @@
 	TestCase::IterateResult	iterate					(void);
 
 private:
+
 	void					logTestInfoIter			(void);
 	void					createImagesIter		(void);
 	void					destroyImagesIter		(void);
 	void					verifySourceIter		(void);
 	void					verifyDestinationIter	(void);
+	void					renderSourceIter		(void);
+	void					renderDestinationIter	(void);
 	void					copyImageIter			(void);
 
+	typedef void (CopyImageTest::*IterationFunc)(void);
+
+	struct Iteration
+	{
+		Iteration (int methodCount_, const IterationFunc* methods_)
+			: methodCount	(methodCount_)
+			, methods		(methods_)
+		{
+		}
+
+		int						methodCount;
+		const IterationFunc*	methods;
+	};
+
 	struct State
 	{
 		State (int					seed,
@@ -1807,7 +2008,7 @@
 
 	log << TestLog::Message << "Verifying source image." << TestLog::EndMessage;
 
-	verify(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *srcImage, srcImageLevels, m_srcImageInfo);
+	render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *srcImage, srcImageLevels, m_srcImageInfo, VERIFY_COMPARE_REFERENCE);
 }
 
 void CopyImageTest::verifyDestinationIter (void)
@@ -1822,7 +2023,37 @@
 
 	log << TestLog::Message << "Verifying destination image." << TestLog::EndMessage;
 
-	verify(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *dstImage, dstImageLevels, m_dstImageInfo);
+	render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *dstImage, dstImageLevels, m_dstImageInfo, VERIFY_COMPARE_REFERENCE);
+}
+
+void CopyImageTest::renderSourceIter (void)
+{
+	TestLog&						log					= m_testCtx.getLog();
+	const tcu::ScopedLogSection		sourceSection		(log, "Source image verify.", "Source image verify.");
+
+	de::Random&						rng					= m_state->rng;
+	tcu::ResultCollector&			results				= m_state->results;
+	glu::ObjectWrapper&				srcImage			= *m_state->srcImage;
+	vector<ArrayBuffer<deUint8> >&	srcImageLevels		= m_state->srcImageLevels;
+
+	log << TestLog::Message << "Verifying source image." << TestLog::EndMessage;
+
+	render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *srcImage, srcImageLevels, m_srcImageInfo, VERIFY_NONE);
+}
+
+void CopyImageTest::renderDestinationIter (void)
+{
+	TestLog&						log					= m_testCtx.getLog();
+	const tcu::ScopedLogSection		destinationSection	(log, "Destination image verify.", "Destination image verify.");
+
+	de::Random&						rng					= m_state->rng;
+	tcu::ResultCollector&			results				= m_state->results;
+	glu::ObjectWrapper&				dstImage			= *m_state->dstImage;
+	vector<ArrayBuffer<deUint8> >&	dstImageLevels		= m_state->dstImageLevels;
+
+	log << TestLog::Message << "Verifying destination image." << TestLog::EndMessage;
+
+	render(m_testCtx, m_context.getRenderContext(), m_state->textureRenderer, results, rng, *dstImage, dstImageLevels, m_dstImageInfo, VERIFY_NONE);
 }
 
 struct Copy
@@ -1983,31 +2214,65 @@
 
 TestCase::IterateResult CopyImageTest::iterate (void)
 {
-	void(CopyImageTest::*methods[])(void) =
+	// Note: Returning from iterate() has two side-effects: it touches
+	// watchdog and calls eglSwapBuffers. For the first it's important
+	// to keep work per iteration reasonable to avoid
+	// timeouts. Because of the latter, it's prudent to do more than
+	// trivial amount of work. Otherwise we'll end up waiting for a
+	// new buffer in swap, it seems.
+
+	// The split below tries to combine trivial work with actually
+	// expensive rendering iterations without having too much
+	// rendering in one iteration to avoid timeouts.
+	const IterationFunc iteration1[] =
 	{
 		&CopyImageTest::logTestInfoIter,
-
-		// Render both images and then copy and verify again.
 		&CopyImageTest::createImagesIter,
-		&CopyImageTest::verifySourceIter,
-		&CopyImageTest::verifyDestinationIter,
+		&CopyImageTest::renderSourceIter
+	};
+	const IterationFunc iteration2[] =
+	{
+		&CopyImageTest::renderDestinationIter
+	};
+	const IterationFunc iteration3[] =
+	{
 		&CopyImageTest::copyImageIter,
-		&CopyImageTest::verifySourceIter,
-		&CopyImageTest::verifyDestinationIter,
-		&CopyImageTest::destroyImagesIter,
-
-		// Create images and immediately copies between thew and verify.
-		&CopyImageTest::createImagesIter,
-		&CopyImageTest::copyImageIter,
-		&CopyImageTest::verifySourceIter,
+		&CopyImageTest::verifySourceIter
+	};
+	const IterationFunc iteration4[] =
+	{
 		&CopyImageTest::verifyDestinationIter,
 		&CopyImageTest::destroyImagesIter
 	};
-
-	if (m_iteration < DE_LENGTH_OF_ARRAY(methods))
+	const IterationFunc iteration5[] =
 	{
-		(this->*methods[m_iteration])();
-		m_iteration++;
+		&CopyImageTest::createImagesIter,
+		&CopyImageTest::copyImageIter,
+		&CopyImageTest::verifySourceIter
+	};
+	const IterationFunc iteration6[] =
+	{
+		&CopyImageTest::verifyDestinationIter,
+		&CopyImageTest::destroyImagesIter
+	};
+	const Iteration iterations[] =
+	{
+		Iteration(DE_LENGTH_OF_ARRAY(iteration1), iteration1),
+		Iteration(DE_LENGTH_OF_ARRAY(iteration2), iteration2),
+		Iteration(DE_LENGTH_OF_ARRAY(iteration3), iteration3),
+		Iteration(DE_LENGTH_OF_ARRAY(iteration4), iteration4),
+		Iteration(DE_LENGTH_OF_ARRAY(iteration5), iteration5),
+		Iteration(DE_LENGTH_OF_ARRAY(iteration6), iteration6)
+	};
+
+	DE_ASSERT(m_iteration < DE_LENGTH_OF_ARRAY(iterations));
+	for (int method = 0; method < iterations[m_iteration].methodCount; method++)
+		(this->*iterations[m_iteration].methods[method])();
+
+	m_iteration++;
+
+	if (m_iteration < DE_LENGTH_OF_ARRAY(iterations))
+	{
 		return CONTINUE;
 	}
 	else
@@ -2130,11 +2395,11 @@
 
 			const string	targetTestName	= string(targetToName(srcTarget)) + "_to_" + targetToName(dstTarget);
 
-			const IVec3		targetSize2D	(128, 128, 1);
-			const IVec3		targetSize3D	(128, 128, 16);
-
-			const IVec3		srcSize			= getTestedSize(srcTarget, srcFormat, (srcIs3D ? targetSize3D : targetSize2D));
-			const IVec3		dstSize			= getTestedSize(dstTarget, dstFormat, (dstIs3D ? targetSize3D : targetSize2D));
+			// Compressed formats require more space to fit all block size combinations.
+			const bool		isCompressedCase	= glu::isCompressedFormat(srcFormat) || glu::isCompressedFormat(dstFormat);
+			const IVec3		targetSize			= isCompressedCase ? IVec3(128, 128, 16) : IVec3(64, 64, 8);
+			const IVec3		srcSize				= getTestedSize(srcTarget, srcFormat, targetSize);
+			const IVec3		dstSize				= getTestedSize(dstTarget, dstFormat, targetSize);
 
 			group->addChild(new CopyImageTest(root->getContext(),
 											ImageInfo(srcFormat, srcTarget, srcSize),
diff --git a/modules/gles31/functional/es31fDebugTests.cpp b/modules/gles31/functional/es31fDebugTests.cpp
index d6dde30..d41addb 100644
--- a/modules/gles31/functional/es31fDebugTests.cpp
+++ b/modules/gles31/functional/es31fDebugTests.cpp
@@ -34,8 +34,11 @@
 #include "es31fNegativeShaderImageLoadStoreTests.hpp"
 #include "es31fNegativeShaderFunctionTests.hpp"
 #include "es31fNegativeShaderDirectiveTests.hpp"
+#include "es31fNegativeSSBOBlockTests.hpp"
 #include "es31fNegativePreciseTests.hpp"
 #include "es31fNegativeAdvancedBlendEquationTests.hpp"
+#include "es31fNegativeShaderStorageTests.hpp"
+#include "es31fNegativeTessellationTests.hpp"
 
 #include "deUniquePtr.hpp"
 #include "deRandom.hpp"
@@ -2945,6 +2948,7 @@
 	const vector<FunctionContainer> fragmentFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativeFragmentApiTestFunctions());
 	const vector<FunctionContainer> vaFuncs					 = wrapCoreFunctions(NegativeTestShared::getNegativeVertexArrayApiTestFunctions());
 	const vector<FunctionContainer> stateFuncs				 = wrapCoreFunctions(NegativeTestShared::getNegativeStateApiTestFunctions());
+	const vector<FunctionContainer> tessellationFuncs		 = wrapCoreFunctions(NegativeTestShared::getNegativeTessellationTestFunctions());
 	const vector<FunctionContainer> atomicCounterFuncs		 = wrapCoreFunctions(NegativeTestShared::getNegativeAtomicCounterTestFunctions());
 	const vector<FunctionContainer> imageLoadFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageLoadTestFunctions());
 	const vector<FunctionContainer> imageStoreFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageStoreTestFunctions());
@@ -2952,8 +2956,10 @@
 	const vector<FunctionContainer> imageAtomicExchangeFuncs = wrapCoreFunctions(NegativeTestShared::getNegativeShaderImageAtomicExchangeTestFunctions());
 	const vector<FunctionContainer> shaderFunctionFuncs		 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderFunctionTestFunctions());
 	const vector<FunctionContainer> shaderDirectiveFuncs	 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderDirectiveTestFunctions());
+	const vector<FunctionContainer> ssboBlockFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativeSSBOBlockTestFunctions());
 	const vector<FunctionContainer> preciseFuncs			 = wrapCoreFunctions(NegativeTestShared::getNegativePreciseTestFunctions());
 	const vector<FunctionContainer> advancedBlendFuncs		 = wrapCoreFunctions(NegativeTestShared::getNegativeAdvancedBlendEquationTestFunctions());
+	const vector<FunctionContainer> shaderStorageFuncs		 = wrapCoreFunctions(NegativeTestShared::getNegativeShaderStorageTestFunctions());
 	const vector<FunctionContainer> externalFuncs			 = getUserMessageFuncs();
 
 	{
@@ -3057,8 +3063,11 @@
 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_image_exchange",		"Negative Shader Image Atomic Exchange API Cases",	imageAtomicExchangeFuncs));
 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_function",			"Negative Shader Function Cases",					shaderFunctionFuncs));
 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_directive",			"Negative Shader Directive Cases",					shaderDirectiveFuncs));
+			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "ssbo_block",					"Negative SSBO Block Cases",						ssboBlockFuncs));
 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "precise",					"Negative Precise Cases",							preciseFuncs));
 			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "advanced_blend",				"Negative Advanced Blend Equation Cases",			advancedBlendFuncs));
+			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "shader_storage",				"Negative Shader Storage Cases",					shaderStorageFuncs));
+			host->addChild(createChildCases(CASETYPE_CALLBACK, m_context, "tessellation",				"Negative Tessellation Cases",						tessellationFuncs));
 		}
 
 		{
@@ -3079,8 +3088,11 @@
 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_image_exchange",	"Negative Shader Image Atomic Exchange API Cases",	imageAtomicExchangeFuncs));
 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_function",			"Negative Shader Function Cases",					shaderFunctionFuncs));
 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_directive",		"Negative Shader Directive Cases",					shaderDirectiveFuncs));
+			host->addChild(createChildCases(CASETYPE_LOG, m_context, "ssbo_block",				"Negative SSBO Block Cases",						ssboBlockFuncs));
 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "precise",					"Negative Precise Cases",							preciseFuncs));
 			host->addChild(createChildCases(CASETYPE_LOG, m_context, "advanced_blend",			"Negative Advanced Blend Equation Cases",			advancedBlendFuncs));
+			host->addChild(createChildCases(CASETYPE_LOG, m_context, "shader_storage",			"Negative Shader Storage Cases",					shaderStorageFuncs));
+			host->addChild(createChildCases(CASETYPE_LOG, m_context, "tessellation",			"Negative Tessellation Cases",						tessellationFuncs));
 		}
 
 		{
@@ -3101,8 +3113,11 @@
 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_image_exchange",		"Negative Shader Image Atomic Exchange API Cases",	imageAtomicExchangeFuncs));
 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_function",			"Negative Shader Function Cases",					shaderFunctionFuncs));
 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_directive",			"Negative Shader Directive Cases",					shaderDirectiveFuncs));
+			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "ssbo_block",					"Negative SSBO Block Cases",						ssboBlockFuncs));
 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "precise",					"Negative Precise Cases",							preciseFuncs));
 			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "advanced_blend",				"Negative Advanced Blend Equation Cases",			advancedBlendFuncs));
+			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "shader_storage",				"Negative Shader Storage Cases",					shaderStorageFuncs));
+			host->addChild(createChildCases(CASETYPE_GETERROR, m_context, "tessellation",				"Negative Tessellation Cases",						tessellationFuncs));
 		}
 	}
 
diff --git a/modules/gles31/functional/es31fFunctionalTests.cpp b/modules/gles31/functional/es31fFunctionalTests.cpp
index 784e70c..b2bdac6 100644
--- a/modules/gles31/functional/es31fFunctionalTests.cpp
+++ b/modules/gles31/functional/es31fFunctionalTests.cpp
@@ -88,6 +88,7 @@
 #include "es31fCopyImageTests.hpp"
 #include "es31fDrawBuffersIndexedTests.hpp"
 #include "es31fDefaultVertexArrayObjectTests.hpp"
+#include "es31fSRGBDecodeTests.hpp"
 
 namespace deqp
 {
@@ -296,6 +297,20 @@
 	}
 };
 
+class SRGBTextureDecodeTests : public TestCaseGroup
+{
+public:
+	SRGBTextureDecodeTests (Context& context)
+		: TestCaseGroup (context, "srgb_texture_decode", "GL_EXT_texture_sRGB_decode tests")
+	{
+	}
+
+	void init (void)
+	{
+		addChild(new SRGBDecodeTests	(m_context));
+	}
+};
+
 FunctionalTests::FunctionalTests (Context& context)
 	: TestCaseGroup(context, "functional", "Functionality Tests")
 {
@@ -337,6 +352,7 @@
 	addChild(createCopyImageTests						(m_context));
 	addChild(createDrawBuffersIndexedTests				(m_context));
 	addChild(new DefaultVertexArrayObjectTests			(m_context));
+	addChild(new SRGBTextureDecodeTests					(m_context));
 }
 
 } // Functional
diff --git a/modules/gles31/functional/es31fIntegerStateQueryTests.cpp b/modules/gles31/functional/es31fIntegerStateQueryTests.cpp
index 104630b..461ef4d 100644
--- a/modules/gles31/functional/es31fIntegerStateQueryTests.cpp
+++ b/modules/gles31/functional/es31fIntegerStateQueryTests.cpp
@@ -873,7 +873,7 @@
 	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_tess_control_uniform_components_" + verifierSuffix).c_str(),			"Test MAX_TESS_CONTROL_UNIFORM_COMPONENTS",			GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS,			1024,	verifier,	glu::ApiType::es(3, 2)))
 	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_tess_control_texture_image_units_" + verifierSuffix).c_str(),			"Test MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS",		GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS,		16,		verifier,	glu::ApiType::es(3, 2)))
 	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_tess_control_output_components_" + verifierSuffix).c_str(),			"Test MAX_TESS_CONTROL_OUTPUT_COMPONENTS",			GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS,			64,		verifier,	glu::ApiType::es(3, 2)))
-	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_tess_control_total_output_components_" + verifierSuffix).c_str(),		"Test MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS",	GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS,	4096,	verifier,	glu::ApiType::es(3, 2)))
+	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_tess_control_total_output_components_" + verifierSuffix).c_str(),		"Test MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS",	GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS,	2048,	verifier,	glu::ApiType::es(3, 2)))
 	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_tess_control_input_components_" + verifierSuffix).c_str(),			"Test MAX_TESS_CONTROL_INPUT_COMPONENTS",			GL_MAX_TESS_CONTROL_INPUT_COMPONENTS,			64,		verifier,	glu::ApiType::es(3, 2)))
 	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_tess_control_uniform_blocks_" + verifierSuffix).c_str(),				"Test MAX_TESS_CONTROL_UNIFORM_BLOCKS",				GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS,				12,		verifier,	glu::ApiType::es(3, 2)))
 	FOR_EACH_VERIFIER(new MinimumValueCase(m_context,	(std::string() + "max_tess_control_atomic_counter_buffers_" + verifierSuffix).c_str(),		"Test MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS",		GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS,		0,		verifier,	glu::ApiType::es(3, 2)))
diff --git a/modules/gles31/functional/es31fLayoutBindingTests.cpp b/modules/gles31/functional/es31fLayoutBindingTests.cpp
index b11bcf3..242b43e 100644
--- a/modules/gles31/functional/es31fLayoutBindingTests.cpp
+++ b/modules/gles31/functional/es31fLayoutBindingTests.cpp
@@ -26,6 +26,7 @@
 #include "gluShaderProgram.hpp"
 #include "gluPixelTransfer.hpp"
 #include "gluTextureUtil.hpp"
+#include "gluContextInfo.hpp"
 
 #include "glwFunctions.hpp"
 #include "glwEnums.hpp"
@@ -71,7 +72,9 @@
 {
 	SHADERTYPE_VERTEX = 0,
 	SHADERTYPE_FRAGMENT,
-	SHADERTYPE_BOTH,
+	SHADERTYPE_TESS_CONTROL,
+	SHADERTYPE_TESS_EVALUATION,
+	SHADERTYPE_ALL,
 
 	SHADERTYPE_LAST,
 };
@@ -94,7 +97,7 @@
 	switch (shaderType)
 	{
 		case SHADERTYPE_VERTEX:
-		case SHADERTYPE_BOTH:
+		case SHADERTYPE_ALL:
 		{
 			std::ostringstream vertexShaderSource;
 			vertexShaderSource	<<	"#version 310 es\n"
@@ -114,6 +117,8 @@
 		}
 
 		case SHADERTYPE_FRAGMENT:
+		case SHADERTYPE_TESS_CONTROL:
+		case SHADERTYPE_TESS_EVALUATION:
 			return s_simpleVertexShaderSource;
 
 		default:
@@ -135,6 +140,8 @@
 	switch (shaderType)
 	{
 		case SHADERTYPE_VERTEX:
+		case SHADERTYPE_TESS_CONTROL:
+		case SHADERTYPE_TESS_EVALUATION:
 			return s_simpleFragmentShaderSource;
 
 		case SHADERTYPE_FRAGMENT:
@@ -153,7 +160,7 @@
 
 			return fragmentShaderSource.str();
 		}
-		case SHADERTYPE_BOTH:
+		case SHADERTYPE_ALL:
 		{
 			std::ostringstream fragmentShaderSource;
 			fragmentShaderSource	<<	"#version 310 es\n"
@@ -178,6 +185,96 @@
 	}
 }
 
+std::string generateTessControlShader (ShaderType shaderType, const std::string& shaderUniformDeclarations, const std::string& shaderBody)
+{
+	static const char* const s_simpleTessContorlShaderSource =	"#version 310 es\n"
+																"#extension GL_EXT_tessellation_shader : require\n"
+																"layout (vertices=3) out;\n"
+																"\n"
+																"void main (void)\n"
+																"{\n"
+																"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+																"}\n";
+
+	switch (shaderType)
+	{
+		case SHADERTYPE_VERTEX:
+		case SHADERTYPE_FRAGMENT:
+		case SHADERTYPE_TESS_EVALUATION:
+			return s_simpleTessContorlShaderSource;
+
+		case SHADERTYPE_TESS_CONTROL:
+		case SHADERTYPE_ALL:
+		{
+			std::ostringstream tessControlShaderSource;
+			tessControlShaderSource <<	"#version 310 es\n"
+									<<	"#extension GL_EXT_tessellation_shader : require\n"
+									<<	"layout (vertices=3) out;\n"
+									<<	"\n"
+									<<	"uniform highp int u_arrayNdx;\n\n"
+									<<	shaderUniformDeclarations << "\n"
+									<<	"void main (void)\n"
+									<<	"{\n"
+									<<	"	highp vec4 color;\n\n"
+									<<	shaderBody << "\n"
+									<<	"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+									<<	"}\n";
+
+			return tessControlShaderSource.str();
+		}
+
+		default:
+			DE_ASSERT(false);
+			return "";
+	}
+}
+
+std::string generateTessEvaluationShader (ShaderType shaderType, const std::string& shaderUniformDeclarations, const std::string& shaderBody)
+{
+	static const char* const s_simpleTessEvaluationShaderSource =	"#version 310 es\n"
+																	"#extension GL_EXT_tessellation_shader : require\n"
+																	"layout (triangles) in;\n"
+																	"\n"
+																	"void main (void)\n"
+																	"{\n"
+																	"	gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n"
+																	"}\n";
+
+	switch (shaderType)
+	{
+		case SHADERTYPE_VERTEX:
+		case SHADERTYPE_FRAGMENT:
+		case SHADERTYPE_TESS_CONTROL:
+			return s_simpleTessEvaluationShaderSource;
+
+		case SHADERTYPE_TESS_EVALUATION:
+		case SHADERTYPE_ALL:
+		{
+			std::ostringstream tessEvaluationShaderSource;
+			tessEvaluationShaderSource	<< "#version 310 es\n"
+										<< "#extension GL_EXT_tessellation_shader : require\n"
+										<< "layout (triangles) in;\n"
+										<< "\n"
+										<< "uniform highp int u_arrayNdx;\n\n"
+										<< shaderUniformDeclarations << "\n"
+										<< "out mediump vec4 v_color;\n"
+										<< "void main (void)\n"
+										<< "{\n"
+										<< "	highp vec4 color;\n\n"
+										<<	shaderBody << "\n"
+										<< "	v_color = color;\n"
+										<< "	gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position + gl_TessCoord[1] * gl_in[1].gl_Position + gl_TessCoord[2] * gl_in[2].gl_Position;\n"
+										<< "}\n";
+
+			return tessEvaluationShaderSource.str();
+		}
+
+		default:
+			DE_ASSERT(false);
+			return "";
+	}
+}
+
 std::string getUniformName (const std::string& name, int declNdx)
 {
 	return name + de::toString(declNdx);
@@ -320,7 +417,7 @@
 				maxUnits = maxFragmentUnits;
 				break;
 
-			case SHADERTYPE_BOTH:
+			case SHADERTYPE_ALL:
 				maxUnits = maxCombinedUnits/2;
 				break;
 
@@ -354,11 +451,11 @@
 		}
 
 		// Check that we have enough uniforms in different shaders to perform the tests
-		if ( ((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_BOTH)) && (maxVertexUnits < m_numBindings) )
+		if ( ((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_ALL)) && (maxVertexUnits < m_numBindings) )
 			throw tcu::NotSupportedError("Vertex shader: not enough uniforms available for test");
-		if ( ((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_BOTH)) && (maxFragmentUnits < m_numBindings) )
+		if ( ((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_ALL)) && (maxFragmentUnits < m_numBindings) )
 			throw tcu::NotSupportedError("Fragment shader: not enough uniforms available for test");
-		if ( (m_shaderType == SHADERTYPE_BOTH) && (maxCombinedUnits < m_numBindings*2) )
+		if ( (m_shaderType == SHADERTYPE_ALL) && (maxCombinedUnits < m_numBindings*2) )
 			throw tcu::NotSupportedError("Not enough uniforms available for test");
 
 		// Check that we have enough binding points to perform the tests
@@ -590,6 +687,8 @@
 																		 glw::GLenum		maxBindingPointEnum,
 																		 glw::GLenum		maxVertexUnitsEnum,
 																		 glw::GLenum		maxFragmentUnitsEnum,
+																		 glw::GLenum		maxTessCtrlUnitsEnum,
+																		 glw::GLenum		maxTessEvalUnitsEnum,
 																		 glw::GLenum		maxCombinedUnitsEnum,
 																		 const std::string& uniformName);
 	virtual								~LayoutBindingNegativeCase		(void);
@@ -608,11 +707,16 @@
 	const glw::GLenum					m_maxBindingPointEnum;
 	const glw::GLenum					m_maxVertexUnitsEnum;
 	const glw::GLenum					m_maxFragmentUnitsEnum;
+	const glw::GLenum					m_maxTessCtrlUnitsEnum;
+	const glw::GLenum					m_maxTessEvalUnitsEnum;
 	const glw::GLenum					m_maxCombinedUnitsEnum;
 	const std::string					m_uniformName;
 	glw::GLint							m_numBindings;
 	std::vector<glw::GLint>				m_vertexShaderBinding;
 	std::vector<glw::GLint>				m_fragmentShaderBinding;
+	std::vector<glw::GLint>				m_tessCtrlShaderBinding;
+	std::vector<glw::GLint>				m_tessEvalShaderBinding;
+	bool								m_tessSupport;
 
 private:
 	void								initBindingPoints				(int minBindingPoint, int numBindingPoints);
@@ -626,6 +730,8 @@
 													  ErrorType				errorType,
 													  glw::GLenum			maxBindingPointEnum,
 													  glw::GLenum			maxVertexUnitsEnum,
+													  glw::GLenum			maxTessCtrlUnitsEnum,
+													  glw::GLenum			maxTessEvalUnitsEnum,
 													  glw::GLenum			maxFragmentUnitsEnum,
 													  glw::GLenum			maxCombinedUnitsEnum,
 													  const std::string&	uniformName)
@@ -637,9 +743,12 @@
 	, m_maxBindingPointEnum		(maxBindingPointEnum)
 	, m_maxVertexUnitsEnum		(maxVertexUnitsEnum)
 	, m_maxFragmentUnitsEnum	(maxFragmentUnitsEnum)
+	, m_maxTessCtrlUnitsEnum	(maxTessCtrlUnitsEnum)
+	, m_maxTessEvalUnitsEnum	(maxTessEvalUnitsEnum)
 	, m_maxCombinedUnitsEnum	(maxCombinedUnitsEnum)
 	, m_uniformName				(uniformName)
 	, m_numBindings				(0)
+	, m_tessSupport				(false)
 {
 }
 
@@ -657,16 +766,27 @@
 	glw::GLint				maxVertexUnits		= 0;	// Available uniforms in the vertex shader
 	glw::GLint				maxFragmentUnits	= 0;	// Available uniforms in the fragment shader
 	glw::GLint				maxCombinedUnits	= 0;	// Available uniforms in all the shader stages combined
+	glw::GLint				maxTessCtrlUnits	= 0;	// Available uniforms in tessellation control shader
+	glw::GLint				maxTessEvalUnits	= 0;	// Available uniforms in tessellation evaluation shader
 	glw::GLint				maxUnits			= 0;	// Maximum available uniforms for this test
 
+	m_tessSupport = m_context.getContextInfo().isExtensionSupported("GL_EXT_tessellation_shader")
+					|| contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2));
+
+	int numShaderStages = (!m_tessSupport) ? 2 : 4;
+
 	gl.getIntegerv(m_maxVertexUnitsEnum, &maxVertexUnits);
 	gl.getIntegerv(m_maxFragmentUnitsEnum, &maxFragmentUnits);
+	gl.getIntegerv(m_maxTessCtrlUnitsEnum, &maxTessCtrlUnits);
+	gl.getIntegerv(m_maxTessEvalUnitsEnum, &maxTessEvalUnits);
 	gl.getIntegerv(m_maxCombinedUnitsEnum, &maxCombinedUnits);
 	gl.getIntegerv(m_maxBindingPointEnum, &numBindingPoints);
 	GLU_EXPECT_NO_ERROR(gl.getError(), "Querying available uniform numbers failed");
 
 	m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the vertex shader: " << maxVertexUnits << tcu::TestLog::EndMessage;
 	m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the fragment shader: " << maxFragmentUnits << tcu::TestLog::EndMessage;
+	m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the tessellation control shader: " << maxTessCtrlUnits << tcu::TestLog::EndMessage;
+	m_testCtx.getLog() << tcu::TestLog::Message << "Maximum units for uniform type in the tessellation evaluation shader: " << maxTessCtrlUnits << tcu::TestLog::EndMessage;
 	m_testCtx.getLog() << tcu::TestLog::Message << "Maximum combined units for uniform type: " << maxCombinedUnits << tcu::TestLog::EndMessage;
 	m_testCtx.getLog() << tcu::TestLog::Message << "Maximum binding point for uniform type: " << numBindingPoints-1 << tcu::TestLog::EndMessage;
 
@@ -681,8 +801,16 @@
 			maxUnits = maxFragmentUnits;
 			break;
 
-		case SHADERTYPE_BOTH:
-			maxUnits = de::min(de::min(maxVertexUnits, maxFragmentUnits), maxCombinedUnits/2);
+		case SHADERTYPE_ALL:
+			maxUnits = de::min(de::min(de::min(maxVertexUnits, maxFragmentUnits), de::min(maxTessCtrlUnits, maxTessEvalUnits)), maxCombinedUnits/numShaderStages);
+			break;
+
+		case SHADERTYPE_TESS_CONTROL:
+			maxUnits = maxTessCtrlUnits;
+			break;
+
+		case SHADERTYPE_TESS_EVALUATION:
+			maxUnits = maxTessEvalUnits;
 			break;
 
 		default:
@@ -720,11 +848,16 @@
 	}
 
 	// Check that we have enough uniforms in different shaders to perform the tests
-	if ( ((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_BOTH)) && (maxVertexUnits < m_numBindings) )
+	if ( ((m_shaderType == SHADERTYPE_VERTEX) || (m_shaderType == SHADERTYPE_ALL)) && (maxVertexUnits < m_numBindings) )
 		throw tcu::NotSupportedError("Vertex shader: not enough uniforms available for test");
-	if ( ((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_BOTH)) && (maxFragmentUnits < m_numBindings) )
+	if ( ((m_shaderType == SHADERTYPE_FRAGMENT) || (m_shaderType == SHADERTYPE_ALL)) && (maxFragmentUnits < m_numBindings) )
 		throw tcu::NotSupportedError("Fragment shader: not enough uniforms available for test");
-	if ( (m_shaderType == SHADERTYPE_BOTH) && (maxCombinedUnits < m_numBindings*2) )
+	if ( (m_tessSupport) && ((m_shaderType == SHADERTYPE_TESS_CONTROL) || (m_shaderType == SHADERTYPE_ALL)) && (maxTessCtrlUnits < m_numBindings) )
+		throw tcu::NotSupportedError("Tessellation control shader: not enough uniforms available for test");
+	if ( (m_tessSupport) && ((m_shaderType == SHADERTYPE_TESS_EVALUATION) || (m_shaderType == SHADERTYPE_ALL)) && (maxTessEvalUnits < m_numBindings) )
+		throw tcu::NotSupportedError("Tessellation evaluation shader: not enough uniforms available for test");
+
+	if ( (m_shaderType == SHADERTYPE_ALL) && (maxCombinedUnits < m_numBindings*numShaderStages) )
 		throw tcu::NotSupportedError("Not enough uniforms available for test");
 
 	// Check that we have enough binding points to perform the tests
@@ -767,8 +900,21 @@
 
 		case ERRORTYPE_LESS_THAN_ZERO:		// Out of bounds binding points should cause a compile-time error
 		case ERRORTYPE_OVER_MAX_UNITS:
-			if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk || !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT)).compileOk)
-				pass = true;
+			if (m_tessSupport)
+			{
+				if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk
+					|| !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk)
+					|| !(m_program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_CONTROL).compileOk)
+					|| !(m_program->getShaderInfo(glu::SHADERTYPE_TESSELLATION_EVALUATION)).compileOk)
+					pass = true;
+			}
+			else
+			{
+				if (!(m_program->getShaderInfo(glu::SHADERTYPE_VERTEX)).compileOk
+					|| !(m_program->getShaderInfo(glu::SHADERTYPE_FRAGMENT).compileOk))
+					pass = true;
+			}
+
 			failMessage = "Test failed - expected a compile-time error";
 			break;
 
@@ -794,6 +940,8 @@
 		{
 			m_vertexShaderBinding.push_back(numBindingPoints+1-m_numBindings);
 			m_fragmentShaderBinding.push_back(numBindingPoints+1-m_numBindings);
+			m_tessCtrlShaderBinding.push_back(numBindingPoints+1-m_numBindings);
+			m_tessEvalShaderBinding.push_back(numBindingPoints+1-m_numBindings);
 			break;
 		}
 
@@ -802,6 +950,8 @@
 			const glw::GLint binding = -rnd.getInt(1, m_numBindings);
 			m_vertexShaderBinding.push_back(binding);
 			m_fragmentShaderBinding.push_back(binding);
+			m_tessCtrlShaderBinding.push_back(binding);
+			m_tessEvalShaderBinding.push_back(binding);
 			break;
 		}
 
@@ -809,7 +959,15 @@
 		{
 			m_vertexShaderBinding.push_back(minBindingPoint);
 			m_fragmentShaderBinding.push_back((minBindingPoint+1)%numBindingPoints);
-			DE_ASSERT(m_vertexShaderBinding.back() != m_fragmentShaderBinding.back());
+			m_tessCtrlShaderBinding.push_back((minBindingPoint+2)%numBindingPoints);
+			m_tessEvalShaderBinding.push_back((minBindingPoint+3)%numBindingPoints);
+
+			DE_ASSERT(m_vertexShaderBinding.back()		!= m_fragmentShaderBinding.back());
+			DE_ASSERT(m_fragmentShaderBinding.back()	!= m_tessEvalShaderBinding.back());
+			DE_ASSERT(m_tessEvalShaderBinding.back()	!= m_tessCtrlShaderBinding.back());
+			DE_ASSERT(m_tessCtrlShaderBinding.back()	!= m_vertexShaderBinding.back());
+			DE_ASSERT(m_vertexShaderBinding.back()		!= m_tessEvalShaderBinding.back());
+			DE_ASSERT(m_tessCtrlShaderBinding.back()	!= m_fragmentShaderBinding.back());
 			break;
 		}
 
@@ -822,6 +980,8 @@
 	{
 		m_vertexShaderBinding.push_back(m_vertexShaderBinding.front()+ndx);
 		m_fragmentShaderBinding.push_back(m_fragmentShaderBinding.front()+ndx);
+		m_tessCtrlShaderBinding.push_back(m_tessCtrlShaderBinding.front()+ndx);
+		m_tessEvalShaderBinding.push_back(m_tessCtrlShaderBinding.front()+ndx);
 	}
 }
 
@@ -1052,7 +1212,19 @@
 														TestType		testType,
 														ErrorType		errorType,
 														glw::GLenum		samplerType)
-	: LayoutBindingNegativeCase		(context, name, desc, shaderType, testType, errorType, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, GL_MAX_TEXTURE_IMAGE_UNITS, GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, "u_sampler")
+	: LayoutBindingNegativeCase		(context,
+									 name,
+									 desc,
+									 shaderType,
+									 testType,
+									 errorType,
+									 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
+									 GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS,
+									 GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS,
+									 GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS,
+									 GL_MAX_TEXTURE_IMAGE_UNITS,
+									 GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
+									 "u_sampler")
 	, m_samplerType					(samplerType)
 {
 }
@@ -1066,6 +1238,8 @@
 {
 	std::ostringstream		vertexUniformDecl;
 	std::ostringstream		fragmentUniformDecl;
+	std::ostringstream		tessCtrlUniformDecl;
+	std::ostringstream		tessEvalUniformDecl;
 	std::ostringstream		shaderBody;
 
 	const std::string		texCoordType	= glu::getDataTypeName(getSamplerTexCoordType());
@@ -1080,6 +1254,10 @@
 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
 		fragmentUniformDecl << "layout(binding = " << m_fragmentShaderBinding[declNdx] << ") uniform highp " << samplerType
 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
+		tessCtrlUniformDecl << "layout(binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform highp " << samplerType
+			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
+		tessEvalUniformDecl << "layout(binding = " << m_tessEvalShaderBinding[declNdx] << ") uniform highp " << samplerType
+			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
 	}
 
 	// Generate the shader body for the vertex and fragment shaders
@@ -1096,9 +1274,16 @@
 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
 				<< "	}\n";
 
-	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
+	glu::ProgramSources sources = glu::ProgramSources()
 				<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
-				<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str())));
+				<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
+
+	if (m_tessSupport)
+		sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
+				<< glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
+
+	return new glu::ShaderProgram(m_context.getRenderContext(), sources);
+
 }
 
 glu::DataType SamplerBindingNegativeCase::getSamplerTexCoordType(void) const
@@ -1351,7 +1536,19 @@
 													TestType		testType,
 													ErrorType		errorType,
 													glw::GLenum		imageType)
-	: LayoutBindingNegativeCase		(context, name, desc, shaderType, testType, errorType, GL_MAX_IMAGE_UNITS, GL_MAX_VERTEX_IMAGE_UNIFORMS, GL_MAX_FRAGMENT_IMAGE_UNIFORMS, GL_MAX_COMBINED_IMAGE_UNIFORMS, "u_image")
+	: LayoutBindingNegativeCase		(context,
+									 name,
+									 desc,
+									 shaderType,
+									 testType,
+									 errorType,
+									 GL_MAX_IMAGE_UNITS,
+									 GL_MAX_VERTEX_IMAGE_UNIFORMS,
+									 GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS,
+									 GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS,
+									 GL_MAX_FRAGMENT_IMAGE_UNIFORMS,
+									 GL_MAX_COMBINED_IMAGE_UNIFORMS,
+									 "u_image")
 	, m_imageType					(imageType)
 {
 }
@@ -1365,6 +1562,8 @@
 {
 	std::ostringstream		vertexUniformDecl;
 	std::ostringstream		fragmentUniformDecl;
+	std::ostringstream		tessCtrlUniformDecl;
+	std::ostringstream		tessEvalUniformDecl;
 	std::ostringstream		shaderBody;
 
 	const std::string		texCoordType	= glu::getDataTypeName(getImageTexCoordType());
@@ -1379,6 +1578,10 @@
 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
 		fragmentUniformDecl << "layout(rgba8, binding = " << m_fragmentShaderBinding[declNdx] << ") uniform readonly highp " << imageType
 			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
+		tessCtrlUniformDecl << "layout(rgba8, binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform readonly highp " << imageType
+			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
+		tessEvalUniformDecl << "layout(rgba8, binding = " << m_tessEvalShaderBinding[declNdx] << ") uniform readonly highp " << imageType
+			<< " " << (arrayInstance ? getUniformName(m_uniformName, declNdx, m_numBindings) : getUniformName(m_uniformName, declNdx)) << ";\n";
 	}
 
 	// Generate the shader body for the vertex and fragment shaders
@@ -1395,9 +1598,15 @@
 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
 				<< "	}\n";
 
-	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
-					<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
-					<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str())));
+	glu::ProgramSources sources = glu::ProgramSources()
+				<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
+				<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
+
+	if (m_tessSupport)
+		sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
+				<< glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
+
+	return new glu::ShaderProgram(m_context.getRenderContext(), sources);
 }
 
 glu::DataType ImageBindingNegativeCase::getImageTexCoordType(void) const
@@ -1596,7 +1805,19 @@
 												ShaderType		shaderType,
 												TestType		testType,
 												ErrorType		errorType)
-	: LayoutBindingNegativeCase(context, name, desc, shaderType, testType, errorType, GL_MAX_UNIFORM_BUFFER_BINDINGS, GL_MAX_VERTEX_UNIFORM_BLOCKS, GL_MAX_FRAGMENT_UNIFORM_BLOCKS, GL_MAX_COMBINED_UNIFORM_BLOCKS, "ColorBlock")
+	: LayoutBindingNegativeCase(context,
+								name,
+								desc,
+								shaderType,
+								testType,
+								errorType,
+								GL_MAX_UNIFORM_BUFFER_BINDINGS,
+								GL_MAX_VERTEX_UNIFORM_BLOCKS,
+								GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS,
+								GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS,
+								GL_MAX_FRAGMENT_UNIFORM_BLOCKS,
+								GL_MAX_COMBINED_UNIFORM_BLOCKS,
+								"ColorBlock")
 {
 }
 
@@ -1609,6 +1830,8 @@
 {
 	std::ostringstream		vertexUniformDecl;
 	std::ostringstream		fragmentUniformDecl;
+	std::ostringstream		tessCtrlUniformDecl;
+	std::ostringstream		tessEvalUniformDecl;
 	std::ostringstream		shaderBody;
 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
 	const int				numDeclarations = (arrayInstance ? 1 : m_numBindings);
@@ -1629,6 +1852,20 @@
 			<< "	highp vec4 color1;\n"
 			<< "	highp vec4 color2;\n"
 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
+
+		tessCtrlUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform "
+			<< getUniformName(m_uniformName, declNdx) << "\n"
+			<< "{\n"
+			<< "	highp vec4 color1;\n"
+			<< "	highp vec4 color2;\n"
+			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
+
+		tessEvalUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") uniform "
+			<< getUniformName(m_uniformName, declNdx) << "\n"
+			<< "{\n"
+			<< "	highp vec4 color1;\n"
+			<< "	highp vec4 color2;\n"
+			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
 	}
 
 	// Generate the shader body for the vertex and fragment shaders
@@ -1646,9 +1883,15 @@
 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
 				<< "	}\n";
 
-	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
-					<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
-					<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str())));
+	glu::ProgramSources sources = glu::ProgramSources()
+				<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
+				<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
+
+	if (m_tessSupport)
+		sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
+				<< glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
+
+	return new glu::ShaderProgram(m_context.getRenderContext(), sources);
 }
 
 
@@ -1831,7 +2074,19 @@
 												  ShaderType shaderType,
 												  TestType testType,
 												  ErrorType errorType)
-	: LayoutBindingNegativeCase(context, name, desc, shaderType, testType, errorType, GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS, GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, "ColorBuffer")
+	: LayoutBindingNegativeCase(context,
+								name,
+								desc,
+								shaderType,
+								testType,
+								errorType,
+								GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS,
+								GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS,
+								GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS,
+								GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS,
+								GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS,
+								GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS,
+								"ColorBuffer")
 {
 }
 
@@ -1844,6 +2099,8 @@
 {
 	std::ostringstream		vertexUniformDecl;
 	std::ostringstream		fragmentUniformDecl;
+	std::ostringstream		tessCtrlUniformDecl;
+	std::ostringstream		tessEvalUniformDecl;
 	std::ostringstream		shaderBody;
 	const bool				arrayInstance	= (m_testType == TESTTYPE_BINDING_ARRAY || m_testType == TESTTYPE_BINDING_MAX_ARRAY);
 	const int				numDeclarations = (arrayInstance ? 1 : m_numBindings);
@@ -1864,6 +2121,20 @@
 			<< "	highp vec4 color1;\n"
 			<< "	highp vec4 color2;\n"
 			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
+
+		tessCtrlUniformDecl << "layout(std140, binding = " << m_tessCtrlShaderBinding[declNdx] << ") buffer "
+			<< getUniformName(m_uniformName, declNdx) << "\n"
+			<< "{\n"
+			<< "	highp vec4 color1;\n"
+			<< "	highp vec4 color2;\n"
+			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
+
+		tessEvalUniformDecl << "layout(std140, binding = " << m_tessEvalShaderBinding[declNdx] << ") buffer "
+			<< getUniformName(m_uniformName, declNdx) << "\n"
+			<< "{\n"
+			<< "	highp vec4 color1;\n"
+			<< "	highp vec4 color2;\n"
+			<< "} " << (arrayInstance ? getUniformName("colors", declNdx, m_numBindings) : getUniformName("colors", declNdx)) << ";\n";
 	}
 
 	// Generate the shader body for the vertex and fragment shaders
@@ -1881,9 +2152,15 @@
 				<< "		color = vec4(0.0, 0.0, 0.0, 1.0);\n"
 				<< "	}\n";
 
-	return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources()
-					<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
-					<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str())));
+	glu::ProgramSources sources = glu::ProgramSources()
+				<< glu::VertexSource(generateVertexShader(m_shaderType, vertexUniformDecl.str(), shaderBody.str()))
+				<< glu::FragmentSource(generateFragmentShader(m_shaderType, fragmentUniformDecl.str(), shaderBody.str()));
+
+	if (m_tessSupport)
+		sources << glu::TessellationControlSource(generateTessControlShader(m_shaderType, tessCtrlUniformDecl.str(), shaderBody.str()))
+				<< glu::TessellationEvaluationSource(generateTessEvaluationShader(m_shaderType, tessEvalUniformDecl.str(), shaderBody.str()));
+
+	return new glu::ShaderProgram(m_context.getRenderContext(), sources);
 }
 
 
@@ -1956,18 +2233,26 @@
 		std::string								descPostfix;
 	} s_negativeTestTypes[] =
 	{
-		{ SHADERTYPE_VERTEX,	TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"vertex_binding_over_max",			"over maximum binding point"},
-		{ SHADERTYPE_FRAGMENT,	TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"fragment_binding_over_max",		"over maximum binding point"},
-		{ SHADERTYPE_VERTEX,	TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"vertex_binding_neg",				"negative binding point"},
-		{ SHADERTYPE_FRAGMENT,	TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"fragment_binding_neg",				"negative binding point"},
+		{ SHADERTYPE_VERTEX,			TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"vertex_binding_over_max",					"over maximum binding point"   },
+		{ SHADERTYPE_FRAGMENT,			TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"fragment_binding_over_max",				"over maximum binding point"   },
+		{ SHADERTYPE_TESS_CONTROL,		TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"tess_control_binding_over_max",			"over maximum binding point"   },
+		{ SHADERTYPE_TESS_EVALUATION,	TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"tess_evaluation_binding_over_max",			"over maximum binding point"   },
+		{ SHADERTYPE_VERTEX,			TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"vertex_binding_neg",						"negative binding point"	   },
+		{ SHADERTYPE_FRAGMENT,			TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"fragment_binding_neg",						"negative binding point"	   },
+		{ SHADERTYPE_TESS_CONTROL,		TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"tess_control_binding_neg",					"negative binding point"	   },
+		{ SHADERTYPE_TESS_EVALUATION,	TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"tess_evaluation_binding_neg",				"negative binding point"	   },
 
-		{ SHADERTYPE_VERTEX,	TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"vertex_binding_over_max_array",	"over maximum binding point"},
-		{ SHADERTYPE_FRAGMENT,	TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"fragment_binding_over_max_array",	"over maximum binding point"},
-		{ SHADERTYPE_VERTEX,	TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"vertex_binding_neg_array",			"negative binding point"},
-		{ SHADERTYPE_FRAGMENT,	TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"fragment_binding_neg_array",		"negative binding point"},
+		{ SHADERTYPE_VERTEX,			TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"vertex_binding_over_max_array",			"over maximum binding point"   },
+		{ SHADERTYPE_FRAGMENT,			TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"fragment_binding_over_max_array",			"over maximum binding point"   },
+		{ SHADERTYPE_TESS_CONTROL,		TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"tess_control_binding_over_max_array",		"over maximum binding point"   },
+		{ SHADERTYPE_TESS_EVALUATION,	TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_OVER_MAX_UNITS,	"tess_evaluation_binding_over_max_array",	"over maximum binding point"   },
+		{ SHADERTYPE_VERTEX,			TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"vertex_binding_neg_array",					"negative binding point"	   },
+		{ SHADERTYPE_FRAGMENT,			TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"fragment_binding_neg_array",				"negative binding point"	   },
+		{ SHADERTYPE_TESS_CONTROL,		TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"tess_control_binding_neg_array",			"negative binding point"	   },
+		{ SHADERTYPE_TESS_EVALUATION,	TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_LESS_THAN_ZERO,	"tess_evaluation_binding_neg_array",		"negative binding point"	   },
 
-		{ SHADERTYPE_BOTH,		TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY,		"binding_contradictory",			"contradictory binding points"},
-		{ SHADERTYPE_BOTH,		TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY,		"binding_contradictory_array",		"contradictory binding points"},
+		{ SHADERTYPE_ALL,				TESTTYPE_BINDING_SINGLE,		LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY,		"binding_contradictory",					"contradictory binding points" },
+		{ SHADERTYPE_ALL,				TESTTYPE_BINDING_ARRAY,			LayoutBindingNegativeCase::ERRORTYPE_CONTRADICTORY,		"binding_contradictory_array",				"contradictory binding points" },
 	};
 
 	// Render tests
diff --git a/modules/gles31/functional/es31fNegativeBufferApiTests.cpp b/modules/gles31/functional/es31fNegativeBufferApiTests.cpp
index e4b67cd..309a507 100644
--- a/modules/gles31/functional/es31fNegativeBufferApiTests.cpp
+++ b/modules/gles31/functional/es31fNegativeBufferApiTests.cpp
@@ -446,15 +446,19 @@
 		ctx.endSection();
 
 		ctx.beginSection("GL_INVALID_VALUE is generated if target is GL_ATOMIC_COUNTER_BUFFER and offset is not multiples of 4.");
-		ctx.glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, bufTF, 5, 0);
+		ctx.glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, bufTF, 5, 4);
 		ctx.expectError(GL_INVALID_VALUE);
 		ctx.endSection();
 
-		ctx.beginSection("GL_INVALID_VALUE is generated if target is GL_SHADER_STORAGE_BUFFER and offset is not a multiple of the value of GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT.");
 		ctx.glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssAlignment);
-		ctx.glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, bufTF, ssAlignment+1, 0);
-		ctx.expectError(GL_INVALID_VALUE);
-		ctx.endSection();
+
+		if (ssAlignment != 1)
+		{
+			ctx.beginSection("GL_INVALID_VALUE is generated if target is GL_SHADER_STORAGE_BUFFER and offset is not a multiple of the value of GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT.");
+			ctx.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, 0, bufTF, ssAlignment+1, 4);
+			ctx.expectError(GL_INVALID_VALUE);
+			ctx.endSection();
+		}
 	}
 
 	ctx.glDeleteBuffers(1, &bufU);
@@ -497,24 +501,6 @@
 	ctx.expectError(GL_INVALID_VALUE);
 	ctx.endSection();
 
-	if (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)))
-	{
-		int maxACize = 0x1234;
-		int maxSSize = 0x1234;
-
-		ctx.beginSection("GL_INVALID_VALUE is generated if target is GL_ATOMIC_COUNTER_BUFFER and index is greater than or equal to GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS.");
-		ctx.glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &maxACize);
-		ctx.glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, maxACize, bufU, 0, 4);
-		ctx.expectError(GL_INVALID_VALUE);
-		ctx.endSection();
-
-		ctx.beginSection("GL_INVALID_VALUE is generated if target is GL_SHADER_STORAGE_BUFFER and index is greater than or equal to GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS.");
-		ctx.glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxSSize);
-		ctx.glBindBufferRange(GL_SHADER_STORAGE_BUFFER, maxSSize, bufU, 0, 4);
-		ctx.expectError(GL_INVALID_VALUE);
-		ctx.endSection();
-	}
-
 	ctx.glDeleteBuffers(1, &bufU);
 	ctx.glDeleteBuffers(1, &bufTF);
 }
diff --git a/modules/gles31/functional/es31fNegativeSSBOBlockTests.cpp b/modules/gles31/functional/es31fNegativeSSBOBlockTests.cpp
new file mode 100644
index 0000000..bddd035
--- /dev/null
+++ b/modules/gles31/functional/es31fNegativeSSBOBlockTests.cpp
@@ -0,0 +1,617 @@
+/*-------------------------------------------------------------------------
+* drawElements Quality Program OpenGL ES 3.1 Module
+* -------------------------------------------------
+*
+* Copyright 2016 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 Negative Shader Storage Buffer Object (SSBO) tests.
+*//*--------------------------------------------------------------------*/
+#include "es31fNegativeSSBOBlockTests.hpp"
+#include "glwDefs.hpp"
+#include "glwEnums.hpp"
+#include "tcuStringTemplate.hpp"
+#include "gluShaderProgram.hpp"
+#include <map>
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+namespace
+{
+using tcu::TestLog;
+using glu::CallLogWrapper;
+using namespace glw;
+namespace args
+{
+enum ArgMember
+{
+	ARGMEMBER_FORMAT			=	0,
+	ARGMEMBER_BINDING_POINT,
+	ARGMEMBER_MATRIX_ORDER,
+	ARGMEMBER_MEMBER_TYPE,
+	ARGMEMBER_NAME,
+	ARGMEMBER_FIXED_ARRAY,
+	ARGMEMBER_VARIABLE_ARRAY,
+	ARGMEMBER_REORDER
+};
+
+// key pair ssbo arg data
+struct SsboArgData
+{
+	ArgMember	member;
+	std::string	data;
+
+	SsboArgData(const ArgMember& member_, const std::string& data_)
+	{
+		member	=	member_;
+		data	=	data_;
+	}
+};
+
+// class which manages string based argument used to build varying ssbo interface blocks and members
+class SsboArgs
+{
+public:
+					SsboArgs(const std::string version, tcu::TestLog& log);
+
+	void			setSingleValue						(const SsboArgData argData);
+	bool			setAllValues						(const std::vector<SsboArgData> argDataList);
+
+	const std::string&	getContextVersion				(void) const;
+	const std::string&	getStdFormat					(void) const;
+	const std::string&	getBindingPoint					(void) const;
+	const std::string&	getMatrixOrder					(void) const;
+	const std::string&	getMemberType					(void) const;
+	const std::string&	getMemberName					(void) const;
+	const std::string&	getMemberFixedArrayName			(void) const;
+	const std::string&	getMemberVariableArray			(void) const;
+	bool				getMemberReorder				(void) const;
+	int					getNumberMembers				(void) const;
+
+	void				resetValues						(void);
+
+	std::map<std::string, std::string>	populateArgsMap	(void) const;
+
+private:
+	std::string		m_negativeContextVersion;
+	std::string		m_stdFormat;
+	std::string		m_bindingPoint;
+	std::string		m_matrixOrder;
+	std::string		m_memberType;
+	std::string		m_memberName;
+	std::string		m_memberFixedArrayerName;
+	std::string		m_memberVariableArray;
+	bool			m_memberReorder;
+	int				m_numberMembers;
+	tcu::TestLog&	m_testLog;
+
+	void			setDefaultValues					(void);
+};
+
+//constructor which ensure a proper context is passed into the struct
+SsboArgs::SsboArgs(const std::string version, tcu::TestLog& log)
+	: m_negativeContextVersion	(version)
+	, m_numberMembers			(8)
+	, m_testLog					(log)
+{
+	setDefaultValues();
+}
+
+void SsboArgs::setSingleValue (const SsboArgData argData)
+{
+	std::string message;
+
+	switch (argData.member)
+	{
+		case ARGMEMBER_FORMAT:
+			m_stdFormat					=	argData.data;
+			return;
+		case ARGMEMBER_BINDING_POINT:
+			m_bindingPoint				=	argData.data;
+			return;
+		case ARGMEMBER_MATRIX_ORDER:
+			m_matrixOrder				=	argData.data;
+			return;
+		case ARGMEMBER_MEMBER_TYPE:
+			m_memberType				=	argData.data;
+			return;
+		case ARGMEMBER_NAME:
+			m_memberName				=	argData.data;
+			return;
+		case ARGMEMBER_FIXED_ARRAY:
+			m_memberFixedArrayerName	=	argData.data;
+			return;
+		case ARGMEMBER_VARIABLE_ARRAY:
+			m_memberVariableArray		=	argData.data;
+			return;
+		case ARGMEMBER_REORDER:
+			if (argData.data == "true")
+			{
+				m_memberReorder			=	true;
+			}
+			return;
+		default:
+			message = "auto loop argument data member not recognised.";
+			m_testLog << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+	}
+}
+
+bool SsboArgs::setAllValues (const std::vector<SsboArgData> argDataList)
+{
+	std::string	message;
+
+	if ((argDataList.size() == 0) || (argDataList.size() > (size_t)m_numberMembers))
+	{
+		message = "set of args does not match the number of args struct changeable members.";
+		m_testLog << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+		return false;
+	}
+	else
+	{
+		for (unsigned int idx = 0; idx < argDataList.size(); idx++)
+		{
+			setSingleValue(argDataList[idx]);
+		}
+	}
+
+	return true;
+}
+
+const std::string& SsboArgs::getContextVersion (void) const
+{
+	return m_negativeContextVersion;
+}
+
+const std::string& SsboArgs::getStdFormat (void) const
+{
+	return m_stdFormat;
+}
+
+const std::string& SsboArgs::getBindingPoint (void) const
+{
+	return m_bindingPoint;
+}
+
+const std::string& SsboArgs::getMatrixOrder (void) const
+{
+	return m_matrixOrder;
+}
+
+const std::string& SsboArgs::getMemberType (void) const
+{
+	return m_memberType;
+}
+
+const std::string& SsboArgs::getMemberName (void) const
+{
+	return m_memberName;
+}
+
+const std::string& SsboArgs::getMemberFixedArrayName (void) const
+{
+	return m_memberFixedArrayerName;
+}
+
+const std::string& SsboArgs::getMemberVariableArray (void) const
+{
+	return m_memberVariableArray;
+}
+
+bool SsboArgs::getMemberReorder (void) const
+{
+	return m_memberReorder;
+}
+
+int SsboArgs::getNumberMembers (void) const
+{
+	return m_numberMembers;
+}
+
+void SsboArgs::resetValues (void)
+{
+	setDefaultValues();
+}
+
+//converts SsboArgs member variable into a map object to be used by tcu::StringTemplate
+std::map<std::string, std::string> SsboArgs::populateArgsMap (void) const
+{
+	std::map<std::string, std::string> argsMap;
+
+	// key placeholders located at specific points in the ssbo block
+	argsMap["NEGATIVE_CONTEXT_VERSION"]	=	m_negativeContextVersion;
+	argsMap["STD_FORMAT"]				=	m_stdFormat;
+	argsMap["BINDING_POINT"]			=	m_bindingPoint;
+	argsMap["MATRIX_ORDER"]				=	m_matrixOrder;
+	argsMap["MEMBER_TYPE"]				=	m_memberType;
+	argsMap["MEMBER_NAME"]				=	m_memberName;
+	argsMap["MEMBER_FIXED_ARRAY"]		=	m_memberFixedArrayerName;
+	argsMap["MEMBER_VARIABLE_ARRAY"]	=	m_memberVariableArray;
+
+	return argsMap;
+}
+
+// default values i.e. same shader template
+void SsboArgs::setDefaultValues (void)
+{
+	m_stdFormat					=	"std430";
+	m_bindingPoint				=	"0";
+	m_matrixOrder				=	"column_major";
+	m_memberType				=	"int";
+	m_memberName				=	"matrix";
+	m_memberFixedArrayerName	=	"10";
+	m_memberVariableArray		=	"";
+	m_memberReorder				=	false;
+}
+} // args
+
+std::string generateVaryingSSBOShader(const glw::GLenum shaderType, const args::SsboArgs& args, tcu::TestLog& log)
+{
+	std::map<std::string, std::string>	argsMap;
+	std::ostringstream					source;
+	std::string							sourceString;
+	std::stringstream					ssboString;
+	std::string							message;
+
+	if (args.getMemberReorder())
+	{
+		ssboString	<< "	mediump vec4 array_1[${MEMBER_FIXED_ARRAY}];\n"
+					<< "	highp mat4 ${MEMBER_NAME};\n"
+					<< "	lowp ${MEMBER_TYPE} data;\n"
+					<< "	mediump float array_2[${MEMBER_VARIABLE_ARRAY}];\n";
+	}
+	else
+	{
+		ssboString	<< "	lowp ${MEMBER_TYPE} data;\n"
+					<< "	highp mat4 ${MEMBER_NAME};\n"
+					<< "	mediump vec4 array_1[${MEMBER_FIXED_ARRAY}];\n"
+					<< "	mediump float array_2[${MEMBER_VARIABLE_ARRAY}];\n";
+	}
+
+	argsMap = args.populateArgsMap();
+
+	switch (shaderType)
+	{
+		case GL_VERTEX_SHADER:
+		{
+			source	<< "${NEGATIVE_CONTEXT_VERSION}\n"
+					<< "layout (location = 0) in highp vec4 position;\n"
+					<< "layout (location = 1) in mediump vec4 colour;\n"
+					<< "out mediump vec4 vertex_colour;\n"
+					<< "layout (${STD_FORMAT}, binding = ${BINDING_POINT}, ${MATRIX_ORDER}) buffer ssbo_block\n"
+					<< "{\n";
+
+			source << ssboString.str();
+
+			source	<< "} ssbo;\n"
+					<< "void main()\n"
+					<< "{\n"
+					<< "	mediump vec4 variable;\n"
+					<< "	gl_Position = ssbo.${MEMBER_NAME} * position;\n"
+					<< "	for (int idx = 0; idx < ${MEMBER_FIXED_ARRAY}; idx++)\n"
+					<< "	{\n"
+					<< "		variable += ssbo.array_1[idx];\n"
+					<< "	}\n"
+					<< "	vertex_colour = colour + variable;\n"
+					<< "}\n";
+
+			sourceString = source.str();
+			sourceString = tcu::StringTemplate(sourceString).specialize(argsMap);
+
+			return sourceString;
+		}
+
+		case GL_FRAGMENT_SHADER:
+		{
+			source	<< "${NEGATIVE_CONTEXT_VERSION}\n"
+					<< "in mediump vec4 vertex_colour;\n"
+					<< "layout (location = 0) out mediump vec4 fragment_colour;\n"
+					<< "layout (${STD_FORMAT}, binding = ${BINDING_POINT}, ${MATRIX_ORDER}) buffer ssbo_block\n"
+					<< "{\n";
+
+			source << ssboString.str();
+
+			source	<< "} ssbo;\n"
+					<< "void main()\n"
+					<< "{\n"
+					<< "	mediump vec4 variable;\n"
+					<< "	variable * ssbo.${MEMBER_NAME};\n"
+					<< "	for (int idx = 0; idx < ${MEMBER_FIXED_ARRAY}; idx++)\n"
+					<< "	{\n"
+					<< "		variable += ssbo.array_1[idx];\n"
+					<< "	}\n"
+					<< "	fragment_colour = vertex_colour + variable;\n"
+					<< "}\n";
+
+			sourceString = source.str();
+			sourceString = tcu::StringTemplate(sourceString).specialize(argsMap);
+
+			return sourceString;
+		}
+
+		case GL_GEOMETRY_SHADER:
+		{
+			// TODO:
+			return sourceString;
+		}
+
+		case GL_TESS_CONTROL_SHADER:
+		{
+			// TODO:
+			return sourceString;
+		}
+
+		case GL_TESS_EVALUATION_SHADER:
+		{
+			// TODO:
+			return sourceString;
+		}
+
+		case GL_COMPUTE_SHADER:
+		{
+			// TODO:
+			return sourceString;
+		}
+
+		default:
+		{
+			message = "shader type not recognised.";
+			log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+		}
+	}
+
+	return std::string();
+}
+
+void logProgramInfo(NegativeTestContext& ctx, GLint program)
+{
+	GLint			maxLength	=	0;
+	std::string		message;
+	tcu::TestLog&	log			=	ctx.getLog();
+
+	ctx.glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
+
+	message = "Program log:";
+	log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+	if (maxLength == 0)
+	{
+		message = "No available info log.";
+		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+		return;
+	}
+
+	std::vector<GLchar> infoLog(maxLength);
+	ctx.glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
+
+	std::string programLogMessage(&infoLog[0], maxLength);
+	log << tcu::TestLog::Message << programLogMessage << tcu::TestLog::EndMessage;
+}
+
+void ssbo_block_matching(NegativeTestContext& ctx)
+{
+	const bool				isES32													=	contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+	const glu::GLSLVersion	version													=	isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
+	tcu::TestLog&			log														=	ctx.getLog();
+	std::string				message;
+	std::string				versionString(glu::getGLSLVersionDeclaration(version));
+	args::SsboArgs			ssboArgs(versionString, log);
+	GLint					shaderVertexGL;
+	std::string				shaderVertexString;
+	const char*				shaderVertexCharPtr;
+
+	// List of arguments used to create varying ssbo objects in the fragment shader
+	const args::SsboArgData argDataArrayFrag[] = {	args::SsboArgData(args::ARGMEMBER_FORMAT,			"std140"),
+													args::SsboArgData(args::ARGMEMBER_BINDING_POINT,	"10"),
+													args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER,		"row_major"),
+													args::SsboArgData(args::ARGMEMBER_MEMBER_TYPE,		"vec2"),
+													args::SsboArgData(args::ARGMEMBER_NAME,				"name_changed"),
+													args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY,		"20"),
+													args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY,	"5"),
+													args::SsboArgData(args::ARGMEMBER_REORDER,			"true") };
+	std::vector<args::SsboArgData> argDataVectorFrag(argDataArrayFrag, argDataArrayFrag + sizeof(argDataArrayFrag) / sizeof(argDataArrayFrag[0]));
+
+	// create default vertex shader
+	shaderVertexString = generateVaryingSSBOShader(GL_VERTEX_SHADER, ssboArgs, log);
+	shaderVertexCharPtr = shaderVertexString.c_str();
+	shaderVertexGL = ctx.glCreateShader(GL_VERTEX_SHADER);
+
+	// log
+	message = shaderVertexString;
+	log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+	// compile
+	ctx.glShaderSource(shaderVertexGL, 1, &shaderVertexCharPtr, DE_NULL);
+	ctx.glCompileShader(shaderVertexGL);
+
+	for (std::size_t idx = 0; idx < argDataVectorFrag.size(); ++idx)
+	{
+		GLint			linkStatus				=	-1;
+		GLint			program;
+		GLint			shaderFragmentGL;
+		std::string		shaderFragmentString;
+		const char*		shaderFragmentCharPtr;
+
+		ctx.beginSection("Multiple shaders created using SSBO's sharing the same name but not matching layouts");
+
+		program = ctx.glCreateProgram();
+
+		// reset args to default and make a single change
+		ssboArgs.resetValues();
+		ssboArgs.setSingleValue(argDataVectorFrag[idx]);
+
+		// create fragment shader
+		shaderFragmentString = generateVaryingSSBOShader(GL_FRAGMENT_SHADER, ssboArgs, log);
+		shaderFragmentCharPtr = shaderFragmentString.c_str();
+		shaderFragmentGL = ctx.glCreateShader(GL_FRAGMENT_SHADER);
+
+		// log
+		message = shaderFragmentString;
+		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+		// compile
+		ctx.glShaderSource(shaderFragmentGL, 1, &shaderFragmentCharPtr, DE_NULL);
+		ctx.glCompileShader(shaderFragmentGL);
+
+		// attach shaders to program and attempt to link
+		ctx.glAttachShader(program, shaderVertexGL);
+		ctx.glAttachShader(program, shaderFragmentGL);
+		ctx.glLinkProgram(program);
+		ctx.glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+
+		logProgramInfo(ctx, program);
+
+		if (linkStatus == GL_TRUE)
+		{
+			ctx.fail("Program should not have linked");
+		}
+
+		// clean up resources
+		ctx.glDeleteShader(shaderFragmentGL);
+		ctx.glDeleteProgram(program);
+
+		ctx.endSection();
+	}
+
+	// clean up default resources
+	ctx.glDeleteShader(shaderVertexGL);
+}
+
+void ssbo_block_shared_qualifier(NegativeTestContext& ctx)
+{
+	const bool				isES32													=	contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+	const glu::GLSLVersion	version													=	isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
+	tcu::TestLog&			log														=	ctx.getLog();
+	std::string				message;
+	std::string				versionString(glu::getGLSLVersionDeclaration(version));
+	args::SsboArgs			ssboArgs(versionString, log);
+	bool					result;
+	GLint					shaderVertexGL;
+	std::string				shaderVertexString;
+	const char*				shaderVertexCharPtr;
+
+	// default args used in vertex shader ssbo
+	const args::SsboArgData argDataArrayVert[] = {	args::SsboArgData(args::ARGMEMBER_FORMAT,			"shared"),
+													args::SsboArgData(args::ARGMEMBER_BINDING_POINT,	"0"),
+													args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER,		"column_major"),
+													args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY,		"10"),
+													args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY,	"10"),
+													args::SsboArgData(args::ARGMEMBER_REORDER,			"false") };
+	std::vector<args::SsboArgData> argDataVectorVert(argDataArrayVert, argDataArrayVert + sizeof(argDataArrayVert) / sizeof(argDataArrayVert[0]));
+
+	// args changed in fragment shader ssbo
+	const args::SsboArgData argDataArrayFrag[] = {	args::SsboArgData(args::ARGMEMBER_MATRIX_ORDER,		"row_major"),
+													args::SsboArgData(args::ARGMEMBER_VARIABLE_ARRAY,	""),
+													args::SsboArgData(args::ARGMEMBER_FIXED_ARRAY,		"20") };
+	std::vector<args::SsboArgData> argDataVectorFrag(argDataArrayFrag, argDataArrayFrag + sizeof(argDataArrayFrag) / sizeof(argDataArrayFrag[0]));
+
+	// set default vertex ssbo args
+	result = ssboArgs.setAllValues(argDataVectorVert);
+
+	if (result == false)
+	{
+		message = "Invalid use of args.setAllValues()";
+		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+		return;
+	}
+
+	// create default vertex shader
+	shaderVertexString = generateVaryingSSBOShader(GL_VERTEX_SHADER, ssboArgs, log);
+	shaderVertexCharPtr = shaderVertexString.c_str();
+	shaderVertexGL = ctx.glCreateShader(GL_VERTEX_SHADER);
+
+	// log
+	message = shaderVertexString;
+	log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+	// compile
+	ctx.glShaderSource(shaderVertexGL, 1, &shaderVertexCharPtr, DE_NULL);
+	ctx.glCompileShader(shaderVertexGL);
+
+	for (std::size_t idx = 0; idx < argDataVectorFrag.size(); idx++)
+	{
+		GLint		linkStatus				=	-1;
+		GLint		program;
+		GLint		shaderFragmentGL;
+		std::string	shaderFragmentString;
+		const char*	shaderFragmentCharPtr;
+
+		ctx.beginSection("Multiple shaders created using SSBO's sharing the same name but not matching layouts");
+
+		program = ctx.glCreateProgram();
+
+		// reset args to default and make a single change
+		ssboArgs.setAllValues(argDataVectorVert);
+		ssboArgs.setSingleValue(argDataVectorFrag[idx]);
+
+		// create fragment shader
+		shaderFragmentString = generateVaryingSSBOShader(GL_FRAGMENT_SHADER, ssboArgs, log);
+		shaderFragmentCharPtr = shaderFragmentString.c_str();
+		shaderFragmentGL = ctx.glCreateShader(GL_FRAGMENT_SHADER);
+
+		// log
+		message = shaderFragmentString;
+		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+
+		// compile
+		ctx.glShaderSource(shaderFragmentGL, 1, &shaderFragmentCharPtr, DE_NULL);
+		ctx.glCompileShader(shaderFragmentGL);
+
+		// attach shaders to the program and attempt to link
+		ctx.glAttachShader(program, shaderVertexGL);
+		ctx.glAttachShader(program, shaderFragmentGL);
+		ctx.glLinkProgram(program);
+		ctx.glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
+
+		logProgramInfo(ctx, program);
+
+		if (linkStatus == GL_TRUE)
+		{
+			ctx.fail("Program should not have linked");
+		}
+
+		// clean up resources
+		ctx.glDeleteShader(shaderFragmentGL);
+		ctx.glDeleteProgram(program);
+
+		ctx.endSection();
+	}
+
+	// clean up default resources
+	ctx.glDeleteShader(shaderVertexGL);
+}
+} // anonymous
+
+std::vector<FunctionContainer> getNegativeSSBOBlockTestFunctions (void)
+{
+	const FunctionContainer funcs[] =
+	{
+		{ ssbo_block_matching,			"ssbo_block_interface_matching_tests",	"Invalid Shader Linkage" },
+		{ ssbo_block_shared_qualifier,	"ssbo_using_shared_qualifier_tests",	"Invalid Shader Linkage" },
+	};
+
+	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
+}
+} // NegativeTestShared
+} //Functional
+} //gles31
+} //deqp
diff --git a/modules/gles31/functional/es31fNegativeSSBOBlockTests.hpp b/modules/gles31/functional/es31fNegativeSSBOBlockTests.hpp
new file mode 100644
index 0000000..db1d3bb
--- /dev/null
+++ b/modules/gles31/functional/es31fNegativeSSBOBlockTests.hpp
@@ -0,0 +1,44 @@
+#ifndef _ES31FNEGATIVESSBOBLOCKTESTS_HPP
+#define _ES31FNEGATIVESSBOBLOCKTESTS_HPP
+/*-------------------------------------------------------------------------
+* drawElements Quality Program OpenGL ES 3.1 Module
+* -------------------------------------------------
+*
+* Copyright 2016 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 Negative Shader Storage Block Object (SSBO) API tests.
+*//*--------------------------------------------------------------------*/
+#include "tcuDefs.hpp"
+#include "es31fNegativeTestShared.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+
+std::vector<FunctionContainer> getNegativeSSBOBlockTestFunctions (void);
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FNEGATIVESSBOBLOCKTESTS_HPP
\ No newline at end of file
diff --git a/modules/gles31/functional/es31fNegativeShaderApiTests.cpp b/modules/gles31/functional/es31fNegativeShaderApiTests.cpp
index 7c3fc0f..a80d6ca 100644
--- a/modules/gles31/functional/es31fNegativeShaderApiTests.cpp
+++ b/modules/gles31/functional/es31fNegativeShaderApiTests.cpp
@@ -2334,7 +2334,7 @@
 	}
 }
 
-void compile_compute_shader_helper (NegativeTestContext& ctx, const char** computeShaderSource, GLint* compileStatus)
+void compile_compute_shader_helper (NegativeTestContext& ctx, const char* const* computeShaderSource, GLint* compileStatus)
 {
 	GLuint shader = ctx.glCreateShader(GL_COMPUTE_SHADER);
 
@@ -2351,68 +2351,155 @@
 	ctx.beginSection("Compile Computer Shader");
 
 	{
-		const char* computeShaderSource		=	"#version 300 es\n"
-												"void main (void)\n"
-												"{\n"
-												"}\n\0";
+		const char* const computeShaderSource		=	"#version 300 es\n"
+														"void main (void)\n"
+														"{\n"
+														"}\n";
 
 		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
 		if (compileStatus != GL_FALSE)
 			ctx.fail("Compute Shader should not have compiled with #version 300 es.");
 	}
 	{
-		const char* computeShaderSource		=	"#version 310 es\n"
-												"buffer SSBO { vec4 data }"
-												"void main (void)\n"
-												"{\n"
-												"}\n\0";
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"buffer SSBO { vec4 data }"
+														"void main (void)\n"
+														"{\n"
+														"}\n";
 
 		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
 		if (compileStatus != GL_FALSE)
 			ctx.fail("Compute Shader should not have compiled: incorrect SSBO syntax.");
 	}
 	{
-		const char* computeShaderSource		=	"#version 310 es\n"
-												"buffer SSBO { vec4 data;};"
-												"uniform mat4 data;"
-												"void main (void)\n"
-												"{\n"
-												"}\n\0";
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"buffer SSBO { vec4 data;};"
+														"uniform mat4 data;"
+														"void main (void)\n"
+														"{\n"
+														"}\n";
 
 		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
 		if (compileStatus != GL_FALSE)
 			ctx.fail("Compute Shader should not have compiled: buffer variable redefinition.");
 	}
 	{
-		const char* computeShaderSource		=	"#version 310 es\n"
-												"buffer SSBO { vec4 data[]; vec4 moreData;};"
-												"void main (void)\n"
-												"{\n"
-												"}\n\0";
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"buffer SSBO { vec4 data[]; vec4 moreData;};"
+														"void main (void)\n"
+														"{\n"
+														"}\n";
 
 		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
 		if (compileStatus != GL_FALSE)
 			ctx.fail("Compute Shader should not have compiled: unspecified length buffer member not at the end.");
 	}
 	{
-		const char* computeShaderSource		=	"#version 310 es\n"
-												"in vec4 data;"
-												"void main (void)\n"
-												"{\n"
-												"}\n\0";
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"in vec4 data;"
+														"void main (void)\n"
+														"{\n"
+														"}\n";
 
 		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
 		if (compileStatus != GL_FALSE)
 			ctx.fail("Compute Shader should not have compiled: input qualifier used.");
 	}
 	{
-		const char* computeShaderSource		=	"#version 310 es\n"
-												"shared uint data = 0;";
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"shared uint data = 0;";
 
 		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
 		if (compileStatus != GL_FALSE)
 			ctx.fail("Compute Shader should not have compiled: shared-qualified variable initialized.");
 	}
+	{
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"buffer SSBO { vec4 data; vec4 moreData[];} ssbo;"
+														"void test (vec4 data[10]) {}"
+														"void main (void)\n"
+														"{\n"
+														"    test(ssbo.moreData);"
+														"}\n";
+
+		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+		if (compileStatus != GL_FALSE)
+			ctx.fail("Compute Shader should not have compiled: unspecified length buffer member passed as argument to function.");
+	}
+	{
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"buffer SSBO { vec4 data; vec4 moreData[];} ssbo;"
+														"void main (void)\n"
+														"{\n"
+														"    vec4 var = ssbo.moreData[-1];"
+														"}\n";
+
+		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+		if (compileStatus != GL_FALSE)
+			ctx.fail("Compute Shader should not have compiled: unspecified length buffer member indexed with negative constant expression.");
+	}
+	{
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"layout(binding=-1) buffer SSBO { vec4 data;};"
+														"void main (void)\n"
+														"{\n"
+														"}\n";
+
+		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+		if (compileStatus != GL_FALSE)
+			ctx.fail("Compute Shader should not have compiled: binding point less than zero.");
+	}
+	{
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"layout(binding=1) buffer;"
+														"layout(binding=2) buffer SSBO { vec4 data;};"
+														"void main (void)\n"
+														"{\n"
+														"}\n";
+
+		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+		if (compileStatus != GL_FALSE)
+			ctx.fail("Compute Shader should not have compiled: binding point specified for global scope.");
+	}
+	{
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"buffer SSBO {"
+														"	layout(binding=1) vec4 data;"
+														"	layout(binding=2) vec4 moreData[];"
+														"} ssbo;"
+														"void main (void)\n"
+														"{\n"
+														"}\n";
+
+		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+		if (compileStatus != GL_FALSE)
+			ctx.fail("Compute Shader should not have compiled: binding point specified for block member declarations.");
+	}
+	{
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"readonly buffer SSBO {vec4 data;} ssbo;"
+														"void main (void)\n"
+														"{\n"
+															"ssbo.data = vec4(1, 1, 1, 1);"
+														"}\n";
+
+		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+		if (compileStatus != GL_FALSE)
+			ctx.fail("Compute Shader should not have compiled: writing to buffer block qualified with readonly.");
+	}
+	{
+		const char* const computeShaderSource		=	"#version 310 es\n"
+														"writeonly buffer SSBO {vec4 data;} ssbo;"
+														"void main (void)\n"
+														"{\n"
+															"vec4 var = ssbo.data;"
+														"}\n";
+
+		compile_compute_shader_helper(ctx, &computeShaderSource, &compileStatus);
+		if (compileStatus != GL_FALSE)
+			ctx.fail("Compute Shader should not have compiled: reading from buffer block qualified with writeonly.");
+	}
+
 	ctx.endSection();
 }
 
diff --git a/modules/gles31/functional/es31fNegativeShaderDirectiveTests.cpp b/modules/gles31/functional/es31fNegativeShaderDirectiveTests.cpp
index 2b54462..8d87a21 100644
--- a/modules/gles31/functional/es31fNegativeShaderDirectiveTests.cpp
+++ b/modules/gles31/functional/es31fNegativeShaderDirectiveTests.cpp
@@ -126,14 +126,42 @@
 	if (contextSupports(ctx.getRenderContext().getType() , glu::ApiType::es(3, 2)))
 	{
 		ctx.beginSection("gl_BoundingBox does not require the OES/EXT suffix in a 320 es shader.");
-		const std::string source =	"#version 320 es\n"
-									"layout(vertices = 3) out;\n"
-									"void main()\n"
-									"{\n"
-									"	gl_BoundingBox[0] = vec4(0.0, 0.0, 0.0, 0.0);\n"
-									"	gl_BoundingBox[1] = vec4(0.0, 0.0, 0.0, 0.0);\n"
-									"}\n";
-		verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source, EXPECT_RESULT_PASS);
+		{
+			const std::string source =	"#version 320 es\n"
+										"layout(vertices = 3) out;\n"
+										"void main()\n"
+										"{\n"
+										"	gl_BoundingBox[0] = vec4(0.0, 0.0, 0.0, 0.0);\n"
+										"	gl_BoundingBox[1] = vec4(0.0, 0.0, 0.0, 0.0);\n"
+										"}\n";
+			verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source, EXPECT_RESULT_PASS);
+		}
+		ctx.endSection();
+
+		ctx.beginSection("Invalid index used when assigning to gl_BoundingBox in 320 es shader.");
+		{
+			const std::string source =	"#version 320 es\n"
+										"layout(vertices = 3) out;\n"
+										"void main()\n"
+										"{\n"
+										"	gl_BoundingBox[0] = vec4(0.0, 0.0, 0.0, 0.0);\n"
+										"	gl_BoundingBox[2] = vec4(0.0, 0.0, 0.0, 0.0);\n"
+										"}\n";
+			verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source, EXPECT_RESULT_FAIL);
+		}
+		ctx.endSection();
+
+		ctx.beginSection("Invalid type assignment to per-patch output array in 320 es shader.");
+		{
+			const std::string source =	"#version 320 es\n"
+										"layout(vertices = 3) out;\n"
+										"void main()\n"
+										"{\n"
+										"	gl_BoundingBox[0] = ivec4(0, 0, 0, 0);\n"
+										"	gl_BoundingBox[1] = ivec4(0, 0, 0, 0);\n"
+										"}\n";
+			verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_CONTROL, source, EXPECT_RESULT_FAIL);
+		}
 		ctx.endSection();
 	}
 }
@@ -474,6 +502,113 @@
 	ctx.endSection();
 }
 
+void executeAccessingBoundingBoxType (NegativeTestContext& ctx, const std::string builtInTypeName, glu::GLSLVersion glslVersion)
+{
+	std::ostringstream	sourceStream;
+	std::string			version;
+	std::string			extensionPrim;
+	std::string			extensionTess;
+
+	if (glslVersion == glu::GLSL_VERSION_310_ES)
+	{
+		version = "#version 310 es\n";
+		extensionPrim = "#extension GL_EXT_primitive_bounding_box : require\n";
+		extensionTess = "#extension GL_EXT_tessellation_shader : require\n";
+	}
+	else if (glslVersion >= glu::GLSL_VERSION_320_ES)
+	{
+		version = "#version 320 es\n";
+		extensionPrim = "";
+		extensionTess = "";
+	}
+	else
+	{
+		DE_FATAL("error: context below 3.1 and not supported");
+	}
+
+	ctx.beginSection("cannot access built-in type " + builtInTypeName + "[]" + " in vertex shader");
+	sourceStream	<< version
+					<< extensionPrim
+					<< "void main()\n"
+					<< "{\n"
+					<< "	" + builtInTypeName + "[0] = vec4(1.0, 1.0, 1.0, 1.0);\n"
+					<< "	gl_Position = " + builtInTypeName + "[0];\n"
+					<< "}\n";
+	verifyShader(ctx, glu::SHADERTYPE_VERTEX, sourceStream.str(), EXPECT_RESULT_FAIL);
+	ctx.endSection();
+
+	sourceStream.str(std::string());
+
+	if (ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_EVALUATION))
+	{
+		ctx.beginSection("cannot access built-in type " + builtInTypeName + "[]" + " in tessellation evaluation shader");
+		sourceStream	<< version
+						<< extensionPrim
+						<< extensionTess
+						<< "layout (triangles, equal_spacing, ccw) in;\n"
+						<< "void main()\n"
+						<< "{\n"
+						<< "	" + builtInTypeName + "[0] = vec4(1.0, 1.0, 1.0, 1.0);\n"
+						<< "	gl_Position = (	gl_TessCoord.x * " +  builtInTypeName + "[0] +\n"
+						<< "					gl_TessCoord.y * " +  builtInTypeName + "[0] +\n"
+						<< "					gl_TessCoord.z * " +  builtInTypeName + "[0]);\n"
+						<< "}\n";
+		verifyShader(ctx, glu::SHADERTYPE_TESSELLATION_EVALUATION, sourceStream.str(), EXPECT_RESULT_FAIL);
+		ctx.endSection();
+
+		sourceStream.str(std::string());
+	}
+
+	if (ctx.isShaderSupported(glu::SHADERTYPE_GEOMETRY))
+	{
+		ctx.beginSection("cannot access built-in type " + builtInTypeName + "[]" + " in geometry shader");
+		sourceStream	<< version
+						<< extensionPrim
+						<< "layout (triangles) in;\n"
+						<< "layout (triangle_strip, max_vertices = 3) out;\n"
+						<< "void main()\n"
+						<< "{\n"
+						<< "	" + builtInTypeName + "[0] = vec4(1.0, 1.0, 1.0, 1.0);\n"
+						<< "	for (int idx = 0; idx < 3; idx++)\n"
+						<< "	{\n"
+						<< "		gl_Position = gl_in[idx].gl_Position * " + builtInTypeName + "[0];\n"
+						<< "		EmitVertex();\n"
+						<< "	}\n"
+						<< "	EndPrimitive();\n"
+						<< "}\n";
+		verifyShader(ctx, glu::SHADERTYPE_GEOMETRY, sourceStream.str(), EXPECT_RESULT_FAIL);
+		ctx.endSection();
+
+		sourceStream.str(std::string());
+	}
+
+	ctx.beginSection("cannot access built-in type " + builtInTypeName + "[]" + " in fragment shader");
+	sourceStream	<< version
+					<< extensionPrim
+					<< "layout (location = 0) out mediump vec4 fs_colour;\n"
+					<< "void main()\n"
+					<< "{\n"
+					<< "	" + builtInTypeName + "[0] = vec4(1.0, 1.0, 1.0, 1.0);\n"
+					<< "	fs_colour = " + builtInTypeName + "[0];\n"
+					<< "}\n";
+	verifyShader(ctx, glu::SHADERTYPE_FRAGMENT, sourceStream.str(), EXPECT_RESULT_FAIL);
+	ctx.endSection();
+}
+
+void accessing_bounding_box_type (NegativeTestContext& ctx)
+{
+	// Extension requirements and name differences depending on the context
+	if ((ctx.getRenderContext().getType().getMajorVersion() == 3) && (ctx.getRenderContext().getType().getMinorVersion() == 1))
+	{
+		executeAccessingBoundingBoxType(ctx, "gl_BoundingBoxEXT", glu::GLSL_VERSION_310_ES);
+	}
+	else
+	{
+		executeAccessingBoundingBoxType(ctx, "gl_BoundingBox", glu::GLSL_VERSION_320_ES);
+	}
+
+}
+
 } // anonymous
 
 std::vector<FunctionContainer> getNegativeShaderDirectiveTestFunctions (void)
@@ -492,6 +627,7 @@
 		{tessellation_shader,					"tessellation_shader",					"GL_EXT_tessellation_shader is required in 310 es shaders to use AEP features"													},
 		{texture_buffer,						"texture_buffer",						"GL_EXT_texture_buffer is required in 310 es shaders to use AEP features"														},
 		{texture_cube_map_array,				"texture_cube_map_array",				"GL_EXT_texture_cube_map_array is required in 310 es shaders to use AEP features"												},
+		{accessing_bounding_box_type,			"accessing_bounding_box_type",			"Should not be able to access gl_BoundingBoxEXT[] and gl_BoundingBox[] in shaders other than tess control and evaluation"		},
 	};
 
 	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
diff --git a/modules/gles31/functional/es31fNegativeShaderStorageTests.cpp b/modules/gles31/functional/es31fNegativeShaderStorageTests.cpp
new file mode 100644
index 0000000..31d425e
--- /dev/null
+++ b/modules/gles31/functional/es31fNegativeShaderStorageTests.cpp
@@ -0,0 +1,330 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2016 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 Negative Shader Storage Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fNegativeShaderStorageTests.hpp"
+
+#include "gluShaderProgram.hpp"
+#include "glwDefs.hpp"
+#include "glwEnums.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+namespace
+{
+
+void verifyProgram(NegativeTestContext& ctx, glu::ProgramSources sources)
+{
+	tcu::TestLog&				log			= ctx.getLog();
+	const glu::ShaderProgram	program		(ctx.getRenderContext(), sources);
+	bool						testFailed	= false;
+
+	log << program;
+
+	testFailed = program.getProgramInfo().linkOk;
+
+	if (testFailed)
+	{
+		const char* const message("Program was not expected to link.");
+		log << tcu::TestLog::Message << message << tcu::TestLog::EndMessage;
+		ctx.fail(message);
+	}
+}
+
+const char* getShaderExtensionDeclaration (glw::GLenum glShaderType)
+{
+	switch (glShaderType)
+	{
+		case GL_TESS_CONTROL_SHADER:
+		case GL_TESS_EVALUATION_SHADER: return "#extension GL_EXT_tessellation_shader : require\n";
+		case GL_GEOMETRY_SHADER:		return "#extension GL_EXT_geometry_shader : require\n";
+		default:
+			return "";
+	}
+}
+
+glu::ShaderType getGLUShaderType (glw::GLenum glShaderType)
+{
+	switch (glShaderType)
+	{
+		case GL_VERTEX_SHADER:			 return glu::SHADERTYPE_VERTEX;
+		case GL_FRAGMENT_SHADER:		 return glu::SHADERTYPE_FRAGMENT;
+		case GL_TESS_CONTROL_SHADER:	 return glu::SHADERTYPE_TESSELLATION_CONTROL;
+		case GL_TESS_EVALUATION_SHADER:	 return glu::SHADERTYPE_TESSELLATION_EVALUATION;
+		case GL_GEOMETRY_SHADER:		 return glu::SHADERTYPE_GEOMETRY;
+		case GL_COMPUTE_SHADER:			 return glu::SHADERTYPE_COMPUTE;
+		default:
+			DE_FATAL("Unknown shader type");
+			return glu::SHADERTYPE_LAST;
+	}
+}
+
+glw::GLenum getMaxSSBlockSizeEnum (glw::GLenum glShaderType)
+{
+	switch (glShaderType)
+	{
+		case GL_VERTEX_SHADER:			 return GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
+		case GL_FRAGMENT_SHADER:		 return GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
+		case GL_TESS_CONTROL_SHADER:	 return GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
+		case GL_TESS_EVALUATION_SHADER:	 return GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
+		case GL_GEOMETRY_SHADER:		 return GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
+		case GL_COMPUTE_SHADER:			 return GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
+		default:
+			 DE_FATAL("Unknown shader type");
+			 return -1;
+	}
+}
+
+int getMaxSSBlockSize (NegativeTestContext& ctx, glw::GLenum glShaderType)
+{
+	int maxSSBlocks = 0;
+	ctx.glGetIntegerv(getMaxSSBlockSizeEnum(glShaderType), &maxSSBlocks);
+
+	return maxSSBlocks;
+}
+
+std::string genBlockSource (NegativeTestContext& ctx, deInt64 numSSBlocks, glw::GLenum shaderType)
+{
+	const bool				isES32		= contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+	const glu::GLSLVersion	version		= isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
+	std::ostringstream		source;
+
+	source	<< glu::getGLSLVersionDeclaration(version) << "\n"
+			<< ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
+
+	switch (shaderType)
+	{
+		case GL_VERTEX_SHADER:
+		case GL_FRAGMENT_SHADER:
+			break;
+
+		case GL_COMPUTE_SHADER:
+			source << "layout (local_size_x = 1) in;\n";
+			break;
+
+		case GL_GEOMETRY_SHADER:
+			source << "layout(points) in;\n"
+				   << "layout(line_strip, max_vertices = 3) out;\n";
+			break;
+
+		case GL_TESS_CONTROL_SHADER:
+			source << "layout(vertices = 10) out;\n";
+			break;
+
+		case GL_TESS_EVALUATION_SHADER:
+			source << "layout(triangles) in;\n";
+			break;
+
+		default:
+			DE_FATAL("Unknown shader type");
+			break;
+	}
+
+	source  << "\n"
+			<< "layout(std430, binding = 0) buffer Block {\n"
+			<< "    int value;\n"
+			<< "} sb_in[" << numSSBlocks << "];\n"
+			<< "void main(void) { sb_in[0].value = 1; }\n";
+
+	return source.str();
+}
+
+std::string genCommonSource (NegativeTestContext& ctx, glw::GLenum shaderType)
+{
+	const bool				isES32		= contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+	const glu::GLSLVersion	version		= isES32 ? glu::GLSL_VERSION_320_ES : glu::GLSL_VERSION_310_ES;
+	std::ostringstream		source;
+
+	source << glu::getGLSLVersionDeclaration(version) << "\n"
+		   << ((isES32) ? "" : getShaderExtensionDeclaration(shaderType));
+
+	switch (shaderType)
+	{
+		case GL_TESS_CONTROL_SHADER:
+			source	<< "layout(vertices = 3) out;\n"
+					<< "void main() {}\n";
+			break;
+
+		case GL_TESS_EVALUATION_SHADER:
+			source	<< "layout(triangles, equal_spacing, cw) in;\n"
+					<< "void main() {}\n";
+			break;
+
+		default:
+			source  << "void main() {}\n";
+			break;
+	}
+
+	return source.str();
+}
+
+int genMaxSSBlocksSource (NegativeTestContext& ctx, glw::GLenum glShaderType, glu::ProgramSources& sources)
+{
+	int		maxSSBlocks				= getMaxSSBlockSize(ctx, glShaderType);
+	const	std::string shaderSrc	= genBlockSource(ctx, (maxSSBlocks), glShaderType);
+
+	sources.sources[getGLUShaderType(glShaderType)].push_back(shaderSrc);
+
+	return maxSSBlocks;
+}
+
+void block_number_limits (NegativeTestContext& ctx)
+{
+	const glw::GLenum glShaderTypes[] =
+	{
+		GL_VERTEX_SHADER,
+		GL_FRAGMENT_SHADER,
+		GL_TESS_CONTROL_SHADER,
+		GL_TESS_EVALUATION_SHADER,
+		GL_GEOMETRY_SHADER,
+		GL_COMPUTE_SHADER,
+	};
+
+	const std::string	vertSource			= genCommonSource(ctx, GL_VERTEX_SHADER);
+	const std::string	fragSource			= genCommonSource(ctx, GL_FRAGMENT_SHADER);
+	const std::string	tessControlSource	= genCommonSource(ctx, GL_TESS_CONTROL_SHADER);
+	const std::string	tessEvalSource		= genCommonSource(ctx, GL_TESS_EVALUATION_SHADER);
+
+	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(glShaderTypes); ndx++)
+	{
+		ctx.beginSection("maxShaderStorageBlocks: Exceed limits");
+
+		if (!ctx.isShaderSupported(static_cast<glu::ShaderType>(getGLUShaderType(glShaderTypes[ndx]))))
+		{
+			ctx.endSection();
+			continue;
+		}
+
+		int					maxSSBlocks			= getMaxSSBlockSize(ctx, glShaderTypes[ndx]);
+		std::string			source				= genBlockSource(ctx, maxSSBlocks+1, glShaderTypes[ndx]);
+
+		glu::ProgramSources sources;
+
+		if (maxSSBlocks == 0)
+		{
+			ctx.endSection();
+			continue;
+		}
+
+		switch (glShaderTypes[ndx])
+		{
+			case GL_VERTEX_SHADER:
+				sources << glu::VertexSource(source)
+						<< glu::FragmentSource(fragSource);
+				break;
+
+			case GL_FRAGMENT_SHADER:
+				sources << glu::VertexSource(vertSource)
+						<< glu::FragmentSource(source);
+				break;
+
+			case GL_TESS_CONTROL_SHADER:
+				sources << glu::VertexSource(vertSource)
+						<< glu::FragmentSource(fragSource)
+						<< glu::TessellationControlSource(source)
+						<< glu::TessellationEvaluationSource(tessEvalSource);
+				break;
+
+			case GL_TESS_EVALUATION_SHADER:
+				sources << glu::VertexSource(vertSource)
+						<< glu::FragmentSource(fragSource)
+						<< glu::TessellationControlSource(tessControlSource)
+						<< glu::TessellationEvaluationSource(source);
+				break;
+
+			case GL_GEOMETRY_SHADER:
+				sources << glu::VertexSource(vertSource)
+						<< glu::FragmentSource(fragSource)
+						<< glu::GeometrySource(source);
+				break;
+
+			case GL_COMPUTE_SHADER:
+				sources << glu::ComputeSource(source);
+				break;
+
+			default:
+				DE_FATAL("Unknown shader type");
+				break;
+		}
+
+		verifyProgram(ctx, sources);
+		ctx.endSection();
+	}
+}
+
+void max_combined_block_number_limit (NegativeTestContext& ctx)
+{
+	ctx.beginSection("maxCombinedShaderStorageBlocks: Exceed limits");
+
+	glu::ProgramSources sources;
+
+	int combinedSSBlocks	= 0;
+	int maxCombinedSSBlocks = 0;
+
+	combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_VERTEX_SHADER, sources);
+	combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_FRAGMENT_SHADER, sources);
+
+	if ((ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_CONTROL)) && (ctx.isShaderSupported(glu::SHADERTYPE_TESSELLATION_EVALUATION)))
+	{
+		combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_CONTROL_SHADER, sources);
+		combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_TESS_EVALUATION_SHADER, sources);
+	}
+
+	if (ctx.isShaderSupported(glu::SHADERTYPE_GEOMETRY))
+		combinedSSBlocks += genMaxSSBlocksSource(ctx, GL_GEOMETRY_SHADER, sources);
+
+	ctx.glGetIntegerv(GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS, &maxCombinedSSBlocks);
+
+	ctx.getLog() << tcu::TestLog::Message << "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << maxCombinedSSBlocks << tcu::TestLog::EndMessage;
+	ctx.getLog() << tcu::TestLog::Message << "Combined shader storage blocks: " << combinedSSBlocks << tcu::TestLog::EndMessage;
+
+	if (combinedSSBlocks > maxCombinedSSBlocks)
+		verifyProgram(ctx, sources);
+	else
+		ctx.getLog() << tcu::TestLog::Message << "Test skipped: Combined shader storage blocks < GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS: " << tcu::TestLog::EndMessage;
+
+	ctx.endSection();
+}
+
+} // anonymous
+
+std::vector<FunctionContainer> getNegativeShaderStorageTestFunctions ()
+{
+	const FunctionContainer funcs[] =
+	{
+		{ block_number_limits,				"block_number_limits",				"Invalid shader linkage" },
+		{ max_combined_block_number_limit,	"max_combined_block_number_limit",	"Invalid shader linkage" },
+	};
+
+	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
+}
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fNegativeShaderStorageTests.hpp b/modules/gles31/functional/es31fNegativeShaderStorageTests.hpp
new file mode 100644
index 0000000..13cbd1f
--- /dev/null
+++ b/modules/gles31/functional/es31fNegativeShaderStorageTests.hpp
@@ -0,0 +1,45 @@
+#ifndef _ES31FNEGATIVESHADERSTORAGETESTS_HPP
+#define _ES31FNEGATIVESHADERSTORAGETESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2016 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 Negative Shader Storage Tests
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "es31fNegativeTestShared.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+
+std::vector<FunctionContainer> getNegativeShaderStorageTestFunctions (void);
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp
+
+#endif // _ES31FNEGATIVESHADERSTORAGETESTS_HPP
diff --git a/modules/gles31/functional/es31fNegativeStateApiTests.cpp b/modules/gles31/functional/es31fNegativeStateApiTests.cpp
index 1f1cfeb..19184c6 100644
--- a/modules/gles31/functional/es31fNegativeStateApiTests.cpp
+++ b/modules/gles31/functional/es31fNegativeStateApiTests.cpp
@@ -184,8 +184,9 @@
 
 void get_integeri_v (NegativeTestContext& ctx)
 {
-	GLint data						= -1;
-	GLint maxUniformBufferBindings	= 0;
+	GLint data								= -1;
+	GLint maxUniformBufferBindings			=  0;
+	GLint maxShaderStorageBufferBindings	=  0;
 
 	ctx.beginSection("GL_INVALID_ENUM is generated if name is not an accepted value.");
 	ctx.glGetIntegeri_v(-1, 0, &data);
@@ -198,12 +199,20 @@
 	ctx.glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, maxUniformBufferBindings, &data);
 	ctx.expectError(GL_INVALID_VALUE);
 	ctx.endSection();
+
+	ctx.beginSection("GL_INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.");
+	ctx.glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings);
+	ctx.expectError(GL_NO_ERROR);
+	ctx.glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_BINDING, maxShaderStorageBufferBindings, &data);
+	ctx.expectError(GL_INVALID_VALUE);
+	ctx.endSection();
 }
 
 void get_integer64i_v (NegativeTestContext& ctx)
 {
-	GLint64	data						= (GLint64)-1;
-	GLint	maxUniformBufferBindings	= 0;
+	GLint64	data							= (GLint64)-1;
+	GLint	maxUniformBufferBindings		= 0;
+	GLint	maxShaderStorageBufferBindings	= 0;
 
 	ctx.beginSection("GL_INVALID_ENUM is generated if name is not an accepted value.");
 	ctx.glGetInteger64i_v(-1, 0, &data);
@@ -216,6 +225,15 @@
 	ctx.glGetInteger64i_v(GL_UNIFORM_BUFFER_START, maxUniformBufferBindings, &data);
 	ctx.expectError(GL_INVALID_VALUE);
 	ctx.endSection();
+
+	ctx.beginSection("GL_INVALID_VALUE is generated if index is outside of the valid range for the indexed state target.");
+	ctx.glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &maxShaderStorageBufferBindings);
+	ctx.expectError(GL_NO_ERROR);
+	ctx.glGetInteger64i_v(GL_SHADER_STORAGE_BUFFER_START, maxShaderStorageBufferBindings, &data);
+	ctx.expectError(GL_INVALID_VALUE);
+	ctx.glGetInteger64i_v(GL_SHADER_STORAGE_BUFFER_SIZE, maxShaderStorageBufferBindings, &data);
+	ctx.expectError(GL_INVALID_VALUE);
+	ctx.endSection();
 }
 
 void get_string (NegativeTestContext& ctx)
diff --git a/modules/gles31/functional/es31fNegativeTessellationTests.cpp b/modules/gles31/functional/es31fNegativeTessellationTests.cpp
new file mode 100644
index 0000000..e42f94a
--- /dev/null
+++ b/modules/gles31/functional/es31fNegativeTessellationTests.cpp
@@ -0,0 +1,423 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2016 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 Negative Tessellation tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fNegativeTessellationTests.hpp"
+#include "gluContextInfo.hpp"
+#include "gluShaderProgram.hpp"
+#include "glwDefs.hpp"
+#include "glwEnums.hpp"
+#include "tcuStringTemplate.hpp"
+
+namespace deqp
+{
+
+using std::string;
+using std::map;
+
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+
+using tcu::TestLog;
+using namespace glw;
+
+static const char* vertexShaderSource		=	"${GLSL_VERSION_STRING}\n"
+												"\n"
+												"void main (void)\n"
+												"{\n"
+												"	gl_Position = vec4(0.0);\n"
+												"}\n";
+
+static const char* fragmentShaderSource		=	"${GLSL_VERSION_STRING}\n"
+												"precision mediump float;\n"
+												"layout(location = 0) out mediump vec4 fragColor;\n"
+												"\n"
+												"void main (void)\n"
+												"{\n"
+												"	fragColor = vec4(1.0);\n"
+												"}\n";
+
+static const char* tessControlShaderSource	=	"${GLSL_VERSION_STRING}\n"
+												"${GLSL_TESS_EXTENSION_STRING}\n"
+												"layout (vertices=3) out;\n"
+												"\n"
+												"void main()\n"
+												"{\n"
+												"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+												"}\n";
+
+static const char* tessEvalShaderSource		=	"${GLSL_VERSION_STRING}\n"
+												"${GLSL_TESS_EXTENSION_STRING}\n"
+												"layout(triangles) in;\n"
+												"\n"
+												"void main()\n"
+												"{\n"
+												"	gl_Position = gl_TessCoord[0] * gl_in[0].gl_Position;\n"
+												"}\n";
+
+static void checkExtensionSupport (NegativeTestContext& ctx, const char* extName)
+{
+	if (!ctx.getContextInfo().isExtensionSupported(extName))
+		throw tcu::NotSupportedError(string(extName) + " not supported");
+}
+
+static void checkTessellationSupport (NegativeTestContext& ctx)
+{
+	checkExtensionSupport(ctx, "GL_EXT_tessellation_shader");
+}
+
+// Helper for constructing tessellation pipeline sources.
+static glu::ProgramSources makeTessPipelineSources (const std::string& vertexSrc, const std::string& fragmentSrc, const std::string& tessCtrlSrc, const std::string& tessEvalSrc)
+{
+	glu::ProgramSources sources;
+	sources.sources[glu::SHADERTYPE_VERTEX].push_back(vertexSrc);
+	sources.sources[glu::SHADERTYPE_FRAGMENT].push_back(fragmentSrc);
+
+	if (!tessCtrlSrc.empty())
+		sources.sources[glu::SHADERTYPE_TESSELLATION_CONTROL].push_back(tessCtrlSrc);
+
+	if (!tessEvalSrc.empty())
+		sources.sources[glu::SHADERTYPE_TESSELLATION_EVALUATION].push_back(tessEvalSrc);
+
+	return sources;
+}
+
+// Incomplete active tess shaders
+void single_tessellation_stage (NegativeTestContext& ctx)
+{
+	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+	map<string, string>			args;
+	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+	args["GLSL_TESS_EXTENSION_STRING"]	= isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
+
+	checkTessellationSupport(ctx);
+
+	{
+		glu::ShaderProgram program(ctx.getRenderContext(),
+								   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+														   tcu::StringTemplate(fragmentShaderSource).specialize(args),
+														   tcu::StringTemplate(tessControlShaderSource).specialize(args),
+														   "")); // missing tessEvalShaderSource
+		tcu::TestLog& log = ctx.getLog();
+		log << program;
+
+		ctx.beginSection("A link error is generated if a non-separable program has a tessellation control shader but no tessellation evaluation shader.");
+
+		if (program.isOk())
+			ctx.fail("Program was not expected to link");
+
+		ctx.endSection();
+	}
+
+	{
+		glu::ShaderProgram program(ctx.getRenderContext(),
+								   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+														   tcu::StringTemplate(fragmentShaderSource).specialize(args),
+														   tcu::StringTemplate(tessControlShaderSource).specialize(args),
+														   "") // missing tessEvalShaderSource
+								   << glu::ProgramSeparable(true));
+		tcu::TestLog& log = ctx.getLog();
+		log << program;
+
+		if (!program.isOk())
+			TCU_THROW(TestError, "failed to build program");
+
+		ctx.glUseProgram(program.getProgram());
+		ctx.expectError(GL_NO_ERROR);
+
+		ctx.beginSection("GL_INVALID_OPERATION is generated if current program state has tessellation control shader but no tessellation evaluation shader.");
+		ctx.glDrawArrays(GL_PATCHES, 0, 3);
+		ctx.expectError(GL_INVALID_OPERATION);
+		ctx.endSection();
+
+		ctx.glUseProgram(0);
+	}
+
+	{
+		glu::ShaderProgram program(ctx.getRenderContext(),
+								   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+														   tcu::StringTemplate(fragmentShaderSource).specialize(args),
+														   "", // missing tessControlShaderSource
+														   tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
+		tcu::TestLog& log = ctx.getLog();
+		log << program;
+
+		ctx.beginSection("A link error is generated if a non-separable program has a tessellation evaluation shader but no tessellation control shader.");
+
+		if (program.isOk())
+			ctx.fail("Program was not expected to link");
+
+		ctx.endSection();
+	}
+
+	{
+		glu::ShaderProgram program(ctx.getRenderContext(),
+								   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+														   tcu::StringTemplate(fragmentShaderSource).specialize(args),
+														   "", // missing tessControlShaderSource
+														   tcu::StringTemplate(tessEvalShaderSource).specialize(args))
+									<< glu::ProgramSeparable(true));
+		tcu::TestLog& log = ctx.getLog();
+		log << program;
+
+		if (!program.isOk())
+			TCU_THROW(TestError, "failed to build program");
+
+		ctx.glUseProgram(program.getProgram());
+		ctx.expectError(GL_NO_ERROR);
+
+		ctx.beginSection("GL_INVALID_OPERATION is generated if current program state has tessellation evaluation shader but no tessellation control shader.");
+		ctx.glDrawArrays(GL_PATCHES, 0, 3);
+		ctx.expectError(GL_INVALID_OPERATION);
+		ctx.endSection();
+
+		ctx.glUseProgram(0);
+	}
+}
+
+// Complete active tess shaders invalid primitive mode
+void invalid_primitive_mode (NegativeTestContext& ctx)
+{
+	checkTessellationSupport(ctx);
+
+	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+	map<string, string>			args;
+	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+	args["GLSL_TESS_EXTENSION_STRING"]	= isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
+
+	glu::ShaderProgram program(ctx.getRenderContext(),
+							   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+													   tcu::StringTemplate(fragmentShaderSource).specialize(args),
+													   tcu::StringTemplate(tessControlShaderSource).specialize(args),
+													   tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
+	tcu::TestLog& log = ctx.getLog();
+	log << program;
+
+	ctx.glUseProgram(program.getProgram());
+	ctx.expectError(GL_NO_ERROR);
+
+	ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is active and primitive mode is not GL_PATCHES.");
+	ctx.glDrawArrays(GL_TRIANGLES, 0, 3);
+	ctx.expectError(GL_INVALID_OPERATION);
+	ctx.endSection();
+
+	ctx.glUseProgram(0);
+}
+
+void tessellation_not_active (NegativeTestContext& ctx)
+{
+	checkTessellationSupport(ctx);
+
+	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+	const glw::GLenum			tessErr = ctx.getContextInfo().isExtensionSupported("GL_NV_gpu_shader5") ? GL_NO_ERROR : GL_INVALID_OPERATION;
+	map<string, string>			args;
+	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+	args["GLSL_TESS_EXTENSION_STRING"]	= isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
+
+	glu::ShaderProgram program(ctx.getRenderContext(),
+							   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+													   tcu::StringTemplate(fragmentShaderSource).specialize(args),
+													   "",		// missing tessControlShaderSource
+													   ""));	// missing tessEvalShaderSource
+	tcu::TestLog& log = ctx.getLog();
+	log << program;
+
+	ctx.glUseProgram(program.getProgram());
+	ctx.expectError(GL_NO_ERROR);
+
+	ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is not active and primitive mode is GL_PATCHES, unless GL_NV_gpu_shader5 is supported.");
+	ctx.glDrawArrays(GL_PATCHES, 0, 3);
+	ctx.expectError(tessErr);
+	ctx.endSection();
+
+	ctx.glUseProgram(0);
+}
+
+void invalid_program_state (NegativeTestContext& ctx)
+{
+	checkTessellationSupport(ctx);
+
+	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+	map<string, string>			args;
+	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+	args["GLSL_TESS_EXTENSION_STRING"]	= isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
+
+	glu::FragmentSource frgSource(tcu::StringTemplate(fragmentShaderSource).specialize(args));
+	glu::TessellationControlSource tessCtrlSource(tcu::StringTemplate(tessControlShaderSource).specialize(args));
+	glu::TessellationEvaluationSource tessEvalSource(tcu::StringTemplate(tessEvalShaderSource).specialize(args));
+
+	glu::ProgramPipeline pipeline(ctx.getRenderContext());
+
+	glu::ShaderProgram	fragProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << frgSource);
+	glu::ShaderProgram	tessCtrlProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessCtrlSource);
+	glu::ShaderProgram	tessEvalProgram	(ctx.getRenderContext(), glu::ProgramSources() << glu::ProgramSeparable(true) << tessEvalSource);
+
+	tcu::TestLog& log = ctx.getLog();
+	log << fragProgram << tessCtrlProgram << tessEvalProgram;
+
+	if (!fragProgram.isOk() || !tessCtrlProgram.isOk() || !tessEvalProgram.isOk())
+		throw tcu::TestError("failed to build program");
+
+	ctx.glBindProgramPipeline(pipeline.getPipeline());
+	ctx.expectError(GL_NO_ERROR);
+
+	ctx.glUseProgramStages(pipeline.getPipeline(), GL_FRAGMENT_SHADER_BIT, fragProgram.getProgram());
+	ctx.glUseProgramStages(pipeline.getPipeline(), GL_TESS_CONTROL_SHADER_BIT, tessCtrlProgram.getProgram());
+	ctx.glUseProgramStages(pipeline.getPipeline(), GL_TESS_EVALUATION_SHADER_BIT, tessEvalProgram.getProgram());
+	ctx.expectError(GL_NO_ERROR);
+
+	ctx.beginSection("GL_INVALID_OPERATION is generated if tessellation is active and vertex shader is missing.");
+	ctx.glDrawArrays(GL_PATCHES, 0, 3);
+	ctx.expectError(GL_INVALID_OPERATION);
+	ctx.endSection();
+
+	ctx.glBindProgramPipeline(0);
+	ctx.expectError(GL_NO_ERROR);
+}
+
+void tessellation_control_invalid_vertex_count (NegativeTestContext& ctx)
+{
+	checkTessellationSupport(ctx);
+
+	const char* const tessControlVertLimitSource	=	"${GLSL_VERSION_STRING}\n"
+														"${GLSL_TESS_EXTENSION_STRING}\n"
+														"layout (vertices=${GL_MAX_PATCH_LIMIT}) out;\n"
+														"void main()\n"
+														"{\n"
+														"	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
+														"}\n";
+
+	const bool					isES32	= glu::contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2));
+	map<string, string>			args;
+	args["GLSL_VERSION_STRING"]			= isES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES);
+	args["GLSL_TESS_EXTENSION_STRING"]	= isES32 ? "" : "#extension GL_EXT_tessellation_shader : require";
+
+	int maxPatchVertices= 0;
+
+	ctx.beginSection("Output vertex count exceeds GL_MAX_PATCH_VERTICES.");
+	ctx.glGetIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
+	ctx.expectError(GL_NO_ERROR);
+
+	std::ostringstream				oss;
+	oss << (maxPatchVertices + 1);
+	args["GL_MAX_PATCH_LIMIT"] =	oss.str();
+
+
+	glu::ShaderProgram program(ctx.getRenderContext(),
+							   makeTessPipelineSources(tcu::StringTemplate(vertexShaderSource).specialize(args),
+													   tcu::StringTemplate(fragmentShaderSource).specialize(args),
+													   tcu::StringTemplate(tessControlVertLimitSource).specialize(args),
+													   tcu::StringTemplate(tessEvalShaderSource).specialize(args)));
+	tcu::TestLog& log = ctx.getLog();
+	log << program;
+
+	bool testFailed = program.getProgramInfo().linkOk;
+
+	if (testFailed)
+		ctx.fail("Program was not expected to link");
+
+	ctx.endSection();
+}
+
+void invalid_get_programiv (NegativeTestContext& ctx)
+{
+	checkTessellationSupport(ctx);
+
+	GLuint	program		= ctx.glCreateProgram();
+	GLint	params[1]	= { 0 };
+
+	ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_CONTROL_OUTPUT_VERTICES is queried for a program which has not been linked properly.");
+	ctx.glGetProgramiv(program, GL_TESS_CONTROL_OUTPUT_VERTICES, &params[0]);
+	ctx.expectError(GL_INVALID_OPERATION);
+	ctx.endSection();
+
+	ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_MODE is queried for a program which has not been linked properly.");
+	ctx.glGetProgramiv(program, GL_TESS_GEN_MODE, &params[0]);
+	ctx.expectError(GL_INVALID_OPERATION);
+	ctx.endSection();
+
+	ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_SPACING is queried for a program which has not been linked properly.");
+	ctx.glGetProgramiv(program, GL_TESS_GEN_SPACING, &params[0]);
+	ctx.expectError(GL_INVALID_OPERATION);
+	ctx.endSection();
+
+	ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_VERTEX_ORDER is queried for a program which has not been linked properly.");
+	ctx.glGetProgramiv(program, GL_TESS_GEN_VERTEX_ORDER, &params[0]);
+	ctx.expectError(GL_INVALID_OPERATION);
+	ctx.endSection();
+
+	ctx.beginSection("GL_INVALID_OPERATION is generated if GL_TESS_GEN_POINT_MODE is queried for a program which has not been linked properly.");
+	ctx.glGetProgramiv(program, GL_TESS_GEN_POINT_MODE, &params[0]);
+	ctx.expectError(GL_INVALID_OPERATION);
+	ctx.endSection();
+
+	ctx.glDeleteProgram(program);
+}
+
+void invalid_patch_parameteri (NegativeTestContext& ctx)
+{
+	checkTessellationSupport(ctx);
+
+	ctx.beginSection("GL_INVALID_ENUM is generated if pname is not GL_PATCH_VERTICES.");
+	ctx.glPatchParameteri(-1, 1);
+	ctx.expectError(GL_INVALID_ENUM);
+	ctx.endSection();
+
+	ctx.beginSection("GL_INVALID_VALUE is generated if value is less than or equal to zero.");
+	ctx.glPatchParameteri(GL_PATCH_VERTICES, 0);
+	ctx.expectError(GL_INVALID_VALUE);
+	ctx.endSection();
+
+	int maxPatchVertices= 0;
+	ctx.glGetIntegerv(GL_MAX_PATCH_VERTICES, &maxPatchVertices);
+	ctx.expectError(GL_NO_ERROR);
+
+	ctx.beginSection("GL_INVALID_VALUE is generated if value is greater than GL_MAX_PATCH_VERTICES.");
+	ctx.glPatchParameteri(GL_PATCH_VERTICES, maxPatchVertices + 1);
+	ctx.expectError(GL_INVALID_VALUE);
+	ctx.endSection();
+}
+
+std::vector<FunctionContainer> getNegativeTessellationTestFunctions (void)
+{
+	const FunctionContainer funcs[] =
+	{
+		{ single_tessellation_stage,					"single_tessellation_stage",					"Invalid program state with single tessellation stage"							},
+		{ invalid_primitive_mode,						"invalid_primitive_mode",						"Invalid primitive mode when tessellation is active"							},
+		{ tessellation_not_active,						"tessellation_not_active",						"Use of GL_PATCHES when tessellation is not active"								},
+		{ invalid_program_state,						"invalid_program_state",						"Invalid program state when tessellation active but no vertex shader present"	},
+		{ invalid_get_programiv,						"get_programiv",								"Invalid glGetProgramiv() usage"												},
+		{ invalid_patch_parameteri,						"invalid_program_queries",						"Invalid glPatchParameteri() usage"												},
+		{ tessellation_control_invalid_vertex_count,	"tessellation_control_invalid_vertex_count",	"Exceed vertex count limit in tessellation control shader"						},
+	};
+
+	return std::vector<FunctionContainer>(DE_ARRAY_BEGIN(funcs), DE_ARRAY_END(funcs));
+}
+
+} // NegativeTestShared
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fNegativeTessellationTests.hpp b/modules/gles31/functional/es31fNegativeTessellationTests.hpp
new file mode 100644
index 0000000..d376656
--- /dev/null
+++ b/modules/gles31/functional/es31fNegativeTessellationTests.hpp
@@ -0,0 +1,45 @@
+#ifndef _ES31FNEGATIVETESSELLATIONTESTS_HPP
+#define _ES31FNEGATIVETESSELLATIONTESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2016 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 Negative Tessellation tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "es31fNegativeTestShared.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace NegativeTestShared
+{
+
+std::vector<FunctionContainer> getNegativeTessellationTestFunctions (void);
+
+} // NegativeTestShared
+} // Functional
+} // gles3
+} // deqp
+
+#endif // _ES31FNEGATIVETESSELLATIONTESTS_HPP
diff --git a/modules/gles31/functional/es31fNegativeTextureApiTests.cpp b/modules/gles31/functional/es31fNegativeTextureApiTests.cpp
index 6038b40..52f7146 100644
--- a/modules/gles31/functional/es31fNegativeTextureApiTests.cpp
+++ b/modules/gles31/functional/es31fNegativeTextureApiTests.cpp
@@ -2916,8 +2916,6 @@
 	ctx.glTexImage3D		(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 	ctx.glBindTexture		(GL_TEXTURE_2D_ARRAY, textures[1]);
 	ctx.glTexImage3D		(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-	ctx.glBindTexture		(GL_TEXTURE_CUBE_MAP_ARRAY, textures[2]);
-	ctx.glTexImage3D		(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 4, 4, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 	ctx.expectError			(GL_NO_ERROR);
 
 	ctx.beginSection("GL_INVALID_VALUE is generated if level is less than 0.");
@@ -2928,6 +2926,10 @@
 
 	if (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) || ctx.getContextInfo().isExtensionSupported("GL_OES_texture_cube_map_array"))
 	{
+		ctx.glBindTexture		(GL_TEXTURE_CUBE_MAP_ARRAY, textures[2]);
+		ctx.glTexImage3D		(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 4, 4, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+		ctx.expectError			(GL_NO_ERROR);
+
 		ctx.glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, -1, 0, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 		ctx.expectError(GL_INVALID_VALUE);
 	}
@@ -2971,8 +2973,6 @@
 	ctx.glTexImage3D		(GL_TEXTURE_3D, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 	ctx.glBindTexture		(GL_TEXTURE_2D_ARRAY, textures[1]);
 	ctx.glTexImage3D		(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
-	ctx.glBindTexture		(GL_TEXTURE_CUBE_MAP_ARRAY, textures[2]);
-	ctx.glTexImage3D		(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 4, 4, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 	ctx.expectError			(GL_NO_ERROR);
 
 	ctx.beginSection("GL_INVALID_VALUE is generated if xoffset, yoffset or zoffset are negative.");
@@ -2995,6 +2995,10 @@
 
 	if (contextSupports(ctx.getRenderContext().getType(), glu::ApiType::es(3, 2)) || ctx.getContextInfo().isExtensionSupported("GL_OES_texture_cube_map_array"))
 	{
+		ctx.glBindTexture		(GL_TEXTURE_CUBE_MAP_ARRAY, textures[2]);
+		ctx.glTexImage3D		(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA, 4, 4, 6, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+		ctx.expectError			(GL_NO_ERROR);
+
 		ctx.glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, -1, 0, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 		ctx.expectError(GL_INVALID_VALUE);
 		ctx.glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, 0, -1, 0, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
diff --git a/modules/gles31/functional/es31fPrimitiveBoundingBoxTests.cpp b/modules/gles31/functional/es31fPrimitiveBoundingBoxTests.cpp
index c1fa0af..7f07d36 100644
--- a/modules/gles31/functional/es31fPrimitiveBoundingBoxTests.cpp
+++ b/modules/gles31/functional/es31fPrimitiveBoundingBoxTests.cpp
@@ -1402,6 +1402,8 @@
 	{
 		SCANRESULT_NUM_LINES_OK_BIT		= (1 << 0),
 		SCANRESULT_LINE_WIDTH_OK_BIT	= (1 << 1),
+		SCANRESULT_LINE_WIDTH_WARN_BIT	= (1 << 2),
+		SCANRESULT_LINE_WIDTH_ERR_BIT	= (1 << 3),
 	};
 
 	void				init							(void);
@@ -1422,7 +1424,7 @@
 	deUint8				scanColumn						(const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, const tcu::IVec2& numLines, int& floodCounter) const;
 	bool				checkAreaNumLines				(const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& floodCounter, int componentNdx, const tcu::IVec2& numLines) const;
 	tcu::IVec2			getNumMinimaMaxima				(const tcu::ConstPixelBufferAccess& access, int componentNdx) const;
-	bool				checkLineWidths					(const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& floodCounter) const;
+	deUint8				checkLineWidths					(const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& floodCounter) const;
 	void				printLineWidthError				(const tcu::IVec2& pos, int detectedLineWidth, const tcu::IVec2& lineWidthRange, bool isHorizontal, int& floodCounter) const;
 
 	const int			m_patternSide;
@@ -1787,23 +1789,24 @@
 
 void LineRenderCase::verifyRenderResult (const IterationConfig& config)
 {
-	const glw::Functions&	gl						= m_context.getRenderContext().getFunctions();
-	const bool				isMsaa					= m_context.getRenderTarget().getNumSamples() > 1;
-	const ProjectedBBox		projectedBBox			= projectBoundingBox(config.bbox);
-	const float				lineWidth				= (m_isWideLineCase) ? ((float)m_wideLineLineWidth) : (1.0f);
-	const tcu::IVec4		viewportBBoxArea		= getViewportBoundingBoxArea(projectedBBox, config.viewportSize, lineWidth);
-	const tcu::IVec4		viewportPatternArea		= getViewportPatternArea(config.patternPos, config.patternSize, config.viewportSize, ROUND_INWARDS);
-	const tcu::IVec2		expectedHorizontalLines	= getNumberOfLinesRange(viewportBBoxArea.y(), viewportBBoxArea.w(), config.patternPos.y(), config.patternSize.y(), config.viewportSize.y(), DIRECTION_VERTICAL);
-	const tcu::IVec2		expectedVerticalLines	= getNumberOfLinesRange(viewportBBoxArea.x(), viewportBBoxArea.z(), config.patternPos.x(), config.patternSize.x(), config.viewportSize.x(), DIRECTION_HORIZONTAL);
-	const tcu::IVec4		verificationArea		= tcu::IVec4(de::max(viewportBBoxArea.x(), 0),
-																 de::max(viewportBBoxArea.y(), 0),
-																 de::min(viewportBBoxArea.z(), config.viewportSize.x()),
-																 de::min(viewportBBoxArea.w(), config.viewportSize.y()));
+	const glw::Functions&	gl							= m_context.getRenderContext().getFunctions();
+	const bool				isMsaa						= m_context.getRenderTarget().getNumSamples() > 1;
+	const ProjectedBBox		projectedBBox				= projectBoundingBox(config.bbox);
+	const float				lineWidth					= (m_isWideLineCase) ? ((float)m_wideLineLineWidth) : (1.0f);
+	const tcu::IVec4		viewportBBoxArea			= getViewportBoundingBoxArea(projectedBBox, config.viewportSize, lineWidth);
+	const tcu::IVec4		viewportPatternArea			= getViewportPatternArea(config.patternPos, config.patternSize, config.viewportSize, ROUND_INWARDS);
+	const tcu::IVec2		expectedHorizontalLines		= getNumberOfLinesRange(viewportBBoxArea.y(), viewportBBoxArea.w(), config.patternPos.y(), config.patternSize.y(), config.viewportSize.y(), DIRECTION_VERTICAL);
+	const tcu::IVec2		expectedVerticalLines		= getNumberOfLinesRange(viewportBBoxArea.x(), viewportBBoxArea.z(), config.patternPos.x(), config.patternSize.x(), config.viewportSize.x(), DIRECTION_HORIZONTAL);
+	const tcu::IVec4		verificationArea			= tcu::IVec4(de::max(viewportBBoxArea.x(), 0),
+																	 de::max(viewportBBoxArea.y(), 0),
+																	 de::min(viewportBBoxArea.z(), config.viewportSize.x()),
+																	 de::min(viewportBBoxArea.w(), config.viewportSize.y()));
 
-	tcu::Surface			viewportSurface			(config.viewportSize.x(), config.viewportSize.y());
-	bool					anyError				= false;
-	bool					msaaRelaxationRequired	= false;
-	int						messageLimitCounter		= 8;
+	tcu::Surface			viewportSurface				(config.viewportSize.x(), config.viewportSize.y());
+	bool					anyError					= false;
+	bool					msaaRelaxationRequired		= false;
+	bool					hwIssueRelaxationRequired	= false;
+	int						messageLimitCounter			= 8;
 
 	if (!m_calcPerPrimitiveBBox)
 		m_testCtx.getLog()
@@ -1853,6 +1856,11 @@
 				// multisampled wide lines might not be supported
 				msaaRelaxationRequired = true;
 			}
+			else if ((result & SCANRESULT_LINE_WIDTH_ERR_BIT) == 0 &&
+					 (result & SCANRESULT_LINE_WIDTH_WARN_BIT) != 0)
+			{
+				hwIssueRelaxationRequired = true;
+			}
 			else
 				anyError = true;
 		}
@@ -1877,12 +1885,16 @@
 				// multisampled wide lines might not be supported
 				msaaRelaxationRequired = true;
 			}
+			else if ((result & SCANRESULT_LINE_WIDTH_WARN_BIT) != 0)
+			{
+				hwIssueRelaxationRequired = true;
+			}
 			else
 				anyError = true;
 		}
 	}
 
-	if (anyError || msaaRelaxationRequired)
+	if (anyError || msaaRelaxationRequired || hwIssueRelaxationRequired)
 	{
 		if (messageLimitCounter < 0)
 			m_testCtx.getLog() << tcu::TestLog::Message << "Omitted " << (-messageLimitCounter) << " row/column error descriptions." << tcu::TestLog::EndMessage;
@@ -1897,6 +1909,11 @@
 
 		if (anyError)
 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed");
+		else if (hwIssueRelaxationRequired)
+		{
+			// Line width hw issue
+			m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, "Line width verification failed");
+		}
 		else
 		{
 			// MSAA wide lines are optional
@@ -1949,20 +1966,36 @@
 
 deUint8 LineRenderCase::scanRow (const tcu::ConstPixelBufferAccess& access, int row, int rowBegin, int rowEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
 {
-	const bool numLinesOk	= checkAreaNumLines(access, tcu::IVec4(rowBegin, row, rowEnd - rowBegin, 1), messageLimitCounter, SCAN_ROW_COMPONENT_NDX, numLines);
-	const bool lineWidthOk	= checkLineWidths(access, tcu::IVec2(rowBegin, row), tcu::IVec2(rowEnd, row), SCAN_ROW_COMPONENT_NDX, messageLimitCounter);
+	const bool		numLinesOk		= checkAreaNumLines(access, tcu::IVec4(rowBegin, row, rowEnd - rowBegin, 1), messageLimitCounter, SCAN_ROW_COMPONENT_NDX, numLines);
+	const deUint8	lineWidthRes	= checkLineWidths(access, tcu::IVec2(rowBegin, row), tcu::IVec2(rowEnd, row), SCAN_ROW_COMPONENT_NDX, messageLimitCounter);
+	deUint8			result			= 0;
 
-	return	(deUint8)((numLinesOk	? (deUint8)SCANRESULT_NUM_LINES_OK_BIT	: 0u) |
-					  (lineWidthOk	? (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT	: 0u));
+	if (numLinesOk)
+		result |= (deUint8)SCANRESULT_NUM_LINES_OK_BIT;
+
+	if (lineWidthRes == 0)
+		result |= (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT;
+	else
+		result |= lineWidthRes;
+
+	return result;
 }
 
 deUint8 LineRenderCase::scanColumn (const tcu::ConstPixelBufferAccess& access, int column, int columnBegin, int columnEnd, const tcu::IVec2& numLines, int& messageLimitCounter) const
 {
-	const bool numLinesOk	= checkAreaNumLines(access, tcu::IVec4(column, columnBegin, 1, columnEnd - columnBegin), messageLimitCounter, SCAN_COL_COMPONENT_NDX, numLines);
-	const bool lineWidthOk	= checkLineWidths(access, tcu::IVec2(column, columnBegin), tcu::IVec2(column, columnEnd), SCAN_COL_COMPONENT_NDX, messageLimitCounter);
+	const bool		numLinesOk		= checkAreaNumLines(access, tcu::IVec4(column, columnBegin, 1, columnEnd - columnBegin), messageLimitCounter, SCAN_COL_COMPONENT_NDX, numLines);
+	const deUint8	lineWidthRes	= checkLineWidths(access, tcu::IVec2(column, columnBegin), tcu::IVec2(column, columnEnd), SCAN_COL_COMPONENT_NDX, messageLimitCounter);
+	deUint8			result			= 0;
 
-	return	(deUint8)((numLinesOk	? (deUint8)SCANRESULT_NUM_LINES_OK_BIT	: 0u) |
-					  (lineWidthOk	? (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT	: 0u));
+	if (numLinesOk)
+		result |= (deUint8)SCANRESULT_NUM_LINES_OK_BIT;
+
+	if (lineWidthRes == 0)
+		result |= (deUint8)SCANRESULT_LINE_WIDTH_OK_BIT;
+	else
+		result |= lineWidthRes;
+
+	return result;
 }
 
 bool LineRenderCase::checkAreaNumLines (const tcu::ConstPixelBufferAccess& access, const tcu::IVec4& area, int& messageLimitCounter, int componentNdx, const tcu::IVec2& numLines) const
@@ -2052,19 +2085,20 @@
 	return tcu::IVec2(numMinima, numMaxima);
 }
 
-bool LineRenderCase::checkLineWidths (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const
+deUint8 LineRenderCase::checkLineWidths (const tcu::ConstPixelBufferAccess& access, const tcu::IVec2& begin, const tcu::IVec2& end, int componentNdx, int& messageLimitCounter) const
 {
-	const bool			multisample		= m_context.getRenderTarget().getNumSamples() > 1;
-	const int			lineRenderWidth	= (m_isWideLineCase) ? (m_wideLineLineWidth) : 1;
-	const tcu::IVec2	lineWidthRange	= (multisample)
-											? (tcu::IVec2(lineRenderWidth, lineRenderWidth+1))	// multisampled "smooth" lines may spread to neighboring pixel
-											: (tcu::IVec2(lineRenderWidth, lineRenderWidth));
+	const bool			multisample				= m_context.getRenderTarget().getNumSamples() > 1;
+	const int			lineRenderWidth			= (m_isWideLineCase) ? (m_wideLineLineWidth) : 1;
+	const tcu::IVec2	lineWidthRange			= (multisample)
+													? (tcu::IVec2(lineRenderWidth, lineRenderWidth+1))	// multisampled "smooth" lines may spread to neighboring pixel
+													: (tcu::IVec2(lineRenderWidth, lineRenderWidth));
+	const tcu::IVec2	relaxedLineWidthRange	= (tcu::IVec2(lineRenderWidth-1, lineRenderWidth+1));
 
-	int					lineWidth		= 0;
-	bool				bboxLimitedLine	= false;
-	bool				anyError		= false;
+	int					lineWidth				= 0;
+	bool				bboxLimitedLine			= false;
+	deUint8				errorMask				= 0;
 
-	const tcu::IVec2	advance			= (begin.x() == end.x()) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0));
+	const tcu::IVec2	advance					= (begin.x() == end.x()) ? (tcu::IVec2(0, 1)) : (tcu::IVec2(1, 0));
 
 	// fragments before begin?
 	if (access.getPixelInt(begin.x(), begin.y())[componentNdx] != 0)
@@ -2099,7 +2133,13 @@
 
 			if (incorrectLineWidth)
 			{
-				anyError = true;
+				const bool incorrectRelaxedLineWidth = (lineWidth < relaxedLineWidthRange.x() && !bboxLimitedLine) || (lineWidth > relaxedLineWidthRange.y());
+
+				if (incorrectRelaxedLineWidth)
+					errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
+				else
+					errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
+
 				printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
 			}
 
@@ -2117,7 +2157,11 @@
 			{
 				if (lineWidth > lineWidthRange.y())
 				{
-					anyError = true;
+					if (lineWidth > relaxedLineWidthRange.y())
+						errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
+					else
+						errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
+
 					printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
 				}
 
@@ -2135,7 +2179,13 @@
 
 				if (incorrectLineWidth)
 				{
-					anyError = true;
+					const bool incorrectRelaxedLineWidth = (lineWidth > relaxedLineWidthRange.y());
+
+					if (incorrectRelaxedLineWidth)
+						errorMask |= SCANRESULT_LINE_WIDTH_ERR_BIT;
+					else
+						errorMask |= SCANRESULT_LINE_WIDTH_WARN_BIT;
+
 					printLineWidthError(cursor, lineWidth, lineWidthRange, advance.x() == 0, messageLimitCounter);
 				}
 
@@ -2144,7 +2194,7 @@
 		}
 	}
 
-	return !anyError;
+	return errorMask;
 }
 
 void LineRenderCase::printLineWidthError (const tcu::IVec2& pos, int detectedLineWidth, const tcu::IVec2& lineWidthRange, bool isHorizontal, int& messageLimitCounter) const
diff --git a/modules/gles31/functional/es31fSRGBDecodeTests.cpp b/modules/gles31/functional/es31fSRGBDecodeTests.cpp
new file mode 100644
index 0000000..27b9644
--- /dev/null
+++ b/modules/gles31/functional/es31fSRGBDecodeTests.cpp
@@ -0,0 +1,2057 @@
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 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 Texture format tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "es31fSRGBDecodeTests.hpp"
+#include "gluContextInfo.hpp"
+#include "gluCallLogWrapper.hpp"
+#include "gluRenderContext.hpp"
+#include "gluTexture.hpp"
+#include "glsTextureTestUtil.hpp"
+#include "tcuPixelFormat.hpp"
+#include "tcuTestContext.hpp"
+#include "tcuRenderTarget.hpp"
+#include "gluTextureUtil.hpp"
+#include "tcuTextureUtil.hpp"
+#include "glwFunctions.hpp"
+#include "gluDefs.hpp"
+#include "glwEnums.hpp"
+#include "deUniquePtr.hpp"
+#include "gluPixelTransfer.hpp"
+#include "tcuDefs.hpp"
+#include "tcuVectorUtil.hpp"
+#include "gluObjectWrapper.hpp"
+#include "gluStrUtil.hpp"
+#include "tcuTestLog.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+namespace
+{
+
+using glu::TextureTestUtil::TEXTURETYPE_2D;
+
+enum SRGBDecode
+{
+	SRGBDECODE_SKIP_DECODE		= 0,
+	SRGBDECODE_DECODE,
+	SRGBDECODE_DECODE_DEFAULT
+};
+
+enum ShaderOutputs
+{
+	SHADEROUTPUTS_ONE	= 1,
+	SHADEROUTPUTS_TWO,
+};
+
+enum ShaderUniforms
+{
+	SHADERUNIFORMS_ONE	= 1,
+	SHADERUNIFORMS_TWO,
+};
+
+enum ShaderSamplingGroup
+{
+	SHADERSAMPLINGGROUP_TEXTURE		= 0,
+	SHADERSAMPLINGGROUP_TEXEL_FETCH
+};
+
+enum ShaderSamplingType
+{
+	TEXTURESAMPLING_TEXTURE													= 0,
+	TEXTURESAMPLING_TEXTURE_LOD,
+	TEXTURESAMPLING_TEXTURE_GRAD,
+	TEXTURESAMPLING_TEXTURE_OFFSET,
+	TEXTURESAMPLING_TEXTURE_PROJ,
+	TEXTURESAMPLING_TEXELFETCH,
+	TEXTURESAMPLING_TEXELFETCH_OFFSET,
+
+	// ranges required for looping mechanism in a case nodes iteration function
+	TEXTURESAMPLING_TEXTURE_START		= TEXTURESAMPLING_TEXTURE,
+	TEXTURESAMPLING_TEXTURE_END			= TEXTURESAMPLING_TEXTURE_PROJ		+ 1,
+	TEXTURESAMPLING_TEXELFETCH_START	= TEXTURESAMPLING_TEXELFETCH,
+	TEXTURESAMPLING_TEXELFETCH_END		= TEXTURESAMPLING_TEXELFETCH_OFFSET	+ 1
+};
+
+enum FunctionParameters
+{
+	FUNCTIONPARAMETERS_ONE = 1,
+	FUNCTIONPARAMETERS_TWO
+};
+
+enum Blending
+{
+	BLENDING_REQUIRED		= 0,
+	BLENDING_NOT_REQUIRED
+};
+
+enum Toggling
+{
+	TOGGLING_REQUIRED		= 0,
+	TOGGLING_NOT_REQUIRED
+};
+
+tcu::Vec4 getColorReferenceLinear (void)
+{
+	return tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f);
+}
+
+tcu::Vec4 getColorReferenceSRGB (void)
+{
+	return tcu::linearToSRGB(tcu::Vec4(0.2f, 0.3f, 0.4f, 1.0f));
+}
+
+tcu::Vec4 getColorGreenPass (void)
+{
+	return tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
+}
+
+namespace TestDimensions
+{
+	const int WIDTH		= 128;
+	const int HEIGHT	= 128;
+} // global test texture dimensions
+
+namespace TestSamplingPositions
+{
+	const int X_POS = 0;
+	const int Y_POS = 0;
+} // global test sampling positions
+
+const char* getFunctionDefinitionSRGBToLinearCheck (void)
+{
+	static const char* functionDefinition =
+			"mediump vec4 srgbToLinearCheck(in mediump vec4 texelSRGBA, in mediump vec4 texelLinear) \n"
+			"{ \n"
+			"	const int NUM_CHANNELS = 4;"
+			"	mediump vec4 texelSRGBAConverted; \n"
+			"	mediump vec4 epsilonErr = vec4(0.005); \n"
+			"	mediump vec4 testResult; \n"
+			"	for (int idx = 0; idx < NUM_CHANNELS; idx++) \n"
+			"	{ \n"
+			"		texelSRGBAConverted[idx] = pow( (texelSRGBA[idx] + 0.055) / 1.055, 1.0 / 0.4116); \n"
+			"	} \n"
+			"	if ( all(lessThan(abs(texelSRGBAConverted - texelLinear), epsilonErr)) || all(equal(texelSRGBAConverted, texelLinear)) ) \n"
+			"	{ \n"
+			"		return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
+			"	} \n"
+			"	else \n"
+			"	{ \n"
+			"		return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
+			"	} \n"
+			"} \n";
+
+	return functionDefinition;
+}
+
+const char* getFunctionDefinitionEqualCheck (void)
+{
+	static const char* functionDefinition =
+			"mediump vec4 colorsEqualCheck(in mediump vec4 colorA, in mediump vec4 colorB) \n"
+			"{ \n"
+			"	mediump vec4 epsilonErr = vec4(0.005); \n"
+			"	mediump vec4 testResult; \n"
+			"	if ( all(lessThan(abs(colorA - colorB), epsilonErr)) || all(equal(colorA, colorB)) ) \n"
+			"	{ \n"
+			"		return testResult = vec4(0.0, 1.0, 0.0, 1.0); \n"
+			"	} \n"
+			"	else \n"
+			"	{ \n"
+			"		return testResult = vec4(1.0, 0.0, 0.0, 1.0); \n"
+			"	} \n"
+			"} \n";
+
+	return functionDefinition;
+}
+
+namespace EpsilonError
+{
+	const float CPU = 0.005f;
+}
+
+struct TestGroupConfig
+{
+	TestGroupConfig			(const char* groupName, const char* groupDescription, const tcu::TextureFormat groupInternalFormat)
+		: name				(groupName)
+		, description		(groupDescription)
+		, internalFormat	(groupInternalFormat) {}
+
+	~TestGroupConfig		(void) {};
+
+	const char*					name;
+	const char*					description;
+	const tcu::TextureFormat	internalFormat;
+};
+
+struct UniformData
+{
+	UniformData			(glw::GLuint uniformLocation, const std::string& uniformName)
+		: location		(uniformLocation)
+		, name			(uniformName)
+		, toggleDecode	(false) {}
+
+	~UniformData		(void) {}
+
+	glw::GLuint	location;
+	std::string	name;
+	bool		toggleDecode;
+};
+
+struct UniformToToggle
+{
+	UniformToToggle		(const int uniformProgramIdx, const std::string& uniformName)
+		: programIdx	(uniformProgramIdx)
+		, name			(uniformName) {}
+
+	~UniformToToggle	(void) {}
+
+	int			programIdx;
+	std::string	name;
+};
+
+struct ComparisonFunction
+{
+	ComparisonFunction		(const std::string& funcName, const FunctionParameters funcParameters, const std::string& funcImplementation)
+		: name				(funcName)
+		, parameters		(funcParameters)
+		, implementation	(funcImplementation) {}
+
+	~ComparisonFunction		(void) {}
+
+	std::string			name;
+	FunctionParameters	parameters;
+	std::string			implementation;
+};
+
+struct FragmentShaderParameters
+{
+	FragmentShaderParameters	(const ShaderOutputs	outputTotal,
+								 const ShaderUniforms	uniformTotal,
+								 ComparisonFunction*	comparisonFunction,
+								 Blending				blendRequired,
+								 Toggling				toggleRequired);
+
+	~FragmentShaderParameters	(void);
+
+	ShaderOutputs				outputTotal;
+	ShaderUniforms				uniformTotal;
+	ShaderSamplingType			samplingType;
+	std::string					functionName;
+	FunctionParameters			functionParameters;
+	std::string					functionImplementation;
+	bool						hasFunction;
+	Blending					blendRequired;
+	Toggling					toggleRequired;
+	std::vector<std::string>	uniformsToToggle;
+};
+
+FragmentShaderParameters::FragmentShaderParameters	(const ShaderOutputs	paramsOutputTotal,
+													 const ShaderUniforms	paramsUniformTotal,
+													 ComparisonFunction*	paramsComparisonFunction,
+													 Blending				paramsBlendRequired,
+													 Toggling				paramsToggleRequired)
+	: outputTotal									(paramsOutputTotal)
+	, uniformTotal									(paramsUniformTotal)
+	, blendRequired									(paramsBlendRequired)
+	, toggleRequired								(paramsToggleRequired)
+{
+	if (paramsComparisonFunction != DE_NULL)
+	{
+		functionName			= paramsComparisonFunction->name;
+		functionParameters		= paramsComparisonFunction->parameters;
+		functionImplementation	= paramsComparisonFunction->implementation;
+
+		hasFunction = true;
+	}
+	else
+	{
+		hasFunction = false;
+	}
+}
+
+FragmentShaderParameters::~FragmentShaderParameters (void)
+{
+}
+
+class SRGBTestSampler
+{
+public:
+				SRGBTestSampler		(Context&						context,
+									 const tcu::Sampler::WrapMode	wrapS,
+									 const tcu::Sampler::WrapMode	wrapT,
+									 const tcu::Sampler::FilterMode	minFilter,
+									 const tcu::Sampler::FilterMode	magFilter,
+									 const SRGBDecode				decoding);
+				~SRGBTestSampler	(void);
+
+	void		setDecode			(const SRGBDecode decoding);
+	void		setTextureUnit		(const deUint32 textureUnit);
+	void		setIsActive			(const bool isActive);
+
+	deUint32	getHandle			(void) const;
+	bool		getIsActive			(void) const;
+
+	void		bindToTexture		(void);
+	void		unbindFromTexture	(void);
+
+private:
+	const glw::Functions*		m_gl;
+	deUint32					m_samplerHandle;
+	tcu::Sampler::WrapMode		m_wrapS;
+	tcu::Sampler::WrapMode		m_wrapT;
+	tcu::Sampler::FilterMode	m_minFilter;
+	tcu::Sampler::FilterMode	m_magFilter;
+	SRGBDecode					m_decoding;
+	deUint32					m_textureUnit;
+	bool						m_isActive;
+};
+
+SRGBTestSampler::SRGBTestSampler	(Context&						context,
+									 const tcu::Sampler::WrapMode	wrapS,
+									 const tcu::Sampler::WrapMode	wrapT,
+									 const tcu::Sampler::FilterMode	minFilter,
+									 const tcu::Sampler::FilterMode	magFilter,
+									 const SRGBDecode				decoding)
+	: m_gl							(&context.getRenderContext().getFunctions())
+	, m_wrapS						(wrapS)
+	, m_wrapT						(wrapT)
+	, m_minFilter					(minFilter)
+	, m_magFilter					(magFilter)
+	, m_isActive					(false)
+{
+	m_gl->genSamplers(1, &m_samplerHandle);
+
+	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
+	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
+	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
+	m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));
+
+	this->setDecode(decoding);
+}
+
+SRGBTestSampler::~SRGBTestSampler (void)
+{
+	m_gl->deleteSamplers(1, &m_samplerHandle);
+}
+
+void SRGBTestSampler::setDecode (const SRGBDecode decoding)
+{
+	if (decoding == SRGBDECODE_SKIP_DECODE)
+	{
+		m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+		GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
+	}
+	else if (decoding == SRGBDECODE_DECODE)
+	{
+		m_gl->samplerParameteri(m_samplerHandle, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
+		GLU_EXPECT_NO_ERROR(m_gl->getError(), "samplerParameteri(m_samplerID, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
+	}
+	else
+	{
+		DE_FATAL("sRGB texture sampler must have either GL_SKIP_DECODE_EXT or GL_DECODE_EXT settings");
+	}
+
+	m_decoding = decoding;
+}
+
+void SRGBTestSampler::setTextureUnit (const deUint32 textureUnit)
+{
+	m_textureUnit = textureUnit;
+}
+
+void SRGBTestSampler::setIsActive (const bool isActive)
+{
+	m_isActive = isActive;
+}
+
+deUint32 SRGBTestSampler::getHandle (void) const
+{
+	return m_samplerHandle;
+}
+
+bool SRGBTestSampler::getIsActive (void) const
+{
+	return m_isActive;
+}
+
+void SRGBTestSampler::bindToTexture (void)
+{
+	m_gl->bindSampler(m_textureUnit, m_samplerHandle);
+}
+
+void SRGBTestSampler::unbindFromTexture (void)
+{
+	m_gl->bindSampler(m_textureUnit, 0);
+}
+
+class SRGBTestTexture
+{
+public:
+				SRGBTestTexture		(Context&									context,
+									 const glu::TextureTestUtil::TextureType	targetType,
+									 const tcu::TextureFormat					internalFormat,
+									 const int									width,
+									 const int									height,
+									 const tcu::Vec4							color,
+									 const tcu::Sampler::WrapMode				wrapS,
+									 const tcu::Sampler::WrapMode				wrapT,
+									 const tcu::Sampler::FilterMode				minFilter,
+									 const tcu::Sampler::FilterMode				magFilter,
+									 const SRGBDecode							decoding);
+				~SRGBTestTexture	(void);
+
+	void		setParameters		(void);
+	void		setDecode			(const SRGBDecode decoding);
+	void		setHasSampler		(const bool hasSampler);
+
+	deUint32	getHandle			(void) const;
+	deUint32	getGLTargetType		(void) const;
+	SRGBDecode	getDecode			(void) const;
+	bool		getHasSampler		(void) const;
+
+	void		upload				(void);
+
+private:
+	void		setColor			(void);
+
+	Context&							m_context;
+	glu::Texture2D						m_source;
+	glu::TextureTestUtil::TextureType	m_targetType;
+	const tcu::TextureFormat			m_internalFormat;
+	const int							m_width;
+	const int							m_height;
+	tcu::Vec4							m_color;
+	tcu::Sampler::WrapMode				m_wrapS;
+	tcu::Sampler::WrapMode				m_wrapT;
+	tcu::Sampler::FilterMode			m_minFilter;
+	tcu::Sampler::FilterMode			m_magFilter;
+	SRGBDecode							m_decoding;
+	bool								m_hasSampler;
+};
+
+SRGBTestTexture::SRGBTestTexture	(Context&									context,
+									 const glu::TextureTestUtil::TextureType	targetType,
+									 const tcu::TextureFormat					internalFormat,
+									 const int									width,
+									 const int									height,
+									 const tcu::Vec4							color,
+									 const tcu::Sampler::WrapMode				wrapS,
+									 const tcu::Sampler::WrapMode				wrapT,
+									 const tcu::Sampler::FilterMode				minFilter,
+									 const tcu::Sampler::FilterMode				magFilter,
+									 SRGBDecode									decoding)
+	: m_context						(context)
+	, m_source						(context.getRenderContext(), glu::getInternalFormat(internalFormat), width, height)
+	, m_targetType					(targetType)
+	, m_internalFormat				(internalFormat)
+	, m_width						(width)
+	, m_height						(height)
+	, m_color						(color)
+	, m_wrapS						(wrapS)
+	, m_wrapT						(wrapT)
+	, m_minFilter					(minFilter)
+	, m_magFilter					(magFilter)
+	, m_decoding					(decoding)
+	, m_hasSampler					(false)
+{
+	this->setColor();
+}
+
+SRGBTestTexture::~SRGBTestTexture (void)
+{
+}
+
+void SRGBTestTexture::setParameters (void)
+{
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+	gl.bindTexture(this->getGLTargetType(), this->getHandle());
+
+	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_S, glu::getGLWrapMode(m_wrapS));
+	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_WRAP_T, glu::getGLWrapMode(m_wrapT));
+	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(m_minFilter));
+	gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(m_magFilter));
+
+	gl.bindTexture(this->getGLTargetType(), 0);
+
+	setDecode(m_decoding);
+}
+
+void SRGBTestTexture::setDecode (const SRGBDecode decoding)
+{
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+	gl.bindTexture(this->getGLTargetType(), this->getHandle());
+
+	switch (decoding)
+	{
+		case SRGBDECODE_SKIP_DECODE:
+		{
+			gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
+			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT)");
+			break;
+		}
+		case SRGBDECODE_DECODE:
+		{
+			gl.texParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT);
+			GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri(this->getGLTargetType(), GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT)");
+			break;
+		}
+		case SRGBDECODE_DECODE_DEFAULT:
+		{
+			// do not use srgb decode options. Set to default
+			break;
+		}
+		default:
+			DE_FATAL("Error: Decoding option not recognised");
+	}
+
+	gl.bindTexture(this->getGLTargetType(), 0);
+
+	m_decoding = decoding;
+}
+
+void SRGBTestTexture::setHasSampler (const bool hasSampler)
+{
+	m_hasSampler = hasSampler;
+}
+
+deUint32 SRGBTestTexture::getHandle (void) const
+{
+	return m_source.getGLTexture();
+}
+
+deUint32 SRGBTestTexture::getGLTargetType (void) const
+{
+	switch (m_targetType)
+	{
+		case TEXTURETYPE_2D:
+		{
+			return GL_TEXTURE_2D;
+		}
+		default:
+		{
+			DE_FATAL("Error: Target type not recognised");
+			return -1;
+		}
+	}
+}
+
+SRGBDecode SRGBTestTexture::getDecode (void) const
+{
+	return m_decoding;
+}
+
+bool SRGBTestTexture::getHasSampler (void) const
+{
+	return m_hasSampler;
+}
+
+void SRGBTestTexture::upload (void)
+{
+	m_source.upload();
+}
+
+void SRGBTestTexture::setColor (void)
+{
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+	gl.bindTexture(this->getGLTargetType(), this->getHandle());
+
+	m_source.getRefTexture().allocLevel(0);
+
+	for (int py = 0; py < m_height; py++)
+	{
+		for (int px = 0; px < m_width; px++)
+		{
+			m_source.getRefTexture().getLevel(0).setPixel(m_color, px, py);
+		}
+	}
+
+	gl.bindTexture(this->getGLTargetType(), 0);
+}
+
+class SRGBTestProgram
+{
+public:
+									SRGBTestProgram			(Context& context, const FragmentShaderParameters& shaderParameters);
+									~SRGBTestProgram		(void);
+
+	void							setBlendRequired		(bool blendRequired);
+	void							setToggleRequired		(bool toggleRequired);
+	void							setUniformToggle		(int location, bool toggleDecodeValue);
+
+	int								getUniformTotal			(void) const;
+	const std::vector<UniformData>&	getUniformDataList		(void) const;
+	const UniformData&				getUniformAtLocation	(int location) const;
+	int								getUniformLocation		(const std::string& name);
+	deUint32						getHandle				(void) const;
+	bool							getBlendRequired		(void) const;
+	bool							getToggleRequired		(void) const;
+	const std::string&				getFragmentShader		(void) const;
+
+private:
+	std::string						genFunctionCall			(ShaderSamplingType samplingType, const int uniformIdx);
+	void							genFragmentShader		(void);
+
+	Context&						m_context;
+	de::MovePtr<glu::ShaderProgram>	m_program;
+	FragmentShaderParameters		m_shaderFragmentParameters;
+	std::string						m_shaderVertex;
+	std::string						m_shaderFragment;
+	std::vector<UniformData>		m_uniformDataList;
+	bool							m_blendRequired;
+	bool							m_toggleRequired;
+};
+
+SRGBTestProgram::SRGBTestProgram	(Context& context, const FragmentShaderParameters& shaderParameters)
+	: m_context						(context)
+	, m_shaderFragmentParameters	(shaderParameters)
+	, m_blendRequired				(false)
+	, m_toggleRequired				(false)
+{
+	const glw::Functions&	gl					= m_context.getRenderContext().getFunctions();
+	tcu::TestLog&			log					= m_context.getTestContext().getLog();
+	glu::ShaderProgramInfo	buildInfo;
+	const int				totalShaderStages	= 2;
+
+	// default vertex shader used in all tests
+	m_shaderVertex =	"#version 310 es \n"
+						"layout (location = 0) in mediump vec3 aPosition; \n"
+						"layout (location = 1) in mediump vec2 aTexCoord; \n"
+						"out mediump vec2 vs_aTexCoord; \n"
+						"void main () \n"
+						"{ \n"
+						"	gl_Position = vec4(aPosition, 1.0); \n"
+						"	vs_aTexCoord = aTexCoord; \n"
+						"} \n";
+
+	this->genFragmentShader();
+
+	m_program = de::MovePtr<glu::ShaderProgram>(new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(m_shaderVertex, m_shaderFragment)));
+
+	if (!m_program->isOk())
+	{
+		TCU_FAIL("Failed to compile shaders and link program");
+	}
+
+	glw::GLint activeUniforms, maxLen;
+	glw::GLint size, location;
+	glw::GLenum type;
+
+	gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxLen);
+	gl.getProgramiv(this->getHandle(), GL_ACTIVE_UNIFORMS, &activeUniforms);
+
+	std::vector<glw::GLchar> uniformName(static_cast<int>(maxLen));
+	for (int idx = 0; idx < activeUniforms; idx++)
+	{
+		gl.getActiveUniform(this->getHandle(), idx, maxLen, NULL, &size, &type, &uniformName[0]);
+		location = gl.getUniformLocation(this->getHandle(), &uniformName[idx]);
+
+		UniformData uniformData(location, std::string(&uniformName[0], strlen(&uniformName[0])));
+		m_uniformDataList.push_back(uniformData);
+	}
+
+	// log shader program info. Only vertex and fragment shaders included
+	buildInfo.program = m_program->getProgramInfo();
+	for (int shaderIdx = 0; shaderIdx < totalShaderStages; shaderIdx++)
+	{
+		glu::ShaderInfo shaderInfo = m_program->getShaderInfo(static_cast<glu::ShaderType>(static_cast<int>(glu::SHADERTYPE_VERTEX) + static_cast<int>(shaderIdx)), 0);
+		buildInfo.shaders.push_back(shaderInfo);
+	}
+
+	log << buildInfo;
+}
+
+SRGBTestProgram::~SRGBTestProgram (void)
+{
+	m_program	= de::MovePtr<glu::ShaderProgram>(DE_NULL);
+}
+
+void SRGBTestProgram::setBlendRequired (bool blendRequired)
+{
+	m_blendRequired = blendRequired;
+}
+
+void SRGBTestProgram::setToggleRequired (bool toggleRequired)
+{
+	m_toggleRequired = toggleRequired;
+}
+
+void SRGBTestProgram::setUniformToggle (int location, bool toggleDecodeValue)
+{
+	if ( (m_uniformDataList.empty() == false) && (location >= 0) && (location <= (int)m_uniformDataList.size()) )
+	{
+		m_uniformDataList[location].toggleDecode = toggleDecodeValue;
+	}
+	else
+	{
+		TCU_THROW(TestError, "Error: Uniform location not found. glGetActiveUniforms returned uniforms incorrectly ");
+	}
+}
+
+int SRGBTestProgram::getUniformTotal (void) const
+{
+	return (int)m_uniformDataList.size();
+}
+
+const std::vector<UniformData>& SRGBTestProgram::getUniformDataList (void) const
+{
+	return m_uniformDataList;
+}
+
+const UniformData& SRGBTestProgram::getUniformAtLocation (int location) const
+{
+	return m_uniformDataList[location];
+}
+
+int SRGBTestProgram::getUniformLocation (const std::string& name)
+{
+	for (std::size_t idx = 0; idx < m_uniformDataList.size(); idx++)
+	{
+		if (m_uniformDataList[idx].name == name)
+		{
+			return m_uniformDataList[idx].location;
+		}
+	}
+
+	TCU_THROW(TestError, "Error: If name correctly requested then glGetActiveUniforms() returned active uniform data incorrectly");
+	return -1;
+}
+
+glw::GLuint SRGBTestProgram::getHandle (void) const
+{
+	return m_program->getProgram();
+}
+
+bool SRGBTestProgram::getBlendRequired (void) const
+{
+	return m_blendRequired;
+}
+
+bool SRGBTestProgram::getToggleRequired (void) const
+{
+	return m_toggleRequired;
+}
+
+const std::string& SRGBTestProgram::getFragmentShader (void) const
+{
+	return m_shaderFragment;
+}
+
+std::string SRGBTestProgram::genFunctionCall (ShaderSamplingType samplingType, const int uniformIdx)
+{
+	std::ostringstream functionCall;
+
+	functionCall << "	mediump vec4 texelColor" << uniformIdx << " = ";
+
+	switch (samplingType)
+		{
+			case TEXTURESAMPLING_TEXTURE:
+			{
+				functionCall << "texture(uTexture" << uniformIdx << ", vs_aTexCoord); \n";
+				break;
+			}
+			case TEXTURESAMPLING_TEXTURE_LOD:
+			{
+				functionCall << "textureLod(uTexture" << uniformIdx << ", vs_aTexCoord, 0.0); \n";
+				break;
+			}
+			case TEXTURESAMPLING_TEXTURE_GRAD:
+			{
+				functionCall << "textureGrad(uTexture" << uniformIdx << ", vs_aTexCoord, vec2(0.0, 0.0), vec2(0.0, 0.0)); \n";
+				break;
+			}
+			case TEXTURESAMPLING_TEXTURE_OFFSET:
+			{
+				functionCall << "textureOffset(uTexture" << uniformIdx << ", vs_aTexCoord, ivec2(0.0, 0.0)); \n";
+				break;
+			}
+			case TEXTURESAMPLING_TEXTURE_PROJ:
+			{
+				functionCall << "textureProj(uTexture" << uniformIdx << ", vec3(vs_aTexCoord, 1.0)); \n";
+				break;
+			}
+			case TEXTURESAMPLING_TEXELFETCH:
+			{
+				functionCall << "texelFetch(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0); \n";
+				break;
+			}
+			case TEXTURESAMPLING_TEXELFETCH_OFFSET:
+			{
+				functionCall << "texelFetchOffset(uTexture" << uniformIdx << ", ivec2(vs_aTexCoord), 0, ivec2(0.0, 0.0)); \n";
+				break;
+			}
+			default:
+			{
+				DE_FATAL("Error: Sampling type not recognised");
+			}
+		}
+
+	return functionCall.str();
+}
+
+void SRGBTestProgram::genFragmentShader (void)
+{
+	std::ostringstream source;
+	std::ostringstream sampleTexture;
+	std::ostringstream functionParameters;
+	std::ostringstream shaderOutputs;
+
+	// if comparison function is present resulting shader requires precisely one output
+	DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.outputTotal) != static_cast<int>(SHADEROUTPUTS_ONE))) );
+
+	// function parameters must equal the number of uniforms i.e. textures passed into the function
+	DE_ASSERT( !(m_shaderFragmentParameters.hasFunction && (static_cast<int>(m_shaderFragmentParameters.uniformTotal) != static_cast<int>(m_shaderFragmentParameters.functionParameters))) );
+
+	// fragment shader cannot contain more outputs than the number of texture uniforms
+	DE_ASSERT( !(static_cast<int>(m_shaderFragmentParameters.outputTotal) > static_cast<int>(m_shaderFragmentParameters.uniformTotal)) ) ;
+
+	source << "#version 310 es \n"
+		<< "in mediump vec2 vs_aTexCoord; \n";
+
+	for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
+	{
+		source << "layout (location = " << output << ") out mediump vec4 fs_aColor" << output << "; \n";
+	}
+
+	for (int uniform = 0; uniform < m_shaderFragmentParameters.uniformTotal; uniform++)
+	{
+		source << "uniform sampler2D uTexture" << uniform << "; \n";
+	}
+
+	if (m_shaderFragmentParameters.hasFunction == true)
+	{
+		source << m_shaderFragmentParameters.functionImplementation;
+	}
+
+	source << "void main () \n"
+		<< "{ \n";
+
+	for (int uniformIdx = 0; uniformIdx < m_shaderFragmentParameters.uniformTotal; uniformIdx++)
+	{
+		source << this->genFunctionCall(m_shaderFragmentParameters.samplingType, uniformIdx);
+	}
+
+	if (m_shaderFragmentParameters.hasFunction == true)
+	{
+		switch ( static_cast<FunctionParameters>(m_shaderFragmentParameters.functionParameters) )
+		{
+			case FUNCTIONPARAMETERS_ONE:
+			{
+				functionParameters << "(texelColor0)";
+				break;
+			}
+			case FUNCTIONPARAMETERS_TWO:
+			{
+				functionParameters << "(texelColor0, texelColor1)";
+				break;
+			}
+			default:
+			{
+				DE_FATAL("Error: Number of comparison function parameters invalid");
+			}
+		}
+
+		shaderOutputs << "	fs_aColor0 = " << m_shaderFragmentParameters.functionName << functionParameters.str() << "; \n";
+	}
+	else
+	{
+		for (int output = 0; output < m_shaderFragmentParameters.outputTotal; output++)
+		{
+			shaderOutputs << "	fs_aColor" << output << " = texelColor" << output << "; \n";
+		}
+	}
+
+	source << shaderOutputs.str();
+	source << "} \n";
+
+	m_shaderFragment = source.str();
+}
+
+class SRGBTestCase : public TestCase
+{
+public:
+							SRGBTestCase					(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat);
+							~SRGBTestCase					(void);
+
+	void					init							(void);
+	void					deinit							(void);
+	virtual IterateResult	iterate							(void);
+
+	void					setSamplingGroup				(const ShaderSamplingGroup samplingGroup);
+	void					setSamplingLocations			(const int px, const int py);
+	void					setShaderProgramBlendRequired	(const int programIdx, const bool blend);
+	void					setShaderProgramToggleRequired	(const int programIdx, const bool toggle);
+	void					setUniformToggle				(const int programIdx, const std::string& uniformName, bool toggleDecode);
+
+	deUint32				getShaderProgramHandle			(const int programIdx) const;
+	deUint32				getTextureHandle				(const int textureIdx) const;
+
+	void					addTexture						(const glu::TextureTestUtil::TextureType	targetType,
+															 const int									width,
+															 const int									height,
+															 const tcu::Vec4							color,
+															 const tcu::Sampler::WrapMode				wrapS,
+															 const tcu::Sampler::WrapMode				wrapT,
+															 const tcu::Sampler::FilterMode				minFilter,
+															 const tcu::Sampler::FilterMode				magFilter,
+															 const SRGBDecode							decoding);
+	void					addSampler						(const tcu::Sampler::WrapMode	wrapS,
+															 const tcu::Sampler::WrapMode	wrapT,
+															 const tcu::Sampler::FilterMode	minFilter,
+															 const tcu::Sampler::FilterMode	magFilter,
+															 const SRGBDecode				decoding);
+	void					addShaderProgram				(const FragmentShaderParameters& shaderParameters);
+
+	void					genShaderPrograms				(ShaderSamplingType samplingType);
+	void					deleteShaderPrograms			(void);
+
+	void					readResultTextures				(void);
+	void					storeResultPixels				(std::vector<tcu::Vec4>& resultPixelData);
+
+	void					toggleDecode					(const std::vector<UniformData>& uniformDataList);
+	void					bindSamplerToTexture			(const int samplerIdx, const int textureIdx, const deUint32 textureUnit);
+	void					activateSampler					(const int samplerIdx, const bool active);
+	void					logColor						(const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const;
+	tcu::Vec4				formatReferenceColor			(tcu::Vec4 referenceColor);
+
+	// render function has a default implentation. Can be overriden for special cases
+	virtual void			render							(void);
+
+	// following functions must be overidden to perform individual test cases
+	virtual void			setupTest						(void) = 0;
+	virtual bool			verifyResult					(void) = 0;
+
+protected:
+	de::MovePtr<glu::Framebuffer>			m_framebuffer;
+	std::vector<SRGBTestTexture*>			m_textureSourceList;
+	std::vector<SRGBTestSampler*>			m_samplerList;
+	std::vector<glw::GLuint>				m_renderBufferList;
+	const tcu::Vec4							m_epsilonError;
+	std::vector<tcu::TextureLevel>			m_textureResultList;
+	int										m_resultOutputTotal;
+	tcu::TextureFormat						m_resultTextureFormat;
+	glw::GLuint								m_vaoID;
+	glw::GLuint								m_vertexDataID;
+	std::vector<FragmentShaderParameters>	m_shaderParametersList;
+	std::vector<SRGBTestProgram*>			m_shaderProgramList;
+	ShaderSamplingGroup						m_samplingGroup;
+	int										m_px;
+	int										m_py;
+	const tcu::TextureFormat				m_internalFormat;
+
+private:
+	void			uploadTextures	(void);
+	void			initFrameBuffer	(void);
+	void			initVertexData	(void);
+
+					SRGBTestCase	(const SRGBTestCase&);
+	SRGBTestCase&	operator=		(const SRGBTestCase&);
+};
+
+SRGBTestCase::SRGBTestCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+	: TestCase				(context, name, description)
+	, m_epsilonError		(EpsilonError::CPU)
+	, m_resultTextureFormat	(tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8))
+	, m_vaoID				((glw::GLuint)-1)
+	, m_vertexDataID		((glw::GLuint)-1)
+	, m_samplingGroup		(SHADERSAMPLINGGROUP_TEXTURE)
+	, m_internalFormat		(internalFormat)
+{
+}
+
+SRGBTestCase::~SRGBTestCase (void)
+{
+	deinit();
+}
+
+void SRGBTestCase::init (void)
+{
+	// extension requirements for test
+	if ( (glu::getInternalFormat(m_internalFormat) == GL_SRGB8_ALPHA8) && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_decode") )
+	{
+		throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_decode extension");
+	}
+
+	if ( (glu::getInternalFormat(m_internalFormat) == GL_SR8_EXT) && !(m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_sRGB_R8")) )
+	{
+		throw tcu::NotSupportedError("Test requires GL_EXT_texture_sRGB_R8 extension");
+	}
+
+	m_framebuffer = de::MovePtr<glu::Framebuffer>(new glu::Framebuffer(m_context.getRenderContext()));
+}
+
+void SRGBTestCase::deinit (void)
+{
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+	m_framebuffer	= de::MovePtr<glu::Framebuffer>(DE_NULL);
+
+	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
+	{
+		gl.deleteRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
+	}
+	m_renderBufferList.clear();
+
+	for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
+	{
+		delete m_textureSourceList[textureSourceIdx];
+	}
+	m_textureSourceList.clear();
+
+	for (std::size_t samplerIdx = 0; samplerIdx < m_samplerList.size(); samplerIdx++)
+	{
+		delete m_samplerList[samplerIdx];
+	}
+	m_samplerList.clear();
+
+	if (m_vaoID != (glw::GLuint)-1)
+	{
+		gl.deleteVertexArrays(1, &m_vaoID);
+		m_vaoID = (glw::GLuint)-1;
+	}
+
+	if (m_vertexDataID != (glw::GLuint)-1)
+	{
+		gl.deleteBuffers(1, &m_vertexDataID);
+		m_vertexDataID = (glw::GLuint)-1;
+	}
+}
+
+SRGBTestCase::IterateResult SRGBTestCase::iterate (void)
+{
+	bool	result;
+	int		startIdx	= -1;
+	int		endIdx		= -1;
+
+	this->setupTest();
+
+	if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXTURE)
+	{
+		startIdx	= static_cast<int>(TEXTURESAMPLING_TEXTURE_START);
+		endIdx		= static_cast<int>(TEXTURESAMPLING_TEXTURE_END);
+	}
+	else if (m_samplingGroup == SHADERSAMPLINGGROUP_TEXEL_FETCH)
+	{
+		startIdx	= static_cast<int>(TEXTURESAMPLING_TEXELFETCH_START);
+		endIdx		= static_cast<int>(TEXTURESAMPLING_TEXELFETCH_END);
+	}
+	else
+	{
+		DE_FATAL("Error: Sampling group not defined");
+	}
+
+	this->initVertexData();
+	this->initFrameBuffer();
+
+	// loop through all sampling types in the required sampling group, performing individual tests for each
+	for (int samplingTypeIdx = startIdx; samplingTypeIdx < endIdx; samplingTypeIdx++)
+	{
+		this->genShaderPrograms(static_cast<ShaderSamplingType>(samplingTypeIdx));
+		this->uploadTextures();
+		this->render();
+
+		result = this->verifyResult();
+
+		this->deleteShaderPrograms();
+
+		if (result == true)
+		{
+			m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
+		}
+		else
+		{
+			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result verification failed");
+			return STOP;
+		}
+	}
+
+	return STOP;
+}
+
+void SRGBTestCase::setSamplingGroup (const ShaderSamplingGroup samplingGroup)
+{
+	m_samplingGroup = samplingGroup;
+}
+
+void SRGBTestCase::setSamplingLocations (const int px, const int py)
+{
+	m_px = px;
+	m_py = py;
+}
+
+void SRGBTestCase::setShaderProgramBlendRequired (const int programIdx, const bool blend)
+{
+	m_shaderProgramList[programIdx]->setBlendRequired(blend);
+}
+
+void SRGBTestCase::setShaderProgramToggleRequired (const int programIdx, const bool toggle)
+{
+	m_shaderProgramList[programIdx]->setToggleRequired(toggle);
+}
+
+void SRGBTestCase::setUniformToggle (const int programIdx, const std::string& uniformName, bool toggleDecodeValue)
+{
+	int uniformLocation = m_shaderProgramList[programIdx]->getUniformLocation(uniformName);
+	m_shaderProgramList[programIdx]->setUniformToggle(uniformLocation, toggleDecodeValue);
+}
+
+deUint32 SRGBTestCase::getShaderProgramHandle (const int programIdx) const
+{
+	return m_shaderProgramList[programIdx]->getHandle();
+}
+
+deUint32 SRGBTestCase::getTextureHandle (const int textureIdx) const
+{
+	return m_textureSourceList[textureIdx]->getHandle();
+}
+
+void SRGBTestCase::addTexture (	const glu::TextureTestUtil::TextureType	targetType,
+								const int								width,
+								const int								height,
+								const tcu::Vec4							color,
+								const tcu::Sampler::WrapMode			wrapS,
+								const tcu::Sampler::WrapMode			wrapT,
+								const tcu::Sampler::FilterMode			minFilter,
+								const tcu::Sampler::FilterMode			magFilter,
+								const SRGBDecode						decoding)
+{
+	SRGBTestTexture* texture = new SRGBTestTexture(m_context, targetType, m_internalFormat, width, height, color, wrapS, wrapT, minFilter, magFilter, decoding);
+	m_textureSourceList.push_back(texture);
+}
+
+void SRGBTestCase::addSampler (	const tcu::Sampler::WrapMode	wrapS,
+								const tcu::Sampler::WrapMode	wrapT,
+								const tcu::Sampler::FilterMode	minFilter,
+								const tcu::Sampler::FilterMode	magFilter,
+								const SRGBDecode				decoding)
+{
+	SRGBTestSampler *sampler = new SRGBTestSampler(m_context, wrapS, wrapT, minFilter, magFilter, decoding);
+	m_samplerList.push_back(sampler);
+}
+
+void SRGBTestCase::addShaderProgram (const FragmentShaderParameters& shaderParameters)
+{
+	m_shaderParametersList.push_back(shaderParameters);
+	m_resultOutputTotal = shaderParameters.outputTotal;
+}
+
+void SRGBTestCase::genShaderPrograms (ShaderSamplingType samplingType)
+{
+	for (int shaderParamsIdx = 0; shaderParamsIdx < (int)m_shaderParametersList.size(); shaderParamsIdx++)
+	{
+		m_shaderParametersList[shaderParamsIdx].samplingType = samplingType;
+		SRGBTestProgram* shaderProgram = new SRGBTestProgram(m_context, m_shaderParametersList[shaderParamsIdx]);
+
+		if (m_shaderParametersList[shaderParamsIdx].blendRequired == BLENDING_REQUIRED)
+		{
+			shaderProgram->setBlendRequired(true);
+		}
+
+		if (m_shaderParametersList[shaderParamsIdx].toggleRequired == TOGGLING_REQUIRED)
+		{
+			shaderProgram->setToggleRequired(true);
+			std::vector<std::string> uniformsToToggle = m_shaderParametersList[shaderParamsIdx].uniformsToToggle;
+
+			for (int uniformNameIdx = 0; uniformNameIdx < (int)uniformsToToggle.size(); uniformNameIdx++)
+			{
+				shaderProgram->setUniformToggle(shaderProgram->getUniformLocation(uniformsToToggle[uniformNameIdx]), true);
+			}
+		}
+
+		m_shaderProgramList.push_back(shaderProgram);
+	}
+}
+
+void SRGBTestCase::deleteShaderPrograms (void)
+{
+	for (std::size_t idx = 0; idx < m_shaderProgramList.size(); idx++)
+	{
+		delete m_shaderProgramList[idx];
+	}
+	m_shaderProgramList.clear();
+}
+
+void SRGBTestCase::readResultTextures (void)
+{
+	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
+	int						width	= m_context.getRenderContext().getRenderTarget().getWidth();
+	int						height	= m_context.getRenderContext().getRenderTarget().getHeight();
+
+	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
+
+	m_textureResultList.resize(m_renderBufferList.size());
+
+	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
+	{
+		gl.readBuffer(GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx);
+		m_textureResultList[renderBufferIdx].setStorage(m_resultTextureFormat, width, height);
+		glu::readPixels(m_context.getRenderContext(), 0, 0, m_textureResultList[renderBufferIdx].getAccess());
+		GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
+	}
+
+	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+void SRGBTestCase::storeResultPixels (std::vector<tcu::Vec4>& resultPixelData)
+{
+	tcu::TestLog&		log			= m_context.getTestContext().getLog();
+	std::ostringstream	message;
+	int					width		= m_context.getRenderContext().getRenderTarget().getWidth();
+	int					height		= m_context.getRenderContext().getRenderTarget().getHeight();
+
+	// ensure result sampling coordinates are within range of the result color attachment
+	DE_ASSERT((m_px >= 0) && (m_px < width));
+	DE_ASSERT((m_py >= 0) && (m_py < height));
+	DE_UNREF(width && height);
+
+	for (int idx = 0; idx < (int)m_textureResultList.size(); idx++)
+	{
+		resultPixelData.push_back(m_textureResultList[idx].getAccess().getPixel(m_px, m_py));
+		this->logColor(std::string("Result color: "), idx, resultPixelData[idx]);
+	}
+
+	// log error rate (threshold)
+	message << m_epsilonError;
+	log << tcu::TestLog::Message << std::string("Epsilon error: ") << message.str() << tcu::TestLog::EndMessage;
+}
+
+void SRGBTestCase::toggleDecode (const std::vector<UniformData>& uniformDataList)
+{
+	DE_ASSERT( uniformDataList.size() <= m_textureSourceList.size() );
+
+	for (int uniformIdx = 0; uniformIdx < (int)uniformDataList.size(); uniformIdx++)
+	{
+		if (uniformDataList[uniformIdx].toggleDecode == true)
+		{
+			if (m_textureSourceList[uniformIdx]->getDecode() == SRGBDECODE_DECODE_DEFAULT)
+			{
+				// cannot toggle default
+				continue;
+			}
+
+			// toggle sRGB decode values (ignoring value if set to default)
+			m_textureSourceList[uniformIdx]->setDecode((SRGBDecode)((m_textureSourceList[uniformIdx]->getDecode() + 1) % SRGBDECODE_DECODE_DEFAULT));
+		}
+	}
+}
+
+void SRGBTestCase::bindSamplerToTexture (const int samplerIdx, const int textureIdx, const deUint32 textureUnit)
+{
+	deUint32 enumConversion = textureUnit - GL_TEXTURE0;
+	m_textureSourceList[textureIdx]->setHasSampler(true);
+	m_samplerList[samplerIdx]->setTextureUnit(enumConversion);
+}
+
+void SRGBTestCase::activateSampler (const int samplerIdx, const bool active)
+{
+	m_samplerList[samplerIdx]->setIsActive(active);
+}
+
+void SRGBTestCase::logColor (const std::string& colorLogMessage, int colorIdx, tcu::Vec4 color) const
+{
+	tcu::TestLog&			log		= m_context.getTestContext().getLog();
+	std::ostringstream		message;
+
+	message << colorLogMessage << colorIdx << " = (" << color.x() << ", " << color.y() << ", " << color.z() << ", " << color.w() << ")";
+	log << tcu::TestLog::Message << message.str() << tcu::TestLog::EndMessage;
+}
+
+tcu::Vec4 SRGBTestCase::formatReferenceColor (tcu::Vec4 referenceColor)
+{
+	switch (glu::getInternalFormat(m_internalFormat))
+	{
+		case GL_SRGB8_ALPHA8:
+		{
+			return referenceColor;
+		}
+		case GL_SR8_EXT:
+		{
+			// zero unwanted color channels
+			referenceColor.y() = 0;
+			referenceColor.z() = 0;
+			return referenceColor;
+		}
+		default:
+		{
+			DE_FATAL("Error: Internal format not recognised");
+			return referenceColor;
+		}
+	}
+}
+
+void SRGBTestCase::render (void)
+{
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+	// default rendering only uses one program
+	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
+	gl.bindVertexArray(m_vaoID);
+
+	gl.useProgram(m_shaderProgramList[0]->getHandle());
+
+	for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
+	{
+		gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
+		gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
+		glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[0]->getHandle(), m_shaderProgramList[0]->getUniformAtLocation(textureSourceIdx).name.c_str());
+		TCU_CHECK(samplerUniformLocationID != (glw::GLuint)-1);
+		gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
+	}
+
+	for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
+	{
+		if (m_samplerList[samplerIdx]->getIsActive() == true)
+		{
+			m_samplerList[samplerIdx]->bindToTexture();
+		}
+	}
+
+	gl.drawArrays(GL_TRIANGLES, 0, 6);
+
+	for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
+	{
+		gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
+	}
+	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+	gl.bindVertexArray(0);
+	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+void SRGBTestCase::uploadTextures (void)
+{
+	for (std::size_t idx = 0; idx < m_textureSourceList.size(); idx++)
+	{
+		m_textureSourceList[idx]->upload();
+		m_textureSourceList[idx]->setParameters();
+	}
+}
+
+void SRGBTestCase::initFrameBuffer (void)
+{
+	const glw::Functions&	gl		= m_context.getRenderContext().getFunctions();
+	int						width	= m_context.getRenderContext().getRenderTarget().getWidth();
+	int						height	= m_context.getRenderContext().getRenderTarget().getHeight();
+
+	if (m_resultOutputTotal == 0)
+	{
+		throw std::invalid_argument("SRGBTestExecutor must have at least 1 rendered result");
+	}
+
+	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
+
+	DE_ASSERT(m_renderBufferList.empty());
+	for (int outputIdx = 0; outputIdx < m_resultOutputTotal; outputIdx++)
+	{
+		glw::GLuint renderBuffer = -1;
+		m_renderBufferList.push_back(renderBuffer);
+	}
+
+	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
+	{
+		gl.genRenderbuffers(1, &m_renderBufferList[renderBufferIdx]);
+		gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
+		gl.renderbufferStorage(GL_RENDERBUFFER, glu::getInternalFormat(m_resultTextureFormat), width, height);
+		gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx, GL_RENDERBUFFER, m_renderBufferList[renderBufferIdx]);
+		GLU_EXPECT_NO_ERROR(gl.getError(), "Create and setup renderbuffer object");
+	}
+	TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
+
+	std::vector<glw::GLenum> renderBufferTargets(m_renderBufferList.size());
+	for (std::size_t renderBufferIdx = 0; renderBufferIdx < m_renderBufferList.size(); renderBufferIdx++)
+	{
+		renderBufferTargets[renderBufferIdx] = GL_COLOR_ATTACHMENT0 + (glw::GLenum)renderBufferIdx;
+	}
+	gl.drawBuffers((glw::GLsizei)renderBufferTargets.size(), &renderBufferTargets[0]);
+	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawBuffer()");
+
+	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+void SRGBTestCase::initVertexData (void)
+{
+	const glw::Functions&	gl				= m_context.getRenderContext().getFunctions();
+
+	static const glw::GLfloat squareVertexData[] =
+	{
+		// position				// texcoord
+		-1.0f, -1.0f, 0.0f,		0.0f, 0.0f, // bottom left corner
+		 1.0f, -1.0f, 0.0f,		1.0f, 0.0f, // bottom right corner
+		 1.0f,  1.0f, 0.0f,		1.0f, 1.0f, // Top right corner
+
+		-1.0f,  1.0f, 0.0f,		0.0f, 1.0f, // top left corner
+		 1.0f,  1.0f, 0.0f,		1.0f, 1.0f, // Top right corner
+		-1.0f, -1.0f, 0.0f,		0.0f, 0.0f  // bottom left corner
+	};
+
+	DE_ASSERT(m_vaoID == (glw::GLuint)-1);
+	gl.genVertexArrays(1, &m_vaoID);
+	gl.bindVertexArray(m_vaoID);
+
+	gl.genBuffers(1, &m_vertexDataID);
+	gl.bindBuffer(GL_ARRAY_BUFFER, m_vertexDataID);
+	gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizei)sizeof(squareVertexData), squareVertexData, GL_STATIC_DRAW);
+
+	gl.vertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)0);
+	gl.enableVertexAttribArray(0);
+	gl.vertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * (glw::GLsizei)sizeof(GL_FLOAT), (glw::GLvoid *)(3 * sizeof(GL_FLOAT)));
+	gl.enableVertexAttribArray(1);
+
+	gl.bindVertexArray(0);
+	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+class TextureDecodeSkippedCase : public SRGBTestCase
+{
+public:
+			TextureDecodeSkippedCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+				: SRGBTestCase			(context, name, description, internalFormat) {}
+
+			~TextureDecodeSkippedCase	(void) {}
+
+	void	setupTest					(void);
+	bool	verifyResult				(void);
+};
+
+void TextureDecodeSkippedCase::setupTest (void)
+{
+	// TEST STEPS:
+	//	- create and set texture to DECODE_SKIP_EXT
+	//	- store texture on GPU
+	//	- in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
+	//	- on the host, read back the pixel values into a tcu::TextureLevel
+	//	- analyse the texel values, expecting them in sRGB format i.e. linear space decoding was skipped
+
+	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+	this->addTexture(	TEXTURETYPE_2D,
+						TestDimensions::WIDTH,
+						TestDimensions::HEIGHT,
+						getColorReferenceLinear(),
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::LINEAR,
+						tcu::Sampler::LINEAR,
+						SRGBDECODE_SKIP_DECODE);
+
+	this->addShaderProgram(shaderParameters);
+	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+
+	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool TextureDecodeSkippedCase::verifyResult (void)
+{
+	tcu::TestLog&			log				= m_context.getTestContext().getLog();
+	const int				resultColorIdx	= 0;
+	std::vector<tcu::Vec4>	pixelResultList;
+	tcu::Vec4				pixelConverted;
+	tcu::Vec4				pixelReference;
+	tcu::Vec4				pixelExpected;
+
+	this->readResultTextures();
+	this->storeResultPixels(pixelResultList);
+
+	pixelConverted = tcu::sRGBToLinear(pixelResultList[resultColorIdx]);
+	pixelReference = this->formatReferenceColor(getColorReferenceLinear());
+	pixelExpected = this->formatReferenceColor(getColorReferenceSRGB());
+
+	this->formatReferenceColor(pixelReference);
+	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
+
+	// result color 0 should be sRGB. Compare with linear reference color
+	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
+	{
+		log << tcu::TestLog::Message << std::string("sRGB as expected") << tcu::TestLog::EndMessage;
+		return true;
+	}
+	else
+	{
+		log << tcu::TestLog::Message << std::string("not sRGB as expected") << tcu::TestLog::EndMessage;
+		return false;
+	}
+}
+
+class TextureDecodeEnabledCase : public SRGBTestCase
+{
+public:
+		TextureDecodeEnabledCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+			: SRGBTestCase			(context, name, description, internalFormat) {}
+
+		~TextureDecodeEnabledCase	(void) {}
+
+		void	setupTest			(void);
+		bool	verifyResult		(void);
+};
+
+void TextureDecodeEnabledCase::setupTest (void)
+{
+	// TEST STEPS:
+	//	- create and set texture to DECODE_EXT
+	//	- store texture on GPU
+	//	- in fragment shader, sample the texture using texture*() and render texel values to a color attachment in the FBO
+	//	- on the host, read back the pixel values into a tcu::TextureLevel
+	//	- analyse the texel values, expecting them in lRGB format i.e. linear space decoding was enabled
+
+	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+	this->addTexture(	TEXTURETYPE_2D,
+						TestDimensions::WIDTH,
+						TestDimensions::HEIGHT,
+						getColorReferenceLinear(),
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::LINEAR,
+						tcu::Sampler::LINEAR,
+						SRGBDECODE_DECODE);
+
+	this->addShaderProgram(shaderParameters);
+
+	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+
+	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool TextureDecodeEnabledCase::verifyResult (void)
+{
+	tcu::TestLog&			log				= m_context.getTestContext().getLog();
+	const int				resultColorIdx	= 0;
+	std::vector<tcu::Vec4>	pixelResultList;
+	tcu::Vec4				pixelConverted;
+	tcu::Vec4				pixelReference;
+	tcu::Vec4				pixelExpected;
+
+	this->readResultTextures();
+	this->storeResultPixels(pixelResultList);
+
+	pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
+	pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
+	pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
+
+	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
+
+	// result color 0 should be SRGB. Compare with sRGB reference color
+	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
+	{
+		log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
+		return true;
+	}
+	else
+	{
+		log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
+		return false;
+	}
+}
+
+class TexelFetchDecodeSkippedcase : public SRGBTestCase
+{
+public:
+			TexelFetchDecodeSkippedcase		(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+				: SRGBTestCase				(context, name, description, internalFormat) {}
+
+			~TexelFetchDecodeSkippedcase	(void) {}
+
+	void	setupTest						(void);
+	bool	verifyResult					(void);
+};
+
+void TexelFetchDecodeSkippedcase::setupTest (void)
+{
+	// TEST STEPS:
+	//	- create and set texture to DECODE_SKIP_EXT
+	//	- store texture on GPU
+	//	- in fragment shader, sample the texture using texelFetch*() and render texel values to a color attachment in the FBO
+	//	- on the host, read back the pixel values into a tcu::TextureLevel
+	//	- analyse the texel values, expecting them in lRGB format i.e. linear space decoding is always enabled with texelFetch*()
+
+	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+	this->addTexture(	TEXTURETYPE_2D,
+						TestDimensions::WIDTH,
+						TestDimensions::HEIGHT,
+						getColorReferenceLinear(),
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::LINEAR,
+						tcu::Sampler::LINEAR,
+						SRGBDECODE_SKIP_DECODE);
+
+	this->addShaderProgram(shaderParameters);
+
+	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+
+	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXEL_FETCH);
+}
+
+bool TexelFetchDecodeSkippedcase::verifyResult (void)
+{
+	tcu::TestLog&			log				= m_context.getTestContext().getLog();
+	const int				resultColorIdx	= 0;
+	std::vector<tcu::Vec4>	pixelResultList;
+	tcu::Vec4				pixelReference;
+	tcu::Vec4				pixelExpected;
+
+	this->readResultTextures();
+	this->storeResultPixels(pixelResultList);
+
+	pixelReference = pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
+
+	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
+
+	// result color 0 should be linear due to automatic conversion via texelFetch*(). Compare with linear reference color
+	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelResultList[0] - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelResultList[0], pixelReference))) )
+	{
+		log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
+		return true;
+	}
+	else
+	{
+		log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
+		return false;
+	}
+}
+
+class GPUConversionDecodeEnabledCase : public SRGBTestCase
+{
+public:
+			GPUConversionDecodeEnabledCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+				: SRGBTestCase				(context, name, description, internalFormat) {}
+
+			~GPUConversionDecodeEnabledCase	(void) {}
+
+	void	setupTest						(void);
+	bool	verifyResult					(void);
+};
+
+void GPUConversionDecodeEnabledCase::setupTest (void)
+{
+	// TEST STEPS:
+	//	- create and set texture_a to DECODE_SKIP_EXT and texture_b to default
+	//	- store textures on GPU
+	//	- in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_b
+	//	- in fragment shader, compare converted texture_b with texture_a
+	//	- render green image for pass or red for fail
+
+	ComparisonFunction comparisonFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());
+
+	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &comparisonFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+	this->addTexture(	TEXTURETYPE_2D,
+						TestDimensions::WIDTH,
+						TestDimensions::HEIGHT,
+						getColorReferenceLinear(),
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::LINEAR,
+						tcu::Sampler::LINEAR,
+						SRGBDECODE_SKIP_DECODE);
+
+	this->addTexture(	TEXTURETYPE_2D,
+						TestDimensions::WIDTH,
+						TestDimensions::HEIGHT,
+						getColorReferenceLinear(),
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::LINEAR,
+						tcu::Sampler::LINEAR,
+						SRGBDECODE_DECODE_DEFAULT);
+
+	this->addShaderProgram(shaderParameters);
+
+	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+
+	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool GPUConversionDecodeEnabledCase::verifyResult (void)
+{
+	tcu::TestLog&			log				= m_context.getTestContext().getLog();
+	const int				resultColorIdx	= 0;
+	std::vector<tcu::Vec4>	pixelResultList;
+
+	this->readResultTextures();
+	this->storeResultPixels(pixelResultList);
+	this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());
+
+	// result color returned from GPU is either green (pass) or fail (red)
+	if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
+	{
+		log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
+		return true;
+	}
+	else
+	{
+		log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
+		return false;
+	}
+}
+
+class DecodeToggledCase : public SRGBTestCase
+{
+public:
+			DecodeToggledCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+				: SRGBTestCase	(context, name, description, internalFormat) {}
+
+			~DecodeToggledCase	(void) {}
+
+	void	render				(void);
+	void	setupTest			(void);
+	bool	verifyResult		(void);
+};
+
+void DecodeToggledCase::render (void)
+{
+	// override the base SRGBTestCase render function with the purpose of switching between shader programs,
+	// toggling texture sRGB decode state between draw calls
+	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
+
+	gl.bindFramebuffer(GL_FRAMEBUFFER, **m_framebuffer);
+	gl.bindVertexArray(m_vaoID);
+
+	for (std::size_t programIdx = 0; programIdx < m_shaderProgramList.size(); programIdx++)
+	{
+		gl.useProgram(m_shaderProgramList[programIdx]->getHandle());
+
+		this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());
+
+		for (int textureSourceIdx = 0; textureSourceIdx < (int)m_textureSourceList.size(); textureSourceIdx++)
+		{
+			gl.activeTexture(GL_TEXTURE0 + (glw::GLenum)textureSourceIdx);
+			gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), m_textureSourceList[textureSourceIdx]->getHandle());
+			glw::GLuint samplerUniformLocationID = gl.getUniformLocation(m_shaderProgramList[programIdx]->getHandle(), m_shaderProgramList[programIdx]->getUniformAtLocation(textureSourceIdx).name.c_str());
+			TCU_CHECK(samplerUniformLocationID != (glw::GLuint) - 1);
+			gl.uniform1i(samplerUniformLocationID, (glw::GLenum)textureSourceIdx);
+		}
+
+		for (int samplerIdx = 0; samplerIdx < (int)m_samplerList.size(); samplerIdx++)
+		{
+			if (m_samplerList[samplerIdx]->getIsActive() == true)
+			{
+				m_samplerList[samplerIdx]->bindToTexture();
+			}
+		}
+
+		if (m_shaderProgramList[programIdx]->getBlendRequired() == true)
+		{
+			gl.enable(GL_BLEND);
+			gl.blendEquation(GL_MAX);
+			gl.blendFunc(GL_ONE, GL_ONE);
+		}
+		else
+		{
+			gl.disable(GL_BLEND);
+		}
+
+		gl.drawArrays(GL_TRIANGLES, 0, 6);
+
+		// reset sRGB decode state on textures
+		this->toggleDecode(m_shaderProgramList[programIdx]->getUniformDataList());
+	}
+
+	for (std::size_t textureSourceIdx = 0; textureSourceIdx < m_textureSourceList.size(); textureSourceIdx++)
+	{
+		gl.bindTexture(m_textureSourceList[textureSourceIdx]->getGLTargetType(), 0);
+	}
+	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
+	gl.bindVertexArray(0);
+	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+void DecodeToggledCase::setupTest (void)
+{
+	// TEST STEPS:
+	//	- create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
+	//	- create and use two seperate shader programs, program_a and program_b, each using different fragment shaders
+	//	- store texture_a and texture_b on GPU
+	// FIRST PASS:
+	//	- use program_a
+	//	- in fragment shader, sample both textures using texture*() and manually perform sRGB to lRGB conversion on texture_a
+	//	- in fragment shader, test converted texture_a value with texture_b
+	//	- render green image for pass or red for fail
+	//	- store result in a color attachement 0
+	// TOGGLE STAGE
+	//	- during rendering, toggle texture_a from DECODE_SKIP_EXT to DECODE_EXT
+	// SECOND PASS:
+	//	- use program_b
+	//	- in fragment shader, sample both textures using texture*() and manually perform equality check. Both should be linear
+	//	- blend first pass result with second pass. Anything but a green result equals fail
+
+	ComparisonFunction srgbToLinearFunction("srgbToLinearCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionSRGBToLinearCheck());
+	ComparisonFunction colorsEqualFunction("colorsEqualCheck", FUNCTIONPARAMETERS_TWO, getFunctionDefinitionEqualCheck());
+
+	FragmentShaderParameters shaderParametersA(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &srgbToLinearFunction, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+	FragmentShaderParameters shaderParametersB(SHADEROUTPUTS_ONE, SHADERUNIFORMS_TWO, &colorsEqualFunction, BLENDING_REQUIRED, TOGGLING_REQUIRED);
+
+	// need to specify which texture uniform to toggle DECODE_EXT/SKIP_DECODE_EXT
+	shaderParametersB.uniformsToToggle.push_back("uTexture0");
+
+	this->addTexture(	TEXTURETYPE_2D,
+						TestDimensions::WIDTH,
+						TestDimensions::HEIGHT,
+						getColorReferenceLinear(),
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::LINEAR,
+						tcu::Sampler::LINEAR,
+						SRGBDECODE_SKIP_DECODE);
+
+	this->addTexture(	TEXTURETYPE_2D,
+						TestDimensions::WIDTH,
+						TestDimensions::HEIGHT,
+						getColorReferenceLinear(),
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::LINEAR,
+						tcu::Sampler::LINEAR,
+						SRGBDECODE_DECODE);
+
+	this->addShaderProgram(shaderParametersA);
+	this->addShaderProgram(shaderParametersB);
+
+	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool DecodeToggledCase::verifyResult (void)
+{
+	tcu::TestLog&			log				= m_context.getTestContext().getLog();
+	const int				resultColorIdx	= 0;
+	std::vector<tcu::Vec4>	pixelResultList;
+
+	this->readResultTextures();
+	this->storeResultPixels(pixelResultList);
+	this->logColor(std::string("Expected color: "), resultColorIdx, getColorGreenPass());
+
+	//	result color is either green (pass) or fail (red)
+	if ( tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], getColorGreenPass())) )
+	{
+		log << tcu::TestLog::Message << std::string("returned pass color from GPU") << tcu::TestLog::EndMessage;
+		return true;
+	}
+	else
+	{
+		log << tcu::TestLog::Message << std::string("returned fail color from GPU") << tcu::TestLog::EndMessage;
+		return false;
+	}
+}
+
+class DecodeMultipleTexturesCase : public SRGBTestCase
+{
+public:
+			DecodeMultipleTexturesCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+				: SRGBTestCase			(context, name, description, internalFormat) {}
+
+			~DecodeMultipleTexturesCase	(void) {}
+
+	void	setupTest					(void);
+	bool	verifyResult				(void);
+};
+
+void DecodeMultipleTexturesCase::setupTest (void)
+{
+	// TEST STEPS:
+	//	- create and set texture_a to DECODE_SKIP_EXT and texture_b to DECODE_EXT
+	//	- upload textures to the GPU and bind to seperate uniform variables
+	//	- sample both textures using texture*()
+	//	- read texel values back to the CPU
+	//	- compare the texel values, both should be different from each other
+
+	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_TWO, SHADERUNIFORMS_TWO, NULL,  BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+	this->addTexture(	TEXTURETYPE_2D,
+						TestDimensions::WIDTH,
+						TestDimensions::HEIGHT,
+						getColorReferenceLinear(),
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::LINEAR,
+						tcu::Sampler::LINEAR,
+						SRGBDECODE_SKIP_DECODE);
+
+	this->addTexture(	TEXTURETYPE_2D,
+						TestDimensions::WIDTH,
+						TestDimensions::HEIGHT,
+						getColorReferenceLinear(),
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::LINEAR,
+						tcu::Sampler::LINEAR,
+						SRGBDECODE_DECODE);
+
+	this->addShaderProgram(shaderParameters);
+
+	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool DecodeMultipleTexturesCase::verifyResult (void)
+{
+	tcu::TestLog&			log				= m_context.getTestContext().getLog();
+	const int				resultColorIdx	= 0;
+	std::vector<tcu::Vec4>	pixelResultList;
+	tcu::Vec4				pixelExpected0;
+	tcu::Vec4				pixelExpected1;
+
+	this->readResultTextures();
+	this->storeResultPixels(pixelResultList);
+
+	pixelExpected0 = this->formatReferenceColor(getColorReferenceSRGB());
+	pixelExpected1 = this->formatReferenceColor(getColorReferenceLinear());
+
+	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected0);
+	this->logColor(std::string("Expected color: "), resultColorIdx +1, pixelExpected1);
+
+	//	check if the two textures have different values i.e. uTexture0 = sRGB and uTexture1 = linear
+	if ( !(tcu::boolAll(tcu::equal(pixelResultList[resultColorIdx], pixelResultList[resultColorIdx +1]))) )
+	{
+		log << tcu::TestLog::Message << std::string("texel values are different") << tcu::TestLog::EndMessage;
+		return true;
+	}
+	else
+	{
+		log << tcu::TestLog::Message << std::string("texel values are equal") << tcu::TestLog::EndMessage;
+		return false;
+	}
+}
+
+class DecodeSamplerCase : public SRGBTestCase
+{
+public:
+			DecodeSamplerCase	(Context& context, const char* name, const char* description, const tcu::TextureFormat internalFormat)
+				: SRGBTestCase	(context, name, description, internalFormat) {}
+
+			~DecodeSamplerCase	(void) {}
+
+	void	setupTest			(void);
+	bool	verifyResult		(void);
+};
+
+void DecodeSamplerCase::setupTest (void)
+{
+	// TEST STEPS:
+	//	- create and set texture_a to DECODE_SKIP_EXT
+	//	- upload texture to the GPU and bind to sampler
+	//	- sample texture using texture*()
+	//	- read texel values back to the CPU
+	//	- compare the texel values, should be in sampler format (linear)
+
+	FragmentShaderParameters shaderParameters(SHADEROUTPUTS_ONE, SHADERUNIFORMS_ONE, NULL, BLENDING_NOT_REQUIRED, TOGGLING_NOT_REQUIRED);
+
+	this->addTexture(	TEXTURETYPE_2D,
+						TestDimensions::WIDTH,
+						TestDimensions::HEIGHT,
+						getColorReferenceLinear(),
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::LINEAR,
+						tcu::Sampler::LINEAR,
+						SRGBDECODE_SKIP_DECODE);
+
+	this->addSampler(	tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::MIRRORED_REPEAT_GL,
+						tcu::Sampler::LINEAR,
+						tcu::Sampler::LINEAR,
+						SRGBDECODE_DECODE);
+
+	this->addShaderProgram(shaderParameters);
+
+	this->bindSamplerToTexture(0, 0, GL_TEXTURE0);
+	this->activateSampler(0, true);
+
+	this->setSamplingLocations(TestSamplingPositions::X_POS, TestSamplingPositions::Y_POS);
+	this->setSamplingGroup(SHADERSAMPLINGGROUP_TEXTURE);
+}
+
+bool DecodeSamplerCase::verifyResult (void)
+{
+	tcu::TestLog&			log				= m_context.getTestContext().getLog();
+	const int				resultColorIdx	= 0;
+	std::vector<tcu::Vec4>	pixelResultList;
+	tcu::Vec4				pixelConverted;
+	tcu::Vec4				pixelReference;
+	tcu::Vec4				pixelExpected;
+
+	this->readResultTextures();
+	this->storeResultPixels(pixelResultList);
+
+	pixelConverted = tcu::linearToSRGB(pixelResultList[resultColorIdx]);
+	pixelReference = this->formatReferenceColor(getColorReferenceSRGB());
+	pixelExpected = this->formatReferenceColor(getColorReferenceLinear());
+
+	this->logColor(std::string("Expected color: "), resultColorIdx, pixelExpected);
+
+	//	texture was rendered using a sampler object with setting DECODE_EXT, therefore, results should be linear
+	if ( (tcu::boolAll(tcu::lessThan(tcu::abs(pixelConverted - pixelReference), m_epsilonError))) || (tcu::boolAll(tcu::equal(pixelConverted, pixelReference))) )
+	{
+		log << tcu::TestLog::Message << std::string("linear as expected") << tcu::TestLog::EndMessage;
+		return true;
+	}
+	else
+	{
+		log << tcu::TestLog::Message << std::string("not linear as expected") << tcu::TestLog::EndMessage;
+		return false;
+	}
+}
+
+} // anonymous
+
+SRGBDecodeTests::SRGBDecodeTests	(Context& context)
+	: TestCaseGroup					(context, "skip_decode", "sRGB skip decode tests")
+{
+}
+
+SRGBDecodeTests::~SRGBDecodeTests (void)
+{
+}
+
+void SRGBDecodeTests::init (void)
+{
+	const TestGroupConfig testGroupConfigList[] =
+	{
+		TestGroupConfig("srgba8",	"srgb decode tests using srgba internal format",	tcu::TextureFormat(tcu::TextureFormat::sRGBA, tcu::TextureFormat::UNORM_INT8)),
+		TestGroupConfig("sr8",		"srgb decode tests using sr8 internal format",		tcu::TextureFormat(tcu::TextureFormat::sR, tcu::TextureFormat::UNORM_INT8))
+	};
+
+	// create groups for all desired internal formats, adding test cases to each
+	for (std::size_t idx = 0; idx < DE_LENGTH_OF_ARRAY(testGroupConfigList); idx++)
+	{
+		tcu::TestCaseGroup* const testGroup = new tcu::TestCaseGroup(m_testCtx, testGroupConfigList[idx].name, testGroupConfigList[idx].description);
+		tcu::TestNode::addChild(testGroup);
+
+		testGroup->addChild(new TextureDecodeSkippedCase		(m_context, "skipped",			"testing for sRGB color values with sRGB texture decoding skipped",		testGroupConfigList[idx].internalFormat));
+		testGroup->addChild(new TextureDecodeEnabledCase		(m_context, "enabled",			"testing for linear color values with sRGB texture decoding enabled",	testGroupConfigList[idx].internalFormat));
+		testGroup->addChild(new TexelFetchDecodeSkippedcase		(m_context, "texel_fetch",		"testing for linear color values with sRGB texture decoding skipped",	testGroupConfigList[idx].internalFormat));
+		testGroup->addChild(new GPUConversionDecodeEnabledCase	(m_context, "conversion_gpu",	"sampling linear values and performing conversion on the gpu",			testGroupConfigList[idx].internalFormat));
+		testGroup->addChild(new DecodeToggledCase				(m_context, "toggled",			"toggle the sRGB decoding between draw calls",							testGroupConfigList[idx].internalFormat));
+		testGroup->addChild(new DecodeMultipleTexturesCase		(m_context, "multiple_textures","upload multiple textures with different sRGB decode values and sample",testGroupConfigList[idx].internalFormat));
+		testGroup->addChild(new DecodeSamplerCase				(m_context, "using_sampler",	"testing that sampler object takes priority over texture state",		testGroupConfigList[idx].internalFormat));
+	}
+}
+
+} // Functional
+} // gles31
+} // deqp
diff --git a/modules/gles31/functional/es31fSRGBDecodeTests.hpp b/modules/gles31/functional/es31fSRGBDecodeTests.hpp
new file mode 100644
index 0000000..8be5da7
--- /dev/null
+++ b/modules/gles31/functional/es31fSRGBDecodeTests.hpp
@@ -0,0 +1,54 @@
+#ifndef _ES31FSRGBDECODETESTS_HPP
+#define _ES31FSRGBDECODETESTS_HPP
+/*-------------------------------------------------------------------------
+ * drawElements Quality Program OpenGL ES 3.1 Module
+ * -------------------------------------------------
+ *
+ * Copyright 2017 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 sRGB decode tests.
+ *//*--------------------------------------------------------------------*/
+
+#include "tcuDefs.hpp"
+#include "tes31TestCase.hpp"
+
+namespace deqp
+{
+namespace gles31
+{
+namespace Functional
+{
+
+class SRGBDecodeTests : public TestCaseGroup
+{
+public:
+						 SRGBDecodeTests	(Context& context);
+						~SRGBDecodeTests	(void);
+
+private:
+	void				init				(void);
+
+						SRGBDecodeTests		(const SRGBDecodeTests& other);
+	SRGBDecodeTests&	operator=			(const SRGBDecodeTests& other);
+};
+
+} // Functional
+} // gles31
+} // deqp
+
+
+#endif // _ES31FSRGBDECODETESTS_HPP
\ No newline at end of file
diff --git a/modules/gles31/functional/es31fSynchronizationTests.cpp b/modules/gles31/functional/es31fSynchronizationTests.cpp
index d84b6cb..c07181f 100644
--- a/modules/gles31/functional/es31fSynchronizationTests.cpp
+++ b/modules/gles31/functional/es31fSynchronizationTests.cpp
@@ -3101,7 +3101,7 @@
 		<< "void main ()\n"
 		<< "{\n"
 		<< "	// flip high bits\n"
-		<< "	highp uint mask = uint(1) << (16u + (gl_GlobalInvocationID.x % 16u));\n"
+		<< "	highp uint mask = uint(1) << (24u + (gl_GlobalInvocationID.x % 8u));\n"
 		<< "	sb_work.dummy = atomicXor(sb_work.targetValue, mask);\n"
 		<< "}";
 
diff --git a/modules/gles31/functional/es31fTessellationTests.cpp b/modules/gles31/functional/es31fTessellationTests.cpp
index e367fd3..cabb96f 100644
--- a/modules/gles31/functional/es31fTessellationTests.cpp
+++ b/modules/gles31/functional/es31fTessellationTests.cpp
@@ -7230,7 +7230,7 @@
 		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_texture_image_units",			"Test MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS",			GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS,		16));
 		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_output_components",				"Test MAX_TESS_CONTROL_OUTPUT_COMPONENTS",				GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS,			64));
 		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_patch_components",							"Test MAX_TESS_PATCH_COMPONENTS",						GL_MAX_TESS_PATCH_COMPONENTS,					120));
-		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_total_output_components",			"Test MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS",		GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS,	4096));
+		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_total_output_components",			"Test MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS",		GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS,	2048));
 		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_output_components",				"Test MAX_TESS_EVALUATION_OUTPUT_COMPONENTS",			GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS,		64));
 		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_control_uniform_blocks",					"Test MAX_TESS_CONTROL_UNIFORM_BLOCKS",					GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS,				12));
 		queryGroup->addChild(new LimitQueryCase(m_context, "max_tess_evaluation_uniform_blocks",				"Test MAX_TESS_EVALUATION_UNIFORM_BLOCKS",				GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS,			12));
diff --git a/modules/glshared/glsFboCompletenessTests.cpp b/modules/glshared/glsFboCompletenessTests.cpp
index 3901ec1..791d8c9 100644
--- a/modules/glshared/glsFboCompletenessTests.cpp
+++ b/modules/glshared/glsFboCompletenessTests.cpp
@@ -232,6 +232,12 @@
 		(deUint32)(DEPTH_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID),
 		GLS_ARRAY_RANGE(s_oesPackedDepthStencilTexFormats)
 	},
+	// The ANGLE extension incorporates GL_OES_depth_texture/GL_OES_packed_depth_stencil.
+	{
+		"GL_ANGLE_depth_texture",
+		(deUint32)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | TEXTURE_VALID),
+		GLS_ARRAY_RANGE(s_oesDepthTextureFormats),
+	},
 	// \todo [2013-12-10 lauri] Find out if OES_texture_half_float is really a
 	// requirement on ES3 also. Or is color_buffer_half_float applicatble at
 	// all on ES3, since there's also EXT_color_buffer_float?
diff --git a/scripts/egl/common.py b/scripts/egl/common.py
index 7554f2b..c8761ce 100644
--- a/scripts/egl/common.py
+++ b/scripts/egl/common.py
@@ -39,8 +39,8 @@
 
 EGL_SOURCE			= khr_util.registry_cache.RegistrySource(
 						"egl.xml",
-						32725,
-						"3464385212ae9b816d121c77bc4191ed3dfb32ce7bfca1a02b42fcefa3ec2354")
+						33315,
+						"19f3b517f0dede56a6a94b820d08149ef5e1726f58202f47d69fa27f6f483bd2")
 
 VERSION				= '1.5'
 
@@ -65,7 +65,8 @@
 	"EGL_EXT_buffer_age",
 	"EGL_KHR_partial_update",
 	"EGL_KHR_swap_buffers_with_damage",
-	"EGL_KHR_mutable_render_buffer"
+	"EGL_KHR_mutable_render_buffer",
+	"EGL_EXT_pixel_format_float"
 ]
 PROTECTS			= [
 	"KHRONOS_SUPPORT_INT64"
diff --git a/scripts/egl/str_util.py b/scripts/egl/str_util.py
index 4372932..57627b6 100644
--- a/scripts/egl/str_util.py
+++ b/scripts/egl/str_util.py
@@ -106,7 +106,8 @@
 		"TRANSPARENT_TYPE",
 		"TRANSPARENT_RED_VALUE",
 		"TRANSPARENT_GREEN_VALUE",
-		"TRANSPARENT_BLUE_VALUE"
+		"TRANSPARENT_BLUE_VALUE",
+		"COLOR_COMPONENT_TYPE_EXT"
 		]),
 	("SurfaceAttrib", [
 		"CONFIG_ID",
@@ -141,6 +142,7 @@
 		"YUV_PLANE_BPP_8_EXT",
 		"YUV_PLANE_BPP_10_EXT",
 		]),
+	("ColorComponentType",	["COLOR_COMPONENT_TYPE_FIXED_EXT", "COLOR_COMPONENT_TYPE_FLOAT_EXT"]),
 	("SurfaceTarget",		["READ", "DRAW"]),
 
 	# ConfigAttrib values