Add utilities to split combined-depth-stencil accesses.

Change-Id: I2fed3761217fd55d0273e01a951867804a15a5b9
diff --git a/framework/common/tcuTexture.hpp b/framework/common/tcuTexture.hpp
index 2fb0d6a..68bf4a9 100644
--- a/framework/common/tcuTexture.hpp
+++ b/framework/common/tcuTexture.hpp
@@ -195,6 +195,14 @@
 		COMPAREMODE_LAST
 	};
 
+	enum DepthStencilMode
+	{
+		MODE_DEPTH = 0,
+		MODE_STENCIL,
+
+		MODE_LAST
+	};
+
 	// Wrap control
 	WrapMode		wrapS;
 	WrapMode		wrapT;
diff --git a/framework/common/tcuTextureUtil.cpp b/framework/common/tcuTextureUtil.cpp
index 4c4aceb8d..a959ee2 100644
--- a/framework/common/tcuTextureUtil.cpp
+++ b/framework/common/tcuTextureUtil.cpp
@@ -78,6 +78,15 @@
 			format.order == TextureFormat::sRGBA;
 }
 
+bool isCombinedDepthStencilType (TextureFormat::ChannelType type)
+{
+	// make sure to update this if type table is updated
+	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 26);
+
+	return	type == TextureFormat::UNSIGNED_INT_24_8 ||
+			type == TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV;
+}
+
 //! Get texture channel class for format
 TextureChannelClass getTextureChannelClass (TextureFormat::ChannelType channelType)
 {
@@ -996,4 +1005,119 @@
 	return rs | (gs << 9) | (bs << 18) | (exps << 27);
 }
 
+// Sampler utils
+
+static const void* addOffset (const void* ptr, int numBytes)
+{
+	return (const deUint8*)ptr + numBytes;
+}
+
+static void* addOffset (void* ptr, int numBytes)
+{
+	return (deUint8*)ptr + numBytes;
+}
+
+template <typename AccessType>
+static AccessType toSamplerAccess (const AccessType& baseAccess, Sampler::DepthStencilMode mode)
+{
+	// make sure to update this if type table is updated
+	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 26);
+
+	if (!isCombinedDepthStencilType(baseAccess.getFormat().type))
+		return baseAccess;
+	else
+	{
+#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
+		const deUint32 uint32ByteOffsetBits0To8	= 0; //!< least significant byte in the lowest address
+		const deUint32 uint32ByteOffset8To32	= 1;
+#else
+		const deUint32 uint32ByteOffsetBits0To8	= 3; //!< least significant byte in the highest address
+		const deUint32 uint32ByteOffset8To32	= 0;
+#endif
+
+		// Sampled channel must exist
+		DE_ASSERT(baseAccess.getFormat().order == TextureFormat::DS ||
+				  (mode == Sampler::MODE_DEPTH && baseAccess.getFormat().order == TextureFormat::D) ||
+				  (mode == Sampler::MODE_STENCIL && baseAccess.getFormat().order == TextureFormat::S));
+
+		// combined formats have multiple channel classes, detect on sampler settings
+		switch (baseAccess.getFormat().type)
+		{
+			case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
+			{
+				if (mode == Sampler::MODE_DEPTH)
+				{
+					// select the float component
+					return AccessType(TextureFormat(TextureFormat::D, TextureFormat::FLOAT),
+									  baseAccess.getSize(),
+									  baseAccess.getPitch(),
+									  baseAccess.getDataPtr());
+				}
+				else if (mode == Sampler::MODE_STENCIL)
+				{
+					// select the uint 8 component
+					return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
+									  baseAccess.getSize(),
+									  baseAccess.getPitch(),
+									  addOffset(baseAccess.getDataPtr(), 4 + uint32ByteOffsetBits0To8));
+				}
+				else
+				{
+					// unknown sampler mode
+					DE_ASSERT(false);
+					return AccessType();
+				}
+			}
+
+			case TextureFormat::UNSIGNED_INT_24_8:
+			{
+				if (mode == Sampler::MODE_DEPTH)
+				{
+					// select the unorm24 component
+					return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT24),
+									  baseAccess.getSize(),
+									  baseAccess.getPitch(),
+									  addOffset(baseAccess.getDataPtr(), uint32ByteOffset8To32));
+				}
+				else if (mode == Sampler::MODE_STENCIL)
+				{
+					// select the uint 8 component
+					return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8),
+									  baseAccess.getSize(),
+									  baseAccess.getPitch(),
+									  addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To8));
+				}
+				else
+				{
+					// unknown sampler mode
+					DE_ASSERT(false);
+					return AccessType();
+				}
+			}
+
+			default:
+			{
+				// unknown combined format
+				DE_ASSERT(false);
+				return AccessType();
+			}
+		}
+	}
+}
+
+PixelBufferAccess getEffectiveDepthStencilAccess (const PixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
+{
+	return toSamplerAccess<PixelBufferAccess>(baseAccess, mode);
+}
+
+ConstPixelBufferAccess getEffectiveDepthStencilAccess (const ConstPixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode)
+{
+	return toSamplerAccess<ConstPixelBufferAccess>(baseAccess, mode);
+}
+
+TextureFormat getEffectiveDepthStencilTextureFormat (const TextureFormat& baseFormat, Sampler::DepthStencilMode mode)
+{
+	return toSamplerAccess(ConstPixelBufferAccess(baseFormat, IVec3(0, 0, 0), DE_NULL), mode).getFormat();
+}
+
 } // tcu
diff --git a/framework/common/tcuTextureUtil.hpp b/framework/common/tcuTextureUtil.hpp
index d9f07c8..b5989d0 100644
--- a/framework/common/tcuTextureUtil.hpp
+++ b/framework/common/tcuTextureUtil.hpp
@@ -30,19 +30,20 @@
 {
 
 // PixelBufferAccess utilities.
-PixelBufferAccess		getSubregion	(const PixelBufferAccess& access, int x, int y, int z, int width, int height, int depth);
-ConstPixelBufferAccess	getSubregion	(const ConstPixelBufferAccess& access, int x, int y, int z, int width, int height, int depth);
+PixelBufferAccess		getSubregion				(const PixelBufferAccess& access, int x, int y, int z, int width, int height, int depth);
+ConstPixelBufferAccess	getSubregion				(const ConstPixelBufferAccess& access, int x, int y, int z, int width, int height, int depth);
 
-PixelBufferAccess		getSubregion	(const PixelBufferAccess& access, int x, int y, int width, int height);
-ConstPixelBufferAccess	getSubregion	(const ConstPixelBufferAccess& access, int x, int y, int width, int height);
+PixelBufferAccess		getSubregion				(const PixelBufferAccess& access, int x, int y, int width, int height);
+ConstPixelBufferAccess	getSubregion				(const ConstPixelBufferAccess& access, int x, int y, int width, int height);
 
-PixelBufferAccess		flipYAccess		(const PixelBufferAccess& access);
-ConstPixelBufferAccess	flipYAccess		(const ConstPixelBufferAccess& access);
+PixelBufferAccess		flipYAccess					(const PixelBufferAccess& access);
+ConstPixelBufferAccess	flipYAccess					(const ConstPixelBufferAccess& access);
 
 // sRGB - linear conversion.
-Vec4					sRGBToLinear	(const Vec4& cs);
-Vec4					linearToSRGB	(const Vec4& cl);
-bool					isSRGB			(TextureFormat format);
+Vec4					sRGBToLinear				(const Vec4& cs);
+Vec4					linearToSRGB				(const Vec4& cl);
+bool					isSRGB						(TextureFormat format);
+bool					isCombinedDepthStencilType	(TextureFormat::ChannelType type);
 
 /*--------------------------------------------------------------------*//*!
  * \brief Color channel storage type
@@ -128,6 +129,18 @@
 
 deUint32 packRGB999E5 (const tcu::Vec4& color);
 
+/*--------------------------------------------------------------------*//*!
+ * \brief Depth-stencil utilities
+ *//*--------------------------------------------------------------------*/
+
+TextureFormat				getEffectiveDepthStencilTextureFormat	(const TextureFormat& baseFormat, Sampler::DepthStencilMode mode);
+
+//! returns the currently effective access to an access with a given sampler mode, e.g.
+//! for combined depth stencil accesses and for sampler set to sample stencil returns
+//! stencil access. Identity for non-combined formats.
+PixelBufferAccess			getEffectiveDepthStencilAccess			(const PixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode);
+ConstPixelBufferAccess		getEffectiveDepthStencilAccess			(const ConstPixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode);
+
 } // tcu
 
 #endif // _TCUTEXTUREUTIL_HPP
diff --git a/modules/glshared/glsTextureTestUtil.cpp b/modules/glshared/glsTextureTestUtil.cpp
index 85204b5..fb31621 100644
--- a/modules/glshared/glsTextureTestUtil.cpp
+++ b/modules/glshared/glsTextureTestUtil.cpp
@@ -1760,7 +1760,7 @@
 							  const tcu::PixelBufferAccess&			errorMask,
 							  const tcu::Texture2DView&				baseView,
 							  const float*							texCoord,
-							  const ReferenceParams&					sampleParams,
+							  const ReferenceParams&				sampleParams,
 							  const tcu::LookupPrecision&			lookupPrec,
 							  const tcu::LodPrecision&				lodPrec,
 							  qpWatchDog*							watchDog)