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