tcuTextureUtil.js (29498B)
1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES Utilities 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 tcuTextureUtil.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 21 'use strict'; 22 goog.provide('framework.common.tcuTextureUtil'); 23 goog.require('framework.common.tcuTexture'); 24 goog.require('framework.delibs.debase.deMath'); 25 goog.require('framework.delibs.debase.deRandom'); 26 27 goog.scope(function() { 28 29 var tcuTextureUtil = framework.common.tcuTextureUtil; 30 var tcuTexture = framework.common.tcuTexture; 31 var deMath = framework.delibs.debase.deMath; 32 var deRandom = framework.delibs.debase.deRandom; 33 34 var DE_ASSERT = function(x) { 35 if (!x) 36 throw new Error('Assert failed'); 37 }; 38 39 /** 40 * @param {number} t 41 * @param {number} minVal 42 * @param {number} maxVal 43 * @return {number} 44 */ 45 tcuTextureUtil.linearInterpolate = function(t, minVal, maxVal) { 46 return minVal + (maxVal - minVal) * t; 47 }; 48 49 /** tcuTextureUtil.linearChannelToSRGB 50 * @param {number} cl 51 * @return {number} 52 */ 53 tcuTextureUtil.linearChannelToSRGB = function(cl) { 54 if (cl <= 0.0) 55 return 0.0; 56 else if (cl < 0.0031308) 57 return 12.92 * cl; 58 else if (cl < 1.0) 59 return 1.055 * Math.pow(cl, 0.41666) - 0.055; 60 else 61 return 1.0; 62 }; 63 64 /** 65 * Convert sRGB to linear colorspace 66 * @param {Array<number>} cs 67 * @return {Array<number>} 68 */ 69 tcuTextureUtil.sRGBToLinear = function(cs) { 70 return [tcuTextureUtil.sRGBChannelToLinear(cs[0]), 71 tcuTextureUtil.sRGBChannelToLinear(cs[1]), 72 tcuTextureUtil.sRGBChannelToLinear(cs[2]), 73 cs[3]]; 74 }; 75 76 /** 77 * @param {number} cs 78 * @return {number} 79 */ 80 tcuTextureUtil.sRGBChannelToLinear = function(cs) { 81 if (cs <= 0.04045) 82 return cs / 12.92; 83 else 84 return Math.pow((cs + 0.055) / 1.055, 2.4); 85 }; 86 87 /** tcuTextureUtil.linearToSRGB 88 * @param {Array<number>} cl 89 * @return {Array<number>} 90 */ 91 tcuTextureUtil.linearToSRGB = function(cl) { 92 return [tcuTextureUtil.linearChannelToSRGB(cl[0]), 93 tcuTextureUtil.linearChannelToSRGB(cl[1]), 94 tcuTextureUtil.linearChannelToSRGB(cl[2]), 95 cl[3] 96 ]; 97 }; 98 99 /** 100 * tcuTextureUtil.getSubregion 101 * @param {tcuTexture.PixelBufferAccess} access 102 * @param {number} x 103 * @param {number} y 104 * @param {number} z 105 * @param {number} width 106 * @param {number} height 107 * @param {number} depth 108 * @return {tcuTexture.PixelBufferAccess} 109 */ 110 tcuTextureUtil.getSubregion = function(access, x, y, z, width, height, depth) { 111 112 DE_ASSERT(deMath.deInBounds32(x, 0, access.getWidth()) && deMath.deInRange32(x + width, x, access.getWidth())); 113 DE_ASSERT(deMath.deInBounds32(y, 0, access.getHeight()) && deMath.deInRange32(y + height, y, access.getHeight())); 114 DE_ASSERT(deMath.deInBounds32(z, 0, access.getDepth()) && deMath.deInRange32(z + depth, z, access.getDepth())); 115 116 return new tcuTexture.PixelBufferAccess({ 117 format: access.getFormat(), 118 width: width, 119 height: height, 120 depth: depth, 121 rowPitch: access.getRowPitch(), 122 slicePitch: access.getSlicePitch(), 123 offset: access.m_offset + access.getFormat().getPixelSize() * x + access.getRowPitch() * y + access.getSlicePitch() * z, 124 data: access.getBuffer() 125 }); 126 }; 127 128 /** 129 * @param {tcuTexture.PixelBufferAccess} access 130 * @param {Array<number>} minVal 131 * @param {Array<number>} maxVal 132 */ 133 tcuTextureUtil.fillWithComponentGradients1D = function(access, minVal, maxVal) { 134 DE_ASSERT(access.getHeight() == 1); 135 for (var x = 0; x < access.getWidth(); x++) { 136 var s = (x + 0.5) / access.getWidth(); 137 138 var r = tcuTextureUtil.linearInterpolate(s, minVal[0], maxVal[0]); 139 var g = tcuTextureUtil.linearInterpolate(s, minVal[1], maxVal[1]); 140 var b = tcuTextureUtil.linearInterpolate(s, minVal[2], maxVal[2]); 141 var a = tcuTextureUtil.linearInterpolate(s, minVal[3], maxVal[3]); 142 143 access.setPixel([r, g, b, a], x, 0); 144 } 145 }; 146 147 /** 148 * @param {tcuTexture.PixelBufferAccess} access 149 * @param {Array<number>} minVal 150 * @param {Array<number>} maxVal 151 */ 152 tcuTextureUtil.fillWithComponentGradients2D = function(access, minVal, maxVal) { 153 for (var y = 0; y < access.getHeight(); y++) { 154 var t = (y + 0.5) / access.getHeight(); 155 for (var x = 0; x < access.getWidth(); x++) { 156 var s = (x + 0.5) / access.getWidth(); 157 158 var r = tcuTextureUtil.linearInterpolate((s + t) * 0.5, minVal[0], maxVal[0]); 159 var g = tcuTextureUtil.linearInterpolate((s + (1 - t)) * 0.5, minVal[1], maxVal[1]); 160 var b = tcuTextureUtil.linearInterpolate(((1 - s) + t) * 0.5, minVal[2], maxVal[2]); 161 var a = tcuTextureUtil.linearInterpolate(((1 - s) + (1 - t)) * 0.5, minVal[3], maxVal[3]); 162 163 access.setPixel([r, g, b, a], x, y); 164 } 165 } 166 }; 167 168 /** 169 * @param {tcuTexture.PixelBufferAccess} dst 170 * @param {Array<number>} minVal 171 * @param {Array<number>} maxVal 172 */ 173 tcuTextureUtil.fillWithComponentGradients3D = function(dst, minVal, maxVal) { 174 for (var z = 0; z < dst.getDepth(); z++) { 175 var p = (z + 0.5) / dst.getDepth(); 176 var b = tcuTextureUtil.linearInterpolate(p, minVal[2], maxVal[2]); 177 for (var y = 0; y < dst.getHeight(); y++) { 178 var t = (y + 0.5) / dst.getHeight(); 179 var g = tcuTextureUtil.linearInterpolate(t, minVal[1], maxVal[1]); 180 for (var x = 0; x < dst.getWidth(); x++) { 181 var s = (x + 0.5) / dst.getWidth(); 182 var r = tcuTextureUtil.linearInterpolate(s, minVal[0], maxVal[0]); 183 var a = tcuTextureUtil.linearInterpolate(1 - (s + t + p) / 3, minVal[3], maxVal[3]); 184 dst.setPixel([r, g, b, a], x, y, z); 185 } 186 } 187 } 188 }; 189 190 /** 191 * @param {tcuTexture.PixelBufferAccess} access 192 * @param {Array<number>} minVal 193 * @param {Array<number>} maxVal 194 */ 195 tcuTextureUtil.fillWithComponentGradients = function(access, minVal, maxVal) { 196 if (access.getHeight() == 1 && access.getDepth() == 1) 197 tcuTextureUtil.fillWithComponentGradients1D(access, minVal, maxVal); 198 else if (access.getDepth() == 1) 199 tcuTextureUtil.fillWithComponentGradients2D(access, minVal, maxVal); 200 else 201 tcuTextureUtil.fillWithComponentGradients3D(access, minVal, maxVal); 202 }; 203 204 /** 205 * @param {tcuTexture.PixelBufferAccess} dst 206 */ 207 tcuTextureUtil.fillWithRGBAQuads = function(dst) { 208 checkMessage(dst.getDepth() == 1, 'Depth must be 1'); 209 var width = dst.getWidth(); 210 var height = dst.getHeight(); 211 var left = width / 2; 212 var top = height / 2; 213 214 tcuTextureUtil.getSubregion(dst, 0, 0, 0, left, top, 1).clear([1.0, 0.0, 0.0, 1.0]); 215 tcuTextureUtil.getSubregion(dst, left, 0, 0, width - left, top, 1).clear([0.0, 1.0, 0.0, 1.0]); 216 tcuTextureUtil.getSubregion(dst, 0, top, 0, left, height - top, 1).clear([0.0, 0.0, 1.0, 0.0]); 217 tcuTextureUtil.getSubregion(dst, left, top, 0, width - left, height - top, 1).clear([0.5, 0.5, 0.5, 1.0]); 218 }; 219 220 // \todo [2012-11-13 pyry] There is much better metaballs code in CL SIR value generators. 221 /** 222 * @param {tcuTexture.PixelBufferAccess} dst 223 * @param {number} numBalls 224 * @param {number} seed 225 */ 226 tcuTextureUtil.fillWithMetaballs = function(dst, numBalls, seed) { 227 checkMessage(dst.getDepth() == 1, 'Depth must be 1'); 228 var points = []; 229 var rnd = new deRandom.Random(seed); 230 231 for (var i = 0; i < numBalls; i++) { 232 var x = rnd.getFloat(); 233 var y = rnd.getFloat(); 234 points[i] = [x, y]; 235 } 236 237 for (var y = 0; y < dst.getHeight(); y++) 238 for (var x = 0; x < dst.getWidth(); x++) { 239 var p = [x / dst.getWidth(), y / dst.getHeight()]; 240 241 var sum = 0.0; 242 for (var pointNdx = 0; pointNdx < points.length; pointNdx++) { 243 var d = deMath.subtract(p, points[pointNdx]); 244 var f = 0.01 / (d[0] * d[0] + d[1] * d[1]); 245 246 sum += f; 247 } 248 249 dst.setPixel([sum, sum, sum, sum], x, y); 250 } 251 }; 252 253 /** 254 * Create tcuTextureUtil.TextureFormatInfo. 255 * @constructor 256 * @param {Array<number>} valueMin 257 * @param {Array<number>} valueMax 258 * @param {Array<number>} lookupScale 259 * @param {Array<number>} lookupBias 260 */ 261 tcuTextureUtil.TextureFormatInfo = function(valueMin, valueMax, lookupScale, lookupBias) { 262 /** @type {Array<number>} */ this.valueMin = valueMin; 263 /** @type {Array<number>} */ this.valueMax = valueMax; 264 /** @type {Array<number>} */ this.lookupScale = lookupScale; 265 /** @type {Array<number>} */ this.lookupBias = lookupBias; 266 }; 267 268 /** 269 * @param {?tcuTexture.ChannelType} channelType 270 * @return {Array<number>} 271 */ 272 tcuTextureUtil.getChannelValueRange = function(channelType) { 273 var cMin = 0; 274 var cMax = 0; 275 276 switch (channelType) { 277 // Signed normalized formats. 278 case tcuTexture.ChannelType.SNORM_INT8: 279 case tcuTexture.ChannelType.SNORM_INT16: cMin = -1; cMax = 1; break; 280 281 // Unsigned normalized formats. 282 case tcuTexture.ChannelType.UNORM_INT8: 283 case tcuTexture.ChannelType.UNORM_INT16: 284 case tcuTexture.ChannelType.UNORM_SHORT_565: 285 case tcuTexture.ChannelType.UNORM_SHORT_4444: 286 case tcuTexture.ChannelType.UNORM_INT_101010: 287 case tcuTexture.ChannelType.UNORM_INT_1010102_REV: cMin = 0; cMax = 1; break; 288 289 // Misc formats. 290 case tcuTexture.ChannelType.SIGNED_INT8: cMin = -128; cMax = 127; break; 291 case tcuTexture.ChannelType.SIGNED_INT16: cMin = -32768; cMax = 32767; break; 292 case tcuTexture.ChannelType.SIGNED_INT32: cMin = -2147483648; cMax = 2147483647; break; 293 case tcuTexture.ChannelType.UNSIGNED_INT8: cMin = 0; cMax = 255; break; 294 case tcuTexture.ChannelType.UNSIGNED_INT16: cMin = 0; cMax = 65535; break; 295 case tcuTexture.ChannelType.UNSIGNED_INT32: cMin = 0; cMax = 4294967295; break; 296 case tcuTexture.ChannelType.HALF_FLOAT: cMin = -1e3; cMax = 1e3; break; 297 case tcuTexture.ChannelType.FLOAT: cMin = -1e5; cMax = 1e5; break; 298 case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: cMin = 0; cMax = 1e4; break; 299 case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV: cMin = 0; cMax = 1e5; break; 300 301 default: 302 DE_ASSERT(false); 303 } 304 305 return [cMin, cMax]; 306 }; 307 308 /** 309 * Creates an array by choosing between 'a' and 'b' based on 'cond' array. 310 * @param {Array | number} a 311 * @param {Array | number} b 312 * @param {Array<boolean>} cond Condtions 313 * @return {Array} 314 */ 315 tcuTextureUtil.select = function(a, b, cond) { 316 317 /*DE_ASSERT(!(a.length && !b.length) 318 || !(!a.length && b.length) 319 || !((a.length && b.length) && ((a.length != b.length) || (b.length != cond.length) || (a.length != cond.length))));*/ 320 321 if (a.length && !b.length) throw new Error('second input parameter is not a vector'); 322 if (!a.length && b.length) throw new Error('first input parameter is not a vector'); 323 if ((a.length && b.length) && ((a.length != b.length) || (b.length != cond.length) || (a.length != cond.length))) throw new Error('different size vectors'); 324 325 var dst = []; 326 for (var i = 0; i < cond.length; i++) 327 if (cond[i]) { 328 if (a.length) dst.push(a[i]); 329 else dst.push(a); 330 } else { 331 if (b.length) dst.push(b[i]); 332 else dst.push(b); 333 } 334 return dst; 335 }; 336 337 /** 338 * Get standard parameters for testing texture format 339 * 340 * Returns tcuTextureUtil.TextureFormatInfo that describes good parameters for exercising 341 * given TextureFormat. Parameters include value ranges per channel and 342 * suitable lookup scaling and bias in order to reduce result back to 343 * 0..1 range. 344 * 345 * @param {tcuTexture.TextureFormat} format 346 * @return {tcuTextureUtil.TextureFormatInfo} 347 */ 348 tcuTextureUtil.getTextureFormatInfo = function(format) { 349 // Special cases. 350 if (format.isEqual(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV))) 351 return new tcuTextureUtil.TextureFormatInfo([0, 0, 0, 0], 352 [1023, 1023, 1023, 3], 353 [1 / 1023, 1 / 1023, 1 / 1023, 1 / 3], 354 [0, 0, 0, 0]); 355 else if (format.order == tcuTexture.ChannelOrder.D || format.order == tcuTexture.ChannelOrder.DS) 356 return new tcuTextureUtil.TextureFormatInfo([0, 0, 0, 0], 357 [1, 1, 1, 0], 358 [1, 1, 1, 1], 359 [0, 0, 0, 0]); // Depth / stencil formats. 360 else if (format.isEqual(new tcuTexture.TextureFormat(tcuTexture.ChannelOrder.RGBA, tcuTexture.ChannelType.UNORM_SHORT_5551))) 361 return new tcuTextureUtil.TextureFormatInfo([0, 0, 0, 0.5], 362 [1, 1, 1, 1.5], 363 [1, 1, 1, 1], 364 [0, 0, 0, 0]); 365 366 var cRange = tcuTextureUtil.getChannelValueRange(format.type); 367 var chnMask = null; 368 369 switch (format.order) { 370 case tcuTexture.ChannelOrder.R: chnMask = [true, false, false, false]; break; 371 case tcuTexture.ChannelOrder.A: chnMask = [false, false, false, true]; break; 372 case tcuTexture.ChannelOrder.L: chnMask = [true, true, true, false]; break; 373 case tcuTexture.ChannelOrder.LA: chnMask = [true, true, true, true]; break; 374 case tcuTexture.ChannelOrder.RG: chnMask = [true, true, false, false]; break; 375 case tcuTexture.ChannelOrder.RGB: chnMask = [true, true, true, false]; break; 376 case tcuTexture.ChannelOrder.RGBA: chnMask = [true, true, true, true]; break; 377 case tcuTexture.ChannelOrder.sRGB: chnMask = [true, true, true, false]; break; 378 case tcuTexture.ChannelOrder.sRGBA: chnMask = [true, true, true, true]; break; 379 case tcuTexture.ChannelOrder.D: chnMask = [true, true, true, false]; break; 380 case tcuTexture.ChannelOrder.DS: chnMask = [true, true, true, true]; break; 381 default: 382 DE_ASSERT(false); 383 } 384 385 var scale = 1 / (cRange[1] - cRange[0]); 386 var bias = -cRange[0] * scale; 387 388 return new tcuTextureUtil.TextureFormatInfo(tcuTextureUtil.select(cRange[0], 0, chnMask), 389 tcuTextureUtil.select(cRange[1], 0, chnMask), 390 tcuTextureUtil.select(scale, 1, chnMask), 391 tcuTextureUtil.select(bias, 0, chnMask)); 392 }; 393 394 /** tcuTextureUtil.getChannelBitDepth 395 * @param {?tcuTexture.ChannelType} channelType 396 * @return {Array<number>} 397 */ 398 tcuTextureUtil.getChannelBitDepth = function(channelType) { 399 400 switch (channelType) { 401 case tcuTexture.ChannelType.SNORM_INT8: return [8, 8, 8, 8]; 402 case tcuTexture.ChannelType.SNORM_INT16: return [16, 16, 16, 16]; 403 case tcuTexture.ChannelType.SNORM_INT32: return [32, 32, 32, 32]; 404 case tcuTexture.ChannelType.UNORM_INT8: return [8, 8, 8, 8]; 405 case tcuTexture.ChannelType.UNORM_INT16: return [16, 16, 16, 16]; 406 case tcuTexture.ChannelType.UNORM_INT32: return [32, 32, 32, 32]; 407 case tcuTexture.ChannelType.UNORM_SHORT_565: return [5, 6, 5, 0]; 408 case tcuTexture.ChannelType.UNORM_SHORT_4444: return [4, 4, 4, 4]; 409 case tcuTexture.ChannelType.UNORM_SHORT_555: return [5, 5, 5, 0]; 410 case tcuTexture.ChannelType.UNORM_SHORT_5551: return [5, 5, 5, 1]; 411 case tcuTexture.ChannelType.UNORM_INT_101010: return [10, 10, 10, 0]; 412 case tcuTexture.ChannelType.UNORM_INT_1010102_REV: return [10, 10, 10, 2]; 413 case tcuTexture.ChannelType.SIGNED_INT8: return [8, 8, 8, 8]; 414 case tcuTexture.ChannelType.SIGNED_INT16: return [16, 16, 16, 16]; 415 case tcuTexture.ChannelType.SIGNED_INT32: return [32, 32, 32, 32]; 416 case tcuTexture.ChannelType.UNSIGNED_INT8: return [8, 8, 8, 8]; 417 case tcuTexture.ChannelType.UNSIGNED_INT16: return [16, 16, 16, 16]; 418 case tcuTexture.ChannelType.UNSIGNED_INT32: return [32, 32, 32, 32]; 419 case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV: return [10, 10, 10, 2]; 420 case tcuTexture.ChannelType.UNSIGNED_INT_24_8: return [24, 0, 0, 8]; 421 case tcuTexture.ChannelType.HALF_FLOAT: return [16, 16, 16, 16]; 422 case tcuTexture.ChannelType.FLOAT: return [32, 32, 32, 32]; 423 case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: return [11, 11, 10, 0]; 424 case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV: return [9, 9, 9, 0]; 425 case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: return [32, 0, 0, 8]; 426 default: 427 DE_ASSERT(false); 428 return [0, 0, 0, 0]; 429 } 430 }; 431 432 /** tcuTextureUtil.getTextureFormatBitDepth 433 * @param {tcuTexture.TextureFormat} format 434 * @return {Array<number>} 435 */ 436 tcuTextureUtil.getTextureFormatBitDepth = function(format) { 437 438 /** @type {Array<number>} */ var chnBits = tcuTextureUtil.getChannelBitDepth(format.type); // IVec4 439 /** @type {Array<boolean>} */ var chnMask = [false, false, false, false]; // BVec4 440 /** @type {Array<number>} */ var chnSwz = [0, 1, 2, 3]; // IVec4 441 442 switch (format.order) { 443 case tcuTexture.ChannelOrder.R: chnMask = [true, false, false, false]; break; 444 case tcuTexture.ChannelOrder.A: chnMask = [false, false, false, true]; break; 445 case tcuTexture.ChannelOrder.RA: chnMask = [true, false, false, true]; break; 446 case tcuTexture.ChannelOrder.L: chnMask = [true, true, true, false]; break; 447 case tcuTexture.ChannelOrder.I: chnMask = [true, true, true, true]; break; 448 case tcuTexture.ChannelOrder.LA: chnMask = [true, true, true, true]; break; 449 case tcuTexture.ChannelOrder.RG: chnMask = [true, true, false, false]; break; 450 case tcuTexture.ChannelOrder.RGB: chnMask = [true, true, true, false]; break; 451 case tcuTexture.ChannelOrder.RGBA: chnMask = [true, true, true, true]; break; 452 case tcuTexture.ChannelOrder.BGRA: chnMask = [true, true, true, true]; chnSwz = [2, 1, 0, 3]; break; 453 case tcuTexture.ChannelOrder.ARGB: chnMask = [true, true, true, true]; chnSwz = [1, 2, 3, 0]; break; 454 case tcuTexture.ChannelOrder.sRGB: chnMask = [true, true, true, false]; break; 455 case tcuTexture.ChannelOrder.sRGBA: chnMask = [true, true, true, true]; break; 456 case tcuTexture.ChannelOrder.D: chnMask = [true, false, false, false]; break; 457 case tcuTexture.ChannelOrder.DS: chnMask = [true, false, false, true]; break; 458 case tcuTexture.ChannelOrder.S: chnMask = [false, false, false, true]; break; 459 default: 460 DE_ASSERT(false); 461 } 462 463 return tcuTextureUtil.select(deMath.swizzle(chnBits, [chnSwz[0], chnSwz[1], chnSwz[2], chnSwz[3]]), [0, 0, 0, 0], chnMask); 464 465 }; 466 467 /** tcuTextureUtil.fillWithGrid 468 * @const @param {tcuTexture.PixelBufferAccess} access 469 * @param {number} cellSize 470 * @param {Array<number>} colorA 471 * @param {Array<number>} colorB 472 */ 473 tcuTextureUtil.fillWithGrid = function(access, cellSize, colorA, colorB) { 474 if (access.getHeight() == 1 && access.getDepth() == 1) 475 tcuTextureUtil.fillWithGrid1D(access, cellSize, colorA, colorB); 476 else if (access.getDepth() == 1) 477 tcuTextureUtil.fillWithGrid2D(access, cellSize, colorA, colorB); 478 else 479 tcuTextureUtil.fillWithGrid3D(access, cellSize, colorA, colorB); 480 }; 481 482 /** tcuTextureUtil.fillWithGrid1D 483 * @const @param {tcuTexture.PixelBufferAccess} access 484 * @param {number} cellSize 485 * @param {Array<number>} colorA 486 * @param {Array<number>} colorB 487 */ 488 tcuTextureUtil.fillWithGrid1D = function(access, cellSize, colorA, colorB) { 489 for (var x = 0; x < access.getWidth(); x++) { 490 var mx = Math.floor(x / cellSize) % 2; 491 492 if (mx) 493 access.setPixel(colorB, x, 0); 494 else 495 access.setPixel(colorA, x, 0); 496 } 497 }; 498 499 /** tcuTextureUtil.fillWithGrid2D 500 * @const @param {tcuTexture.PixelBufferAccess} access 501 * @param {number} cellSize 502 * @param {Array<number>} colorA 503 * @param {Array<number>} colorB 504 */ 505 tcuTextureUtil.fillWithGrid2D = function(access, cellSize, colorA, colorB) { 506 for (var y = 0; y < access.getHeight(); y++) 507 for (var x = 0; x < access.getWidth(); x++) { 508 var mx = Math.floor(x / cellSize) % 2; 509 var my = Math.floor(y / cellSize) % 2; 510 511 if (mx ^ my) 512 access.setPixel(colorB, x, y); 513 else 514 access.setPixel(colorA, x, y); 515 } 516 }; 517 518 /** tcuTextureUtil.fillWithGrid3D 519 * @const @param {tcuTexture.PixelBufferAccess} access 520 * @param {number} cellSize 521 * @param {Array<number>} colorA 522 * @param {Array<number>} colorB 523 */ 524 tcuTextureUtil.fillWithGrid3D = function(access, cellSize, colorA, colorB) { 525 for (var z = 0; z < access.getDepth(); z++) 526 for (var y = 0; y < access.getHeight(); y++) 527 for (var x = 0; x < access.getWidth(); x++) { 528 var mx = Math.floor(x / cellSize) % 2; 529 var my = Math.floor(y / cellSize) % 2; 530 var mz = Math.floor(z / cellSize) % 2; 531 532 if (mx ^ my ^ mz) 533 access.setPixel(colorB, x, y, z); 534 else 535 access.setPixel(colorA, x, y, z); 536 } 537 }; 538 539 /** 540 * @const @param {tcuTexture.TextureFormat} format 541 * @return {Array<number>} 542 */ 543 tcuTextureUtil.getTextureFormatMantissaBitDepth = function(format) { 544 /** @type {Array<number>} */ var chnBits = tcuTextureUtil.getChannelMantissaBitDepth(format.type); 545 /** @type {Array<boolean>} */ var chnMask = [false, false, false, false]; 546 /** @type {Array<number>} */ var chnSwz = [0, 1, 2, 3]; 547 548 switch (format.order) { 549 case tcuTexture.ChannelOrder.R: chnMask = [true, false, false, false]; break; 550 case tcuTexture.ChannelOrder.A: chnMask = [false, false, false, true]; break; 551 case tcuTexture.ChannelOrder.RA: chnMask = [true, false, false, true]; break; 552 case tcuTexture.ChannelOrder.L: chnMask = [true, true, true, false]; break; 553 case tcuTexture.ChannelOrder.I: chnMask = [true, true, true, true]; break; 554 case tcuTexture.ChannelOrder.LA: chnMask = [true, true, true, true]; break; 555 case tcuTexture.ChannelOrder.RG: chnMask = [true, true, false, false]; break; 556 case tcuTexture.ChannelOrder.RGB: chnMask = [true, true, true, false]; break; 557 case tcuTexture.ChannelOrder.RGBA: chnMask = [true, true, true, true]; break; 558 case tcuTexture.ChannelOrder.BGRA: chnMask = [true, true, true, true]; chnSwz = [2, 1, 0, 3]; break; 559 case tcuTexture.ChannelOrder.ARGB: chnMask = [true, true, true, true]; chnSwz = [1, 2, 3, 0]; break; 560 case tcuTexture.ChannelOrder.sRGB: chnMask = [true, true, true, false]; break; 561 case tcuTexture.ChannelOrder.sRGBA: chnMask = [true, true, true, true]; break; 562 case tcuTexture.ChannelOrder.D: chnMask = [true, false, false, false]; break; 563 case tcuTexture.ChannelOrder.DS: chnMask = [true, false, false, true]; break; 564 case tcuTexture.ChannelOrder.S: chnMask = [false, false, false, true]; break; 565 default: 566 DE_ASSERT(false); 567 } 568 return tcuTextureUtil.select(deMath.swizzle(chnBits, [chnSwz[0], chnSwz[1], chnSwz[2], chnSwz[3]]), [0, 0, 0, 0], chnMask); 569 }; 570 571 /** 572 * @param {?tcuTexture.ChannelType} channelType 573 * @return {Array<number>} 574 */ 575 tcuTextureUtil.getChannelMantissaBitDepth = function(channelType) { 576 switch (channelType) { 577 case tcuTexture.ChannelType.SNORM_INT8: 578 case tcuTexture.ChannelType.SNORM_INT16: 579 case tcuTexture.ChannelType.SNORM_INT32: 580 case tcuTexture.ChannelType.UNORM_INT8: 581 case tcuTexture.ChannelType.UNORM_INT16: 582 case tcuTexture.ChannelType.UNORM_INT32: 583 case tcuTexture.ChannelType.UNORM_SHORT_565: 584 case tcuTexture.ChannelType.UNORM_SHORT_4444: 585 case tcuTexture.ChannelType.UNORM_SHORT_555: 586 case tcuTexture.ChannelType.UNORM_SHORT_5551: 587 case tcuTexture.ChannelType.UNORM_INT_101010: 588 case tcuTexture.ChannelType.UNORM_INT_1010102_REV: 589 case tcuTexture.ChannelType.SIGNED_INT8: 590 case tcuTexture.ChannelType.SIGNED_INT16: 591 case tcuTexture.ChannelType.SIGNED_INT32: 592 case tcuTexture.ChannelType.UNSIGNED_INT8: 593 case tcuTexture.ChannelType.UNSIGNED_INT16: 594 case tcuTexture.ChannelType.UNSIGNED_INT32: 595 case tcuTexture.ChannelType.UNSIGNED_INT_1010102_REV: 596 case tcuTexture.ChannelType.UNSIGNED_INT_24_8: 597 case tcuTexture.ChannelType.UNSIGNED_INT_999_E5_REV: 598 return tcuTextureUtil.getChannelBitDepth(channelType); 599 case tcuTexture.ChannelType.HALF_FLOAT: return [10, 10, 10, 10]; 600 case tcuTexture.ChannelType.FLOAT: return [23, 23, 23, 23]; 601 case tcuTexture.ChannelType.UNSIGNED_INT_11F_11F_10F_REV: return [6, 6, 5, 0]; 602 case tcuTexture.ChannelType.FLOAT_UNSIGNED_INT_24_8_REV: return [23, 0, 0, 8]; 603 default: 604 throw new Error('Invalid channelType: ' + channelType); 605 } 606 }; 607 608 /** 609 * @param {tcuTexture.PixelBufferAccess} dst 610 * @param {tcuTexture.ConstPixelBufferAccess} src 611 */ 612 tcuTextureUtil.copy = function(dst, src) { 613 var width = dst.getWidth(); 614 var height = dst.getHeight(); 615 var depth = dst.getDepth(); 616 617 DE_ASSERT(src.getWidth() == width && src.getHeight() == height && src.getDepth() == depth); 618 619 if (src.getFormat().isEqual(dst.getFormat())) { 620 var srcData = src.getDataPtr(); 621 var dstData = dst.getDataPtr(); 622 623 if (srcData.length == dstData.length) { 624 dstData.set(srcData); 625 return; 626 } 627 } 628 var srcClass = tcuTexture.getTextureChannelClass(src.getFormat().type); 629 var dstClass = tcuTexture.getTextureChannelClass(dst.getFormat().type); 630 var srcIsInt = srcClass == tcuTexture.TextureChannelClass.SIGNED_INTEGER || srcClass == tcuTexture.TextureChannelClass.UNSIGNED_INTEGER; 631 var dstIsInt = dstClass == tcuTexture.TextureChannelClass.SIGNED_INTEGER || dstClass == tcuTexture.TextureChannelClass.UNSIGNED_INTEGER; 632 633 if (srcIsInt && dstIsInt) { 634 for (var z = 0; z < depth; z++) 635 for (var y = 0; y < height; y++) 636 for (var x = 0; x < width; x++) 637 dst.setPixelInt(src.getPixelInt(x, y, z), x, y, z); 638 } else { 639 for (var z = 0; z < depth; z++) 640 for (var y = 0; y < height; y++) 641 for (var x = 0; x < width; x++) 642 dst.setPixel(src.getPixel(x, y, z), x, y, z); 643 } 644 }; 645 646 /** 647 * @param {tcuTexture.ConstPixelBufferAccess} access 648 */ 649 tcuTextureUtil.estimatePixelValueRange = function(access) { 650 var format = access.getFormat(); 651 652 switch (format.type) { 653 case tcuTexture.ChannelType.UNORM_INT8: 654 case tcuTexture.ChannelType.UNORM_INT16: 655 // Normalized unsigned formats. 656 return [ 657 [0, 0, 0, 0], 658 [1, 1, 1, 1] 659 ]; 660 661 case tcuTexture.ChannelType.SNORM_INT8: 662 case tcuTexture.ChannelType.SNORM_INT16: 663 // Normalized signed formats. 664 return [ 665 [-1, -1, -1, -1], 666 [1, 1, 1, 1] 667 ]; 668 669 default: 670 // \note Samples every 4/8th pixel. 671 var minVal = [Infinity, Infinity, Infinity, Infinity]; 672 var maxVal = [-Infinity, -Infinity, -Infinity, -Infinity]; 673 674 for (var z = 0; z < access.getDepth(); z += 2) { 675 for (var y = 0; y < access.getHeight(); y += 2) { 676 for (var x = 0; x < access.getWidth(); x += 2) { 677 var p = access.getPixel(x, y, z); 678 679 minVal[0] = Math.min(minVal[0], p[0]); 680 minVal[1] = Math.min(minVal[1], p[1]); 681 minVal[2] = Math.min(minVal[2], p[2]); 682 minVal[3] = Math.min(minVal[3], p[3]); 683 684 maxVal[0] = Math.max(maxVal[0], p[0]); 685 maxVal[1] = Math.max(maxVal[1], p[1]); 686 maxVal[2] = Math.max(maxVal[2], p[2]); 687 maxVal[3] = Math.max(maxVal[3], p[3]); 688 } 689 } 690 } 691 return [minVal, maxVal]; 692 } 693 }; 694 695 /** 696 * @param {tcuTexture.ConstPixelBufferAccess} access 697 * @return {{scale: Array<number>, bias: Array<number>}} 698 */ 699 tcuTextureUtil.computePixelScaleBias = function(access) { 700 var limits = tcuTextureUtil.estimatePixelValueRange(access); 701 var minVal = limits[0]; 702 var maxVal = limits[1]; 703 704 var scale = [1, 1, 1, 1]; 705 var bias = [0, 0, 0, 0]; 706 707 var eps = 0.0001; 708 709 for (var c = 0; c < 4; c++) { 710 if (maxVal[c] - minVal[c] < eps) { 711 scale[c] = (maxVal[c] < eps) ? 1 : (1 / maxVal[c]); 712 bias[c] = (c == 3) ? (1 - maxVal[c] * scale[c]) : (0 - minVal[c] * scale[c]); 713 } else { 714 scale[c] = 1 / (maxVal[c] - minVal[c]); 715 bias[c] = 0 - minVal[c] * scale[c]; 716 } 717 } 718 719 return { 720 scale: scale, 721 bias: bias 722 }; 723 }; 724 725 });