es3fFboTestCase.js (17780B)
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 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('functional.gles3.es3fFboTestCase'); 23 goog.require('framework.common.tcuImageCompare'); 24 goog.require('framework.common.tcuPixelFormat'); 25 goog.require('framework.common.tcuSurface'); 26 goog.require('framework.common.tcuTestCase'); 27 goog.require('framework.common.tcuTexture'); 28 goog.require('framework.delibs.debase.deMath'); 29 goog.require('framework.delibs.debase.deRandom'); 30 goog.require('framework.delibs.debase.deString'); 31 goog.require('framework.opengl.simplereference.sglrGLContext'); 32 goog.require('framework.opengl.simplereference.sglrReferenceContext'); 33 goog.require('framework.referencerenderer.rrRenderer'); 34 goog.require('functional.gles3.es3fFboTestUtil'); 35 36 goog.scope(function() { 37 38 var es3fFboTestCase = functional.gles3.es3fFboTestCase; 39 var tcuTestCase = framework.common.tcuTestCase; 40 var deMath = framework.delibs.debase.deMath; 41 var tcuSurface = framework.common.tcuSurface; 42 var tcuTexture = framework.common.tcuTexture; 43 var rrRenderer = framework.referencerenderer.rrRenderer; 44 var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext; 45 var tcuPixelFormat = framework.common.tcuPixelFormat; 46 var tcuImageCompare = framework.common.tcuImageCompare; 47 var deString = framework.delibs.debase.deString; 48 var sglrGLContext = framework.opengl.simplereference.sglrGLContext; 49 var es3fFboTestUtil = functional.gles3.es3fFboTestUtil; 50 var deRandom = framework.delibs.debase.deRandom; 51 52 /** @typedef {(sglrGLContext.GLContext | WebGL2RenderingContext | sglrReferenceContext.ReferenceContext)} */ 53 es3fFboTestCase.Context; 54 55 var DE_ASSERT = function(x) { 56 if (!x) 57 throw new Error('Assert failed'); 58 }; 59 60 /** 61 * es3fFboTestCase.FboTestCase class, inherits from TestCase and sglrContextWrapper 62 * @constructor 63 * @extends {tcuTestCase.DeqpTest} 64 * @param {string} name 65 * @param {string} description 66 * @param {boolean=} useScreenSizedViewport 67 */ 68 es3fFboTestCase.FboTestCase = function(name, description, useScreenSizedViewport /*= false */) { 69 tcuTestCase.DeqpTest.call(this, name, description); 70 /** @type {number} */ this.m_viewportWidth = useScreenSizedViewport === undefined ? gl.drawingBufferWidth : 128; 71 /** @type {number} */ this.m_viewportHeight = useScreenSizedViewport === undefined ? gl.drawingBufferHeight : 128; 72 /** @type {es3fFboTestCase.Context} */ this.m_curCtx = null; 73 }; 74 75 es3fFboTestCase.FboTestCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 76 es3fFboTestCase.FboTestCase.prototype.constructor = es3fFboTestCase.FboTestCase; 77 78 es3fFboTestCase.FboTestCase.prototype.getWidth = function() { 79 return Math.min(gl.drawingBufferWidth, this.m_viewportWidth); 80 }; 81 82 es3fFboTestCase.FboTestCase.prototype.getHeight = function() { 83 return Math.min(gl.drawingBufferHeight, this.m_viewportHeight); 84 }; 85 86 /** 87 * Sets the current context (inherited from sglrContextWrapper) 88 * @param {es3fFboTestCase.Context} context 89 */ 90 es3fFboTestCase.FboTestCase.prototype.setContext = function(context) { 91 this.m_curCtx = context; 92 }; 93 94 /** 95 * Gets the current context (inherited from sglrContextWrapper) 96 * @return {es3fFboTestCase.Context} 97 */ 98 es3fFboTestCase.FboTestCase.prototype.getCurrentContext = function() { 99 return this.m_curCtx; 100 }; 101 102 /** 103 * @param {tcuSurface.Surface} reference 104 * @param {tcuSurface.Surface} result 105 */ 106 es3fFboTestCase.FboTestCase.prototype.compare = function(reference, result) { 107 return tcuImageCompare.fuzzyCompare('Result', 'Image comparison result', reference.getAccess(), result.getAccess(), 0.05, tcuImageCompare.CompareLogMode.RESULT); 108 }; 109 110 /** 111 * @param {number} sizedFormat 112 */ 113 es3fFboTestCase.FboTestCase.prototype.checkFormatSupport = function(sizedFormat) { 114 /** @const @type {boolean} */ var isCoreFormat = es3fFboTestCase.isRequiredFormat(sizedFormat); 115 /** @const @type {Array<string>} */ var requiredExts = (!isCoreFormat) ? es3fFboTestCase.getEnablingExtensions(sizedFormat) : []; 116 117 // Check that we don't try to use invalid formats. 118 DE_ASSERT(isCoreFormat || requiredExts); 119 if (requiredExts.length > 0 && !es3fFboTestCase.isAnyExtensionSupported(gl, requiredExts)) { 120 var msg = 'SKIP: Format ' + WebGLTestUtils.glEnumToString(gl, sizedFormat) + ' not supported'; 121 debug(msg); 122 throw new TestFailedException(msg); 123 } 124 }; 125 126 /** 127 * @param {number} sizedFormat deUint32 128 * @param {number} numSamples 129 */ 130 es3fFboTestCase.FboTestCase.prototype.checkSampleCount = function(sizedFormat, numSamples) { 131 /** @const @type {number} */ var minSampleCount = es3fFboTestCase.getMinimumSampleCount(sizedFormat); 132 133 if (numSamples > minSampleCount) { 134 // Exceeds spec-mandated minimum - need to check. 135 /** @const @type {goog.NumberArray} */ var supportedSampleCounts = es3fFboTestCase.querySampleCounts(sizedFormat); 136 var supported = Array.prototype.slice.call(supportedSampleCounts); 137 if (supported.indexOf(numSamples) == -1) { 138 if (minSampleCount == 0 || numSamples > gl.getParameter(gl.MAX_SAMPLES)) { 139 checkMessage(false, "Sample count not supported, but it is allowed."); 140 return false; 141 } else { 142 throw new Error('Sample count not supported'); 143 } 144 } 145 return true; 146 } 147 return true; 148 }; 149 150 /** 151 * @param {tcuSurface.Surface} dst 152 * @param {number} x 153 * @param {number} y 154 * @param {number} width 155 * @param {number} height 156 * @param {tcuTexture.TextureFormat} format 157 * @param {Array<number>} scale Vec4 158 * @param {Array<number>} bias Vec4 159 */ 160 es3fFboTestCase.FboTestCase.prototype.readPixelsUsingFormat = function(dst, x, y, width, height, format, scale, bias) { 161 dst.setSize(width, height); 162 es3fFboTestUtil.readPixels(this.getCurrentContext(), dst, x, y, width, height, format, scale, bias); 163 }; 164 165 /** 166 * @param {tcuSurface.Surface} dst 167 * @param {number} x 168 * @param {number} y 169 * @param {number} width 170 * @param {number} height 171 */ 172 es3fFboTestCase.FboTestCase.prototype.readPixels = function(dst, x, y, width, height) { 173 dst.readViewport(this.getCurrentContext(), [x, y, width, height]); 174 }; 175 176 /** 177 * @param {number} target 178 */ 179 es3fFboTestCase.FboTestCase.prototype.checkFramebufferStatus = function(target) { 180 /** @type {number} */ var status = this.getCurrentContext().checkFramebufferStatus(target); 181 if (status != gl.FRAMEBUFFER_COMPLETE) 182 throw new Error('Framebuffer Status: ' + WebGLTestUtils.glEnumToString(gl, status)); 183 }; 184 185 es3fFboTestCase.FboTestCase.prototype.checkError = function() { 186 /** @type {number} */ var err = this.getCurrentContext().getError(); 187 if (err != gl.NO_ERROR) 188 throw new Error('glError: ' + WebGLTestUtils.glEnumToString(gl, err)); 189 }; 190 191 /** 192 * @param {tcuTexture.TextureFormat} format 193 * @param {Array<number>=} value Vec4 194 */ 195 es3fFboTestCase.FboTestCase.prototype.clearColorBuffer = function(format, value) { 196 if (value === undefined) value = [0.0, 0.0, 0.0, 0.0]; 197 es3fFboTestUtil.clearColorBuffer(this.getCurrentContext(), format, value); 198 }; 199 200 es3fFboTestCase.FboTestCase.prototype.iterate = function() { 201 // Viewport. 202 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name)); 203 /** @type {number} */ var width = Math.min(gl.drawingBufferWidth, this.m_viewportWidth); 204 /** @type {number} */ var height = Math.min(gl.drawingBufferHeight, this.m_viewportHeight); 205 /** @type {number} */ var x = rnd.getInt(0, gl.drawingBufferWidth - width); 206 /** @type {number} */ var y = rnd.getInt(0, gl.drawingBufferHeight - height); 207 208 // Surface format and storage is choosen by render(). 209 /** @type {tcuSurface.Surface} */ var reference = new tcuSurface.Surface(width, height); 210 /** @type {tcuSurface.Surface} */ var result = new tcuSurface.Surface(width, height); 211 212 // Call preCheck() that can throw exception if some requirement is not met. 213 if (this.preCheck && !this.preCheck()) 214 return tcuTestCase.IterateResult.STOP; 215 216 // Render using GLES3. 217 try { 218 /** @type {sglrGLContext.GLContext} */ var context = new sglrGLContext.GLContext( 219 gl, 220 [x, y, width, height]); 221 222 this.setContext(context); 223 this.render(result); 224 225 // Check error. 226 /** @type {number} */ var err = context.getError(); 227 if (err != gl.NO_ERROR) 228 throw new Error('glError: ' + context); 229 230 this.setContext(null); 231 } catch (e) { 232 if (e instanceof es3fFboTestUtil.FboIncompleteException) 233 if (e.getReason() == gl.FRAMEBUFFER_UNSUPPORTED) { 234 // log << e; 235 // m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, 'Not supported'); 236 assertMsgOptions(false, 'Not supported', true, false); 237 return tcuTestCase.IterateResult.STOP; 238 } 239 throw e; 240 } 241 242 // Render reference. 243 var alphaBits = /** @type {number} */ (gl.getParameter(gl.ALPHA_BITS)); 244 /** @type {sglrReferenceContext.ReferenceContextBuffers} */ 245 var buffers = new sglrReferenceContext.ReferenceContextBuffers(new tcuPixelFormat.PixelFormat( 246 8, 247 8, 248 8, 249 alphaBits > 0 ? 8 : 0), 250 /** @type {number} */ (gl.getParameter(gl.DEPTH_BITS)), 251 /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS)), 252 width, 253 height); 254 /** @type {sglrReferenceContext.ReferenceContext} */ 255 var refContext = new sglrReferenceContext.ReferenceContext(new sglrReferenceContext.ReferenceContextLimits(gl), 256 buffers.getColorbuffer(), 257 buffers.getDepthbuffer(), 258 buffers.getStencilbuffer()); 259 refContext.getError(); 260 this.setContext(refContext); 261 this.render(reference); 262 this.setContext(null); 263 264 /** @type {boolean} */ var isOk = this.compare(reference, result); 265 266 assertMsgOptions(isOk, '', true, false); 267 268 return tcuTestCase.IterateResult.STOP; 269 }; 270 271 /** 272 * Deinit. Clear some GL state variables 273 */ 274 es3fFboTestCase.FboTestCase.prototype.deinit = function () { 275 // Pixel operations 276 { 277 gl.disable(gl.SCISSOR_TEST); 278 279 gl.disable(gl.STENCIL_TEST); 280 gl.stencilFunc(gl.ALWAYS, 0, 0xffff); 281 gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); 282 283 gl.disable(gl.DEPTH_TEST); 284 gl.depthFunc(gl.LESS); 285 286 gl.disable(gl.BLEND); 287 gl.blendFunc(gl.ONE, gl.ZERO); 288 gl.blendEquation(gl.FUNC_ADD); 289 gl.blendColor(0.0, 0.0, 0.0, 0.0); 290 291 gl.enable(gl.DITHER); 292 } 293 294 // Framebuffer control 295 { 296 gl.colorMask(true, true, true, true); 297 gl.depthMask(true); 298 gl.stencilMask(0xffff); 299 300 gl.clearColor(0.0, 0.0, 0.0, 0.0); 301 gl.clearDepth(1.0); 302 gl.clearStencil(0.0); 303 // Do not call clear() here because it might generate an INVALID_OPERATION if 304 // some color buffers are of integer formats due to WebGL2 specific constraint. 305 // The tests do not rely on clear() here. 306 } 307 }; 308 309 /** 310 * @param {number} format 311 * @return {boolean} 312 */ 313 es3fFboTestCase.isRequiredFormat = function(format) { 314 switch (format) { 315 // Color-renderable formats 316 case gl.RGBA32I: 317 case gl.RGBA32UI: 318 case gl.RGBA16I: 319 case gl.RGBA16UI: 320 case gl.RGBA8: 321 case gl.RGBA8I: 322 case gl.RGBA8UI: 323 case gl.SRGB8_ALPHA8: 324 case gl.RGB10_A2: 325 case gl.RGB10_A2UI: 326 case gl.RGBA4: 327 case gl.RGB5_A1: 328 case gl.RGB8: 329 case gl.RGB565: 330 case gl.RG32I: 331 case gl.RG32UI: 332 case gl.RG16I: 333 case gl.RG16UI: 334 case gl.RG8: 335 case gl.RG8I: 336 case gl.RG8UI: 337 case gl.R32I: 338 case gl.R32UI: 339 case gl.R16I: 340 case gl.R16UI: 341 case gl.R8: 342 case gl.R8I: 343 case gl.R8UI: 344 return true; 345 346 // Depth formats 347 case gl.DEPTH_COMPONENT32F: 348 case gl.DEPTH_COMPONENT24: 349 case gl.DEPTH_COMPONENT16: 350 return true; 351 352 // Depth+stencil formats 353 case gl.DEPTH32F_STENCIL8: 354 case gl.DEPTH24_STENCIL8: 355 return true; 356 357 // Stencil formats 358 case gl.STENCIL_INDEX8: 359 return true; 360 361 default: 362 return false; 363 } 364 }; 365 366 /** 367 * @param {number} format deUint32 368 * @return {Array<string>} 369 */ 370 es3fFboTestCase.getEnablingExtensions = function(format) { 371 /** @return {Array<string>} */ var out = []; 372 373 DE_ASSERT(!es3fFboTestCase.isRequiredFormat(format)); 374 375 switch (format) { 376 case gl.RGBA16F: 377 case gl.RG16F: 378 case gl.R16F: 379 case gl.RGBA32F: 380 case gl.RGB32F: 381 case gl.R11F_G11F_B10F: 382 case gl.RG32F: 383 case gl.R32F: 384 out.push('EXT_color_buffer_float'); 385 break; 386 case gl.RGB16F: 387 // EXT_color_buffer_half_float is not exposed in WebGL 2.0. 388 break; 389 default: 390 break; 391 } 392 393 return out; 394 }; 395 396 /** 397 * @param {es3fFboTestCase.Context} context 398 * @param {Array<string>} requiredExts 399 * @return {boolean} 400 */ 401 es3fFboTestCase.isAnyExtensionSupported = function(context, requiredExts) { 402 for (var iter in requiredExts) { 403 /** @const @type {string} */ var extension = requiredExts[iter]; 404 405 if (sglrGLContext.isExtensionSupported(gl, extension)) { 406 // enable the extension 407 gl.getExtension(extension); 408 return true; 409 } 410 } 411 412 return false; 413 }; 414 415 /** 416 * @param {number} format GL format 417 * @return {number} 418 */ 419 es3fFboTestCase.getMinimumSampleCount = function(format) { 420 switch (format) { 421 // Core formats 422 case gl.RGBA32I: 423 case gl.RGBA32UI: 424 case gl.RGBA16I: 425 case gl.RGBA16UI: 426 case gl.RGBA8: 427 case gl.RGBA8I: 428 case gl.RGBA8UI: 429 case gl.SRGB8_ALPHA8: 430 case gl.RGB10_A2: 431 case gl.RGB10_A2UI: 432 case gl.RGBA4: 433 case gl.RGB5_A1: 434 case gl.RGB8: 435 case gl.RGB565: 436 case gl.RG32I: 437 case gl.RG32UI: 438 case gl.RG16I: 439 case gl.RG16UI: 440 case gl.RG8: 441 case gl.RG8I: 442 case gl.RG8UI: 443 case gl.R32I: 444 case gl.R32UI: 445 case gl.R16I: 446 case gl.R16UI: 447 case gl.R8: 448 case gl.R8I: 449 case gl.R8UI: 450 case gl.DEPTH_COMPONENT32F: 451 case gl.DEPTH_COMPONENT24: 452 case gl.DEPTH_COMPONENT16: 453 case gl.DEPTH32F_STENCIL8: 454 case gl.DEPTH24_STENCIL8: 455 case gl.STENCIL_INDEX8: 456 return 4; 457 458 // gl.EXT_color_buffer_float 459 case gl.R11F_G11F_B10F: 460 case gl.RG16F: 461 case gl.R16F: 462 return 4; 463 464 case gl.RGBA32F: 465 case gl.RGBA16F: 466 case gl.RG32F: 467 case gl.R32F: 468 return 0; 469 470 // gl.EXT_color_buffer_half_float 471 case gl.RGB16F: 472 return 0; 473 474 default: 475 throw new Error('Unknown format:' + format); 476 } 477 }; 478 479 es3fFboTestCase.querySampleCounts = function(format) { 480 return gl.getInternalformatParameter(gl.RENDERBUFFER, format, gl.SAMPLES); 481 }; 482 483 });