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 Texture utilities. 22 *//*--------------------------------------------------------------------*/ 23 24#include "tcuTextureUtil.hpp" 25#include "tcuVectorUtil.hpp" 26#include "deRandom.hpp" 27#include "deMath.h" 28#include "deMemory.h" 29 30#include <limits> 31 32namespace tcu 33{ 34 35static inline float sRGBChannelToLinear (float cs) 36{ 37 if (cs <= 0.04045) 38 return cs / 12.92f; 39 else 40 return deFloatPow((cs + 0.055f) / 1.055f, 2.4f); 41} 42 43static const deUint32 s_srgb8Lut[256] = 44{ 45#include "tcuSRGB8Lut.inl" 46}; 47 48static inline float sRGB8ChannelToLinear (deUint32 cs) 49{ 50 DE_ASSERT(cs < 256); 51 52 // \note This triggers UB, but in practice it doesn't cause any problems 53 return ((const float*)s_srgb8Lut)[cs]; 54} 55 56static inline float linearChannelToSRGB (float cl) 57{ 58 if (cl <= 0.0f) 59 return 0.0f; 60 else if (cl < 0.0031308f) 61 return 12.92f*cl; 62 else if (cl < 1.0f) 63 return 1.055f*deFloatPow(cl, 0.41666f) - 0.055f; 64 else 65 return 1.0f; 66} 67 68//! Convert sRGB to linear colorspace 69Vec4 sRGBToLinear (const Vec4& cs) 70{ 71 return Vec4(sRGBChannelToLinear(cs[0]), 72 sRGBChannelToLinear(cs[1]), 73 sRGBChannelToLinear(cs[2]), 74 cs[3]); 75} 76 77Vec4 sRGB8ToLinear (const UVec4& cs) 78{ 79 return Vec4(sRGB8ChannelToLinear(cs[0]), 80 sRGB8ChannelToLinear(cs[1]), 81 sRGB8ChannelToLinear(cs[2]), 82 1.0f); 83} 84 85Vec4 sRGBA8ToLinear (const UVec4& cs) 86{ 87 return Vec4(sRGB8ChannelToLinear(cs[0]), 88 sRGB8ChannelToLinear(cs[1]), 89 sRGB8ChannelToLinear(cs[2]), 90 (float)cs[3] / 255.0f); 91} 92 93//! Convert from linear to sRGB colorspace 94Vec4 linearToSRGB (const Vec4& cl) 95{ 96 return Vec4(linearChannelToSRGB(cl[0]), 97 linearChannelToSRGB(cl[1]), 98 linearChannelToSRGB(cl[2]), 99 cl[3]); 100} 101 102bool isSRGB (TextureFormat format) 103{ 104 // make sure to update this if type table is updated 105 DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21); 106 107 return format.order == TextureFormat::sR || 108 format.order == TextureFormat::sRG || 109 format.order == TextureFormat::sRGB || 110 format.order == TextureFormat::sRGBA || 111 format.order == TextureFormat::sBGR || 112 format.order == TextureFormat::sBGRA; 113} 114 115tcu::Vec4 linearToSRGBIfNeeded (const TextureFormat& format, const tcu::Vec4& color) 116{ 117 return isSRGB(format) ? linearToSRGB(color) : color; 118} 119 120bool isCombinedDepthStencilType (TextureFormat::ChannelType type) 121{ 122 // make sure to update this if type table is updated 123 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40); 124 125 return type == TextureFormat::UNSIGNED_INT_16_8_8 || 126 type == TextureFormat::UNSIGNED_INT_24_8 || 127 type == TextureFormat::UNSIGNED_INT_24_8_REV || 128 type == TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV; 129} 130 131bool hasStencilComponent (TextureFormat::ChannelOrder order) 132{ 133 DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21); 134 135 switch (order) 136 { 137 case TextureFormat::S: 138 case TextureFormat::DS: 139 return true; 140 141 default: 142 return false; 143 } 144} 145 146bool hasDepthComponent (TextureFormat::ChannelOrder order) 147{ 148 DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21); 149 150 switch (order) 151 { 152 case TextureFormat::D: 153 case TextureFormat::DS: 154 return true; 155 156 default: 157 return false; 158 } 159} 160 161//! Get texture channel class for format 162TextureChannelClass getTextureChannelClass (TextureFormat::ChannelType channelType) 163{ 164 // make sure this table is updated if format table is updated 165 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40); 166 167 switch (channelType) 168 { 169 case TextureFormat::SNORM_INT8: return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT; 170 case TextureFormat::SNORM_INT16: return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT; 171 case TextureFormat::SNORM_INT32: return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT; 172 case TextureFormat::UNORM_INT8: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 173 case TextureFormat::UNORM_INT16: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 174 case TextureFormat::UNORM_INT24: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 175 case TextureFormat::UNORM_INT32: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 176 case TextureFormat::UNORM_BYTE_44: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 177 case TextureFormat::UNORM_SHORT_565: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 178 case TextureFormat::UNORM_SHORT_555: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 179 case TextureFormat::UNORM_SHORT_4444: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 180 case TextureFormat::UNORM_SHORT_5551: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 181 case TextureFormat::UNORM_SHORT_1555: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 182 case TextureFormat::UNSIGNED_BYTE_44: return TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 183 case TextureFormat::UNSIGNED_SHORT_565: return TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 184 case TextureFormat::UNSIGNED_SHORT_4444: return TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 185 case TextureFormat::UNSIGNED_SHORT_5551: return TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 186 case TextureFormat::UNORM_INT_101010: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 187 case TextureFormat::SNORM_INT_1010102_REV: return TEXTURECHANNELCLASS_SIGNED_FIXED_POINT; 188 case TextureFormat::UNORM_INT_1010102_REV: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 189 case TextureFormat::SIGNED_INT_1010102_REV: return TEXTURECHANNELCLASS_SIGNED_INTEGER; 190 case TextureFormat::UNSIGNED_INT_1010102_REV: return TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 191 case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: return TEXTURECHANNELCLASS_FLOATING_POINT; 192 case TextureFormat::UNSIGNED_INT_999_E5_REV: return TEXTURECHANNELCLASS_FLOATING_POINT; 193 case TextureFormat::UNSIGNED_INT_16_8_8: return TEXTURECHANNELCLASS_LAST; //!< packed unorm16-x8-uint8 194 case TextureFormat::UNSIGNED_INT_24_8: return TEXTURECHANNELCLASS_LAST; //!< packed unorm24-uint8 195 case TextureFormat::UNSIGNED_INT_24_8_REV: return TEXTURECHANNELCLASS_LAST; //!< packed unorm24-uint8 196 case TextureFormat::SIGNED_INT8: return TEXTURECHANNELCLASS_SIGNED_INTEGER; 197 case TextureFormat::SIGNED_INT16: return TEXTURECHANNELCLASS_SIGNED_INTEGER; 198 case TextureFormat::SIGNED_INT32: return TEXTURECHANNELCLASS_SIGNED_INTEGER; 199 case TextureFormat::UNSIGNED_INT8: return TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 200 case TextureFormat::UNSIGNED_INT16: return TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 201 case TextureFormat::UNSIGNED_INT24: return TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 202 case TextureFormat::UNSIGNED_INT32: return TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 203 case TextureFormat::HALF_FLOAT: return TEXTURECHANNELCLASS_FLOATING_POINT; 204 case TextureFormat::FLOAT: return TEXTURECHANNELCLASS_FLOATING_POINT; 205 case TextureFormat::FLOAT64: return TEXTURECHANNELCLASS_FLOATING_POINT; 206 case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: return TEXTURECHANNELCLASS_LAST; //!< packed float32-pad24-uint8 207 case TextureFormat::UNORM_SHORT_10: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 208 case TextureFormat::UNORM_SHORT_12: return TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 209 default: 210 DE_FATAL("Unknown channel type"); 211 return TEXTURECHANNELCLASS_LAST; 212 } 213} 214 215bool isAccessValid (TextureFormat format, TextureAccessType type) 216{ 217 DE_ASSERT(isValid(format)); 218 219 if (format.order == TextureFormat::DS) 220 { 221 // It is never allowed to access combined depth-stencil format with getPixel(). 222 // Instead either getPixDepth() or getPixStencil(), or effective depth- or stencil- 223 // access must be used. 224 return false; 225 } 226 else if (format.order == TextureFormat::D) 227 return type == TEXTUREACCESSTYPE_FLOAT; 228 else if (format.order == TextureFormat::S) 229 return type == TEXTUREACCESSTYPE_UNSIGNED_INT; 230 else 231 { 232 // A few packed color formats have access type restrictions 233 if (format.type == TextureFormat::UNSIGNED_INT_11F_11F_10F_REV || 234 format.type == TextureFormat::UNSIGNED_INT_999_E5_REV) 235 return type == TEXTUREACCESSTYPE_FLOAT; 236 else 237 return true; 238 } 239} 240 241/*--------------------------------------------------------------------*//*! 242 * \brief Get access to subregion of pixel buffer 243 * \param access Parent access object 244 * \param x X offset 245 * \param y Y offset 246 * \param z Z offset 247 * \param width Width 248 * \param height Height 249 * \param depth Depth 250 * \return Access object that targets given subregion of parent access object 251 *//*--------------------------------------------------------------------*/ 252ConstPixelBufferAccess getSubregion (const ConstPixelBufferAccess& access, int x, int y, int z, int width, int height, int depth) 253{ 254 DE_ASSERT(de::inBounds(x, 0, access.getWidth())); 255 DE_ASSERT(de::inRange(x+width, x+1, access.getWidth())); 256 257 DE_ASSERT(de::inBounds(y, 0, access.getHeight())); 258 DE_ASSERT(de::inRange(y+height, y+1, access.getHeight())); 259 260 DE_ASSERT(de::inBounds(z, 0, access.getDepth())); 261 DE_ASSERT(de::inRange(z+depth, z+1, access.getDepth())); 262 263 return ConstPixelBufferAccess(access.getFormat(), tcu::IVec3(width, height, depth), access.getPitch(), 264 (const deUint8*)access.getDataPtr() + access.getPixelPitch()*x + access.getRowPitch()*y + access.getSlicePitch()*z); 265} 266 267/*--------------------------------------------------------------------*//*! 268 * \brief Get access to subregion of pixel buffer 269 * \param access Parent access object 270 * \param x X offset 271 * \param y Y offset 272 * \param z Z offset 273 * \param width Width 274 * \param height Height 275 * \param depth Depth 276 * \return Access object that targets given subregion of parent access object 277 *//*--------------------------------------------------------------------*/ 278PixelBufferAccess getSubregion (const PixelBufferAccess& access, int x, int y, int z, int width, int height, int depth) 279{ 280 DE_ASSERT(de::inBounds(x, 0, access.getWidth())); 281 DE_ASSERT(de::inRange(x+width, x+1, access.getWidth())); 282 283 DE_ASSERT(de::inBounds(y, 0, access.getHeight())); 284 DE_ASSERT(de::inRange(y+height, y+1, access.getHeight())); 285 286 DE_ASSERT(de::inBounds(z, 0, access.getDepth())); 287 DE_ASSERT(de::inRange(z+depth, z+1, access.getDepth())); 288 289 return PixelBufferAccess(access.getFormat(), tcu::IVec3(width, height, depth), access.getPitch(), 290 (deUint8*)access.getDataPtr() + access.getPixelPitch()*x + access.getRowPitch()*y + access.getSlicePitch()*z); 291} 292 293/*--------------------------------------------------------------------*//*! 294 * \brief Get access to subregion of pixel buffer 295 * \param access Parent access object 296 * \param x X offset 297 * \param y Y offset 298 * \param width Width 299 * \param height Height 300 * \return Access object that targets given subregion of parent access object 301 *//*--------------------------------------------------------------------*/ 302PixelBufferAccess getSubregion (const PixelBufferAccess& access, int x, int y, int width, int height) 303{ 304 return getSubregion(access, x, y, 0, width, height, 1); 305} 306 307/*--------------------------------------------------------------------*//*! 308 * \brief Get access to subregion of pixel buffer 309 * \param access Parent access object 310 * \param x X offset 311 * \param y Y offset 312 * \param width Width 313 * \param height Height 314 * \return Access object that targets given subregion of parent access object 315 *//*--------------------------------------------------------------------*/ 316ConstPixelBufferAccess getSubregion (const ConstPixelBufferAccess& access, int x, int y, int width, int height) 317{ 318 return getSubregion(access, x, y, 0, width, height, 1); 319} 320 321/*--------------------------------------------------------------------*//*! 322 * \brief Flip rows in Y direction 323 * \param access Access object 324 * \return Modified access object where Y coordinates are reversed 325 *//*--------------------------------------------------------------------*/ 326PixelBufferAccess flipYAccess (const PixelBufferAccess& access) 327{ 328 const int rowPitch = access.getRowPitch(); 329 const int offsetToLast = rowPitch*(access.getHeight()-1); 330 const tcu::IVec3 pitch (access.getPixelPitch(), -rowPitch, access.getSlicePitch()); 331 332 return PixelBufferAccess(access.getFormat(), access.getSize(), pitch, (deUint8*)access.getDataPtr() + offsetToLast); 333} 334 335/*--------------------------------------------------------------------*//*! 336 * \brief Flip rows in Y direction 337 * \param access Access object 338 * \return Modified access object where Y coordinates are reversed 339 *//*--------------------------------------------------------------------*/ 340ConstPixelBufferAccess flipYAccess (const ConstPixelBufferAccess& access) 341{ 342 const int rowPitch = access.getRowPitch(); 343 const int offsetToLast = rowPitch*(access.getHeight()-1); 344 const tcu::IVec3 pitch (access.getPixelPitch(), -rowPitch, access.getSlicePitch()); 345 346 return ConstPixelBufferAccess(access.getFormat(), access.getSize(), pitch, (deUint8*)access.getDataPtr() + offsetToLast); 347} 348 349static Vec2 getFloatChannelValueRange (TextureFormat::ChannelType channelType) 350{ 351 // make sure this table is updated if format table is updated 352 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40); 353 354 float cMin = 0.0f; 355 float cMax = 0.0f; 356 357 switch (channelType) 358 { 359 // Signed normalized formats. 360 case TextureFormat::SNORM_INT8: 361 case TextureFormat::SNORM_INT16: 362 case TextureFormat::SNORM_INT32: 363 case TextureFormat::SNORM_INT_1010102_REV: cMin = -1.0f; cMax = 1.0f; break; 364 365 // Unsigned normalized formats. 366 case TextureFormat::UNORM_INT8: 367 case TextureFormat::UNORM_INT16: 368 case TextureFormat::UNORM_INT24: 369 case TextureFormat::UNORM_INT32: 370 case TextureFormat::UNORM_BYTE_44: 371 case TextureFormat::UNORM_SHORT_565: 372 case TextureFormat::UNORM_SHORT_555: 373 case TextureFormat::UNORM_SHORT_4444: 374 case TextureFormat::UNORM_SHORT_5551: 375 case TextureFormat::UNORM_SHORT_1555: 376 case TextureFormat::UNORM_INT_101010: 377 case TextureFormat::UNORM_INT_1010102_REV: 378 case TextureFormat::UNORM_SHORT_10: 379 case TextureFormat::UNORM_SHORT_12: cMin = 0.0f; cMax = 1.0f; break; 380 381 // Misc formats. 382 case TextureFormat::SIGNED_INT8: cMin = -128.0f; cMax = 127.0f; break; 383 case TextureFormat::SIGNED_INT16: cMin = -32768.0f; cMax = 32767.0f; break; 384 case TextureFormat::SIGNED_INT32: cMin = -2147483520.0f; cMax = 2147483520.0f; break; // Maximum exactly representable 31-bit integer: (2^24 - 1) * 2^7 385 case TextureFormat::UNSIGNED_INT8: cMin = 0.0f; cMax = 255.0f; break; 386 case TextureFormat::UNSIGNED_INT16: cMin = 0.0f; cMax = 65535.0f; break; 387 case TextureFormat::UNSIGNED_INT24: cMin = 0.0f; cMax = 16777215.0f; break; 388 case TextureFormat::UNSIGNED_INT32: cMin = 0.0f; cMax = 4294967040.f; break; // Maximum exactly representable 32-bit integer: (2^24 - 1) * 2^8 389 case TextureFormat::HALF_FLOAT: cMin = -1e3f; cMax = 1e3f; break; 390 case TextureFormat::FLOAT: cMin = -1e5f; cMax = 1e5f; break; 391 case TextureFormat::FLOAT64: cMin = -1e5f; cMax = 1e5f; break; 392 case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: cMin = 0.0f; cMax = 1e4f; break; 393 case TextureFormat::UNSIGNED_INT_999_E5_REV: cMin = 0.0f; cMax = 1e5f; break; 394 case TextureFormat::UNSIGNED_BYTE_44: cMin = 0.0f; cMax = 15.f; break; 395 case TextureFormat::UNSIGNED_SHORT_4444: cMin = 0.0f; cMax = 15.f; break; 396 397 default: 398 DE_ASSERT(false); 399 } 400 401 return Vec2(cMin, cMax); 402} 403 404/*--------------------------------------------------------------------*//*! 405 * \brief Get standard parameters for testing texture format 406 * 407 * Returns TextureFormatInfo that describes good parameters for exercising 408 * given TextureFormat. Parameters include value ranges per channel and 409 * suitable lookup scaling and bias in order to reduce result back to 410 * 0..1 range. 411 *//*--------------------------------------------------------------------*/ 412TextureFormatInfo getTextureFormatInfo (const TextureFormat& format) 413{ 414 // Special cases. 415 if (format.type == TextureFormat::UNSIGNED_INT_1010102_REV) 416 return TextureFormatInfo(Vec4( 0.0f, 0.0f, 0.0f, 0.0f), 417 Vec4( 1023.0f, 1023.0f, 1023.0f, 3.0f), 418 Vec4(1.0f/1023.f, 1.0f/1023.0f, 1.0f/1023.0f, 1.0f/3.0f), 419 Vec4( 0.0f, 0.0f, 0.0f, 0.0f)); 420 if (format.type == TextureFormat::SIGNED_INT_1010102_REV) 421 return TextureFormatInfo(Vec4( -512.0f, -512.0f, -512.0f, -2.0f), 422 Vec4( 511.0f, 511.0f, 511.0f, 1.0f), 423 Vec4(1.0f/1023.f, 1.0f/1023.0f, 1.0f/1023.0f, 1.0f/3.0f), 424 Vec4( 0.5f, 0.5f, 0.5f, 0.5f)); 425 else if (format.order == TextureFormat::D || format.order == TextureFormat::DS) 426 return TextureFormatInfo(Vec4(0.0f, 0.0f, 0.0f, 0.0f), 427 Vec4(1.0f, 1.0f, 1.0f, 0.0f), 428 Vec4(1.0f, 1.0f, 1.0f, 1.0f), 429 Vec4(0.0f, 0.0f, 0.0f, 0.0f)); // Depth / stencil formats. 430 else if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_SHORT_5551)) 431 return TextureFormatInfo(Vec4(0.0f, 0.0f, 0.0f, 0.5f), 432 Vec4(1.0f, 1.0f, 1.0f, 1.5f), 433 Vec4(1.0f, 1.0f, 1.0f, 1.0f), 434 Vec4(0.0f, 0.0f, 0.0f, 0.0f)); 435 else if (format.type == TextureFormat::UNSIGNED_SHORT_5551) 436 return TextureFormatInfo(Vec4( 0.0f, 0.0f, 0.0f, 0.0f), 437 Vec4( 31.0f, 31.0f, 31.0f, 1.0f), 438 Vec4(1.0f/31.f, 1.0f/31.0f, 1.0f/31.0f, 1.0f), 439 Vec4( 0.0f, 0.0f, 0.0f, 0.0f)); 440 else if (format.type == TextureFormat::UNSIGNED_SHORT_565) 441 return TextureFormatInfo(Vec4( 0.0f, 0.0f, 0.0f, 0.0f), 442 Vec4( 31.0f, 63.0f, 31.0f, 0.0f), 443 Vec4(1.0f/31.f, 1.0f/63.0f, 1.0f/31.0f, 1.0f), 444 Vec4( 0.0f, 0.0f, 0.0f, 0.0f)); 445 446 const Vec2 cRange = getFloatChannelValueRange(format.type); 447 const TextureSwizzle::Channel* map = getChannelReadSwizzle(format.order).components; 448 const BVec4 chnMask = BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 449 deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 450 deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 451 deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE); 452 const float scale = 1.0f / (cRange[1] - cRange[0]); 453 const float bias = -cRange[0] * scale; 454 455 return TextureFormatInfo(select(cRange[0], 0.0f, chnMask), 456 select(cRange[1], 0.0f, chnMask), 457 select(scale, 1.0f, chnMask), 458 select(bias, 0.0f, chnMask)); 459} 460 461IVec4 getFormatMinIntValue (const TextureFormat& format) 462{ 463 DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_SIGNED_INTEGER); 464 465 switch (format.type) 466 { 467 case TextureFormat::SIGNED_INT8: return IVec4(std::numeric_limits<deInt8>::min()); 468 case TextureFormat::SIGNED_INT16: return IVec4(std::numeric_limits<deInt16>::min()); 469 case TextureFormat::SIGNED_INT32: return IVec4(std::numeric_limits<deInt32>::min()); 470 471 default: 472 DE_FATAL("Invalid channel type"); 473 return IVec4(0); 474 } 475} 476 477IVec4 getFormatMaxIntValue (const TextureFormat& format) 478{ 479 DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_SIGNED_INTEGER); 480 481 if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::SIGNED_INT_1010102_REV) || 482 format == TextureFormat(TextureFormat::BGRA, TextureFormat::SIGNED_INT_1010102_REV)) 483 return IVec4(511, 511, 511, 1); 484 485 switch (format.type) 486 { 487 case TextureFormat::SIGNED_INT8: return IVec4(std::numeric_limits<deInt8>::max()); 488 case TextureFormat::SIGNED_INT16: return IVec4(std::numeric_limits<deInt16>::max()); 489 case TextureFormat::SIGNED_INT32: return IVec4(std::numeric_limits<deInt32>::max()); 490 491 default: 492 DE_FATAL("Invalid channel type"); 493 return IVec4(0); 494 } 495} 496 497UVec4 getFormatMaxUintValue (const TextureFormat& format) 498{ 499 DE_ASSERT(getTextureChannelClass(format.type) == TEXTURECHANNELCLASS_UNSIGNED_INTEGER); 500 501 if (format == TextureFormat(TextureFormat::RGBA, TextureFormat::UNSIGNED_INT_1010102_REV) || 502 format == TextureFormat(TextureFormat::BGRA, TextureFormat::UNSIGNED_INT_1010102_REV)) 503 return UVec4(1023u, 1023u, 1023u, 3u); 504 505 switch (format.type) 506 { 507 case TextureFormat::UNSIGNED_INT8: return UVec4(std::numeric_limits<deUint8>::max()); 508 case TextureFormat::UNSIGNED_INT16: return UVec4(std::numeric_limits<deUint16>::max()); 509 case TextureFormat::UNSIGNED_INT24: return UVec4(0xffffffu); 510 case TextureFormat::UNSIGNED_INT32: return UVec4(std::numeric_limits<deUint32>::max()); 511 512 default: 513 DE_FATAL("Invalid channel type"); 514 return UVec4(0); 515 } 516} 517 518static IVec4 getChannelBitDepth (TextureFormat::ChannelType channelType) 519{ 520 // make sure this table is updated if format table is updated 521 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40); 522 523 switch (channelType) 524 { 525 case TextureFormat::SNORM_INT8: return IVec4(8); 526 case TextureFormat::SNORM_INT16: return IVec4(16); 527 case TextureFormat::SNORM_INT32: return IVec4(32); 528 case TextureFormat::UNORM_INT8: return IVec4(8); 529 case TextureFormat::UNORM_INT16: return IVec4(16); 530 case TextureFormat::UNORM_INT24: return IVec4(24); 531 case TextureFormat::UNORM_INT32: return IVec4(32); 532 case TextureFormat::UNORM_BYTE_44: return IVec4(4,4,0,0); 533 case TextureFormat::UNORM_SHORT_565: return IVec4(5,6,5,0); 534 case TextureFormat::UNORM_SHORT_4444: return IVec4(4); 535 case TextureFormat::UNORM_SHORT_555: return IVec4(5,5,5,0); 536 case TextureFormat::UNORM_SHORT_5551: return IVec4(5,5,5,1); 537 case TextureFormat::UNORM_SHORT_1555: return IVec4(1,5,5,5); 538 case TextureFormat::UNSIGNED_BYTE_44: return IVec4(4,4,0,0); 539 case TextureFormat::UNSIGNED_SHORT_565: return IVec4(5,6,5,0); 540 case TextureFormat::UNSIGNED_SHORT_4444: return IVec4(4); 541 case TextureFormat::UNSIGNED_SHORT_5551: return IVec4(5,5,5,1); 542 case TextureFormat::UNORM_INT_101010: return IVec4(10,10,10,0); 543 case TextureFormat::SNORM_INT_1010102_REV: return IVec4(10,10,10,2); 544 case TextureFormat::UNORM_INT_1010102_REV: return IVec4(10,10,10,2); 545 case TextureFormat::SIGNED_INT8: return IVec4(8); 546 case TextureFormat::SIGNED_INT16: return IVec4(16); 547 case TextureFormat::SIGNED_INT32: return IVec4(32); 548 case TextureFormat::UNSIGNED_INT8: return IVec4(8); 549 case TextureFormat::UNSIGNED_INT16: return IVec4(16); 550 case TextureFormat::UNSIGNED_INT24: return IVec4(24); 551 case TextureFormat::UNSIGNED_INT32: return IVec4(32); 552 case TextureFormat::SIGNED_INT_1010102_REV: return IVec4(10,10,10,2); 553 case TextureFormat::UNSIGNED_INT_1010102_REV: return IVec4(10,10,10,2); 554 case TextureFormat::UNSIGNED_INT_16_8_8: return IVec4(16,8,0,0); 555 case TextureFormat::UNSIGNED_INT_24_8: return IVec4(24,8,0,0); 556 case TextureFormat::UNSIGNED_INT_24_8_REV: return IVec4(24,8,0,0); 557 case TextureFormat::HALF_FLOAT: return IVec4(16); 558 case TextureFormat::FLOAT: return IVec4(32); 559 case TextureFormat::FLOAT64: return IVec4(64); 560 case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: return IVec4(11,11,10,0); 561 case TextureFormat::UNSIGNED_INT_999_E5_REV: return IVec4(9,9,9,0); 562 case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: return IVec4(32,8,0,0); 563 case TextureFormat::UNORM_SHORT_10: return IVec4(10); 564 case TextureFormat::UNORM_SHORT_12: return IVec4(12); 565 default: 566 DE_ASSERT(false); 567 return IVec4(0); 568 } 569} 570 571IVec4 getTextureFormatBitDepth (const TextureFormat& format) 572{ 573 const IVec4 chnBits = getChannelBitDepth(format.type); 574 const TextureSwizzle::Channel* map = getChannelReadSwizzle(format.order).components; 575 const BVec4 chnMask = BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 576 deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 577 deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 578 deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE); 579 const IVec4 chnSwz = IVec4((chnMask[0]) ? ((int)map[0]) : (0), 580 (chnMask[1]) ? ((int)map[1]) : (0), 581 (chnMask[2]) ? ((int)map[2]) : (0), 582 (chnMask[3]) ? ((int)map[3]) : (0)); 583 584 return select(chnBits.swizzle(chnSwz.x(), chnSwz.y(), chnSwz.z(), chnSwz.w()), IVec4(0), chnMask); 585} 586 587static IVec4 getChannelMantissaBitDepth (TextureFormat::ChannelType channelType) 588{ 589 // make sure this table is updated if format table is updated 590 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40); 591 592 switch (channelType) 593 { 594 case TextureFormat::SNORM_INT8: 595 case TextureFormat::SNORM_INT16: 596 case TextureFormat::SNORM_INT32: 597 case TextureFormat::UNORM_INT8: 598 case TextureFormat::UNORM_INT16: 599 case TextureFormat::UNORM_INT24: 600 case TextureFormat::UNORM_INT32: 601 case TextureFormat::UNORM_BYTE_44: 602 case TextureFormat::UNORM_SHORT_565: 603 case TextureFormat::UNORM_SHORT_4444: 604 case TextureFormat::UNORM_SHORT_555: 605 case TextureFormat::UNORM_SHORT_5551: 606 case TextureFormat::UNORM_SHORT_1555: 607 case TextureFormat::UNSIGNED_BYTE_44: 608 case TextureFormat::UNSIGNED_SHORT_565: 609 case TextureFormat::UNSIGNED_SHORT_4444: 610 case TextureFormat::UNSIGNED_SHORT_5551: 611 case TextureFormat::UNORM_INT_101010: 612 case TextureFormat::SNORM_INT_1010102_REV: 613 case TextureFormat::UNORM_INT_1010102_REV: 614 case TextureFormat::SIGNED_INT8: 615 case TextureFormat::SIGNED_INT16: 616 case TextureFormat::SIGNED_INT32: 617 case TextureFormat::UNSIGNED_INT8: 618 case TextureFormat::UNSIGNED_INT16: 619 case TextureFormat::UNSIGNED_INT24: 620 case TextureFormat::UNSIGNED_INT32: 621 case TextureFormat::SIGNED_INT_1010102_REV: 622 case TextureFormat::UNSIGNED_INT_1010102_REV: 623 case TextureFormat::UNSIGNED_INT_16_8_8: 624 case TextureFormat::UNSIGNED_INT_24_8: 625 case TextureFormat::UNSIGNED_INT_24_8_REV: 626 case TextureFormat::UNSIGNED_INT_999_E5_REV: 627 case TextureFormat::UNORM_SHORT_10: 628 case TextureFormat::UNORM_SHORT_12: 629 return getChannelBitDepth(channelType); 630 631 case TextureFormat::HALF_FLOAT: return IVec4(10); 632 case TextureFormat::FLOAT: return IVec4(23); 633 case TextureFormat::FLOAT64: return IVec4(52); 634 case TextureFormat::UNSIGNED_INT_11F_11F_10F_REV: return IVec4(6,6,5,0); 635 case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: return IVec4(23,8,0,0); 636 default: 637 DE_ASSERT(false); 638 return IVec4(0); 639 } 640} 641 642IVec4 getTextureFormatMantissaBitDepth (const TextureFormat& format) 643{ 644 const IVec4 chnBits = getChannelMantissaBitDepth(format.type); 645 const TextureSwizzle::Channel* map = getChannelReadSwizzle(format.order).components; 646 const BVec4 chnMask = BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 647 deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 648 deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 649 deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE); 650 const IVec4 chnSwz = IVec4((chnMask[0]) ? ((int)map[0]) : (0), 651 (chnMask[1]) ? ((int)map[1]) : (0), 652 (chnMask[2]) ? ((int)map[2]) : (0), 653 (chnMask[3]) ? ((int)map[3]) : (0)); 654 655 return select(chnBits.swizzle(chnSwz.x(), chnSwz.y(), chnSwz.z(), chnSwz.w()), IVec4(0), chnMask); 656} 657 658BVec4 getTextureFormatChannelMask (const TextureFormat& format) 659{ 660 const TextureSwizzle::Channel* const map = getChannelReadSwizzle(format.order).components; 661 return BVec4(deInRange32(map[0], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 662 deInRange32(map[1], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 663 deInRange32(map[2], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE, 664 deInRange32(map[3], TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE); 665} 666 667static inline float linearInterpolate (float t, float minVal, float maxVal) 668{ 669 return minVal + (maxVal - minVal) * t; 670} 671 672static inline Vec4 linearInterpolate (float t, const Vec4& a, const Vec4& b) 673{ 674 return a + (b - a) * t; 675} 676 677enum 678{ 679 CLEAR_OPTIMIZE_THRESHOLD = 128, 680 CLEAR_OPTIMIZE_MAX_PIXEL_SIZE = 8 681}; 682 683inline void fillRow (const PixelBufferAccess& dst, int y, int z, int pixelSize, const deUint8* pixel) 684{ 685 DE_ASSERT(dst.getPixelPitch() == pixelSize); // only tightly packed 686 687 deUint8* dstPtr = (deUint8*)dst.getPixelPtr(0, y, z); 688 int width = dst.getWidth(); 689 690 if (pixelSize == 8 && deIsAlignedPtr(dstPtr, pixelSize)) 691 { 692 deUint64 val; 693 memcpy(&val, pixel, sizeof(val)); 694 695 for (int i = 0; i < width; i++) 696 ((deUint64*)dstPtr)[i] = val; 697 } 698 else if (pixelSize == 4 && deIsAlignedPtr(dstPtr, pixelSize)) 699 { 700 deUint32 val; 701 memcpy(&val, pixel, sizeof(val)); 702 703 for (int i = 0; i < width; i++) 704 ((deUint32*)dstPtr)[i] = val; 705 } 706 else 707 { 708 for (int i = 0; i < width; i++) 709 for (int j = 0; j < pixelSize; j++) 710 dstPtr[i*pixelSize+j] = pixel[j]; 711 } 712} 713 714void clear (const PixelBufferAccess& access, const Vec4& color) 715{ 716 const int pixelSize = access.getFormat().getPixelSize(); 717 const int pixelPitch = access.getPixelPitch(); 718 const bool rowPixelsTightlyPacked = (pixelSize == pixelPitch); 719 720 if (access.getWidth()*access.getHeight()*access.getDepth() >= CLEAR_OPTIMIZE_THRESHOLD && 721 pixelSize < CLEAR_OPTIMIZE_MAX_PIXEL_SIZE && rowPixelsTightlyPacked) 722 { 723 // Convert to destination format. 724 union 725 { 726 deUint8 u8[CLEAR_OPTIMIZE_MAX_PIXEL_SIZE]; 727 deUint64 u64; // Forces 64-bit alignment. 728 } pixel; 729 DE_STATIC_ASSERT(sizeof(pixel) == CLEAR_OPTIMIZE_MAX_PIXEL_SIZE); 730 PixelBufferAccess(access.getFormat(), 1, 1, 1, 0, 0, &pixel.u8[0]).setPixel(color, 0, 0); 731 732 for (int z = 0; z < access.getDepth(); z++) 733 for (int y = 0; y < access.getHeight(); y++) 734 fillRow(access, y, z, pixelSize, &pixel.u8[0]); 735 } 736 else 737 { 738 for (int z = 0; z < access.getDepth(); z++) 739 for (int y = 0; y < access.getHeight(); y++) 740 for (int x = 0; x < access.getWidth(); x++) 741 access.setPixel(color, x, y, z); 742 } 743} 744 745void clear (const PixelBufferAccess& access, const IVec4& color) 746{ 747 const int pixelSize = access.getFormat().getPixelSize(); 748 const int pixelPitch = access.getPixelPitch(); 749 const bool rowPixelsTightlyPacked = (pixelSize == pixelPitch); 750 751 if (access.getWidth()*access.getHeight()*access.getDepth() >= CLEAR_OPTIMIZE_THRESHOLD && 752 pixelSize < CLEAR_OPTIMIZE_MAX_PIXEL_SIZE && rowPixelsTightlyPacked) 753 { 754 // Convert to destination format. 755 union 756 { 757 deUint8 u8[CLEAR_OPTIMIZE_MAX_PIXEL_SIZE]; 758 deUint64 u64; // Forces 64-bit alignment. 759 } pixel; 760 DE_STATIC_ASSERT(sizeof(pixel) == CLEAR_OPTIMIZE_MAX_PIXEL_SIZE); 761 PixelBufferAccess(access.getFormat(), 1, 1, 1, 0, 0, &pixel.u8[0]).setPixel(color, 0, 0); 762 763 for (int z = 0; z < access.getDepth(); z++) 764 for (int y = 0; y < access.getHeight(); y++) 765 fillRow(access, y, z, pixelSize, &pixel.u8[0]); 766 } 767 else 768 { 769 for (int z = 0; z < access.getDepth(); z++) 770 for (int y = 0; y < access.getHeight(); y++) 771 for (int x = 0; x < access.getWidth(); x++) 772 access.setPixel(color, x, y, z); 773 } 774} 775 776void clear (const PixelBufferAccess& access, const UVec4& color) 777{ 778 clear(access, color.cast<deInt32>()); 779} 780 781void clearDepth (const PixelBufferAccess& access, float depth) 782{ 783 DE_ASSERT(access.getFormat().order == TextureFormat::DS || access.getFormat().order == TextureFormat::D); 784 785 clear(getEffectiveDepthStencilAccess(access, Sampler::MODE_DEPTH), tcu::Vec4(depth, 0.0f, 0.0f, 0.0f)); 786} 787 788void clearStencil (const PixelBufferAccess& access, int stencil) 789{ 790 DE_ASSERT(access.getFormat().order == TextureFormat::DS || access.getFormat().order == TextureFormat::S); 791 792 clear(getEffectiveDepthStencilAccess(access, Sampler::MODE_STENCIL), tcu::UVec4(stencil, 0u, 0u, 0u)); 793} 794 795static void fillWithComponentGradients1D (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal) 796{ 797 DE_ASSERT(access.getHeight() == 1); 798 for (int x = 0; x < access.getWidth(); x++) 799 { 800 float s = ((float)x + 0.5f) / (float)access.getWidth(); 801 802 float r = linearInterpolate(s, minVal.x(), maxVal.x()); 803 float g = linearInterpolate(s, minVal.y(), maxVal.y()); 804 float b = linearInterpolate(s, minVal.z(), maxVal.z()); 805 float a = linearInterpolate(s, minVal.w(), maxVal.w()); 806 807 access.setPixel(tcu::Vec4(r, g, b, a), x, 0); 808 } 809} 810 811static void fillWithComponentGradients2D (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal) 812{ 813 for (int y = 0; y < access.getHeight(); y++) 814 { 815 for (int x = 0; x < access.getWidth(); x++) 816 { 817 float s = ((float)x + 0.5f) / (float)access.getWidth(); 818 float t = ((float)y + 0.5f) / (float)access.getHeight(); 819 820 float r = linearInterpolate(( s + t) *0.5f, minVal.x(), maxVal.x()); 821 float g = linearInterpolate(( s + (1.0f-t))*0.5f, minVal.y(), maxVal.y()); 822 float b = linearInterpolate(((1.0f-s) + t) *0.5f, minVal.z(), maxVal.z()); 823 float a = linearInterpolate(((1.0f-s) + (1.0f-t))*0.5f, minVal.w(), maxVal.w()); 824 825 access.setPixel(tcu::Vec4(r, g, b, a), x, y); 826 } 827 } 828} 829 830static void fillWithComponentGradients3D (const PixelBufferAccess& dst, const Vec4& minVal, const Vec4& maxVal) 831{ 832 for (int z = 0; z < dst.getDepth(); z++) 833 { 834 for (int y = 0; y < dst.getHeight(); y++) 835 { 836 for (int x = 0; x < dst.getWidth(); x++) 837 { 838 float s = ((float)x + 0.5f) / (float)dst.getWidth(); 839 float t = ((float)y + 0.5f) / (float)dst.getHeight(); 840 float p = ((float)z + 0.5f) / (float)dst.getDepth(); 841 842 float r = linearInterpolate(s, minVal.x(), maxVal.x()); 843 float g = linearInterpolate(t, minVal.y(), maxVal.y()); 844 float b = linearInterpolate(p, minVal.z(), maxVal.z()); 845 float a = linearInterpolate(1.0f - (s+t+p)/3.0f, minVal.w(), maxVal.w()); 846 847 dst.setPixel(tcu::Vec4(r, g, b, a), x, y, z); 848 } 849 } 850 } 851} 852 853void fillWithComponentGradients (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal) 854{ 855 if (isCombinedDepthStencilType(access.getFormat().type)) 856 { 857 const bool hasDepth = access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::D; 858 const bool hasStencil = access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::S; 859 860 DE_ASSERT(hasDepth || hasStencil); 861 862 // For combined formats, treat D and S as separate channels 863 if (hasDepth) 864 fillWithComponentGradients(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_DEPTH), minVal, maxVal); 865 if (hasStencil) 866 fillWithComponentGradients(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_STENCIL), minVal.swizzle(3,2,1,0), maxVal.swizzle(3,2,1,0)); 867 } 868 else 869 { 870 if (access.getHeight() == 1 && access.getDepth() == 1) 871 fillWithComponentGradients1D(access, minVal, maxVal); 872 else if (access.getDepth() == 1) 873 fillWithComponentGradients2D(access, minVal, maxVal); 874 else 875 fillWithComponentGradients3D(access, minVal, maxVal); 876 } 877} 878 879static void fillWithGrid1D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB) 880{ 881 for (int x = 0; x < access.getWidth(); x++) 882 { 883 int mx = (x / cellSize) % 2; 884 885 if (mx) 886 access.setPixel(colorB, x, 0); 887 else 888 access.setPixel(colorA, x, 0); 889 } 890} 891 892static void fillWithGrid2D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB) 893{ 894 for (int y = 0; y < access.getHeight(); y++) 895 { 896 for (int x = 0; x < access.getWidth(); x++) 897 { 898 int mx = (x / cellSize) % 2; 899 int my = (y / cellSize) % 2; 900 901 if (mx ^ my) 902 access.setPixel(colorB, x, y); 903 else 904 access.setPixel(colorA, x, y); 905 } 906 } 907} 908 909static void fillWithGrid3D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB) 910{ 911 for (int z = 0; z < access.getDepth(); z++) 912 { 913 for (int y = 0; y < access.getHeight(); y++) 914 { 915 for (int x = 0; x < access.getWidth(); x++) 916 { 917 int mx = (x / cellSize) % 2; 918 int my = (y / cellSize) % 2; 919 int mz = (z / cellSize) % 2; 920 921 if (mx ^ my ^ mz) 922 access.setPixel(colorB, x, y, z); 923 else 924 access.setPixel(colorA, x, y, z); 925 } 926 } 927 } 928} 929 930void fillWithGrid (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB) 931{ 932 if (isCombinedDepthStencilType(access.getFormat().type)) 933 { 934 const bool hasDepth = access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::D; 935 const bool hasStencil = access.getFormat().order == tcu::TextureFormat::DS || access.getFormat().order == tcu::TextureFormat::S; 936 937 DE_ASSERT(hasDepth || hasStencil); 938 939 // For combined formats, treat D and S as separate channels 940 if (hasDepth) 941 fillWithGrid(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_DEPTH), cellSize, colorA, colorB); 942 if (hasStencil) 943 fillWithGrid(getEffectiveDepthStencilAccess(access, tcu::Sampler::MODE_STENCIL), cellSize, colorA.swizzle(3,2,1,0), colorB.swizzle(3,2,1,0)); 944 } 945 else 946 { 947 if (access.getHeight() == 1 && access.getDepth() == 1) 948 fillWithGrid1D(access, cellSize, colorA, colorB); 949 else if (access.getDepth() == 1) 950 fillWithGrid2D(access, cellSize, colorA, colorB); 951 else 952 fillWithGrid3D(access, cellSize, colorA, colorB); 953 } 954} 955 956void fillWithRepeatableGradient (const PixelBufferAccess& access, const Vec4& colorA, const Vec4& colorB) 957{ 958 for (int y = 0; y < access.getHeight(); y++) 959 { 960 for (int x = 0; x < access.getWidth(); x++) 961 { 962 float s = ((float)x + 0.5f) / (float)access.getWidth(); 963 float t = ((float)y + 0.5f) / (float)access.getHeight(); 964 965 float a = s > 0.5f ? (2.0f - 2.0f*s) : 2.0f*s; 966 float b = t > 0.5f ? (2.0f - 2.0f*t) : 2.0f*t; 967 968 float p = deFloatClamp(deFloatSqrt(a*a + b*b), 0.0f, 1.0f); 969 access.setPixel(linearInterpolate(p, colorA, colorB), x, y); 970 } 971 } 972} 973 974void fillWithRGBAQuads (const PixelBufferAccess& dst) 975{ 976 TCU_CHECK_INTERNAL(dst.getDepth() == 1); 977 int width = dst.getWidth(); 978 int height = dst.getHeight(); 979 int left = width/2; 980 int top = height/2; 981 982 clear(getSubregion(dst, 0, 0, 0, left, top, 1), Vec4(1.0f, 0.0f, 0.0f, 1.0f)); 983 clear(getSubregion(dst, left, 0, 0, width-left, top, 1), Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 984 clear(getSubregion(dst, 0, top, 0, left, height-top, 1), Vec4(0.0f, 0.0f, 1.0f, 0.0f)); 985 clear(getSubregion(dst, left, top, 0, width-left, height-top, 1), Vec4(0.5f, 0.5f, 0.5f, 1.0f)); 986} 987 988// \todo [2012-11-13 pyry] There is much better metaballs code in CL SIR value generators. 989void fillWithMetaballs (const PixelBufferAccess& dst, int numBalls, deUint32 seed) 990{ 991 TCU_CHECK_INTERNAL(dst.getDepth() == 1); 992 std::vector<Vec2> points(numBalls); 993 de::Random rnd(seed); 994 995 for (int i = 0; i < numBalls; i++) 996 { 997 float x = rnd.getFloat(); 998 float y = rnd.getFloat(); 999 points[i] = (Vec2(x, y)); 1000 } 1001 1002 for (int y = 0; y < dst.getHeight(); y++) 1003 for (int x = 0; x < dst.getWidth(); x++) 1004 { 1005 Vec2 p((float)x/(float)dst.getWidth(), (float)y/(float)dst.getHeight()); 1006 1007 float sum = 0.0f; 1008 for (std::vector<Vec2>::const_iterator i = points.begin(); i != points.end(); i++) 1009 { 1010 Vec2 d = p - *i; 1011 float f = 0.01f / (d.x()*d.x() + d.y()*d.y()); 1012 1013 sum += f; 1014 } 1015 1016 dst.setPixel(Vec4(sum), x, y); 1017 } 1018} 1019 1020void copy (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src) 1021{ 1022 DE_ASSERT(src.getSize() == dst.getSize()); 1023 1024 const int width = dst.getWidth(); 1025 const int height = dst.getHeight(); 1026 const int depth = dst.getDepth(); 1027 1028 const int srcPixelSize = src.getFormat().getPixelSize(); 1029 const int dstPixelSize = dst.getFormat().getPixelSize(); 1030 const int srcPixelPitch = src.getPixelPitch(); 1031 const int dstPixelPitch = dst.getPixelPitch(); 1032 const bool srcTightlyPacked = (srcPixelSize == srcPixelPitch); 1033 const bool dstTightlyPacked = (dstPixelSize == dstPixelPitch); 1034 1035 const bool srcHasDepth = (src.getFormat().order == tcu::TextureFormat::DS || src.getFormat().order == tcu::TextureFormat::D); 1036 const bool srcHasStencil = (src.getFormat().order == tcu::TextureFormat::DS || src.getFormat().order == tcu::TextureFormat::S); 1037 const bool dstHasDepth = (dst.getFormat().order == tcu::TextureFormat::DS || dst.getFormat().order == tcu::TextureFormat::D); 1038 const bool dstHasStencil = (dst.getFormat().order == tcu::TextureFormat::DS || dst.getFormat().order == tcu::TextureFormat::S); 1039 1040 if (src.getFormat() == dst.getFormat() && srcTightlyPacked && dstTightlyPacked) 1041 { 1042 // Fast-path for matching formats. 1043 for (int z = 0; z < depth; z++) 1044 for (int y = 0; y < height; y++) 1045 deMemcpy(dst.getPixelPtr(0, y, z), src.getPixelPtr(0, y, z), srcPixelSize*width); 1046 } 1047 else if (src.getFormat() == dst.getFormat()) 1048 { 1049 // Bit-exact copy for matching formats. 1050 for (int z = 0; z < depth; z++) 1051 for (int y = 0; y < height; y++) 1052 for (int x = 0; x < width; x++) 1053 deMemcpy(dst.getPixelPtr(x, y, z), src.getPixelPtr(x, y, z), srcPixelSize); 1054 } 1055 else if (srcHasDepth || srcHasStencil || dstHasDepth || dstHasStencil) 1056 { 1057 DE_ASSERT((srcHasDepth && dstHasDepth) || (srcHasStencil && dstHasStencil)); // must have at least one common channel 1058 1059 if (dstHasDepth && srcHasDepth) 1060 { 1061 for (int z = 0; z < depth; z++) 1062 for (int y = 0; y < height; y++) 1063 for (int x = 0; x < width; x++) 1064 dst.setPixDepth(src.getPixDepth(x, y, z), x, y, z); 1065 } 1066 else if (dstHasDepth && !srcHasDepth) 1067 { 1068 // consistency with color copies 1069 tcu::clearDepth(dst, 0.0f); 1070 } 1071 1072 if (dstHasStencil && srcHasStencil) 1073 { 1074 for (int z = 0; z < depth; z++) 1075 for (int y = 0; y < height; y++) 1076 for (int x = 0; x < width; x++) 1077 dst.setPixStencil(src.getPixStencil(x, y, z), x, y, z); 1078 } 1079 else if (dstHasStencil && !srcHasStencil) 1080 { 1081 // consistency with color copies 1082 tcu::clearStencil(dst, 0u); 1083 } 1084 } 1085 else 1086 { 1087 TextureChannelClass srcClass = getTextureChannelClass(src.getFormat().type); 1088 TextureChannelClass dstClass = getTextureChannelClass(dst.getFormat().type); 1089 bool srcIsInt = srcClass == TEXTURECHANNELCLASS_SIGNED_INTEGER || srcClass == TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 1090 bool dstIsInt = dstClass == TEXTURECHANNELCLASS_SIGNED_INTEGER || dstClass == TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 1091 1092 if (srcIsInt && dstIsInt) 1093 { 1094 for (int z = 0; z < depth; z++) 1095 for (int y = 0; y < height; y++) 1096 for (int x = 0; x < width; x++) 1097 dst.setPixel(src.getPixelInt(x, y, z), x, y, z); 1098 } 1099 else 1100 { 1101 for (int z = 0; z < depth; z++) 1102 for (int y = 0; y < height; y++) 1103 for (int x = 0; x < width; x++) 1104 dst.setPixel(src.getPixel(x, y, z), x, y, z); 1105 } 1106 } 1107} 1108 1109void scale (const PixelBufferAccess& dst, const ConstPixelBufferAccess& src, Sampler::FilterMode filter) 1110{ 1111 DE_ASSERT(filter == Sampler::NEAREST || filter == Sampler::LINEAR); 1112 1113 Sampler sampler(Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, Sampler::CLAMP_TO_EDGE, 1114 filter, filter, 0.0f, false); 1115 1116 float sX = (float)src.getWidth() / (float)dst.getWidth(); 1117 float sY = (float)src.getHeight() / (float)dst.getHeight(); 1118 float sZ = (float)src.getDepth() / (float)dst.getDepth(); 1119 1120 if (dst.getDepth() == 1 && src.getDepth() == 1) 1121 { 1122 for (int y = 0; y < dst.getHeight(); y++) 1123 for (int x = 0; x < dst.getWidth(); x++) 1124 dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample2D(sampler, filter, ((float)x+0.5f)*sX, ((float)y+0.5f)*sY, 0)), x, y); 1125 } 1126 else 1127 { 1128 for (int z = 0; z < dst.getDepth(); z++) 1129 for (int y = 0; y < dst.getHeight(); y++) 1130 for (int x = 0; x < dst.getWidth(); x++) 1131 dst.setPixel(linearToSRGBIfNeeded(dst.getFormat(), src.sample3D(sampler, filter, ((float)x+0.5f)*sX, ((float)y+0.5f)*sY, ((float)z+0.5f)*sZ)), x, y, z); 1132 } 1133} 1134 1135void estimatePixelValueRange (const ConstPixelBufferAccess& access, Vec4& minVal, Vec4& maxVal) 1136{ 1137 const TextureFormat& format = access.getFormat(); 1138 1139 switch (getTextureChannelClass(format.type)) 1140 { 1141 case TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 1142 // Normalized unsigned formats. 1143 minVal = Vec4(0.0f); 1144 maxVal = Vec4(1.0f); 1145 break; 1146 1147 case TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 1148 // Normalized signed formats. 1149 minVal = Vec4(-1.0f); 1150 maxVal = Vec4(+1.0f); 1151 break; 1152 1153 default: 1154 // \note Samples every 4/8th pixel. 1155 minVal = Vec4(std::numeric_limits<float>::max()); 1156 maxVal = Vec4(std::numeric_limits<float>::min()); 1157 1158 for (int z = 0; z < access.getDepth(); z += 2) 1159 { 1160 for (int y = 0; y < access.getHeight(); y += 2) 1161 { 1162 for (int x = 0; x < access.getWidth(); x += 2) 1163 { 1164 Vec4 p = access.getPixel(x, y, z); 1165 1166 minVal[0] = (deFloatIsNaN(p[0]) ? minVal[0] : de::min(minVal[0], p[0])); 1167 minVal[1] = (deFloatIsNaN(p[1]) ? minVal[1] : de::min(minVal[1], p[1])); 1168 minVal[2] = (deFloatIsNaN(p[2]) ? minVal[2] : de::min(minVal[2], p[2])); 1169 minVal[3] = (deFloatIsNaN(p[3]) ? minVal[3] : de::min(minVal[3], p[3])); 1170 1171 maxVal[0] = (deFloatIsNaN(p[0]) ? maxVal[0] : de::max(maxVal[0], p[0])); 1172 maxVal[1] = (deFloatIsNaN(p[1]) ? maxVal[1] : de::max(maxVal[1], p[1])); 1173 maxVal[2] = (deFloatIsNaN(p[2]) ? maxVal[2] : de::max(maxVal[2], p[2])); 1174 maxVal[3] = (deFloatIsNaN(p[3]) ? maxVal[3] : de::max(maxVal[3], p[3])); 1175 } 1176 } 1177 } 1178 break; 1179 } 1180} 1181 1182void computePixelScaleBias (const ConstPixelBufferAccess& access, Vec4& scale, Vec4& bias) 1183{ 1184 Vec4 minVal, maxVal; 1185 estimatePixelValueRange(access, minVal, maxVal); 1186 1187 const float eps = 0.0001f; 1188 1189 for (int c = 0; c < 4; c++) 1190 { 1191 if (maxVal[c] - minVal[c] < eps) 1192 { 1193 scale[c] = (maxVal[c] < eps) ? 1.0f : (1.0f / maxVal[c]); 1194 bias[c] = (c == 3) ? (1.0f - maxVal[c]*scale[c]) : (0.0f - minVal[c]*scale[c]); 1195 } 1196 else 1197 { 1198 scale[c] = 1.0f / (maxVal[c] - minVal[c]); 1199 bias[c] = 0.0f - minVal[c]*scale[c]; 1200 } 1201 } 1202} 1203 1204int getCubeArrayFaceIndex (CubeFace face) 1205{ 1206 DE_ASSERT((int)face >= 0 && face < CUBEFACE_LAST); 1207 1208 switch (face) 1209 { 1210 case CUBEFACE_POSITIVE_X: return 0; 1211 case CUBEFACE_NEGATIVE_X: return 1; 1212 case CUBEFACE_POSITIVE_Y: return 2; 1213 case CUBEFACE_NEGATIVE_Y: return 3; 1214 case CUBEFACE_POSITIVE_Z: return 4; 1215 case CUBEFACE_NEGATIVE_Z: return 5; 1216 1217 default: 1218 return -1; 1219 } 1220} 1221 1222deUint32 packRGB999E5 (const tcu::Vec4& color) 1223{ 1224 const int mBits = 9; 1225 const int eBits = 5; 1226 const int eBias = 15; 1227 const int eMax = (1<<eBits)-1; 1228 const float maxVal = (float)(((1<<mBits) - 1) * (1<<(eMax-eBias))) / (float)(1<<mBits); 1229 1230 float rc = deFloatClamp(color[0], 0.0f, maxVal); 1231 float gc = deFloatClamp(color[1], 0.0f, maxVal); 1232 float bc = deFloatClamp(color[2], 0.0f, maxVal); 1233 float maxc = de::max(rc, de::max(gc, bc)); 1234 int expp = de::max(-eBias - 1, deFloorFloatToInt32(deFloatLog2(maxc))) + 1 + eBias; 1235 float e = deFloatPow(2.0f, (float)(expp-eBias-mBits)); 1236 int maxs = deFloorFloatToInt32(maxc / e + 0.5f); 1237 1238 deUint32 exps = maxs == (1<<mBits) ? expp+1 : expp; 1239 deUint32 rs = (deUint32)deClamp32(deFloorFloatToInt32(rc / e + 0.5f), 0, (1<<9)-1); 1240 deUint32 gs = (deUint32)deClamp32(deFloorFloatToInt32(gc / e + 0.5f), 0, (1<<9)-1); 1241 deUint32 bs = (deUint32)deClamp32(deFloorFloatToInt32(bc / e + 0.5f), 0, (1<<9)-1); 1242 1243 DE_ASSERT((exps & ~((1<<5)-1)) == 0); 1244 DE_ASSERT((rs & ~((1<<9)-1)) == 0); 1245 DE_ASSERT((gs & ~((1<<9)-1)) == 0); 1246 DE_ASSERT((bs & ~((1<<9)-1)) == 0); 1247 1248 return rs | (gs << 9) | (bs << 18) | (exps << 27); 1249} 1250 1251// Sampler utils 1252 1253static const void* addOffset (const void* ptr, int numBytes) 1254{ 1255 return (const deUint8*)ptr + numBytes; 1256} 1257 1258static void* addOffset (void* ptr, int numBytes) 1259{ 1260 return (deUint8*)ptr + numBytes; 1261} 1262 1263template <typename AccessType> 1264static AccessType toSamplerAccess (const AccessType& baseAccess, Sampler::DepthStencilMode mode) 1265{ 1266 // make sure to update this if type table is updated 1267 DE_STATIC_ASSERT(TextureFormat::CHANNELTYPE_LAST == 40); 1268 1269 if (!isCombinedDepthStencilType(baseAccess.getFormat().type)) 1270 return baseAccess; 1271 else 1272 { 1273#if (DE_ENDIANNESS == DE_LITTLE_ENDIAN) 1274 const deUint32 uint32ByteOffsetBits0To8 = 0; //!< least significant byte in the lowest address 1275 const deUint32 uint32ByteOffsetBits0To24 = 0; 1276 const deUint32 uint32ByteOffsetBits8To32 = 1; 1277 const deUint32 uint32ByteOffsetBits16To32 = 2; 1278 const deUint32 uint32ByteOffsetBits24To32 = 3; 1279#else 1280 const deUint32 uint32ByteOffsetBits0To8 = 3; //!< least significant byte in the highest address 1281 const deUint32 uint32ByteOffsetBits0To24 = 1; 1282 const deUint32 uint32ByteOffsetBits8To32 = 0; 1283 const deUint32 uint32ByteOffsetBits16To32 = 0; 1284 const deUint32 uint32ByteOffsetBits24To32 = 0; 1285#endif 1286 1287 // Sampled channel must exist 1288 DE_ASSERT(baseAccess.getFormat().order == TextureFormat::DS || 1289 (mode == Sampler::MODE_DEPTH && baseAccess.getFormat().order == TextureFormat::D) || 1290 (mode == Sampler::MODE_STENCIL && baseAccess.getFormat().order == TextureFormat::S)); 1291 1292 // combined formats have multiple channel classes, detect on sampler settings 1293 switch (baseAccess.getFormat().type) 1294 { 1295 case TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: 1296 { 1297 if (mode == Sampler::MODE_DEPTH) 1298 { 1299 // select the float component 1300 return AccessType(TextureFormat(TextureFormat::D, TextureFormat::FLOAT), 1301 baseAccess.getSize(), 1302 baseAccess.getPitch(), 1303 baseAccess.getDataPtr()); 1304 } 1305 else if (mode == Sampler::MODE_STENCIL) 1306 { 1307 // select the uint 8 component 1308 return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8), 1309 baseAccess.getSize(), 1310 baseAccess.getPitch(), 1311 addOffset(baseAccess.getDataPtr(), 4 + uint32ByteOffsetBits0To8)); 1312 } 1313 else 1314 { 1315 // unknown sampler mode 1316 DE_ASSERT(false); 1317 return AccessType(); 1318 } 1319 } 1320 1321 case TextureFormat::UNSIGNED_INT_16_8_8: 1322 { 1323 if (mode == Sampler::MODE_DEPTH) 1324 { 1325 // select the unorm16 component 1326 return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT16), 1327 baseAccess.getSize(), 1328 baseAccess.getPitch(), 1329 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits16To32)); 1330 } 1331 else if (mode == Sampler::MODE_STENCIL) 1332 { 1333 // select the uint 8 component 1334 return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8), 1335 baseAccess.getSize(), 1336 baseAccess.getPitch(), 1337 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To8)); 1338 } 1339 else 1340 { 1341 // unknown sampler mode 1342 DE_ASSERT(false); 1343 return AccessType(); 1344 } 1345 } 1346 1347 case TextureFormat::UNSIGNED_INT_24_8: 1348 { 1349 if (mode == Sampler::MODE_DEPTH) 1350 { 1351 // select the unorm24 component 1352 return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT24), 1353 baseAccess.getSize(), 1354 baseAccess.getPitch(), 1355 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits8To32)); 1356 } 1357 else if (mode == Sampler::MODE_STENCIL) 1358 { 1359 // select the uint 8 component 1360 return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8), 1361 baseAccess.getSize(), 1362 baseAccess.getPitch(), 1363 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To8)); 1364 } 1365 else 1366 { 1367 // unknown sampler mode 1368 DE_ASSERT(false); 1369 return AccessType(); 1370 } 1371 } 1372 1373 case TextureFormat::UNSIGNED_INT_24_8_REV: 1374 { 1375 if (mode == Sampler::MODE_DEPTH) 1376 { 1377 // select the unorm24 component 1378 return AccessType(TextureFormat(TextureFormat::D, TextureFormat::UNORM_INT24), 1379 baseAccess.getSize(), 1380 baseAccess.getPitch(), 1381 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits0To24)); 1382 } 1383 else if (mode == Sampler::MODE_STENCIL) 1384 { 1385 // select the uint 8 component 1386 return AccessType(TextureFormat(TextureFormat::S, TextureFormat::UNSIGNED_INT8), 1387 baseAccess.getSize(), 1388 baseAccess.getPitch(), 1389 addOffset(baseAccess.getDataPtr(), uint32ByteOffsetBits24To32)); 1390 } 1391 else 1392 { 1393 // unknown sampler mode 1394 DE_ASSERT(false); 1395 return AccessType(); 1396 } 1397 } 1398 1399 default: 1400 { 1401 // unknown combined format 1402 DE_ASSERT(false); 1403 return AccessType(); 1404 } 1405 } 1406 } 1407} 1408 1409PixelBufferAccess getEffectiveDepthStencilAccess (const PixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode) 1410{ 1411 return toSamplerAccess<PixelBufferAccess>(baseAccess, mode); 1412} 1413 1414ConstPixelBufferAccess getEffectiveDepthStencilAccess (const ConstPixelBufferAccess& baseAccess, Sampler::DepthStencilMode mode) 1415{ 1416 return toSamplerAccess<ConstPixelBufferAccess>(baseAccess, mode); 1417} 1418 1419TextureFormat getEffectiveDepthStencilTextureFormat (const TextureFormat& baseFormat, Sampler::DepthStencilMode mode) 1420{ 1421 return toSamplerAccess(ConstPixelBufferAccess(baseFormat, IVec3(0, 0, 0), DE_NULL), mode).getFormat(); 1422} 1423 1424template <typename ViewType> 1425ViewType getEffectiveTView (const ViewType& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler) 1426{ 1427 storage.resize(src.getNumLevels()); 1428 1429 ViewType view = ViewType(src.getNumLevels(), &storage[0]); 1430 1431 for (int levelNdx = 0; levelNdx < src.getNumLevels(); ++levelNdx) 1432 storage[levelNdx] = tcu::getEffectiveDepthStencilAccess(src.getLevel(levelNdx), sampler.depthStencilMode); 1433 1434 return view; 1435} 1436 1437tcu::TextureCubeView getEffectiveTView (const tcu::TextureCubeView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler) 1438{ 1439 storage.resize(tcu::CUBEFACE_LAST * src.getNumLevels()); 1440 1441 const tcu::ConstPixelBufferAccess* storagePtrs[tcu::CUBEFACE_LAST] = 1442 { 1443 &storage[0 * src.getNumLevels()], 1444 &storage[1 * src.getNumLevels()], 1445 &storage[2 * src.getNumLevels()], 1446 &storage[3 * src.getNumLevels()], 1447 &storage[4 * src.getNumLevels()], 1448 &storage[5 * src.getNumLevels()], 1449 }; 1450 1451 tcu::TextureCubeView view = tcu::TextureCubeView(src.getNumLevels(), storagePtrs); 1452 1453 for (int faceNdx = 0; faceNdx < tcu::CUBEFACE_LAST; ++faceNdx) 1454 for (int levelNdx = 0; levelNdx < src.getNumLevels(); ++levelNdx) 1455 storage[faceNdx * src.getNumLevels() + levelNdx] = tcu::getEffectiveDepthStencilAccess(src.getLevelFace(levelNdx, (tcu::CubeFace)faceNdx), sampler.depthStencilMode); 1456 1457 return view; 1458} 1459 1460tcu::Texture1DView getEffectiveTextureView (const tcu::Texture1DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler) 1461{ 1462 return getEffectiveTView(src, storage, sampler); 1463} 1464 1465tcu::Texture2DView getEffectiveTextureView (const tcu::Texture2DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler) 1466{ 1467 return getEffectiveTView(src, storage, sampler); 1468} 1469 1470tcu::Texture3DView getEffectiveTextureView (const tcu::Texture3DView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler) 1471{ 1472 return getEffectiveTView(src, storage, sampler); 1473} 1474 1475tcu::Texture1DArrayView getEffectiveTextureView (const tcu::Texture1DArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler) 1476{ 1477 return getEffectiveTView(src, storage, sampler); 1478} 1479 1480tcu::Texture2DArrayView getEffectiveTextureView (const tcu::Texture2DArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler) 1481{ 1482 return getEffectiveTView(src, storage, sampler); 1483} 1484 1485tcu::TextureCubeView getEffectiveTextureView (const tcu::TextureCubeView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler) 1486{ 1487 return getEffectiveTView(src, storage, sampler); 1488} 1489 1490tcu::TextureCubeArrayView getEffectiveTextureView (const tcu::TextureCubeArrayView& src, std::vector<tcu::ConstPixelBufferAccess>& storage, const tcu::Sampler& sampler) 1491{ 1492 return getEffectiveTView(src, storage, sampler); 1493} 1494 1495//! Returns the effective swizzle of a border color. The effective swizzle is the 1496//! equal to first writing an RGBA color with a write swizzle and then reading 1497//! it back using a read swizzle, i.e. BorderSwizzle(c) == readSwizzle(writeSwizzle(C)) 1498static const TextureSwizzle& getBorderColorReadSwizzle (TextureFormat::ChannelOrder order) 1499{ 1500 // make sure to update these tables when channel orders are updated 1501 DE_STATIC_ASSERT(TextureFormat::CHANNELORDER_LAST == 21); 1502 1503 static const TextureSwizzle INV = {{ TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE }}; 1504 static const TextureSwizzle R = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE }}; 1505 static const TextureSwizzle A = {{ TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_3 }}; 1506 static const TextureSwizzle I = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0 }}; 1507 static const TextureSwizzle L = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ONE }}; 1508 static const TextureSwizzle LA = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3 }}; 1509 static const TextureSwizzle RG = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE }}; 1510 static const TextureSwizzle RA = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_3 }}; 1511 static const TextureSwizzle RGB = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_ONE }}; 1512 static const TextureSwizzle RGBA = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_3 }}; 1513 static const TextureSwizzle D = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE }}; 1514 static const TextureSwizzle S = {{ TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ZERO, TextureSwizzle::CHANNEL_ONE }}; 1515 1516 const TextureSwizzle* swizzle; 1517 1518 switch (order) 1519 { 1520 case TextureFormat::R: swizzle = &R; break; 1521 case TextureFormat::A: swizzle = &A; break; 1522 case TextureFormat::I: swizzle = &I; break; 1523 case TextureFormat::L: swizzle = &L; break; 1524 case TextureFormat::LA: swizzle = &LA; break; 1525 case TextureFormat::RG: swizzle = &RG; break; 1526 case TextureFormat::RA: swizzle = &RA; break; 1527 case TextureFormat::RGB: swizzle = &RGB; break; 1528 case TextureFormat::RGBA: swizzle = &RGBA; break; 1529 case TextureFormat::ARGB: swizzle = &RGBA; break; 1530 case TextureFormat::BGR: swizzle = &RGB; break; 1531 case TextureFormat::BGRA: swizzle = &RGBA; break; 1532 case TextureFormat::sR: swizzle = &R; break; 1533 case TextureFormat::sRG: swizzle = &RG; break; 1534 case TextureFormat::sRGB: swizzle = &RGB; break; 1535 case TextureFormat::sRGBA: swizzle = &RGBA; break; 1536 case TextureFormat::sBGR: swizzle = &RGB; break; 1537 case TextureFormat::sBGRA: swizzle = &RGBA; break; 1538 case TextureFormat::D: swizzle = &D; break; 1539 case TextureFormat::S: swizzle = &S; break; 1540 1541 case TextureFormat::DS: 1542 DE_ASSERT(false); // combined depth-stencil border color? 1543 swizzle = &INV; 1544 break; 1545 1546 default: 1547 DE_ASSERT(false); 1548 swizzle = &INV; 1549 break; 1550 } 1551 1552#ifdef DE_DEBUG 1553 1554 { 1555 // check that BorderSwizzle(c) == readSwizzle(writeSwizzle(C)) 1556 const TextureSwizzle& readSwizzle = getChannelReadSwizzle(order); 1557 const TextureSwizzle& writeSwizzle = getChannelWriteSwizzle(order); 1558 1559 for (int ndx = 0; ndx < 4; ++ndx) 1560 { 1561 TextureSwizzle::Channel writeRead = readSwizzle.components[ndx]; 1562 if (deInRange32(writeRead, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_3) == DE_TRUE) 1563 writeRead = writeSwizzle.components[(int)writeRead]; 1564 DE_ASSERT(writeRead == swizzle->components[ndx]); 1565 } 1566 } 1567 1568#endif 1569 1570 return *swizzle; 1571} 1572 1573static tcu::UVec4 getNBitUnsignedIntegerVec4MaxValue (const tcu::IVec4& numBits) 1574{ 1575 return tcu::UVec4((numBits[0] > 0) ? (deUintMaxValue32(numBits[0])) : (0), 1576 (numBits[1] > 0) ? (deUintMaxValue32(numBits[1])) : (0), 1577 (numBits[2] > 0) ? (deUintMaxValue32(numBits[2])) : (0), 1578 (numBits[3] > 0) ? (deUintMaxValue32(numBits[3])) : (0)); 1579} 1580 1581static tcu::IVec4 getNBitSignedIntegerVec4MaxValue (const tcu::IVec4& numBits) 1582{ 1583 return tcu::IVec4((numBits[0] > 0) ? (deIntMaxValue32(numBits[0])) : (0), 1584 (numBits[1] > 0) ? (deIntMaxValue32(numBits[1])) : (0), 1585 (numBits[2] > 0) ? (deIntMaxValue32(numBits[2])) : (0), 1586 (numBits[3] > 0) ? (deIntMaxValue32(numBits[3])) : (0)); 1587} 1588 1589static tcu::IVec4 getNBitSignedIntegerVec4MinValue (const tcu::IVec4& numBits) 1590{ 1591 return tcu::IVec4((numBits[0] > 0) ? (deIntMinValue32(numBits[0])) : (0), 1592 (numBits[1] > 0) ? (deIntMinValue32(numBits[1])) : (0), 1593 (numBits[2] > 0) ? (deIntMinValue32(numBits[2])) : (0), 1594 (numBits[3] > 0) ? (deIntMinValue32(numBits[3])) : (0)); 1595} 1596 1597static tcu::Vec4 getTextureBorderColorFloat (const TextureFormat& format, const Sampler& sampler) 1598{ 1599 const tcu::TextureChannelClass channelClass = getTextureChannelClass(format.type); 1600 const TextureSwizzle::Channel* channelMap = getBorderColorReadSwizzle(format.order).components; 1601 const bool isFloat = channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT; 1602 const bool isSigned = channelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 1603 const float valueMin = (isSigned) ? (-1.0f) : (0.0f); 1604 const float valueMax = 1.0f; 1605 Vec4 result; 1606 1607 DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT || 1608 channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || 1609 channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT); 1610 1611 for (int c = 0; c < 4; c++) 1612 { 1613 const TextureSwizzle::Channel map = channelMap[c]; 1614 if (map == TextureSwizzle::CHANNEL_ZERO) 1615 result[c] = 0.0f; 1616 else if (map == TextureSwizzle::CHANNEL_ONE) 1617 result[c] = 1.0f; 1618 else if (isFloat) 1619 { 1620 // floating point values are not clamped 1621 result[c] = sampler.borderColor.getAccess<float>()[(int)map]; 1622 } 1623 else 1624 { 1625 // fixed point values are clamped to a representable range 1626 result[c] = de::clamp(sampler.borderColor.getAccess<float>()[(int)map], valueMin, valueMax); 1627 } 1628 } 1629 1630 return result; 1631} 1632 1633static tcu::IVec4 getTextureBorderColorInt (const TextureFormat& format, const Sampler& sampler) 1634{ 1635 const tcu::TextureChannelClass channelClass = getTextureChannelClass(format.type); 1636 const TextureSwizzle::Channel* channelMap = getBorderColorReadSwizzle(format.order).components; 1637 const IVec4 channelBits = getChannelBitDepth(format.type); 1638 const IVec4 valueMin = getNBitSignedIntegerVec4MinValue(channelBits); 1639 const IVec4 valueMax = getNBitSignedIntegerVec4MaxValue(channelBits); 1640 IVec4 result; 1641 1642 DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER); 1643 DE_UNREF(channelClass); 1644 1645 for (int c = 0; c < 4; c++) 1646 { 1647 const TextureSwizzle::Channel map = channelMap[c]; 1648 if (map == TextureSwizzle::CHANNEL_ZERO) 1649 result[c] = 0; 1650 else if (map == TextureSwizzle::CHANNEL_ONE) 1651 result[c] = 1; 1652 else 1653 { 1654 // integer values are clamped to a representable range 1655 result[c] = de::clamp(sampler.borderColor.getAccess<deInt32>()[(int)map], valueMin[(int)map], valueMax[(int)map]); 1656 } 1657 } 1658 1659 return result; 1660} 1661 1662static tcu::UVec4 getTextureBorderColorUint (const TextureFormat& format, const Sampler& sampler) 1663{ 1664 const tcu::TextureChannelClass channelClass = getTextureChannelClass(format.type); 1665 const TextureSwizzle::Channel* channelMap = getBorderColorReadSwizzle(format.order).components; 1666 const IVec4 channelBits = getChannelBitDepth(format.type); 1667 const UVec4 valueMax = getNBitUnsignedIntegerVec4MaxValue(channelBits); 1668 UVec4 result; 1669 1670 DE_ASSERT(channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER); 1671 DE_UNREF(channelClass); 1672 1673 for (int c = 0; c < 4; c++) 1674 { 1675 const TextureSwizzle::Channel map = channelMap[c]; 1676 if (map == TextureSwizzle::CHANNEL_ZERO) 1677 result[c] = 0; 1678 else if (map == TextureSwizzle::CHANNEL_ONE) 1679 result[c] = 1; 1680 else 1681 { 1682 // integer values are clamped to a representable range 1683 result[c] = de::min(sampler.borderColor.getAccess<deUint32>()[(int)map], valueMax[(int)map]); 1684 } 1685 } 1686 1687 return result; 1688} 1689 1690template <typename ScalarType> 1691tcu::Vector<ScalarType, 4> sampleTextureBorder (const TextureFormat& format, const Sampler& sampler) 1692{ 1693 const tcu::TextureChannelClass channelClass = getTextureChannelClass(format.type); 1694 1695 switch (channelClass) 1696 { 1697 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 1698 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 1699 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 1700 return getTextureBorderColorFloat(format, sampler).cast<ScalarType>(); 1701 1702 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 1703 return getTextureBorderColorInt(format, sampler).cast<ScalarType>(); 1704 1705 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 1706 return getTextureBorderColorUint(format, sampler).cast<ScalarType>(); 1707 1708 default: 1709 DE_ASSERT(false); 1710 return tcu::Vector<ScalarType, 4>(); 1711 } 1712} 1713 1714// instantiation 1715template tcu::Vector<float, 4> sampleTextureBorder (const TextureFormat& format, const Sampler& sampler); 1716template tcu::Vector<deInt32, 4> sampleTextureBorder (const TextureFormat& format, const Sampler& sampler); 1717template tcu::Vector<deUint32, 4> sampleTextureBorder (const TextureFormat& format, const Sampler& sampler); 1718 1719} // tcu 1720