1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program Tester Core
3e5c31af7Sopenharmony_ci * ----------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci *//*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief Reference Texture Implementation.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "tcuTexture.hpp"
25e5c31af7Sopenharmony_ci#include "deInt32.h"
26e5c31af7Sopenharmony_ci#include "deFloat16.h"
27e5c31af7Sopenharmony_ci#include "deMath.h"
28e5c31af7Sopenharmony_ci#include "deMemory.h"
29e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
30e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
31e5c31af7Sopenharmony_ci#include "tcuFloat.hpp"
32e5c31af7Sopenharmony_ci#include "tcuTextureUtil.hpp"
33e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
34e5c31af7Sopenharmony_ci#include "deArrayUtil.hpp"
35e5c31af7Sopenharmony_ci#include "tcuMatrix.hpp"
36e5c31af7Sopenharmony_ci
37e5c31af7Sopenharmony_ci#include <limits>
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_cinamespace tcu
40e5c31af7Sopenharmony_ci{
41e5c31af7Sopenharmony_ci
42e5c31af7Sopenharmony_ci// \note No sign. Denorms are supported.
43e5c31af7Sopenharmony_citypedef Float<deUint32, 5, 6, 15, FLOAT_SUPPORT_DENORM>	Float11;
44e5c31af7Sopenharmony_citypedef Float<deUint32, 5, 5, 15, FLOAT_SUPPORT_DENORM>	Float10;
45e5c31af7Sopenharmony_ci
46e5c31af7Sopenharmony_cinamespace
47e5c31af7Sopenharmony_ci{
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_ci// Optimized getters for common formats.
50e5c31af7Sopenharmony_ci// \todo [2012-11-14 pyry] Use intrinsics if available.
51e5c31af7Sopenharmony_ci
52e5c31af7Sopenharmony_ciinline Vec4		readRGBA8888Float	(const deUint8* ptr) { return Vec4(ptr[0]/255.0f, ptr[1]/255.0f, ptr[2]/255.0f, ptr[3]/255.0f); }
53e5c31af7Sopenharmony_ciinline Vec4		readRGB888Float		(const deUint8* ptr) { return Vec4(ptr[0]/255.0f, ptr[1]/255.0f, ptr[2]/255.0f, 1.0f); }
54e5c31af7Sopenharmony_ciinline IVec4	readRGBA8888Int		(const deUint8* ptr) { return IVec4(ptr[0], ptr[1], ptr[2], ptr[3]); }
55e5c31af7Sopenharmony_ciinline IVec4	readRGB888Int		(const deUint8* ptr) { return IVec4(ptr[0], ptr[1], ptr[2], 1); }
56e5c31af7Sopenharmony_ci
57e5c31af7Sopenharmony_ci// Optimized setters.
58e5c31af7Sopenharmony_ci
59e5c31af7Sopenharmony_ciinline void writeRGBA8888Int (deUint8* ptr, const IVec4& val)
60e5c31af7Sopenharmony_ci{
61e5c31af7Sopenharmony_ci	ptr[0] = (deUint8)de::clamp(val[0], 0, 255);
62e5c31af7Sopenharmony_ci	ptr[1] = (deUint8)de::clamp(val[1], 0, 255);
63e5c31af7Sopenharmony_ci	ptr[2] = (deUint8)de::clamp(val[2], 0, 255);
64e5c31af7Sopenharmony_ci	ptr[3] = (deUint8)de::clamp(val[3], 0, 255);
65e5c31af7Sopenharmony_ci}
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ciinline void writeRGB888Int (deUint8* ptr, const IVec4& val)
68e5c31af7Sopenharmony_ci{
69e5c31af7Sopenharmony_ci	ptr[0] = (deUint8)de::clamp(val[0], 0, 255);
70e5c31af7Sopenharmony_ci	ptr[1] = (deUint8)de::clamp(val[1], 0, 255);
71e5c31af7Sopenharmony_ci	ptr[2] = (deUint8)de::clamp(val[2], 0, 255);
72e5c31af7Sopenharmony_ci}
73e5c31af7Sopenharmony_ci
74e5c31af7Sopenharmony_ciinline void writeRGBA8888Float (deUint8* ptr, const Vec4& val)
75e5c31af7Sopenharmony_ci{
76e5c31af7Sopenharmony_ci	ptr[0] = floatToU8(val[0]);
77e5c31af7Sopenharmony_ci	ptr[1] = floatToU8(val[1]);
78e5c31af7Sopenharmony_ci	ptr[2] = floatToU8(val[2]);
79e5c31af7Sopenharmony_ci	ptr[3] = floatToU8(val[3]);
80e5c31af7Sopenharmony_ci}
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ciinline void writeRGB888Float (deUint8* ptr, const Vec4& val)
83e5c31af7Sopenharmony_ci{
84e5c31af7Sopenharmony_ci	ptr[0] = floatToU8(val[0]);
85e5c31af7Sopenharmony_ci	ptr[1] = floatToU8(val[1]);
86e5c31af7Sopenharmony_ci	ptr[2] = floatToU8(val[2]);
87e5c31af7Sopenharmony_ci}
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ciinline void writeUint24 (deUint8* dst, deUint32 val)
90e5c31af7Sopenharmony_ci{
91e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
92e5c31af7Sopenharmony_ci	dst[0] = (deUint8)((val & 0x0000FFu) >>  0u);
93e5c31af7Sopenharmony_ci	dst[1] = (deUint8)((val & 0x00FF00u) >>  8u);
94e5c31af7Sopenharmony_ci	dst[2] = (deUint8)((val & 0xFF0000u) >> 16u);
95e5c31af7Sopenharmony_ci#else
96e5c31af7Sopenharmony_ci	dst[0] = (deUint8)((val & 0xFF0000u) >> 16u);
97e5c31af7Sopenharmony_ci	dst[1] = (deUint8)((val & 0x00FF00u) >>  8u);
98e5c31af7Sopenharmony_ci	dst[2] = (deUint8)((val & 0x0000FFu) >>  0u);
99e5c31af7Sopenharmony_ci#endif
100e5c31af7Sopenharmony_ci}
101e5c31af7Sopenharmony_ci
102e5c31af7Sopenharmony_ciinline deUint32 readUint24 (const deUint8* src)
103e5c31af7Sopenharmony_ci{
104e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
105e5c31af7Sopenharmony_ci	return	(((deUint32)src[0]) <<  0u) |
106e5c31af7Sopenharmony_ci			(((deUint32)src[1]) <<  8u) |
107e5c31af7Sopenharmony_ci			(((deUint32)src[2]) << 16u);
108e5c31af7Sopenharmony_ci#else
109e5c31af7Sopenharmony_ci	return	(((deUint32)src[0]) << 16u) |
110e5c31af7Sopenharmony_ci			(((deUint32)src[1]) <<  8u) |
111e5c31af7Sopenharmony_ci			(((deUint32)src[2]) <<  0u);
112e5c31af7Sopenharmony_ci#endif
113e5c31af7Sopenharmony_ci}
114e5c31af7Sopenharmony_ci
115e5c31af7Sopenharmony_ciinline deUint8 readUint32Low8 (const deUint8* src)
116e5c31af7Sopenharmony_ci{
117e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
118e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffsetBits0To8	= 0; //!< least significant byte in the lowest address
119e5c31af7Sopenharmony_ci#else
120e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffsetBits0To8	= 3; //!< least significant byte in the highest address
121e5c31af7Sopenharmony_ci#endif
122e5c31af7Sopenharmony_ci
123e5c31af7Sopenharmony_ci	return src[uint32ByteOffsetBits0To8];
124e5c31af7Sopenharmony_ci}
125e5c31af7Sopenharmony_ci
126e5c31af7Sopenharmony_ciinline deUint8 readUint32High8 (const deUint8* src)
127e5c31af7Sopenharmony_ci{
128e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
129e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffsetBits24To32	= 3;
130e5c31af7Sopenharmony_ci#else
131e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffsetBits24To32	= 0;
132e5c31af7Sopenharmony_ci#endif
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_ci	return src[uint32ByteOffsetBits24To32];
135e5c31af7Sopenharmony_ci}
136e5c31af7Sopenharmony_ci
137e5c31af7Sopenharmony_ciinline void writeUint32Low8 (deUint8* dst, deUint8 val)
138e5c31af7Sopenharmony_ci{
139e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
140e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffsetBits0To8	= 0; //!< least significant byte in the lowest address
141e5c31af7Sopenharmony_ci#else
142e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffsetBits0To8	= 3; //!< least significant byte in the highest address
143e5c31af7Sopenharmony_ci#endif
144e5c31af7Sopenharmony_ci
145e5c31af7Sopenharmony_ci	dst[uint32ByteOffsetBits0To8] = val;
146e5c31af7Sopenharmony_ci}
147e5c31af7Sopenharmony_ci
148e5c31af7Sopenharmony_ciinline void writeUint32High8 (deUint8* dst, deUint8 val)
149e5c31af7Sopenharmony_ci{
150e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
151e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffsetBits24To32	= 3;
152e5c31af7Sopenharmony_ci#else
153e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffsetBits24To32	= 0;
154e5c31af7Sopenharmony_ci#endif
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ci	dst[uint32ByteOffsetBits24To32] = val;
157e5c31af7Sopenharmony_ci}
158e5c31af7Sopenharmony_ci
159e5c31af7Sopenharmony_ciinline deUint32 readUint32High16 (const deUint8* src)
160e5c31af7Sopenharmony_ci{
161e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
162e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset16To32	= 2;
163e5c31af7Sopenharmony_ci#else
164e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset16To32	= 0;
165e5c31af7Sopenharmony_ci#endif
166e5c31af7Sopenharmony_ci
167e5c31af7Sopenharmony_ci	return *(const deUint16*)(src + uint32ByteOffset16To32);
168e5c31af7Sopenharmony_ci}
169e5c31af7Sopenharmony_ci
170e5c31af7Sopenharmony_ciinline void writeUint32High16 (deUint8* dst, deUint16 val)
171e5c31af7Sopenharmony_ci{
172e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
173e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset16To32	= 2;
174e5c31af7Sopenharmony_ci#else
175e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset16To32	= 0;
176e5c31af7Sopenharmony_ci#endif
177e5c31af7Sopenharmony_ci
178e5c31af7Sopenharmony_ci	*(deUint16*)(dst + uint32ByteOffset16To32) = val;
179e5c31af7Sopenharmony_ci}
180e5c31af7Sopenharmony_ci
181e5c31af7Sopenharmony_ciinline deUint32 readUint32Low24 (const deUint8* src)
182e5c31af7Sopenharmony_ci{
183e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
184e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset0To24	= 0;
185e5c31af7Sopenharmony_ci#else
186e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset0To24	= 1;
187e5c31af7Sopenharmony_ci#endif
188e5c31af7Sopenharmony_ci
189e5c31af7Sopenharmony_ci	return readUint24(src + uint32ByteOffset0To24);
190e5c31af7Sopenharmony_ci}
191e5c31af7Sopenharmony_ci
192e5c31af7Sopenharmony_ciinline deUint32 readUint32High24 (const deUint8* src)
193e5c31af7Sopenharmony_ci{
194e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
195e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset8To32	= 1;
196e5c31af7Sopenharmony_ci#else
197e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset8To32	= 0;
198e5c31af7Sopenharmony_ci#endif
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ci	return readUint24(src + uint32ByteOffset8To32);
201e5c31af7Sopenharmony_ci}
202e5c31af7Sopenharmony_ci
203e5c31af7Sopenharmony_ciinline void writeUint32Low24 (deUint8* dst, deUint32 val)
204e5c31af7Sopenharmony_ci{
205e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
206e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset0To24	= 0;
207e5c31af7Sopenharmony_ci#else
208e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset0To24	= 1;
209e5c31af7Sopenharmony_ci#endif
210e5c31af7Sopenharmony_ci
211e5c31af7Sopenharmony_ci	writeUint24(dst + uint32ByteOffset0To24, val);
212e5c31af7Sopenharmony_ci}
213e5c31af7Sopenharmony_ci
214e5c31af7Sopenharmony_ciinline void writeUint32High24 (deUint8* dst, deUint32 val)
215e5c31af7Sopenharmony_ci{
216e5c31af7Sopenharmony_ci#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN)
217e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset8To32	= 1;
218e5c31af7Sopenharmony_ci#else
219e5c31af7Sopenharmony_ci	const deUint32 uint32ByteOffset8To32	= 0;
220e5c31af7Sopenharmony_ci#endif
221e5c31af7Sopenharmony_ci
222e5c31af7Sopenharmony_ci	writeUint24(dst + uint32ByteOffset8To32, val);
223e5c31af7Sopenharmony_ci}
224e5c31af7Sopenharmony_ci
225e5c31af7Sopenharmony_ci// \todo [2011-09-21 pyry] Move to tcutil?
226e5c31af7Sopenharmony_citemplate <typename T>
227e5c31af7Sopenharmony_ciinline T convertSatRte (float f)
228e5c31af7Sopenharmony_ci{
229e5c31af7Sopenharmony_ci	// \note Doesn't work for 64-bit types
230e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(sizeof(T) < sizeof(deUint64));
231e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT((-3 % 2 != 0) && (-4 % 2 == 0));
232e5c31af7Sopenharmony_ci
233e5c31af7Sopenharmony_ci	deInt64	minVal	= std::numeric_limits<T>::min();
234e5c31af7Sopenharmony_ci	deInt64 maxVal	= std::numeric_limits<T>::max();
235e5c31af7Sopenharmony_ci	float	q		= deFloatFrac(f);
236e5c31af7Sopenharmony_ci	deInt64 intVal	= (deInt64)(f-q);
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_ci	// Rounding.
239e5c31af7Sopenharmony_ci	if (q == 0.5f)
240e5c31af7Sopenharmony_ci	{
241e5c31af7Sopenharmony_ci		if (intVal % 2 != 0)
242e5c31af7Sopenharmony_ci			intVal++;
243e5c31af7Sopenharmony_ci	}
244e5c31af7Sopenharmony_ci	else if (q > 0.5f)
245e5c31af7Sopenharmony_ci		intVal++;
246e5c31af7Sopenharmony_ci	// else Don't add anything
247e5c31af7Sopenharmony_ci
248e5c31af7Sopenharmony_ci	// Saturate.
249e5c31af7Sopenharmony_ci	intVal = de::max(minVal, de::min(maxVal, intVal));
250e5c31af7Sopenharmony_ci
251e5c31af7Sopenharmony_ci	return (T)intVal;
252e5c31af7Sopenharmony_ci}
253e5c31af7Sopenharmony_ci
254e5c31af7Sopenharmony_ciinline deUint32 convertSatRteUint24 (float f)
255e5c31af7Sopenharmony_ci{
256e5c31af7Sopenharmony_ci	const deUint32 rounded		= convertSatRte<deUint32>(f);
257e5c31af7Sopenharmony_ci	const deUint32 maxUint24	= 0xFFFFFFu;
258e5c31af7Sopenharmony_ci	return de::min(rounded, maxUint24);
259e5c31af7Sopenharmony_ci}
260e5c31af7Sopenharmony_ci
261e5c31af7Sopenharmony_ciinline deUint16 convertSatRteUint10 (float f)
262e5c31af7Sopenharmony_ci{
263e5c31af7Sopenharmony_ci	const deUint16 rounded		= convertSatRte<deUint16>(f);
264e5c31af7Sopenharmony_ci	const deUint16 maxUint10	= 0x3FFu;
265e5c31af7Sopenharmony_ci	return de::min(rounded, maxUint10);
266e5c31af7Sopenharmony_ci}
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ciinline deUint16 convertSatRteUint12 (float f)
269e5c31af7Sopenharmony_ci{
270e5c31af7Sopenharmony_ci	const deUint16 rounded		= convertSatRte<deUint16>(f);
271e5c31af7Sopenharmony_ci	const deUint16 maxUint12	= 0xFFFu;
272e5c31af7Sopenharmony_ci	return de::min(rounded, maxUint12);
273e5c31af7Sopenharmony_ci}
274e5c31af7Sopenharmony_ci
275e5c31af7Sopenharmony_ciinline float channelToFloat (const deUint8* value, TextureFormat::ChannelType type)
276e5c31af7Sopenharmony_ci{
277e5c31af7Sopenharmony_ci	// make sure this table is updated if format table is updated
278e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48);
279e5c31af7Sopenharmony_ci
280e5c31af7Sopenharmony_ci	switch (type)
281e5c31af7Sopenharmony_ci	{
282e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT8:			return de::max(-1.0f, (float)*((const deInt8*)value) / 127.0f);
283e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT16:		return de::max(-1.0f, (float)*((const deInt16*)value) / 32767.0f);
284e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT32:		return de::max(-1.0f, (float)*((const deInt32*)value) / 2147483647.0f);
285e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT8:			return (float)*((const deUint8*)value) / 255.0f;
286e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT16:		return (float)*((const deUint16*)value) / 65535.0f;
287e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT24:		return (float)readUint24(value) / 16777215.0f;
288e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT32:		return (float)*((const deUint32*)value) / 4294967295.0f;
289e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT8:		return (float)*((const deInt8*)value);
290e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT16:		return (float)*((const deInt16*)value);
291e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT32:		return (float)*((const deInt32*)value);
292e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT64:		return (float)*((const deInt64*)value);
293e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT8:		return (float)*((const deUint8*)value);
294e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT16:		return (float)*((const deUint16*)value);
295e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT24:		return (float)readUint24(value);
296e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT32:		return (float)*((const deUint32*)value);
297e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT64:		return (float)*((const deUint64*)value);
298e5c31af7Sopenharmony_ci		case TextureFormat::HALF_FLOAT:			return deFloat16To32(*(const deFloat16*)value);
299e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT:				return *((const float*)value);
300e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT64:			return (float)*((const double*)value);
301e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_10:		return (float)((*((const deUint16*)value)) >> 6u) / 1023.0f;
302e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_12:		return (float)((*((const deUint16*)value)) >> 4u) / 4095.0f;
303e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT8:		return (float)*((const deUint8*)value);
304e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT16:		return (float)*((const deUint16*)value);
305e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT8:		return (float)*((const deInt8*)value);
306e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT16:		return (float)*((const deInt16*)value);
307e5c31af7Sopenharmony_ci		default:
308e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
309e5c31af7Sopenharmony_ci			return 0.0f;
310e5c31af7Sopenharmony_ci	}
311e5c31af7Sopenharmony_ci}
312e5c31af7Sopenharmony_ci
313e5c31af7Sopenharmony_citemplate <class T>
314e5c31af7Sopenharmony_ciinline T channelToIntType (const deUint8* value, TextureFormat::ChannelType type)
315e5c31af7Sopenharmony_ci{
316e5c31af7Sopenharmony_ci	// make sure this table is updated if format table is updated
317e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48);
318e5c31af7Sopenharmony_ci
319e5c31af7Sopenharmony_ci	switch (type)
320e5c31af7Sopenharmony_ci	{
321e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT8:			return (T)*((const deInt8*)value);
322e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT16:		return (T)*((const deInt16*)value);
323e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT32:		return (T)*((const deInt32*)value);
324e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT8:			return (T)*((const deUint8*)value);
325e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT16:		return (T)*((const deUint16*)value);
326e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT24:		return (T)readUint24(value);
327e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT32:		return (T)*((const deUint32*)value);
328e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT8:		return (T)*((const deInt8*)value);
329e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT16:		return (T)*((const deInt16*)value);
330e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT32:		return (T)*((const deInt32*)value);
331e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT64:		return (T)*((const deInt64*)value);
332e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT8:		return (T)*((const deUint8*)value);
333e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT16:		return (T)*((const deUint16*)value);
334e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT24:		return (T)readUint24(value);
335e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT32:		return (T)*((const deUint32*)value);
336e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT64:		return (T)*((const deUint64*)value);
337e5c31af7Sopenharmony_ci		case TextureFormat::HALF_FLOAT:			return (T)deFloat16To32(*(const deFloat16*)value);
338e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT:				return (T)*((const float*)value);
339e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT64:			return (T)*((const double*)value);
340e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_10:		return (T)((*(((const deUint16*)value))) >> 6u);
341e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_12:		return (T)((*(((const deUint16*)value))) >> 4u);
342e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT8:		return (T)*((const deUint8*)value);
343e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT16:		return (T)*((const deUint16*)value);
344e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT8:		return (T)*((const deInt8*)value);
345e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT16:		return (T)*((const deInt16*)value);
346e5c31af7Sopenharmony_ci		default:
347e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
348e5c31af7Sopenharmony_ci			return 0;
349e5c31af7Sopenharmony_ci	}
350e5c31af7Sopenharmony_ci}
351e5c31af7Sopenharmony_ci
352e5c31af7Sopenharmony_ciinline uint64_t retrieveChannelBitsAsUint64 (const deUint8* value, TextureFormat::ChannelType type)
353e5c31af7Sopenharmony_ci{
354e5c31af7Sopenharmony_ci	// make sure this table is updated if format table is updated
355e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48);
356e5c31af7Sopenharmony_ci
357e5c31af7Sopenharmony_ci	switch (type)
358e5c31af7Sopenharmony_ci	{
359e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT8:			return (uint64_t)*((const uint8_t*)value);
360e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT16:		return (uint64_t)*((const uint16_t*)value);
361e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT32:		return (uint64_t)*((const uint32_t*)value);
362e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT8:			return (uint64_t)*((const uint8_t*)value);
363e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT16:		return (uint64_t)*((const uint16_t*)value);
364e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT24:		return (uint64_t)readUint24(value);
365e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT32:		return (uint64_t)*((const uint32_t*)value);
366e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT8:		return (uint64_t)*((const uint8_t*)value);
367e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT16:		return (uint64_t)*((const uint16_t*)value);
368e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT32:		return (uint64_t)*((const uint32_t*)value);
369e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT64:		return (uint64_t)*((const uint64_t*)value);
370e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT8:		return (uint64_t)*((const uint8_t*)value);
371e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT16:		return (uint64_t)*((const uint16_t*)value);
372e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT24:		return (uint64_t)readUint24(value);
373e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT32:		return (uint64_t)*((const uint32_t*)value);
374e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT64:		return (uint64_t)*((const uint64_t*)value);
375e5c31af7Sopenharmony_ci		case TextureFormat::HALF_FLOAT:			return (uint64_t)*((const uint16_t*)value);
376e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT:				return (uint64_t)*((const uint32_t*)value);
377e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT64:			return (uint64_t)*((const uint64_t*)value);
378e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_10:		return (uint64_t)((*((const uint16_t*)value)) >> 6u);
379e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_12:		return (uint64_t)((*((const uint16_t*)value)) >> 4u);
380e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT8:		return (uint64_t)*((const uint8_t*)value);
381e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT16:		return (uint64_t)*((const uint16_t*)value);
382e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT8:		return (uint64_t)*((const uint8_t*)value);
383e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT16:		return (uint64_t)*((const uint16_t*)value);
384e5c31af7Sopenharmony_ci		default:
385e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
386e5c31af7Sopenharmony_ci			return 0;
387e5c31af7Sopenharmony_ci	}
388e5c31af7Sopenharmony_ci}
389e5c31af7Sopenharmony_ci
390e5c31af7Sopenharmony_ciinline int channelToInt (const deUint8* value, TextureFormat::ChannelType type)
391e5c31af7Sopenharmony_ci{
392e5c31af7Sopenharmony_ci	return channelToIntType<int>(value, type);
393e5c31af7Sopenharmony_ci}
394e5c31af7Sopenharmony_ci
395e5c31af7Sopenharmony_civoid floatToChannel (deUint8* dst, float src, TextureFormat::ChannelType type)
396e5c31af7Sopenharmony_ci{
397e5c31af7Sopenharmony_ci	// make sure this table is updated if format table is updated
398e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48);
399e5c31af7Sopenharmony_ci
400e5c31af7Sopenharmony_ci	switch (type)
401e5c31af7Sopenharmony_ci	{
402e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT8:			*((deInt8*)dst)			= convertSatRte<deInt8>		(src * 127.0f);				break;
403e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT16:		*((deInt16*)dst)		= convertSatRte<deInt16>	(src * 32767.0f);			break;
404e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT32:		*((deInt32*)dst)		= convertSatRte<deInt32>	(src * 2147483647.0f);		break;
405e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT8:			*((deUint8*)dst)		= convertSatRte<deUint8>	(src * 255.0f);				break;
406e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT16:		*((deUint16*)dst)		= convertSatRte<deUint16>	(src * 65535.0f);			break;
407e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT24:		writeUint24(dst,		  convertSatRteUint24		(src * 16777215.0f));		break;
408e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT32:		*((deUint32*)dst)		= convertSatRte<deUint32>	(src * 4294967295.0f);		break;
409e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT8:		*((deInt8*)dst)			= convertSatRte<deInt8>		(src);						break;
410e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT16:		*((deInt16*)dst)		= convertSatRte<deInt16>	(src);						break;
411e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT32:		*((deInt32*)dst)		= convertSatRte<deInt32>	(src);						break;
412e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT8:		*((deUint8*)dst)		= convertSatRte<deUint8>	(src);						break;
413e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT16:		*((deUint16*)dst)		= convertSatRte<deUint16>	(src);						break;
414e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT24:		writeUint24(dst,		  convertSatRteUint24		(src));						break;
415e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT32:		*((deUint32*)dst)		= convertSatRte<deUint32>	(src);						break;
416e5c31af7Sopenharmony_ci		case TextureFormat::HALF_FLOAT:			*((deFloat16*)dst)		= deFloat32To16				(src);						break;
417e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT:				*((float*)dst)			= src;													break;
418e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT64:			*((double*)dst)			= (double)src;											break;
419e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_10:		*((deUint16*)dst)		= (deUint16)(convertSatRteUint10(src * 1023.0f) << 6u);	break;
420e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_12:		*((deUint16*)dst)		= (deUint16)(convertSatRteUint12(src * 4095.0f) << 4u);	break;
421e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT8:		*((deUint8*)dst)		= convertSatRte<deUint8>	(src);						break;
422e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT16:		*((deUint16*)dst)		= convertSatRte<deUint16>	(src);						break;
423e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT8:		*((deInt8*)dst)			= convertSatRte<deInt8>		(src);						break;
424e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT16:		*((deInt16*)dst)		= convertSatRte<deInt16>	(src);						break;
425e5c31af7Sopenharmony_ci		default:
426e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
427e5c31af7Sopenharmony_ci	}
428e5c31af7Sopenharmony_ci}
429e5c31af7Sopenharmony_ci
430e5c31af7Sopenharmony_citemplate <typename T, typename S>
431e5c31af7Sopenharmony_cistatic inline T convertSat (S src)
432e5c31af7Sopenharmony_ci{
433e5c31af7Sopenharmony_ci	S min = (S)std::numeric_limits<T>::min();
434e5c31af7Sopenharmony_ci	S max = (S)std::numeric_limits<T>::max();
435e5c31af7Sopenharmony_ci
436e5c31af7Sopenharmony_ci	if (src < min)
437e5c31af7Sopenharmony_ci		return (T)min;
438e5c31af7Sopenharmony_ci	else if (src > max)
439e5c31af7Sopenharmony_ci		return (T)max;
440e5c31af7Sopenharmony_ci	else
441e5c31af7Sopenharmony_ci		return (T)src;
442e5c31af7Sopenharmony_ci}
443e5c31af7Sopenharmony_ci
444e5c31af7Sopenharmony_citemplate <typename S>
445e5c31af7Sopenharmony_cistatic inline deUint32 convertSatUint24 (S src)
446e5c31af7Sopenharmony_ci{
447e5c31af7Sopenharmony_ci	S min = (S)0u;
448e5c31af7Sopenharmony_ci	S max = (S)0xFFFFFFu;
449e5c31af7Sopenharmony_ci
450e5c31af7Sopenharmony_ci	if (src < min)
451e5c31af7Sopenharmony_ci		return (deUint32)min;
452e5c31af7Sopenharmony_ci	else if (src > max)
453e5c31af7Sopenharmony_ci		return (deUint32)max;
454e5c31af7Sopenharmony_ci	else
455e5c31af7Sopenharmony_ci		return (deUint32)src;
456e5c31af7Sopenharmony_ci}
457e5c31af7Sopenharmony_ci
458e5c31af7Sopenharmony_citemplate <typename S>
459e5c31af7Sopenharmony_cistatic inline deUint16 convertSatUint10 (S src)
460e5c31af7Sopenharmony_ci{
461e5c31af7Sopenharmony_ci	S min = (S)0u;
462e5c31af7Sopenharmony_ci	S max = (S)0x3FFu;
463e5c31af7Sopenharmony_ci
464e5c31af7Sopenharmony_ci	if (src < min)
465e5c31af7Sopenharmony_ci		return (deUint16)min;
466e5c31af7Sopenharmony_ci	else if (src > max)
467e5c31af7Sopenharmony_ci		return (deUint16)max;
468e5c31af7Sopenharmony_ci	else
469e5c31af7Sopenharmony_ci		return (deUint16)src;
470e5c31af7Sopenharmony_ci}
471e5c31af7Sopenharmony_ci
472e5c31af7Sopenharmony_citemplate <typename S>
473e5c31af7Sopenharmony_cistatic inline deUint16 convertSatUint12 (S src)
474e5c31af7Sopenharmony_ci{
475e5c31af7Sopenharmony_ci	S min = (S)0u;
476e5c31af7Sopenharmony_ci	S max = (S)0xFFFu;
477e5c31af7Sopenharmony_ci
478e5c31af7Sopenharmony_ci	if (src < min)
479e5c31af7Sopenharmony_ci		return (deUint16)min;
480e5c31af7Sopenharmony_ci	else if (src > max)
481e5c31af7Sopenharmony_ci		return (deUint16)max;
482e5c31af7Sopenharmony_ci	else
483e5c31af7Sopenharmony_ci		return (deUint16)src;
484e5c31af7Sopenharmony_ci}
485e5c31af7Sopenharmony_ci
486e5c31af7Sopenharmony_civoid intToChannel (deUint8* dst, int src, TextureFormat::ChannelType type)
487e5c31af7Sopenharmony_ci{
488e5c31af7Sopenharmony_ci	// make sure this table is updated if format table is updated
489e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48);
490e5c31af7Sopenharmony_ci
491e5c31af7Sopenharmony_ci	switch (type)
492e5c31af7Sopenharmony_ci	{
493e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT8:			*((deInt8*)dst)			= convertSat<deInt8>	(src);				break;
494e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT16:		*((deInt16*)dst)		= convertSat<deInt16>	(src);				break;
495e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT8:			*((deUint8*)dst)		= convertSat<deUint8>	(src);				break;
496e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT16:		*((deUint16*)dst)		= convertSat<deUint16>	(src);				break;
497e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT24:		writeUint24(dst,		  convertSatUint24		(src));				break;
498e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT8:		*((deInt8*)dst)			= convertSat<deInt8>	(src);				break;
499e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT16:		*((deInt16*)dst)		= convertSat<deInt16>	(src);				break;
500e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT32:		*((deInt32*)dst)		= convertSat<deInt32>	(src);				break;
501e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT64:		*((deInt64*)dst)		= convertSat<deInt64>	((deInt64)src);		break;
502e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT8:		*((deUint8*)dst)		= convertSat<deUint8>	((deUint32)src);	break;
503e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT16:		*((deUint16*)dst)		= convertSat<deUint16>	((deUint32)src);	break;
504e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT24:		writeUint24(dst,		  convertSatUint24		((deUint32)src));	break;
505e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT32:		*((deUint32*)dst)		= convertSat<deUint32>	((deUint32)src);	break;
506e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT64:		*((deUint64*)dst)		= convertSat<deUint64>	((deUint64)src);	break;
507e5c31af7Sopenharmony_ci		case TextureFormat::HALF_FLOAT:			*((deFloat16*)dst)		= deFloat32To16((float)src);				break;
508e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT:				*((float*)dst)			= (float)src;								break;
509e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT64:			*((double*)dst)			= (double)src;								break;
510e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_10:		*((deUint16*)dst)		= (deUint16)(convertSatUint10(src) << 6u);	break;
511e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_12:		*((deUint16*)dst)		= (deUint16)(convertSatUint12(src) << 4u);	break;
512e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT8:		*((deUint8*)dst)		= convertSat<deUint8>	((deUint32)src);	break;
513e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT16:		*((deUint16*)dst)		= convertSat<deUint16>	((deUint32)src);	break;
514e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT8:		*((deInt8*)dst)			= convertSat<deInt8>	(src);				break;
515e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT16:		*((deInt16*)dst)		= convertSat<deInt16>	(src);				break;
516e5c31af7Sopenharmony_ci		default:
517e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
518e5c31af7Sopenharmony_ci	}
519e5c31af7Sopenharmony_ci}
520e5c31af7Sopenharmony_ci
521e5c31af7Sopenharmony_ciinline float channelToUnormFloat (deUint32 src, int bits)
522e5c31af7Sopenharmony_ci{
523e5c31af7Sopenharmony_ci	const deUint32 maxVal = (1u << bits) - 1;
524e5c31af7Sopenharmony_ci
525e5c31af7Sopenharmony_ci	// \note Will lose precision if bits > 23
526e5c31af7Sopenharmony_ci	return (float)src / (float)maxVal;
527e5c31af7Sopenharmony_ci}
528e5c31af7Sopenharmony_ci
529e5c31af7Sopenharmony_ci//! Extend < 32b signed integer to 32b
530e5c31af7Sopenharmony_ciinline deInt32 signExtend (deUint32 src, int bits)
531e5c31af7Sopenharmony_ci{
532e5c31af7Sopenharmony_ci	const deUint32 signBit = 1u << (bits-1);
533e5c31af7Sopenharmony_ci
534e5c31af7Sopenharmony_ci	src |= ~((src & signBit) - 1);
535e5c31af7Sopenharmony_ci
536e5c31af7Sopenharmony_ci	return (deInt32)src;
537e5c31af7Sopenharmony_ci}
538e5c31af7Sopenharmony_ci
539e5c31af7Sopenharmony_ciinline float channelToSnormFloat (deUint32 src, int bits)
540e5c31af7Sopenharmony_ci{
541e5c31af7Sopenharmony_ci	const deUint32	range	= (1u << (bits-1)) - 1;
542e5c31af7Sopenharmony_ci
543e5c31af7Sopenharmony_ci	// \note Will lose precision if bits > 24
544e5c31af7Sopenharmony_ci	return de::max(-1.0f, (float)signExtend(src, bits) / (float)range);
545e5c31af7Sopenharmony_ci}
546e5c31af7Sopenharmony_ci
547e5c31af7Sopenharmony_ciinline deUint32 unormFloatToChannel (float src, int bits)
548e5c31af7Sopenharmony_ci{
549e5c31af7Sopenharmony_ci	const deUint32	maxVal	= (1u << bits) - 1;
550e5c31af7Sopenharmony_ci	const deUint32	intVal	= convertSatRte<deUint32>(src * (float)maxVal);
551e5c31af7Sopenharmony_ci
552e5c31af7Sopenharmony_ci	return de::min(intVal, maxVal);
553e5c31af7Sopenharmony_ci}
554e5c31af7Sopenharmony_ci
555e5c31af7Sopenharmony_ciinline deUint32 snormFloatToChannel (float src, int bits)
556e5c31af7Sopenharmony_ci{
557e5c31af7Sopenharmony_ci	const deInt32	range	= (deInt32)((1u << (bits-1)) - 1u);
558e5c31af7Sopenharmony_ci	const deUint32	mask	= (1u << bits) - 1;
559e5c31af7Sopenharmony_ci	const deInt32	intVal	= convertSatRte<deInt32>(src * (float)range);
560e5c31af7Sopenharmony_ci
561e5c31af7Sopenharmony_ci	return (deUint32)de::clamp(intVal, -range, range) & mask;
562e5c31af7Sopenharmony_ci}
563e5c31af7Sopenharmony_ci
564e5c31af7Sopenharmony_ciinline deUint32 uintToChannel (deUint32 src, int bits)
565e5c31af7Sopenharmony_ci{
566e5c31af7Sopenharmony_ci	const deUint32 maxVal = (1u << bits) - 1;
567e5c31af7Sopenharmony_ci	return de::min(src, maxVal);
568e5c31af7Sopenharmony_ci}
569e5c31af7Sopenharmony_ci
570e5c31af7Sopenharmony_ciinline deUint32 intToChannel (deInt32 src, int bits)
571e5c31af7Sopenharmony_ci{
572e5c31af7Sopenharmony_ci	const deInt32	minVal	= -(deInt32)(1u << (bits-1));
573e5c31af7Sopenharmony_ci	const deInt32	maxVal	= (deInt32)((1u << (bits-1)) - 1u);
574e5c31af7Sopenharmony_ci	const deUint32	mask	= (1u << bits) - 1;
575e5c31af7Sopenharmony_ci
576e5c31af7Sopenharmony_ci	return (deUint32)de::clamp(src, minVal, maxVal) & mask;
577e5c31af7Sopenharmony_ci}
578e5c31af7Sopenharmony_ci
579e5c31af7Sopenharmony_citcu::Vec4 unpackRGB999E5 (deUint32 color)
580e5c31af7Sopenharmony_ci{
581e5c31af7Sopenharmony_ci	const int	mBits	= 9;
582e5c31af7Sopenharmony_ci	const int	eBias	= 15;
583e5c31af7Sopenharmony_ci
584e5c31af7Sopenharmony_ci	deUint32	exp		= color >> 27;
585e5c31af7Sopenharmony_ci	deUint32	bs		= (color >> 18) & ((1<<9)-1);
586e5c31af7Sopenharmony_ci	deUint32	gs		= (color >> 9) & ((1<<9)-1);
587e5c31af7Sopenharmony_ci	deUint32	rs		= color & ((1<<9)-1);
588e5c31af7Sopenharmony_ci
589e5c31af7Sopenharmony_ci	float		e		= deFloatPow(2.0f, (float)((int)exp - eBias - mBits));
590e5c31af7Sopenharmony_ci	float		r		= (float)rs * e;
591e5c31af7Sopenharmony_ci	float		g		= (float)gs * e;
592e5c31af7Sopenharmony_ci	float		b		= (float)bs * e;
593e5c31af7Sopenharmony_ci
594e5c31af7Sopenharmony_ci	return tcu::Vec4(r, g, b, 1.0f);
595e5c31af7Sopenharmony_ci}
596e5c31af7Sopenharmony_ci
597e5c31af7Sopenharmony_cibool isColorOrder (TextureFormat::ChannelOrder order)
598e5c31af7Sopenharmony_ci{
599e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 22);
600e5c31af7Sopenharmony_ci
601e5c31af7Sopenharmony_ci	switch (order)
602e5c31af7Sopenharmony_ci	{
603e5c31af7Sopenharmony_ci		case TextureFormat::R:
604e5c31af7Sopenharmony_ci		case TextureFormat::A:
605e5c31af7Sopenharmony_ci		case TextureFormat::I:
606e5c31af7Sopenharmony_ci		case TextureFormat::L:
607e5c31af7Sopenharmony_ci		case TextureFormat::LA:
608e5c31af7Sopenharmony_ci		case TextureFormat::RG:
609e5c31af7Sopenharmony_ci		case TextureFormat::RA:
610e5c31af7Sopenharmony_ci		case TextureFormat::RGB:
611e5c31af7Sopenharmony_ci		case TextureFormat::RGBA:
612e5c31af7Sopenharmony_ci		case TextureFormat::ARGB:
613e5c31af7Sopenharmony_ci		case TextureFormat::ABGR:
614e5c31af7Sopenharmony_ci		case TextureFormat::BGR:
615e5c31af7Sopenharmony_ci		case TextureFormat::BGRA:
616e5c31af7Sopenharmony_ci		case TextureFormat::sR:
617e5c31af7Sopenharmony_ci		case TextureFormat::sRG:
618e5c31af7Sopenharmony_ci		case TextureFormat::sRGB:
619e5c31af7Sopenharmony_ci		case TextureFormat::sRGBA:
620e5c31af7Sopenharmony_ci		case TextureFormat::sBGR:
621e5c31af7Sopenharmony_ci		case TextureFormat::sBGRA:
622e5c31af7Sopenharmony_ci			return true;
623e5c31af7Sopenharmony_ci
624e5c31af7Sopenharmony_ci		default:
625e5c31af7Sopenharmony_ci			return false;
626e5c31af7Sopenharmony_ci	}
627e5c31af7Sopenharmony_ci}
628e5c31af7Sopenharmony_ci
629e5c31af7Sopenharmony_cifloat getImageViewMinLod(ImageViewMinLod& l)
630e5c31af7Sopenharmony_ci{
631e5c31af7Sopenharmony_ci	return (l.mode == IMAGEVIEWMINLODMODE_PREFERRED) ? l.value : deFloatFloor(l.value);
632e5c31af7Sopenharmony_ci}
633e5c31af7Sopenharmony_ci
634e5c31af7Sopenharmony_ci} // anonymous
635e5c31af7Sopenharmony_ci
636e5c31af7Sopenharmony_cibool isValid (TextureFormat format)
637e5c31af7Sopenharmony_ci{
638e5c31af7Sopenharmony_ci	const bool	isColor	= isColorOrder(format.order);
639e5c31af7Sopenharmony_ci
640e5c31af7Sopenharmony_ci	switch (format.type)
641e5c31af7Sopenharmony_ci	{
642e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT8:
643e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT16:
644e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT32:
645e5c31af7Sopenharmony_ci			return isColor;
646e5c31af7Sopenharmony_ci
647e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT8:
648e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT16:
649e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT24:
650e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT32:
651e5c31af7Sopenharmony_ci			return isColor || format.order == TextureFormat::D;
652e5c31af7Sopenharmony_ci
653e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_BYTE_44:
654e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_BYTE_44:
655e5c31af7Sopenharmony_ci			return format.order == TextureFormat::RG;
656e5c31af7Sopenharmony_ci
657e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_565:
658e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_555:
659e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_565:
660e5c31af7Sopenharmony_ci			return format.order == TextureFormat::RGB || format.order == TextureFormat::BGR;
661e5c31af7Sopenharmony_ci
662e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_4444:
663e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_5551:
664e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_4444:
665e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_5551:
666e5c31af7Sopenharmony_ci			return format.order == TextureFormat::RGBA || format.order == TextureFormat::BGRA
667e5c31af7Sopenharmony_ci				|| format.order == TextureFormat::ARGB || format.order == TextureFormat::ABGR;
668e5c31af7Sopenharmony_ci
669e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_1555:
670e5c31af7Sopenharmony_ci			return format.order == TextureFormat::ARGB || format.order == TextureFormat::ABGR;
671e5c31af7Sopenharmony_ci
672e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_101010:
673e5c31af7Sopenharmony_ci			return format.order == TextureFormat::RGB;
674e5c31af7Sopenharmony_ci
675e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT_1010102_REV:
676e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_1010102_REV:
677e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT_1010102_REV:
678e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_1010102_REV:
679e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT_1010102_REV:
680e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT_1010102_REV:
681e5c31af7Sopenharmony_ci			return format.order == TextureFormat::RGBA || format.order == TextureFormat::BGRA;
682e5c31af7Sopenharmony_ci
683e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
684e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_999_E5_REV:
685e5c31af7Sopenharmony_ci			return format.order == TextureFormat::RGB;
686e5c31af7Sopenharmony_ci
687e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_16_8_8:
688e5c31af7Sopenharmony_ci			return format.order == TextureFormat::DS;
689e5c31af7Sopenharmony_ci
690e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8:
691e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8_REV:
692e5c31af7Sopenharmony_ci			return format.order == TextureFormat::D || format.order == TextureFormat::DS;
693e5c31af7Sopenharmony_ci
694e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT8:
695e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT16:
696e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT32:
697e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT8:
698e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT16:
699e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT64:
700e5c31af7Sopenharmony_ci			return isColor;
701e5c31af7Sopenharmony_ci
702e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT8:
703e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT16:
704e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT24:
705e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT32:
706e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT8:
707e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT16:
708e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT64:
709e5c31af7Sopenharmony_ci			return isColor || format.order == TextureFormat::S;
710e5c31af7Sopenharmony_ci
711e5c31af7Sopenharmony_ci		case TextureFormat::HALF_FLOAT:
712e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT:
713e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT64:
714e5c31af7Sopenharmony_ci			return isColor || format.order == TextureFormat::D;
715e5c31af7Sopenharmony_ci
716e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
717e5c31af7Sopenharmony_ci			return format.order == TextureFormat::DS;
718e5c31af7Sopenharmony_ci
719e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_10:
720e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_12:
721e5c31af7Sopenharmony_ci			return isColor;
722e5c31af7Sopenharmony_ci
723e5c31af7Sopenharmony_ci		default:
724e5c31af7Sopenharmony_ci			DE_FATAL("Unknown format");
725e5c31af7Sopenharmony_ci			return 0u;
726e5c31af7Sopenharmony_ci	}
727e5c31af7Sopenharmony_ci
728e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48);
729e5c31af7Sopenharmony_ci}
730e5c31af7Sopenharmony_ci
731e5c31af7Sopenharmony_ciint getNumUsedChannels (TextureFormat::ChannelOrder order)
732e5c31af7Sopenharmony_ci{
733e5c31af7Sopenharmony_ci	// make sure this table is updated if type table is updated
734e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 22);
735e5c31af7Sopenharmony_ci
736e5c31af7Sopenharmony_ci	switch (order)
737e5c31af7Sopenharmony_ci	{
738e5c31af7Sopenharmony_ci		case TextureFormat::R:			return 1;
739e5c31af7Sopenharmony_ci		case TextureFormat::A:			return 1;
740e5c31af7Sopenharmony_ci		case TextureFormat::I:			return 1;
741e5c31af7Sopenharmony_ci		case TextureFormat::L:			return 1;
742e5c31af7Sopenharmony_ci		case TextureFormat::LA:			return 2;
743e5c31af7Sopenharmony_ci		case TextureFormat::RG:			return 2;
744e5c31af7Sopenharmony_ci		case TextureFormat::RA:			return 2;
745e5c31af7Sopenharmony_ci		case TextureFormat::RGB:		return 3;
746e5c31af7Sopenharmony_ci		case TextureFormat::RGBA:		return 4;
747e5c31af7Sopenharmony_ci		case TextureFormat::ARGB:		return 4;
748e5c31af7Sopenharmony_ci		case TextureFormat::ABGR:		return 4;
749e5c31af7Sopenharmony_ci		case TextureFormat::BGR:		return 3;
750e5c31af7Sopenharmony_ci		case TextureFormat::BGRA:		return 4;
751e5c31af7Sopenharmony_ci		case TextureFormat::sR:			return 1;
752e5c31af7Sopenharmony_ci		case TextureFormat::sRG:		return 2;
753e5c31af7Sopenharmony_ci		case TextureFormat::sRGB:		return 3;
754e5c31af7Sopenharmony_ci		case TextureFormat::sRGBA:		return 4;
755e5c31af7Sopenharmony_ci		case TextureFormat::sBGR:		return 3;
756e5c31af7Sopenharmony_ci		case TextureFormat::sBGRA:		return 4;
757e5c31af7Sopenharmony_ci		case TextureFormat::D:			return 1;
758e5c31af7Sopenharmony_ci		case TextureFormat::S:			return 1;
759e5c31af7Sopenharmony_ci		case TextureFormat::DS:			return 2;
760e5c31af7Sopenharmony_ci		default:
761e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
762e5c31af7Sopenharmony_ci			return 0;
763e5c31af7Sopenharmony_ci	}
764e5c31af7Sopenharmony_ci}
765e5c31af7Sopenharmony_ci
766e5c31af7Sopenharmony_ciint getChannelSize (TextureFormat::ChannelType type)
767e5c31af7Sopenharmony_ci{
768e5c31af7Sopenharmony_ci	// make sure this table is updated if format table is updated
769e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48);
770e5c31af7Sopenharmony_ci
771e5c31af7Sopenharmony_ci	switch (type)
772e5c31af7Sopenharmony_ci	{
773e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT8:			return 1;
774e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT16:		return 2;
775e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT32:		return 4;
776e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT8:			return 1;
777e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT16:		return 2;
778e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT24:		return 3;
779e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT32:		return 4;
780e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT8:		return 1;
781e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT16:		return 2;
782e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT32:		return 4;
783e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT64:		return 8;
784e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT8:		return 1;
785e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT16:		return 2;
786e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT24:		return 3;
787e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT32:		return 4;
788e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT64:		return 8;
789e5c31af7Sopenharmony_ci		case TextureFormat::HALF_FLOAT:			return 2;
790e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT:				return 4;
791e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT64:			return 8;
792e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_10:		return 2;
793e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_12:		return 2;
794e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT8:		return 1;
795e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT16:		return 2;
796e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT8:		return 1;
797e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT16:		return 2;
798e5c31af7Sopenharmony_ci		default:
799e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
800e5c31af7Sopenharmony_ci			return 0;
801e5c31af7Sopenharmony_ci	}
802e5c31af7Sopenharmony_ci}
803e5c31af7Sopenharmony_ci
804e5c31af7Sopenharmony_ci/** Get pixel size in bytes. */
805e5c31af7Sopenharmony_ciint getPixelSize (TextureFormat format)
806e5c31af7Sopenharmony_ci{
807e5c31af7Sopenharmony_ci	const TextureFormat::ChannelOrder	order	= format.order;
808e5c31af7Sopenharmony_ci	const TextureFormat::ChannelType	type	= format.type;
809e5c31af7Sopenharmony_ci
810e5c31af7Sopenharmony_ci	DE_ASSERT(isValid(format));
811e5c31af7Sopenharmony_ci
812e5c31af7Sopenharmony_ci	// make sure this table is updated if format table is updated
813e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48);
814e5c31af7Sopenharmony_ci
815e5c31af7Sopenharmony_ci	switch (type)
816e5c31af7Sopenharmony_ci	{
817e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_BYTE_44:
818e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_BYTE_44:
819e5c31af7Sopenharmony_ci			return 1;
820e5c31af7Sopenharmony_ci
821e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_565:
822e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_555:
823e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_4444:
824e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_5551:
825e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_1555:
826e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_565:
827e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_4444:
828e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_5551:
829e5c31af7Sopenharmony_ci			return 2;
830e5c31af7Sopenharmony_ci
831e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_101010:
832e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_999_E5_REV:
833e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
834e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT_1010102_REV:
835e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_1010102_REV:
836e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT_1010102_REV:
837e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_1010102_REV:
838e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8:
839e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8_REV:
840e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_16_8_8:
841e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT_1010102_REV:
842e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT_1010102_REV:
843e5c31af7Sopenharmony_ci			return 4;
844e5c31af7Sopenharmony_ci
845e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
846e5c31af7Sopenharmony_ci			return 8;
847e5c31af7Sopenharmony_ci
848e5c31af7Sopenharmony_ci		default:
849e5c31af7Sopenharmony_ci			return getNumUsedChannels(order) * getChannelSize(type);
850e5c31af7Sopenharmony_ci	}
851e5c31af7Sopenharmony_ci}
852e5c31af7Sopenharmony_ci
853e5c31af7Sopenharmony_ciint TextureFormat::getPixelSize (void) const
854e5c31af7Sopenharmony_ci{
855e5c31af7Sopenharmony_ci	return ::tcu::getPixelSize(*this);
856e5c31af7Sopenharmony_ci}
857e5c31af7Sopenharmony_ci
858e5c31af7Sopenharmony_ciconst TextureSwizzle& getChannelReadSwizzle (TextureFormat::ChannelOrder order)
859e5c31af7Sopenharmony_ci{
860e5c31af7Sopenharmony_ci	// make sure to update these tables when channel orders are updated
861e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 22);
862e5c31af7Sopenharmony_ci
863e5c31af7Sopenharmony_ci	static const TextureSwizzle INV		= {{ TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
864e5c31af7Sopenharmony_ci	static const TextureSwizzle R		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
865e5c31af7Sopenharmony_ci	static const TextureSwizzle A		= {{ TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_0	}};
866e5c31af7Sopenharmony_ci	static const TextureSwizzle I		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0	}};
867e5c31af7Sopenharmony_ci	static const TextureSwizzle L		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ONE	}};
868e5c31af7Sopenharmony_ci	static const TextureSwizzle LA		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1	}};
869e5c31af7Sopenharmony_ci	static const TextureSwizzle RG		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
870e5c31af7Sopenharmony_ci	static const TextureSwizzle RA		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_1	}};
871e5c31af7Sopenharmony_ci	static const TextureSwizzle RGB		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_ONE	}};
872e5c31af7Sopenharmony_ci	static const TextureSwizzle RGBA	= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_3	}};
873e5c31af7Sopenharmony_ci	static const TextureSwizzle BGR		= {{ TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ONE	}};
874e5c31af7Sopenharmony_ci	static const TextureSwizzle BGRA	= {{ TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_3	}};
875e5c31af7Sopenharmony_ci	static const TextureSwizzle ARGB	= {{ TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_3,		TextureSwizzle::CHANNEL_0	}};
876e5c31af7Sopenharmony_ci	static const TextureSwizzle ABGR	= {{ TextureSwizzle::CHANNEL_3,		TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_0	}};
877e5c31af7Sopenharmony_ci	static const TextureSwizzle D		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
878e5c31af7Sopenharmony_ci	static const TextureSwizzle S		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
879e5c31af7Sopenharmony_ci	static const TextureSwizzle DS		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_ZERO,	TextureSwizzle::CHANNEL_ONE	}};
880e5c31af7Sopenharmony_ci
881e5c31af7Sopenharmony_ci	switch (order)
882e5c31af7Sopenharmony_ci	{
883e5c31af7Sopenharmony_ci		case TextureFormat::R:			return R;
884e5c31af7Sopenharmony_ci		case TextureFormat::A:			return A;
885e5c31af7Sopenharmony_ci		case TextureFormat::I:			return I;
886e5c31af7Sopenharmony_ci		case TextureFormat::L:			return L;
887e5c31af7Sopenharmony_ci		case TextureFormat::LA:			return LA;
888e5c31af7Sopenharmony_ci		case TextureFormat::RG:			return RG;
889e5c31af7Sopenharmony_ci		case TextureFormat::RA:			return RA;
890e5c31af7Sopenharmony_ci		case TextureFormat::RGB:		return RGB;
891e5c31af7Sopenharmony_ci		case TextureFormat::RGBA:		return RGBA;
892e5c31af7Sopenharmony_ci		case TextureFormat::ARGB:		return ARGB;
893e5c31af7Sopenharmony_ci		case TextureFormat::ABGR:		return ABGR;
894e5c31af7Sopenharmony_ci		case TextureFormat::BGR:		return BGR;
895e5c31af7Sopenharmony_ci		case TextureFormat::BGRA:		return BGRA;
896e5c31af7Sopenharmony_ci		case TextureFormat::sR:			return R;
897e5c31af7Sopenharmony_ci		case TextureFormat::sRG:		return RG;
898e5c31af7Sopenharmony_ci		case TextureFormat::sRGB:		return RGB;
899e5c31af7Sopenharmony_ci		case TextureFormat::sRGBA:		return RGBA;
900e5c31af7Sopenharmony_ci		case TextureFormat::sBGR:		return BGR;
901e5c31af7Sopenharmony_ci		case TextureFormat::sBGRA:		return BGRA;
902e5c31af7Sopenharmony_ci		case TextureFormat::D:			return D;
903e5c31af7Sopenharmony_ci		case TextureFormat::S:			return S;
904e5c31af7Sopenharmony_ci		case TextureFormat::DS:			return DS;
905e5c31af7Sopenharmony_ci
906e5c31af7Sopenharmony_ci		default:
907e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
908e5c31af7Sopenharmony_ci			return INV;
909e5c31af7Sopenharmony_ci	}
910e5c31af7Sopenharmony_ci}
911e5c31af7Sopenharmony_ci
912e5c31af7Sopenharmony_ciconst TextureSwizzle& getChannelWriteSwizzle (TextureFormat::ChannelOrder order)
913e5c31af7Sopenharmony_ci{
914e5c31af7Sopenharmony_ci	// make sure to update these tables when channel orders are updated
915e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 22);
916e5c31af7Sopenharmony_ci
917e5c31af7Sopenharmony_ci	static const TextureSwizzle INV		= {{ TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST	}};
918e5c31af7Sopenharmony_ci	static const TextureSwizzle R		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST	}};
919e5c31af7Sopenharmony_ci	static const TextureSwizzle A		= {{ TextureSwizzle::CHANNEL_3,		TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST	}};
920e5c31af7Sopenharmony_ci	static const TextureSwizzle I		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST	}};
921e5c31af7Sopenharmony_ci	static const TextureSwizzle L		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST	}};
922e5c31af7Sopenharmony_ci	static const TextureSwizzle LA		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_3,		TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST	}};
923e5c31af7Sopenharmony_ci	static const TextureSwizzle RG		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST	}};
924e5c31af7Sopenharmony_ci	static const TextureSwizzle RA		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_3,		TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST	}};
925e5c31af7Sopenharmony_ci	static const TextureSwizzle RGB		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_LAST	}};
926e5c31af7Sopenharmony_ci	static const TextureSwizzle RGBA	= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_3		}};
927e5c31af7Sopenharmony_ci	static const TextureSwizzle BGR		= {{ TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_LAST	}};
928e5c31af7Sopenharmony_ci	static const TextureSwizzle BGRA	= {{ TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_3		}};
929e5c31af7Sopenharmony_ci	static const TextureSwizzle ARGB	= {{ TextureSwizzle::CHANNEL_3,		TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_2		}};
930e5c31af7Sopenharmony_ci	static const TextureSwizzle ABGR	= {{ TextureSwizzle::CHANNEL_3,		TextureSwizzle::CHANNEL_2,		TextureSwizzle::CHANNEL_1,		TextureSwizzle::CHANNEL_0		}};
931e5c31af7Sopenharmony_ci	static const TextureSwizzle D		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST	}};
932e5c31af7Sopenharmony_ci	static const TextureSwizzle S		= {{ TextureSwizzle::CHANNEL_0,		TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST,	TextureSwizzle::CHANNEL_LAST	}};
933e5c31af7Sopenharmony_ci
934e5c31af7Sopenharmony_ci	switch (order)
935e5c31af7Sopenharmony_ci	{
936e5c31af7Sopenharmony_ci		case TextureFormat::R:			return R;
937e5c31af7Sopenharmony_ci		case TextureFormat::A:			return A;
938e5c31af7Sopenharmony_ci		case TextureFormat::I:			return I;
939e5c31af7Sopenharmony_ci		case TextureFormat::L:			return L;
940e5c31af7Sopenharmony_ci		case TextureFormat::LA:			return LA;
941e5c31af7Sopenharmony_ci		case TextureFormat::RG:			return RG;
942e5c31af7Sopenharmony_ci		case TextureFormat::RA:			return RA;
943e5c31af7Sopenharmony_ci		case TextureFormat::RGB:		return RGB;
944e5c31af7Sopenharmony_ci		case TextureFormat::RGBA:		return RGBA;
945e5c31af7Sopenharmony_ci		case TextureFormat::ARGB:		return ARGB;
946e5c31af7Sopenharmony_ci		case TextureFormat::ABGR:		return ABGR;
947e5c31af7Sopenharmony_ci		case TextureFormat::BGR:		return BGR;
948e5c31af7Sopenharmony_ci		case TextureFormat::BGRA:		return BGRA;
949e5c31af7Sopenharmony_ci		case TextureFormat::sR:			return R;
950e5c31af7Sopenharmony_ci		case TextureFormat::sRG:		return RG;
951e5c31af7Sopenharmony_ci		case TextureFormat::sRGB:		return RGB;
952e5c31af7Sopenharmony_ci		case TextureFormat::sRGBA:		return RGBA;
953e5c31af7Sopenharmony_ci		case TextureFormat::sBGR:		return BGR;
954e5c31af7Sopenharmony_ci		case TextureFormat::sBGRA:		return BGRA;
955e5c31af7Sopenharmony_ci		case TextureFormat::D:			return D;
956e5c31af7Sopenharmony_ci		case TextureFormat::S:			return S;
957e5c31af7Sopenharmony_ci
958e5c31af7Sopenharmony_ci		case TextureFormat::DS:
959e5c31af7Sopenharmony_ci			DE_ASSERT(false); // combined formats cannot be written to
960e5c31af7Sopenharmony_ci			return INV;
961e5c31af7Sopenharmony_ci
962e5c31af7Sopenharmony_ci		default:
963e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
964e5c31af7Sopenharmony_ci			return INV;
965e5c31af7Sopenharmony_ci	}
966e5c31af7Sopenharmony_ci}
967e5c31af7Sopenharmony_ci
968e5c31af7Sopenharmony_ciIVec3 calculatePackedPitch (const TextureFormat& format, const IVec3& size)
969e5c31af7Sopenharmony_ci{
970e5c31af7Sopenharmony_ci	const int pixelSize		= format.getPixelSize();
971e5c31af7Sopenharmony_ci	const int rowPitch		= pixelSize * size.x();
972e5c31af7Sopenharmony_ci	const int slicePitch	= rowPitch * size.y();
973e5c31af7Sopenharmony_ci
974e5c31af7Sopenharmony_ci	return IVec3(pixelSize, rowPitch, slicePitch);
975e5c31af7Sopenharmony_ci}
976e5c31af7Sopenharmony_ci
977e5c31af7Sopenharmony_ciConstPixelBufferAccess::ConstPixelBufferAccess (void)
978e5c31af7Sopenharmony_ci	: m_size		(0)
979e5c31af7Sopenharmony_ci	, m_pitch		(0)
980e5c31af7Sopenharmony_ci	, m_divider		(1,1,1)
981e5c31af7Sopenharmony_ci	, m_data		(DE_NULL)
982e5c31af7Sopenharmony_ci{
983e5c31af7Sopenharmony_ci}
984e5c31af7Sopenharmony_ci
985e5c31af7Sopenharmony_ciConstPixelBufferAccess::ConstPixelBufferAccess (const TextureFormat& format, int width, int height, int depth, const void* data)
986e5c31af7Sopenharmony_ci	: m_format		(format)
987e5c31af7Sopenharmony_ci	, m_size		(width, height, depth)
988e5c31af7Sopenharmony_ci	, m_pitch		(calculatePackedPitch(m_format, m_size))
989e5c31af7Sopenharmony_ci	, m_divider		(1,1,1)
990e5c31af7Sopenharmony_ci	, m_data		((void*)data)
991e5c31af7Sopenharmony_ci{
992e5c31af7Sopenharmony_ci	DE_ASSERT(isValid(format));
993e5c31af7Sopenharmony_ci}
994e5c31af7Sopenharmony_ci
995e5c31af7Sopenharmony_ciConstPixelBufferAccess::ConstPixelBufferAccess (const TextureFormat& format, const IVec3& size, const void* data)
996e5c31af7Sopenharmony_ci	: m_format		(format)
997e5c31af7Sopenharmony_ci	, m_size		(size)
998e5c31af7Sopenharmony_ci	, m_pitch		(calculatePackedPitch(m_format, m_size))
999e5c31af7Sopenharmony_ci	, m_divider		(1,1,1)
1000e5c31af7Sopenharmony_ci	, m_data		((void*)data)
1001e5c31af7Sopenharmony_ci{
1002e5c31af7Sopenharmony_ci	DE_ASSERT(isValid(format));
1003e5c31af7Sopenharmony_ci}
1004e5c31af7Sopenharmony_ci
1005e5c31af7Sopenharmony_ciConstPixelBufferAccess::ConstPixelBufferAccess (const TextureFormat& format, int width, int height, int depth, int rowPitch, int slicePitch, const void* data)
1006e5c31af7Sopenharmony_ci	: m_format		(format)
1007e5c31af7Sopenharmony_ci	, m_size		(width, height, depth)
1008e5c31af7Sopenharmony_ci	, m_pitch		(format.getPixelSize(), rowPitch, slicePitch)
1009e5c31af7Sopenharmony_ci	, m_divider		(1,1,1)
1010e5c31af7Sopenharmony_ci	, m_data		((void*)data)
1011e5c31af7Sopenharmony_ci{
1012e5c31af7Sopenharmony_ci	DE_ASSERT(isValid(format));
1013e5c31af7Sopenharmony_ci}
1014e5c31af7Sopenharmony_ci
1015e5c31af7Sopenharmony_ciConstPixelBufferAccess::ConstPixelBufferAccess (const TextureFormat& format, const IVec3& size, const IVec3& pitch, const void* data)
1016e5c31af7Sopenharmony_ci	: m_format		(format)
1017e5c31af7Sopenharmony_ci	, m_size		(size)
1018e5c31af7Sopenharmony_ci	, m_pitch		(pitch)
1019e5c31af7Sopenharmony_ci	, m_divider		(1,1,1)
1020e5c31af7Sopenharmony_ci	, m_data		((void*)data)
1021e5c31af7Sopenharmony_ci{
1022e5c31af7Sopenharmony_ci	DE_ASSERT(isValid(format));
1023e5c31af7Sopenharmony_ci	DE_ASSERT(m_format.getPixelSize() <= m_pitch.x());
1024e5c31af7Sopenharmony_ci}
1025e5c31af7Sopenharmony_ci
1026e5c31af7Sopenharmony_ciConstPixelBufferAccess::ConstPixelBufferAccess(const TextureFormat& format, const IVec3& size, const IVec3& pitch, const IVec3& block, const void* data)
1027e5c31af7Sopenharmony_ci	: m_format		(format)
1028e5c31af7Sopenharmony_ci	, m_size		(size)
1029e5c31af7Sopenharmony_ci	, m_pitch		(pitch)
1030e5c31af7Sopenharmony_ci	, m_divider		(block)
1031e5c31af7Sopenharmony_ci	, m_data		((void*)data)
1032e5c31af7Sopenharmony_ci{
1033e5c31af7Sopenharmony_ci	DE_ASSERT(isValid(format));
1034e5c31af7Sopenharmony_ci	DE_ASSERT(m_format.getPixelSize() <= m_pitch.x());
1035e5c31af7Sopenharmony_ci}
1036e5c31af7Sopenharmony_ci
1037e5c31af7Sopenharmony_ciConstPixelBufferAccess::ConstPixelBufferAccess (const TextureLevel& level)
1038e5c31af7Sopenharmony_ci	: m_format		(level.getFormat())
1039e5c31af7Sopenharmony_ci	, m_size		(level.getSize())
1040e5c31af7Sopenharmony_ci	, m_pitch		(calculatePackedPitch(m_format, m_size))
1041e5c31af7Sopenharmony_ci	, m_divider		(1,1,1)
1042e5c31af7Sopenharmony_ci	, m_data		((void*)level.getPtr())
1043e5c31af7Sopenharmony_ci{
1044e5c31af7Sopenharmony_ci}
1045e5c31af7Sopenharmony_ci
1046e5c31af7Sopenharmony_ciPixelBufferAccess::PixelBufferAccess (const TextureFormat& format, int width, int height, int depth, void* data)
1047e5c31af7Sopenharmony_ci	: ConstPixelBufferAccess(format, width, height, depth, data)
1048e5c31af7Sopenharmony_ci{
1049e5c31af7Sopenharmony_ci}
1050e5c31af7Sopenharmony_ci
1051e5c31af7Sopenharmony_ciPixelBufferAccess::PixelBufferAccess (const TextureFormat& format, const IVec3& size, void* data)
1052e5c31af7Sopenharmony_ci	: ConstPixelBufferAccess(format, size, data)
1053e5c31af7Sopenharmony_ci{
1054e5c31af7Sopenharmony_ci}
1055e5c31af7Sopenharmony_ci
1056e5c31af7Sopenharmony_ciPixelBufferAccess::PixelBufferAccess (const TextureFormat& format, int width, int height, int depth, int rowPitch, int slicePitch, void* data)
1057e5c31af7Sopenharmony_ci	: ConstPixelBufferAccess(format, width, height, depth, rowPitch, slicePitch, data)
1058e5c31af7Sopenharmony_ci{
1059e5c31af7Sopenharmony_ci}
1060e5c31af7Sopenharmony_ci
1061e5c31af7Sopenharmony_ciPixelBufferAccess::PixelBufferAccess (const TextureFormat& format, const IVec3& size, const IVec3& pitch, void* data)
1062e5c31af7Sopenharmony_ci	: ConstPixelBufferAccess(format, size, pitch, data)
1063e5c31af7Sopenharmony_ci{
1064e5c31af7Sopenharmony_ci}
1065e5c31af7Sopenharmony_ci
1066e5c31af7Sopenharmony_ciPixelBufferAccess::PixelBufferAccess(const TextureFormat& format, const IVec3& size, const IVec3& pitch, const IVec3& block, void* data)
1067e5c31af7Sopenharmony_ci	: ConstPixelBufferAccess(format, size, pitch, block, data)
1068e5c31af7Sopenharmony_ci{
1069e5c31af7Sopenharmony_ci}
1070e5c31af7Sopenharmony_ci
1071e5c31af7Sopenharmony_ci
1072e5c31af7Sopenharmony_ciPixelBufferAccess::PixelBufferAccess (TextureLevel& level)
1073e5c31af7Sopenharmony_ci	: ConstPixelBufferAccess(level)
1074e5c31af7Sopenharmony_ci{
1075e5c31af7Sopenharmony_ci}
1076e5c31af7Sopenharmony_ci
1077e5c31af7Sopenharmony_ci//! Swizzle generally based on channel order.
1078e5c31af7Sopenharmony_citemplate<typename T>
1079e5c31af7Sopenharmony_ciVector<T, 4> swizzleGe (const Vector<T, 4>& v, TextureFormat::ChannelOrder src, TextureFormat::ChannelOrder dst)
1080e5c31af7Sopenharmony_ci{
1081e5c31af7Sopenharmony_ci	if (src == dst)
1082e5c31af7Sopenharmony_ci		return v;
1083e5c31af7Sopenharmony_ci	else
1084e5c31af7Sopenharmony_ci	{
1085e5c31af7Sopenharmony_ci		if ((src == TextureFormat::RGBA && dst == TextureFormat::ARGB) ||
1086e5c31af7Sopenharmony_ci			(src == TextureFormat::BGRA && dst == TextureFormat::ABGR))
1087e5c31af7Sopenharmony_ci			return v.swizzle(3, 0, 1, 2);
1088e5c31af7Sopenharmony_ci
1089e5c31af7Sopenharmony_ci		if ((src == TextureFormat::ARGB && dst == TextureFormat::RGBA) ||
1090e5c31af7Sopenharmony_ci			(src == TextureFormat::ABGR && dst == TextureFormat::BGRA))
1091e5c31af7Sopenharmony_ci			return v.swizzle(1, 2, 3, 0);
1092e5c31af7Sopenharmony_ci
1093e5c31af7Sopenharmony_ci		if ((src == TextureFormat::BGRA && dst == TextureFormat::ARGB) ||
1094e5c31af7Sopenharmony_ci		    (src == TextureFormat::ABGR && dst == TextureFormat::RGBA) ||
1095e5c31af7Sopenharmony_ci			(src == TextureFormat::RGBA && dst == TextureFormat::ABGR) ||
1096e5c31af7Sopenharmony_ci			(src == TextureFormat::ARGB && dst == TextureFormat::BGRA))
1097e5c31af7Sopenharmony_ci			return v.swizzle(3, 2, 1, 0);
1098e5c31af7Sopenharmony_ci
1099e5c31af7Sopenharmony_ci		if ((src == TextureFormat::RGB && dst == TextureFormat::BGR) ||
1100e5c31af7Sopenharmony_ci			(src == TextureFormat::BGR && dst == TextureFormat::RGB) ||
1101e5c31af7Sopenharmony_ci			(src == TextureFormat::RGBA && dst == TextureFormat::BGRA) ||
1102e5c31af7Sopenharmony_ci			(src == TextureFormat::BGRA && dst == TextureFormat::RGBA))
1103e5c31af7Sopenharmony_ci			return v.swizzle(2,1,0,3);
1104e5c31af7Sopenharmony_ci
1105e5c31af7Sopenharmony_ci		DE_ASSERT(false);
1106e5c31af7Sopenharmony_ci		return v;
1107e5c31af7Sopenharmony_ci	}
1108e5c31af7Sopenharmony_ci}
1109e5c31af7Sopenharmony_ci
1110e5c31af7Sopenharmony_ciVec4 ConstPixelBufferAccess::getPixel (int x, int y, int z) const
1111e5c31af7Sopenharmony_ci{
1112e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(x, 0, m_size.x()));
1113e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(y, 0, m_size.y()));
1114e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(z, 0, m_size.z()));
1115e5c31af7Sopenharmony_ci	DE_ASSERT(!isCombinedDepthStencilType(m_format.type)); // combined types cannot be accessed directly
1116e5c31af7Sopenharmony_ci	DE_ASSERT(m_format.order != TextureFormat::DS); // combined formats cannot be accessed directly
1117e5c31af7Sopenharmony_ci
1118e5c31af7Sopenharmony_ci	const deUint8* pixelPtr = (const deUint8*)getPixelPtr(x, y, z);
1119e5c31af7Sopenharmony_ci
1120e5c31af7Sopenharmony_ci	// Optimized fomats.
1121e5c31af7Sopenharmony_ci	if (m_format.type == TextureFormat::UNORM_INT8)
1122e5c31af7Sopenharmony_ci	{
1123e5c31af7Sopenharmony_ci		if (m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA)
1124e5c31af7Sopenharmony_ci			return readRGBA8888Float(pixelPtr);
1125e5c31af7Sopenharmony_ci		else if (m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB)
1126e5c31af7Sopenharmony_ci			return readRGB888Float(pixelPtr);
1127e5c31af7Sopenharmony_ci	}
1128e5c31af7Sopenharmony_ci
1129e5c31af7Sopenharmony_ci#define UI8(OFFS, COUNT)		((*((const deUint8*)pixelPtr) >> (OFFS)) & ((1<<(COUNT))-1))
1130e5c31af7Sopenharmony_ci#define UI16(OFFS, COUNT)		((*((const deUint16*)pixelPtr) >> (OFFS)) & ((1<<(COUNT))-1))
1131e5c31af7Sopenharmony_ci#define UI32(OFFS, COUNT)		((*((const deUint32*)pixelPtr) >> (OFFS)) & ((1<<(COUNT))-1))
1132e5c31af7Sopenharmony_ci#define SI32(OFFS, COUNT)		signExtend(UI32(OFFS, COUNT), (COUNT))
1133e5c31af7Sopenharmony_ci#define UN8(OFFS, COUNT)		channelToUnormFloat(UI8 (OFFS, COUNT), (COUNT))
1134e5c31af7Sopenharmony_ci#define UN16(OFFS, COUNT)		channelToUnormFloat(UI16(OFFS, COUNT), (COUNT))
1135e5c31af7Sopenharmony_ci#define UN32(OFFS, COUNT)		channelToUnormFloat(UI32(OFFS, COUNT), (COUNT))
1136e5c31af7Sopenharmony_ci#define SN32(OFFS, COUNT)		channelToSnormFloat(UI32(OFFS, COUNT), (COUNT))
1137e5c31af7Sopenharmony_ci
1138e5c31af7Sopenharmony_ci	// Packed formats.
1139e5c31af7Sopenharmony_ci	switch (m_format.type)
1140e5c31af7Sopenharmony_ci	{
1141e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_BYTE_44:				return			  Vec4(UN8 (4,   4), UN8 ( 0,  4), 0.0f, 1.0f);
1142e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_BYTE_44:			return			 UVec4(UI8 (4,   4), UI8 ( 0,  4), 0u, 1u).cast<float>();
1143e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_565:			return swizzleGe( Vec4(UN16(11,  5), UN16( 5,  6), UN16( 0,  5), 1.0f), m_format.order, TextureFormat::RGB);
1144e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_565:			return swizzleGe(UVec4(UI16(11,  5), UI16( 5,  6), UI16( 0,  5), 1u), m_format.order, TextureFormat::RGB).cast<float>();
1145e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_555:			return swizzleGe( Vec4(UN16(10,  5), UN16( 5,  5), UN16( 0,  5), 1.0f), m_format.order, TextureFormat::RGB);
1146e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_4444:			return swizzleGe( Vec4(UN16(12,  4), UN16( 8,  4), UN16( 4,  4), UN16( 0, 4)), m_format.order, TextureFormat::RGBA);
1147e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_4444:		return swizzleGe(UVec4(UI16(12,  4), UI16( 8,  4), UI16( 4,  4), UI16( 0, 4)), m_format.order, TextureFormat::RGBA).cast<float>();
1148e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_5551:			return swizzleGe( Vec4(UN16(11,  5), UN16( 6,  5), UN16( 1,  5), UN16( 0, 1)), m_format.order, TextureFormat::RGBA);
1149e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_5551:		return swizzleGe(UVec4(UI16(11,  5), UI16( 6,  5), UI16( 1,  5), UI16( 0, 1)), m_format.order, TextureFormat::RGBA).cast<float>();
1150e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_1555:			return swizzleGe( Vec4(UN16(15,  1), UN16(10,  5), UN16( 5,  5), UN16( 0, 5)), m_format.order, TextureFormat::RGBA);
1151e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_101010:			return			  Vec4(UN32(22, 10), UN32(12, 10), UN32( 2, 10), 1.0f);
1152e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_1010102_REV:		return swizzleGe( Vec4(UN32( 0, 10), UN32(10, 10), UN32(20, 10), UN32(30, 2)), m_format.order, TextureFormat::RGBA);
1153e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT_1010102_REV:		return swizzleGe( Vec4(SN32( 0, 10), SN32(10, 10), SN32(20, 10), SN32(30, 2)), m_format.order, TextureFormat::RGBA);
1154e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT_1010102_REV:
1155e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_1010102_REV:	return swizzleGe( UVec4(UI32(0, 10), UI32(10, 10), UI32(20, 10), UI32(30, 2)), m_format.order, TextureFormat::RGBA).cast<float>();
1156e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT_1010102_REV:
1157e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT_1010102_REV:		return swizzleGe( UVec4(SI32(0, 10), SI32(10, 10), SI32(20, 10), SI32(30, 2)), m_format.order, TextureFormat::RGBA).cast<float>();
1158e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_999_E5_REV:	return unpackRGB999E5(*((const deUint32*)pixelPtr));
1159e5c31af7Sopenharmony_ci
1160e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
1161e5c31af7Sopenharmony_ci			return Vec4(Float11(UI32(0, 11)).asFloat(), Float11(UI32(11, 11)).asFloat(), Float10(UI32(22, 10)).asFloat(), 1.0f);
1162e5c31af7Sopenharmony_ci
1163e5c31af7Sopenharmony_ci		default:
1164e5c31af7Sopenharmony_ci			break;
1165e5c31af7Sopenharmony_ci	}
1166e5c31af7Sopenharmony_ci
1167e5c31af7Sopenharmony_ci#undef UN8
1168e5c31af7Sopenharmony_ci#undef UN16
1169e5c31af7Sopenharmony_ci#undef UN32
1170e5c31af7Sopenharmony_ci#undef SN32
1171e5c31af7Sopenharmony_ci#undef SI32
1172e5c31af7Sopenharmony_ci#undef UI8
1173e5c31af7Sopenharmony_ci#undef UI16
1174e5c31af7Sopenharmony_ci#undef UI32
1175e5c31af7Sopenharmony_ci
1176e5c31af7Sopenharmony_ci	// Generic path.
1177e5c31af7Sopenharmony_ci	Vec4							result;
1178e5c31af7Sopenharmony_ci	const TextureSwizzle::Channel*	channelMap	= getChannelReadSwizzle(m_format.order).components;
1179e5c31af7Sopenharmony_ci	int								channelSize	= getChannelSize(m_format.type);
1180e5c31af7Sopenharmony_ci
1181e5c31af7Sopenharmony_ci	for (int c = 0; c < 4; c++)
1182e5c31af7Sopenharmony_ci	{
1183e5c31af7Sopenharmony_ci		switch (channelMap[c])
1184e5c31af7Sopenharmony_ci		{
1185e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_0:
1186e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_1:
1187e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_2:
1188e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_3:
1189e5c31af7Sopenharmony_ci				result[c] = channelToFloat(pixelPtr + channelSize*((int)channelMap[c]), m_format.type);
1190e5c31af7Sopenharmony_ci				break;
1191e5c31af7Sopenharmony_ci
1192e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_ZERO:
1193e5c31af7Sopenharmony_ci				result[c] = 0.0f;
1194e5c31af7Sopenharmony_ci				break;
1195e5c31af7Sopenharmony_ci
1196e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_ONE:
1197e5c31af7Sopenharmony_ci				result[c] = 1.0f;
1198e5c31af7Sopenharmony_ci				break;
1199e5c31af7Sopenharmony_ci
1200e5c31af7Sopenharmony_ci			default:
1201e5c31af7Sopenharmony_ci				DE_ASSERT(false);
1202e5c31af7Sopenharmony_ci		}
1203e5c31af7Sopenharmony_ci	}
1204e5c31af7Sopenharmony_ci
1205e5c31af7Sopenharmony_ci	return result;
1206e5c31af7Sopenharmony_ci}
1207e5c31af7Sopenharmony_ci
1208e5c31af7Sopenharmony_citemplate <typename T>
1209e5c31af7Sopenharmony_cistatic tcu::Vector<T, 4> getPixelIntGeneric (const deUint8* pixelPtr, const tcu::TextureFormat& format)
1210e5c31af7Sopenharmony_ci{
1211e5c31af7Sopenharmony_ci	tcu::Vector<T, 4> result;
1212e5c31af7Sopenharmony_ci
1213e5c31af7Sopenharmony_ci	// Generic path.
1214e5c31af7Sopenharmony_ci	const TextureSwizzle::Channel*	channelMap	= getChannelReadSwizzle(format.order).components;
1215e5c31af7Sopenharmony_ci	int								channelSize	= getChannelSize(format.type);
1216e5c31af7Sopenharmony_ci
1217e5c31af7Sopenharmony_ci	for (int c = 0; c < 4; c++)
1218e5c31af7Sopenharmony_ci	{
1219e5c31af7Sopenharmony_ci		switch (channelMap[c])
1220e5c31af7Sopenharmony_ci		{
1221e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_0:
1222e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_1:
1223e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_2:
1224e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_3:
1225e5c31af7Sopenharmony_ci				result[c] = channelToIntType<T>(pixelPtr + channelSize*((int)channelMap[c]), format.type);
1226e5c31af7Sopenharmony_ci				break;
1227e5c31af7Sopenharmony_ci
1228e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_ZERO:
1229e5c31af7Sopenharmony_ci				result[c] = 0;
1230e5c31af7Sopenharmony_ci				break;
1231e5c31af7Sopenharmony_ci
1232e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_ONE:
1233e5c31af7Sopenharmony_ci				result[c] = 1;
1234e5c31af7Sopenharmony_ci				break;
1235e5c31af7Sopenharmony_ci
1236e5c31af7Sopenharmony_ci			default:
1237e5c31af7Sopenharmony_ci				DE_ASSERT(false);
1238e5c31af7Sopenharmony_ci		}
1239e5c31af7Sopenharmony_ci	}
1240e5c31af7Sopenharmony_ci
1241e5c31af7Sopenharmony_ci	return result;
1242e5c31af7Sopenharmony_ci}
1243e5c31af7Sopenharmony_ci
1244e5c31af7Sopenharmony_cistatic U64Vec4 getPixelAsBitsUint64 (const deUint8* pixelPtr, const tcu::TextureFormat& format)
1245e5c31af7Sopenharmony_ci{
1246e5c31af7Sopenharmony_ci	U64Vec4 result;
1247e5c31af7Sopenharmony_ci
1248e5c31af7Sopenharmony_ci	// Generic path.
1249e5c31af7Sopenharmony_ci	const TextureSwizzle::Channel*	channelMap	= getChannelReadSwizzle(format.order).components;
1250e5c31af7Sopenharmony_ci	int								channelSize	= getChannelSize(format.type);
1251e5c31af7Sopenharmony_ci
1252e5c31af7Sopenharmony_ci	for (int c = 0; c < 4; c++)
1253e5c31af7Sopenharmony_ci	{
1254e5c31af7Sopenharmony_ci		switch (channelMap[c])
1255e5c31af7Sopenharmony_ci		{
1256e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_0:
1257e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_1:
1258e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_2:
1259e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_3:
1260e5c31af7Sopenharmony_ci				result[c] = retrieveChannelBitsAsUint64(pixelPtr + channelSize*((int)channelMap[c]), format.type);
1261e5c31af7Sopenharmony_ci				break;
1262e5c31af7Sopenharmony_ci
1263e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_ZERO:
1264e5c31af7Sopenharmony_ci				result[c] = 0;
1265e5c31af7Sopenharmony_ci				break;
1266e5c31af7Sopenharmony_ci
1267e5c31af7Sopenharmony_ci			case TextureSwizzle::CHANNEL_ONE:
1268e5c31af7Sopenharmony_ci				result[c] = 1;
1269e5c31af7Sopenharmony_ci				break;
1270e5c31af7Sopenharmony_ci
1271e5c31af7Sopenharmony_ci			default:
1272e5c31af7Sopenharmony_ci				DE_ASSERT(false);
1273e5c31af7Sopenharmony_ci		}
1274e5c31af7Sopenharmony_ci	}
1275e5c31af7Sopenharmony_ci
1276e5c31af7Sopenharmony_ci	return result;
1277e5c31af7Sopenharmony_ci}
1278e5c31af7Sopenharmony_ci
1279e5c31af7Sopenharmony_ciIVec4 ConstPixelBufferAccess::getPixelInt (int x, int y, int z) const
1280e5c31af7Sopenharmony_ci{
1281e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(x, 0, m_size.x()));
1282e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(y, 0, m_size.y()));
1283e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(z, 0, m_size.z()));
1284e5c31af7Sopenharmony_ci	DE_ASSERT(!isCombinedDepthStencilType(m_format.type)); // combined types cannot be accessed directly
1285e5c31af7Sopenharmony_ci	DE_ASSERT(m_format.order != TextureFormat::DS); // combined formats cannot be accessed directly
1286e5c31af7Sopenharmony_ci
1287e5c31af7Sopenharmony_ci	const deUint8* const	pixelPtr = (const deUint8*)getPixelPtr(x, y, z);
1288e5c31af7Sopenharmony_ci
1289e5c31af7Sopenharmony_ci	// Optimized fomats.
1290e5c31af7Sopenharmony_ci	if (m_format.type == TextureFormat::UNORM_INT8)
1291e5c31af7Sopenharmony_ci	{
1292e5c31af7Sopenharmony_ci		if (m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA)
1293e5c31af7Sopenharmony_ci			return readRGBA8888Int(pixelPtr);
1294e5c31af7Sopenharmony_ci		else if (m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB)
1295e5c31af7Sopenharmony_ci			return readRGB888Int(pixelPtr);
1296e5c31af7Sopenharmony_ci	}
1297e5c31af7Sopenharmony_ci
1298e5c31af7Sopenharmony_ci#define U8(OFFS, COUNT)			((*((const deUint8* )pixelPtr) >> (OFFS)) & ((1<<(COUNT))-1))
1299e5c31af7Sopenharmony_ci#define U16(OFFS, COUNT)		((*((const deUint16*)pixelPtr) >> (OFFS)) & ((1<<(COUNT))-1))
1300e5c31af7Sopenharmony_ci#define U32(OFFS, COUNT)		((*((const deUint32*)pixelPtr) >> (OFFS)) & ((1<<(COUNT))-1))
1301e5c31af7Sopenharmony_ci#define S32(OFFS, COUNT)		signExtend(U32(OFFS, COUNT), (COUNT))
1302e5c31af7Sopenharmony_ci
1303e5c31af7Sopenharmony_ci	switch (m_format.type)
1304e5c31af7Sopenharmony_ci	{
1305e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_BYTE_44:			// Fall-through
1306e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_BYTE_44:				return			 UVec4(U8 ( 4,  4), U8 ( 0,  4), 0u, 1u).cast<int>();
1307e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_565:			// Fall-through
1308e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_565:			return swizzleGe(UVec4(U16(11,  5), U16( 5,  6), U16( 0,  5), 1).cast<int>(), m_format.order, TextureFormat::RGB);
1309e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_555:			return swizzleGe(UVec4(U16(10,  5), U16( 5,  5), U16( 0,  5), 1).cast<int>(), m_format.order, TextureFormat::RGB);
1310e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_4444:		// Fall-through
1311e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_4444:			return swizzleGe(UVec4(U16(12,  4), U16( 8,  4), U16( 4,  4), U16( 0, 4)).cast<int>(), m_format.order, TextureFormat::RGBA);
1312e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_5551:		// Fall-through
1313e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_5551:			return swizzleGe(UVec4(U16(11,  5), U16( 6,  5), U16( 1,  5), U16( 0, 1)).cast<int>(), m_format.order, TextureFormat::RGBA);
1314e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_1555:			return swizzleGe(UVec4(U16(15,  1), U16(10,  5), U16( 5,  5), U16( 0, 5)).cast<int>(), m_format.order, TextureFormat::RGBA);
1315e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_101010:			return			 UVec4(U32(22, 10), U32(12, 10), U32( 2, 10), 1).cast<int>();
1316e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_1010102_REV:		// Fall-through
1317e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT_1010102_REV:	// Fall-through
1318e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_1010102_REV:	return swizzleGe(UVec4(U32( 0, 10), U32(10, 10), U32(20, 10), U32(30, 2)), m_format.order, TextureFormat::RGBA).cast<int>();
1319e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT_1010102_REV:		// Fall-through
1320e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT_1010102_REV:	// Fall-through
1321e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT_1010102_REV:		return swizzleGe(IVec4(S32( 0, 10), S32(10, 10), S32(20, 10), S32(30, 2)), m_format.order, TextureFormat::RGBA);
1322e5c31af7Sopenharmony_ci
1323e5c31af7Sopenharmony_ci		default:
1324e5c31af7Sopenharmony_ci			break; // To generic path.
1325e5c31af7Sopenharmony_ci	}
1326e5c31af7Sopenharmony_ci
1327e5c31af7Sopenharmony_ci#undef U8
1328e5c31af7Sopenharmony_ci#undef U16
1329e5c31af7Sopenharmony_ci#undef U32
1330e5c31af7Sopenharmony_ci#undef S32
1331e5c31af7Sopenharmony_ci
1332e5c31af7Sopenharmony_ci	// Generic path.
1333e5c31af7Sopenharmony_ci	return getPixelIntGeneric<int>(pixelPtr, m_format);
1334e5c31af7Sopenharmony_ci}
1335e5c31af7Sopenharmony_ci
1336e5c31af7Sopenharmony_ciI64Vec4 ConstPixelBufferAccess::getPixelInt64 (int x, int y, int z) const
1337e5c31af7Sopenharmony_ci{
1338e5c31af7Sopenharmony_ci	// Rely on getPixelInt() for some formats.
1339e5c31af7Sopenharmony_ci	if (m_format.type == TextureFormat::UNORM_INT8 &&
1340e5c31af7Sopenharmony_ci		(m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA ||
1341e5c31af7Sopenharmony_ci		 m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB))
1342e5c31af7Sopenharmony_ci	{
1343e5c31af7Sopenharmony_ci			return getPixelInt(x, y, z).cast<deInt64>();
1344e5c31af7Sopenharmony_ci	}
1345e5c31af7Sopenharmony_ci
1346e5c31af7Sopenharmony_ci	switch (m_format.type)
1347e5c31af7Sopenharmony_ci	{
1348e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_BYTE_44:
1349e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_BYTE_44:
1350e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_565:
1351e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_565:
1352e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_555:
1353e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_4444:
1354e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_4444:
1355e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_5551:
1356e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_5551:
1357e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_101010:
1358e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_1010102_REV:
1359e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT_1010102_REV:
1360e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_1010102_REV:
1361e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT_1010102_REV:
1362e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT_1010102_REV:
1363e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT_1010102_REV:
1364e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_1555:
1365e5c31af7Sopenharmony_ci			return getPixelInt(x, y, z).cast<deInt64>();
1366e5c31af7Sopenharmony_ci
1367e5c31af7Sopenharmony_ci		default:
1368e5c31af7Sopenharmony_ci			break; // To generic path.
1369e5c31af7Sopenharmony_ci	}
1370e5c31af7Sopenharmony_ci
1371e5c31af7Sopenharmony_ci	// Generic path.
1372e5c31af7Sopenharmony_ci	auto pixelPtr = reinterpret_cast<const deUint8*>(getPixelPtr(x, y, z));
1373e5c31af7Sopenharmony_ci	return getPixelIntGeneric<deInt64>(pixelPtr, m_format);
1374e5c31af7Sopenharmony_ci}
1375e5c31af7Sopenharmony_ci
1376e5c31af7Sopenharmony_ciU64Vec4 ConstPixelBufferAccess::getPixelBitsAsUint64 (int x, int y, int z) const
1377e5c31af7Sopenharmony_ci{
1378e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(x, 0, m_size.x()));
1379e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(y, 0, m_size.y()));
1380e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(z, 0, m_size.z()));
1381e5c31af7Sopenharmony_ci	DE_ASSERT(!isCombinedDepthStencilType(m_format.type)); // combined types cannot be accessed directly
1382e5c31af7Sopenharmony_ci	DE_ASSERT(m_format.order != TextureFormat::DS); // combined formats cannot be accessed directly
1383e5c31af7Sopenharmony_ci
1384e5c31af7Sopenharmony_ci	const deUint8* const	pixelPtr = (const deUint8*)getPixelPtr(x, y, z);
1385e5c31af7Sopenharmony_ci
1386e5c31af7Sopenharmony_ci	if (m_format.type == TextureFormat::UNORM_INT8)
1387e5c31af7Sopenharmony_ci	{
1388e5c31af7Sopenharmony_ci		if (m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA)
1389e5c31af7Sopenharmony_ci			return U64Vec4(pixelPtr[0], pixelPtr[1], pixelPtr[2], pixelPtr[3]);
1390e5c31af7Sopenharmony_ci		else if (m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB)
1391e5c31af7Sopenharmony_ci			return U64Vec4(pixelPtr[0], pixelPtr[1], pixelPtr[2], 1);
1392e5c31af7Sopenharmony_ci	}
1393e5c31af7Sopenharmony_ci
1394e5c31af7Sopenharmony_ci#define U8(OFFS, COUNT)			((*((const deUint8* )pixelPtr) >> (OFFS)) & ((1<<(COUNT))-1))
1395e5c31af7Sopenharmony_ci#define U16(OFFS, COUNT)		((*((const deUint16*)pixelPtr) >> (OFFS)) & ((1<<(COUNT))-1))
1396e5c31af7Sopenharmony_ci#define U32(OFFS, COUNT)		((*((const deUint32*)pixelPtr) >> (OFFS)) & ((1<<(COUNT))-1))
1397e5c31af7Sopenharmony_ci
1398e5c31af7Sopenharmony_ci	switch (m_format.type)
1399e5c31af7Sopenharmony_ci	{
1400e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_BYTE_44:			// Fall-through
1401e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_BYTE_44:				return			 U64Vec4(U8 ( 4,  4), U8 ( 0,  4), 0u, 1u);
1402e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_565:			// Fall-through
1403e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_565:			return swizzleGe(U64Vec4(U16(11,  5), U16( 5,  6), U16( 0,  5), 1), m_format.order, TextureFormat::RGB);
1404e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_555:			return swizzleGe(U64Vec4(U16(10,  5), U16( 5,  5), U16( 0,  5), 1), m_format.order, TextureFormat::RGB);
1405e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_4444:		// Fall-through
1406e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_4444:			return swizzleGe(U64Vec4(U16(12,  4), U16( 8,  4), U16( 4,  4), U16( 0, 4)), m_format.order, TextureFormat::RGBA);
1407e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_5551:		// Fall-through
1408e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_5551:			return swizzleGe(U64Vec4(U16(11,  5), U16( 6,  5), U16( 1,  5), U16( 0, 1)), m_format.order, TextureFormat::RGBA);
1409e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_101010:			return			 U64Vec4(U32(22, 10), U32(12, 10), U32( 2, 10), 1);
1410e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_1010102_REV:		// Fall-through
1411e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT_1010102_REV:	// Fall-through
1412e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_1010102_REV:	return swizzleGe(U64Vec4(U32( 0, 10), U32(10, 10), U32(20, 10), U32(30, 2)), m_format.order, TextureFormat::RGBA);
1413e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT_1010102_REV:		// Fall-through
1414e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT_1010102_REV:	// Fall-through
1415e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT_1010102_REV:		return swizzleGe(U64Vec4(U32( 0, 10), U32(10, 10), U32(20, 10), U32(30, 2)), m_format.order, TextureFormat::RGBA);
1416e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_1555:			return swizzleGe(U64Vec4(U16(15,  1), U16(10,  5), U16( 5,  5), U16( 0, 5)), m_format.order, TextureFormat::RGBA);
1417e5c31af7Sopenharmony_ci
1418e5c31af7Sopenharmony_ci
1419e5c31af7Sopenharmony_ci		default:
1420e5c31af7Sopenharmony_ci			break; // To generic path.
1421e5c31af7Sopenharmony_ci	}
1422e5c31af7Sopenharmony_ci
1423e5c31af7Sopenharmony_ci#undef U8
1424e5c31af7Sopenharmony_ci#undef U16
1425e5c31af7Sopenharmony_ci#undef U32
1426e5c31af7Sopenharmony_ci
1427e5c31af7Sopenharmony_ci	// Generic path.
1428e5c31af7Sopenharmony_ci	return getPixelAsBitsUint64(pixelPtr, m_format);
1429e5c31af7Sopenharmony_ci}
1430e5c31af7Sopenharmony_ci
1431e5c31af7Sopenharmony_citemplate<>
1432e5c31af7Sopenharmony_ciVec4 ConstPixelBufferAccess::getPixelT (int x, int y, int z) const
1433e5c31af7Sopenharmony_ci{
1434e5c31af7Sopenharmony_ci	return getPixel(x, y, z);
1435e5c31af7Sopenharmony_ci}
1436e5c31af7Sopenharmony_ci
1437e5c31af7Sopenharmony_citemplate<>
1438e5c31af7Sopenharmony_ciIVec4 ConstPixelBufferAccess::getPixelT (int x, int y, int z) const
1439e5c31af7Sopenharmony_ci{
1440e5c31af7Sopenharmony_ci	return getPixelInt(x, y, z);
1441e5c31af7Sopenharmony_ci}
1442e5c31af7Sopenharmony_ci
1443e5c31af7Sopenharmony_citemplate<>
1444e5c31af7Sopenharmony_ciUVec4 ConstPixelBufferAccess::getPixelT (int x, int y, int z) const
1445e5c31af7Sopenharmony_ci{
1446e5c31af7Sopenharmony_ci	return getPixelUint(x, y, z);
1447e5c31af7Sopenharmony_ci}
1448e5c31af7Sopenharmony_ci
1449e5c31af7Sopenharmony_citemplate<>
1450e5c31af7Sopenharmony_ciI64Vec4 ConstPixelBufferAccess::getPixelT (int x, int y, int z) const
1451e5c31af7Sopenharmony_ci{
1452e5c31af7Sopenharmony_ci	return getPixelInt64(x, y, z);
1453e5c31af7Sopenharmony_ci}
1454e5c31af7Sopenharmony_ci
1455e5c31af7Sopenharmony_citemplate<>
1456e5c31af7Sopenharmony_ciU64Vec4 ConstPixelBufferAccess::getPixelT (int x, int y, int z) const
1457e5c31af7Sopenharmony_ci{
1458e5c31af7Sopenharmony_ci	return getPixelUint64(x, y, z);
1459e5c31af7Sopenharmony_ci}
1460e5c31af7Sopenharmony_ci
1461e5c31af7Sopenharmony_cifloat ConstPixelBufferAccess::getPixDepth (int x, int y, int z) const
1462e5c31af7Sopenharmony_ci{
1463e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(x, 0, getWidth()));
1464e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(y, 0, getHeight()));
1465e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(z, 0, getDepth()));
1466e5c31af7Sopenharmony_ci
1467e5c31af7Sopenharmony_ci	const deUint8* const pixelPtr = (const deUint8*)getPixelPtr(x, y, z);
1468e5c31af7Sopenharmony_ci
1469e5c31af7Sopenharmony_ci	switch (m_format.type)
1470e5c31af7Sopenharmony_ci	{
1471e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_16_8_8:
1472e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::DS);
1473e5c31af7Sopenharmony_ci			return (float)readUint32High16(pixelPtr) / 65535.0f;
1474e5c31af7Sopenharmony_ci
1475e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8:
1476e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::D || m_format.order == TextureFormat::DS);
1477e5c31af7Sopenharmony_ci			return (float)readUint32High24(pixelPtr) / 16777215.0f;
1478e5c31af7Sopenharmony_ci
1479e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8_REV:
1480e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::D || m_format.order == TextureFormat::DS);
1481e5c31af7Sopenharmony_ci			return (float)readUint32Low24(pixelPtr) / 16777215.0f;
1482e5c31af7Sopenharmony_ci
1483e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
1484e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::DS);
1485e5c31af7Sopenharmony_ci			return *((const float*)pixelPtr);
1486e5c31af7Sopenharmony_ci
1487e5c31af7Sopenharmony_ci		default:
1488e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::D); // no other combined depth stencil types
1489e5c31af7Sopenharmony_ci			return channelToFloat(pixelPtr, m_format.type);
1490e5c31af7Sopenharmony_ci	}
1491e5c31af7Sopenharmony_ci}
1492e5c31af7Sopenharmony_ci
1493e5c31af7Sopenharmony_ciint ConstPixelBufferAccess::getPixStencil (int x, int y, int z) const
1494e5c31af7Sopenharmony_ci{
1495e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(x, 0, getWidth()));
1496e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(y, 0, getHeight()));
1497e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(z, 0, getDepth()));
1498e5c31af7Sopenharmony_ci
1499e5c31af7Sopenharmony_ci	const deUint8* const pixelPtr = (const deUint8*)getPixelPtr(x, y, z);
1500e5c31af7Sopenharmony_ci
1501e5c31af7Sopenharmony_ci	switch (m_format.type)
1502e5c31af7Sopenharmony_ci	{
1503e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8_REV:
1504e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::DS);
1505e5c31af7Sopenharmony_ci			return (int)readUint32High8(pixelPtr);
1506e5c31af7Sopenharmony_ci
1507e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_16_8_8:
1508e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8:
1509e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::DS);
1510e5c31af7Sopenharmony_ci			return (int)readUint32Low8(pixelPtr);
1511e5c31af7Sopenharmony_ci
1512e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
1513e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::DS);
1514e5c31af7Sopenharmony_ci			return (int)readUint32Low8(pixelPtr + 4);
1515e5c31af7Sopenharmony_ci
1516e5c31af7Sopenharmony_ci		default:
1517e5c31af7Sopenharmony_ci		{
1518e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::S); // no other combined depth stencil types
1519e5c31af7Sopenharmony_ci			return channelToInt(pixelPtr, m_format.type);
1520e5c31af7Sopenharmony_ci		}
1521e5c31af7Sopenharmony_ci	}
1522e5c31af7Sopenharmony_ci}
1523e5c31af7Sopenharmony_ci
1524e5c31af7Sopenharmony_civoid PixelBufferAccess::setPixel (const Vec4& color, int x, int y, int z) const
1525e5c31af7Sopenharmony_ci{
1526e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(x, 0, getWidth()));
1527e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(y, 0, getHeight()));
1528e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(z, 0, getDepth()));
1529e5c31af7Sopenharmony_ci	DE_ASSERT(!isCombinedDepthStencilType(m_format.type)); // combined types cannot be accessed directly
1530e5c31af7Sopenharmony_ci	DE_ASSERT(m_format.order != TextureFormat::DS); // combined formats cannot be accessed directly
1531e5c31af7Sopenharmony_ci
1532e5c31af7Sopenharmony_ci	deUint8* const pixelPtr = (deUint8*)getPixelPtr(x, y, z);
1533e5c31af7Sopenharmony_ci
1534e5c31af7Sopenharmony_ci	// Optimized fomats.
1535e5c31af7Sopenharmony_ci	if (m_format.type == TextureFormat::UNORM_INT8)
1536e5c31af7Sopenharmony_ci	{
1537e5c31af7Sopenharmony_ci		if (m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA)
1538e5c31af7Sopenharmony_ci		{
1539e5c31af7Sopenharmony_ci			writeRGBA8888Float(pixelPtr, color);
1540e5c31af7Sopenharmony_ci			return;
1541e5c31af7Sopenharmony_ci		}
1542e5c31af7Sopenharmony_ci		else if (m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB)
1543e5c31af7Sopenharmony_ci		{
1544e5c31af7Sopenharmony_ci			writeRGB888Float(pixelPtr, color);
1545e5c31af7Sopenharmony_ci			return;
1546e5c31af7Sopenharmony_ci		}
1547e5c31af7Sopenharmony_ci	}
1548e5c31af7Sopenharmony_ci
1549e5c31af7Sopenharmony_ci#define PN(VAL, OFFS, BITS)		(unormFloatToChannel((VAL), (BITS)) << (OFFS))
1550e5c31af7Sopenharmony_ci#define PS(VAL, OFFS, BITS)		(snormFloatToChannel((VAL), (BITS)) << (OFFS))
1551e5c31af7Sopenharmony_ci#define PU(VAL, OFFS, BITS)		(uintToChannel((VAL), (BITS)) << (OFFS))
1552e5c31af7Sopenharmony_ci#define PI(VAL, OFFS, BITS)		(intToChannel((VAL), (BITS)) << (OFFS))
1553e5c31af7Sopenharmony_ci
1554e5c31af7Sopenharmony_ci	switch (m_format.type)
1555e5c31af7Sopenharmony_ci	{
1556e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_BYTE_44:		*((deUint8 *)pixelPtr) = (deUint8)(PN(color[0], 4, 4) | PN(color[1], 0, 4));						break;
1557e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_BYTE_44:	*((deUint8 *)pixelPtr) = (deUint8)(PU((deUint32)color[0], 4, 4) | PU((deUint32)color[1], 0, 4));	break;
1558e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_101010:	*((deUint32*)pixelPtr) = PN(color[0], 22, 10) | PN(color[1], 12, 10) | PN(color[2], 2, 10);			break;
1559e5c31af7Sopenharmony_ci
1560e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_565:
1561e5c31af7Sopenharmony_ci		{
1562e5c31af7Sopenharmony_ci			const Vec4 swizzled = swizzleGe(color, TextureFormat::RGB, m_format.order);
1563e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PN(swizzled[0], 11, 5) | PN(swizzled[1], 5, 6) | PN(swizzled[2], 0, 5));
1564e5c31af7Sopenharmony_ci			break;
1565e5c31af7Sopenharmony_ci		}
1566e5c31af7Sopenharmony_ci
1567e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_565:
1568e5c31af7Sopenharmony_ci		{
1569e5c31af7Sopenharmony_ci			const UVec4 swizzled = swizzleGe(color.cast<deUint32>(), TextureFormat::RGB, m_format.order);
1570e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PU(swizzled[0], 11, 5) | PU(swizzled[1], 5, 6) | PU(swizzled[2], 0, 5));
1571e5c31af7Sopenharmony_ci			break;
1572e5c31af7Sopenharmony_ci		}
1573e5c31af7Sopenharmony_ci
1574e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_555:
1575e5c31af7Sopenharmony_ci		{
1576e5c31af7Sopenharmony_ci			const Vec4 swizzled = swizzleGe(color, TextureFormat::RGB, m_format.order);
1577e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PN(swizzled[0], 10, 5) | PN(swizzled[1], 5, 5) | PN(swizzled[2], 0, 5));
1578e5c31af7Sopenharmony_ci			break;
1579e5c31af7Sopenharmony_ci		}
1580e5c31af7Sopenharmony_ci
1581e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_4444:
1582e5c31af7Sopenharmony_ci		{
1583e5c31af7Sopenharmony_ci			const Vec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order);
1584e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PN(swizzled[0], 12, 4) | PN(swizzled[1], 8, 4) | PN(swizzled[2], 4, 4) | PN(swizzled[3], 0, 4));
1585e5c31af7Sopenharmony_ci			break;
1586e5c31af7Sopenharmony_ci		}
1587e5c31af7Sopenharmony_ci
1588e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_4444:
1589e5c31af7Sopenharmony_ci		{
1590e5c31af7Sopenharmony_ci			const UVec4 swizzled = swizzleGe(color.cast<deUint32>(), TextureFormat::RGBA, m_format.order);
1591e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PU(swizzled[0], 12, 4) | PU(swizzled[1], 8, 4) | PU(swizzled[2], 4, 4) | PU(swizzled[3], 0, 4));
1592e5c31af7Sopenharmony_ci			break;
1593e5c31af7Sopenharmony_ci		}
1594e5c31af7Sopenharmony_ci
1595e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_5551:
1596e5c31af7Sopenharmony_ci		{
1597e5c31af7Sopenharmony_ci			const Vec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order);
1598e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PN(swizzled[0], 11, 5) | PN(swizzled[1], 6, 5) | PN(swizzled[2], 1, 5) | PN(swizzled[3], 0, 1));
1599e5c31af7Sopenharmony_ci			break;
1600e5c31af7Sopenharmony_ci		}
1601e5c31af7Sopenharmony_ci
1602e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_1555:
1603e5c31af7Sopenharmony_ci		{
1604e5c31af7Sopenharmony_ci			const Vec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order);
1605e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PN(swizzled[0], 15, 1) | PN(swizzled[1], 10, 5) | PN(swizzled[2], 5, 5) | PN(swizzled[3], 0, 5));
1606e5c31af7Sopenharmony_ci			break;
1607e5c31af7Sopenharmony_ci		}
1608e5c31af7Sopenharmony_ci
1609e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_5551:
1610e5c31af7Sopenharmony_ci		{
1611e5c31af7Sopenharmony_ci			const UVec4 swizzled = swizzleGe(color.cast<deUint32>(), TextureFormat::RGBA, m_format.order);
1612e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PU(swizzled[0], 11, 5) | PU(swizzled[1], 6, 5) | PU(swizzled[2], 1, 5) | PU(swizzled[3], 0, 1));
1613e5c31af7Sopenharmony_ci			break;
1614e5c31af7Sopenharmony_ci		}
1615e5c31af7Sopenharmony_ci
1616e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_1010102_REV:
1617e5c31af7Sopenharmony_ci		{
1618e5c31af7Sopenharmony_ci			const Vec4 u = swizzleGe(color, TextureFormat::RGBA, m_format.order);
1619e5c31af7Sopenharmony_ci			*((deUint32*)pixelPtr) = PN(u[0], 0, 10) | PN(u[1], 10, 10) | PN(u[2], 20, 10) | PN(u[3], 30, 2);
1620e5c31af7Sopenharmony_ci			break;
1621e5c31af7Sopenharmony_ci		}
1622e5c31af7Sopenharmony_ci
1623e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT_1010102_REV:
1624e5c31af7Sopenharmony_ci		{
1625e5c31af7Sopenharmony_ci			const Vec4 u = swizzleGe(color, TextureFormat::RGBA, m_format.order);
1626e5c31af7Sopenharmony_ci			*((deUint32*)pixelPtr) = PS(u[0], 0, 10) | PS(u[1], 10, 10) | PS(u[2], 20, 10) | PS(u[3], 30, 2);
1627e5c31af7Sopenharmony_ci			break;
1628e5c31af7Sopenharmony_ci		}
1629e5c31af7Sopenharmony_ci
1630e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_1010102_REV:
1631e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT_1010102_REV:
1632e5c31af7Sopenharmony_ci		{
1633e5c31af7Sopenharmony_ci			const UVec4 u = swizzleGe(color.cast<deUint32>(), TextureFormat::RGBA, m_format.order);
1634e5c31af7Sopenharmony_ci			*((deUint32*)pixelPtr) = PU(u[0], 0, 10) | PU(u[1], 10, 10) | PU(u[2], 20, 10) | PU(u[3], 30, 2);
1635e5c31af7Sopenharmony_ci			break;
1636e5c31af7Sopenharmony_ci		}
1637e5c31af7Sopenharmony_ci
1638e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT_1010102_REV:
1639e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT_1010102_REV:
1640e5c31af7Sopenharmony_ci		{
1641e5c31af7Sopenharmony_ci			const IVec4 u = swizzleGe(color.cast<deInt32>(), TextureFormat::RGBA, m_format.order);
1642e5c31af7Sopenharmony_ci			*((deUint32*)pixelPtr) = PI(u[0], 0, 10) | PI(u[1], 10, 10) | PI(u[2], 20, 10) | PI(u[3], 30, 2);
1643e5c31af7Sopenharmony_ci			break;
1644e5c31af7Sopenharmony_ci		}
1645e5c31af7Sopenharmony_ci
1646e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV:
1647e5c31af7Sopenharmony_ci			*((deUint32*)pixelPtr) = Float11(color[0]).bits() | (Float11(color[1]).bits() << 11) | (Float10(color[2]).bits() << 22);
1648e5c31af7Sopenharmony_ci			break;
1649e5c31af7Sopenharmony_ci
1650e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_999_E5_REV:
1651e5c31af7Sopenharmony_ci			*((deUint32*)pixelPtr) = packRGB999E5(color);
1652e5c31af7Sopenharmony_ci			break;
1653e5c31af7Sopenharmony_ci
1654e5c31af7Sopenharmony_ci		default:
1655e5c31af7Sopenharmony_ci		{
1656e5c31af7Sopenharmony_ci			// Generic path.
1657e5c31af7Sopenharmony_ci			int								numChannels	= getNumUsedChannels(m_format.order);
1658e5c31af7Sopenharmony_ci			const TextureSwizzle::Channel*	map			= getChannelWriteSwizzle(m_format.order).components;
1659e5c31af7Sopenharmony_ci			int								channelSize	= getChannelSize(m_format.type);
1660e5c31af7Sopenharmony_ci
1661e5c31af7Sopenharmony_ci			for (int c = 0; c < numChannels; c++)
1662e5c31af7Sopenharmony_ci			{
1663e5c31af7Sopenharmony_ci				DE_ASSERT(deInRange32(map[c], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3));
1664e5c31af7Sopenharmony_ci				floatToChannel(pixelPtr + channelSize*c, color[map[c]], m_format.type);
1665e5c31af7Sopenharmony_ci			}
1666e5c31af7Sopenharmony_ci			break;
1667e5c31af7Sopenharmony_ci		}
1668e5c31af7Sopenharmony_ci	}
1669e5c31af7Sopenharmony_ci
1670e5c31af7Sopenharmony_ci#undef PN
1671e5c31af7Sopenharmony_ci#undef PS
1672e5c31af7Sopenharmony_ci#undef PU
1673e5c31af7Sopenharmony_ci#undef PI
1674e5c31af7Sopenharmony_ci}
1675e5c31af7Sopenharmony_ci
1676e5c31af7Sopenharmony_civoid PixelBufferAccess::setPixel (const IVec4& color, int x, int y, int z) const
1677e5c31af7Sopenharmony_ci{
1678e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(x, 0, getWidth()));
1679e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(y, 0, getHeight()));
1680e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(z, 0, getDepth()));
1681e5c31af7Sopenharmony_ci	DE_ASSERT(!isCombinedDepthStencilType(m_format.type)); // combined types cannot be accessed directly
1682e5c31af7Sopenharmony_ci	DE_ASSERT(m_format.order != TextureFormat::DS); // combined formats cannot be accessed directly
1683e5c31af7Sopenharmony_ci
1684e5c31af7Sopenharmony_ci	deUint8* const pixelPtr = (deUint8*)getPixelPtr(x, y, z);
1685e5c31af7Sopenharmony_ci
1686e5c31af7Sopenharmony_ci	// Optimized fomats.
1687e5c31af7Sopenharmony_ci	if (m_format.type == TextureFormat::UNORM_INT8)
1688e5c31af7Sopenharmony_ci	{
1689e5c31af7Sopenharmony_ci		if (m_format.order == TextureFormat::RGBA || m_format.order == TextureFormat::sRGBA)
1690e5c31af7Sopenharmony_ci		{
1691e5c31af7Sopenharmony_ci			writeRGBA8888Int(pixelPtr, color);
1692e5c31af7Sopenharmony_ci			return;
1693e5c31af7Sopenharmony_ci		}
1694e5c31af7Sopenharmony_ci		else if (m_format.order == TextureFormat::RGB || m_format.order == TextureFormat::sRGB)
1695e5c31af7Sopenharmony_ci		{
1696e5c31af7Sopenharmony_ci			writeRGB888Int(pixelPtr, color);
1697e5c31af7Sopenharmony_ci			return;
1698e5c31af7Sopenharmony_ci		}
1699e5c31af7Sopenharmony_ci	}
1700e5c31af7Sopenharmony_ci
1701e5c31af7Sopenharmony_ci#define PU(VAL, OFFS, BITS)		(uintToChannel((deUint32)(VAL), (BITS)) << (OFFS))
1702e5c31af7Sopenharmony_ci#define PI(VAL, OFFS, BITS)		(intToChannel((deUint32)(VAL), (BITS)) << (OFFS))
1703e5c31af7Sopenharmony_ci
1704e5c31af7Sopenharmony_ci	switch (m_format.type)
1705e5c31af7Sopenharmony_ci	{
1706e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_BYTE_44:	// Fall-through
1707e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_BYTE_44:		*((deUint8 *)pixelPtr) = (deUint8 )(PU(color[0],  4, 4) | PU(color[1], 0, 4));				break;
1708e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_101010:	*((deUint32*)pixelPtr) = PU(color[0], 22, 10) | PU(color[1], 12, 10) | PU(color[2], 2, 10);	break;
1709e5c31af7Sopenharmony_ci
1710e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_565:
1711e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_565:
1712e5c31af7Sopenharmony_ci		{
1713e5c31af7Sopenharmony_ci			const IVec4 swizzled = swizzleGe(color, TextureFormat::RGB, m_format.order);
1714e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PU(swizzled[0], 11, 5) | PU(swizzled[1], 5, 6) | PU(swizzled[2], 0, 5));
1715e5c31af7Sopenharmony_ci			break;
1716e5c31af7Sopenharmony_ci		}
1717e5c31af7Sopenharmony_ci
1718e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_555:
1719e5c31af7Sopenharmony_ci		{
1720e5c31af7Sopenharmony_ci			const IVec4 swizzled = swizzleGe(color, TextureFormat::RGB, m_format.order);
1721e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PU(swizzled[0], 10, 5) | PU(swizzled[1], 5, 5) | PU(swizzled[2], 0, 5));
1722e5c31af7Sopenharmony_ci			break;
1723e5c31af7Sopenharmony_ci		}
1724e5c31af7Sopenharmony_ci
1725e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_4444:
1726e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_4444:
1727e5c31af7Sopenharmony_ci		{
1728e5c31af7Sopenharmony_ci			const IVec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order);
1729e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PU(swizzled[0], 12, 4) | PU(swizzled[1], 8, 4) | PU(swizzled[2], 4, 4) | PU(swizzled[3], 0, 4));
1730e5c31af7Sopenharmony_ci			break;
1731e5c31af7Sopenharmony_ci		}
1732e5c31af7Sopenharmony_ci
1733e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_5551:
1734e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_SHORT_5551:
1735e5c31af7Sopenharmony_ci		{
1736e5c31af7Sopenharmony_ci			const IVec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order);
1737e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PU(swizzled[0], 11, 5) | PU(swizzled[1], 6, 5) | PU(swizzled[2], 1, 5) | PU(swizzled[3], 0, 1));
1738e5c31af7Sopenharmony_ci			break;
1739e5c31af7Sopenharmony_ci		}
1740e5c31af7Sopenharmony_ci
1741e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_SHORT_1555:
1742e5c31af7Sopenharmony_ci		{
1743e5c31af7Sopenharmony_ci			const IVec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order);
1744e5c31af7Sopenharmony_ci			*((deUint16*)pixelPtr) = (deUint16)(PU(swizzled[0], 15, 1) | PU(swizzled[1], 10, 5) | PU(swizzled[2], 5, 5) | PU(swizzled[3], 0, 5));
1745e5c31af7Sopenharmony_ci			break;
1746e5c31af7Sopenharmony_ci		}
1747e5c31af7Sopenharmony_ci
1748e5c31af7Sopenharmony_ci		case TextureFormat::UNORM_INT_1010102_REV:
1749e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_1010102_REV:
1750e5c31af7Sopenharmony_ci		case TextureFormat::USCALED_INT_1010102_REV:
1751e5c31af7Sopenharmony_ci		{
1752e5c31af7Sopenharmony_ci			const IVec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order);
1753e5c31af7Sopenharmony_ci			*((deUint32*)pixelPtr) = PU(swizzled[0],  0, 10) | PU(swizzled[1], 10, 10) | PU(swizzled[2], 20, 10) | PU(swizzled[3], 30, 2);
1754e5c31af7Sopenharmony_ci			break;
1755e5c31af7Sopenharmony_ci		}
1756e5c31af7Sopenharmony_ci
1757e5c31af7Sopenharmony_ci		case TextureFormat::SNORM_INT_1010102_REV:
1758e5c31af7Sopenharmony_ci		case TextureFormat::SIGNED_INT_1010102_REV:
1759e5c31af7Sopenharmony_ci		case TextureFormat::SSCALED_INT_1010102_REV:
1760e5c31af7Sopenharmony_ci		{
1761e5c31af7Sopenharmony_ci			const IVec4 swizzled = swizzleGe(color, TextureFormat::RGBA, m_format.order);
1762e5c31af7Sopenharmony_ci			*((deUint32*)pixelPtr) = PI(swizzled[0],  0, 10) | PI(swizzled[1], 10, 10) | PI(swizzled[2], 20, 10) | PI(swizzled[3], 30, 2);
1763e5c31af7Sopenharmony_ci			break;
1764e5c31af7Sopenharmony_ci		}
1765e5c31af7Sopenharmony_ci
1766e5c31af7Sopenharmony_ci		default:
1767e5c31af7Sopenharmony_ci		{
1768e5c31af7Sopenharmony_ci			// Generic path.
1769e5c31af7Sopenharmony_ci			int								numChannels	= getNumUsedChannels(m_format.order);
1770e5c31af7Sopenharmony_ci			const TextureSwizzle::Channel*	map			= getChannelWriteSwizzle(m_format.order).components;
1771e5c31af7Sopenharmony_ci			int								channelSize	= getChannelSize(m_format.type);
1772e5c31af7Sopenharmony_ci
1773e5c31af7Sopenharmony_ci			for (int c = 0; c < numChannels; c++)
1774e5c31af7Sopenharmony_ci			{
1775e5c31af7Sopenharmony_ci				DE_ASSERT(deInRange32(map[c], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3));
1776e5c31af7Sopenharmony_ci				intToChannel(pixelPtr + channelSize*c, color[map[c]], m_format.type);
1777e5c31af7Sopenharmony_ci			}
1778e5c31af7Sopenharmony_ci			break;
1779e5c31af7Sopenharmony_ci		}
1780e5c31af7Sopenharmony_ci	}
1781e5c31af7Sopenharmony_ci
1782e5c31af7Sopenharmony_ci#undef PU
1783e5c31af7Sopenharmony_ci#undef PI
1784e5c31af7Sopenharmony_ci}
1785e5c31af7Sopenharmony_ci
1786e5c31af7Sopenharmony_civoid PixelBufferAccess::setPixDepth (float depth, int x, int y, int z) const
1787e5c31af7Sopenharmony_ci{
1788e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(x, 0, getWidth()));
1789e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(y, 0, getHeight()));
1790e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(z, 0, getDepth()));
1791e5c31af7Sopenharmony_ci
1792e5c31af7Sopenharmony_ci	deUint8* const pixelPtr = (deUint8*)getPixelPtr(x, y, z);
1793e5c31af7Sopenharmony_ci
1794e5c31af7Sopenharmony_ci	switch (m_format.type)
1795e5c31af7Sopenharmony_ci	{
1796e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_16_8_8:
1797e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::DS);
1798e5c31af7Sopenharmony_ci			writeUint32High16(pixelPtr, convertSatRte<deUint16>(depth * 65535.0f));
1799e5c31af7Sopenharmony_ci			break;
1800e5c31af7Sopenharmony_ci
1801e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8:
1802e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::D || m_format.order == TextureFormat::DS);
1803e5c31af7Sopenharmony_ci			writeUint32High24(pixelPtr,  convertSatRteUint24(depth * 16777215.0f));
1804e5c31af7Sopenharmony_ci			break;
1805e5c31af7Sopenharmony_ci
1806e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8_REV:
1807e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::D || m_format.order == TextureFormat::DS);
1808e5c31af7Sopenharmony_ci			writeUint32Low24(pixelPtr,  convertSatRteUint24(depth * 16777215.0f));
1809e5c31af7Sopenharmony_ci			break;
1810e5c31af7Sopenharmony_ci
1811e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
1812e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::DS);
1813e5c31af7Sopenharmony_ci			*((float*)pixelPtr) = depth;
1814e5c31af7Sopenharmony_ci			break;
1815e5c31af7Sopenharmony_ci
1816e5c31af7Sopenharmony_ci		default:
1817e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::D); // no other combined depth stencil types
1818e5c31af7Sopenharmony_ci			floatToChannel(pixelPtr, depth, m_format.type);
1819e5c31af7Sopenharmony_ci			break;
1820e5c31af7Sopenharmony_ci	}
1821e5c31af7Sopenharmony_ci}
1822e5c31af7Sopenharmony_ci
1823e5c31af7Sopenharmony_civoid PixelBufferAccess::setPixStencil (int stencil, int x, int y, int z) const
1824e5c31af7Sopenharmony_ci{
1825e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(x, 0, getWidth()));
1826e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(y, 0, getHeight()));
1827e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(z, 0, getDepth()));
1828e5c31af7Sopenharmony_ci
1829e5c31af7Sopenharmony_ci	deUint8* const pixelPtr = (deUint8*)getPixelPtr(x, y, z);
1830e5c31af7Sopenharmony_ci
1831e5c31af7Sopenharmony_ci	switch (m_format.type)
1832e5c31af7Sopenharmony_ci	{
1833e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_16_8_8:
1834e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8:
1835e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::DS);
1836e5c31af7Sopenharmony_ci			writeUint32Low8(pixelPtr, convertSat<deUint8>((deUint32)stencil));
1837e5c31af7Sopenharmony_ci			break;
1838e5c31af7Sopenharmony_ci
1839e5c31af7Sopenharmony_ci		case TextureFormat::UNSIGNED_INT_24_8_REV:
1840e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::DS);
1841e5c31af7Sopenharmony_ci			writeUint32High8(pixelPtr, convertSat<deUint8>((deUint32)stencil));
1842e5c31af7Sopenharmony_ci			break;
1843e5c31af7Sopenharmony_ci
1844e5c31af7Sopenharmony_ci		case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV:
1845e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::DS);
1846e5c31af7Sopenharmony_ci			writeUint32Low8(pixelPtr + 4, convertSat<deUint8>((deUint32)stencil));
1847e5c31af7Sopenharmony_ci			break;
1848e5c31af7Sopenharmony_ci
1849e5c31af7Sopenharmony_ci		default:
1850e5c31af7Sopenharmony_ci			DE_ASSERT(m_format.order == TextureFormat::S);  // no other combined depth stencil types
1851e5c31af7Sopenharmony_ci			intToChannel(pixelPtr, stencil, m_format.type);
1852e5c31af7Sopenharmony_ci			break;
1853e5c31af7Sopenharmony_ci	}
1854e5c31af7Sopenharmony_ci}
1855e5c31af7Sopenharmony_ci
1856e5c31af7Sopenharmony_cistatic inline int imod (int a, int b)
1857e5c31af7Sopenharmony_ci{
1858e5c31af7Sopenharmony_ci	int m = a % b;
1859e5c31af7Sopenharmony_ci	return m < 0 ? m + b : m;
1860e5c31af7Sopenharmony_ci}
1861e5c31af7Sopenharmony_ci
1862e5c31af7Sopenharmony_cistatic inline int mirror (int a)
1863e5c31af7Sopenharmony_ci{
1864e5c31af7Sopenharmony_ci	return a >= 0 ? a : -(1 + a);
1865e5c31af7Sopenharmony_ci}
1866e5c31af7Sopenharmony_ci
1867e5c31af7Sopenharmony_ci// Nearest-even rounding in case of tie (fractional part 0.5), otherwise ordinary rounding.
1868e5c31af7Sopenharmony_cistatic inline float rint (float a)
1869e5c31af7Sopenharmony_ci{
1870e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT((-3 % 2 != 0) && (-4 % 2 == 0));
1871e5c31af7Sopenharmony_ci
1872e5c31af7Sopenharmony_ci	float		fracVal		= deFloatFrac(a);
1873e5c31af7Sopenharmony_ci
1874e5c31af7Sopenharmony_ci	if (fracVal != 0.5f)
1875e5c31af7Sopenharmony_ci		return deFloatRound(a); // Ordinary case.
1876e5c31af7Sopenharmony_ci
1877e5c31af7Sopenharmony_ci	float	floorVal	= a - fracVal;
1878e5c31af7Sopenharmony_ci	bool	roundUp		= (deInt64)floorVal % 2 != 0;
1879e5c31af7Sopenharmony_ci
1880e5c31af7Sopenharmony_ci	return floorVal + (roundUp ? 1.0f : 0.0f);
1881e5c31af7Sopenharmony_ci}
1882e5c31af7Sopenharmony_ci
1883e5c31af7Sopenharmony_cistatic inline int wrap (Sampler::WrapMode mode, int c, int size)
1884e5c31af7Sopenharmony_ci{
1885e5c31af7Sopenharmony_ci	switch (mode)
1886e5c31af7Sopenharmony_ci	{
1887e5c31af7Sopenharmony_ci		case tcu::Sampler::CLAMP_TO_BORDER:
1888e5c31af7Sopenharmony_ci			return deClamp32(c, -1, size);
1889e5c31af7Sopenharmony_ci
1890e5c31af7Sopenharmony_ci		case tcu::Sampler::CLAMP_TO_EDGE:
1891e5c31af7Sopenharmony_ci			return deClamp32(c, 0, size-1);
1892e5c31af7Sopenharmony_ci
1893e5c31af7Sopenharmony_ci		case tcu::Sampler::REPEAT_GL:
1894e5c31af7Sopenharmony_ci			return imod(c, size);
1895e5c31af7Sopenharmony_ci
1896e5c31af7Sopenharmony_ci		case tcu::Sampler::REPEAT_CL:
1897e5c31af7Sopenharmony_ci			return imod(c, size);
1898e5c31af7Sopenharmony_ci
1899e5c31af7Sopenharmony_ci		case tcu::Sampler::MIRRORED_ONCE:
1900e5c31af7Sopenharmony_ci			c = deClamp32(c, -size, size);
1901e5c31af7Sopenharmony_ci			// Fall-through
1902e5c31af7Sopenharmony_ci
1903e5c31af7Sopenharmony_ci		case tcu::Sampler::MIRRORED_REPEAT_GL:
1904e5c31af7Sopenharmony_ci			return (size - 1) - mirror(imod(c, 2*size) - size);
1905e5c31af7Sopenharmony_ci
1906e5c31af7Sopenharmony_ci		case tcu::Sampler::MIRRORED_REPEAT_CL:
1907e5c31af7Sopenharmony_ci			return deClamp32(c, 0, size-1); // \note Actual mirroring done already in unnormalization function.
1908e5c31af7Sopenharmony_ci
1909e5c31af7Sopenharmony_ci		default:
1910e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
1911e5c31af7Sopenharmony_ci			return 0;
1912e5c31af7Sopenharmony_ci	}
1913e5c31af7Sopenharmony_ci}
1914e5c31af7Sopenharmony_ci
1915e5c31af7Sopenharmony_ci// Special unnormalization for REPEAT_CL and MIRRORED_REPEAT_CL wrap modes; otherwise ordinary unnormalization.
1916e5c31af7Sopenharmony_cistatic inline float unnormalize (Sampler::WrapMode mode, float c, int size)
1917e5c31af7Sopenharmony_ci{
1918e5c31af7Sopenharmony_ci	switch (mode)
1919e5c31af7Sopenharmony_ci	{
1920e5c31af7Sopenharmony_ci		case tcu::Sampler::CLAMP_TO_EDGE:
1921e5c31af7Sopenharmony_ci		case tcu::Sampler::CLAMP_TO_BORDER:
1922e5c31af7Sopenharmony_ci		case tcu::Sampler::REPEAT_GL:
1923e5c31af7Sopenharmony_ci		case tcu::Sampler::MIRRORED_REPEAT_GL:
1924e5c31af7Sopenharmony_ci		case tcu::Sampler::MIRRORED_ONCE:		// Fall-through (ordinary case).
1925e5c31af7Sopenharmony_ci			return (float)size*c;
1926e5c31af7Sopenharmony_ci
1927e5c31af7Sopenharmony_ci		case tcu::Sampler::REPEAT_CL:
1928e5c31af7Sopenharmony_ci			return (float)size * (c - deFloatFloor(c));
1929e5c31af7Sopenharmony_ci
1930e5c31af7Sopenharmony_ci		case tcu::Sampler::MIRRORED_REPEAT_CL:
1931e5c31af7Sopenharmony_ci			return (float)size * deFloatAbs(c - 2.0f * rint(0.5f * c));
1932e5c31af7Sopenharmony_ci
1933e5c31af7Sopenharmony_ci		default:
1934e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
1935e5c31af7Sopenharmony_ci			return 0.0f;
1936e5c31af7Sopenharmony_ci	}
1937e5c31af7Sopenharmony_ci}
1938e5c31af7Sopenharmony_ci
1939e5c31af7Sopenharmony_cistatic bool isFixedPointDepthTextureFormat (const tcu::TextureFormat& format)
1940e5c31af7Sopenharmony_ci{
1941e5c31af7Sopenharmony_ci	DE_ASSERT(format.order == TextureFormat::D || format.order == TextureFormat::R);
1942e5c31af7Sopenharmony_ci
1943e5c31af7Sopenharmony_ci	const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(format.type);
1944e5c31af7Sopenharmony_ci	if (channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT)
1945e5c31af7Sopenharmony_ci		return false;
1946e5c31af7Sopenharmony_ci	else if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT)
1947e5c31af7Sopenharmony_ci		return true;
1948e5c31af7Sopenharmony_ci	else
1949e5c31af7Sopenharmony_ci	{
1950e5c31af7Sopenharmony_ci		DE_ASSERT(false);
1951e5c31af7Sopenharmony_ci		return false;
1952e5c31af7Sopenharmony_ci	}
1953e5c31af7Sopenharmony_ci}
1954e5c31af7Sopenharmony_ci
1955e5c31af7Sopenharmony_ci// Texel lookup with color conversion.
1956e5c31af7Sopenharmony_cistatic inline Vec4 lookup (const ConstPixelBufferAccess& access, int i, int j, int k)
1957e5c31af7Sopenharmony_ci{
1958e5c31af7Sopenharmony_ci	const TextureFormat&	format	= access.getFormat();
1959e5c31af7Sopenharmony_ci
1960e5c31af7Sopenharmony_ci	if (isSRGB(format))
1961e5c31af7Sopenharmony_ci	{
1962e5c31af7Sopenharmony_ci		if (format.type == TextureFormat::UNORM_INT8 && format.order == TextureFormat::sRGB)
1963e5c31af7Sopenharmony_ci				return sRGB8ToLinear(access.getPixelUint(i, j, k));
1964e5c31af7Sopenharmony_ci		else if (format.type == TextureFormat::UNORM_INT8 && format.order == TextureFormat::sRGBA)
1965e5c31af7Sopenharmony_ci				return sRGBA8ToLinear(access.getPixelUint(i, j, k));
1966e5c31af7Sopenharmony_ci		else
1967e5c31af7Sopenharmony_ci			return sRGBToLinear(access.getPixel(i, j, k));
1968e5c31af7Sopenharmony_ci	}
1969e5c31af7Sopenharmony_ci	else
1970e5c31af7Sopenharmony_ci	{
1971e5c31af7Sopenharmony_ci		return access.getPixel(i, j, k);
1972e5c31af7Sopenharmony_ci	}
1973e5c31af7Sopenharmony_ci}
1974e5c31af7Sopenharmony_ci
1975e5c31af7Sopenharmony_ci// Border texel lookup with color conversion.
1976e5c31af7Sopenharmony_cistatic inline Vec4 lookupBorder (const tcu::TextureFormat& format, const tcu::Sampler& sampler)
1977e5c31af7Sopenharmony_ci{
1978e5c31af7Sopenharmony_ci	// "lookup" for a combined format does not make sense, disallow
1979e5c31af7Sopenharmony_ci	DE_ASSERT(!isCombinedDepthStencilType(format.type));
1980e5c31af7Sopenharmony_ci
1981e5c31af7Sopenharmony_ci	const tcu::TextureChannelClass	channelClass			= tcu::getTextureChannelClass(format.type);
1982e5c31af7Sopenharmony_ci	const bool						isFloat					= channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT;
1983e5c31af7Sopenharmony_ci	const bool						isFixed					= channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT ||
1984e5c31af7Sopenharmony_ci															  channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT;
1985e5c31af7Sopenharmony_ci	const bool						isPureInteger			= channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER;
1986e5c31af7Sopenharmony_ci	const bool						isPureUnsignedInteger	= channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER;
1987e5c31af7Sopenharmony_ci
1988e5c31af7Sopenharmony_ci	if (isFloat || isFixed)
1989e5c31af7Sopenharmony_ci		return sampleTextureBorder<float>(format, sampler);
1990e5c31af7Sopenharmony_ci	else if (isPureInteger)
1991e5c31af7Sopenharmony_ci		return sampleTextureBorder<deInt32>(format, sampler).cast<float>();
1992e5c31af7Sopenharmony_ci	else if (isPureUnsignedInteger)
1993e5c31af7Sopenharmony_ci		return sampleTextureBorder<deUint32>(format, sampler).cast<float>();
1994e5c31af7Sopenharmony_ci	else
1995e5c31af7Sopenharmony_ci	{
1996e5c31af7Sopenharmony_ci		DE_ASSERT(false);
1997e5c31af7Sopenharmony_ci		return Vec4(-1.0);
1998e5c31af7Sopenharmony_ci	}
1999e5c31af7Sopenharmony_ci}
2000e5c31af7Sopenharmony_ci
2001e5c31af7Sopenharmony_cistatic inline float execCompare (const tcu::Vec4& color, Sampler::CompareMode compare, int chanNdx, float ref_, bool isFixedPoint)
2002e5c31af7Sopenharmony_ci{
2003e5c31af7Sopenharmony_ci	const bool	clampValues	= isFixedPoint;	// if comparing against a floating point texture, ref (and value) is not clamped
2004e5c31af7Sopenharmony_ci	const float	cmp			= (clampValues) ? (de::clamp(color[chanNdx], 0.0f, 1.0f)) : (color[chanNdx]);
2005e5c31af7Sopenharmony_ci	const float	ref			= (clampValues) ? (de::clamp(ref_, 0.0f, 1.0f)) : (ref_);
2006e5c31af7Sopenharmony_ci	bool		res			= false;
2007e5c31af7Sopenharmony_ci
2008e5c31af7Sopenharmony_ci	switch (compare)
2009e5c31af7Sopenharmony_ci	{
2010e5c31af7Sopenharmony_ci		case Sampler::COMPAREMODE_LESS:				res = ref < cmp;	break;
2011e5c31af7Sopenharmony_ci		case Sampler::COMPAREMODE_LESS_OR_EQUAL:	res = ref <= cmp;	break;
2012e5c31af7Sopenharmony_ci		case Sampler::COMPAREMODE_GREATER:			res = ref > cmp;	break;
2013e5c31af7Sopenharmony_ci		case Sampler::COMPAREMODE_GREATER_OR_EQUAL:	res = ref >= cmp;	break;
2014e5c31af7Sopenharmony_ci		case Sampler::COMPAREMODE_EQUAL:			res = ref == cmp;	break;
2015e5c31af7Sopenharmony_ci		case Sampler::COMPAREMODE_NOT_EQUAL:		res = ref != cmp;	break;
2016e5c31af7Sopenharmony_ci		case Sampler::COMPAREMODE_ALWAYS:			res = true;			break;
2017e5c31af7Sopenharmony_ci		case Sampler::COMPAREMODE_NEVER:			res = false;		break;
2018e5c31af7Sopenharmony_ci		default:
2019e5c31af7Sopenharmony_ci			DE_ASSERT(false);
2020e5c31af7Sopenharmony_ci	}
2021e5c31af7Sopenharmony_ci
2022e5c31af7Sopenharmony_ci	return res ? 1.0f : 0.0f;
2023e5c31af7Sopenharmony_ci}
2024e5c31af7Sopenharmony_ci
2025e5c31af7Sopenharmony_cistatic Vec4 sampleNearest1D (const ConstPixelBufferAccess& access, const Sampler& sampler, float u, const IVec2& offset)
2026e5c31af7Sopenharmony_ci{
2027e5c31af7Sopenharmony_ci	int width	= access.getWidth();
2028e5c31af7Sopenharmony_ci
2029e5c31af7Sopenharmony_ci	int x = deFloorFloatToInt32(u)+offset.x();
2030e5c31af7Sopenharmony_ci
2031e5c31af7Sopenharmony_ci	// Check for CLAMP_TO_BORDER.
2032e5c31af7Sopenharmony_ci	if (sampler.wrapS == Sampler::CLAMP_TO_BORDER && !deInBounds32(x, 0, width))
2033e5c31af7Sopenharmony_ci		return lookupBorder(access.getFormat(), sampler);
2034e5c31af7Sopenharmony_ci
2035e5c31af7Sopenharmony_ci	int i = wrap(sampler.wrapS, x, width);
2036e5c31af7Sopenharmony_ci
2037e5c31af7Sopenharmony_ci	return lookup(access, i, offset.y(), 0);
2038e5c31af7Sopenharmony_ci}
2039e5c31af7Sopenharmony_ci
2040e5c31af7Sopenharmony_cistatic Vec4 sampleNearest2D (const ConstPixelBufferAccess& access, const Sampler& sampler, float u, float v, const IVec3& offset)
2041e5c31af7Sopenharmony_ci{
2042e5c31af7Sopenharmony_ci	int width	= access.getWidth();
2043e5c31af7Sopenharmony_ci	int height	= access.getHeight();
2044e5c31af7Sopenharmony_ci
2045e5c31af7Sopenharmony_ci	int x = deFloorFloatToInt32(u)+offset.x();
2046e5c31af7Sopenharmony_ci	int y = deFloorFloatToInt32(v)+offset.y();
2047e5c31af7Sopenharmony_ci
2048e5c31af7Sopenharmony_ci	// Check for CLAMP_TO_BORDER.
2049e5c31af7Sopenharmony_ci	if ((sampler.wrapS == Sampler::CLAMP_TO_BORDER && !deInBounds32(x, 0, width)) ||
2050e5c31af7Sopenharmony_ci		(sampler.wrapT == Sampler::CLAMP_TO_BORDER && !deInBounds32(y, 0, height)))
2051e5c31af7Sopenharmony_ci		return lookupBorder(access.getFormat(), sampler);
2052e5c31af7Sopenharmony_ci
2053e5c31af7Sopenharmony_ci	int i = wrap(sampler.wrapS, x, width);
2054e5c31af7Sopenharmony_ci	int j = wrap(sampler.wrapT, y, height);
2055e5c31af7Sopenharmony_ci
2056e5c31af7Sopenharmony_ci	return lookup(access, i, j, offset.z());
2057e5c31af7Sopenharmony_ci}
2058e5c31af7Sopenharmony_ci
2059e5c31af7Sopenharmony_cistatic Vec4 sampleNearest3D (const ConstPixelBufferAccess& access, const Sampler& sampler, float u, float v, float w, const IVec3& offset)
2060e5c31af7Sopenharmony_ci{
2061e5c31af7Sopenharmony_ci	int width	= access.getWidth();
2062e5c31af7Sopenharmony_ci	int height	= access.getHeight();
2063e5c31af7Sopenharmony_ci	int depth	= access.getDepth();
2064e5c31af7Sopenharmony_ci
2065e5c31af7Sopenharmony_ci	int x = deFloorFloatToInt32(u)+offset.x();
2066e5c31af7Sopenharmony_ci	int y = deFloorFloatToInt32(v)+offset.y();
2067e5c31af7Sopenharmony_ci	int z = deFloorFloatToInt32(w)+offset.z();
2068e5c31af7Sopenharmony_ci
2069e5c31af7Sopenharmony_ci	// Check for CLAMP_TO_BORDER.
2070e5c31af7Sopenharmony_ci	if ((sampler.wrapS == Sampler::CLAMP_TO_BORDER && !deInBounds32(x, 0, width))	||
2071e5c31af7Sopenharmony_ci		(sampler.wrapT == Sampler::CLAMP_TO_BORDER && !deInBounds32(y, 0, height))	||
2072e5c31af7Sopenharmony_ci		(sampler.wrapR == Sampler::CLAMP_TO_BORDER && !deInBounds32(z, 0, depth)))
2073e5c31af7Sopenharmony_ci		return lookupBorder(access.getFormat(), sampler);
2074e5c31af7Sopenharmony_ci
2075e5c31af7Sopenharmony_ci	int i = wrap(sampler.wrapS, x, width);
2076e5c31af7Sopenharmony_ci	int j = wrap(sampler.wrapT, y, height);
2077e5c31af7Sopenharmony_ci	int k = wrap(sampler.wrapR, z, depth);
2078e5c31af7Sopenharmony_ci
2079e5c31af7Sopenharmony_ci	return lookup(access, i, j, k);
2080e5c31af7Sopenharmony_ci}
2081e5c31af7Sopenharmony_ci
2082e5c31af7Sopenharmony_cistatic Vec4 sampleLinear1D (const ConstPixelBufferAccess& access, const Sampler& sampler, float u, const IVec2& offset)
2083e5c31af7Sopenharmony_ci{
2084e5c31af7Sopenharmony_ci	int w = access.getWidth();
2085e5c31af7Sopenharmony_ci
2086e5c31af7Sopenharmony_ci	int x0 = deFloorFloatToInt32(u-0.5f)+offset.x();
2087e5c31af7Sopenharmony_ci	int x1 = x0+1;
2088e5c31af7Sopenharmony_ci
2089e5c31af7Sopenharmony_ci	int i0 = wrap(sampler.wrapS, x0, w);
2090e5c31af7Sopenharmony_ci	int i1 = wrap(sampler.wrapS, x1, w);
2091e5c31af7Sopenharmony_ci
2092e5c31af7Sopenharmony_ci	float a = deFloatFrac(u-0.5f);
2093e5c31af7Sopenharmony_ci
2094e5c31af7Sopenharmony_ci	bool i0UseBorder = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i0, 0, w);
2095e5c31af7Sopenharmony_ci	bool i1UseBorder = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i1, 0, w);
2096e5c31af7Sopenharmony_ci
2097e5c31af7Sopenharmony_ci	// Border color for out-of-range coordinates if using CLAMP_TO_BORDER, otherwise execute lookups.
2098e5c31af7Sopenharmony_ci	Vec4 p0 = i0UseBorder ? lookupBorder(access.getFormat(), sampler) : lookup(access, i0, offset.y(), 0);
2099e5c31af7Sopenharmony_ci	Vec4 p1 = i1UseBorder ? lookupBorder(access.getFormat(), sampler) : lookup(access, i1, offset.y(), 0);
2100e5c31af7Sopenharmony_ci
2101e5c31af7Sopenharmony_ci	// Interpolate.
2102e5c31af7Sopenharmony_ci	return p0 * (1.0f - a) + p1 * a;
2103e5c31af7Sopenharmony_ci}
2104e5c31af7Sopenharmony_ci
2105e5c31af7Sopenharmony_cistatic Vec4 sampleCubic1D(const ConstPixelBufferAccess& access, const Sampler& sampler, float u, const IVec2& offset)
2106e5c31af7Sopenharmony_ci{
2107e5c31af7Sopenharmony_ci	int width = access.getWidth();
2108e5c31af7Sopenharmony_ci
2109e5c31af7Sopenharmony_ci	tcu::IVec4 x, i;
2110e5c31af7Sopenharmony_ci
2111e5c31af7Sopenharmony_ci	x[0] = deFloorFloatToInt32(u - 1.5f) + offset.x();
2112e5c31af7Sopenharmony_ci	x[1] = x[0] + 1;
2113e5c31af7Sopenharmony_ci	x[2] = x[1] + 1;
2114e5c31af7Sopenharmony_ci	x[3] = x[2] + 1;
2115e5c31af7Sopenharmony_ci
2116e5c31af7Sopenharmony_ci	for (deUint32 m = 0; m < 4; ++m)
2117e5c31af7Sopenharmony_ci		i[m] = wrap(sampler.wrapS, x[m], width);
2118e5c31af7Sopenharmony_ci
2119e5c31af7Sopenharmony_ci	bool iUseBorder[4];
2120e5c31af7Sopenharmony_ci	for (deUint32 m = 0; m < 4; ++m)
2121e5c31af7Sopenharmony_ci		iUseBorder[m] = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i[m], 0, width);
2122e5c31af7Sopenharmony_ci
2123e5c31af7Sopenharmony_ci	// Catmull-Rom basis matrix
2124e5c31af7Sopenharmony_ci	static const float crValues[16] = { 0.0f,	1.0f,	0.0f,	0.0f,
2125e5c31af7Sopenharmony_ci										-0.5f,	0.0f,	0.5f,	0.0f,
2126e5c31af7Sopenharmony_ci										1.0f,	-2.5f,	2.0f,	-0.5f,
2127e5c31af7Sopenharmony_ci										-0.5f,	1.5f,	-1.5f,	0.5f };
2128e5c31af7Sopenharmony_ci	static const tcu::Mat4 crBasis(crValues);
2129e5c31af7Sopenharmony_ci
2130e5c31af7Sopenharmony_ci	float		a = deFloatFrac(u - 0.5f);
2131e5c31af7Sopenharmony_ci	tcu::Vec4	alpha(1, a, a*a, a*a*a);
2132e5c31af7Sopenharmony_ci	tcu::Vec4	wi = alpha * crBasis;
2133e5c31af7Sopenharmony_ci
2134e5c31af7Sopenharmony_ci	tcu::Vec4 result(0.0f, 0.0f, 0.0f, 0.0f);
2135e5c31af7Sopenharmony_ci	for (deUint32 m = 0; m < 4; ++m)
2136e5c31af7Sopenharmony_ci	{
2137e5c31af7Sopenharmony_ci		tcu::Vec4 p = (iUseBorder[m]) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i[m], offset.y(), 0);
2138e5c31af7Sopenharmony_ci		result += wi[m] * p;
2139e5c31af7Sopenharmony_ci	}
2140e5c31af7Sopenharmony_ci	return result;
2141e5c31af7Sopenharmony_ci}
2142e5c31af7Sopenharmony_ci
2143e5c31af7Sopenharmony_cistatic Vec4 sampleLinear2D (const ConstPixelBufferAccess& access, const Sampler& sampler, float u, float v, const IVec3& offset)
2144e5c31af7Sopenharmony_ci{
2145e5c31af7Sopenharmony_ci	int w = access.getWidth();
2146e5c31af7Sopenharmony_ci	int h = access.getHeight();
2147e5c31af7Sopenharmony_ci
2148e5c31af7Sopenharmony_ci	int x0 = deFloorFloatToInt32(u-0.5f)+offset.x();
2149e5c31af7Sopenharmony_ci	int x1 = x0+1;
2150e5c31af7Sopenharmony_ci	int y0 = deFloorFloatToInt32(v-0.5f)+offset.y();
2151e5c31af7Sopenharmony_ci	int y1 = y0+1;
2152e5c31af7Sopenharmony_ci
2153e5c31af7Sopenharmony_ci	int i0 = wrap(sampler.wrapS, x0, w);
2154e5c31af7Sopenharmony_ci	int i1 = wrap(sampler.wrapS, x1, w);
2155e5c31af7Sopenharmony_ci	int j0 = wrap(sampler.wrapT, y0, h);
2156e5c31af7Sopenharmony_ci	int j1 = wrap(sampler.wrapT, y1, h);
2157e5c31af7Sopenharmony_ci
2158e5c31af7Sopenharmony_ci	float a = deFloatFrac(u-0.5f);
2159e5c31af7Sopenharmony_ci	float b = deFloatFrac(v-0.5f);
2160e5c31af7Sopenharmony_ci
2161e5c31af7Sopenharmony_ci	bool i0UseBorder = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i0, 0, w);
2162e5c31af7Sopenharmony_ci	bool i1UseBorder = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i1, 0, w);
2163e5c31af7Sopenharmony_ci	bool j0UseBorder = sampler.wrapT == Sampler::CLAMP_TO_BORDER && !de::inBounds(j0, 0, h);
2164e5c31af7Sopenharmony_ci	bool j1UseBorder = sampler.wrapT == Sampler::CLAMP_TO_BORDER && !de::inBounds(j1, 0, h);
2165e5c31af7Sopenharmony_ci
2166e5c31af7Sopenharmony_ci	// Border color for out-of-range coordinates if using CLAMP_TO_BORDER, otherwise execute lookups.
2167e5c31af7Sopenharmony_ci	Vec4 p00 = (i0UseBorder || j0UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i0, j0, offset.z());
2168e5c31af7Sopenharmony_ci	Vec4 p10 = (i1UseBorder || j0UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i1, j0, offset.z());
2169e5c31af7Sopenharmony_ci	Vec4 p01 = (i0UseBorder || j1UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i0, j1, offset.z());
2170e5c31af7Sopenharmony_ci	Vec4 p11 = (i1UseBorder || j1UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i1, j1, offset.z());
2171e5c31af7Sopenharmony_ci
2172e5c31af7Sopenharmony_ci	// Interpolate.
2173e5c31af7Sopenharmony_ci	return (p00*(1.0f-a)*(1.0f-b)) +
2174e5c31af7Sopenharmony_ci		   (p10*(     a)*(1.0f-b)) +
2175e5c31af7Sopenharmony_ci		   (p01*(1.0f-a)*(     b)) +
2176e5c31af7Sopenharmony_ci		   (p11*(     a)*(     b));
2177e5c31af7Sopenharmony_ci}
2178e5c31af7Sopenharmony_ci
2179e5c31af7Sopenharmony_cistatic Vec4 sampleCubic2D(const ConstPixelBufferAccess& access, const Sampler& sampler, float u, float v, const IVec3& offset)
2180e5c31af7Sopenharmony_ci{
2181e5c31af7Sopenharmony_ci	int width	= access.getWidth();
2182e5c31af7Sopenharmony_ci	int height	= access.getHeight();
2183e5c31af7Sopenharmony_ci
2184e5c31af7Sopenharmony_ci	tcu::IVec4 x, y, i, j;
2185e5c31af7Sopenharmony_ci
2186e5c31af7Sopenharmony_ci	x[0] = deFloorFloatToInt32(u - 1.5f) + offset.x();
2187e5c31af7Sopenharmony_ci	x[1] = x[0] + 1;
2188e5c31af7Sopenharmony_ci	x[2] = x[1] + 1;
2189e5c31af7Sopenharmony_ci	x[3] = x[2] + 1;
2190e5c31af7Sopenharmony_ci	y[0] = deFloorFloatToInt32(v - 1.5f) + offset.y();
2191e5c31af7Sopenharmony_ci	y[1] = y[0] + 1;
2192e5c31af7Sopenharmony_ci	y[2] = y[1] + 1;
2193e5c31af7Sopenharmony_ci	y[3] = y[2] + 1;
2194e5c31af7Sopenharmony_ci
2195e5c31af7Sopenharmony_ci	for (deUint32 m = 0; m < 4; ++m)
2196e5c31af7Sopenharmony_ci		i[m] = wrap(sampler.wrapS, x[m], width);
2197e5c31af7Sopenharmony_ci	for (deUint32 n = 0; n < 4; ++n)
2198e5c31af7Sopenharmony_ci		j[n] = wrap(sampler.wrapT, y[n], height);
2199e5c31af7Sopenharmony_ci
2200e5c31af7Sopenharmony_ci	bool iUseBorder[4], jUseBorder[4];
2201e5c31af7Sopenharmony_ci	for (deUint32 m = 0; m < 4; ++m)
2202e5c31af7Sopenharmony_ci		iUseBorder[m] = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i[m], 0, width);
2203e5c31af7Sopenharmony_ci	for (deUint32 n = 0; n < 4; ++n)
2204e5c31af7Sopenharmony_ci		jUseBorder[n] = sampler.wrapT == Sampler::CLAMP_TO_BORDER && !de::inBounds(j[n], 0, height);
2205e5c31af7Sopenharmony_ci
2206e5c31af7Sopenharmony_ci	// Catmull-Rom basis matrix
2207e5c31af7Sopenharmony_ci	static const float crValues[16] = {	0.0f,	1.0f,	0.0f,	0.0f,
2208e5c31af7Sopenharmony_ci										-0.5f,	0.0f,	0.5f,	0.0f,
2209e5c31af7Sopenharmony_ci										1.0f,	-2.5f,	2.0f,	-0.5f,
2210e5c31af7Sopenharmony_ci										-0.5f,	1.5f,	-1.5f,	0.5f };
2211e5c31af7Sopenharmony_ci	static const tcu::Mat4 crBasis(crValues);
2212e5c31af7Sopenharmony_ci
2213e5c31af7Sopenharmony_ci	float		a		= deFloatFrac(u - 0.5f);
2214e5c31af7Sopenharmony_ci	float		b		= deFloatFrac(v - 0.5f);
2215e5c31af7Sopenharmony_ci	tcu::Vec4	alpha	(1, a, a*a, a*a*a);
2216e5c31af7Sopenharmony_ci	tcu::Vec4	beta	(1, b, b*b, b*b*b);
2217e5c31af7Sopenharmony_ci	tcu::Vec4	wi		= alpha * crBasis;
2218e5c31af7Sopenharmony_ci	tcu::Vec4	wj		= beta  * crBasis;
2219e5c31af7Sopenharmony_ci
2220e5c31af7Sopenharmony_ci	tcu::Vec4 result(0.0f, 0.0f, 0.0f, 0.0f);
2221e5c31af7Sopenharmony_ci	for (deUint32 n = 0; n < 4; ++n)
2222e5c31af7Sopenharmony_ci		for (deUint32 m = 0; m < 4; ++m)
2223e5c31af7Sopenharmony_ci		{
2224e5c31af7Sopenharmony_ci			tcu::Vec4 p = (iUseBorder[m] || jUseBorder[n]) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i[m], j[n], offset.z());
2225e5c31af7Sopenharmony_ci			result += wi[m] * wj[n] * p;
2226e5c31af7Sopenharmony_ci		}
2227e5c31af7Sopenharmony_ci	return result;
2228e5c31af7Sopenharmony_ci}
2229e5c31af7Sopenharmony_ci
2230e5c31af7Sopenharmony_cistatic float sampleLinear1DCompare (const ConstPixelBufferAccess& access, const Sampler& sampler, float ref, float u, const IVec2& offset, bool isFixedPointDepthFormat)
2231e5c31af7Sopenharmony_ci{
2232e5c31af7Sopenharmony_ci	int w = access.getWidth();
2233e5c31af7Sopenharmony_ci
2234e5c31af7Sopenharmony_ci	int x0 = deFloorFloatToInt32(u-0.5f)+offset.x();
2235e5c31af7Sopenharmony_ci	int x1 = x0+1;
2236e5c31af7Sopenharmony_ci
2237e5c31af7Sopenharmony_ci	int i0 = wrap(sampler.wrapS, x0, w);
2238e5c31af7Sopenharmony_ci	int i1 = wrap(sampler.wrapS, x1, w);
2239e5c31af7Sopenharmony_ci
2240e5c31af7Sopenharmony_ci	float a = deFloatFrac(u-0.5f);
2241e5c31af7Sopenharmony_ci
2242e5c31af7Sopenharmony_ci	bool i0UseBorder = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i0, 0, w);
2243e5c31af7Sopenharmony_ci	bool i1UseBorder = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i1, 0, w);
2244e5c31af7Sopenharmony_ci
2245e5c31af7Sopenharmony_ci	// Border color for out-of-range coordinates if using CLAMP_TO_BORDER, otherwise execute lookups.
2246e5c31af7Sopenharmony_ci	Vec4 p0Clr = i0UseBorder  ? lookupBorder(access.getFormat(), sampler) : lookup(access, i0, offset.y(), 0);
2247e5c31af7Sopenharmony_ci	Vec4 p1Clr = i1UseBorder  ? lookupBorder(access.getFormat(), sampler) : lookup(access, i1, offset.y(), 0);
2248e5c31af7Sopenharmony_ci
2249e5c31af7Sopenharmony_ci	// Execute comparisons.
2250e5c31af7Sopenharmony_ci	float p0 = execCompare(p0Clr, sampler.compare, sampler.compareChannel, ref, isFixedPointDepthFormat);
2251e5c31af7Sopenharmony_ci	float p1 = execCompare(p1Clr, sampler.compare, sampler.compareChannel, ref, isFixedPointDepthFormat);
2252e5c31af7Sopenharmony_ci
2253e5c31af7Sopenharmony_ci	// Interpolate.
2254e5c31af7Sopenharmony_ci	return (p0 * (1.0f - a)) + (p1 * a);
2255e5c31af7Sopenharmony_ci}
2256e5c31af7Sopenharmony_ci
2257e5c31af7Sopenharmony_cistatic float sampleLinear2DCompare (const ConstPixelBufferAccess& access, const Sampler& sampler, float ref, float u, float v, const IVec3& offset, bool isFixedPointDepthFormat)
2258e5c31af7Sopenharmony_ci{
2259e5c31af7Sopenharmony_ci	int w = access.getWidth();
2260e5c31af7Sopenharmony_ci	int h = access.getHeight();
2261e5c31af7Sopenharmony_ci
2262e5c31af7Sopenharmony_ci	int x0 = deFloorFloatToInt32(u-0.5f)+offset.x();
2263e5c31af7Sopenharmony_ci	int x1 = x0+1;
2264e5c31af7Sopenharmony_ci	int y0 = deFloorFloatToInt32(v-0.5f)+offset.y();
2265e5c31af7Sopenharmony_ci	int y1 = y0+1;
2266e5c31af7Sopenharmony_ci
2267e5c31af7Sopenharmony_ci	int i0 = wrap(sampler.wrapS, x0, w);
2268e5c31af7Sopenharmony_ci	int i1 = wrap(sampler.wrapS, x1, w);
2269e5c31af7Sopenharmony_ci	int j0 = wrap(sampler.wrapT, y0, h);
2270e5c31af7Sopenharmony_ci	int j1 = wrap(sampler.wrapT, y1, h);
2271e5c31af7Sopenharmony_ci
2272e5c31af7Sopenharmony_ci	float a = deFloatFrac(u-0.5f);
2273e5c31af7Sopenharmony_ci	float b = deFloatFrac(v-0.5f);
2274e5c31af7Sopenharmony_ci
2275e5c31af7Sopenharmony_ci	bool i0UseBorder = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i0, 0, w);
2276e5c31af7Sopenharmony_ci	bool i1UseBorder = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i1, 0, w);
2277e5c31af7Sopenharmony_ci	bool j0UseBorder = sampler.wrapT == Sampler::CLAMP_TO_BORDER && !de::inBounds(j0, 0, h);
2278e5c31af7Sopenharmony_ci	bool j1UseBorder = sampler.wrapT == Sampler::CLAMP_TO_BORDER && !de::inBounds(j1, 0, h);
2279e5c31af7Sopenharmony_ci
2280e5c31af7Sopenharmony_ci	// Border color for out-of-range coordinates if using CLAMP_TO_BORDER, otherwise execute lookups.
2281e5c31af7Sopenharmony_ci	Vec4 p00Clr = (i0UseBorder || j0UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i0, j0, offset.z());
2282e5c31af7Sopenharmony_ci	Vec4 p10Clr = (i1UseBorder || j0UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i1, j0, offset.z());
2283e5c31af7Sopenharmony_ci	Vec4 p01Clr = (i0UseBorder || j1UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i0, j1, offset.z());
2284e5c31af7Sopenharmony_ci	Vec4 p11Clr = (i1UseBorder || j1UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i1, j1, offset.z());
2285e5c31af7Sopenharmony_ci
2286e5c31af7Sopenharmony_ci	// Execute comparisons.
2287e5c31af7Sopenharmony_ci	float p00 = execCompare(p00Clr, sampler.compare, sampler.compareChannel, ref, isFixedPointDepthFormat);
2288e5c31af7Sopenharmony_ci	float p10 = execCompare(p10Clr, sampler.compare, sampler.compareChannel, ref, isFixedPointDepthFormat);
2289e5c31af7Sopenharmony_ci	float p01 = execCompare(p01Clr, sampler.compare, sampler.compareChannel, ref, isFixedPointDepthFormat);
2290e5c31af7Sopenharmony_ci	float p11 = execCompare(p11Clr, sampler.compare, sampler.compareChannel, ref, isFixedPointDepthFormat);
2291e5c31af7Sopenharmony_ci
2292e5c31af7Sopenharmony_ci	// Interpolate.
2293e5c31af7Sopenharmony_ci	return (p00*(1.0f-a)*(1.0f-b)) +
2294e5c31af7Sopenharmony_ci		   (p10*(     a)*(1.0f-b)) +
2295e5c31af7Sopenharmony_ci		   (p01*(1.0f-a)*(     b)) +
2296e5c31af7Sopenharmony_ci		   (p11*(     a)*(     b));
2297e5c31af7Sopenharmony_ci}
2298e5c31af7Sopenharmony_ci
2299e5c31af7Sopenharmony_cistatic Vec4 sampleLinear3D (const ConstPixelBufferAccess& access, const Sampler& sampler, float u, float v, float w, const IVec3& offset)
2300e5c31af7Sopenharmony_ci{
2301e5c31af7Sopenharmony_ci	int width	= access.getWidth();
2302e5c31af7Sopenharmony_ci	int height	= access.getHeight();
2303e5c31af7Sopenharmony_ci	int depth	= access.getDepth();
2304e5c31af7Sopenharmony_ci
2305e5c31af7Sopenharmony_ci	int x0 = deFloorFloatToInt32(u-0.5f)+offset.x();
2306e5c31af7Sopenharmony_ci	int x1 = x0+1;
2307e5c31af7Sopenharmony_ci	int y0 = deFloorFloatToInt32(v-0.5f)+offset.y();
2308e5c31af7Sopenharmony_ci	int y1 = y0+1;
2309e5c31af7Sopenharmony_ci	int z0 = deFloorFloatToInt32(w-0.5f)+offset.z();
2310e5c31af7Sopenharmony_ci	int z1 = z0+1;
2311e5c31af7Sopenharmony_ci
2312e5c31af7Sopenharmony_ci	int i0 = wrap(sampler.wrapS, x0, width);
2313e5c31af7Sopenharmony_ci	int i1 = wrap(sampler.wrapS, x1, width);
2314e5c31af7Sopenharmony_ci	int j0 = wrap(sampler.wrapT, y0, height);
2315e5c31af7Sopenharmony_ci	int j1 = wrap(sampler.wrapT, y1, height);
2316e5c31af7Sopenharmony_ci	int k0 = wrap(sampler.wrapR, z0, depth);
2317e5c31af7Sopenharmony_ci	int k1 = wrap(sampler.wrapR, z1, depth);
2318e5c31af7Sopenharmony_ci
2319e5c31af7Sopenharmony_ci	float a = deFloatFrac(u-0.5f);
2320e5c31af7Sopenharmony_ci	float b = deFloatFrac(v-0.5f);
2321e5c31af7Sopenharmony_ci	float c = deFloatFrac(w-0.5f);
2322e5c31af7Sopenharmony_ci
2323e5c31af7Sopenharmony_ci	bool i0UseBorder = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i0, 0, width);
2324e5c31af7Sopenharmony_ci	bool i1UseBorder = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i1, 0, width);
2325e5c31af7Sopenharmony_ci	bool j0UseBorder = sampler.wrapT == Sampler::CLAMP_TO_BORDER && !de::inBounds(j0, 0, height);
2326e5c31af7Sopenharmony_ci	bool j1UseBorder = sampler.wrapT == Sampler::CLAMP_TO_BORDER && !de::inBounds(j1, 0, height);
2327e5c31af7Sopenharmony_ci	bool k0UseBorder = sampler.wrapR == Sampler::CLAMP_TO_BORDER && !de::inBounds(k0, 0, depth);
2328e5c31af7Sopenharmony_ci	bool k1UseBorder = sampler.wrapR == Sampler::CLAMP_TO_BORDER && !de::inBounds(k1, 0, depth);
2329e5c31af7Sopenharmony_ci
2330e5c31af7Sopenharmony_ci	// Border color for out-of-range coordinates if using CLAMP_TO_BORDER, otherwise execute lookups.
2331e5c31af7Sopenharmony_ci	Vec4 p000 = (i0UseBorder || j0UseBorder || k0UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i0, j0, k0);
2332e5c31af7Sopenharmony_ci	Vec4 p100 = (i1UseBorder || j0UseBorder || k0UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i1, j0, k0);
2333e5c31af7Sopenharmony_ci	Vec4 p010 = (i0UseBorder || j1UseBorder || k0UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i0, j1, k0);
2334e5c31af7Sopenharmony_ci	Vec4 p110 = (i1UseBorder || j1UseBorder || k0UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i1, j1, k0);
2335e5c31af7Sopenharmony_ci	Vec4 p001 = (i0UseBorder || j0UseBorder || k1UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i0, j0, k1);
2336e5c31af7Sopenharmony_ci	Vec4 p101 = (i1UseBorder || j0UseBorder || k1UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i1, j0, k1);
2337e5c31af7Sopenharmony_ci	Vec4 p011 = (i0UseBorder || j1UseBorder || k1UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i0, j1, k1);
2338e5c31af7Sopenharmony_ci	Vec4 p111 = (i1UseBorder || j1UseBorder || k1UseBorder) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i1, j1, k1);
2339e5c31af7Sopenharmony_ci
2340e5c31af7Sopenharmony_ci	// Interpolate.
2341e5c31af7Sopenharmony_ci	return (p000*(1.0f-a)*(1.0f-b)*(1.0f-c)) +
2342e5c31af7Sopenharmony_ci		   (p100*(     a)*(1.0f-b)*(1.0f-c)) +
2343e5c31af7Sopenharmony_ci		   (p010*(1.0f-a)*(     b)*(1.0f-c)) +
2344e5c31af7Sopenharmony_ci		   (p110*(     a)*(     b)*(1.0f-c)) +
2345e5c31af7Sopenharmony_ci		   (p001*(1.0f-a)*(1.0f-b)*(     c)) +
2346e5c31af7Sopenharmony_ci		   (p101*(     a)*(1.0f-b)*(     c)) +
2347e5c31af7Sopenharmony_ci		   (p011*(1.0f-a)*(     b)*(     c)) +
2348e5c31af7Sopenharmony_ci		   (p111*(     a)*(     b)*(     c));
2349e5c31af7Sopenharmony_ci}
2350e5c31af7Sopenharmony_ci
2351e5c31af7Sopenharmony_cistatic Vec4 sampleCubic3D(const ConstPixelBufferAccess& access, const Sampler& sampler, float u, float v, float w, const IVec3& offset)
2352e5c31af7Sopenharmony_ci{
2353e5c31af7Sopenharmony_ci	int width	= access.getWidth();
2354e5c31af7Sopenharmony_ci	int height	= access.getHeight();
2355e5c31af7Sopenharmony_ci	int depth	= access.getDepth();
2356e5c31af7Sopenharmony_ci
2357e5c31af7Sopenharmony_ci	tcu::IVec4 x, y, z, i, j, k;
2358e5c31af7Sopenharmony_ci
2359e5c31af7Sopenharmony_ci	x[0] = deFloorFloatToInt32(u - 1.5f) + offset.x();
2360e5c31af7Sopenharmony_ci	x[1] = x[0] + 1;
2361e5c31af7Sopenharmony_ci	x[2] = x[1] + 1;
2362e5c31af7Sopenharmony_ci	x[3] = x[2] + 1;
2363e5c31af7Sopenharmony_ci	y[0] = deFloorFloatToInt32(v - 1.5f) + offset.y();
2364e5c31af7Sopenharmony_ci	y[1] = y[0] + 1;
2365e5c31af7Sopenharmony_ci	y[2] = y[1] + 1;
2366e5c31af7Sopenharmony_ci	y[3] = y[2] + 1;
2367e5c31af7Sopenharmony_ci	z[0] = deFloorFloatToInt32(w - 1.5f) + offset.z();
2368e5c31af7Sopenharmony_ci	z[1] = z[0] + 1;
2369e5c31af7Sopenharmony_ci	z[2] = z[1] + 1;
2370e5c31af7Sopenharmony_ci	z[3] = z[2] + 1;
2371e5c31af7Sopenharmony_ci
2372e5c31af7Sopenharmony_ci	for (deUint32 m = 0; m < 4; ++m)
2373e5c31af7Sopenharmony_ci		i[m] = wrap(sampler.wrapS, x[m], width);
2374e5c31af7Sopenharmony_ci	for (deUint32 n = 0; n < 4; ++n)
2375e5c31af7Sopenharmony_ci		j[n] = wrap(sampler.wrapT, y[n], height);
2376e5c31af7Sopenharmony_ci	for (deUint32 o = 0; o < 4; ++o)
2377e5c31af7Sopenharmony_ci		k[o] = wrap(sampler.wrapR, k[o], depth);
2378e5c31af7Sopenharmony_ci
2379e5c31af7Sopenharmony_ci	bool iUseBorder[4], jUseBorder[4], kUseBorder[4];
2380e5c31af7Sopenharmony_ci	for (deUint32 m = 0; m < 4; ++m)
2381e5c31af7Sopenharmony_ci		iUseBorder[m] = sampler.wrapS == Sampler::CLAMP_TO_BORDER && !de::inBounds(i[m], 0, width);
2382e5c31af7Sopenharmony_ci	for (deUint32 n = 0; n < 4; ++n)
2383e5c31af7Sopenharmony_ci		jUseBorder[n] = sampler.wrapT == Sampler::CLAMP_TO_BORDER && !de::inBounds(j[n], 0, height);
2384e5c31af7Sopenharmony_ci	for (deUint32 o = 0; o < 4; ++o)
2385e5c31af7Sopenharmony_ci		kUseBorder[o] = sampler.wrapR == Sampler::CLAMP_TO_BORDER && !de::inBounds(k[o], 0, depth);
2386e5c31af7Sopenharmony_ci
2387e5c31af7Sopenharmony_ci	// Catmull-Rom basis matrix
2388e5c31af7Sopenharmony_ci	static const float crValues[16] = {	0.0f,	1.0f,	0.0f,	0.0f,
2389e5c31af7Sopenharmony_ci										-0.5f,	0.0f,	0.5f,	0.0f,
2390e5c31af7Sopenharmony_ci										1.0f,	-2.5f,	2.0f,	-0.5f,
2391e5c31af7Sopenharmony_ci										-0.5f,	1.5f,	-1.5f,	0.5f };
2392e5c31af7Sopenharmony_ci	static const tcu::Mat4 crBasis(crValues);
2393e5c31af7Sopenharmony_ci
2394e5c31af7Sopenharmony_ci	float		a		= deFloatFrac(u - 0.5f);
2395e5c31af7Sopenharmony_ci	float		b		= deFloatFrac(v - 0.5f);
2396e5c31af7Sopenharmony_ci	float		c		= deFloatFrac(w - 0.5f);
2397e5c31af7Sopenharmony_ci	tcu::Vec4	alpha	(1, a, a*a, a*a*a);
2398e5c31af7Sopenharmony_ci	tcu::Vec4	beta	(1, b, b*b, b*b*b);
2399e5c31af7Sopenharmony_ci	tcu::Vec4	gamma	(1, c, c*c, c*c*c);
2400e5c31af7Sopenharmony_ci	tcu::Vec4	wi		= alpha * crBasis;
2401e5c31af7Sopenharmony_ci	tcu::Vec4	wj		= beta  * crBasis;
2402e5c31af7Sopenharmony_ci	tcu::Vec4	wk		= gamma * crBasis;
2403e5c31af7Sopenharmony_ci
2404e5c31af7Sopenharmony_ci	tcu::Vec4 result(0.0f, 0.0f, 0.0f, 0.0f);
2405e5c31af7Sopenharmony_ci	for (deUint32 o = 0; o < 4; ++o)
2406e5c31af7Sopenharmony_ci		for (deUint32 n = 0; n < 4; ++n)
2407e5c31af7Sopenharmony_ci			for (deUint32 m = 0; m < 4; ++m)
2408e5c31af7Sopenharmony_ci			{
2409e5c31af7Sopenharmony_ci				tcu::Vec4 p = (iUseBorder[m] || jUseBorder[n] || kUseBorder[o]) ? lookupBorder(access.getFormat(), sampler) : lookup(access, i[m], j[n], k[o]);
2410e5c31af7Sopenharmony_ci				result += wi[m] * wj[n] * wk[o] * p;
2411e5c31af7Sopenharmony_ci			}
2412e5c31af7Sopenharmony_ci	return result;
2413e5c31af7Sopenharmony_ci}
2414e5c31af7Sopenharmony_ci
2415e5c31af7Sopenharmony_ciVec4 ConstPixelBufferAccess::sample1D (const Sampler& sampler, Sampler::FilterMode filter, float s, int level) const
2416e5c31af7Sopenharmony_ci{
2417e5c31af7Sopenharmony_ci	// check selected layer exists
2418e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(level, 0, m_size.y()));
2419e5c31af7Sopenharmony_ci
2420e5c31af7Sopenharmony_ci	return sample1DOffset(sampler, filter, s, tcu::IVec2(0, level));
2421e5c31af7Sopenharmony_ci}
2422e5c31af7Sopenharmony_ci
2423e5c31af7Sopenharmony_ciVec4 ConstPixelBufferAccess::sample2D (const Sampler& sampler, Sampler::FilterMode filter, float s, float t, int depth) const
2424e5c31af7Sopenharmony_ci{
2425e5c31af7Sopenharmony_ci	// check selected layer exists
2426e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(depth, 0, m_size.z()));
2427e5c31af7Sopenharmony_ci
2428e5c31af7Sopenharmony_ci	return sample2DOffset(sampler, filter, s, t, tcu::IVec3(0, 0, depth));
2429e5c31af7Sopenharmony_ci}
2430e5c31af7Sopenharmony_ci
2431e5c31af7Sopenharmony_ciVec4 ConstPixelBufferAccess::sample3D (const Sampler& sampler, Sampler::FilterMode filter, float s, float t, float r) const
2432e5c31af7Sopenharmony_ci{
2433e5c31af7Sopenharmony_ci	return sample3DOffset(sampler, filter, s, t, r, tcu::IVec3(0, 0, 0));
2434e5c31af7Sopenharmony_ci}
2435e5c31af7Sopenharmony_ci
2436e5c31af7Sopenharmony_ciVec4 ConstPixelBufferAccess::sample1DOffset (const Sampler& sampler, Sampler::FilterMode filter, float s, const IVec2& offset) const
2437e5c31af7Sopenharmony_ci{
2438e5c31af7Sopenharmony_ci	// check selected layer exists
2439e5c31af7Sopenharmony_ci	// \note offset.x is X offset, offset.y is the selected layer
2440e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(offset.y(), 0, m_size.y()));
2441e5c31af7Sopenharmony_ci
2442e5c31af7Sopenharmony_ci	// Non-normalized coordinates.
2443e5c31af7Sopenharmony_ci	float u = s;
2444e5c31af7Sopenharmony_ci
2445e5c31af7Sopenharmony_ci	if (sampler.normalizedCoords)
2446e5c31af7Sopenharmony_ci		u = unnormalize(sampler.wrapS, s, m_size.x());
2447e5c31af7Sopenharmony_ci
2448e5c31af7Sopenharmony_ci	switch (filter)
2449e5c31af7Sopenharmony_ci	{
2450e5c31af7Sopenharmony_ci		case Sampler::NEAREST:	return sampleNearest1D	(*this, sampler, u, offset);
2451e5c31af7Sopenharmony_ci		case Sampler::LINEAR:	return sampleLinear1D	(*this, sampler, u, offset);
2452e5c31af7Sopenharmony_ci		case Sampler::CUBIC:	return sampleCubic1D	(*this, sampler, u, offset);
2453e5c31af7Sopenharmony_ci		default:
2454e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
2455e5c31af7Sopenharmony_ci			return Vec4(0.0f);
2456e5c31af7Sopenharmony_ci	}
2457e5c31af7Sopenharmony_ci}
2458e5c31af7Sopenharmony_ci
2459e5c31af7Sopenharmony_ciVec4 ConstPixelBufferAccess::sample2DOffset (const Sampler& sampler, Sampler::FilterMode filter, float s, float t, const IVec3& offset) const
2460e5c31af7Sopenharmony_ci{
2461e5c31af7Sopenharmony_ci	// check selected layer exists
2462e5c31af7Sopenharmony_ci	// \note offset.xy is the XY offset, offset.z is the selected layer
2463e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(offset.z(), 0, m_size.z()));
2464e5c31af7Sopenharmony_ci
2465e5c31af7Sopenharmony_ci	// Non-normalized coordinates.
2466e5c31af7Sopenharmony_ci	float u = s;
2467e5c31af7Sopenharmony_ci	float v = t;
2468e5c31af7Sopenharmony_ci
2469e5c31af7Sopenharmony_ci	if (sampler.normalizedCoords)
2470e5c31af7Sopenharmony_ci	{
2471e5c31af7Sopenharmony_ci		u = unnormalize(sampler.wrapS, s, m_size.x());
2472e5c31af7Sopenharmony_ci		v = unnormalize(sampler.wrapT, t, m_size.y());
2473e5c31af7Sopenharmony_ci	}
2474e5c31af7Sopenharmony_ci
2475e5c31af7Sopenharmony_ci	switch (filter)
2476e5c31af7Sopenharmony_ci	{
2477e5c31af7Sopenharmony_ci		case Sampler::NEAREST:	return sampleNearest2D	(*this, sampler, u, v, offset);
2478e5c31af7Sopenharmony_ci		case Sampler::LINEAR:	return sampleLinear2D	(*this, sampler, u, v, offset);
2479e5c31af7Sopenharmony_ci		case Sampler::CUBIC:	return sampleCubic2D	(*this, sampler, u, v, offset);
2480e5c31af7Sopenharmony_ci		default:
2481e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
2482e5c31af7Sopenharmony_ci			return Vec4(0.0f);
2483e5c31af7Sopenharmony_ci	}
2484e5c31af7Sopenharmony_ci}
2485e5c31af7Sopenharmony_ci
2486e5c31af7Sopenharmony_ciVec4 ConstPixelBufferAccess::sample3DOffset (const Sampler& sampler, Sampler::FilterMode filter, float s, float t, float r, const IVec3& offset) const
2487e5c31af7Sopenharmony_ci{
2488e5c31af7Sopenharmony_ci	// Non-normalized coordinates.
2489e5c31af7Sopenharmony_ci	float u = s;
2490e5c31af7Sopenharmony_ci	float v = t;
2491e5c31af7Sopenharmony_ci	float w = r;
2492e5c31af7Sopenharmony_ci
2493e5c31af7Sopenharmony_ci	if (sampler.normalizedCoords)
2494e5c31af7Sopenharmony_ci	{
2495e5c31af7Sopenharmony_ci		u = unnormalize(sampler.wrapS, s, m_size.x());
2496e5c31af7Sopenharmony_ci		v = unnormalize(sampler.wrapT, t, m_size.y());
2497e5c31af7Sopenharmony_ci		w = unnormalize(sampler.wrapR, r, m_size.z());
2498e5c31af7Sopenharmony_ci	}
2499e5c31af7Sopenharmony_ci
2500e5c31af7Sopenharmony_ci	switch (filter)
2501e5c31af7Sopenharmony_ci	{
2502e5c31af7Sopenharmony_ci		case Sampler::NEAREST:	return sampleNearest3D	(*this, sampler, u, v, w, offset);
2503e5c31af7Sopenharmony_ci		case Sampler::LINEAR:	return sampleLinear3D	(*this, sampler, u, v, w, offset);
2504e5c31af7Sopenharmony_ci		case Sampler::CUBIC:	return sampleCubic3D	(*this, sampler, u, v, w, offset);
2505e5c31af7Sopenharmony_ci		default:
2506e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
2507e5c31af7Sopenharmony_ci			return Vec4(0.0f);
2508e5c31af7Sopenharmony_ci	}
2509e5c31af7Sopenharmony_ci}
2510e5c31af7Sopenharmony_ci
2511e5c31af7Sopenharmony_cifloat ConstPixelBufferAccess::sample1DCompare (const Sampler& sampler, Sampler::FilterMode filter, float ref, float s, const IVec2& offset) const
2512e5c31af7Sopenharmony_ci{
2513e5c31af7Sopenharmony_ci	// check selected layer exists
2514e5c31af7Sopenharmony_ci	// \note offset.x is X offset, offset.y is the selected layer
2515e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(offset.y(), 0, m_size.y()));
2516e5c31af7Sopenharmony_ci
2517e5c31af7Sopenharmony_ci	// Format information for comparison function
2518e5c31af7Sopenharmony_ci	const bool isFixedPointDepth = isFixedPointDepthTextureFormat(m_format);
2519e5c31af7Sopenharmony_ci
2520e5c31af7Sopenharmony_ci	// Non-normalized coordinates.
2521e5c31af7Sopenharmony_ci	float u = s;
2522e5c31af7Sopenharmony_ci
2523e5c31af7Sopenharmony_ci	if (sampler.normalizedCoords)
2524e5c31af7Sopenharmony_ci		u = unnormalize(sampler.wrapS, s, m_size.x());
2525e5c31af7Sopenharmony_ci
2526e5c31af7Sopenharmony_ci	switch (filter)
2527e5c31af7Sopenharmony_ci	{
2528e5c31af7Sopenharmony_ci		case Sampler::NEAREST:	return execCompare(sampleNearest1D(*this, sampler, u, offset), sampler.compare, sampler.compareChannel, ref, isFixedPointDepth);
2529e5c31af7Sopenharmony_ci		case Sampler::LINEAR:	return sampleLinear1DCompare(*this, sampler, ref, u, offset, isFixedPointDepth);
2530e5c31af7Sopenharmony_ci		default:
2531e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
2532e5c31af7Sopenharmony_ci			return 0.0f;
2533e5c31af7Sopenharmony_ci	}
2534e5c31af7Sopenharmony_ci}
2535e5c31af7Sopenharmony_ci
2536e5c31af7Sopenharmony_cifloat ConstPixelBufferAccess::sample2DCompare (const Sampler& sampler, Sampler::FilterMode filter, float ref, float s, float t, const IVec3& offset) const
2537e5c31af7Sopenharmony_ci{
2538e5c31af7Sopenharmony_ci	// check selected layer exists
2539e5c31af7Sopenharmony_ci	// \note offset.xy is XY offset, offset.z is the selected layer
2540e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(offset.z(), 0, m_size.z()));
2541e5c31af7Sopenharmony_ci
2542e5c31af7Sopenharmony_ci	// Format information for comparison function
2543e5c31af7Sopenharmony_ci	const bool isFixedPointDepth = isFixedPointDepthTextureFormat(m_format);
2544e5c31af7Sopenharmony_ci
2545e5c31af7Sopenharmony_ci	// Non-normalized coordinates.
2546e5c31af7Sopenharmony_ci	float u = s;
2547e5c31af7Sopenharmony_ci	float v = t;
2548e5c31af7Sopenharmony_ci
2549e5c31af7Sopenharmony_ci	if (sampler.normalizedCoords)
2550e5c31af7Sopenharmony_ci	{
2551e5c31af7Sopenharmony_ci		u = unnormalize(sampler.wrapS, s, m_size.x());
2552e5c31af7Sopenharmony_ci		v = unnormalize(sampler.wrapT, t, m_size.y());
2553e5c31af7Sopenharmony_ci	}
2554e5c31af7Sopenharmony_ci
2555e5c31af7Sopenharmony_ci	switch (filter)
2556e5c31af7Sopenharmony_ci	{
2557e5c31af7Sopenharmony_ci		case Sampler::NEAREST:	return execCompare(sampleNearest2D(*this, sampler, u, v, offset), sampler.compare, sampler.compareChannel, ref, isFixedPointDepth);
2558e5c31af7Sopenharmony_ci		case Sampler::LINEAR:	return sampleLinear2DCompare(*this, sampler, ref, u, v, offset, isFixedPointDepth);
2559e5c31af7Sopenharmony_ci		default:
2560e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
2561e5c31af7Sopenharmony_ci			return 0.0f;
2562e5c31af7Sopenharmony_ci	}
2563e5c31af7Sopenharmony_ci}
2564e5c31af7Sopenharmony_ci
2565e5c31af7Sopenharmony_ciTextureLevel::TextureLevel (void)
2566e5c31af7Sopenharmony_ci	: m_format	()
2567e5c31af7Sopenharmony_ci	, m_size	(0)
2568e5c31af7Sopenharmony_ci{
2569e5c31af7Sopenharmony_ci}
2570e5c31af7Sopenharmony_ci
2571e5c31af7Sopenharmony_ciTextureLevel::TextureLevel (const TextureFormat& format)
2572e5c31af7Sopenharmony_ci	: m_format	(format)
2573e5c31af7Sopenharmony_ci	, m_size	(0)
2574e5c31af7Sopenharmony_ci{
2575e5c31af7Sopenharmony_ci}
2576e5c31af7Sopenharmony_ci
2577e5c31af7Sopenharmony_ciTextureLevel::TextureLevel (const TextureFormat& format, int width, int height, int depth)
2578e5c31af7Sopenharmony_ci	: m_format	(format)
2579e5c31af7Sopenharmony_ci	, m_size	(0)
2580e5c31af7Sopenharmony_ci{
2581e5c31af7Sopenharmony_ci	setSize(width, height, depth);
2582e5c31af7Sopenharmony_ci}
2583e5c31af7Sopenharmony_ci
2584e5c31af7Sopenharmony_ciTextureLevel::~TextureLevel (void)
2585e5c31af7Sopenharmony_ci{
2586e5c31af7Sopenharmony_ci}
2587e5c31af7Sopenharmony_ci
2588e5c31af7Sopenharmony_civoid TextureLevel::setStorage (const TextureFormat& format, int width, int height, int depth)
2589e5c31af7Sopenharmony_ci{
2590e5c31af7Sopenharmony_ci	m_format = format;
2591e5c31af7Sopenharmony_ci	setSize(width, height, depth);
2592e5c31af7Sopenharmony_ci}
2593e5c31af7Sopenharmony_ci
2594e5c31af7Sopenharmony_civoid TextureLevel::setSize (int width, int height, int depth)
2595e5c31af7Sopenharmony_ci{
2596e5c31af7Sopenharmony_ci	int pixelSize = m_format.getPixelSize();
2597e5c31af7Sopenharmony_ci
2598e5c31af7Sopenharmony_ci	m_size = IVec3(width, height, depth);
2599e5c31af7Sopenharmony_ci
2600e5c31af7Sopenharmony_ci	m_data.setStorage(m_size.x() * m_size.y() * m_size.z() * pixelSize);
2601e5c31af7Sopenharmony_ci}
2602e5c31af7Sopenharmony_ci
2603e5c31af7Sopenharmony_ciVec4 sampleLevelArray1D (const ConstPixelBufferAccess* levels, int numLevels, const Sampler& sampler, float s, int depth, float lod)
2604e5c31af7Sopenharmony_ci{
2605e5c31af7Sopenharmony_ci	return sampleLevelArray1DOffset(levels, numLevels, sampler, s, lod, IVec2(0, depth)); // y-offset in 1D textures is layer selector
2606e5c31af7Sopenharmony_ci}
2607e5c31af7Sopenharmony_ci
2608e5c31af7Sopenharmony_ciVec4 sampleLevelArray2D (const ConstPixelBufferAccess* levels, int numLevels, const Sampler& sampler, float s, float t, int depth, float lod, bool es2, ImageViewMinLodParams* minLodParams)
2609e5c31af7Sopenharmony_ci{
2610e5c31af7Sopenharmony_ci	return sampleLevelArray2DOffset(levels, numLevels, sampler, s, t, lod, IVec3(0, 0, depth), es2, minLodParams); // z-offset in 2D textures is layer selector
2611e5c31af7Sopenharmony_ci}
2612e5c31af7Sopenharmony_ci
2613e5c31af7Sopenharmony_ciVec4 sampleLevelArray3D (const ConstPixelBufferAccess* levels, int numLevels, const Sampler& sampler, float s, float t, float r, float lod, ImageViewMinLodParams* minLodParams)
2614e5c31af7Sopenharmony_ci{
2615e5c31af7Sopenharmony_ci	return sampleLevelArray3DOffset(levels, numLevels, sampler, s, t, r, lod, IVec3(0, 0, 0), minLodParams);
2616e5c31af7Sopenharmony_ci}
2617e5c31af7Sopenharmony_ci
2618e5c31af7Sopenharmony_ciVec4 sampleLevelArray1DOffset (const ConstPixelBufferAccess* levels, int numLevels, const Sampler& sampler, float s, float lod, const IVec2& offset)
2619e5c31af7Sopenharmony_ci{
2620e5c31af7Sopenharmony_ci	bool					magnified	= lod <= sampler.lodThreshold;
2621e5c31af7Sopenharmony_ci	Sampler::FilterMode		filterMode	= magnified ? sampler.magFilter : sampler.minFilter;
2622e5c31af7Sopenharmony_ci
2623e5c31af7Sopenharmony_ci	switch (filterMode)
2624e5c31af7Sopenharmony_ci	{
2625e5c31af7Sopenharmony_ci		case Sampler::NEAREST:	return levels[0].sample1DOffset(sampler, filterMode, s, offset);
2626e5c31af7Sopenharmony_ci		case Sampler::LINEAR:	return levels[0].sample1DOffset(sampler, filterMode, s, offset);
2627e5c31af7Sopenharmony_ci
2628e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_NEAREST:
2629e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_NEAREST:
2630e5c31af7Sopenharmony_ci		{
2631e5c31af7Sopenharmony_ci			int					maxLevel	= (int)numLevels-1;
2632e5c31af7Sopenharmony_ci			int					level		= deClamp32((int)deFloatCeil(lod + 0.5f) - 1, 0, maxLevel);
2633e5c31af7Sopenharmony_ci			Sampler::FilterMode	levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_NEAREST) ? Sampler::LINEAR : Sampler::NEAREST;
2634e5c31af7Sopenharmony_ci
2635e5c31af7Sopenharmony_ci			return levels[level].sample1DOffset(sampler, levelFilter, s, offset);
2636e5c31af7Sopenharmony_ci		}
2637e5c31af7Sopenharmony_ci
2638e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_LINEAR:
2639e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_LINEAR:
2640e5c31af7Sopenharmony_ci		{
2641e5c31af7Sopenharmony_ci			int					maxLevel	= (int)numLevels-1;
2642e5c31af7Sopenharmony_ci			int					level0		= deClamp32((int)deFloatFloor(lod), 0, maxLevel);
2643e5c31af7Sopenharmony_ci			int					level1		= de::min(maxLevel, level0 + 1);
2644e5c31af7Sopenharmony_ci			Sampler::FilterMode	levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_LINEAR) ? Sampler::LINEAR : Sampler::NEAREST;
2645e5c31af7Sopenharmony_ci			float				f			= deFloatFrac(lod);
2646e5c31af7Sopenharmony_ci			tcu::Vec4			t0			= levels[level0].sample1DOffset(sampler, levelFilter, s, offset);
2647e5c31af7Sopenharmony_ci			tcu::Vec4			t1			= levels[level1].sample1DOffset(sampler, levelFilter, s, offset);
2648e5c31af7Sopenharmony_ci
2649e5c31af7Sopenharmony_ci			return t0*(1.0f - f) + t1*f;
2650e5c31af7Sopenharmony_ci		}
2651e5c31af7Sopenharmony_ci
2652e5c31af7Sopenharmony_ci		default:
2653e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
2654e5c31af7Sopenharmony_ci			return Vec4(0.0f);
2655e5c31af7Sopenharmony_ci	}
2656e5c31af7Sopenharmony_ci}
2657e5c31af7Sopenharmony_ci
2658e5c31af7Sopenharmony_ciVec4 sampleLevelArray2DOffset (const ConstPixelBufferAccess* levels, int numLevels, const Sampler& sampler, float s, float t, float lod, const IVec3& offset, bool es2, ImageViewMinLodParams* minLodParams)
2659e5c31af7Sopenharmony_ci{
2660e5c31af7Sopenharmony_ci	bool					magnified;
2661e5c31af7Sopenharmony_ci	// minLodRelative is used to calculate the image level to sample from, when VK_EXT_image_view_min_lod extension is enabled.
2662e5c31af7Sopenharmony_ci	// The value is relative to baseLevel as the Texture*View was created as the baseLevel being level[0].
2663e5c31af7Sopenharmony_ci	const float				minLodRelative	= (minLodParams != DE_NULL) ? getImageViewMinLod(minLodParams->minLod) - (float)minLodParams->baseLevel : 0.0f;
2664e5c31af7Sopenharmony_ci
2665e5c31af7Sopenharmony_ci	if (es2 && sampler.magFilter == Sampler::LINEAR &&
2666e5c31af7Sopenharmony_ci		(sampler.minFilter == Sampler::NEAREST_MIPMAP_NEAREST || sampler.minFilter == Sampler::NEAREST_MIPMAP_LINEAR))
2667e5c31af7Sopenharmony_ci		magnified = lod <= 0.5;
2668e5c31af7Sopenharmony_ci	else
2669e5c31af7Sopenharmony_ci		magnified = lod <= sampler.lodThreshold;
2670e5c31af7Sopenharmony_ci
2671e5c31af7Sopenharmony_ci	// VK_EXT_image_view_min_lod: Integer Texel Coordinates case (with robustness2 supported)
2672e5c31af7Sopenharmony_ci	if (minLodParams != DE_NULL && minLodParams->intTexCoord)
2673e5c31af7Sopenharmony_ci	{
2674e5c31af7Sopenharmony_ci		if (lod < deFloatFloor(minLodRelative) || lod >= (float)numLevels)
2675e5c31af7Sopenharmony_ci			return Vec4(0.0f);
2676e5c31af7Sopenharmony_ci
2677e5c31af7Sopenharmony_ci		if (s < 0.0f || s > 1.0f || t < 0.0f || t > 1.0f)
2678e5c31af7Sopenharmony_ci			return Vec4(0.0f);
2679e5c31af7Sopenharmony_ci	}
2680e5c31af7Sopenharmony_ci
2681e5c31af7Sopenharmony_ci	Sampler::FilterMode		filterMode	= magnified ? sampler.magFilter : sampler.minFilter;
2682e5c31af7Sopenharmony_ci	switch (filterMode)
2683e5c31af7Sopenharmony_ci	{
2684e5c31af7Sopenharmony_ci		case Sampler::NEAREST:
2685e5c31af7Sopenharmony_ci		case Sampler::LINEAR:
2686e5c31af7Sopenharmony_ci		case Sampler::CUBIC:
2687e5c31af7Sopenharmony_ci		{
2688e5c31af7Sopenharmony_ci			bool isLinearMipmapMode	= magnified && tcu::isSamplerMipmapModeLinear(sampler.minFilter);
2689e5c31af7Sopenharmony_ci			const int maxLevel		= (int)numLevels - 1;
2690e5c31af7Sopenharmony_ci			const int level0		= isLinearMipmapMode ? (int)deFloatFloor(minLodRelative) : deClamp32((int)deFloatCeil(minLodRelative + 0.5f) - 1, 0, maxLevel);
2691e5c31af7Sopenharmony_ci			tcu::Vec4 t0			= levels[level0].sample2DOffset(sampler, filterMode, s, t, offset);
2692e5c31af7Sopenharmony_ci
2693e5c31af7Sopenharmony_ci			if (!isLinearMipmapMode)
2694e5c31af7Sopenharmony_ci				return t0;
2695e5c31af7Sopenharmony_ci
2696e5c31af7Sopenharmony_ci			const float frac		= deFloatFrac(minLodRelative);
2697e5c31af7Sopenharmony_ci			const int level1		= de::min(level0 + 1, maxLevel);
2698e5c31af7Sopenharmony_ci			tcu::Vec4 t1			= levels[level1].sample2DOffset(sampler, filterMode, s, t, offset);
2699e5c31af7Sopenharmony_ci			return t0*(1.0f - frac) + t1*frac;
2700e5c31af7Sopenharmony_ci		}
2701e5c31af7Sopenharmony_ci
2702e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_NEAREST:
2703e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_NEAREST:
2704e5c31af7Sopenharmony_ci		case Sampler::CUBIC_MIPMAP_NEAREST:
2705e5c31af7Sopenharmony_ci		{
2706e5c31af7Sopenharmony_ci			if (minLodParams != DE_NULL && !minLodParams->intTexCoord)
2707e5c31af7Sopenharmony_ci				lod = de::max(lod, minLodRelative);
2708e5c31af7Sopenharmony_ci
2709e5c31af7Sopenharmony_ci			int					maxLevel	= (int)numLevels-1;
2710e5c31af7Sopenharmony_ci			int					level		= deClamp32((int)deFloatCeil(lod + 0.5f) - 1, 0, maxLevel);
2711e5c31af7Sopenharmony_ci			Sampler::FilterMode	levelFilter;
2712e5c31af7Sopenharmony_ci			switch (filterMode)
2713e5c31af7Sopenharmony_ci			{
2714e5c31af7Sopenharmony_ci			case Sampler::NEAREST_MIPMAP_NEAREST:	levelFilter = Sampler::NEAREST; break;
2715e5c31af7Sopenharmony_ci			case Sampler::LINEAR_MIPMAP_NEAREST:	levelFilter = Sampler::LINEAR; break;
2716e5c31af7Sopenharmony_ci			case Sampler::CUBIC_MIPMAP_NEAREST:		levelFilter = Sampler::CUBIC; break;
2717e5c31af7Sopenharmony_ci			default:
2718e5c31af7Sopenharmony_ci				DE_ASSERT(DE_FALSE);
2719e5c31af7Sopenharmony_ci				return Vec4(0.0f);
2720e5c31af7Sopenharmony_ci			}
2721e5c31af7Sopenharmony_ci
2722e5c31af7Sopenharmony_ci			return levels[level].sample2DOffset(sampler, levelFilter, s, t, offset);
2723e5c31af7Sopenharmony_ci		}
2724e5c31af7Sopenharmony_ci
2725e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_LINEAR:
2726e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_LINEAR:
2727e5c31af7Sopenharmony_ci		case Sampler::CUBIC_MIPMAP_LINEAR:
2728e5c31af7Sopenharmony_ci		{
2729e5c31af7Sopenharmony_ci			if (minLodParams != DE_NULL && !minLodParams->intTexCoord)
2730e5c31af7Sopenharmony_ci				lod = de::max(lod, minLodRelative);
2731e5c31af7Sopenharmony_ci
2732e5c31af7Sopenharmony_ci			int					maxLevel	= (int)numLevels-1;
2733e5c31af7Sopenharmony_ci			int					level0		= deClamp32((int)deFloatFloor(lod), 0, maxLevel);
2734e5c31af7Sopenharmony_ci			int					level1		= de::min(maxLevel, level0 + 1);
2735e5c31af7Sopenharmony_ci			Sampler::FilterMode	levelFilter;
2736e5c31af7Sopenharmony_ci			switch (filterMode)
2737e5c31af7Sopenharmony_ci			{
2738e5c31af7Sopenharmony_ci			case Sampler::NEAREST_MIPMAP_LINEAR:	levelFilter = Sampler::NEAREST; break;
2739e5c31af7Sopenharmony_ci			case Sampler::LINEAR_MIPMAP_LINEAR:		levelFilter = Sampler::LINEAR; break;
2740e5c31af7Sopenharmony_ci			case Sampler::CUBIC_MIPMAP_LINEAR:		levelFilter = Sampler::CUBIC; break;
2741e5c31af7Sopenharmony_ci			default:
2742e5c31af7Sopenharmony_ci				DE_ASSERT(DE_FALSE);
2743e5c31af7Sopenharmony_ci				return Vec4(0.0f);
2744e5c31af7Sopenharmony_ci			}
2745e5c31af7Sopenharmony_ci			float				f			= deFloatFrac(lod);
2746e5c31af7Sopenharmony_ci			tcu::Vec4			t0			= levels[level0].sample2DOffset(sampler, levelFilter, s, t, offset);
2747e5c31af7Sopenharmony_ci			tcu::Vec4			t1			= levels[level1].sample2DOffset(sampler, levelFilter, s, t, offset);
2748e5c31af7Sopenharmony_ci
2749e5c31af7Sopenharmony_ci			return t0*(1.0f - f) + t1*f;
2750e5c31af7Sopenharmony_ci		}
2751e5c31af7Sopenharmony_ci
2752e5c31af7Sopenharmony_ci		default:
2753e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
2754e5c31af7Sopenharmony_ci			return Vec4(0.0f);
2755e5c31af7Sopenharmony_ci	}
2756e5c31af7Sopenharmony_ci}
2757e5c31af7Sopenharmony_ci
2758e5c31af7Sopenharmony_ciVec4 sampleLevelArray3DOffset (const ConstPixelBufferAccess* levels, int numLevels, const Sampler& sampler, float s, float t, float r, float lod, const IVec3& offset, ImageViewMinLodParams* minLodParams)
2759e5c31af7Sopenharmony_ci{
2760e5c31af7Sopenharmony_ci	// minLodRelative is used to calculate the image level to sample from, when VK_EXT_image_view_min_lod extension is enabled.
2761e5c31af7Sopenharmony_ci	// The value is relative to baseLevel as the Texture*View was created as the baseLevel being level[0].
2762e5c31af7Sopenharmony_ci	const float				minLodRelative	= (minLodParams != DE_NULL) ? getImageViewMinLod(minLodParams->minLod) - (float)minLodParams->baseLevel : 0.0f;
2763e5c31af7Sopenharmony_ci	bool					magnified	= lod <= sampler.lodThreshold;
2764e5c31af7Sopenharmony_ci	Sampler::FilterMode		filterMode	= magnified ? sampler.magFilter : sampler.minFilter;
2765e5c31af7Sopenharmony_ci
2766e5c31af7Sopenharmony_ci	// VK_EXT_image_view_min_lod: Integer Texel Coordinates case (with robustness2 supported)
2767e5c31af7Sopenharmony_ci	if (minLodParams != DE_NULL && minLodParams->intTexCoord)
2768e5c31af7Sopenharmony_ci	{
2769e5c31af7Sopenharmony_ci		if (lod < deFloatFloor(minLodRelative) || lod >= (float)numLevels)
2770e5c31af7Sopenharmony_ci			return Vec4(0.0f);
2771e5c31af7Sopenharmony_ci
2772e5c31af7Sopenharmony_ci		if (s < 0.0f || s > 1.0f || t < 0.0f || t > 1.0f)
2773e5c31af7Sopenharmony_ci			return Vec4(0.0f);
2774e5c31af7Sopenharmony_ci	}
2775e5c31af7Sopenharmony_ci
2776e5c31af7Sopenharmony_ci	switch (filterMode)
2777e5c31af7Sopenharmony_ci	{
2778e5c31af7Sopenharmony_ci		case Sampler::NEAREST:
2779e5c31af7Sopenharmony_ci		case Sampler::LINEAR:
2780e5c31af7Sopenharmony_ci		{
2781e5c31af7Sopenharmony_ci			bool isLinearMipmapMode	= magnified && tcu::isSamplerMipmapModeLinear(sampler.minFilter);
2782e5c31af7Sopenharmony_ci			const int maxLevel		= (int)numLevels - 1;
2783e5c31af7Sopenharmony_ci			const int level0		= isLinearMipmapMode ? (int)deFloatFloor(minLodRelative) : deClamp32((int)deFloatCeil(minLodRelative + 0.5f) - 1, 0, maxLevel);
2784e5c31af7Sopenharmony_ci			tcu::Vec4 t0			= levels[level0].sample3DOffset(sampler, filterMode, s, t, r, offset);
2785e5c31af7Sopenharmony_ci
2786e5c31af7Sopenharmony_ci			if (!isLinearMipmapMode)
2787e5c31af7Sopenharmony_ci				return t0;
2788e5c31af7Sopenharmony_ci
2789e5c31af7Sopenharmony_ci			const float frac		= deFloatFrac(minLodRelative);
2790e5c31af7Sopenharmony_ci			const int level1		= de::min(level0 + 1, maxLevel);
2791e5c31af7Sopenharmony_ci			tcu::Vec4 t1			= levels[level1].sample3DOffset(sampler, filterMode, s, t, r, offset);
2792e5c31af7Sopenharmony_ci			return t0*(1.0f - frac) + t1*frac;
2793e5c31af7Sopenharmony_ci		}
2794e5c31af7Sopenharmony_ci
2795e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_NEAREST:
2796e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_NEAREST:
2797e5c31af7Sopenharmony_ci		{
2798e5c31af7Sopenharmony_ci			if (minLodParams != DE_NULL && !minLodParams->intTexCoord)
2799e5c31af7Sopenharmony_ci				lod = de::max(lod, minLodRelative);
2800e5c31af7Sopenharmony_ci
2801e5c31af7Sopenharmony_ci			int					maxLevel	= (int)numLevels-1;
2802e5c31af7Sopenharmony_ci			int					level		= deClamp32((int)deFloatCeil(lod + 0.5f) - 1, 0, maxLevel);
2803e5c31af7Sopenharmony_ci			Sampler::FilterMode	levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_NEAREST) ? Sampler::LINEAR : Sampler::NEAREST;
2804e5c31af7Sopenharmony_ci
2805e5c31af7Sopenharmony_ci			return levels[level].sample3DOffset(sampler, levelFilter, s, t, r, offset);
2806e5c31af7Sopenharmony_ci		}
2807e5c31af7Sopenharmony_ci
2808e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_LINEAR:
2809e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_LINEAR:
2810e5c31af7Sopenharmony_ci		{
2811e5c31af7Sopenharmony_ci			if (minLodParams != DE_NULL && !minLodParams->intTexCoord)
2812e5c31af7Sopenharmony_ci				lod = de::max(lod, minLodRelative);
2813e5c31af7Sopenharmony_ci
2814e5c31af7Sopenharmony_ci			int					maxLevel	= (int)numLevels-1;
2815e5c31af7Sopenharmony_ci			int					level0		= deClamp32((int)deFloatFloor(lod), 0, maxLevel);
2816e5c31af7Sopenharmony_ci			int					level1		= de::min(maxLevel, level0 + 1);
2817e5c31af7Sopenharmony_ci			Sampler::FilterMode	levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_LINEAR) ? Sampler::LINEAR : Sampler::NEAREST;
2818e5c31af7Sopenharmony_ci			float				f			= deFloatFrac(lod);
2819e5c31af7Sopenharmony_ci			tcu::Vec4			t0			= levels[level0].sample3DOffset(sampler, levelFilter, s, t, r, offset);
2820e5c31af7Sopenharmony_ci			tcu::Vec4			t1			= levels[level1].sample3DOffset(sampler, levelFilter, s, t, r, offset);
2821e5c31af7Sopenharmony_ci
2822e5c31af7Sopenharmony_ci			return t0*(1.0f - f) + t1*f;
2823e5c31af7Sopenharmony_ci		}
2824e5c31af7Sopenharmony_ci
2825e5c31af7Sopenharmony_ci		default:
2826e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
2827e5c31af7Sopenharmony_ci			return Vec4(0.0f);
2828e5c31af7Sopenharmony_ci	}
2829e5c31af7Sopenharmony_ci}
2830e5c31af7Sopenharmony_ci
2831e5c31af7Sopenharmony_cifloat sampleLevelArray1DCompare (const ConstPixelBufferAccess* levels, int numLevels, const Sampler& sampler, float ref, float s, float lod, const IVec2& offset)
2832e5c31af7Sopenharmony_ci{
2833e5c31af7Sopenharmony_ci	bool					magnified	= lod <= sampler.lodThreshold;
2834e5c31af7Sopenharmony_ci	Sampler::FilterMode		filterMode	= magnified ? sampler.magFilter : sampler.minFilter;
2835e5c31af7Sopenharmony_ci
2836e5c31af7Sopenharmony_ci	switch (filterMode)
2837e5c31af7Sopenharmony_ci	{
2838e5c31af7Sopenharmony_ci		case Sampler::NEAREST:	return levels[0].sample1DCompare(sampler, filterMode, ref, s, offset);
2839e5c31af7Sopenharmony_ci		case Sampler::LINEAR:	return levels[0].sample1DCompare(sampler, filterMode, ref, s, offset);
2840e5c31af7Sopenharmony_ci
2841e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_NEAREST:
2842e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_NEAREST:
2843e5c31af7Sopenharmony_ci		{
2844e5c31af7Sopenharmony_ci			int					maxLevel	= (int)numLevels-1;
2845e5c31af7Sopenharmony_ci			int					level		= deClamp32((int)deFloatCeil(lod + 0.5f) - 1, 0, maxLevel);
2846e5c31af7Sopenharmony_ci			Sampler::FilterMode	levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_NEAREST) ? Sampler::LINEAR : Sampler::NEAREST;
2847e5c31af7Sopenharmony_ci
2848e5c31af7Sopenharmony_ci			return levels[level].sample1DCompare(sampler, levelFilter, ref, s, offset);
2849e5c31af7Sopenharmony_ci		}
2850e5c31af7Sopenharmony_ci
2851e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_LINEAR:
2852e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_LINEAR:
2853e5c31af7Sopenharmony_ci		{
2854e5c31af7Sopenharmony_ci			int					maxLevel	= (int)numLevels-1;
2855e5c31af7Sopenharmony_ci			int					level0		= deClamp32((int)deFloatFloor(lod), 0, maxLevel);
2856e5c31af7Sopenharmony_ci			int					level1		= de::min(maxLevel, level0 + 1);
2857e5c31af7Sopenharmony_ci			Sampler::FilterMode	levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_LINEAR) ? Sampler::LINEAR : Sampler::NEAREST;
2858e5c31af7Sopenharmony_ci			float				f			= deFloatFrac(lod);
2859e5c31af7Sopenharmony_ci			float				t0			= levels[level0].sample1DCompare(sampler, levelFilter, ref, s, offset);
2860e5c31af7Sopenharmony_ci			float				t1			= levels[level1].sample1DCompare(sampler, levelFilter, ref, s, offset);
2861e5c31af7Sopenharmony_ci
2862e5c31af7Sopenharmony_ci			return t0*(1.0f - f) + t1*f;
2863e5c31af7Sopenharmony_ci		}
2864e5c31af7Sopenharmony_ci
2865e5c31af7Sopenharmony_ci		default:
2866e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
2867e5c31af7Sopenharmony_ci			return 0.0f;
2868e5c31af7Sopenharmony_ci	}
2869e5c31af7Sopenharmony_ci}
2870e5c31af7Sopenharmony_ci
2871e5c31af7Sopenharmony_cifloat sampleLevelArray2DCompare (const ConstPixelBufferAccess* levels, int numLevels, const Sampler& sampler, float ref, float s, float t, float lod, const IVec3& offset)
2872e5c31af7Sopenharmony_ci{
2873e5c31af7Sopenharmony_ci	bool					magnified	= lod <= sampler.lodThreshold;
2874e5c31af7Sopenharmony_ci	Sampler::FilterMode		filterMode	= magnified ? sampler.magFilter : sampler.minFilter;
2875e5c31af7Sopenharmony_ci
2876e5c31af7Sopenharmony_ci	switch (filterMode)
2877e5c31af7Sopenharmony_ci	{
2878e5c31af7Sopenharmony_ci		case Sampler::NEAREST:	return levels[0].sample2DCompare(sampler, filterMode, ref, s, t, offset);
2879e5c31af7Sopenharmony_ci		case Sampler::LINEAR:	return levels[0].sample2DCompare(sampler, filterMode, ref, s, t, offset);
2880e5c31af7Sopenharmony_ci
2881e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_NEAREST:
2882e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_NEAREST:
2883e5c31af7Sopenharmony_ci		{
2884e5c31af7Sopenharmony_ci			int					maxLevel	= (int)numLevels-1;
2885e5c31af7Sopenharmony_ci			int					level		= deClamp32((int)deFloatCeil(lod + 0.5f) - 1, 0, maxLevel);
2886e5c31af7Sopenharmony_ci			Sampler::FilterMode	levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_NEAREST) ? Sampler::LINEAR : Sampler::NEAREST;
2887e5c31af7Sopenharmony_ci
2888e5c31af7Sopenharmony_ci			return levels[level].sample2DCompare(sampler, levelFilter, ref, s, t, offset);
2889e5c31af7Sopenharmony_ci		}
2890e5c31af7Sopenharmony_ci
2891e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_LINEAR:
2892e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_LINEAR:
2893e5c31af7Sopenharmony_ci		{
2894e5c31af7Sopenharmony_ci			int					maxLevel	= (int)numLevels-1;
2895e5c31af7Sopenharmony_ci			int					level0		= deClamp32((int)deFloatFloor(lod), 0, maxLevel);
2896e5c31af7Sopenharmony_ci			int					level1		= de::min(maxLevel, level0 + 1);
2897e5c31af7Sopenharmony_ci			Sampler::FilterMode	levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_LINEAR) ? Sampler::LINEAR : Sampler::NEAREST;
2898e5c31af7Sopenharmony_ci			float				f			= deFloatFrac(lod);
2899e5c31af7Sopenharmony_ci			float				t0			= levels[level0].sample2DCompare(sampler, levelFilter, ref, s, t, offset);
2900e5c31af7Sopenharmony_ci			float				t1			= levels[level1].sample2DCompare(sampler, levelFilter, ref, s, t, offset);
2901e5c31af7Sopenharmony_ci
2902e5c31af7Sopenharmony_ci			return t0*(1.0f - f) + t1*f;
2903e5c31af7Sopenharmony_ci		}
2904e5c31af7Sopenharmony_ci
2905e5c31af7Sopenharmony_ci		default:
2906e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
2907e5c31af7Sopenharmony_ci			return 0.0f;
2908e5c31af7Sopenharmony_ci	}
2909e5c31af7Sopenharmony_ci}
2910e5c31af7Sopenharmony_ci
2911e5c31af7Sopenharmony_cistatic Vec4 fetchGatherArray2DOffsets (const ConstPixelBufferAccess& src, const Sampler& sampler, float s, float t, int depth, int componentNdx, const IVec2 (&offsets)[4])
2912e5c31af7Sopenharmony_ci{
2913e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(componentNdx, 0, 4));
2914e5c31af7Sopenharmony_ci
2915e5c31af7Sopenharmony_ci	const int		w	= src.getWidth();
2916e5c31af7Sopenharmony_ci	const int		h	= src.getHeight();
2917e5c31af7Sopenharmony_ci	const float		u	= unnormalize(sampler.wrapS, s, w);
2918e5c31af7Sopenharmony_ci	const float		v	= unnormalize(sampler.wrapT, t, h);
2919e5c31af7Sopenharmony_ci	const int		x0	= deFloorFloatToInt32(u-0.5f);
2920e5c31af7Sopenharmony_ci	const int		y0	= deFloorFloatToInt32(v-0.5f);
2921e5c31af7Sopenharmony_ci
2922e5c31af7Sopenharmony_ci	Vec4			result;
2923e5c31af7Sopenharmony_ci
2924e5c31af7Sopenharmony_ci	for (int i = 0; i < 4; i++)
2925e5c31af7Sopenharmony_ci	{
2926e5c31af7Sopenharmony_ci		const int	sampleX	= wrap(sampler.wrapS, x0 + offsets[i].x(), w);
2927e5c31af7Sopenharmony_ci		const int	sampleY	= wrap(sampler.wrapT, y0 + offsets[i].y(), h);
2928e5c31af7Sopenharmony_ci		Vec4		pixel;
2929e5c31af7Sopenharmony_ci
2930e5c31af7Sopenharmony_ci		if (deInBounds32(sampleX, 0, w) && deInBounds32(sampleY, 0, h))
2931e5c31af7Sopenharmony_ci			pixel = lookup(src, sampleX, sampleY, depth);
2932e5c31af7Sopenharmony_ci		else
2933e5c31af7Sopenharmony_ci			pixel = lookupBorder(src.getFormat(), sampler);
2934e5c31af7Sopenharmony_ci
2935e5c31af7Sopenharmony_ci		result[i] = pixel[componentNdx];
2936e5c31af7Sopenharmony_ci	}
2937e5c31af7Sopenharmony_ci
2938e5c31af7Sopenharmony_ci	return result;
2939e5c31af7Sopenharmony_ci}
2940e5c31af7Sopenharmony_ci
2941e5c31af7Sopenharmony_ciVec4 gatherArray2DOffsets (const ConstPixelBufferAccess& src, const Sampler& sampler, float s, float t, int depth, int componentNdx, const IVec2 (&offsets)[4])
2942e5c31af7Sopenharmony_ci{
2943e5c31af7Sopenharmony_ci	DE_ASSERT(sampler.compare == Sampler::COMPAREMODE_NONE);
2944e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(componentNdx, 0, 4));
2945e5c31af7Sopenharmony_ci
2946e5c31af7Sopenharmony_ci	return fetchGatherArray2DOffsets(src, sampler, s, t, depth, componentNdx, offsets);
2947e5c31af7Sopenharmony_ci}
2948e5c31af7Sopenharmony_ci
2949e5c31af7Sopenharmony_ciVec4 gatherArray2DOffsetsCompare (const ConstPixelBufferAccess& src, const Sampler& sampler, float ref, float s, float t, int depth, const IVec2 (&offsets)[4])
2950e5c31af7Sopenharmony_ci{
2951e5c31af7Sopenharmony_ci	DE_ASSERT(sampler.compare != Sampler::COMPAREMODE_NONE);
2952e5c31af7Sopenharmony_ci	DE_ASSERT(src.getFormat().order == TextureFormat::D || src.getFormat().order == TextureFormat::DS);
2953e5c31af7Sopenharmony_ci	DE_ASSERT(sampler.compareChannel == 0);
2954e5c31af7Sopenharmony_ci
2955e5c31af7Sopenharmony_ci	const bool	isFixedPoint	= isFixedPointDepthTextureFormat(src.getFormat());
2956e5c31af7Sopenharmony_ci	const Vec4	gathered		= fetchGatherArray2DOffsets(src, sampler, s, t, depth, 0 /* component 0: depth */, offsets);
2957e5c31af7Sopenharmony_ci	Vec4		result;
2958e5c31af7Sopenharmony_ci
2959e5c31af7Sopenharmony_ci	for (int i = 0; i < 4; i++)
2960e5c31af7Sopenharmony_ci		result[i] = execCompare(gathered, sampler.compare, i, ref, isFixedPoint);
2961e5c31af7Sopenharmony_ci
2962e5c31af7Sopenharmony_ci	return result;
2963e5c31af7Sopenharmony_ci}
2964e5c31af7Sopenharmony_ci
2965e5c31af7Sopenharmony_cistatic Vec4 sampleCubeSeamlessNearest (const ConstPixelBufferAccess& faceAccess, const Sampler& sampler, float s, float t, int depth)
2966e5c31af7Sopenharmony_ci{
2967e5c31af7Sopenharmony_ci	Sampler clampingSampler = sampler;
2968e5c31af7Sopenharmony_ci	clampingSampler.wrapS = Sampler::CLAMP_TO_EDGE;
2969e5c31af7Sopenharmony_ci	clampingSampler.wrapT = Sampler::CLAMP_TO_EDGE;
2970e5c31af7Sopenharmony_ci	return faceAccess.sample2D(clampingSampler, Sampler::NEAREST, s, t, depth);
2971e5c31af7Sopenharmony_ci}
2972e5c31af7Sopenharmony_ci
2973e5c31af7Sopenharmony_ciCubeFace selectCubeFace (const Vec3& coords)
2974e5c31af7Sopenharmony_ci{
2975e5c31af7Sopenharmony_ci	const float	x	= coords.x();
2976e5c31af7Sopenharmony_ci	const float	y	= coords.y();
2977e5c31af7Sopenharmony_ci	const float	z	= coords.z();
2978e5c31af7Sopenharmony_ci	const float	ax	= deFloatAbs(x);
2979e5c31af7Sopenharmony_ci	const float	ay	= deFloatAbs(y);
2980e5c31af7Sopenharmony_ci	const float	az	= deFloatAbs(z);
2981e5c31af7Sopenharmony_ci
2982e5c31af7Sopenharmony_ci	if (ay < ax && az < ax)
2983e5c31af7Sopenharmony_ci		return x >= 0.0f ? CUBEFACE_POSITIVE_X : CUBEFACE_NEGATIVE_X;
2984e5c31af7Sopenharmony_ci	else if (ax < ay && az < ay)
2985e5c31af7Sopenharmony_ci		return y >= 0.0f ? CUBEFACE_POSITIVE_Y : CUBEFACE_NEGATIVE_Y;
2986e5c31af7Sopenharmony_ci	else if (ax < az && ay < az)
2987e5c31af7Sopenharmony_ci		return z >= 0.0f ? CUBEFACE_POSITIVE_Z : CUBEFACE_NEGATIVE_Z;
2988e5c31af7Sopenharmony_ci	else
2989e5c31af7Sopenharmony_ci	{
2990e5c31af7Sopenharmony_ci		// Some of the components are equal. Use tie-breaking rule.
2991e5c31af7Sopenharmony_ci		if (ax == ay)
2992e5c31af7Sopenharmony_ci		{
2993e5c31af7Sopenharmony_ci			if (ax < az)
2994e5c31af7Sopenharmony_ci				return z >= 0.0f ? CUBEFACE_POSITIVE_Z : CUBEFACE_NEGATIVE_Z;
2995e5c31af7Sopenharmony_ci			else
2996e5c31af7Sopenharmony_ci				return x >= 0.0f ? CUBEFACE_POSITIVE_X : CUBEFACE_NEGATIVE_X;
2997e5c31af7Sopenharmony_ci		}
2998e5c31af7Sopenharmony_ci		else if (ax == az)
2999e5c31af7Sopenharmony_ci		{
3000e5c31af7Sopenharmony_ci			if (az < ay)
3001e5c31af7Sopenharmony_ci				return y >= 0.0f ? CUBEFACE_POSITIVE_Y : CUBEFACE_NEGATIVE_Y;
3002e5c31af7Sopenharmony_ci			else
3003e5c31af7Sopenharmony_ci				return z >= 0.0f ? CUBEFACE_POSITIVE_Z : CUBEFACE_NEGATIVE_Z;
3004e5c31af7Sopenharmony_ci		}
3005e5c31af7Sopenharmony_ci		else if (ay == az)
3006e5c31af7Sopenharmony_ci		{
3007e5c31af7Sopenharmony_ci			if (ay < ax)
3008e5c31af7Sopenharmony_ci				return x >= 0.0f ? CUBEFACE_POSITIVE_X : CUBEFACE_NEGATIVE_X;
3009e5c31af7Sopenharmony_ci			else
3010e5c31af7Sopenharmony_ci				return y >= 0.0f ? CUBEFACE_POSITIVE_Y : CUBEFACE_NEGATIVE_Y;
3011e5c31af7Sopenharmony_ci		}
3012e5c31af7Sopenharmony_ci		else
3013e5c31af7Sopenharmony_ci			return x >= 0.0f ? CUBEFACE_POSITIVE_X : CUBEFACE_NEGATIVE_X;
3014e5c31af7Sopenharmony_ci	}
3015e5c31af7Sopenharmony_ci}
3016e5c31af7Sopenharmony_ci
3017e5c31af7Sopenharmony_ciVec2 projectToFace (CubeFace face, const Vec3& coord)
3018e5c31af7Sopenharmony_ci{
3019e5c31af7Sopenharmony_ci	const float	rx		= coord.x();
3020e5c31af7Sopenharmony_ci	const float	ry		= coord.y();
3021e5c31af7Sopenharmony_ci	const float	rz		= coord.z();
3022e5c31af7Sopenharmony_ci	float		sc		= 0.0f;
3023e5c31af7Sopenharmony_ci	float		tc		= 0.0f;
3024e5c31af7Sopenharmony_ci	float		ma		= 0.0f;
3025e5c31af7Sopenharmony_ci	float		s;
3026e5c31af7Sopenharmony_ci	float		t;
3027e5c31af7Sopenharmony_ci
3028e5c31af7Sopenharmony_ci	switch (face)
3029e5c31af7Sopenharmony_ci	{
3030e5c31af7Sopenharmony_ci		case CUBEFACE_NEGATIVE_X: sc = +rz; tc = -ry; ma = -rx; break;
3031e5c31af7Sopenharmony_ci		case CUBEFACE_POSITIVE_X: sc = -rz; tc = -ry; ma = +rx; break;
3032e5c31af7Sopenharmony_ci		case CUBEFACE_NEGATIVE_Y: sc = +rx; tc = -rz; ma = -ry; break;
3033e5c31af7Sopenharmony_ci		case CUBEFACE_POSITIVE_Y: sc = +rx; tc = +rz; ma = +ry; break;
3034e5c31af7Sopenharmony_ci		case CUBEFACE_NEGATIVE_Z: sc = -rx; tc = -ry; ma = -rz; break;
3035e5c31af7Sopenharmony_ci		case CUBEFACE_POSITIVE_Z: sc = +rx; tc = -ry; ma = +rz; break;
3036e5c31af7Sopenharmony_ci		default:
3037e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
3038e5c31af7Sopenharmony_ci	}
3039e5c31af7Sopenharmony_ci
3040e5c31af7Sopenharmony_ci	if (fabs(ma) < FLT_EPSILON)
3041e5c31af7Sopenharmony_ci	{
3042e5c31af7Sopenharmony_ci		return Vec2(0.0f);
3043e5c31af7Sopenharmony_ci	}
3044e5c31af7Sopenharmony_ci
3045e5c31af7Sopenharmony_ci	// Compute s, t
3046e5c31af7Sopenharmony_ci	s = ((sc / ma) + 1.0f) / 2.0f;
3047e5c31af7Sopenharmony_ci	t = ((tc / ma) + 1.0f) / 2.0f;
3048e5c31af7Sopenharmony_ci
3049e5c31af7Sopenharmony_ci	return Vec2(s, t);
3050e5c31af7Sopenharmony_ci}
3051e5c31af7Sopenharmony_ci
3052e5c31af7Sopenharmony_ciCubeFaceFloatCoords getCubeFaceCoords (const Vec3& coords)
3053e5c31af7Sopenharmony_ci{
3054e5c31af7Sopenharmony_ci	const CubeFace face = selectCubeFace(coords);
3055e5c31af7Sopenharmony_ci	return CubeFaceFloatCoords(face, projectToFace(face, coords));
3056e5c31af7Sopenharmony_ci}
3057e5c31af7Sopenharmony_ci
3058e5c31af7Sopenharmony_ci// Checks if origCoords.coords is in bounds defined by size; if not, return a CubeFaceIntCoords with face set to the appropriate neighboring face and coords transformed accordingly.
3059e5c31af7Sopenharmony_ci// \note If both x and y in origCoords.coords are out of bounds, this returns with face CUBEFACE_LAST, signifying that there is no unique neighboring face.
3060e5c31af7Sopenharmony_ciCubeFaceIntCoords remapCubeEdgeCoords (const CubeFaceIntCoords& origCoords, int size)
3061e5c31af7Sopenharmony_ci{
3062e5c31af7Sopenharmony_ci	bool uInBounds = de::inBounds(origCoords.s, 0, size);
3063e5c31af7Sopenharmony_ci	bool vInBounds = de::inBounds(origCoords.t, 0, size);
3064e5c31af7Sopenharmony_ci
3065e5c31af7Sopenharmony_ci	if (uInBounds && vInBounds)
3066e5c31af7Sopenharmony_ci		return origCoords;
3067e5c31af7Sopenharmony_ci
3068e5c31af7Sopenharmony_ci	if (!uInBounds && !vInBounds)
3069e5c31af7Sopenharmony_ci		return CubeFaceIntCoords(CUBEFACE_LAST, -1, -1);
3070e5c31af7Sopenharmony_ci
3071e5c31af7Sopenharmony_ci	IVec2 coords(wrap(Sampler::CLAMP_TO_BORDER, origCoords.s, size),
3072e5c31af7Sopenharmony_ci				 wrap(Sampler::CLAMP_TO_BORDER, origCoords.t, size));
3073e5c31af7Sopenharmony_ci	IVec3 canonizedCoords;
3074e5c31af7Sopenharmony_ci
3075e5c31af7Sopenharmony_ci	// Map the uv coordinates to canonized 3d coordinates.
3076e5c31af7Sopenharmony_ci
3077e5c31af7Sopenharmony_ci	switch (origCoords.face)
3078e5c31af7Sopenharmony_ci	{
3079e5c31af7Sopenharmony_ci		case CUBEFACE_NEGATIVE_X: canonizedCoords = IVec3(0,					size-1-coords.y(),	coords.x());			break;
3080e5c31af7Sopenharmony_ci		case CUBEFACE_POSITIVE_X: canonizedCoords = IVec3(size-1,				size-1-coords.y(),	size-1-coords.x());		break;
3081e5c31af7Sopenharmony_ci		case CUBEFACE_NEGATIVE_Y: canonizedCoords = IVec3(coords.x(),			0,					size-1-coords.y());		break;
3082e5c31af7Sopenharmony_ci		case CUBEFACE_POSITIVE_Y: canonizedCoords = IVec3(coords.x(),			size-1,				coords.y());			break;
3083e5c31af7Sopenharmony_ci		case CUBEFACE_NEGATIVE_Z: canonizedCoords = IVec3(size-1-coords.x(),	size-1-coords.y(),	0);						break;
3084e5c31af7Sopenharmony_ci		case CUBEFACE_POSITIVE_Z: canonizedCoords = IVec3(coords.x(),			size-1-coords.y(),	size-1);				break;
3085e5c31af7Sopenharmony_ci		default: DE_ASSERT(false);
3086e5c31af7Sopenharmony_ci	}
3087e5c31af7Sopenharmony_ci
3088e5c31af7Sopenharmony_ci	// Find an appropriate face to re-map the coordinates to.
3089e5c31af7Sopenharmony_ci
3090e5c31af7Sopenharmony_ci	if (canonizedCoords.x() == -1)
3091e5c31af7Sopenharmony_ci		return CubeFaceIntCoords(CUBEFACE_NEGATIVE_X, IVec2(canonizedCoords.z(), size-1-canonizedCoords.y()));
3092e5c31af7Sopenharmony_ci
3093e5c31af7Sopenharmony_ci	if (canonizedCoords.x() == size)
3094e5c31af7Sopenharmony_ci		return CubeFaceIntCoords(CUBEFACE_POSITIVE_X, IVec2(size-1-canonizedCoords.z(), size-1-canonizedCoords.y()));
3095e5c31af7Sopenharmony_ci
3096e5c31af7Sopenharmony_ci	if (canonizedCoords.y() == -1)
3097e5c31af7Sopenharmony_ci		return CubeFaceIntCoords(CUBEFACE_NEGATIVE_Y, IVec2(canonizedCoords.x(), size-1-canonizedCoords.z()));
3098e5c31af7Sopenharmony_ci
3099e5c31af7Sopenharmony_ci	if (canonizedCoords.y() == size)
3100e5c31af7Sopenharmony_ci		return CubeFaceIntCoords(CUBEFACE_POSITIVE_Y, IVec2(canonizedCoords.x(), canonizedCoords.z()));
3101e5c31af7Sopenharmony_ci
3102e5c31af7Sopenharmony_ci	if (canonizedCoords.z() == -1)
3103e5c31af7Sopenharmony_ci		return CubeFaceIntCoords(CUBEFACE_NEGATIVE_Z, IVec2(size-1-canonizedCoords.x(), size-1-canonizedCoords.y()));
3104e5c31af7Sopenharmony_ci
3105e5c31af7Sopenharmony_ci	if (canonizedCoords.z() == size)
3106e5c31af7Sopenharmony_ci		return CubeFaceIntCoords(CUBEFACE_POSITIVE_Z, IVec2(canonizedCoords.x(), size-1-canonizedCoords.y()));
3107e5c31af7Sopenharmony_ci
3108e5c31af7Sopenharmony_ci	DE_ASSERT(false);
3109e5c31af7Sopenharmony_ci	return CubeFaceIntCoords(CUBEFACE_LAST, IVec2(-1));
3110e5c31af7Sopenharmony_ci}
3111e5c31af7Sopenharmony_ci
3112e5c31af7Sopenharmony_cistatic void getCubeLinearSamples (const ConstPixelBufferAccess (&faceAccesses)[CUBEFACE_LAST], CubeFace baseFace, float u, float v, int depth, Vec4 (&dst)[4])
3113e5c31af7Sopenharmony_ci{
3114e5c31af7Sopenharmony_ci	DE_ASSERT(faceAccesses[0].getWidth() == faceAccesses[0].getHeight());
3115e5c31af7Sopenharmony_ci	int		size					= faceAccesses[0].getWidth();
3116e5c31af7Sopenharmony_ci	int		x0						= deFloorFloatToInt32(u-0.5f);
3117e5c31af7Sopenharmony_ci	int		x1						= x0+1;
3118e5c31af7Sopenharmony_ci	int		y0						= deFloorFloatToInt32(v-0.5f);
3119e5c31af7Sopenharmony_ci	int		y1						= y0+1;
3120e5c31af7Sopenharmony_ci	IVec2	baseSampleCoords[4]		=
3121e5c31af7Sopenharmony_ci	{
3122e5c31af7Sopenharmony_ci		IVec2(x0, y0),
3123e5c31af7Sopenharmony_ci		IVec2(x1, y0),
3124e5c31af7Sopenharmony_ci		IVec2(x0, y1),
3125e5c31af7Sopenharmony_ci		IVec2(x1, y1)
3126e5c31af7Sopenharmony_ci	};
3127e5c31af7Sopenharmony_ci	Vec4	sampleColors[4];
3128e5c31af7Sopenharmony_ci	bool	hasBothCoordsOutOfBounds[4]; //!< Whether correctCubeFace() returns CUBEFACE_LAST, i.e. both u and v are out of bounds.
3129e5c31af7Sopenharmony_ci
3130e5c31af7Sopenharmony_ci	// Find correct faces and coordinates for out-of-bounds sample coordinates.
3131e5c31af7Sopenharmony_ci
3132e5c31af7Sopenharmony_ci	for (int i = 0; i < 4; i++)
3133e5c31af7Sopenharmony_ci	{
3134e5c31af7Sopenharmony_ci		CubeFaceIntCoords coords = remapCubeEdgeCoords(CubeFaceIntCoords(baseFace, baseSampleCoords[i]), size);
3135e5c31af7Sopenharmony_ci		hasBothCoordsOutOfBounds[i] = coords.face == CUBEFACE_LAST;
3136e5c31af7Sopenharmony_ci		if (!hasBothCoordsOutOfBounds[i])
3137e5c31af7Sopenharmony_ci			sampleColors[i] = lookup(faceAccesses[coords.face], coords.s, coords.t, depth);
3138e5c31af7Sopenharmony_ci	}
3139e5c31af7Sopenharmony_ci
3140e5c31af7Sopenharmony_ci	// If a sample was out of bounds in both u and v, we get its color from the average of the three other samples.
3141e5c31af7Sopenharmony_ci	// \note This averaging behavior is not required by the GLES3 spec (though it is recommended). GLES3 spec only
3142e5c31af7Sopenharmony_ci	//		 requires that if the three other samples all have the same color, then the doubly-out-of-bounds sample
3143e5c31af7Sopenharmony_ci	//		 must have this color as well.
3144e5c31af7Sopenharmony_ci
3145e5c31af7Sopenharmony_ci	{
3146e5c31af7Sopenharmony_ci		int bothOutOfBoundsNdx = -1;
3147e5c31af7Sopenharmony_ci		for (int i = 0; i < 4; i++)
3148e5c31af7Sopenharmony_ci		{
3149e5c31af7Sopenharmony_ci			if (hasBothCoordsOutOfBounds[i])
3150e5c31af7Sopenharmony_ci			{
3151e5c31af7Sopenharmony_ci				DE_ASSERT(bothOutOfBoundsNdx < 0); // Only one sample can be out of bounds in both u and v.
3152e5c31af7Sopenharmony_ci				bothOutOfBoundsNdx = i;
3153e5c31af7Sopenharmony_ci			}
3154e5c31af7Sopenharmony_ci		}
3155e5c31af7Sopenharmony_ci		if (bothOutOfBoundsNdx != -1)
3156e5c31af7Sopenharmony_ci		{
3157e5c31af7Sopenharmony_ci			sampleColors[bothOutOfBoundsNdx] = Vec4(0.0f);
3158e5c31af7Sopenharmony_ci			for (int i = 0; i < 4; i++)
3159e5c31af7Sopenharmony_ci				if (i != bothOutOfBoundsNdx)
3160e5c31af7Sopenharmony_ci					sampleColors[bothOutOfBoundsNdx] += sampleColors[i];
3161e5c31af7Sopenharmony_ci
3162e5c31af7Sopenharmony_ci			sampleColors[bothOutOfBoundsNdx] = sampleColors[bothOutOfBoundsNdx] * (1.0f/3.0f);
3163e5c31af7Sopenharmony_ci		}
3164e5c31af7Sopenharmony_ci	}
3165e5c31af7Sopenharmony_ci
3166e5c31af7Sopenharmony_ci	for (int i = 0; i < DE_LENGTH_OF_ARRAY(sampleColors); i++)
3167e5c31af7Sopenharmony_ci		dst[i] = sampleColors[i];
3168e5c31af7Sopenharmony_ci}
3169e5c31af7Sopenharmony_ci
3170e5c31af7Sopenharmony_ci// \todo [2014-02-19 pyry] Optimize faceAccesses
3171e5c31af7Sopenharmony_cistatic Vec4 sampleCubeSeamlessLinear (const ConstPixelBufferAccess (&faceAccesses)[CUBEFACE_LAST], CubeFace baseFace, const Sampler& sampler, float s, float t, int depth)
3172e5c31af7Sopenharmony_ci{
3173e5c31af7Sopenharmony_ci	DE_ASSERT(faceAccesses[0].getWidth() == faceAccesses[0].getHeight());
3174e5c31af7Sopenharmony_ci
3175e5c31af7Sopenharmony_ci	int		size	= faceAccesses[0].getWidth();
3176e5c31af7Sopenharmony_ci	// Non-normalized coordinates.
3177e5c31af7Sopenharmony_ci	float	u		= s;
3178e5c31af7Sopenharmony_ci	float	v		= t;
3179e5c31af7Sopenharmony_ci
3180e5c31af7Sopenharmony_ci	if (sampler.normalizedCoords)
3181e5c31af7Sopenharmony_ci	{
3182e5c31af7Sopenharmony_ci		u = unnormalize(sampler.wrapS, s, size);
3183e5c31af7Sopenharmony_ci		v = unnormalize(sampler.wrapT, t, size);
3184e5c31af7Sopenharmony_ci	}
3185e5c31af7Sopenharmony_ci
3186e5c31af7Sopenharmony_ci	// Get sample colors.
3187e5c31af7Sopenharmony_ci
3188e5c31af7Sopenharmony_ci	Vec4 sampleColors[4];
3189e5c31af7Sopenharmony_ci	getCubeLinearSamples(faceAccesses, baseFace, u, v, depth, sampleColors);
3190e5c31af7Sopenharmony_ci
3191e5c31af7Sopenharmony_ci	// Interpolate.
3192e5c31af7Sopenharmony_ci
3193e5c31af7Sopenharmony_ci	float a = deFloatFrac(u-0.5f);
3194e5c31af7Sopenharmony_ci	float b = deFloatFrac(v-0.5f);
3195e5c31af7Sopenharmony_ci
3196e5c31af7Sopenharmony_ci	return (sampleColors[0]*(1.0f-a)*(1.0f-b)) +
3197e5c31af7Sopenharmony_ci		   (sampleColors[1]*(     a)*(1.0f-b)) +
3198e5c31af7Sopenharmony_ci		   (sampleColors[2]*(1.0f-a)*(     b)) +
3199e5c31af7Sopenharmony_ci		   (sampleColors[3]*(     a)*(     b));
3200e5c31af7Sopenharmony_ci}
3201e5c31af7Sopenharmony_ci
3202e5c31af7Sopenharmony_cistatic Vec4 sampleLevelArrayCubeSeamless (const ConstPixelBufferAccess* const (&faces)[CUBEFACE_LAST], int numLevels, CubeFace face, const Sampler& sampler, float s, float t, int depth, float lod, ImageViewMinLodParams* minLodParams)
3203e5c31af7Sopenharmony_ci{
3204e5c31af7Sopenharmony_ci	// minLodRelative is used to calculate the image level to sample from, when VK_EXT_image_view_min_lod extension is enabled.
3205e5c31af7Sopenharmony_ci	// The value is relative to baseLevel as the Texture*View was created as the baseLevel being level[0].
3206e5c31af7Sopenharmony_ci	const float				minLodRelative	= (minLodParams != DE_NULL) ? getImageViewMinLod(minLodParams->minLod) - (float)minLodParams->baseLevel : 0.0f;
3207e5c31af7Sopenharmony_ci	bool					magnified	= lod <= sampler.lodThreshold;
3208e5c31af7Sopenharmony_ci	Sampler::FilterMode		filterMode	= magnified ? sampler.magFilter : sampler.minFilter;
3209e5c31af7Sopenharmony_ci
3210e5c31af7Sopenharmony_ci	// VK_EXT_image_view_min_lod: Integer Texel Coordinates case (with robustness2 supported)
3211e5c31af7Sopenharmony_ci	if (minLodParams != DE_NULL && minLodParams->intTexCoord)
3212e5c31af7Sopenharmony_ci	{
3213e5c31af7Sopenharmony_ci		if (lod < deFloatFloor(minLodRelative) || lod >= (float)(numLevels - 1))
3214e5c31af7Sopenharmony_ci			return Vec4(0.0f);
3215e5c31af7Sopenharmony_ci
3216e5c31af7Sopenharmony_ci		if (s < 0.0f || s > 1.0f || t < 0.0f || t > 1.0f)
3217e5c31af7Sopenharmony_ci			return Vec4(0.0f);
3218e5c31af7Sopenharmony_ci	}
3219e5c31af7Sopenharmony_ci
3220e5c31af7Sopenharmony_ci	switch (filterMode)
3221e5c31af7Sopenharmony_ci	{
3222e5c31af7Sopenharmony_ci		case Sampler::NEAREST:
3223e5c31af7Sopenharmony_ci		{
3224e5c31af7Sopenharmony_ci			bool isLinearMipmapMode	= magnified && tcu::isSamplerMipmapModeLinear(sampler.minFilter);
3225e5c31af7Sopenharmony_ci			const int maxLevel		= (int)numLevels - 1;
3226e5c31af7Sopenharmony_ci			const int level0		= isLinearMipmapMode ? (int)deFloatFloor(minLodRelative) : deClamp32((int)deFloatCeil(minLodRelative + 0.5f) - 1, 0, maxLevel);
3227e5c31af7Sopenharmony_ci			tcu::Vec4 t0			= sampleCubeSeamlessNearest(faces[face][level0], sampler, s, t, depth);
3228e5c31af7Sopenharmony_ci
3229e5c31af7Sopenharmony_ci			if (!isLinearMipmapMode)
3230e5c31af7Sopenharmony_ci				return t0;
3231e5c31af7Sopenharmony_ci
3232e5c31af7Sopenharmony_ci			const float frac		= deFloatFrac(minLodRelative);
3233e5c31af7Sopenharmony_ci			const int level1		= de::min(level0 + 1, maxLevel);
3234e5c31af7Sopenharmony_ci			tcu::Vec4 t1			= sampleCubeSeamlessNearest(faces[face][level1], sampler, s, t, depth);
3235e5c31af7Sopenharmony_ci			return t0*(1.0f - frac) + t1*frac;
3236e5c31af7Sopenharmony_ci		}
3237e5c31af7Sopenharmony_ci
3238e5c31af7Sopenharmony_ci		case Sampler::LINEAR:
3239e5c31af7Sopenharmony_ci		{
3240e5c31af7Sopenharmony_ci			bool cond = sampler.minFilter == Sampler::NEAREST_MIPMAP_LINEAR || sampler.minFilter == Sampler::LINEAR_MIPMAP_LINEAR;
3241e5c31af7Sopenharmony_ci			const int index = cond ? (int)deFloatFloor(minLodRelative) : ((int)deFloatCeil(minLodRelative + 0.5f) - 1u);
3242e5c31af7Sopenharmony_ci			ConstPixelBufferAccess faceAccesses[CUBEFACE_LAST];
3243e5c31af7Sopenharmony_ci			for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3244e5c31af7Sopenharmony_ci				faceAccesses[i] = faces[i][index];
3245e5c31af7Sopenharmony_ci
3246e5c31af7Sopenharmony_ci			Vec4 result = sampleCubeSeamlessLinear(faceAccesses, face, sampler, s, t, depth);
3247e5c31af7Sopenharmony_ci
3248e5c31af7Sopenharmony_ci
3249e5c31af7Sopenharmony_ci			if (cond && ((index + 1) < numLevels) && deFloatFrac(minLodRelative) != 0.0f)
3250e5c31af7Sopenharmony_ci			{
3251e5c31af7Sopenharmony_ci				// In case of a minLodRelative value with fractional part, we need to ponderate the different sample of N level
3252e5c31af7Sopenharmony_ci				// and sample for level N+1 accordingly.
3253e5c31af7Sopenharmony_ci				result = result * (1.0f - deFloatFrac(minLodRelative));
3254e5c31af7Sopenharmony_ci
3255e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccessesNext[CUBEFACE_LAST];
3256e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3257e5c31af7Sopenharmony_ci					faceAccessesNext[i] = faces[i][index + 1];
3258e5c31af7Sopenharmony_ci				result += sampleCubeSeamlessLinear(faceAccesses, face, sampler, s, t, depth) * deFloatFrac(minLodRelative);
3259e5c31af7Sopenharmony_ci			}
3260e5c31af7Sopenharmony_ci			return result;
3261e5c31af7Sopenharmony_ci		}
3262e5c31af7Sopenharmony_ci
3263e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_NEAREST:
3264e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_NEAREST:
3265e5c31af7Sopenharmony_ci		{
3266e5c31af7Sopenharmony_ci			if (minLodParams != DE_NULL && !minLodParams->intTexCoord)
3267e5c31af7Sopenharmony_ci				lod = de::max(lod, minLodRelative);
3268e5c31af7Sopenharmony_ci
3269e5c31af7Sopenharmony_ci			int						maxLevel	= (int)numLevels-1;
3270e5c31af7Sopenharmony_ci			int						level		= deClamp32((int)deFloatCeil(lod + 0.5f) - 1, 0, maxLevel);
3271e5c31af7Sopenharmony_ci			Sampler::FilterMode		levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_NEAREST) ? Sampler::LINEAR : Sampler::NEAREST;
3272e5c31af7Sopenharmony_ci
3273e5c31af7Sopenharmony_ci			if (levelFilter == Sampler::NEAREST)
3274e5c31af7Sopenharmony_ci				return sampleCubeSeamlessNearest(faces[face][level], sampler, s, t, depth);
3275e5c31af7Sopenharmony_ci			else
3276e5c31af7Sopenharmony_ci			{
3277e5c31af7Sopenharmony_ci				DE_ASSERT(levelFilter == Sampler::LINEAR);
3278e5c31af7Sopenharmony_ci
3279e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses[CUBEFACE_LAST];
3280e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3281e5c31af7Sopenharmony_ci					faceAccesses[i] = faces[i][level];
3282e5c31af7Sopenharmony_ci
3283e5c31af7Sopenharmony_ci				return sampleCubeSeamlessLinear(faceAccesses, face, sampler, s, t, depth);
3284e5c31af7Sopenharmony_ci			}
3285e5c31af7Sopenharmony_ci		}
3286e5c31af7Sopenharmony_ci
3287e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_LINEAR:
3288e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_LINEAR:
3289e5c31af7Sopenharmony_ci		{
3290e5c31af7Sopenharmony_ci			if (minLodParams != DE_NULL && !minLodParams->intTexCoord)
3291e5c31af7Sopenharmony_ci				lod = de::max(lod, minLodRelative);
3292e5c31af7Sopenharmony_ci
3293e5c31af7Sopenharmony_ci			int						maxLevel	= (int)numLevels-1;
3294e5c31af7Sopenharmony_ci			int						level0		= deClamp32((int)deFloatFloor(lod), 0, maxLevel);
3295e5c31af7Sopenharmony_ci			int						level1		= de::min(maxLevel, level0 + 1);
3296e5c31af7Sopenharmony_ci			Sampler::FilterMode		levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_LINEAR) ? Sampler::LINEAR : Sampler::NEAREST;
3297e5c31af7Sopenharmony_ci			float					f			= deFloatFrac(lod);
3298e5c31af7Sopenharmony_ci			Vec4					t0;
3299e5c31af7Sopenharmony_ci			Vec4					t1;
3300e5c31af7Sopenharmony_ci
3301e5c31af7Sopenharmony_ci			if (levelFilter == Sampler::NEAREST)
3302e5c31af7Sopenharmony_ci			{
3303e5c31af7Sopenharmony_ci				t0 = sampleCubeSeamlessNearest(faces[face][level0], sampler, s, t, depth);
3304e5c31af7Sopenharmony_ci				t1 = sampleCubeSeamlessNearest(faces[face][level1], sampler, s, t, depth);
3305e5c31af7Sopenharmony_ci			}
3306e5c31af7Sopenharmony_ci			else
3307e5c31af7Sopenharmony_ci			{
3308e5c31af7Sopenharmony_ci				DE_ASSERT(levelFilter == Sampler::LINEAR);
3309e5c31af7Sopenharmony_ci
3310e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses0[CUBEFACE_LAST];
3311e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses1[CUBEFACE_LAST];
3312e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3313e5c31af7Sopenharmony_ci				{
3314e5c31af7Sopenharmony_ci					faceAccesses0[i] = faces[i][level0];
3315e5c31af7Sopenharmony_ci					faceAccesses1[i] = faces[i][level1];
3316e5c31af7Sopenharmony_ci				}
3317e5c31af7Sopenharmony_ci
3318e5c31af7Sopenharmony_ci				t0 = sampleCubeSeamlessLinear(faceAccesses0, face, sampler, s, t, depth);
3319e5c31af7Sopenharmony_ci				t1 = sampleCubeSeamlessLinear(faceAccesses1, face, sampler, s, t, depth);
3320e5c31af7Sopenharmony_ci			}
3321e5c31af7Sopenharmony_ci
3322e5c31af7Sopenharmony_ci			return t0*(1.0f - f) + t1*f;
3323e5c31af7Sopenharmony_ci		}
3324e5c31af7Sopenharmony_ci
3325e5c31af7Sopenharmony_ci		default:
3326e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
3327e5c31af7Sopenharmony_ci			return Vec4(0.0f);
3328e5c31af7Sopenharmony_ci	}
3329e5c31af7Sopenharmony_ci}
3330e5c31af7Sopenharmony_ci
3331e5c31af7Sopenharmony_cistatic float sampleCubeSeamlessNearestCompare (const ConstPixelBufferAccess& faceAccess, const Sampler& sampler, float ref, float s, float t, int depth = 0)
3332e5c31af7Sopenharmony_ci{
3333e5c31af7Sopenharmony_ci	Sampler clampingSampler = sampler;
3334e5c31af7Sopenharmony_ci	clampingSampler.wrapS = Sampler::CLAMP_TO_EDGE;
3335e5c31af7Sopenharmony_ci	clampingSampler.wrapT = Sampler::CLAMP_TO_EDGE;
3336e5c31af7Sopenharmony_ci	return faceAccess.sample2DCompare(clampingSampler, Sampler::NEAREST, ref, s, t, IVec3(0, 0, depth));
3337e5c31af7Sopenharmony_ci}
3338e5c31af7Sopenharmony_ci
3339e5c31af7Sopenharmony_cistatic float sampleCubeSeamlessLinearCompare (const ConstPixelBufferAccess (&faceAccesses)[CUBEFACE_LAST], CubeFace baseFace, const Sampler& sampler, float ref, float s, float t)
3340e5c31af7Sopenharmony_ci{
3341e5c31af7Sopenharmony_ci	DE_ASSERT(faceAccesses[0].getWidth() == faceAccesses[0].getHeight());
3342e5c31af7Sopenharmony_ci
3343e5c31af7Sopenharmony_ci	int		size	= faceAccesses[0].getWidth();
3344e5c31af7Sopenharmony_ci	// Non-normalized coordinates.
3345e5c31af7Sopenharmony_ci	float	u		= s;
3346e5c31af7Sopenharmony_ci	float	v		= t;
3347e5c31af7Sopenharmony_ci
3348e5c31af7Sopenharmony_ci	if (sampler.normalizedCoords)
3349e5c31af7Sopenharmony_ci	{
3350e5c31af7Sopenharmony_ci		u = unnormalize(sampler.wrapS, s, size);
3351e5c31af7Sopenharmony_ci		v = unnormalize(sampler.wrapT, t, size);
3352e5c31af7Sopenharmony_ci	}
3353e5c31af7Sopenharmony_ci
3354e5c31af7Sopenharmony_ci	int			x0						= deFloorFloatToInt32(u-0.5f);
3355e5c31af7Sopenharmony_ci	int			x1						= x0+1;
3356e5c31af7Sopenharmony_ci	int			y0						= deFloorFloatToInt32(v-0.5f);
3357e5c31af7Sopenharmony_ci	int			y1						= y0+1;
3358e5c31af7Sopenharmony_ci	IVec2		baseSampleCoords[4]		=
3359e5c31af7Sopenharmony_ci	{
3360e5c31af7Sopenharmony_ci		IVec2(x0, y0),
3361e5c31af7Sopenharmony_ci		IVec2(x1, y0),
3362e5c31af7Sopenharmony_ci		IVec2(x0, y1),
3363e5c31af7Sopenharmony_ci		IVec2(x1, y1)
3364e5c31af7Sopenharmony_ci	};
3365e5c31af7Sopenharmony_ci	float		sampleRes[4];
3366e5c31af7Sopenharmony_ci	bool		hasBothCoordsOutOfBounds[4]; //!< Whether correctCubeFace() returns CUBEFACE_LAST, i.e. both u and v are out of bounds.
3367e5c31af7Sopenharmony_ci
3368e5c31af7Sopenharmony_ci	// Find correct faces and coordinates for out-of-bounds sample coordinates.
3369e5c31af7Sopenharmony_ci
3370e5c31af7Sopenharmony_ci	for (int i = 0; i < 4; i++)
3371e5c31af7Sopenharmony_ci	{
3372e5c31af7Sopenharmony_ci		CubeFaceIntCoords coords = remapCubeEdgeCoords(CubeFaceIntCoords(baseFace, baseSampleCoords[i]), size);
3373e5c31af7Sopenharmony_ci		hasBothCoordsOutOfBounds[i] = coords.face == CUBEFACE_LAST;
3374e5c31af7Sopenharmony_ci
3375e5c31af7Sopenharmony_ci		if (!hasBothCoordsOutOfBounds[i])
3376e5c31af7Sopenharmony_ci		{
3377e5c31af7Sopenharmony_ci			const bool isFixedPointDepth = isFixedPointDepthTextureFormat(faceAccesses[coords.face].getFormat());
3378e5c31af7Sopenharmony_ci
3379e5c31af7Sopenharmony_ci			sampleRes[i] = execCompare(faceAccesses[coords.face].getPixel(coords.s, coords.t), sampler.compare, sampler.compareChannel, ref, isFixedPointDepth);
3380e5c31af7Sopenharmony_ci		}
3381e5c31af7Sopenharmony_ci	}
3382e5c31af7Sopenharmony_ci
3383e5c31af7Sopenharmony_ci	// If a sample was out of bounds in both u and v, we get its color from the average of the three other samples.
3384e5c31af7Sopenharmony_ci	// \note This averaging behavior is not required by the GLES3 spec (though it is recommended). GLES3 spec only
3385e5c31af7Sopenharmony_ci	//		 requires that if the three other samples all have the same color, then the doubly-out-of-bounds sample
3386e5c31af7Sopenharmony_ci	//		 must have this color as well.
3387e5c31af7Sopenharmony_ci
3388e5c31af7Sopenharmony_ci	{
3389e5c31af7Sopenharmony_ci		int bothOutOfBoundsNdx = -1;
3390e5c31af7Sopenharmony_ci		for (int i = 0; i < 4; i++)
3391e5c31af7Sopenharmony_ci		{
3392e5c31af7Sopenharmony_ci			if (hasBothCoordsOutOfBounds[i])
3393e5c31af7Sopenharmony_ci			{
3394e5c31af7Sopenharmony_ci				DE_ASSERT(bothOutOfBoundsNdx < 0); // Only one sample can be out of bounds in both u and v.
3395e5c31af7Sopenharmony_ci				bothOutOfBoundsNdx = i;
3396e5c31af7Sopenharmony_ci			}
3397e5c31af7Sopenharmony_ci		}
3398e5c31af7Sopenharmony_ci		if (bothOutOfBoundsNdx != -1)
3399e5c31af7Sopenharmony_ci		{
3400e5c31af7Sopenharmony_ci			sampleRes[bothOutOfBoundsNdx] = 0.0f;
3401e5c31af7Sopenharmony_ci			for (int i = 0; i < 4; i++)
3402e5c31af7Sopenharmony_ci				if (i != bothOutOfBoundsNdx)
3403e5c31af7Sopenharmony_ci					sampleRes[bothOutOfBoundsNdx] += sampleRes[i];
3404e5c31af7Sopenharmony_ci
3405e5c31af7Sopenharmony_ci			sampleRes[bothOutOfBoundsNdx] = sampleRes[bothOutOfBoundsNdx] * (1.0f/3.0f);
3406e5c31af7Sopenharmony_ci		}
3407e5c31af7Sopenharmony_ci	}
3408e5c31af7Sopenharmony_ci
3409e5c31af7Sopenharmony_ci	// Interpolate.
3410e5c31af7Sopenharmony_ci
3411e5c31af7Sopenharmony_ci	float a = deFloatFrac(u-0.5f);
3412e5c31af7Sopenharmony_ci	float b = deFloatFrac(v-0.5f);
3413e5c31af7Sopenharmony_ci
3414e5c31af7Sopenharmony_ci	return (sampleRes[0]*(1.0f-a)*(1.0f-b)) +
3415e5c31af7Sopenharmony_ci		   (sampleRes[1]*(     a)*(1.0f-b)) +
3416e5c31af7Sopenharmony_ci		   (sampleRes[2]*(1.0f-a)*(     b)) +
3417e5c31af7Sopenharmony_ci		   (sampleRes[3]*(     a)*(     b));
3418e5c31af7Sopenharmony_ci}
3419e5c31af7Sopenharmony_ci
3420e5c31af7Sopenharmony_cistatic float sampleLevelArrayCubeSeamlessCompare (const ConstPixelBufferAccess* const (&faces)[CUBEFACE_LAST], int numLevels, CubeFace face, const Sampler& sampler, float ref, float s, float t, float lod)
3421e5c31af7Sopenharmony_ci{
3422e5c31af7Sopenharmony_ci	bool					magnified	= lod <= sampler.lodThreshold;
3423e5c31af7Sopenharmony_ci	Sampler::FilterMode		filterMode	= magnified ? sampler.magFilter : sampler.minFilter;
3424e5c31af7Sopenharmony_ci
3425e5c31af7Sopenharmony_ci	switch (filterMode)
3426e5c31af7Sopenharmony_ci	{
3427e5c31af7Sopenharmony_ci		case Sampler::NEAREST:
3428e5c31af7Sopenharmony_ci			return sampleCubeSeamlessNearestCompare(faces[face][0], sampler, ref, s, t);
3429e5c31af7Sopenharmony_ci
3430e5c31af7Sopenharmony_ci		case Sampler::LINEAR:
3431e5c31af7Sopenharmony_ci		{
3432e5c31af7Sopenharmony_ci			ConstPixelBufferAccess faceAccesses[CUBEFACE_LAST];
3433e5c31af7Sopenharmony_ci			for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3434e5c31af7Sopenharmony_ci				faceAccesses[i] = faces[i][0];
3435e5c31af7Sopenharmony_ci
3436e5c31af7Sopenharmony_ci			return sampleCubeSeamlessLinearCompare(faceAccesses, face, sampler, ref, s, t);
3437e5c31af7Sopenharmony_ci		}
3438e5c31af7Sopenharmony_ci
3439e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_NEAREST:
3440e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_NEAREST:
3441e5c31af7Sopenharmony_ci		{
3442e5c31af7Sopenharmony_ci			int						maxLevel	= (int)numLevels-1;
3443e5c31af7Sopenharmony_ci			int						level		= deClamp32((int)deFloatCeil(lod + 0.5f) - 1, 0, maxLevel);
3444e5c31af7Sopenharmony_ci			Sampler::FilterMode		levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_NEAREST) ? Sampler::LINEAR : Sampler::NEAREST;
3445e5c31af7Sopenharmony_ci
3446e5c31af7Sopenharmony_ci			if (levelFilter == Sampler::NEAREST)
3447e5c31af7Sopenharmony_ci				return sampleCubeSeamlessNearestCompare(faces[face][level], sampler, ref, s, t);
3448e5c31af7Sopenharmony_ci			else
3449e5c31af7Sopenharmony_ci			{
3450e5c31af7Sopenharmony_ci				DE_ASSERT(levelFilter == Sampler::LINEAR);
3451e5c31af7Sopenharmony_ci
3452e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses[CUBEFACE_LAST];
3453e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3454e5c31af7Sopenharmony_ci					faceAccesses[i] = faces[i][level];
3455e5c31af7Sopenharmony_ci
3456e5c31af7Sopenharmony_ci				return sampleCubeSeamlessLinearCompare(faceAccesses, face, sampler, ref, s, t);
3457e5c31af7Sopenharmony_ci			}
3458e5c31af7Sopenharmony_ci		}
3459e5c31af7Sopenharmony_ci
3460e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_LINEAR:
3461e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_LINEAR:
3462e5c31af7Sopenharmony_ci		{
3463e5c31af7Sopenharmony_ci			int						maxLevel	= (int)numLevels-1;
3464e5c31af7Sopenharmony_ci			int						level0		= deClamp32((int)deFloatFloor(lod), 0, maxLevel);
3465e5c31af7Sopenharmony_ci			int						level1		= de::min(maxLevel, level0 + 1);
3466e5c31af7Sopenharmony_ci			Sampler::FilterMode		levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_LINEAR) ? Sampler::LINEAR : Sampler::NEAREST;
3467e5c31af7Sopenharmony_ci			float					f			= deFloatFrac(lod);
3468e5c31af7Sopenharmony_ci			float					t0;
3469e5c31af7Sopenharmony_ci			float					t1;
3470e5c31af7Sopenharmony_ci
3471e5c31af7Sopenharmony_ci			if (levelFilter == Sampler::NEAREST)
3472e5c31af7Sopenharmony_ci			{
3473e5c31af7Sopenharmony_ci				t0 = sampleCubeSeamlessNearestCompare(faces[face][level0], sampler, ref, s, t);
3474e5c31af7Sopenharmony_ci				t1 = sampleCubeSeamlessNearestCompare(faces[face][level1], sampler, ref, s, t);
3475e5c31af7Sopenharmony_ci			}
3476e5c31af7Sopenharmony_ci			else
3477e5c31af7Sopenharmony_ci			{
3478e5c31af7Sopenharmony_ci				DE_ASSERT(levelFilter == Sampler::LINEAR);
3479e5c31af7Sopenharmony_ci
3480e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses0[CUBEFACE_LAST];
3481e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses1[CUBEFACE_LAST];
3482e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3483e5c31af7Sopenharmony_ci				{
3484e5c31af7Sopenharmony_ci					faceAccesses0[i] = faces[i][level0];
3485e5c31af7Sopenharmony_ci					faceAccesses1[i] = faces[i][level1];
3486e5c31af7Sopenharmony_ci				}
3487e5c31af7Sopenharmony_ci
3488e5c31af7Sopenharmony_ci				t0 = sampleCubeSeamlessLinearCompare(faceAccesses0, face, sampler, ref, s, t);
3489e5c31af7Sopenharmony_ci				t1 = sampleCubeSeamlessLinearCompare(faceAccesses1, face, sampler, ref, s, t);
3490e5c31af7Sopenharmony_ci			}
3491e5c31af7Sopenharmony_ci
3492e5c31af7Sopenharmony_ci			return t0*(1.0f - f) + t1*f;
3493e5c31af7Sopenharmony_ci		}
3494e5c31af7Sopenharmony_ci
3495e5c31af7Sopenharmony_ci		default:
3496e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
3497e5c31af7Sopenharmony_ci			return 0.0f;
3498e5c31af7Sopenharmony_ci	}
3499e5c31af7Sopenharmony_ci}
3500e5c31af7Sopenharmony_ci
3501e5c31af7Sopenharmony_ci// Cube map array sampling
3502e5c31af7Sopenharmony_ci
3503e5c31af7Sopenharmony_cistatic inline ConstPixelBufferAccess getCubeArrayFaceAccess (const ConstPixelBufferAccess* const levels, int levelNdx, int slice, CubeFace face)
3504e5c31af7Sopenharmony_ci{
3505e5c31af7Sopenharmony_ci	const ConstPixelBufferAccess&	level	= levels[levelNdx];
3506e5c31af7Sopenharmony_ci	const int						depth	= (slice * 6) + getCubeArrayFaceIndex(face);
3507e5c31af7Sopenharmony_ci
3508e5c31af7Sopenharmony_ci	return getSubregion(level, 0, 0, depth, level.getWidth(), level.getHeight(), 1);
3509e5c31af7Sopenharmony_ci}
3510e5c31af7Sopenharmony_ci
3511e5c31af7Sopenharmony_cistatic Vec4 sampleCubeArraySeamless (const ConstPixelBufferAccess* const levels, int numLevels, int slice, CubeFace face, const Sampler& sampler, float s, float t, float lod)
3512e5c31af7Sopenharmony_ci{
3513e5c31af7Sopenharmony_ci	const int					faceDepth	= (slice * 6) + getCubeArrayFaceIndex(face);
3514e5c31af7Sopenharmony_ci	const bool					magnified	= lod <= sampler.lodThreshold;
3515e5c31af7Sopenharmony_ci	const Sampler::FilterMode	filterMode	= magnified ? sampler.magFilter : sampler.minFilter;
3516e5c31af7Sopenharmony_ci
3517e5c31af7Sopenharmony_ci	switch (filterMode)
3518e5c31af7Sopenharmony_ci	{
3519e5c31af7Sopenharmony_ci		case Sampler::NEAREST:
3520e5c31af7Sopenharmony_ci			return sampleCubeSeamlessNearest(levels[0], sampler, s, t, faceDepth);
3521e5c31af7Sopenharmony_ci
3522e5c31af7Sopenharmony_ci		case Sampler::LINEAR:
3523e5c31af7Sopenharmony_ci		{
3524e5c31af7Sopenharmony_ci			ConstPixelBufferAccess faceAccesses[CUBEFACE_LAST];
3525e5c31af7Sopenharmony_ci			for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3526e5c31af7Sopenharmony_ci				faceAccesses[i] = getCubeArrayFaceAccess(levels, 0, slice, (CubeFace)i);
3527e5c31af7Sopenharmony_ci
3528e5c31af7Sopenharmony_ci			return sampleCubeSeamlessLinear(faceAccesses, face, sampler, s, t, 0);
3529e5c31af7Sopenharmony_ci		}
3530e5c31af7Sopenharmony_ci
3531e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_NEAREST:
3532e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_NEAREST:
3533e5c31af7Sopenharmony_ci		{
3534e5c31af7Sopenharmony_ci			int						maxLevel	= (int)numLevels-1;
3535e5c31af7Sopenharmony_ci			int						level		= deClamp32((int)deFloatCeil(lod + 0.5f) - 1, 0, maxLevel);
3536e5c31af7Sopenharmony_ci			Sampler::FilterMode		levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_NEAREST) ? Sampler::LINEAR : Sampler::NEAREST;
3537e5c31af7Sopenharmony_ci
3538e5c31af7Sopenharmony_ci			if (levelFilter == Sampler::NEAREST)
3539e5c31af7Sopenharmony_ci				return sampleCubeSeamlessNearest(levels[level], sampler, s, t, faceDepth);
3540e5c31af7Sopenharmony_ci			else
3541e5c31af7Sopenharmony_ci			{
3542e5c31af7Sopenharmony_ci				DE_ASSERT(levelFilter == Sampler::LINEAR);
3543e5c31af7Sopenharmony_ci
3544e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses[CUBEFACE_LAST];
3545e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3546e5c31af7Sopenharmony_ci					faceAccesses[i] = getCubeArrayFaceAccess(levels, level, slice, (CubeFace)i);
3547e5c31af7Sopenharmony_ci
3548e5c31af7Sopenharmony_ci				return sampleCubeSeamlessLinear(faceAccesses, face, sampler, s, t, 0);
3549e5c31af7Sopenharmony_ci			}
3550e5c31af7Sopenharmony_ci		}
3551e5c31af7Sopenharmony_ci
3552e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_LINEAR:
3553e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_LINEAR:
3554e5c31af7Sopenharmony_ci		{
3555e5c31af7Sopenharmony_ci			int						maxLevel	= (int)numLevels-1;
3556e5c31af7Sopenharmony_ci			int						level0		= deClamp32((int)deFloatFloor(lod), 0, maxLevel);
3557e5c31af7Sopenharmony_ci			int						level1		= de::min(maxLevel, level0 + 1);
3558e5c31af7Sopenharmony_ci			Sampler::FilterMode		levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_LINEAR) ? Sampler::LINEAR : Sampler::NEAREST;
3559e5c31af7Sopenharmony_ci			float					f			= deFloatFrac(lod);
3560e5c31af7Sopenharmony_ci			Vec4					t0;
3561e5c31af7Sopenharmony_ci			Vec4					t1;
3562e5c31af7Sopenharmony_ci
3563e5c31af7Sopenharmony_ci			if (levelFilter == Sampler::NEAREST)
3564e5c31af7Sopenharmony_ci			{
3565e5c31af7Sopenharmony_ci				t0 = sampleCubeSeamlessNearest(levels[level0], sampler, s, t, faceDepth);
3566e5c31af7Sopenharmony_ci				t1 = sampleCubeSeamlessNearest(levels[level1], sampler, s, t, faceDepth);
3567e5c31af7Sopenharmony_ci			}
3568e5c31af7Sopenharmony_ci			else
3569e5c31af7Sopenharmony_ci			{
3570e5c31af7Sopenharmony_ci				DE_ASSERT(levelFilter == Sampler::LINEAR);
3571e5c31af7Sopenharmony_ci
3572e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses0[CUBEFACE_LAST];
3573e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses1[CUBEFACE_LAST];
3574e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3575e5c31af7Sopenharmony_ci				{
3576e5c31af7Sopenharmony_ci					faceAccesses0[i] = getCubeArrayFaceAccess(levels, level0, slice, (CubeFace)i);
3577e5c31af7Sopenharmony_ci					faceAccesses1[i] = getCubeArrayFaceAccess(levels, level1, slice, (CubeFace)i);
3578e5c31af7Sopenharmony_ci				}
3579e5c31af7Sopenharmony_ci
3580e5c31af7Sopenharmony_ci				t0 = sampleCubeSeamlessLinear(faceAccesses0, face, sampler, s, t, 0);
3581e5c31af7Sopenharmony_ci				t1 = sampleCubeSeamlessLinear(faceAccesses1, face, sampler, s, t, 0);
3582e5c31af7Sopenharmony_ci			}
3583e5c31af7Sopenharmony_ci
3584e5c31af7Sopenharmony_ci			return t0*(1.0f - f) + t1*f;
3585e5c31af7Sopenharmony_ci		}
3586e5c31af7Sopenharmony_ci
3587e5c31af7Sopenharmony_ci		default:
3588e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
3589e5c31af7Sopenharmony_ci			return Vec4(0.0f);
3590e5c31af7Sopenharmony_ci	}
3591e5c31af7Sopenharmony_ci}
3592e5c31af7Sopenharmony_ci
3593e5c31af7Sopenharmony_cistatic float sampleCubeArraySeamlessCompare (const ConstPixelBufferAccess* const levels, int numLevels, int slice, CubeFace face, const Sampler& sampler, float ref, float s, float t, float lod)
3594e5c31af7Sopenharmony_ci{
3595e5c31af7Sopenharmony_ci	const int			faceDepth	= (slice * 6) + getCubeArrayFaceIndex(face);
3596e5c31af7Sopenharmony_ci	const bool			magnified	= lod <= sampler.lodThreshold;
3597e5c31af7Sopenharmony_ci	Sampler::FilterMode	filterMode	= magnified ? sampler.magFilter : sampler.minFilter;
3598e5c31af7Sopenharmony_ci
3599e5c31af7Sopenharmony_ci	switch (filterMode)
3600e5c31af7Sopenharmony_ci	{
3601e5c31af7Sopenharmony_ci		case Sampler::NEAREST:
3602e5c31af7Sopenharmony_ci			return sampleCubeSeamlessNearestCompare(levels[0], sampler, ref, s, t, faceDepth);
3603e5c31af7Sopenharmony_ci
3604e5c31af7Sopenharmony_ci		case Sampler::LINEAR:
3605e5c31af7Sopenharmony_ci		{
3606e5c31af7Sopenharmony_ci			ConstPixelBufferAccess faceAccesses[CUBEFACE_LAST];
3607e5c31af7Sopenharmony_ci			for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3608e5c31af7Sopenharmony_ci				faceAccesses[i] = getCubeArrayFaceAccess(levels, 0, slice, (CubeFace)i);
3609e5c31af7Sopenharmony_ci
3610e5c31af7Sopenharmony_ci			return sampleCubeSeamlessLinearCompare(faceAccesses, face, sampler, ref, s, t);
3611e5c31af7Sopenharmony_ci		}
3612e5c31af7Sopenharmony_ci
3613e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_NEAREST:
3614e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_NEAREST:
3615e5c31af7Sopenharmony_ci		{
3616e5c31af7Sopenharmony_ci			int						maxLevel	= (int)numLevels-1;
3617e5c31af7Sopenharmony_ci			int						level		= deClamp32((int)deFloatCeil(lod + 0.5f) - 1, 0, maxLevel);
3618e5c31af7Sopenharmony_ci			Sampler::FilterMode		levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_NEAREST) ? Sampler::LINEAR : Sampler::NEAREST;
3619e5c31af7Sopenharmony_ci
3620e5c31af7Sopenharmony_ci			if (levelFilter == Sampler::NEAREST)
3621e5c31af7Sopenharmony_ci				return sampleCubeSeamlessNearestCompare(levels[level], sampler, ref, s, t, faceDepth);
3622e5c31af7Sopenharmony_ci			else
3623e5c31af7Sopenharmony_ci			{
3624e5c31af7Sopenharmony_ci				DE_ASSERT(levelFilter == Sampler::LINEAR);
3625e5c31af7Sopenharmony_ci
3626e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses[CUBEFACE_LAST];
3627e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3628e5c31af7Sopenharmony_ci					faceAccesses[i] = getCubeArrayFaceAccess(levels, level, slice, (CubeFace)i);
3629e5c31af7Sopenharmony_ci
3630e5c31af7Sopenharmony_ci				return sampleCubeSeamlessLinearCompare(faceAccesses, face, sampler, ref, s, t);
3631e5c31af7Sopenharmony_ci			}
3632e5c31af7Sopenharmony_ci		}
3633e5c31af7Sopenharmony_ci
3634e5c31af7Sopenharmony_ci		case Sampler::NEAREST_MIPMAP_LINEAR:
3635e5c31af7Sopenharmony_ci		case Sampler::LINEAR_MIPMAP_LINEAR:
3636e5c31af7Sopenharmony_ci		{
3637e5c31af7Sopenharmony_ci			int						maxLevel	= (int)numLevels-1;
3638e5c31af7Sopenharmony_ci			int						level0		= deClamp32((int)deFloatFloor(lod), 0, maxLevel);
3639e5c31af7Sopenharmony_ci			int						level1		= de::min(maxLevel, level0 + 1);
3640e5c31af7Sopenharmony_ci			Sampler::FilterMode		levelFilter	= (filterMode == Sampler::LINEAR_MIPMAP_LINEAR) ? Sampler::LINEAR : Sampler::NEAREST;
3641e5c31af7Sopenharmony_ci			float					f			= deFloatFrac(lod);
3642e5c31af7Sopenharmony_ci			float					t0;
3643e5c31af7Sopenharmony_ci			float					t1;
3644e5c31af7Sopenharmony_ci
3645e5c31af7Sopenharmony_ci			if (levelFilter == Sampler::NEAREST)
3646e5c31af7Sopenharmony_ci			{
3647e5c31af7Sopenharmony_ci				t0 = sampleCubeSeamlessNearestCompare(levels[level0], sampler, ref, s, t, faceDepth);
3648e5c31af7Sopenharmony_ci				t1 = sampleCubeSeamlessNearestCompare(levels[level1], sampler, ref, s, t, faceDepth);
3649e5c31af7Sopenharmony_ci			}
3650e5c31af7Sopenharmony_ci			else
3651e5c31af7Sopenharmony_ci			{
3652e5c31af7Sopenharmony_ci				DE_ASSERT(levelFilter == Sampler::LINEAR);
3653e5c31af7Sopenharmony_ci
3654e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses0[CUBEFACE_LAST];
3655e5c31af7Sopenharmony_ci				ConstPixelBufferAccess faceAccesses1[CUBEFACE_LAST];
3656e5c31af7Sopenharmony_ci				for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3657e5c31af7Sopenharmony_ci				{
3658e5c31af7Sopenharmony_ci					faceAccesses0[i] = getCubeArrayFaceAccess(levels, level0, slice, (CubeFace)i);
3659e5c31af7Sopenharmony_ci					faceAccesses1[i] = getCubeArrayFaceAccess(levels, level1, slice, (CubeFace)i);
3660e5c31af7Sopenharmony_ci				}
3661e5c31af7Sopenharmony_ci
3662e5c31af7Sopenharmony_ci				t0 = sampleCubeSeamlessLinearCompare(faceAccesses0, face, sampler, ref, s, t);
3663e5c31af7Sopenharmony_ci				t1 = sampleCubeSeamlessLinearCompare(faceAccesses1, face, sampler, ref, s, t);
3664e5c31af7Sopenharmony_ci			}
3665e5c31af7Sopenharmony_ci
3666e5c31af7Sopenharmony_ci			return t0*(1.0f - f) + t1*f;
3667e5c31af7Sopenharmony_ci		}
3668e5c31af7Sopenharmony_ci
3669e5c31af7Sopenharmony_ci		default:
3670e5c31af7Sopenharmony_ci			DE_ASSERT(DE_FALSE);
3671e5c31af7Sopenharmony_ci			return 0.0f;
3672e5c31af7Sopenharmony_ci	}
3673e5c31af7Sopenharmony_ci}
3674e5c31af7Sopenharmony_ci
3675e5c31af7Sopenharmony_ciinline int computeMipPyramidLevels (int size)
3676e5c31af7Sopenharmony_ci{
3677e5c31af7Sopenharmony_ci	return deLog2Floor32(size)+1;
3678e5c31af7Sopenharmony_ci}
3679e5c31af7Sopenharmony_ci
3680e5c31af7Sopenharmony_ciinline int computeMipPyramidLevels (int width, int height)
3681e5c31af7Sopenharmony_ci{
3682e5c31af7Sopenharmony_ci	return deLog2Floor32(de::max(width, height))+1;
3683e5c31af7Sopenharmony_ci}
3684e5c31af7Sopenharmony_ci
3685e5c31af7Sopenharmony_ciinline int computeMipPyramidLevels (int width, int height, int depth)
3686e5c31af7Sopenharmony_ci{
3687e5c31af7Sopenharmony_ci	return deLog2Floor32(de::max(width, de::max(height, depth)))+1;
3688e5c31af7Sopenharmony_ci}
3689e5c31af7Sopenharmony_ci
3690e5c31af7Sopenharmony_ciinline int getMipPyramidLevelSize (int baseLevelSize, int levelNdx)
3691e5c31af7Sopenharmony_ci{
3692e5c31af7Sopenharmony_ci	return de::max(baseLevelSize >> levelNdx, 1);
3693e5c31af7Sopenharmony_ci}
3694e5c31af7Sopenharmony_ci
3695e5c31af7Sopenharmony_ci// TextureLevelPyramid
3696e5c31af7Sopenharmony_ci
3697e5c31af7Sopenharmony_ciTextureLevelPyramid::TextureLevelPyramid (const TextureFormat& format, int numLevels)
3698e5c31af7Sopenharmony_ci	: m_format	(format)
3699e5c31af7Sopenharmony_ci	, m_data	(numLevels)
3700e5c31af7Sopenharmony_ci	, m_access	(numLevels)
3701e5c31af7Sopenharmony_ci{
3702e5c31af7Sopenharmony_ci}
3703e5c31af7Sopenharmony_ci
3704e5c31af7Sopenharmony_ciTextureLevelPyramid::TextureLevelPyramid (const TextureLevelPyramid& other)
3705e5c31af7Sopenharmony_ci	: m_format	(other.m_format)
3706e5c31af7Sopenharmony_ci	, m_data	(other.getNumLevels())
3707e5c31af7Sopenharmony_ci	, m_access	(other.getNumLevels())
3708e5c31af7Sopenharmony_ci{
3709e5c31af7Sopenharmony_ci	for (int levelNdx = 0; levelNdx < other.getNumLevels(); levelNdx++)
3710e5c31af7Sopenharmony_ci	{
3711e5c31af7Sopenharmony_ci		if (!other.isLevelEmpty(levelNdx))
3712e5c31af7Sopenharmony_ci		{
3713e5c31af7Sopenharmony_ci			const tcu::ConstPixelBufferAccess& srcLevel = other.getLevel(levelNdx);
3714e5c31af7Sopenharmony_ci
3715e5c31af7Sopenharmony_ci			m_data[levelNdx] = other.m_data[levelNdx];
3716e5c31af7Sopenharmony_ci			m_access[levelNdx] = PixelBufferAccess(srcLevel.getFormat(), srcLevel.getWidth(), srcLevel.getHeight(), srcLevel.getDepth(), m_data[levelNdx].getPtr());
3717e5c31af7Sopenharmony_ci		}
3718e5c31af7Sopenharmony_ci	}
3719e5c31af7Sopenharmony_ci}
3720e5c31af7Sopenharmony_ci
3721e5c31af7Sopenharmony_ciTextureLevelPyramid& TextureLevelPyramid::operator= (const TextureLevelPyramid& other)
3722e5c31af7Sopenharmony_ci{
3723e5c31af7Sopenharmony_ci	if (this == &other)
3724e5c31af7Sopenharmony_ci		return *this;
3725e5c31af7Sopenharmony_ci
3726e5c31af7Sopenharmony_ci	m_format = other.m_format;
3727e5c31af7Sopenharmony_ci	m_data.resize(other.getNumLevels());
3728e5c31af7Sopenharmony_ci	m_access.resize(other.getNumLevels());
3729e5c31af7Sopenharmony_ci
3730e5c31af7Sopenharmony_ci	for (int levelNdx = 0; levelNdx < other.getNumLevels(); levelNdx++)
3731e5c31af7Sopenharmony_ci	{
3732e5c31af7Sopenharmony_ci		if (!other.isLevelEmpty(levelNdx))
3733e5c31af7Sopenharmony_ci		{
3734e5c31af7Sopenharmony_ci			const tcu::ConstPixelBufferAccess& srcLevel = other.getLevel(levelNdx);
3735e5c31af7Sopenharmony_ci
3736e5c31af7Sopenharmony_ci			m_data[levelNdx] = other.m_data[levelNdx];
3737e5c31af7Sopenharmony_ci			m_access[levelNdx] = PixelBufferAccess(srcLevel.getFormat(), srcLevel.getWidth(), srcLevel.getHeight(), srcLevel.getDepth(), m_data[levelNdx].getPtr());
3738e5c31af7Sopenharmony_ci		}
3739e5c31af7Sopenharmony_ci		else if (!isLevelEmpty(levelNdx))
3740e5c31af7Sopenharmony_ci			clearLevel(levelNdx);
3741e5c31af7Sopenharmony_ci	}
3742e5c31af7Sopenharmony_ci
3743e5c31af7Sopenharmony_ci	return *this;
3744e5c31af7Sopenharmony_ci}
3745e5c31af7Sopenharmony_ci
3746e5c31af7Sopenharmony_ciTextureLevelPyramid::~TextureLevelPyramid (void)
3747e5c31af7Sopenharmony_ci{
3748e5c31af7Sopenharmony_ci}
3749e5c31af7Sopenharmony_ci
3750e5c31af7Sopenharmony_civoid TextureLevelPyramid::allocLevel (int levelNdx, int width, int height, int depth)
3751e5c31af7Sopenharmony_ci{
3752e5c31af7Sopenharmony_ci	const int	size	= m_format.getPixelSize()*width*height*depth;
3753e5c31af7Sopenharmony_ci
3754e5c31af7Sopenharmony_ci	DE_ASSERT(isLevelEmpty(levelNdx));
3755e5c31af7Sopenharmony_ci
3756e5c31af7Sopenharmony_ci	m_data[levelNdx].setStorage(size);
3757e5c31af7Sopenharmony_ci	m_access[levelNdx] = PixelBufferAccess(m_format, width, height, depth, m_data[levelNdx].getPtr());
3758e5c31af7Sopenharmony_ci}
3759e5c31af7Sopenharmony_ci
3760e5c31af7Sopenharmony_civoid TextureLevelPyramid::clearLevel (int levelNdx)
3761e5c31af7Sopenharmony_ci{
3762e5c31af7Sopenharmony_ci	DE_ASSERT(!isLevelEmpty(levelNdx));
3763e5c31af7Sopenharmony_ci
3764e5c31af7Sopenharmony_ci	m_data[levelNdx].clear();
3765e5c31af7Sopenharmony_ci	m_access[levelNdx] = PixelBufferAccess();
3766e5c31af7Sopenharmony_ci}
3767e5c31af7Sopenharmony_ci
3768e5c31af7Sopenharmony_ci// Texture1D
3769e5c31af7Sopenharmony_ci
3770e5c31af7Sopenharmony_ciTexture1D::Texture1D (const TextureFormat& format, int width)
3771e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(format, computeMipPyramidLevels(width))
3772e5c31af7Sopenharmony_ci	, m_width				(width)
3773e5c31af7Sopenharmony_ci	, m_view				(getNumLevels(), getLevels())
3774e5c31af7Sopenharmony_ci{
3775e5c31af7Sopenharmony_ci}
3776e5c31af7Sopenharmony_ci
3777e5c31af7Sopenharmony_ciTexture1D::Texture1D (const Texture1D& other)
3778e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(other)
3779e5c31af7Sopenharmony_ci	, m_width				(other.m_width)
3780e5c31af7Sopenharmony_ci	, m_view				(getNumLevels(), getLevels())
3781e5c31af7Sopenharmony_ci{
3782e5c31af7Sopenharmony_ci}
3783e5c31af7Sopenharmony_ci
3784e5c31af7Sopenharmony_ciTexture1D& Texture1D::operator= (const Texture1D& other)
3785e5c31af7Sopenharmony_ci{
3786e5c31af7Sopenharmony_ci	if (this == &other)
3787e5c31af7Sopenharmony_ci		return *this;
3788e5c31af7Sopenharmony_ci
3789e5c31af7Sopenharmony_ci	TextureLevelPyramid::operator=(other);
3790e5c31af7Sopenharmony_ci
3791e5c31af7Sopenharmony_ci	m_width		= other.m_width;
3792e5c31af7Sopenharmony_ci	m_view		= Texture1DView(getNumLevels(), getLevels());
3793e5c31af7Sopenharmony_ci
3794e5c31af7Sopenharmony_ci	return *this;
3795e5c31af7Sopenharmony_ci}
3796e5c31af7Sopenharmony_ci
3797e5c31af7Sopenharmony_ciTexture1D::~Texture1D (void)
3798e5c31af7Sopenharmony_ci{
3799e5c31af7Sopenharmony_ci}
3800e5c31af7Sopenharmony_ci
3801e5c31af7Sopenharmony_civoid Texture1D::allocLevel (int levelNdx)
3802e5c31af7Sopenharmony_ci{
3803e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(levelNdx, 0, getNumLevels()));
3804e5c31af7Sopenharmony_ci
3805e5c31af7Sopenharmony_ci	const int width = getMipPyramidLevelSize(m_width, levelNdx);
3806e5c31af7Sopenharmony_ci
3807e5c31af7Sopenharmony_ci	TextureLevelPyramid::allocLevel(levelNdx, width, 1, 1);
3808e5c31af7Sopenharmony_ci}
3809e5c31af7Sopenharmony_ci
3810e5c31af7Sopenharmony_ci// Texture2D
3811e5c31af7Sopenharmony_ci
3812e5c31af7Sopenharmony_ciTexture2D::Texture2D (const TextureFormat& format, int width, int height, bool es2)
3813e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(format, computeMipPyramidLevels(width, height))
3814e5c31af7Sopenharmony_ci	, m_yuvTextureUsed	(false)
3815e5c31af7Sopenharmony_ci	, m_width		(width)
3816e5c31af7Sopenharmony_ci	, m_height		(height)
3817e5c31af7Sopenharmony_ci	, m_view		(getNumLevels(), getLevels(), es2)
3818e5c31af7Sopenharmony_ci{
3819e5c31af7Sopenharmony_ci}
3820e5c31af7Sopenharmony_ci
3821e5c31af7Sopenharmony_ciTexture2D::Texture2D (const TextureFormat& format, int width, int height, int mipmaps)
3822e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(format, mipmaps)
3823e5c31af7Sopenharmony_ci	, m_yuvTextureUsed	(false)
3824e5c31af7Sopenharmony_ci	, m_width		(width)
3825e5c31af7Sopenharmony_ci	, m_height		(height)
3826e5c31af7Sopenharmony_ci	, m_view		(getNumLevels(), getLevels())
3827e5c31af7Sopenharmony_ci{
3828e5c31af7Sopenharmony_ci}
3829e5c31af7Sopenharmony_ci
3830e5c31af7Sopenharmony_ciTexture2D::Texture2D (const Texture2D& other)
3831e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(other)
3832e5c31af7Sopenharmony_ci	, m_yuvTextureUsed	(other.m_yuvTextureUsed)
3833e5c31af7Sopenharmony_ci	, m_width		(other.m_width)
3834e5c31af7Sopenharmony_ci	, m_height		(other.m_height)
3835e5c31af7Sopenharmony_ci	, m_view		(getNumLevels(), getLevels(), other.getView().isES2())
3836e5c31af7Sopenharmony_ci{
3837e5c31af7Sopenharmony_ci}
3838e5c31af7Sopenharmony_ci
3839e5c31af7Sopenharmony_ciTexture2D& Texture2D::operator= (const Texture2D& other)
3840e5c31af7Sopenharmony_ci{
3841e5c31af7Sopenharmony_ci	if (this == &other)
3842e5c31af7Sopenharmony_ci		return *this;
3843e5c31af7Sopenharmony_ci
3844e5c31af7Sopenharmony_ci	TextureLevelPyramid::operator=(other);
3845e5c31af7Sopenharmony_ci
3846e5c31af7Sopenharmony_ci	m_width		= other.m_width;
3847e5c31af7Sopenharmony_ci	m_height	= other.m_height;
3848e5c31af7Sopenharmony_ci	m_view		= Texture2DView(getNumLevels(), getLevels(), other.getView().isES2());
3849e5c31af7Sopenharmony_ci	m_yuvTextureUsed = other.m_yuvTextureUsed;
3850e5c31af7Sopenharmony_ci	return *this;
3851e5c31af7Sopenharmony_ci}
3852e5c31af7Sopenharmony_ci
3853e5c31af7Sopenharmony_ciTexture2D::~Texture2D (void)
3854e5c31af7Sopenharmony_ci{
3855e5c31af7Sopenharmony_ci}
3856e5c31af7Sopenharmony_ci
3857e5c31af7Sopenharmony_civoid Texture2D::allocLevel (int levelNdx)
3858e5c31af7Sopenharmony_ci{
3859e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(levelNdx, 0, getNumLevels()));
3860e5c31af7Sopenharmony_ci
3861e5c31af7Sopenharmony_ci	const int	width	= getMipPyramidLevelSize(m_width, levelNdx);
3862e5c31af7Sopenharmony_ci	const int	height	= getMipPyramidLevelSize(m_height, levelNdx);
3863e5c31af7Sopenharmony_ci
3864e5c31af7Sopenharmony_ci	TextureLevelPyramid::allocLevel(levelNdx, width, height, 1);
3865e5c31af7Sopenharmony_ci}
3866e5c31af7Sopenharmony_ci
3867e5c31af7Sopenharmony_ci// TextureCubeView
3868e5c31af7Sopenharmony_ci
3869e5c31af7Sopenharmony_ciTextureCubeView::TextureCubeView (void)
3870e5c31af7Sopenharmony_ci	: m_numLevels(0)
3871e5c31af7Sopenharmony_ci	, m_es2(false)
3872e5c31af7Sopenharmony_ci	, m_minLodParams (DE_NULL)
3873e5c31af7Sopenharmony_ci{
3874e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < CUBEFACE_LAST; ndx++)
3875e5c31af7Sopenharmony_ci		m_levels[ndx] = DE_NULL;
3876e5c31af7Sopenharmony_ci}
3877e5c31af7Sopenharmony_ci
3878e5c31af7Sopenharmony_ciTextureCubeView::TextureCubeView (int numLevels, const ConstPixelBufferAccess* const (&levels) [CUBEFACE_LAST], bool es2, ImageViewMinLodParams *minLodParams)
3879e5c31af7Sopenharmony_ci	: m_numLevels(numLevels)
3880e5c31af7Sopenharmony_ci	, m_es2(es2)
3881e5c31af7Sopenharmony_ci	, m_minLodParams(minLodParams)
3882e5c31af7Sopenharmony_ci{
3883e5c31af7Sopenharmony_ci	for (int ndx = 0; ndx < CUBEFACE_LAST; ndx++)
3884e5c31af7Sopenharmony_ci		m_levels[ndx] = levels[ndx];
3885e5c31af7Sopenharmony_ci}
3886e5c31af7Sopenharmony_ci
3887e5c31af7Sopenharmony_citcu::Vec4 TextureCubeView::sample (const Sampler& sampler, float s, float t, float r, float lod) const
3888e5c31af7Sopenharmony_ci{
3889e5c31af7Sopenharmony_ci	DE_ASSERT(sampler.compare == Sampler::COMPAREMODE_NONE);
3890e5c31af7Sopenharmony_ci
3891e5c31af7Sopenharmony_ci	// Computes (face, s, t).
3892e5c31af7Sopenharmony_ci	const CubeFaceFloatCoords coords = getCubeFaceCoords(Vec3(s, t, r));
3893e5c31af7Sopenharmony_ci	if (sampler.seamlessCubeMap)
3894e5c31af7Sopenharmony_ci		return sampleLevelArrayCubeSeamless(m_levels, m_numLevels, coords.face, sampler, coords.s, coords.t, 0 /* depth */, lod, m_minLodParams);
3895e5c31af7Sopenharmony_ci	else
3896e5c31af7Sopenharmony_ci		return sampleLevelArray2D(m_levels[coords.face], m_numLevels, sampler, coords.s, coords.t, 0 /* depth */, lod, m_es2, m_minLodParams);
3897e5c31af7Sopenharmony_ci}
3898e5c31af7Sopenharmony_ci
3899e5c31af7Sopenharmony_cifloat TextureCubeView::sampleCompare (const Sampler& sampler, float ref, float s, float t, float r, float lod) const
3900e5c31af7Sopenharmony_ci{
3901e5c31af7Sopenharmony_ci	DE_ASSERT(sampler.compare != Sampler::COMPAREMODE_NONE);
3902e5c31af7Sopenharmony_ci
3903e5c31af7Sopenharmony_ci	// Computes (face, s, t).
3904e5c31af7Sopenharmony_ci	const CubeFaceFloatCoords coords = getCubeFaceCoords(Vec3(s, t, r));
3905e5c31af7Sopenharmony_ci	if (sampler.seamlessCubeMap)
3906e5c31af7Sopenharmony_ci		return sampleLevelArrayCubeSeamlessCompare(m_levels, m_numLevels, coords.face, sampler, ref, coords.s, coords.t, lod);
3907e5c31af7Sopenharmony_ci	else
3908e5c31af7Sopenharmony_ci		return sampleLevelArray2DCompare(m_levels[coords.face], m_numLevels, sampler, ref, coords.s, coords.t, lod, IVec3(0, 0, 0));
3909e5c31af7Sopenharmony_ci}
3910e5c31af7Sopenharmony_ci
3911e5c31af7Sopenharmony_ciVec4 TextureCubeView::gather (const Sampler& sampler, float s, float t, float r, int componentNdx) const
3912e5c31af7Sopenharmony_ci{
3913e5c31af7Sopenharmony_ci	DE_ASSERT(sampler.compare == Sampler::COMPAREMODE_NONE);
3914e5c31af7Sopenharmony_ci
3915e5c31af7Sopenharmony_ci	ConstPixelBufferAccess faceAccesses[CUBEFACE_LAST];
3916e5c31af7Sopenharmony_ci	for (int i = 0; i < (int)CUBEFACE_LAST; i++)
3917e5c31af7Sopenharmony_ci		faceAccesses[i] = m_levels[i][0];
3918e5c31af7Sopenharmony_ci
3919e5c31af7Sopenharmony_ci	const CubeFaceFloatCoords	coords	= getCubeFaceCoords(Vec3(s, t, r));
3920e5c31af7Sopenharmony_ci	const int					size	= faceAccesses[0].getWidth();
3921e5c31af7Sopenharmony_ci	// Non-normalized coordinates.
3922e5c31af7Sopenharmony_ci	float						u		= coords.s;
3923e5c31af7Sopenharmony_ci	float						v		= coords.t;
3924e5c31af7Sopenharmony_ci
3925e5c31af7Sopenharmony_ci	if (sampler.normalizedCoords)
3926e5c31af7Sopenharmony_ci	{
3927e5c31af7Sopenharmony_ci		u = unnormalize(sampler.wrapS, coords.s, size);
3928e5c31af7Sopenharmony_ci		v = unnormalize(sampler.wrapT, coords.t, size);
3929e5c31af7Sopenharmony_ci	}
3930e5c31af7Sopenharmony_ci
3931e5c31af7Sopenharmony_ci	Vec4 sampleColors[4];
3932e5c31af7Sopenharmony_ci	getCubeLinearSamples(faceAccesses, coords.face, u, v, 0, sampleColors);
3933e5c31af7Sopenharmony_ci
3934e5c31af7Sopenharmony_ci	const int	sampleIndices[4] = { 2, 3, 1, 0 }; // \note Gather returns the samples in a non-obvious order.
3935e5c31af7Sopenharmony_ci	Vec4		result;
3936e5c31af7Sopenharmony_ci	for (int i = 0; i < 4; i++)
3937e5c31af7Sopenharmony_ci		result[i] = sampleColors[sampleIndices[i]][componentNdx];
3938e5c31af7Sopenharmony_ci
3939e5c31af7Sopenharmony_ci	return result;
3940e5c31af7Sopenharmony_ci}
3941e5c31af7Sopenharmony_ci
3942e5c31af7Sopenharmony_ciVec4 TextureCubeView::gatherCompare (const Sampler& sampler, float ref, float s, float t, float r) const
3943e5c31af7Sopenharmony_ci{
3944e5c31af7Sopenharmony_ci	DE_ASSERT(sampler.compare != Sampler::COMPAREMODE_NONE);
3945e5c31af7Sopenharmony_ci	DE_ASSERT(m_levels[0][0].getFormat().order == TextureFormat::D || m_levels[0][0].getFormat().order == TextureFormat::DS);
3946e5c31af7Sopenharmony_ci	DE_ASSERT(sampler.compareChannel == 0);
3947e5c31af7Sopenharmony_ci
3948e5c31af7Sopenharmony_ci	Sampler noCompareSampler = sampler;
3949e5c31af7Sopenharmony_ci	noCompareSampler.compare = Sampler::COMPAREMODE_NONE;
3950e5c31af7Sopenharmony_ci
3951e5c31af7Sopenharmony_ci	const Vec4 gathered			= gather(noCompareSampler, s, t, r, 0 /* component 0: depth */);
3952e5c31af7Sopenharmony_ci	const bool isFixedPoint		= isFixedPointDepthTextureFormat(m_levels[0][0].getFormat());
3953e5c31af7Sopenharmony_ci	Vec4 result;
3954e5c31af7Sopenharmony_ci	for (int i = 0; i < 4; i++)
3955e5c31af7Sopenharmony_ci		result[i] = execCompare(gathered, sampler.compare, i, ref, isFixedPoint);
3956e5c31af7Sopenharmony_ci
3957e5c31af7Sopenharmony_ci	return result;
3958e5c31af7Sopenharmony_ci}
3959e5c31af7Sopenharmony_ci
3960e5c31af7Sopenharmony_ci// TextureCube
3961e5c31af7Sopenharmony_ci
3962e5c31af7Sopenharmony_ciTextureCube::TextureCube (const TextureFormat& format, int size, bool es2)
3963e5c31af7Sopenharmony_ci	: m_format	(format)
3964e5c31af7Sopenharmony_ci	, m_size	(size)
3965e5c31af7Sopenharmony_ci{
3966e5c31af7Sopenharmony_ci	const int						numLevels		= computeMipPyramidLevels(m_size);
3967e5c31af7Sopenharmony_ci	const ConstPixelBufferAccess*	levels[CUBEFACE_LAST];
3968e5c31af7Sopenharmony_ci
3969e5c31af7Sopenharmony_ci	for (int face = 0; face < CUBEFACE_LAST; face++)
3970e5c31af7Sopenharmony_ci	{
3971e5c31af7Sopenharmony_ci		m_data[face].resize(numLevels);
3972e5c31af7Sopenharmony_ci		m_access[face].resize(numLevels);
3973e5c31af7Sopenharmony_ci		levels[face] = &m_access[face][0];
3974e5c31af7Sopenharmony_ci	}
3975e5c31af7Sopenharmony_ci
3976e5c31af7Sopenharmony_ci	m_view = TextureCubeView(numLevels, levels, es2);
3977e5c31af7Sopenharmony_ci}
3978e5c31af7Sopenharmony_ci
3979e5c31af7Sopenharmony_ciTextureCube::TextureCube (const TextureCube& other)
3980e5c31af7Sopenharmony_ci	: m_format	(other.m_format)
3981e5c31af7Sopenharmony_ci	, m_size	(other.m_size)
3982e5c31af7Sopenharmony_ci{
3983e5c31af7Sopenharmony_ci	const int						numLevels		= computeMipPyramidLevels(m_size);
3984e5c31af7Sopenharmony_ci	const ConstPixelBufferAccess*	levels[CUBEFACE_LAST];
3985e5c31af7Sopenharmony_ci
3986e5c31af7Sopenharmony_ci	for (int face = 0; face < CUBEFACE_LAST; face++)
3987e5c31af7Sopenharmony_ci	{
3988e5c31af7Sopenharmony_ci		m_data[face].resize(numLevels);
3989e5c31af7Sopenharmony_ci		m_access[face].resize(numLevels);
3990e5c31af7Sopenharmony_ci		levels[face] = &m_access[face][0];
3991e5c31af7Sopenharmony_ci	}
3992e5c31af7Sopenharmony_ci
3993e5c31af7Sopenharmony_ci	m_view = TextureCubeView(numLevels, levels, other.getView().isES2());
3994e5c31af7Sopenharmony_ci
3995e5c31af7Sopenharmony_ci	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
3996e5c31af7Sopenharmony_ci	{
3997e5c31af7Sopenharmony_ci		for (int face = 0; face < CUBEFACE_LAST; face++)
3998e5c31af7Sopenharmony_ci		{
3999e5c31af7Sopenharmony_ci			if (!other.isLevelEmpty((CubeFace)face, levelNdx))
4000e5c31af7Sopenharmony_ci			{
4001e5c31af7Sopenharmony_ci				allocLevel((CubeFace)face, levelNdx);
4002e5c31af7Sopenharmony_ci				copy(getLevelFace(levelNdx, (CubeFace)face),
4003e5c31af7Sopenharmony_ci					 other.getLevelFace(levelNdx, (CubeFace)face));
4004e5c31af7Sopenharmony_ci			}
4005e5c31af7Sopenharmony_ci		}
4006e5c31af7Sopenharmony_ci	}
4007e5c31af7Sopenharmony_ci}
4008e5c31af7Sopenharmony_ci
4009e5c31af7Sopenharmony_ciTextureCube& TextureCube::operator= (const TextureCube& other)
4010e5c31af7Sopenharmony_ci{
4011e5c31af7Sopenharmony_ci	if (this == &other)
4012e5c31af7Sopenharmony_ci		return *this;
4013e5c31af7Sopenharmony_ci
4014e5c31af7Sopenharmony_ci	const int						numLevels		= computeMipPyramidLevels(other.m_size);
4015e5c31af7Sopenharmony_ci	const ConstPixelBufferAccess*	levels[CUBEFACE_LAST];
4016e5c31af7Sopenharmony_ci
4017e5c31af7Sopenharmony_ci	for (int face = 0; face < CUBEFACE_LAST; face++)
4018e5c31af7Sopenharmony_ci	{
4019e5c31af7Sopenharmony_ci		m_data[face].resize(numLevels);
4020e5c31af7Sopenharmony_ci		m_access[face].resize(numLevels);
4021e5c31af7Sopenharmony_ci		levels[face] = &m_access[face][0];
4022e5c31af7Sopenharmony_ci	}
4023e5c31af7Sopenharmony_ci
4024e5c31af7Sopenharmony_ci	m_format	= other.m_format;
4025e5c31af7Sopenharmony_ci	m_size		= other.m_size;
4026e5c31af7Sopenharmony_ci	m_view		= TextureCubeView(numLevels, levels, other.getView().isES2());
4027e5c31af7Sopenharmony_ci
4028e5c31af7Sopenharmony_ci	for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
4029e5c31af7Sopenharmony_ci	{
4030e5c31af7Sopenharmony_ci		for (int face = 0; face < CUBEFACE_LAST; face++)
4031e5c31af7Sopenharmony_ci		{
4032e5c31af7Sopenharmony_ci			if (!isLevelEmpty((CubeFace)face, levelNdx))
4033e5c31af7Sopenharmony_ci				clearLevel((CubeFace)face, levelNdx);
4034e5c31af7Sopenharmony_ci
4035e5c31af7Sopenharmony_ci			if (!other.isLevelEmpty((CubeFace)face, levelNdx))
4036e5c31af7Sopenharmony_ci			{
4037e5c31af7Sopenharmony_ci				allocLevel((CubeFace)face, levelNdx);
4038e5c31af7Sopenharmony_ci				copy(getLevelFace(levelNdx, (CubeFace)face),
4039e5c31af7Sopenharmony_ci					 other.getLevelFace(levelNdx, (CubeFace)face));
4040e5c31af7Sopenharmony_ci			}
4041e5c31af7Sopenharmony_ci		}
4042e5c31af7Sopenharmony_ci	}
4043e5c31af7Sopenharmony_ci
4044e5c31af7Sopenharmony_ci	return *this;
4045e5c31af7Sopenharmony_ci}
4046e5c31af7Sopenharmony_ci
4047e5c31af7Sopenharmony_ciTextureCube::~TextureCube (void)
4048e5c31af7Sopenharmony_ci{
4049e5c31af7Sopenharmony_ci}
4050e5c31af7Sopenharmony_ci
4051e5c31af7Sopenharmony_civoid TextureCube::allocLevel (tcu::CubeFace face, int levelNdx)
4052e5c31af7Sopenharmony_ci{
4053e5c31af7Sopenharmony_ci	const int	size		= getMipPyramidLevelSize(m_size, levelNdx);
4054e5c31af7Sopenharmony_ci	const int	dataSize	= m_format.getPixelSize()*size*size;
4055e5c31af7Sopenharmony_ci	DE_ASSERT(isLevelEmpty(face, levelNdx));
4056e5c31af7Sopenharmony_ci
4057e5c31af7Sopenharmony_ci	m_data[face][levelNdx].setStorage(dataSize);
4058e5c31af7Sopenharmony_ci	m_access[face][levelNdx] = PixelBufferAccess(m_format, size, size, 1, m_data[face][levelNdx].getPtr());
4059e5c31af7Sopenharmony_ci}
4060e5c31af7Sopenharmony_ci
4061e5c31af7Sopenharmony_civoid TextureCube::clearLevel (tcu::CubeFace face, int levelNdx)
4062e5c31af7Sopenharmony_ci{
4063e5c31af7Sopenharmony_ci	DE_ASSERT(!isLevelEmpty(face, levelNdx));
4064e5c31af7Sopenharmony_ci	m_data[face][levelNdx].clear();
4065e5c31af7Sopenharmony_ci	m_access[face][levelNdx] = PixelBufferAccess();
4066e5c31af7Sopenharmony_ci}
4067e5c31af7Sopenharmony_ci
4068e5c31af7Sopenharmony_ci// Texture1DArrayView
4069e5c31af7Sopenharmony_ci
4070e5c31af7Sopenharmony_ciTexture1DArrayView::Texture1DArrayView (int numLevels, const ConstPixelBufferAccess* levels, bool es2 DE_UNUSED_ATTR, ImageViewMinLodParams* minLodParams DE_UNUSED_ATTR)
4071e5c31af7Sopenharmony_ci	: m_numLevels	(numLevels)
4072e5c31af7Sopenharmony_ci	, m_levels		(levels)
4073e5c31af7Sopenharmony_ci{
4074e5c31af7Sopenharmony_ci}
4075e5c31af7Sopenharmony_ci
4076e5c31af7Sopenharmony_ciinline int Texture1DArrayView::selectLayer (float t) const
4077e5c31af7Sopenharmony_ci{
4078e5c31af7Sopenharmony_ci	DE_ASSERT(m_numLevels > 0 && m_levels);
4079e5c31af7Sopenharmony_ci	return de::clamp(deFloorFloatToInt32(t + 0.5f), 0, m_levels[0].getHeight()-1);
4080e5c31af7Sopenharmony_ci}
4081e5c31af7Sopenharmony_ci
4082e5c31af7Sopenharmony_ciVec4 Texture1DArrayView::sample (const Sampler& sampler, float s, float t, float lod) const
4083e5c31af7Sopenharmony_ci{
4084e5c31af7Sopenharmony_ci	return sampleLevelArray1D(m_levels, m_numLevels, sampler, s, selectLayer(t), lod);
4085e5c31af7Sopenharmony_ci}
4086e5c31af7Sopenharmony_ci
4087e5c31af7Sopenharmony_ciVec4 Texture1DArrayView::sampleOffset (const Sampler& sampler, float s, float t, float lod, deInt32 offset) const
4088e5c31af7Sopenharmony_ci{
4089e5c31af7Sopenharmony_ci	return sampleLevelArray1DOffset(m_levels, m_numLevels, sampler, s, lod, IVec2(offset, selectLayer(t)));
4090e5c31af7Sopenharmony_ci}
4091e5c31af7Sopenharmony_ci
4092e5c31af7Sopenharmony_cifloat Texture1DArrayView::sampleCompare (const Sampler& sampler, float ref, float s, float t, float lod) const
4093e5c31af7Sopenharmony_ci{
4094e5c31af7Sopenharmony_ci	return sampleLevelArray1DCompare(m_levels, m_numLevels, sampler, ref, s, lod, IVec2(0, selectLayer(t)));
4095e5c31af7Sopenharmony_ci}
4096e5c31af7Sopenharmony_ci
4097e5c31af7Sopenharmony_cifloat Texture1DArrayView::sampleCompareOffset (const Sampler& sampler, float ref, float s, float t, float lod, deInt32 offset) const
4098e5c31af7Sopenharmony_ci{
4099e5c31af7Sopenharmony_ci	return sampleLevelArray1DCompare(m_levels, m_numLevels, sampler, ref, s, lod, IVec2(offset, selectLayer(t)));
4100e5c31af7Sopenharmony_ci}
4101e5c31af7Sopenharmony_ci
4102e5c31af7Sopenharmony_ci// Texture2DArrayView
4103e5c31af7Sopenharmony_ci
4104e5c31af7Sopenharmony_ciTexture2DArrayView::Texture2DArrayView (int numLevels, const ConstPixelBufferAccess* levels, bool es2 DE_UNUSED_ATTR, ImageViewMinLodParams* minLodParams DE_UNUSED_ATTR)
4105e5c31af7Sopenharmony_ci	: m_numLevels	(numLevels)
4106e5c31af7Sopenharmony_ci	, m_levels		(levels)
4107e5c31af7Sopenharmony_ci{
4108e5c31af7Sopenharmony_ci}
4109e5c31af7Sopenharmony_ci
4110e5c31af7Sopenharmony_ciinline int Texture2DArrayView::selectLayer (float r) const
4111e5c31af7Sopenharmony_ci{
4112e5c31af7Sopenharmony_ci	DE_ASSERT(m_numLevels > 0 && m_levels);
4113e5c31af7Sopenharmony_ci	return de::clamp(deFloorFloatToInt32(r + 0.5f), 0, m_levels[0].getDepth()-1);
4114e5c31af7Sopenharmony_ci}
4115e5c31af7Sopenharmony_ci
4116e5c31af7Sopenharmony_ciVec4 Texture2DArrayView::sample (const Sampler& sampler, float s, float t, float r, float lod) const
4117e5c31af7Sopenharmony_ci{
4118e5c31af7Sopenharmony_ci	return sampleLevelArray2D(m_levels, m_numLevels, sampler, s, t, selectLayer(r), lod);
4119e5c31af7Sopenharmony_ci}
4120e5c31af7Sopenharmony_ci
4121e5c31af7Sopenharmony_cifloat Texture2DArrayView::sampleCompare (const Sampler& sampler, float ref, float s, float t, float r, float lod) const
4122e5c31af7Sopenharmony_ci{
4123e5c31af7Sopenharmony_ci	return sampleLevelArray2DCompare(m_levels, m_numLevels, sampler, ref, s, t, lod, IVec3(0, 0, selectLayer(r)));
4124e5c31af7Sopenharmony_ci}
4125e5c31af7Sopenharmony_ci
4126e5c31af7Sopenharmony_ciVec4 Texture2DArrayView::sampleOffset (const Sampler& sampler, float s, float t, float r, float lod, const IVec2& offset) const
4127e5c31af7Sopenharmony_ci{
4128e5c31af7Sopenharmony_ci	return sampleLevelArray2DOffset(m_levels, m_numLevels, sampler, s, t, lod, IVec3(offset.x(), offset.y(), selectLayer(r)));
4129e5c31af7Sopenharmony_ci}
4130e5c31af7Sopenharmony_ci
4131e5c31af7Sopenharmony_cifloat Texture2DArrayView::sampleCompareOffset (const Sampler& sampler, float ref, float s, float t, float r, float lod, const IVec2& offset) const
4132e5c31af7Sopenharmony_ci{
4133e5c31af7Sopenharmony_ci	return sampleLevelArray2DCompare(m_levels, m_numLevels, sampler, ref, s, t, lod, IVec3(offset.x(), offset.y(), selectLayer(r)));
4134e5c31af7Sopenharmony_ci}
4135e5c31af7Sopenharmony_ci
4136e5c31af7Sopenharmony_ciVec4 Texture2DArrayView::gatherOffsets (const Sampler& sampler, float s, float t, float r, int componentNdx, const IVec2 (&offsets)[4]) const
4137e5c31af7Sopenharmony_ci{
4138e5c31af7Sopenharmony_ci	return gatherArray2DOffsets(m_levels[0], sampler, s, t, selectLayer(r), componentNdx, offsets);
4139e5c31af7Sopenharmony_ci}
4140e5c31af7Sopenharmony_ci
4141e5c31af7Sopenharmony_ciVec4 Texture2DArrayView::gatherOffsetsCompare (const Sampler& sampler, float ref, float s, float t, float r, const IVec2 (&offsets)[4]) const
4142e5c31af7Sopenharmony_ci{
4143e5c31af7Sopenharmony_ci	return gatherArray2DOffsetsCompare(m_levels[0], sampler, ref, s, t, selectLayer(r), offsets);
4144e5c31af7Sopenharmony_ci}
4145e5c31af7Sopenharmony_ci
4146e5c31af7Sopenharmony_ci// Texture1DArray
4147e5c31af7Sopenharmony_ci
4148e5c31af7Sopenharmony_ciTexture1DArray::Texture1DArray (const TextureFormat& format, int width, int numLayers)
4149e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(format, computeMipPyramidLevels(width))
4150e5c31af7Sopenharmony_ci	, m_width				(width)
4151e5c31af7Sopenharmony_ci	, m_numLayers			(numLayers)
4152e5c31af7Sopenharmony_ci	, m_view				(getNumLevels(), getLevels())
4153e5c31af7Sopenharmony_ci{
4154e5c31af7Sopenharmony_ci}
4155e5c31af7Sopenharmony_ci
4156e5c31af7Sopenharmony_ciTexture1DArray::Texture1DArray (const Texture1DArray& other)
4157e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(other)
4158e5c31af7Sopenharmony_ci	, m_width				(other.m_width)
4159e5c31af7Sopenharmony_ci	, m_numLayers			(other.m_numLayers)
4160e5c31af7Sopenharmony_ci	, m_view				(getNumLevels(), getLevels())
4161e5c31af7Sopenharmony_ci{
4162e5c31af7Sopenharmony_ci}
4163e5c31af7Sopenharmony_ci
4164e5c31af7Sopenharmony_ciTexture1DArray& Texture1DArray::operator= (const Texture1DArray& other)
4165e5c31af7Sopenharmony_ci{
4166e5c31af7Sopenharmony_ci	if (this == &other)
4167e5c31af7Sopenharmony_ci		return *this;
4168e5c31af7Sopenharmony_ci
4169e5c31af7Sopenharmony_ci	TextureLevelPyramid::operator=(other);
4170e5c31af7Sopenharmony_ci
4171e5c31af7Sopenharmony_ci	m_width		= other.m_width;
4172e5c31af7Sopenharmony_ci	m_numLayers	= other.m_numLayers;
4173e5c31af7Sopenharmony_ci	m_view		= Texture1DArrayView(getNumLevels(), getLevels());
4174e5c31af7Sopenharmony_ci
4175e5c31af7Sopenharmony_ci	return *this;
4176e5c31af7Sopenharmony_ci}
4177e5c31af7Sopenharmony_ci
4178e5c31af7Sopenharmony_ciTexture1DArray::~Texture1DArray (void)
4179e5c31af7Sopenharmony_ci{
4180e5c31af7Sopenharmony_ci}
4181e5c31af7Sopenharmony_ci
4182e5c31af7Sopenharmony_civoid Texture1DArray::allocLevel (int levelNdx)
4183e5c31af7Sopenharmony_ci{
4184e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(levelNdx, 0, getNumLevels()));
4185e5c31af7Sopenharmony_ci
4186e5c31af7Sopenharmony_ci	const int width = getMipPyramidLevelSize(m_width, levelNdx);
4187e5c31af7Sopenharmony_ci
4188e5c31af7Sopenharmony_ci	TextureLevelPyramid::allocLevel(levelNdx, width, m_numLayers, 1);
4189e5c31af7Sopenharmony_ci}
4190e5c31af7Sopenharmony_ci
4191e5c31af7Sopenharmony_ci// Texture2DArray
4192e5c31af7Sopenharmony_ci
4193e5c31af7Sopenharmony_ciTexture2DArray::Texture2DArray (const TextureFormat& format, int width, int height, int numLayers)
4194e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(format, computeMipPyramidLevels(width, height))
4195e5c31af7Sopenharmony_ci	, m_width				(width)
4196e5c31af7Sopenharmony_ci	, m_height				(height)
4197e5c31af7Sopenharmony_ci	, m_numLayers			(numLayers)
4198e5c31af7Sopenharmony_ci	, m_view				(getNumLevels(), getLevels())
4199e5c31af7Sopenharmony_ci{
4200e5c31af7Sopenharmony_ci}
4201e5c31af7Sopenharmony_ci
4202e5c31af7Sopenharmony_ciTexture2DArray::Texture2DArray (const Texture2DArray& other)
4203e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(other)
4204e5c31af7Sopenharmony_ci	, m_width				(other.m_width)
4205e5c31af7Sopenharmony_ci	, m_height				(other.m_height)
4206e5c31af7Sopenharmony_ci	, m_numLayers			(other.m_numLayers)
4207e5c31af7Sopenharmony_ci	, m_view				(getNumLevels(), getLevels())
4208e5c31af7Sopenharmony_ci{
4209e5c31af7Sopenharmony_ci}
4210e5c31af7Sopenharmony_ci
4211e5c31af7Sopenharmony_ciTexture2DArray& Texture2DArray::operator= (const Texture2DArray& other)
4212e5c31af7Sopenharmony_ci{
4213e5c31af7Sopenharmony_ci	if (this == &other)
4214e5c31af7Sopenharmony_ci		return *this;
4215e5c31af7Sopenharmony_ci
4216e5c31af7Sopenharmony_ci	TextureLevelPyramid::operator=(other);
4217e5c31af7Sopenharmony_ci
4218e5c31af7Sopenharmony_ci	m_width		= other.m_width;
4219e5c31af7Sopenharmony_ci	m_height	= other.m_height;
4220e5c31af7Sopenharmony_ci	m_numLayers	= other.m_numLayers;
4221e5c31af7Sopenharmony_ci	m_view		= Texture2DArrayView(getNumLevels(), getLevels());
4222e5c31af7Sopenharmony_ci
4223e5c31af7Sopenharmony_ci	return *this;
4224e5c31af7Sopenharmony_ci}
4225e5c31af7Sopenharmony_ci
4226e5c31af7Sopenharmony_ciTexture2DArray::~Texture2DArray (void)
4227e5c31af7Sopenharmony_ci{
4228e5c31af7Sopenharmony_ci}
4229e5c31af7Sopenharmony_ci
4230e5c31af7Sopenharmony_civoid Texture2DArray::allocLevel (int levelNdx)
4231e5c31af7Sopenharmony_ci{
4232e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(levelNdx, 0, getNumLevels()));
4233e5c31af7Sopenharmony_ci
4234e5c31af7Sopenharmony_ci	const int	width	= getMipPyramidLevelSize(m_width,	levelNdx);
4235e5c31af7Sopenharmony_ci	const int	height	= getMipPyramidLevelSize(m_height,	levelNdx);
4236e5c31af7Sopenharmony_ci
4237e5c31af7Sopenharmony_ci	TextureLevelPyramid::allocLevel(levelNdx, width, height, m_numLayers);
4238e5c31af7Sopenharmony_ci}
4239e5c31af7Sopenharmony_ci
4240e5c31af7Sopenharmony_ci// Texture3DView
4241e5c31af7Sopenharmony_ci
4242e5c31af7Sopenharmony_ciTexture3DView::Texture3DView (int numLevels, const ConstPixelBufferAccess* levels, bool es2, ImageViewMinLodParams *minLodParams)
4243e5c31af7Sopenharmony_ci	: m_numLevels		(numLevels)
4244e5c31af7Sopenharmony_ci	, m_levels			(levels)
4245e5c31af7Sopenharmony_ci	, m_es2				(es2)
4246e5c31af7Sopenharmony_ci	, m_minLodParams	(minLodParams)
4247e5c31af7Sopenharmony_ci{
4248e5c31af7Sopenharmony_ci}
4249e5c31af7Sopenharmony_ci
4250e5c31af7Sopenharmony_ci// Texture3D
4251e5c31af7Sopenharmony_ci
4252e5c31af7Sopenharmony_ciTexture3D::Texture3D (const TextureFormat& format, int width, int height, int depth)
4253e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(format, computeMipPyramidLevels(width, height, depth))
4254e5c31af7Sopenharmony_ci	, m_width				(width)
4255e5c31af7Sopenharmony_ci	, m_height				(height)
4256e5c31af7Sopenharmony_ci	, m_depth				(depth)
4257e5c31af7Sopenharmony_ci	, m_view				(getNumLevels(), getLevels())
4258e5c31af7Sopenharmony_ci{
4259e5c31af7Sopenharmony_ci}
4260e5c31af7Sopenharmony_ci
4261e5c31af7Sopenharmony_ciTexture3D::Texture3D (const Texture3D& other)
4262e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(other)
4263e5c31af7Sopenharmony_ci	, m_width				(other.m_width)
4264e5c31af7Sopenharmony_ci	, m_height				(other.m_height)
4265e5c31af7Sopenharmony_ci	, m_depth				(other.m_depth)
4266e5c31af7Sopenharmony_ci	, m_view				(getNumLevels(), getLevels())
4267e5c31af7Sopenharmony_ci{
4268e5c31af7Sopenharmony_ci}
4269e5c31af7Sopenharmony_ci
4270e5c31af7Sopenharmony_ciTexture3D& Texture3D::operator= (const Texture3D& other)
4271e5c31af7Sopenharmony_ci{
4272e5c31af7Sopenharmony_ci	if (this == &other)
4273e5c31af7Sopenharmony_ci		return *this;
4274e5c31af7Sopenharmony_ci
4275e5c31af7Sopenharmony_ci	TextureLevelPyramid::operator=(other);
4276e5c31af7Sopenharmony_ci
4277e5c31af7Sopenharmony_ci	m_width		= other.m_width;
4278e5c31af7Sopenharmony_ci	m_height	= other.m_height;
4279e5c31af7Sopenharmony_ci	m_depth		= other.m_depth;
4280e5c31af7Sopenharmony_ci	m_view		= Texture3DView(getNumLevels(), getLevels());
4281e5c31af7Sopenharmony_ci
4282e5c31af7Sopenharmony_ci	return *this;
4283e5c31af7Sopenharmony_ci}
4284e5c31af7Sopenharmony_ci
4285e5c31af7Sopenharmony_ciTexture3D::~Texture3D (void)
4286e5c31af7Sopenharmony_ci{
4287e5c31af7Sopenharmony_ci}
4288e5c31af7Sopenharmony_ci
4289e5c31af7Sopenharmony_civoid Texture3D::allocLevel (int levelNdx)
4290e5c31af7Sopenharmony_ci{
4291e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(levelNdx, 0, getNumLevels()));
4292e5c31af7Sopenharmony_ci
4293e5c31af7Sopenharmony_ci	const int width		= getMipPyramidLevelSize(m_width,	levelNdx);
4294e5c31af7Sopenharmony_ci	const int height	= getMipPyramidLevelSize(m_height,	levelNdx);
4295e5c31af7Sopenharmony_ci	const int depth		= getMipPyramidLevelSize(m_depth,	levelNdx);
4296e5c31af7Sopenharmony_ci
4297e5c31af7Sopenharmony_ci	TextureLevelPyramid::allocLevel(levelNdx, width, height, depth);
4298e5c31af7Sopenharmony_ci}
4299e5c31af7Sopenharmony_ci
4300e5c31af7Sopenharmony_ci// TextureCubeArrayView
4301e5c31af7Sopenharmony_ci
4302e5c31af7Sopenharmony_ciTextureCubeArrayView::TextureCubeArrayView (int numLevels, const ConstPixelBufferAccess* levels, bool es2 DE_UNUSED_ATTR, ImageViewMinLodParams* minLodParams DE_UNUSED_ATTR)
4303e5c31af7Sopenharmony_ci	: m_numLevels	(numLevels)
4304e5c31af7Sopenharmony_ci	, m_levels		(levels)
4305e5c31af7Sopenharmony_ci{
4306e5c31af7Sopenharmony_ci}
4307e5c31af7Sopenharmony_ci
4308e5c31af7Sopenharmony_ciinline int TextureCubeArrayView::selectLayer (float q) const
4309e5c31af7Sopenharmony_ci{
4310e5c31af7Sopenharmony_ci	DE_ASSERT(m_numLevels > 0 && m_levels);
4311e5c31af7Sopenharmony_ci	DE_ASSERT((m_levels[0].getDepth() % 6) == 0);
4312e5c31af7Sopenharmony_ci
4313e5c31af7Sopenharmony_ci	return de::clamp(deFloorFloatToInt32(q + 0.5f), 0, (m_levels[0].getDepth() / 6)-1);
4314e5c31af7Sopenharmony_ci}
4315e5c31af7Sopenharmony_ci
4316e5c31af7Sopenharmony_citcu::Vec4 TextureCubeArrayView::sample (const Sampler& sampler, float s, float t, float r, float q, float lod) const
4317e5c31af7Sopenharmony_ci{
4318e5c31af7Sopenharmony_ci	const CubeFaceFloatCoords	coords		= getCubeFaceCoords(Vec3(s, t, r));
4319e5c31af7Sopenharmony_ci	const int					layer		= selectLayer(q);
4320e5c31af7Sopenharmony_ci	const int					faceDepth	= (layer * 6) + getCubeArrayFaceIndex(coords.face);
4321e5c31af7Sopenharmony_ci
4322e5c31af7Sopenharmony_ci	DE_ASSERT(sampler.compare == Sampler::COMPAREMODE_NONE);
4323e5c31af7Sopenharmony_ci
4324e5c31af7Sopenharmony_ci	if (sampler.seamlessCubeMap)
4325e5c31af7Sopenharmony_ci		return sampleCubeArraySeamless(m_levels, m_numLevels, layer, coords.face, sampler, coords.s, coords.t, lod);
4326e5c31af7Sopenharmony_ci	else
4327e5c31af7Sopenharmony_ci		return sampleLevelArray2D(m_levels, m_numLevels, sampler, coords.s, coords.t, faceDepth, lod);
4328e5c31af7Sopenharmony_ci}
4329e5c31af7Sopenharmony_ci
4330e5c31af7Sopenharmony_cifloat TextureCubeArrayView::sampleCompare (const Sampler& sampler, float ref, float s, float t, float r, float q, float lod) const
4331e5c31af7Sopenharmony_ci{
4332e5c31af7Sopenharmony_ci	const CubeFaceFloatCoords	coords		= getCubeFaceCoords(Vec3(s, t, r));
4333e5c31af7Sopenharmony_ci	const int					layer		= selectLayer(q);
4334e5c31af7Sopenharmony_ci	const int					faceDepth	= (layer * 6) + getCubeArrayFaceIndex(coords.face);
4335e5c31af7Sopenharmony_ci
4336e5c31af7Sopenharmony_ci	DE_ASSERT(sampler.compare != Sampler::COMPAREMODE_NONE);
4337e5c31af7Sopenharmony_ci
4338e5c31af7Sopenharmony_ci	if (sampler.seamlessCubeMap)
4339e5c31af7Sopenharmony_ci		return sampleCubeArraySeamlessCompare(m_levels, m_numLevels, layer, coords.face, sampler, ref, coords.s, coords.t, lod);
4340e5c31af7Sopenharmony_ci	else
4341e5c31af7Sopenharmony_ci		return sampleLevelArray2DCompare(m_levels, m_numLevels, sampler, ref, coords.s, coords.t, lod, IVec3(0, 0, faceDepth));
4342e5c31af7Sopenharmony_ci}
4343e5c31af7Sopenharmony_ci
4344e5c31af7Sopenharmony_ci// TextureCubeArray
4345e5c31af7Sopenharmony_ci
4346e5c31af7Sopenharmony_ciTextureCubeArray::TextureCubeArray (const TextureFormat& format, int size, int depth)
4347e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(format, computeMipPyramidLevels(size))
4348e5c31af7Sopenharmony_ci	, m_size				(size)
4349e5c31af7Sopenharmony_ci	, m_depth				(depth)
4350e5c31af7Sopenharmony_ci	, m_view				(getNumLevels(), getLevels())
4351e5c31af7Sopenharmony_ci{
4352e5c31af7Sopenharmony_ci	DE_ASSERT(m_depth % 6 == 0);
4353e5c31af7Sopenharmony_ci}
4354e5c31af7Sopenharmony_ci
4355e5c31af7Sopenharmony_ciTextureCubeArray::TextureCubeArray (const TextureCubeArray& other)
4356e5c31af7Sopenharmony_ci	: TextureLevelPyramid	(other)
4357e5c31af7Sopenharmony_ci	, m_size				(other.m_size)
4358e5c31af7Sopenharmony_ci	, m_depth				(other.m_depth)
4359e5c31af7Sopenharmony_ci	, m_view				(getNumLevels(), getLevels())
4360e5c31af7Sopenharmony_ci{
4361e5c31af7Sopenharmony_ci	DE_ASSERT(m_depth % 6 == 0);
4362e5c31af7Sopenharmony_ci}
4363e5c31af7Sopenharmony_ci
4364e5c31af7Sopenharmony_ciTextureCubeArray& TextureCubeArray::operator= (const TextureCubeArray& other)
4365e5c31af7Sopenharmony_ci{
4366e5c31af7Sopenharmony_ci	if (this == &other)
4367e5c31af7Sopenharmony_ci		return *this;
4368e5c31af7Sopenharmony_ci
4369e5c31af7Sopenharmony_ci	TextureLevelPyramid::operator=(other);
4370e5c31af7Sopenharmony_ci
4371e5c31af7Sopenharmony_ci	m_size	= other.m_size;
4372e5c31af7Sopenharmony_ci	m_depth	= other.m_depth;
4373e5c31af7Sopenharmony_ci	m_view	= TextureCubeArrayView(getNumLevels(), getLevels());
4374e5c31af7Sopenharmony_ci
4375e5c31af7Sopenharmony_ci	DE_ASSERT(m_depth % 6 == 0);
4376e5c31af7Sopenharmony_ci
4377e5c31af7Sopenharmony_ci	return *this;
4378e5c31af7Sopenharmony_ci}
4379e5c31af7Sopenharmony_ci
4380e5c31af7Sopenharmony_ciTextureCubeArray::~TextureCubeArray (void)
4381e5c31af7Sopenharmony_ci{
4382e5c31af7Sopenharmony_ci}
4383e5c31af7Sopenharmony_ci
4384e5c31af7Sopenharmony_civoid TextureCubeArray::allocLevel (int levelNdx)
4385e5c31af7Sopenharmony_ci{
4386e5c31af7Sopenharmony_ci	DE_ASSERT(de::inBounds(levelNdx, 0, getNumLevels()));
4387e5c31af7Sopenharmony_ci
4388e5c31af7Sopenharmony_ci	const int size = getMipPyramidLevelSize(m_size, levelNdx);
4389e5c31af7Sopenharmony_ci
4390e5c31af7Sopenharmony_ci	TextureLevelPyramid::allocLevel(levelNdx, size, size, m_depth);
4391e5c31af7Sopenharmony_ci}
4392e5c31af7Sopenharmony_ci
4393e5c31af7Sopenharmony_cistd::ostream& operator<< (std::ostream& str, TextureFormat::ChannelOrder order)
4394e5c31af7Sopenharmony_ci{
4395e5c31af7Sopenharmony_ci	const char* const orderStrings[] =
4396e5c31af7Sopenharmony_ci	{
4397e5c31af7Sopenharmony_ci		"R",
4398e5c31af7Sopenharmony_ci		"A",
4399e5c31af7Sopenharmony_ci		"I",
4400e5c31af7Sopenharmony_ci		"L",
4401e5c31af7Sopenharmony_ci		"LA",
4402e5c31af7Sopenharmony_ci		"RG",
4403e5c31af7Sopenharmony_ci		"RA",
4404e5c31af7Sopenharmony_ci		"RGB",
4405e5c31af7Sopenharmony_ci		"RGBA",
4406e5c31af7Sopenharmony_ci		"ARGB",
4407e5c31af7Sopenharmony_ci		"ABGR",
4408e5c31af7Sopenharmony_ci		"BGR",
4409e5c31af7Sopenharmony_ci		"BGRA",
4410e5c31af7Sopenharmony_ci
4411e5c31af7Sopenharmony_ci		"sR",
4412e5c31af7Sopenharmony_ci		"sRG",
4413e5c31af7Sopenharmony_ci		"sRGB",
4414e5c31af7Sopenharmony_ci		"sRGBA",
4415e5c31af7Sopenharmony_ci		"sBGR",
4416e5c31af7Sopenharmony_ci		"sBGRA",
4417e5c31af7Sopenharmony_ci
4418e5c31af7Sopenharmony_ci		"D",
4419e5c31af7Sopenharmony_ci		"S",
4420e5c31af7Sopenharmony_ci		"DS"
4421e5c31af7Sopenharmony_ci	};
4422e5c31af7Sopenharmony_ci
4423e5c31af7Sopenharmony_ci	return str << de::getSizedArrayElement<TextureFormat::CHANNELORDER_LAST>(orderStrings, order);
4424e5c31af7Sopenharmony_ci}
4425e5c31af7Sopenharmony_ci
4426e5c31af7Sopenharmony_cistd::ostream& operator<< (std::ostream& str, TextureFormat::ChannelType type)
4427e5c31af7Sopenharmony_ci{
4428e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 48);
4429e5c31af7Sopenharmony_ci
4430e5c31af7Sopenharmony_ci	const char* const typeStrings[] =
4431e5c31af7Sopenharmony_ci	{
4432e5c31af7Sopenharmony_ci		"SNORM_INT8",
4433e5c31af7Sopenharmony_ci		"SNORM_INT16",
4434e5c31af7Sopenharmony_ci		"SNORM_INT32",
4435e5c31af7Sopenharmony_ci		"UNORM_INT8",
4436e5c31af7Sopenharmony_ci		"UNORM_INT16",
4437e5c31af7Sopenharmony_ci		"UNORM_INT24",
4438e5c31af7Sopenharmony_ci		"UNORM_INT32",
4439e5c31af7Sopenharmony_ci		"UNORM_BYTE_44",
4440e5c31af7Sopenharmony_ci		"UNORM_SHORT_565",
4441e5c31af7Sopenharmony_ci		"UNORM_SHORT_555",
4442e5c31af7Sopenharmony_ci		"UNORM_SHORT_4444",
4443e5c31af7Sopenharmony_ci		"UNORM_SHORT_5551",
4444e5c31af7Sopenharmony_ci		"UNORM_SHORT_1555",
4445e5c31af7Sopenharmony_ci		"UNORM_INT_101010",
4446e5c31af7Sopenharmony_ci		"SNORM_INT_1010102_REV",
4447e5c31af7Sopenharmony_ci		"UNORM_INT_1010102_REV",
4448e5c31af7Sopenharmony_ci		"UNSIGNED_BYTE_44",
4449e5c31af7Sopenharmony_ci		"UNSIGNED_SHORT_565",
4450e5c31af7Sopenharmony_ci		"UNSIGNED_SHORT_4444",
4451e5c31af7Sopenharmony_ci		"UNSIGNED_SHORT_5551",
4452e5c31af7Sopenharmony_ci		"SIGNED_INT_1010102_REV",
4453e5c31af7Sopenharmony_ci		"UNSIGNED_INT_1010102_REV",
4454e5c31af7Sopenharmony_ci		"UNSIGNED_INT_11F_11F_10F_REV",
4455e5c31af7Sopenharmony_ci		"UNSIGNED_INT_999_E5_REV",
4456e5c31af7Sopenharmony_ci		"UNSIGNED_INT_16_8_8",
4457e5c31af7Sopenharmony_ci		"UNSIGNED_INT_24_8",
4458e5c31af7Sopenharmony_ci		"UNSIGNED_INT_24_8_REV",
4459e5c31af7Sopenharmony_ci		"SIGNED_INT8",
4460e5c31af7Sopenharmony_ci		"SIGNED_INT16",
4461e5c31af7Sopenharmony_ci		"SIGNED_INT32",
4462e5c31af7Sopenharmony_ci		"SIGNED_INT64",
4463e5c31af7Sopenharmony_ci		"UNSIGNED_INT8",
4464e5c31af7Sopenharmony_ci		"UNSIGNED_INT16",
4465e5c31af7Sopenharmony_ci		"UNSIGNED_INT24",
4466e5c31af7Sopenharmony_ci		"UNSIGNED_INT32",
4467e5c31af7Sopenharmony_ci		"UNSIGNED_INT64",
4468e5c31af7Sopenharmony_ci		"HALF_FLOAT",
4469e5c31af7Sopenharmony_ci		"FLOAT",
4470e5c31af7Sopenharmony_ci		"FLOAT64",
4471e5c31af7Sopenharmony_ci		"FLOAT_UNSIGNED_INT_24_8_REV",
4472e5c31af7Sopenharmony_ci		"UNORM_SHORT_10",
4473e5c31af7Sopenharmony_ci		"UNORM_SHORT_12",
4474e5c31af7Sopenharmony_ci		"USCALED_INT8",
4475e5c31af7Sopenharmony_ci		"USCALED_INT16",
4476e5c31af7Sopenharmony_ci		"SSCALED_INT8",
4477e5c31af7Sopenharmony_ci		"SSCALED_INT16",
4478e5c31af7Sopenharmony_ci		"USCALED_INT_1010102_REV",
4479e5c31af7Sopenharmony_ci		"SSCALED_INT_1010102_REV"
4480e5c31af7Sopenharmony_ci	};
4481e5c31af7Sopenharmony_ci
4482e5c31af7Sopenharmony_ci	return str << de::getSizedArrayElement<TextureFormat::CHANNELTYPE_LAST>(typeStrings, type);
4483e5c31af7Sopenharmony_ci}
4484e5c31af7Sopenharmony_ci
4485e5c31af7Sopenharmony_cistd::ostream& operator<< (std::ostream& str, CubeFace face)
4486e5c31af7Sopenharmony_ci{
4487e5c31af7Sopenharmony_ci	switch (face)
4488e5c31af7Sopenharmony_ci	{
4489e5c31af7Sopenharmony_ci		case CUBEFACE_NEGATIVE_X:	return str << "CUBEFACE_NEGATIVE_X";
4490e5c31af7Sopenharmony_ci		case CUBEFACE_POSITIVE_X:	return str << "CUBEFACE_POSITIVE_X";
4491e5c31af7Sopenharmony_ci		case CUBEFACE_NEGATIVE_Y:	return str << "CUBEFACE_NEGATIVE_Y";
4492e5c31af7Sopenharmony_ci		case CUBEFACE_POSITIVE_Y:	return str << "CUBEFACE_POSITIVE_Y";
4493e5c31af7Sopenharmony_ci		case CUBEFACE_NEGATIVE_Z:	return str << "CUBEFACE_NEGATIVE_Z";
4494e5c31af7Sopenharmony_ci		case CUBEFACE_POSITIVE_Z:	return str << "CUBEFACE_POSITIVE_Z";
4495e5c31af7Sopenharmony_ci		case CUBEFACE_LAST:			return str << "CUBEFACE_LAST";
4496e5c31af7Sopenharmony_ci		default:					return str << "UNKNOWN(" << (int)face << ")";
4497e5c31af7Sopenharmony_ci	}
4498e5c31af7Sopenharmony_ci}
4499e5c31af7Sopenharmony_ci
4500e5c31af7Sopenharmony_cistd::ostream& operator<< (std::ostream& str, TextureFormat format)
4501e5c31af7Sopenharmony_ci{
4502e5c31af7Sopenharmony_ci	return str << format.order << ", " << format.type << "";
4503e5c31af7Sopenharmony_ci}
4504e5c31af7Sopenharmony_ci
4505e5c31af7Sopenharmony_cistd::ostream& operator<< (std::ostream& str, const ConstPixelBufferAccess& access)
4506e5c31af7Sopenharmony_ci{
4507e5c31af7Sopenharmony_ci	return str << "format = (" << access.getFormat() << "), size = "
4508e5c31af7Sopenharmony_ci			   << access.getWidth() << " x " << access.getHeight() << " x " << access.getDepth()
4509e5c31af7Sopenharmony_ci			   << ", pitch = " << access.getRowPitch() << " / " << access.getSlicePitch();
4510e5c31af7Sopenharmony_ci}
4511e5c31af7Sopenharmony_ci
4512e5c31af7Sopenharmony_cideBool isSamplerMipmapModeLinear (tcu::Sampler::FilterMode filterMode)
4513e5c31af7Sopenharmony_ci{
4514e5c31af7Sopenharmony_ci	DE_STATIC_ASSERT(tcu::Sampler::FILTERMODE_LAST == 9);
4515e5c31af7Sopenharmony_ci	switch (filterMode)
4516e5c31af7Sopenharmony_ci	{
4517e5c31af7Sopenharmony_ci		case tcu::Sampler::NEAREST:
4518e5c31af7Sopenharmony_ci		case tcu::Sampler::LINEAR:
4519e5c31af7Sopenharmony_ci		case tcu::Sampler::CUBIC:
4520e5c31af7Sopenharmony_ci		case tcu::Sampler::NEAREST_MIPMAP_NEAREST:
4521e5c31af7Sopenharmony_ci		case tcu::Sampler::LINEAR_MIPMAP_NEAREST:
4522e5c31af7Sopenharmony_ci		case tcu::Sampler::CUBIC_MIPMAP_NEAREST:
4523e5c31af7Sopenharmony_ci			return DE_FALSE;
4524e5c31af7Sopenharmony_ci		case tcu::Sampler::NEAREST_MIPMAP_LINEAR:
4525e5c31af7Sopenharmony_ci		case tcu::Sampler::LINEAR_MIPMAP_LINEAR:
4526e5c31af7Sopenharmony_ci		case tcu::Sampler::CUBIC_MIPMAP_LINEAR:
4527e5c31af7Sopenharmony_ci			return DE_TRUE;
4528e5c31af7Sopenharmony_ci		default:
4529e5c31af7Sopenharmony_ci			DE_FATAL("Illegal filter mode");
4530e5c31af7Sopenharmony_ci			return DE_FALSE;
4531e5c31af7Sopenharmony_ci	}
4532e5c31af7Sopenharmony_ci}
4533e5c31af7Sopenharmony_ci} // tcu
4534