es3fPrimitiveRestartTests.js (34632B)
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.es3fPrimitiveRestartTests'); 23 goog.require('framework.common.tcuImageCompare'); 24 goog.require('framework.common.tcuSurface'); 25 goog.require('framework.common.tcuTestCase'); 26 goog.require('framework.delibs.debase.deMath'); 27 goog.require('framework.delibs.debase.deRandom'); 28 goog.require('framework.delibs.debase.deString'); 29 goog.require('framework.opengl.gluShaderProgram'); 30 goog.require('framework.opengl.gluTextureUtil'); 31 32 goog.scope(function() { 33 34 var es3fPrimitiveRestartTests = functional.gles3.es3fPrimitiveRestartTests; 35 var tcuTestCase = framework.common.tcuTestCase; 36 var gluShaderProgram = framework.opengl.gluShaderProgram; 37 var tcuSurface = framework.common.tcuSurface; 38 var deMath = framework.delibs.debase.deMath; 39 var deRandom = framework.delibs.debase.deRandom; 40 var deString = framework.delibs.debase.deString; 41 var tcuImageCompare = framework.common.tcuImageCompare; 42 var gluTextureUtil = framework.opengl.gluTextureUtil; 43 44 /** @type {WebGL2RenderingContext} */ var gl; 45 /** @const @type {number} */ es3fPrimitiveRestartTests.MAX_RENDER_WIDTH = 256; 46 /** @const @type {number} */ es3fPrimitiveRestartTests.MAX_RENDER_HEIGHT = 256; 47 48 /** @const @type {number} */ es3fPrimitiveRestartTests.MAX_UNSIGNED_BYTE = 255; 49 /** @const @type {number} */ es3fPrimitiveRestartTests.MAX_UNSIGNED_SHORT = 65535; 50 /** @const @type {number} */ es3fPrimitiveRestartTests.MAX_UNSIGNED_INT = 4294967295; 51 52 /** @const @type {number} */ es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_BYTE = es3fPrimitiveRestartTests.MAX_UNSIGNED_BYTE; 53 /** @const @type {number} */ es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_SHORT = es3fPrimitiveRestartTests.MAX_UNSIGNED_SHORT; 54 /** @const @type {number} */ es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_INT = es3fPrimitiveRestartTests.MAX_UNSIGNED_INT; 55 56 var DE_ASSERT = function(expression) { 57 if (!expression) throw new Error('Assert failed'); 58 }; 59 60 /** 61 * @enum 62 */ 63 es3fPrimitiveRestartTests.PrimitiveType = { 64 PRIMITIVE_POINTS: 0, 65 PRIMITIVE_LINE_STRIP: 1, 66 PRIMITIVE_LINE_LOOP: 2, 67 PRIMITIVE_LINES: 3, 68 PRIMITIVE_TRIANGLE_STRIP: 4, 69 PRIMITIVE_TRIANGLE_FAN: 5, 70 PRIMITIVE_TRIANGLES: 6 71 }; 72 73 /** 74 * @enum 75 */ 76 es3fPrimitiveRestartTests.IndexType = { 77 INDEX_UNSIGNED_BYTE: 0, 78 INDEX_UNSIGNED_SHORT: 1, 79 INDEX_UNSIGNED_INT: 2 80 }; 81 82 /** 83 * @enum 84 */ 85 es3fPrimitiveRestartTests.DrawFunction = { 86 FUNCTION_DRAW_ELEMENTS: 0, 87 FUNCTION_DRAW_ELEMENTS_INSTANCED: 1, 88 FUNCTION_DRAW_RANGE_ELEMENTS: 2 89 }; 90 91 /** 92 * es3fPrimitiveRestartTests.PrimitiveRestartCase class, inherits from TestCase class 93 * @constructor 94 * @extends {tcuTestCase.DeqpTest} 95 * @param {?string} name 96 * @param {string} description 97 * @param {es3fPrimitiveRestartTests.PrimitiveType} primType 98 * @param {es3fPrimitiveRestartTests.IndexType} indexType 99 * @param {es3fPrimitiveRestartTests.DrawFunction} _function 100 * @param {boolean} beginWithRestart 101 * @param {boolean} endWithRestart 102 * @param {boolean} duplicateRestarts 103 */ 104 es3fPrimitiveRestartTests.PrimitiveRestartCase = function(name, description, primType, indexType, _function, beginWithRestart, endWithRestart, duplicateRestarts) { 105 tcuTestCase.DeqpTest.call(this, name, description); 106 /** @type {es3fPrimitiveRestartTests.PrimitiveType} */ this.m_primType = primType; 107 /** @type {es3fPrimitiveRestartTests.IndexType} */ this.m_indexType = indexType; 108 /** @type {es3fPrimitiveRestartTests.DrawFunction} */ this.m_function = _function; 109 /** @type {boolean} */ this.m_beginWithRestart = beginWithRestart; // Whether there will be restart indices at the beginning of the index array. 110 /** @type {boolean} */ this.m_endWithRestart = endWithRestart; // Whether there will be restart indices at the end of the index array. 111 /** @type {boolean} */ this.m_duplicateRestarts = duplicateRestarts; // Whether two consecutive restarts are used instead of one. 112 /** @type {gluShaderProgram.ShaderProgram} */ this.m_program = null; 113 114 // \note Only one of the following index vectors is used (according to m_indexType). 115 /** @type {Array<number>} */ this.m_indicesUB = []; //deUint8 116 /** @type {Array<number>} */ this.m_indicesUS = []; //deUint16 117 /** @type {Array<number>} */ this.m_indicesUI = []; //deUint32 118 119 /** @type {Array<number>} */ this.m_positions = []; 120 }; 121 122 es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); 123 es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.constructor = es3fPrimitiveRestartTests.PrimitiveRestartCase; 124 125 /** 126 * Draw with the appropriate GLES3 draw function. 127 * @param {number} startNdx 128 * @param {number} count 129 */ 130 es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.draw = function(startNdx, count) { 131 /** @type {number} */ var primTypeGL; 132 133 switch (this.m_primType) { 134 case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_POINTS: 135 primTypeGL = gl.POINTS; 136 break; 137 case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_STRIP: 138 primTypeGL = gl.LINE_STRIP; 139 break; 140 case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_LOOP: 141 primTypeGL = gl.LINE_LOOP; 142 break; 143 case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINES: 144 primTypeGL = gl.LINES; 145 break; 146 case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_STRIP: 147 primTypeGL = gl.TRIANGLE_STRIP; 148 break; 149 case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_FAN: 150 primTypeGL = gl.TRIANGLE_FAN; 151 break; 152 case es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLES: 153 primTypeGL = gl.TRIANGLES; 154 break; 155 default: 156 DE_ASSERT(false); 157 primTypeGL = 0; 158 } 159 160 /** @type {number} */ var indexTypeGL; 161 162 switch (this.m_indexType) { 163 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE: 164 indexTypeGL = gl.UNSIGNED_BYTE; 165 break; 166 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT: 167 indexTypeGL = gl.UNSIGNED_SHORT; 168 break; 169 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT: 170 indexTypeGL = gl.UNSIGNED_INT; 171 break; 172 default: 173 DE_ASSERT(false); 174 indexTypeGL = 0; 175 } 176 177 /** @type {number} */ var restartIndex = this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_BYTE : 178 this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_SHORT : 179 this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_INT : 180 0; 181 182 DE_ASSERT(restartIndex != 0); 183 184 var indexGLBuffer = gl.createBuffer(); 185 var bufferIndex = this.getIndexPtr(startNdx); 186 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexGLBuffer); 187 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, bufferIndex, gl.STATIC_DRAW); 188 189 if (this.m_function == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_ELEMENTS) { 190 gl.drawElements(primTypeGL, count, indexTypeGL, 0); 191 } else if (this.m_function == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_ELEMENTS_INSTANCED) { 192 gl.drawElementsInstanced(primTypeGL, count, indexTypeGL, 0, 1); 193 } else { 194 DE_ASSERT(this.m_function == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_RANGE_ELEMENTS); 195 196 // Find the largest non-restart index in the index array (for glDrawRangeElements() end parameter). 197 198 /** @type {number} */ var max = 0; 199 200 /** @type {number} */ var numIndices = this.getNumIndices(); 201 for (var i = 0; i < numIndices; i++) { 202 /** @type {number} */ var index = this.getIndex(i); 203 if (index != restartIndex && index > max) 204 max = index; 205 } 206 //TODO: drawRangeElements -> check getIndexPtr usage 207 gl.drawRangeElements(primTypeGL, 0, max, count, indexTypeGL, 0); 208 } 209 }; 210 211 es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.renderWithRestart = function() { 212 // Primitive Restart is always on in WebGL2 213 //gl.enable(gl.PRIMITIVE_RESTART_FIXED_INDEX); 214 215 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 216 217 this.draw(0, this.getNumIndices()); 218 }; 219 220 es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.renderWithoutRestart = function() { 221 /** @type {number} */ var restartIndex = this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_BYTE : 222 this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_SHORT : 223 this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_INT : 224 0; 225 226 DE_ASSERT(restartIndex != 0); 227 // Primitive Restart is always on in WebGL2 228 //gl.disable(gl.PRIMITIVE_RESTART_FIXED_INDEX); 229 230 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 231 232 // Draw, emulating primitive restart. 233 234 /** @type {number} */ var numIndices = this.getNumIndices(); 235 236 DE_ASSERT(numIndices >= 0); 237 238 /** @type {number} */ var indexArrayStartNdx = 0; // Keep track of the draw start index - first index after a primitive restart, or initially the first index altogether. 239 240 for (var indexArrayNdx = 0; indexArrayNdx <= numIndices; indexArrayNdx++) { // \note Goes one "too far" in order to detect end of array as well. 241 if (indexArrayNdx >= numIndices || this.getIndex(indexArrayNdx) == restartIndex) {// \note Handle end of array the same way as a restart index encounter. 242 if (indexArrayStartNdx < numIndices) { 243 // Draw from index indexArrayStartNdx to index indexArrayNdx-1 . 244 245 this.draw(indexArrayStartNdx, indexArrayNdx - indexArrayStartNdx); 246 } 247 248 indexArrayStartNdx = indexArrayNdx + 1; // Next draw starts just after this restart index. 249 } 250 } 251 }; 252 253 /** 254 * @param {number} index 255 */ 256 es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.addIndex = function(index) { 257 if (this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE) { 258 DE_ASSERT(deMath.deInRange32(index, 0, es3fPrimitiveRestartTests.MAX_UNSIGNED_BYTE)); 259 this.m_indicesUB.push(index); // deUint8 260 } else if (this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT) { 261 DE_ASSERT(deMath.deInRange32(index, 0, es3fPrimitiveRestartTests.MAX_UNSIGNED_SHORT)); 262 this.m_indicesUS.push(index); // deUint16 263 } else if (this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT) { 264 DE_ASSERT(deMath.deInRange32(index, 0, es3fPrimitiveRestartTests.MAX_UNSIGNED_INT)); 265 this.m_indicesUI.push(index); // // deUint32 266 } else 267 DE_ASSERT(false); 268 }; 269 270 /** 271 * @param {number} indexNdx 272 * @return {number} 273 */ 274 es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.getIndex = function(indexNdx) { 275 switch (this.m_indexType) { 276 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE: 277 return this.m_indicesUB[indexNdx]; //deUint32 278 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT: 279 return this.m_indicesUS[indexNdx]; //deUint32 280 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT: 281 return this.m_indicesUI[indexNdx]; 282 default: 283 DE_ASSERT(false); 284 return 0; 285 } 286 }; 287 288 /** 289 * @return {number} 290 */ 291 es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.getNumIndices = function() { 292 switch (this.m_indexType) { 293 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE: 294 return this.m_indicesUB.length; 295 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT: 296 return this.m_indicesUS.length; 297 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT: 298 return this.m_indicesUI.length; 299 default: 300 DE_ASSERT(false); 301 return 0; 302 } 303 }; 304 305 /** 306 * Pointer to the index value at index indexNdx. 307 * @param {number} indexNdx 308 * @return {Uint8Array|Uint16Array|Uint32Array} 309 */ 310 es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.getIndexPtr = function(indexNdx) { 311 //TODO: implement 312 switch (this.m_indexType) { 313 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE: 314 return new Uint8Array(this.m_indicesUB).subarray(indexNdx); 315 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT: 316 return new Uint16Array(this.m_indicesUS).subarray(indexNdx); 317 case es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT: 318 return new Uint32Array(this.m_indicesUI).subarray(indexNdx); 319 default: 320 DE_ASSERT(false); 321 return null; 322 } 323 }; 324 325 es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.init = function() { 326 // Clear errors from previous tests 327 gl.getError(); 328 329 // Create shader program. 330 331 /** @type {string} */ var vertShaderSource = 332 '#version 300 es\n' + 333 'in highp vec4 a_position;\n' + 334 '\n' + 335 'void main()\n' + 336 ' {\n' + 337 ' gl_Position = a_position;\n'; 338 339 if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_POINTS) { 340 vertShaderSource += ' gl_PointSize = 1.0;\n'; 341 } 342 343 vertShaderSource += '}\n'; 344 345 /** @type {string} */ var fragShaderSource = 346 '#version 300 es\n' + 347 'layout(location = 0) out mediump vec4 o_color;\n' + 348 '\n' + 349 'void main()\n' + 350 ' {\n' + 351 ' o_color = vec4(1.0f);\n' + 352 '}\n'; 353 354 DE_ASSERT(!this.m_program); 355 356 this.m_program = new gluShaderProgram.ShaderProgram(gl, gluShaderProgram.makeVtxFragSources(vertShaderSource, fragShaderSource)); 357 358 if (!this.m_program.isOk()) { 359 //m_testCtx.getLog() << *this.m_program; 360 testFailedOptions('Failed to compile shader', true); 361 } 362 363 /** @type {number} */ var restartIndex = this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_BYTE : 364 this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_SHORT : 365 this.m_indexType == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT ? es3fPrimitiveRestartTests.RESTART_INDEX_UNSIGNED_INT : 366 0; 367 368 DE_ASSERT(restartIndex != 0); 369 370 DE_ASSERT(this.getNumIndices() == 0); 371 372 // If testing a case with restart at beginning, add it there. 373 if (this.m_beginWithRestart) { 374 this.addIndex(restartIndex); 375 if (this.m_duplicateRestarts) 376 this.addIndex(restartIndex); 377 } 378 379 // Generate vertex positions and indices depending on primitive type. 380 // \note At this point, restarts shall not be added to the start or the end of the index vector. Those are special cases, and are done above and after the following if-else chain, respectively. 381 /** @type {number} */ var curIndex; 382 /** @type {number} */ var numRows; 383 /** @type {number} */ var numCols; 384 /** @type {number} */ var fx; 385 /** @type {number} */ var fy; 386 /** @type {number} */ var centerY; 387 /** @type {number} */ var centerX; 388 /** @type {number} */ var numVertices; 389 /** @type {number} */ var numArcVertices; 390 /** @type {number} */ var numStrips; 391 392 if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_POINTS) { 393 // Generate rows with different numbers of points. 394 395 curIndex = 0; 396 numRows = 20; 397 398 for (var row = 0; row < numRows; row++) { 399 for (var col = 0; col < row + 1; col++) { 400 fx = -1.0 + 2.0 * (col + 0.5) / numRows; 401 fy = -1.0 + 2.0 * (row + 0.5) / numRows; 402 403 this.m_positions.push(fx); 404 this.m_positions.push(fy); 405 406 this.addIndex(curIndex++); 407 } 408 409 if (row < numRows - 1) { // Add a restart after all but last row. 410 this.addIndex(restartIndex); 411 if (this.m_duplicateRestarts) 412 this.addIndex(restartIndex); 413 } 414 } 415 } else if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_STRIP || this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_LOOP || this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINES) { 416 // Generate a numRows x numCols arrangement of line polygons of different vertex counts. 417 418 curIndex = 0; 419 numRows = 4; 420 numCols = 4; 421 422 for (var row = 0; row < numRows; row++) { 423 centerY = -1.0 + 2.0 * (row + 0.5) / numRows; 424 425 for (var col = 0; col < numCols; col++) { 426 centerX = -1.0 + 2.0 * (col + 0.5) / numCols; 427 numVertices = row * numCols + col + 1; 428 429 for (var i = 0; i < numVertices; i++) { 430 fx = centerX + 0.9 * Math.cos(i * 2.0 * Math.PI / numVertices) / numCols; 431 fy = centerY + 0.9 * Math.sin(i * 2.0 * Math.PI / numVertices) / numRows; 432 433 this.m_positions.push(fx); 434 this.m_positions.push(fy); 435 436 this.addIndex(curIndex++); 437 } 438 439 if (col < numCols - 1 || row < numRows - 1) {// Add a restart after all but last polygon. 440 this.addIndex(restartIndex); 441 if (this.m_duplicateRestarts) 442 this.addIndex(restartIndex); 443 } 444 } 445 } 446 } else if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_STRIP) { 447 // Generate a number of horizontal triangle strips of different lengths. 448 449 curIndex = 0; 450 numStrips = 20; 451 452 for (var stripNdx = 0; stripNdx < numStrips; stripNdx++) { 453 numVertices = stripNdx + 1; 454 455 for (var i = 0; i < numVertices; i++) { 456 fx = -0.9 + 1.8 * (i / 2 * 2) / numStrips; 457 fy = -0.9 + 1.8 * (stripNdx + (i % 2 == 0 ? 0.0 : 0.8)) / numStrips; 458 459 this.m_positions.push(fx); 460 this.m_positions.push(fy); 461 462 this.addIndex(curIndex++); 463 } 464 465 if (stripNdx < numStrips - 1) { // Add a restart after all but last strip. 466 this.addIndex(restartIndex); 467 if (this.m_duplicateRestarts) 468 this.addIndex(restartIndex); 469 } 470 } 471 } else if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_FAN) { 472 // Generate a numRows x numCols arrangement of triangle fan polygons of different vertex counts. 473 474 curIndex = 0; 475 numRows = 4; 476 numCols = 4; 477 478 for (var row = 0; row < numRows; row++) { 479 centerY = -1.0 + 2.0 * (row + 0.5) / numRows; 480 481 for (var col = 0; col < numCols; col++) { 482 centerX = -1.0 + 2.0 * (col + 0.5) / numCols; 483 numArcVertices = row * numCols + col; 484 485 this.m_positions.push(centerX); 486 this.m_positions.push(centerY); 487 488 this.addIndex(curIndex++); 489 490 for (var i = 0; i < numArcVertices; i++) { 491 fx = centerX + 0.9 * Math.cos(i * 2.0 * Math.PI / numArcVertices) / numCols; 492 fy = centerY + 0.9 * Math.sin(i * 2.0 * Math.PI / numArcVertices) / numRows; 493 494 this.m_positions.push(fx); 495 this.m_positions.push(fy); 496 497 this.addIndex(curIndex++); 498 } 499 500 if (col < numCols - 1 || row < numRows - 1) { // Add a restart after all but last polygon. 501 this.addIndex(restartIndex); 502 if (this.m_duplicateRestarts) 503 this.addIndex(restartIndex); 504 } 505 } 506 } 507 } else if (this.m_primType == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLES) { 508 // Generate a number of rows with (potentially incomplete) triangles. 509 510 curIndex = 0; 511 numRows = 3 * 7; 512 513 for (var rowNdx = 0; rowNdx < numRows; rowNdx++) { 514 numVertices = rowNdx + 1; 515 516 for (var i = 0; i < numVertices; i++) { 517 fx = -0.9 + 1.8 * ((i / 3) + (i % 3 == 2 ? 0.8 : 0.0)) * 3 / numRows; 518 fy = -0.9 + 1.8 * (rowNdx + (i % 3 == 0 ? 0.0 : 0.8)) / numRows; 519 520 this.m_positions.push(fx); 521 this.m_positions.push(fy); 522 523 this.addIndex(curIndex++); 524 } 525 526 if (rowNdx < numRows - 1) { // Add a restart after all but last row. 527 this.addIndex(restartIndex); 528 if (this.m_duplicateRestarts) 529 this.addIndex(restartIndex); 530 } 531 } 532 } else 533 DE_ASSERT(false); 534 535 // If testing a case with restart at end, add it there. 536 if (this.m_endWithRestart) { 537 this.addIndex(restartIndex); 538 if (this.m_duplicateRestarts) 539 this.addIndex(restartIndex); 540 } 541 542 // Special case assertions. 543 544 /** @type {number} */ var numIndices = this.getNumIndices(); 545 546 DE_ASSERT(numIndices > 0); 547 DE_ASSERT(this.m_beginWithRestart || this.getIndex(0) != restartIndex); // We don't want restarts at beginning unless the case is a special case. 548 DE_ASSERT(this.m_endWithRestart || this.getIndex(numIndices - 1) != restartIndex); // We don't want restarts at end unless the case is a special case. 549 550 if (!this.m_duplicateRestarts) 551 for (var i = 1; i < numIndices; i++) 552 DE_ASSERT(this.getIndex(i) != restartIndex || this.getIndex(i - 1) != restartIndex); // We don't want duplicate restarts unless the case is a special case. 553 554 }; 555 556 es3fPrimitiveRestartTests.PrimitiveRestartCase.prototype.iterate = function() { 557 /** @type {number} */ var width = Math.min(gl.drawingBufferWidth, es3fPrimitiveRestartTests.MAX_RENDER_WIDTH); 558 /** @type {number} */ var height = Math.min(gl.drawingBufferHeight, es3fPrimitiveRestartTests.MAX_RENDER_HEIGHT); 559 560 /** @type {number} */ var xOffsetMax = gl.drawingBufferWidth - width; 561 /** @type {number} */ var yOffsetMax = gl.drawingBufferHeight - height; 562 563 /** @type {deRandom.Random} */ var rnd = new deRandom.Random(deString.deStringHash(this.name)); 564 565 /** @type {number} */ var xOffset = rnd.getInt(0, xOffsetMax); 566 /** @type {number} */ var yOffset = rnd.getInt(0, yOffsetMax); 567 /** @type {tcuSurface.Surface} */ var referenceImg = new tcuSurface.Surface(width, height); 568 /** @type {tcuSurface.Surface} */ var resultImg = new tcuSurface.Surface(width, height); 569 570 gl.viewport(xOffset, yOffset, width, height); 571 gl.clearColor(0.0, 0.0, 0.0, 1.0); 572 573 var program = this.m_program.getProgram(); 574 gl.useProgram(program); 575 576 // Setup position attribute. 577 578 /** @type {number} */ var loc = gl.getAttribLocation(program, 'a_position'); 579 gl.enableVertexAttribArray(loc); 580 581 var locGlBuffer = gl.createBuffer(); 582 var bufferLoc = new Float32Array(this.m_positions); 583 gl.bindBuffer(gl.ARRAY_BUFFER, locGlBuffer); 584 gl.bufferData(gl.ARRAY_BUFFER, bufferLoc, gl.STATIC_DRAW); 585 gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0); 586 587 // Render result. 588 this.renderWithRestart(); 589 var resImg = resultImg.getAccess(); 590 var resImgTransferFormat = gluTextureUtil.getTransferFormat(resImg.getFormat()); 591 gl.readPixels(xOffset, yOffset, resImg.m_width, resImg.m_height, resImgTransferFormat.format, resImgTransferFormat.dataType, resultImg.m_pixels); 592 593 // Render reference (same scene as the real deal, but emulate primitive restart without actually using it). 594 this.renderWithoutRestart(); 595 596 var refImg = referenceImg.getAccess(); 597 var refImgTransferFormat = gluTextureUtil.getTransferFormat(refImg.getFormat()); 598 599 gl.readPixels(xOffset, yOffset, refImg.m_width, refImg.m_height, refImgTransferFormat.format, refImgTransferFormat.dataType, referenceImg.m_pixels); 600 601 // Compare. 602 /** @type {boolean} */ var testOk = tcuImageCompare.pixelThresholdCompare('ComparisonResult', 'Image comparison result', referenceImg, resultImg, [0, 0, 0, 0]); 603 604 assertMsgOptions(testOk, '', true, false); 605 gl.useProgram(null); 606 607 return tcuTestCase.IterateResult.STOP; 608 }; 609 610 es3fPrimitiveRestartTests.init = function() { 611 var testGroup = tcuTestCase.runner.testCases; 612 for (var isRestartBeginCaseI = 0; isRestartBeginCaseI <= 1; isRestartBeginCaseI++) { 613 for (var isRestartEndCaseI = 0; isRestartEndCaseI <= 1; isRestartEndCaseI++) { 614 for (var isDuplicateRestartCaseI = 0; isDuplicateRestartCaseI <= 1; isDuplicateRestartCaseI++) { 615 /** @type {boolean} */ var isRestartBeginCase = isRestartBeginCaseI != 0; 616 /** @type {boolean} */ var isRestartEndCase = isRestartEndCaseI != 0; 617 /** @type {boolean} */ var isDuplicateRestartCase = isDuplicateRestartCaseI != 0; 618 619 /** @type {string} */ var specialCaseGroupName = ''; 620 621 if (isRestartBeginCase) specialCaseGroupName = 'begin_restart'; 622 if (isRestartEndCase) specialCaseGroupName += (deString.deIsStringEmpty(specialCaseGroupName) ? '' : '_') + 'end_restart'; 623 if (isDuplicateRestartCase) specialCaseGroupName += (deString.deIsStringEmpty(specialCaseGroupName) ? '' : '_') + 'duplicate_restarts'; 624 625 if (deString.deIsStringEmpty(specialCaseGroupName)) 626 specialCaseGroupName = 'basic'; 627 628 /** @type {tcuTestCase.DeqpTest} */ var specialCaseGroup = tcuTestCase.newTest(specialCaseGroupName, ''); 629 testGroup.addChild(specialCaseGroup); 630 631 for (var primType in es3fPrimitiveRestartTests.PrimitiveType) { 632 /** @type {string} */ var primTypeName = es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_POINTS ? 'points' : 633 es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_STRIP ? 'line_strip' : 634 es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINE_LOOP ? 'line_loop' : 635 es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_LINES ? 'lines' : 636 es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_STRIP ? 'triangle_strip' : 637 es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLE_FAN ? 'triangle_fan' : 638 es3fPrimitiveRestartTests.PrimitiveType[primType] == es3fPrimitiveRestartTests.PrimitiveType.PRIMITIVE_TRIANGLES ? 'triangles' : 639 ''; 640 641 DE_ASSERT(primTypeName != null); 642 643 /** @type {tcuTestCase.DeqpTest} */ var primTypeGroup = tcuTestCase.newTest(primTypeName, ''); 644 specialCaseGroup.addChild(primTypeGroup); 645 646 for (var indexType in es3fPrimitiveRestartTests.IndexType) { 647 /** @type {string} */ var indexTypeName = es3fPrimitiveRestartTests.IndexType[indexType] == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_BYTE ? 'unsigned_byte' : 648 es3fPrimitiveRestartTests.IndexType[indexType] == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_SHORT ? 'unsigned_short' : 649 es3fPrimitiveRestartTests.IndexType[indexType] == es3fPrimitiveRestartTests.IndexType.INDEX_UNSIGNED_INT ? 'unsigned_int' : 650 ''; 651 652 DE_ASSERT(indexTypeName != null); 653 654 /** @type {tcuTestCase.DeqpTest} */ var indexTypeGroup = tcuTestCase.newTest(indexTypeName, ''); 655 primTypeGroup.addChild(indexTypeGroup); 656 657 for (var _function in es3fPrimitiveRestartTests.DrawFunction) { 658 /** @type {?string} */ var functionName = es3fPrimitiveRestartTests.DrawFunction[_function] == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_ELEMENTS ? 'draw_elements' : 659 es3fPrimitiveRestartTests.DrawFunction[_function] == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_ELEMENTS_INSTANCED ? 'draw_elements_instanced' : 660 es3fPrimitiveRestartTests.DrawFunction[_function] == es3fPrimitiveRestartTests.DrawFunction.FUNCTION_DRAW_RANGE_ELEMENTS ? 'draw_range_elements' : 661 null; 662 663 DE_ASSERT(functionName != null); 664 665 indexTypeGroup.addChild(new es3fPrimitiveRestartTests.PrimitiveRestartCase(functionName, 666 '', 667 es3fPrimitiveRestartTests.PrimitiveType[primType], 668 es3fPrimitiveRestartTests.IndexType[indexType], 669 es3fPrimitiveRestartTests.DrawFunction[_function], 670 isRestartBeginCase, 671 isRestartEndCase, 672 isDuplicateRestartCase)); 673 } 674 } 675 } 676 } 677 } 678 } 679 }; 680 681 es3fPrimitiveRestartTests.run = function(context, range) { 682 gl = context; 683 //Set up Test Root parameters 684 var testName = 'primitive_restart'; 685 var testDescription = 'Primitive Restart Tests'; 686 var state = tcuTestCase.runner; 687 688 state.testName = testName; 689 state.setRoot(tcuTestCase.newTest(testName, testDescription, null)); 690 691 //Set up name and description of this test series. 692 setCurrentTestName(testName); 693 description(testDescription); 694 695 try { 696 //Create test cases 697 es3fPrimitiveRestartTests.init(); 698 if (range) 699 state.setRange(range); 700 //Run test cases 701 tcuTestCase.runTestCases(); 702 } 703 catch (err) { 704 testFailedOptions('Failed to es3fPrimitiveRestartTests.run tests', false); 705 tcuTestCase.runner.terminate(); 706 } 707 }; 708 709 });