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