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