glsFboUtil.js (44890B)
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('modules.shared.glsFboUtil'); 23 goog.require('framework.opengl.gluTextureUtil'); 24 goog.require('framework.opengl.gluStrUtil'); 25 26 goog.scope(function() { 27 28 var glsFboUtil = modules.shared.glsFboUtil; 29 var gluTextureUtil = framework.opengl.gluTextureUtil; 30 var gluStrUtil = framework.opengl.gluStrUtil; 31 var DE_ASSERT = function(x) { 32 if (!x) 33 throw new Error('Assert failed'); 34 }; 35 36 /** 37 * @constructor 38 * @template KeyT 39 * @template ValueT 40 * @param {function(!KeyT, !KeyT):boolean} comparefnc 41 */ 42 glsFboUtil.Map = function(comparefnc) { 43 /** @type {Array<{first: !KeyT, second: ValueT}>} */ 44 this.store = []; 45 this.compare = comparefnc; 46 this.length = 0; 47 }; 48 49 /** 50 * @param {number} num1 51 * @param {number} num2 52 * @return {boolean} 53 */ 54 glsFboUtil.Map.compareNumber = function(num1, num2) { 55 return num1 < num2; 56 }; 57 58 /** 59 * @param {!KeyT} key 60 * @param {ValueT} value 61 * @return {{first: !KeyT, second: ValueT}} 62 */ 63 glsFboUtil.Map.prototype.pair = function(key, value) { 64 return { 65 first: key, 66 second: value 67 }; 68 }; 69 70 /** 71 * @protected 72 * @param {!KeyT} key 73 * @return {number} 74 */ 75 glsFboUtil.Map.prototype.findInsertionPoint = function(key) { 76 var /** @type {number} */i, /** @type {number} */length; 77 for (i = 0, length = this.store.length; i < length; ++i) { 78 if (!this.compare(key, this.store[i].first)) break; 79 } 80 return i; 81 }; 82 83 /** 84 * index should be a value returned from findInsertionPoint. 85 * returns true if the compare function returns false reflexively 86 * (i.e. no matter the order in which the keys are passed as arguments). 87 * @protected 88 * @param {!KeyT} key 89 * @param {number} index 90 * @return {boolean} 91 */ 92 glsFboUtil.Map.prototype.foundIndexMatches = function(key, index) { 93 return ( 94 this.store[index] !== undefined && 95 !this.compare(this.store[index].first, key) 96 ); 97 }; 98 99 /** 100 * @param {!KeyT} key 101 * @return {boolean} 102 */ 103 glsFboUtil.Map.prototype.isset = function(key) { 104 return this.foundIndexMatches(key, this.findInsertionPoint(key)); 105 }; 106 107 /** 108 * @param {!KeyT} key 109 * @param {ValueT} value 110 */ 111 glsFboUtil.Map.prototype.set = function(key, value) { 112 var index = this.findInsertionPoint(key); 113 if (this.foundIndexMatches(key, index)) { 114 this.store[index].second = value; 115 } else { 116 this.store.splice(index, 0, this.pair(key, value)); 117 ++this.length; 118 } 119 }; 120 121 /** 122 * @param {!KeyT} key 123 * @return {?ValueT} 124 */ 125 glsFboUtil.Map.prototype.remove = function(key) { 126 var index = this.findInsertionPoint(key); 127 /** @type {?ValueT} */ var ret = null; 128 if (this.foundIndexMatches(key, index)) { 129 ret = this.store[index].second; 130 this.store.splice(index, 1); 131 --this.length; 132 } 133 return ret; 134 }; 135 136 /** 137 * @param {KeyT} key 138 * @return {?{first: KeyT, second: ValueT}} 139 */ 140 glsFboUtil.Map.prototype.get = function(key) { 141 var index = this.findInsertionPoint(key); 142 if (this.foundIndexMatches(key, index)) return this.store[index]; 143 return null; 144 }; 145 146 /** 147 * @param {KeyT} key 148 * @return {?ValueT} 149 */ 150 glsFboUtil.Map.prototype.getValue = function(key) { 151 var index = this.findInsertionPoint(key); 152 if (this.foundIndexMatches(key, index)) return this.store[index].second; 153 return null; 154 }; 155 156 /** 157 * @param {!KeyT} key 158 * @param {ValueT} fallback 159 * @return {ValueT} 160 */ 161 glsFboUtil.Map.prototype.lookupDefault = function(key, fallback) { 162 var index = this.findInsertionPoint(key); 163 if (this.foundIndexMatches(key, index)) return this.store[index].second; 164 return fallback; 165 }; 166 167 /** 168 * @param {number} index 169 * @return {{first: KeyT, second: ValueT}|undefined} 170 */ 171 glsFboUtil.Map.prototype.getIndex = function(index) { 172 return this.store[index]; 173 }; 174 175 /** 176 * Use the callback to set the value to be identified by key. 177 * If a value is already identified by the key, it will be passed to the callback 178 * @param {!KeyT} key 179 * @param {function(ValueT=):!ValueT} callback 180 */ 181 glsFboUtil.Map.prototype.transform = function(key, callback) { 182 var index = this.findInsertionPoint(key); 183 if (this.foundIndexMatches(key, index)) { 184 this.store[index].second = callback(this.store[index].second); 185 } else { 186 this.store.splice(index, 0, this.pair(key, callback())); 187 ++this.length; 188 } 189 }; 190 191 /** 192 * removed all elements from the Map 193 */ 194 glsFboUtil.Map.prototype.clear = function() { 195 this.store.splice(0, this.length); 196 this.length = 0; 197 }; 198 199 /** 200 * @constructor 201 */ 202 glsFboUtil.FormatDB = function() { 203 this.m_map = /** @type {glsFboUtil.Map<glsFboUtil.ImageFormat,number>} */( 204 new glsFboUtil.Map(glsFboUtil.ImageFormat.lessthan) 205 ); 206 }; 207 208 /** 209 * @param {glsFboUtil.ImageFormat} format 210 * @param {number} newFlags 211 */ 212 glsFboUtil.FormatDB.prototype.addFormat = function(format, newFlags) { 213 this.m_map.transform(format, function(flags) { 214 return flags | newFlags; 215 }); 216 }; 217 218 /** 219 * @param {number} requirements 220 * @return {Array<glsFboUtil.ImageFormat>} 221 */ 222 glsFboUtil.FormatDB.prototype.getFormats = function(requirements) { 223 /** @type {Array<glsFboUtil.ImageFormat>} */ var ret = []; 224 for (var i = 0; i < this.m_map.length; ++i) { 225 var pair = this.m_map.getIndex(i); 226 if ((pair.second & requirements) == requirements) 227 ret.push(pair.first); 228 } 229 230 return ret; 231 }; 232 233 /** 234 * @param {glsFboUtil.ImageFormat} format 235 * @param {number} fallback 236 * @return {number} 237 */ 238 glsFboUtil.FormatDB.prototype.getFormatInfo = function(format, fallback) { 239 return this.m_map.lookupDefault(format, fallback); 240 }; 241 242 /** 243 * @param {Object} map 244 * @param {number} key 245 * @param {number} fallback 246 * @return {number} 247 */ 248 glsFboUtil.lookupDefault = function(map, key, fallback) { 249 return (map[key] !== undefined) ? map[key] : fallback; 250 }; 251 252 /** 253 * @param {Array<number>} array 254 * @param {number} item 255 * @return {boolean} 256 */ 257 glsFboUtil.contains = function(array, item) { 258 var l = array.length; 259 for (var i = 0; i < l; ++i) 260 if (array[i] == item) return true; 261 return false; 262 }; 263 264 /** 265 * @typedef {Array<(number | glsFboUtil.Range<number>)>} 266 */ 267 glsFboUtil.formatT; 268 269 /** 270 * @param {glsFboUtil.FormatDB} db 271 * @param {glsFboUtil.Range<glsFboUtil.formatT>} stdFmts 272 */ 273 glsFboUtil.addFormats = function(db, stdFmts) { 274 for (var set = stdFmts.reset(); set = stdFmts.current(); stdFmts.next()) { 275 for (var fmt = set[1].reset(); fmt = set[1].current(); set[1].next()) { 276 db.addFormat(glsFboUtil.formatKeyInfo(fmt), set[0]); 277 } 278 } 279 }; 280 281 /** 282 * @param {glsFboUtil.FormatDB} db 283 * @param {glsFboUtil.Range} extFmts 284 * @param {WebGLRenderingContextBase=} gl 285 * @throws {Error} 286 */ 287 glsFboUtil.addExtFormats = function(db, extFmts, gl) { 288 if (!(gl = gl || window.gl)) throw new Error('Invalid gl object'); 289 var extensions = gl.getSupportedExtensions(); 290 291 // loop through the range, looking at the extentions. 292 for (var ext = extFmts.reset(); ext = extFmts.current(); extFmts.next()) { 293 var tokens = ext.extensions.split(/\s+/); 294 295 var supported = function() { 296 for (var i = 0, l = tokens.length; i < l; ++i) 297 if (extensions.indexOf(tokens[i]) === -1) return false; 298 return true; 299 }(); 300 301 if (supported) { 302 for (var format = ext.formats.reset(); format = ext.formats.current(); ext.formats.next()) { 303 db.addFormat(glsFboUtil.formatKeyInfo(format), ext.flags); 304 } 305 } 306 307 } 308 309 }; 310 311 /** 312 * @param {number} glenum 313 * @param {WebGLRenderingContextBase=} gl 314 * @return {number} 315 * @throws {Error} 316 */ 317 glsFboUtil.formatFlag = function(glenum, gl) { 318 if (!(gl = gl || window.gl)) throw new Error('Invalid gl object'); 319 320 switch (glenum) { 321 case gl.NONE: 322 return glsFboUtil.FormatFlags.ANY_FORMAT; 323 case gl.RENDERBUFFER: 324 return glsFboUtil.FormatFlags.RENDERBUFFER_VALID; 325 case gl.TEXTURE: 326 return glsFboUtil.FormatFlags.TEXTURE_VALID; 327 case gl.STENCIL_ATTACHMENT: 328 return glsFboUtil.FormatFlags.STENCIL_RENDERABLE; 329 case gl.DEPTH_ATTACHMENT: 330 return glsFboUtil.FormatFlags.DEPTH_RENDERABLE; 331 default: 332 if (glenum < gl.COLOR_ATTACHMENT0 || glenum > gl.COLOR_ATTACHMENT15) { 333 throw new Error('glenum out of range'); 334 } 335 } 336 return glsFboUtil.FormatFlags.COLOR_RENDERABLE; 337 }; 338 339 /** 340 * Remove value from array 341 * @param {Array} array 342 * @param {number} value 343 */ 344 glsFboUtil.remove_from_array = function(array, value) { 345 var index = 0; 346 while ((index = array.indexOf(value)) != -1) { 347 array.splice(index, 1); 348 } 349 }; 350 351 /** 352 * glsFboUtil.FormatExtEntry 353 * @constructor 354 * @struct 355 * @param {string=} extensions 356 * @param {number=} flags 357 * @param {glsFboUtil.Range=} formats 358 */ 359 glsFboUtil.FormatExtEntry = function(extensions, flags, formats) { 360 this.extensions = null; 361 this.flags = null; 362 this.formats = null; 363 364 if (extensions !== undefined) { 365 this.extensions = extensions; 366 if (flags !== undefined) { 367 this.flags = flags; 368 if (formats !== undefined) 369 this.formats = formats; 370 } 371 } 372 373 }; 374 375 /** 376 * glsFboUtil.Range 377 * @constructor 378 * @struct 379 * @template T 380 * @param {Array<T>} array 381 * @param {number=} begin 382 * @param {number=} end 383 */ 384 glsFboUtil.Range = function(array, begin, end) { 385 // @private 386 this.m_begin = (begin === undefined ? 0 : begin); 387 // @private 388 this.m_end = end || array.length; 389 /** 390 * @private 391 * @type {Array<T>} 392 */ 393 this.m_array = array; 394 // @private 395 this.m_index = this.m_begin; 396 }; 397 398 /** 399 * @return {Array<T>} 400 */ 401 glsFboUtil.Range.prototype.array = function() { 402 return this.m_array; 403 }; 404 405 /** 406 * @return {number} 407 */ 408 glsFboUtil.Range.prototype.begin = function() { 409 return this.m_begin; 410 }; 411 412 /** *generated by script* 413 * @return {number} 414 */ 415 glsFboUtil.Range.prototype.end = function() { 416 return this.m_end; 417 }; 418 419 /** 420 * Returns the current pointer index as well as the current object 421 * @param {number} id 422 * @return {{first: number, second: T}} 423 */ 424 glsFboUtil.Range.prototype.get = function(id) { 425 return { 426 first: id, 427 second: this.m_array[id] 428 }; 429 }; 430 431 /** 432 * Sets the internal pointer to the beginning of the range, and returns the first object. 433 * @return {T} 434 */ 435 glsFboUtil.Range.prototype.reset = function() { 436 this.m_index = this.m_begin; 437 return this.current(); 438 }; 439 440 /** 441 * returns the current object within the specified range. The internal pointer is unaltered. 442 * @return {T} 443 */ 444 glsFboUtil.Range.prototype.current = function() { 445 return this.m_index < this.m_end ? this.m_array[this.m_index] : null; 446 }; 447 448 /** 449 * Increments the internal pointer 450 */ 451 glsFboUtil.Range.prototype.next = function() { 452 ++this.m_index; 453 }; 454 455 /** 456 * glsFboUtil.rangeArray 457 * replaces the macro GLS_ARRAY_RANGE 458 * Creates a new Range object from the specified array, spanning the whole array. 459 * @template T 460 * @param {Array<T>} array 461 * @return {glsFboUtil.Range<T>} 462 */ 463 glsFboUtil.rangeArray = function(array) { 464 return new glsFboUtil.Range(array); 465 }; 466 467 /** 468 * @constructor 469 * @struct 470 * @param {number=} format 471 * @param {number=} unsizedType 472 */ 473 glsFboUtil.ImageFormat = function(format, unsizedType) { 474 this.format = format || 0; 475 //! Type if format is unsized, gl.NONE if sized. 476 this.unsizedType = unsizedType || 0; 477 478 }; 479 480 /** 481 * @param {!glsFboUtil.ImageFormat} obj1 482 * @param {!glsFboUtil.ImageFormat} obj2 483 * @return {boolean} 484 */ 485 glsFboUtil.ImageFormat.lessthan = function(obj1, obj2) { 486 return ( 487 (obj1.format < obj2.format) || 488 (obj1.format == obj2.format && obj1.unsizedType < obj2.unsizedType) 489 ); 490 }; 491 492 /** 493 * Sets the object's parameters to gl.NONE 494 */ 495 glsFboUtil.ImageFormat.prototype.none = function() { 496 this.format = 0; 497 this.unsizedType = 0; 498 }; 499 500 /** 501 * @return {glsFboUtil.ImageFormat} 502 */ 503 glsFboUtil.ImageFormat.none = function() { 504 var obj = new glsFboUtil.ImageFormat(); 505 obj.none(); 506 return obj; 507 }; 508 509 // where key is a FormatKey, and a FormatKey is a unsigned 32bit int. 510 511 /** 512 * @param {number} key 513 * @return {glsFboUtil.ImageFormat} 514 */ 515 glsFboUtil.formatKeyInfo = function(key) { 516 return new glsFboUtil.ImageFormat( 517 (key & 0x0000ffff), 518 (key & 0xffff0000) >>> 16 519 ); 520 }; 521 522 /** 523 * glsFboUtil.Config Class. 524 * @constructor 525 */ 526 glsFboUtil.Config = function() { 527 this.type = glsFboUtil.Config.s_types.CONFIG; 528 this.target = glsFboUtil.Config.s_target.NONE; 529 }; 530 /** 531 * @enum {number} 532 */ 533 glsFboUtil.Config.s_target = { 534 NONE: 0, 535 RENDERBUFFER: 0x8D41, 536 TEXTURE_2D: 0x0DE1, 537 TEXTURE_CUBE_MAP: 0x8513, 538 TEXTURE_3D: 0x806F, 539 TEXTURE_2D_ARRAY: 0x8C1A, 540 541 FRAMEBUFFER: 0x8D40 542 }; 543 544 // the c++ uses dynamic casts to determain if an object inherits from a 545 // given class. Here, each class' constructor assigns a bit to obj.type. 546 // look for the bit to see if an object inherits that class. 547 548 /** 549 * @enum 550 */ 551 glsFboUtil.Config.s_types = { 552 CONFIG: 0x000001, 553 554 IMAGE: 0x000010, 555 RENDERBUFFER: 0x000020, 556 TEXTURE: 0x000040, 557 TEXTURE_FLAT: 0x000080, 558 TEXTURE_2D: 0x000100, 559 TEXTURE_CUBE_MAP: 0x000200, 560 TEXTURE_LAYERED: 0x000400, 561 TEXTURE_3D: 0x000800, 562 TEXTURE_2D_ARRAY: 0x001000, 563 564 ATTACHMENT: 0x010000, 565 ATT_RENDERBUFFER: 0x020000, 566 ATT_TEXTURE: 0x040000, 567 ATT_TEXTURE_FLAT: 0x080000, 568 ATT_TEXTURE_LAYER: 0x100000, 569 570 UNUSED: 0xFFE0E00E 571 }; 572 573 /** 574 * glsFboUtil.Image Class. 575 * @constructor 576 * @extends {glsFboUtil.Config} 577 */ 578 glsFboUtil.Image = function() { 579 glsFboUtil.Config.call(this); 580 this.type |= glsFboUtil.Config.s_types.IMAGE; 581 this.width = 0; 582 this.height = 0; 583 this.internalFormat = new glsFboUtil.ImageFormat(); 584 }; 585 586 /** 587 * glsFboUtil.Renderbuffer Class. 588 * @constructor 589 * @extends {glsFboUtil.Image} 590 */ 591 glsFboUtil.Renderbuffer = function() { 592 glsFboUtil.Image.call(this); 593 this.type |= glsFboUtil.Config.s_types.RENDERBUFFER; 594 this.target = glsFboUtil.Config.s_target.RENDERBUFFER; 595 this.numSamples = 0; 596 }; 597 598 /** 599 * glsFboUtil.Texture Class. 600 * @constructor 601 * @extends {glsFboUtil.Image} 602 */ 603 glsFboUtil.Texture = function() { 604 glsFboUtil.Image.call(this); 605 this.type |= glsFboUtil.Config.s_types.TEXTURE; 606 this.numLevels = 1; 607 }; 608 609 /** 610 * glsFboUtil.TextureFlat Class. 611 * @constructor 612 * @extends {glsFboUtil.Texture} 613 */ 614 glsFboUtil.TextureFlat = function() { 615 glsFboUtil.Texture.call(this); 616 this.type |= glsFboUtil.Config.s_types.TEXTURE_FLAT; 617 }; 618 619 /** 620 * glsFboUtil.Texture2D Class. 621 * @constructor 622 * @extends {glsFboUtil.TextureFlat} 623 */ 624 glsFboUtil.Texture2D = function() { 625 glsFboUtil.TextureFlat.call(this); 626 this.type |= glsFboUtil.Config.s_types.TEXTURE_2D; 627 this.target = glsFboUtil.Config.s_target.TEXTURE_2D; 628 }; 629 630 /** 631 * glsFboUtil.TextureCubeMap Class. 632 * @constructor 633 * @extends {glsFboUtil.TextureFlat} 634 */ 635 glsFboUtil.TextureCubeMap = function() { 636 glsFboUtil.TextureFlat.call(this); 637 this.type |= glsFboUtil.Config.s_types.TEXTURE_CUBE_MAP; 638 this.target = glsFboUtil.Config.s_target.TEXTURE_CUBE_MAP; 639 }; 640 641 /** 642 * glsFboUtil.TextureLayered Class. 643 * @constructor 644 * @extends {glsFboUtil.Texture} 645 */ 646 glsFboUtil.TextureLayered = function() { 647 glsFboUtil.Texture.call(this); 648 this.type |= glsFboUtil.Config.s_types.TEXTURE_LAYERED; 649 this.numLayers = 1; 650 }; 651 652 /** 653 * glsFboUtil.Texture3D Class. 654 * @constructor 655 * @extends {glsFboUtil.TextureLayered} 656 */ 657 glsFboUtil.Texture3D = function() { 658 glsFboUtil.TextureLayered.call(this); 659 this.type |= glsFboUtil.Config.s_types.TEXTURE_3D; 660 this.target = glsFboUtil.Config.s_target.TEXTURE_3D; 661 }; 662 663 /** 664 * glsFboUtil.Texture2DArray Class. 665 * @constructor 666 * @extends {glsFboUtil.TextureLayered} 667 */ 668 glsFboUtil.Texture2DArray = function() { 669 glsFboUtil.TextureLayered.call(this); 670 this.type |= glsFboUtil.Config.s_types.TEXTURE_2D_ARRAY; 671 this.target = glsFboUtil.Config.s_target.TEXTURE_2D_ARRAY; 672 }; 673 674 /** 675 * glsFboUtil.Attachment Class. 676 * @constructor 677 * @extends {glsFboUtil.Config} 678 */ 679 glsFboUtil.Attachment = function() { 680 glsFboUtil.Config.call(this); 681 682 this.type |= glsFboUtil.Config.s_types.ATTACHMENT; 683 684 /** @type {glsFboUtil.Config.s_target} */ 685 this.target = glsFboUtil.Config.s_target.FRAMEBUFFER; 686 687 /** @type {WebGLObject} */ 688 this.imageName = null; 689 }; 690 691 /** 692 * this function is declared, but has no definition/is unused in the c++ 693 * @param {number} attPoint 694 * @param {number} image 695 * @param {number} vfr 696 */ 697 glsFboUtil.Attachment.prototype.isComplete = function(attPoint, image, vfr) { }; 698 699 /** 700 * glsFboUtil.RenderBufferAttachments Class. 701 * @constructor 702 * @extends {glsFboUtil.Attachment} 703 */ 704 glsFboUtil.RenderbufferAttachment = function() { 705 glsFboUtil.Attachment.call(this); 706 this.type |= glsFboUtil.Config.s_types.ATT_RENDERBUFFER; 707 this.renderbufferTarget = glsFboUtil.Config.s_target.RENDERBUFFER; 708 }; 709 glsFboUtil.RenderbufferAttachment.prototype = Object.create(glsFboUtil.Attachment.prototype); 710 glsFboUtil.RenderbufferAttachment.prototype.constructor = glsFboUtil.RenderbufferAttachment; 711 712 /** 713 * glsFboUtil.TextureAttachment Class. 714 * @constructor 715 * @extends {glsFboUtil.Attachment} 716 */ 717 glsFboUtil.TextureAttachment = function() { 718 glsFboUtil.Attachment.call(this); 719 this.type |= glsFboUtil.Config.s_types.ATT_TEXTURE; 720 this.level = 0; 721 }; 722 glsFboUtil.TextureAttachment.prototype = Object.create(glsFboUtil.Attachment.prototype); 723 glsFboUtil.TextureAttachment.prototype.constructor = glsFboUtil.TextureAttachment; 724 725 /** 726 * glsFboUtil.TextureFlatAttachment Class. 727 * @constructor 728 * @extends {glsFboUtil.TextureAttachment} 729 */ 730 glsFboUtil.TextureFlatAttachment = function() { 731 glsFboUtil.TextureAttachment.call(this); 732 this.type |= glsFboUtil.Config.s_types.ATT_TEXTURE_FLAT; 733 this.texTarget = glsFboUtil.Config.s_target.NONE; 734 }; 735 glsFboUtil.TextureFlatAttachment.prototype = Object.create(glsFboUtil.TextureAttachment.prototype); 736 glsFboUtil.TextureFlatAttachment.prototype.constructor = glsFboUtil.TextureFlatAttachment; 737 738 /** 739 * glsFboUtil.TextureLayerAttachment Class. 740 * @constructor 741 * @extends {glsFboUtil.TextureAttachment} 742 */ 743 glsFboUtil.TextureLayerAttachment = function() { 744 glsFboUtil.TextureAttachment.call(this); 745 this.type |= glsFboUtil.Config.s_types.ATT_TEXTURE_LAYER; 746 this.layer = 0; 747 }; 748 glsFboUtil.TextureLayerAttachment.prototype = Object.create(glsFboUtil.TextureAttachment.prototype); 749 glsFboUtil.TextureLayerAttachment.prototype.constructor = glsFboUtil.TextureLayerAttachment; 750 751 // these are a collection of helper functions for creating various gl textures. 752 glsFboUtil.glsup = function() { 753 754 var glInit = function(cfg, gl) { 755 if ((cfg.type & glsFboUtil.Config.s_types.TEXTURE_2D) != 0) { 756 glInitFlat(cfg, glTarget(cfg, gl), gl); 757 758 } else if ((cfg.type & glsFboUtil.Config.s_types.TEXTURE_CUBE_MAP) != 0) { 759 for (var i = gl.TEXTURE_CUBE_MAP_NEGATIVE_X; i <= gl.TEXTURE_CUBE_MAP_POSITIVE_Z; ++i) 760 glInitFlat(cfg, i, gl); 761 } else if ((cfg.type & glsFboUtil.Config.s_types.TEXTURE_3D) != 0) { 762 glInitLayered(cfg, 2, gl); 763 764 } else if ((cfg.type & glsFboUtil.Config.s_types.TEXTURE_2D_ARRAY) != 0) { 765 glInitLayered(cfg, 1, gl); 766 } 767 }; 768 769 var glInitFlat = function(cfg, target, gl) { 770 var format = glsFboUtil.transferImageFormat(cfg.internalFormat, gl); 771 var w = cfg.width; 772 var h = cfg.height; 773 for (var level = 0; level < cfg.numLevels; ++level) { 774 gl.texImage2D( 775 target, level, cfg.internalFormat.format, 776 w, h, 0, format.format, format.dataType, null 777 ); 778 w = Math.max(1, w / 2); 779 h = Math.max(1, h / 2); 780 } 781 }; 782 783 var glInitLayered = function(cfg, depth_divider, gl) { 784 var format = glsFboUtil.transferImageFormat(cfg.internalFormat, gl); 785 var w = cfg.width; 786 var h = cfg.height; 787 var depth = cfg.numLayers; 788 for (var level = 0; level < cfg.numLevels; ++level) { 789 gl.texImage3D( 790 glTarget(cfg, gl), level, cfg.internalFormat.format, 791 w, h, depth, 0, format.format, format.dataType, null 792 ); 793 w = Math.max(1, w / 2); 794 h = Math.max(1, h / 2); 795 depth = Math.max(1, depth / depth_divider); 796 } 797 }; 798 799 var glCreate = function(cfg, gl) { 800 if (!(gl = gl || window.gl)) throw new Error('Invalid gl object'); 801 802 if (cfg.type & glsFboUtil.Config.s_types.RENDERBUFFER) { 803 var ret = gl.createRenderbuffer(); 804 gl.bindRenderbuffer(gl.RENDERBUFFER, ret); 805 806 if (cfg.numSamples == 0) { 807 gl.renderbufferStorage( 808 gl.RENDERBUFFER, 809 cfg.internalFormat.format, 810 cfg.width, cfg.height 811 ); 812 } else { 813 gl.renderbufferStorageMultisample( 814 gl.RENDERBUFFER, 815 cfg.numSamples, 816 cfg.internalFormat.format, 817 cfg.width, cfg.height 818 ); 819 } 820 gl.bindRenderbuffer(gl.RENDERBUFFER, null); 821 822 } else if (cfg.type & glsFboUtil.Config.s_types.TEXTURE) { 823 var ret = gl.createTexture(); 824 gl.bindTexture(glTarget(cfg, gl), ret); 825 glInit(cfg, gl); 826 gl.bindTexture(glTarget(cfg, gl), null); 827 828 } else { 829 throw new Error('Impossible image type'); 830 } 831 return ret; 832 }; 833 834 var glTarget = function(cfg, gl) { 835 if (!(gl = gl || window.gl)) throw new Error('Invalid gl object'); 836 var mask = ( 837 glsFboUtil.Config.s_types.RENDERBUFFER | 838 glsFboUtil.Config.s_types.TEXTURE_2D | 839 glsFboUtil.Config.s_types.TEXTURE_CUBE_MAP | 840 glsFboUtil.Config.s_types.TEXTURE_3D | 841 glsFboUtil.Config.s_types.TEXTURE_2D_ARRAY 842 ); 843 switch (cfg.type & mask) { 844 case glsFboUtil.Config.s_types.RENDERBUFFER: return gl.RENDERBUFFER; 845 case glsFboUtil.Config.s_types.TEXTURE_2D: return gl.TEXTURE_2D; 846 case glsFboUtil.Config.s_types.TEXTURE_CUBE_MAP: return gl.TEXTURE_CUBE_MAP; 847 case glsFboUtil.Config.s_types.TEXTURE_3D: return gl.TEXTURE_3D; 848 case glsFboUtil.Config.s_types.TEXTURE_2D_ARRAY: return gl.TEXTURE_2D_ARRAY; 849 default: break; 850 } 851 throw new Error('Impossible image type.'); 852 }; 853 854 var glDelete = function(cfg, img, gl) { 855 if (cfg.type & glsFboUtil.Config.s_types.RENDERBUFFER) 856 gl.deleteRenderbuffer(img); 857 else if (cfg.type & glsFboUtil.Config.s_types.TEXTURE) 858 gl.deleteTexture(img); 859 else 860 throw new Error('Impossible image type'); 861 }; 862 863 return { 864 create: glCreate, 865 remove: glDelete 866 }; 867 868 }(); 869 870 /** *generated by script* 871 * @param {number} img 872 * @return {number} 873 */ 874 glsFboUtil.imageNumSamples = function(img) { 875 return (img.numSamples != undefined) ? img.numSamples : 0; 876 }; 877 878 /** *generated by script* 879 * @param {glsFboUtil.Attachment} att 880 * @param {number} attPoint 881 * @param {WebGLRenderingContextBase=} gl 882 * @throws {Error} 883 */ 884 glsFboUtil.attachAttachment = function(att, attPoint, gl) { 885 if (!(gl = gl || window.gl)) throw new Error('Invalid gl object'); 886 887 var mask = ( 888 glsFboUtil.Config.s_types.ATT_RENDERBUFFER | 889 glsFboUtil.Config.s_types.ATT_TEXTURE_FLAT | 890 glsFboUtil.Config.s_types.ATT_TEXTURE_LAYER 891 ); 892 893 switch (att.type & mask) { 894 case glsFboUtil.Config.s_types.ATT_RENDERBUFFER: 895 gl.framebufferRenderbuffer( 896 att.target, attPoint, att.renderbufferTarget, /** @type {WebGLRenderbuffer} */(att.imageName) 897 ); 898 break; 899 case glsFboUtil.Config.s_types.ATT_TEXTURE_FLAT: 900 gl.framebufferTexture2D( 901 att.target, attPoint, att.texTarget, /** @type {WebGLTexture} */(att.imageName), att.level 902 ); 903 break; 904 case glsFboUtil.Config.s_types.ATT_TEXTURE_LAYER: 905 gl.framebufferTextureLayer( 906 att.target, attPoint, /** @type {WebGLTexture} */(att.imageName), att.level, att.layer 907 ); 908 break; 909 default: 910 throw new Error('Impossible attachment type'); 911 } 912 913 }; 914 915 /** *generated by script* 916 * @param {glsFboUtil.Attachment} att 917 * @param {WebGLRenderingContextBase=} gl 918 * @return {number} 919 * @throws {Error} 920 */ 921 glsFboUtil.attachmentType = function(att, gl) { 922 if (!(gl = gl || window.gl)) throw new Error('Invalid gl object'); 923 924 if (att.type & glsFboUtil.Config.s_types.ATT_RENDERBUFFER) { 925 return gl.RENDERBUFFER; 926 } 927 if (att.type & glsFboUtil.Config.s_types.ATT_TEXTURE) { 928 return gl.TEXTURE; 929 } 930 throw new Error('Impossible attachment type.'); 931 932 }; 933 934 /** 935 * @param {glsFboUtil.Attachment} att 936 * @return {number} 937 * @throws {Error} 938 */ 939 glsFboUtil.textureLayer = function(att) { 940 if (att.type & glsFboUtil.Config.s_types.ATT_TEXTURE_FLAT) return 0; 941 if (att.type & glsFboUtil.Config.s_types.ATT_TEXTURE_LAYER) return att.layer; 942 throw new Error('Impossible attachment type.'); 943 }; 944 945 /** 946 * @param {glsFboUtil.Checker} cctx 947 * @param {glsFboUtil.Attachment} att 948 * @param {number} attPoint 949 * @param {glsFboUtil.Image} image 950 * @param {glsFboUtil.FormatDB} db 951 * @param {WebGLRenderingContextBase=} gl 952 * @throws {Error} 953 */ 954 glsFboUtil.checkAttachmentCompleteness = function(cctx, att, attPoint, image, db, gl) { 955 if (!(gl = gl || window.gl)) throw new Error('Invalid gl object'); 956 957 // GLES2 4.4.5 / GLES3 4.4.4, "glsFboUtil.Framebuffer attachment completeness" 958 if ( 959 (att.type & glsFboUtil.Config.s_types.ATT_TEXTURE) && 960 (image.type & glsFboUtil.Config.s_types.TEXTURE_LAYERED) 961 ) { 962 // GLES3: "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is 963 // TEXTURE and the value of FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names a 964 // three-dimensional texture, then the value of 965 // FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER must be smaller than the depth 966 // of the texture. 967 // 968 // GLES3: "If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is 969 // TEXTURE and the value of FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names a 970 // two-dimensional array texture, then the value of 971 // FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER must be smaller than the 972 // number of layers in the texture. 973 cctx.addFBOStatus( 974 glsFboUtil.textureLayer(att) < image.numLayers, 975 gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT 976 ); 977 } 978 979 // "The width and height of image are non-zero." 980 cctx.addFBOStatus( 981 image.width > 0 && image.height > 0, 982 gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT 983 ); 984 985 // Check for renderability 986 var flags = db.getFormatInfo(image.internalFormat, glsFboUtil.FormatFlags.ANY_FORMAT); 987 988 // If the format does not have the proper renderability flag, the 989 // completeness check _must_ fail. 990 cctx.addFBOStatus( 991 (flags & glsFboUtil.formatFlag(attPoint)) != 0, 992 gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT 993 ); 994 995 // If the format is only optionally renderable, the completeness check _can_ fail. 996 cctx.addPotentialFBOStatus( 997 (flags & glsFboUtil.FormatFlags.REQUIRED_RENDERABLE) != 0, 998 gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT 999 ); 1000 1001 }; 1002 1003 // replaces GLS_UNSIZED_FORMATKEY 1004 1005 /** 1006 * All params and return types for this function are 32 bit 1007 * @param {number} format 1008 * @param {number} type 1009 * @return {number} 1010 */ 1011 glsFboUtil.formatkey = function(format, type) { 1012 // The formatkey value should be 32-bit unsigned int. 1013 return ((type << 16) >>> 0 | format) & 0xFFFFFFFF; 1014 }; 1015 1016 /** 1017 * @enum 1018 */ 1019 glsFboUtil.FormatFlags = { 1020 ANY_FORMAT: 0x00, 1021 COLOR_RENDERABLE: 0x01, 1022 DEPTH_RENDERABLE: 0x02, 1023 STENCIL_RENDERABLE: 0x04, 1024 RENDERBUFFER_VALID: 0x08, 1025 TEXTURE_VALID: 0x10, 1026 REQUIRED_RENDERABLE: 0x20 //< Without this, renderability is allowed, not required. 1027 }; 1028 1029 /** 1030 * A framebuffer configuration 1031 * @constructor 1032 * @param {WebGLRenderingContextBase=} gl 1033 */ 1034 glsFboUtil.Framebuffer = function(gl) { 1035 this.m_gl = gl || window.gl; 1036 this.fbid = 0; 1037 1038 var fbidCompare = function(obj1, obj2) { 1039 return obj1._fbid < obj2._fbid; 1040 }; 1041 1042 this.attachments = /** @type {glsFboUtil.Map<number,glsFboUtil.Attachment>} */( 1043 new glsFboUtil.Map(glsFboUtil.Map.compareNumber) 1044 ); 1045 this.textures = /** @type {glsFboUtil.Map<Object,glsFboUtil.Texture>} */( 1046 new glsFboUtil.Map(fbidCompare) 1047 ); 1048 this.rbos = /** @type {glsFboUtil.Map<Object,glsFboUtil.Renderbuffer>} */( 1049 new glsFboUtil.Map(fbidCompare) 1050 ); 1051 }; 1052 1053 /** 1054 * @param {number} attPoint 1055 * @param {glsFboUtil.Attachment} att 1056 */ 1057 glsFboUtil.Framebuffer.prototype.attach = function(attPoint, att) { 1058 if (!att) { 1059 this.attachments.remove(attPoint); 1060 } else { 1061 this.attachments.set(attPoint, att); 1062 } 1063 }; 1064 1065 /** 1066 * @param {WebGLTexture} texName 1067 * @param {glsFboUtil.Texture} texCfg 1068 */ 1069 glsFboUtil.Framebuffer.prototype.setTexture = function(texName, texCfg) { 1070 texName._fbid = this.fbid++; 1071 this.textures.set(texName, texCfg); 1072 }; 1073 1074 /** 1075 * @param {WebGLRenderbuffer} rbName 1076 * @param {glsFboUtil.Renderbuffer} rbCfg 1077 */ 1078 glsFboUtil.Framebuffer.prototype.setRbo = function(rbName, rbCfg) { 1079 rbName._fbid = this.fbid++; 1080 this.rbos.set(rbName, rbCfg); 1081 }; 1082 1083 /** 1084 * @param {number} type 1085 * @param {WebGLObject} imgName 1086 * @return {glsFboUtil.Image} 1087 * @throws {Error} 1088 */ 1089 glsFboUtil.Framebuffer.prototype.getImage = function(type, imgName) { 1090 switch (type) { 1091 case this.m_gl.TEXTURE: return this.textures.lookupDefault(/** @type {WebGLTexture} */(imgName), null); 1092 case this.m_gl.RENDERBUFFER: return this.rbos.lookupDefault(/** @type {WebGLTexture} */(imgName), null); 1093 default: break; 1094 } 1095 throw new Error('Bad image type.'); 1096 }; 1097 1098 /** 1099 * @constructor 1100 * @extends {glsFboUtil.Framebuffer} 1101 * @param {WebGLFramebuffer} fbo 1102 * @param {number} target 1103 * @param {WebGLRenderingContextBase=} gl 1104 */ 1105 glsFboUtil.FboBuilder = function(fbo, target, gl) { 1106 glsFboUtil.Framebuffer.call(this, gl); 1107 1108 this.m_gl = gl || window.gl; 1109 this.m_target = target; 1110 this.m_configs = []; 1111 this.m_error = this.m_gl.NO_ERROR; 1112 1113 this.m_gl.bindFramebuffer(this.m_target, fbo); 1114 1115 }; 1116 1117 glsFboUtil.FboBuilder.prototype = Object.create(glsFboUtil.Framebuffer.prototype); 1118 glsFboUtil.FboBuilder.prototype.constructor = glsFboUtil.FboBuilder; 1119 1120 glsFboUtil.FboBuilder.prototype.deinit = function() { 1121 1122 var pair; 1123 for (var i = 0; i < this.textures.length; ++i) { 1124 pair = this.textures.getIndex(i); 1125 glsFboUtil.glsup.remove(pair.second, pair.first, this.m_gl); 1126 } 1127 this.textures.clear(); 1128 1129 for (var i = 0; i < this.rbos.length; ++i) { 1130 pair = this.rbos.getIndex(i); 1131 glsFboUtil.glsup.remove(pair.second, pair.first, this.m_gl); 1132 } 1133 this.rbos.clear(); 1134 1135 this.m_gl.bindFramebuffer(this.m_target, null); 1136 /* 1137 for (var i = 0 ; i < this.m_configs.length ; ++i) { 1138 delete this.m_configs[i]; 1139 } 1140 //*/ 1141 }; 1142 1143 /** 1144 * @param {number} attPoint 1145 * @param {glsFboUtil.Attachment} att 1146 */ 1147 glsFboUtil.FboBuilder.prototype.glAttach = function(attPoint, att) { 1148 if (!att) { 1149 this.m_gl.framebufferRenderbuffer(this.m_target, attPoint, this.m_gl.RENDERBUFFER, null); 1150 } else { 1151 glsFboUtil.attachAttachment(att, attPoint, this.m_gl); 1152 } 1153 this.checkError(); 1154 this.attach(attPoint, att); 1155 }; 1156 1157 /** 1158 * @param {glsFboUtil.Texture} texCfg 1159 * @return {WebGLTexture} 1160 */ 1161 glsFboUtil.FboBuilder.prototype.glCreateTexture = function(texCfg) { 1162 var texName = glsFboUtil.glsup.create(texCfg, this.m_gl); 1163 this.checkError(); 1164 this.setTexture(texName, texCfg); 1165 return texName; 1166 }; 1167 1168 /** *generated by script* 1169 * @param {glsFboUtil.Renderbuffer} rbCfg 1170 * @return {WebGLRenderbuffer} 1171 */ 1172 glsFboUtil.FboBuilder.prototype.glCreateRbo = function(rbCfg) { 1173 var rbName = glsFboUtil.glsup.create(rbCfg, this.m_gl); 1174 this.checkError(); 1175 this.setRbo(rbName, rbCfg); 1176 return rbName; 1177 }; 1178 1179 /** 1180 * @param {function(new:glsFboUtil.Config)} Definition 1181 * @return {glsFboUtil.Config} 1182 */ 1183 glsFboUtil.FboBuilder.prototype.makeConfig = function(Definition) { 1184 var cfg = new Definition(); 1185 this.m_configs.push(cfg); 1186 return cfg; 1187 }; 1188 1189 /** 1190 */ 1191 glsFboUtil.FboBuilder.prototype.checkError = function() { 1192 var error = this.m_gl.getError(); 1193 if (error != this.m_gl.NO_ERROR && this.m_error == this.m_gl.NO_ERROR) { 1194 this.m_error = error; 1195 } 1196 }; 1197 1198 /** *generated by script* 1199 * @return {number} 1200 */ 1201 glsFboUtil.FboBuilder.prototype.getError = function() { 1202 return this.m_error; 1203 }; 1204 1205 glsFboUtil.isFramebufferStatus = function(fboStatus) { 1206 return gluStrUtil.getFramebufferStatusName(fboStatus) != ''; 1207 } 1208 1209 glsFboUtil.isErrorCode = function(errorCode) { 1210 return gluStrUtil.getErrorName(errorCode) != ''; 1211 } 1212 1213 /** 1214 * @typedef {funcion(): glsFboUtil.ValidStatusCodes} 1215 */ 1216 glsFboUtil.ValidStatusCodes = function() { 1217 this.m_errorCodes = []; 1218 this.m_errorStatusCodes = []; 1219 this.m_allowComplete = false; 1220 }; 1221 1222 glsFboUtil.ValidStatusCodes.prototype.isFBOStatusValid = function(fboStatus) { 1223 if (fboStatus == gl.FRAMEBUFFER_COMPLETE) 1224 return this.m_allowComplete; 1225 else { 1226 for(var ndx = 0; ndx < this.m_errorStatusCodes.length; ++ndx) { 1227 if (this.m_errorStatusCodes[ndx] == fboStatus) 1228 return true; 1229 } 1230 return false; 1231 } 1232 }; 1233 1234 glsFboUtil.ValidStatusCodes.prototype.isFBOStatusRequired = function(fboStatus) { 1235 if (fboStatus == gl.FRAMEBUFFER_COMPLETE) 1236 return this.m_allowComplete && this.m_errorStatusCodes.length == 0; 1237 else 1238 // fboStatus is the only allowed error status and succeeding is forbidden 1239 return !this.m_allowComplete && this.m_errorStatusCodes.length == 1 && this.m_errorStatusCodes[0] == fboStatus; 1240 }; 1241 1242 glsFboUtil.ValidStatusCodes.prototype.isErrorCodeValid = function(errorCode) { 1243 if (errorCode == gl.NO_ERROR) 1244 return this.m_errorCodes.length == 0; 1245 else { 1246 // rule violation exists? 1247 for (var ndx = 0; ndx < this.m_errorCodes.length; ++ndx) { 1248 if (this.m_errorCodes[ndx] == errorCode) 1249 return true; 1250 } 1251 return false; 1252 } 1253 }; 1254 1255 glsFboUtil.ValidStatusCodes.prototype.isErrorCodeRequired = function(errorCode) { 1256 if (this.m_errorCodes.length == 0 && errorCode == gl.NO_ERROR) 1257 return true; 1258 else 1259 // only this error code listed 1260 return this.m_errorCodes.length == 1 && merrorCodes[0] == errorCode; 1261 }; 1262 1263 glsFboUtil.ValidStatusCodes.prototype.addErrorCode = function(error) { 1264 DE_ASSERT(glsFboUtil.isErrorCode(error)); 1265 DE_ASSERT(error != gl.NO_ERROR) 1266 this.m_errorCodes.push(error); 1267 }; 1268 1269 glsFboUtil.ValidStatusCodes.prototype.addFBOErrorStatus = function(status) { 1270 DE_ASSERT(glsFboUtil.isFramebufferStatus(status)); 1271 DE_ASSERT(status != gl.FRAMEBUFFER_COMPLETE) 1272 this.m_errorStatusCodes.push(status); 1273 }; 1274 1275 glsFboUtil.ValidStatusCodes.prototype.setAllowComplete = function(b) { 1276 this.m_allowComplete = b; 1277 }; 1278 1279 /** 1280 * @typedef {function(): glsFboUtil.Checker} 1281 */ 1282 glsFboUtil.CheckerFactory; 1283 1284 /** 1285 * @constructor 1286 * @param {WebGLRenderingContextBase=} gl 1287 * @throws {Error} 1288 */ 1289 glsFboUtil.Checker = function(gl) { 1290 if (!(gl = gl || window.gl)) throw new Error('Invalid gl object'); 1291 1292 this.m_statusCodes = new glsFboUtil.ValidStatusCodes(); 1293 this.m_statusCodes.setAllowComplete(true); 1294 1295 if (typeof(this.check) != 'function') 1296 throw new Error('Constructor called on virtual class: glsFboUtil.Checker'); 1297 }; 1298 1299 /** 1300 * @param {boolean} condition 1301 * @param {number} error 1302 */ 1303 glsFboUtil.Checker.prototype.addGLError = function(condition, error) { 1304 if (!condition) { 1305 this.m_statusCodes.addErrorCode(error); 1306 this.m_statusCodes.setAllowComplete(false); 1307 } 1308 }; 1309 1310 /** 1311 * @param {boolean} condition 1312 * @param {number} error 1313 */ 1314 glsFboUtil.Checker.prototype.addPotentialGLError = function(condition, error) { 1315 if (!condition) { 1316 this.m_statusCodes.addErrorCode(error); 1317 } 1318 }; 1319 1320 /** 1321 * @param {boolean} condition 1322 * @param {number} status 1323 */ 1324 glsFboUtil.Checker.prototype.addFBOStatus = function(condition, status) { 1325 if (!condition) { 1326 this.m_statusCodes.addFBOErrorStatus(status); 1327 this.m_statusCodes.setAllowComplete(false); 1328 } 1329 }; 1330 1331 /** 1332 * @param {boolean} condition 1333 * @param {number} status 1334 */ 1335 glsFboUtil.Checker.prototype.addPotentialFBOStatus = function(condition, status) { 1336 if (!condition) { 1337 this.m_statusCodes.addFBOErrorStatus(status); 1338 } 1339 }; 1340 1341 /** 1342 * @return {Array<number>} 1343 */ 1344 glsFboUtil.Checker.prototype.getStatusCodes = function () { 1345 return this.m_statusCodes; 1346 }; 1347 1348 /** 1349 * @param {glsFboUtil.ImageFormat} imgFormat 1350 * @param {WebGLRenderingContextBase=} gl 1351 * @return {gluTextureUtil.TransferFormat} 1352 * @throws {Error} 1353 */ 1354 glsFboUtil.transferImageFormat = function(imgFormat, gl) { 1355 if (!(gl = gl || window.gl)) throw new Error('Invalid gl object'); 1356 if (imgFormat.unsizedType == gl.NONE) 1357 return gluTextureUtil.getTransferFormat(gluTextureUtil.mapGLInternalFormat(imgFormat.format)); 1358 else 1359 return new gluTextureUtil.TransferFormat(imgFormat.format, imgFormat.unsizedType); 1360 }; 1361 1362 // FormatDB, CheckerFactory 1363 1364 /** 1365 * @constructor 1366 * @param {glsFboUtil.FormatDB} formats 1367 * @param {glsFboUtil.CheckerFactory} factory 1368 */ 1369 glsFboUtil.FboVerifier = function(formats, factory) { 1370 this.m_formats = formats; 1371 this.m_factory = factory; 1372 }; 1373 // config::Framebuffer 1374 glsFboUtil.FboVerifier.prototype.validStatusCodes = function(cfg, gl) { 1375 if (!(gl = gl || window.gl)) throw new Error('Invalid gl object'); 1376 1377 /** @type {glsFboUtil.Checker} */ 1378 var cctx = this.m_factory(); 1379 1380 for (var id = 0; id < cfg.textures.length; ++id) { 1381 var flags = this.m_formats.getFormatInfo(cfg.textures.getIndex(id).second.internalFormat, glsFboUtil.FormatFlags.ANY_FORMAT); 1382 var textureIsValid = (flags & glsFboUtil.FormatFlags.TEXTURE_VALID) != 0; 1383 cctx.addGLError(textureIsValid, gl.INVALID_ENUM); 1384 cctx.addGLError(textureIsValid, gl.INVALID_OPERATION); 1385 cctx.addGLError(textureIsValid, gl.INVALID_VALUE); 1386 } 1387 1388 for (var id = 0; id < cfg.rbos.length; ++id) { 1389 var flags = this.m_formats.getFormatInfo(cfg.rbos.getIndex(id).second.internalFormat, glsFboUtil.FormatFlags.ANY_FORMAT); 1390 var rboIsValid = (flags & glsFboUtil.FormatFlags.RENDERBUFFER_VALID) != 0; 1391 cctx.addGLError(rboIsValid, gl.INVALID_ENUM); 1392 } 1393 1394 var count = 0; 1395 for (var index = 0; index < cfg.attachments.length; ++index) { 1396 var attPoint = cfg.attachments.getIndex(index).first; 1397 var att = cfg.attachments.getIndex(index).second; 1398 /** @type {glsFboUtil.Image}*/ 1399 var image = cfg.getImage(glsFboUtil.attachmentType(att, gl), att.imageName); 1400 glsFboUtil.checkAttachmentCompleteness(cctx, att, attPoint, image, this.m_formats, gl); 1401 cctx.check(attPoint, att, image); 1402 ++count; 1403 } 1404 1405 // "There is at least one image attached to the framebuffer." 1406 // TODO: support XXX_framebuffer_no_attachments 1407 cctx.addFBOStatus(count > 0, gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT); 1408 1409 return cctx.getStatusCodes(); 1410 1411 }; 1412 1413 });