tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

gluShaderProgram.js (15560B)


      1 /*-------------------------------------------------------------------------
      2 * drawElements Quality gluShaderProgram.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('framework.opengl.gluShaderProgram');
     23 
     24 goog.scope(function() {
     25 
     26 var gluShaderProgram = framework.opengl.gluShaderProgram;
     27 
     28 /**
     29 * gluShaderProgram.Shader type enum
     30 * @enum {number}
     31 */
     32 gluShaderProgram.shaderType = {
     33    VERTEX: 0,
     34    FRAGMENT: 1
     35 };
     36 
     37 /**
     38 * gluShaderProgram.Shader type enum name
     39 * @param {gluShaderProgram.shaderType} shaderType
     40 * @return {string}
     41 */
     42 gluShaderProgram.getShaderTypeName = function(shaderType) {
     43    var s_names =
     44    [
     45        'vertex',
     46        'fragment'
     47    ];
     48 
     49    return s_names[shaderType];
     50 };
     51 
     52 /**
     53 * Get GL shader type from gluShaderProgram.shaderType
     54 * @param {WebGL2RenderingContext} gl WebGL context
     55 * @param {gluShaderProgram.shaderType} type gluShaderProgram.Shader Type
     56 * @return {number} GL shader type
     57 */
     58 gluShaderProgram.getGLShaderType = function(gl, type) {
     59    var _glShaderType;
     60    switch (type) {
     61    case gluShaderProgram.shaderType.VERTEX: _glShaderType = gl.VERTEX_SHADER; break;
     62    case gluShaderProgram.shaderType.FRAGMENT: _glShaderType = gl.FRAGMENT_SHADER; break;
     63    default:
     64        throw new Error('Unknown shader type ' + type);
     65    }
     66    return _glShaderType;
     67 };
     68 
     69 /**
     70 * Declares shader information
     71 * @constructor
     72 * @param {gluShaderProgram.shaderType} type
     73 * @param {string=} source
     74 */
     75 gluShaderProgram.ShaderInfo = function(type, source) {
     76    this.type = type; /** gluShaderProgram.Shader type. */
     77    this.source = source; /** gluShaderProgram.Shader source. */
     78    this.infoLog; /** Compile info log. */
     79    this.compileOk = false; /** Did compilation succeed? */
     80    this.compileTimeUs = 0; /** Compile time in microseconds (us). */
     81 };
     82 
     83 /**
     84 * Generates vertex shader info from source
     85 * @param {string} source
     86 * @return {gluShaderProgram.ShaderInfo} vertex shader info
     87 */
     88 gluShaderProgram.genVertexSource = function(source) {
     89 /** @type {gluShaderProgram.ShaderInfo} */ var shader = new gluShaderProgram.ShaderInfo(gluShaderProgram.shaderType.VERTEX, source);
     90    return shader;
     91 };
     92 
     93 /**
     94 * Generates fragment shader info from source
     95 * @param {string} source
     96 * @return {gluShaderProgram.ShaderInfo} fragment shader info
     97 */
     98 gluShaderProgram.genFragmentSource = function(source) {
     99 /** @type {gluShaderProgram.ShaderInfo} */ var shader = new gluShaderProgram.ShaderInfo(gluShaderProgram.shaderType.FRAGMENT, source);
    100    return shader;
    101 };
    102 
    103 /**
    104 * Generates shader from WebGL context and type
    105 * @constructor
    106 * @param {WebGL2RenderingContext} gl WebGL context
    107 * @param {gluShaderProgram.shaderType} type gluShaderProgram.Shader Type
    108 */
    109 gluShaderProgram.Shader = function(gl, type) {
    110    this.gl = gl;
    111    this.info = new gluShaderProgram.ShaderInfo(type); /** Client-side clone of state for debug / perf reasons. */
    112    this.shader = gl.createShader(gluShaderProgram.getGLShaderType(gl, type));
    113    assertMsgOptions(gl.getError() == gl.NO_ERROR, 'gl.createShader()', false, true);
    114 
    115    this.setSources = function(source) {
    116        this.gl.shaderSource(this.shader, source);
    117        assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'glshaderSource()', false, true);
    118        this.info.source = source;
    119    };
    120 
    121    this.getCompileStatus = function() {
    122        return this.info.compileOk;
    123    };
    124 
    125    this.compile = function() {
    126        this.info.compileOk = false;
    127        this.info.compileTimeUs = 0;
    128        this.info.infoLog = '';
    129 
    130        /** @type {Date} */ var compileStart = new Date();
    131        this.gl.compileShader(this.shader);
    132        /** @type {Date} */ var compileEnd = new Date();
    133        this.info.compileTimeUs = 1000 * (compileEnd.getTime() - compileStart.getTime());
    134 
    135        assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.compileShader()', false, true);
    136 
    137        var compileStatus = this.gl.getShaderParameter(this.shader, this.gl.COMPILE_STATUS);
    138        assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'glGetShaderParameter()', false, true);
    139 
    140        this.info.compileOk = compileStatus;
    141        this.info.infoLog = this.gl.getShaderInfoLog(this.shader);
    142    };
    143 
    144    this.getShader = function() {
    145        return this.shader;
    146    };
    147 
    148    this.destroy = function() {
    149        this.gl.deleteShader(this.shader);
    150    };
    151 
    152 };
    153 /**
    154 * Creates gluShaderProgram.ProgramInfo
    155 * @constructor
    156 */
    157 gluShaderProgram.ProgramInfo = function() {
    158    /** @type {string} */  this.infoLog = ''; /** Link info log. */
    159    /** @type {boolean} */ this.linkOk = false; /** Did link succeed? */
    160    /** @type {number} */ this.linkTimeUs = 0; /** Link time in microseconds (us). */
    161 };
    162 
    163 /**
    164 * Creates program.
    165 * Inner methods: attach shaders, bind attributes location, link program and transform Feedback Varyings
    166 * @constructor
    167 * @param {WebGL2RenderingContext} gl WebGL context
    168 * @param {WebGLProgram=} programID
    169 */
    170 gluShaderProgram.Program = function(gl, programID) {
    171    this.gl = gl;
    172    this.program = programID || null;
    173    this.info = new gluShaderProgram.ProgramInfo();
    174 
    175    if (!programID) {
    176        this.program = gl.createProgram();
    177        assertMsgOptions(gl.getError() == gl.NO_ERROR, 'gl.createProgram()', false, true);
    178    }
    179 };
    180 
    181 /**
    182 * @return {WebGLProgram}
    183 */
    184 gluShaderProgram.Program.prototype.getProgram = function() { return this.program; };
    185 
    186 /**
    187 * @return {gluShaderProgram.ProgramInfo}
    188 */
    189 gluShaderProgram.Program.prototype.getInfo = function() { return this.info; };
    190 
    191 /**
    192 * @param {WebGLShader} shader
    193 */
    194 gluShaderProgram.Program.prototype.attachShader = function(shader) {
    195    this.gl.attachShader(this.program, shader);
    196    assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.attachShader()', false, true);
    197 };
    198 
    199 /**
    200 * @param {WebGLShader} shader
    201 */
    202 gluShaderProgram.Program.prototype.detachShader = function(shader) {
    203    this.gl.detachShader(this.program, shader);
    204    assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.detachShader()', false, true);
    205 };
    206 
    207 /**
    208 * @param {number} location
    209 * @param {string} name
    210 */
    211 gluShaderProgram.Program.prototype.bindAttribLocation = function(location, name) {
    212    this.gl.bindAttribLocation(this.program, location, name);
    213    assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.bindAttribLocation()', false, true);
    214 };
    215 
    216 gluShaderProgram.Program.prototype.link = function() {
    217    this.info.linkOk = false;
    218    this.info.linkTimeUs = 0;
    219    this.info.infoLog = '';
    220 
    221    /** @type {Date} */ var linkStart = new Date();
    222    this.gl.linkProgram(this.program);
    223    /** @type {Date} */ var linkEnd = new Date();
    224    this.info.linkTimeUs = 1000 * (linkEnd.getTime() - linkStart.getTime());
    225 
    226    assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.linkProgram()', false, true);
    227 
    228    var linkStatus = this.gl.getProgramParameter(this.program, this.gl.LINK_STATUS);
    229    assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.getProgramParameter()', false, true);
    230    this.info.linkOk = linkStatus;
    231    this.info.infoLog = this.gl.getProgramInfoLog(this.program);
    232    if (!this.info.linkOk)
    233        bufferedLogToConsole("program linking: " + this.info.infoLog);
    234 };
    235 
    236 /**
    237 * return {boolean}
    238 */
    239 gluShaderProgram.Program.prototype.getLinkStatus = function() {
    240    return this.info.linkOk;
    241 };
    242 
    243 /**
    244 * @param {Array<string>} varyings
    245 * @param {number} bufferMode
    246 */
    247 gluShaderProgram.Program.prototype.transformFeedbackVaryings = function(varyings, bufferMode) {
    248    this.gl.transformFeedbackVaryings(this.program, varyings, bufferMode);
    249    assertMsgOptions(this.gl.getError() == this.gl.NO_ERROR, 'gl.transformFeedbackVaryings()', false, true);
    250 };
    251 
    252 /**
    253 * Assigns gl WebGL context and programSources. Declares array of shaders and new program()
    254 * @constructor
    255 * @param {WebGL2RenderingContext} gl WebGL context
    256 * @param {gluShaderProgram.ProgramSources} programSources
    257 */
    258 gluShaderProgram.ShaderProgram = function(gl, programSources) {
    259    this.gl = gl;
    260    this.programSources = programSources;
    261    this.shaders = [];
    262    this.program = new gluShaderProgram.Program(gl);
    263 
    264    /** @type {boolean} */ this.shadersOK = true;
    265 
    266    for (var i = 0; i < programSources.sources.length; i++) {
    267    /** @type {gluShaderProgram.Shader} */ var shader = new gluShaderProgram.Shader(gl, programSources.sources[i].type);
    268        shader.setSources(programSources.sources[i].source);
    269        shader.compile();
    270        this.shaders.push(shader);
    271        this.shadersOK = this.shadersOK && shader.getCompileStatus();
    272        if (!shader.getCompileStatus()) {
    273            bufferedLogToConsole('gluShaderProgram.Shader:\n' + programSources.sources[i].source);
    274            bufferedLogToConsole('Compile status: ' + shader.getCompileStatus());
    275            bufferedLogToConsole('Shader infoLog: ' + shader.info.infoLog);
    276        }
    277    }
    278 
    279    if (this.shadersOK) {
    280        for (var i = 0; i < this.shaders.length; i++)
    281            this.program.attachShader(this.shaders[i].getShader());
    282 
    283        for (var attrib in programSources.attribLocationBindings)
    284            this.program.bindAttribLocation(programSources.attribLocationBindings[attrib], attrib);
    285 
    286        if (programSources.transformFeedbackBufferMode)
    287            if (programSources.transformFeedbackBufferMode === gl.NONE)
    288                assertMsgOptions(programSources.transformFeedbackVaryings.length === 0, 'Transform feedback sanity check', false, true);
    289            else
    290                this.program.transformFeedbackVaryings(programSources.transformFeedbackVaryings, programSources.transformFeedbackBufferMode);
    291 
    292        /* TODO: GLES 3.1: set separable flag */
    293 
    294        this.program.link();
    295 
    296    }
    297 };
    298 
    299 /**
    300 * return {WebGLProgram}
    301 */
    302 gluShaderProgram.ShaderProgram.prototype.getProgram = function() {
    303    return this.program.program;
    304    };
    305 
    306 /**
    307 * @return {gluShaderProgram.ProgramInfo}
    308 */
    309 gluShaderProgram.ShaderProgram.prototype.getProgramInfo = function() {
    310    return this.program.info;
    311 };
    312 
    313 gluShaderProgram.ShaderProgram.prototype.isOk = function() {
    314    return this.shadersOK && this.program.getLinkStatus();
    315 };
    316 
    317 gluShaderProgram.containerTypes = {
    318    ATTRIB_LOCATION_BINDING: 0,
    319    TRANSFORM_FEEDBACK_MODE: 1,
    320    TRANSFORM_FEEDBACK_VARYING: 2,
    321    TRANSFORM_FEEDBACK_VARYINGS: 3,
    322    SHADER_SOURCE: 4,
    323    PROGRAM_SEPARABLE: 5,
    324    PROGRAM_SOURCES: 6,
    325 
    326    CONTAINER_TYPE_LAST: 7,
    327    ATTACHABLE_BEGIN: 0, // ATTRIB_LOCATION_BINDING
    328    ATTACHABLE_END: 5 + 1 // PROGRAM_SEPARABLE + 1
    329 };
    330 
    331 /**
    332 * @constructor
    333 */
    334 gluShaderProgram.AttribLocationBinding = function(name, location) {
    335    this.name = name;
    336    this.location = location;
    337 
    338    this.getContainerType = function() {
    339        return gluShaderProgram.containerTypes.ATTRIB_LOCATION_BINDING;
    340    };
    341 };
    342 
    343 /**
    344 * @constructor
    345 */
    346 gluShaderProgram.TransformFeedbackMode = function(mode) {
    347    this.mode = mode;
    348 
    349    this.getContainerType = function() {
    350        return gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_MODE;
    351    };
    352 };
    353 
    354 /**
    355 * @constructor
    356 * @param {string} name
    357 */
    358 gluShaderProgram.TransformFeedbackVarying = function(name) {
    359    /** @type {string} */ this.name = name;
    360 
    361    this.getContainerType = function() {
    362        return gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_VARYING;
    363    };
    364 };
    365 
    366 /**
    367 * @constructor
    368 * @param {Array<string>} array
    369 */
    370 gluShaderProgram.TransformFeedbackVaryings = function(array) {
    371    /** @type {Array<string>} */ this.array = array;
    372 
    373    this.getContainerType = function() {
    374        return gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_VARYINGS;
    375    };
    376 };
    377 
    378 /**
    379 * @constructor
    380 */
    381 gluShaderProgram.ProgramSeparable = function(separable) {
    382    this.separable = separable;
    383 
    384    this.getContainerType = function() {
    385        return gluShaderProgram.containerTypes.PROGRAM_SEPARABLE;
    386    };
    387 };
    388 
    389 /**
    390 * @constructor
    391 */
    392 gluShaderProgram.VertexSource = function(str) {
    393    this.shaderType = gluShaderProgram.shaderType.VERTEX;
    394    this.source = str;
    395 
    396    this.getContainerType = function() {
    397        return gluShaderProgram.containerTypes.SHADER_SOURCE;
    398    };
    399 };
    400 
    401 /**
    402 * @constructor
    403 */
    404 gluShaderProgram.FragmentSource = function(str) {
    405    this.shaderType = gluShaderProgram.shaderType.FRAGMENT;
    406    this.source = str;
    407 
    408    this.getContainerType = function() {
    409        return gluShaderProgram.containerTypes.SHADER_SOURCE;
    410    };
    411 };
    412 
    413 /**
    414 * Create gluShaderProgram.ProgramSources.
    415 * @constructor
    416 */
    417 gluShaderProgram.ProgramSources = function() {
    418    /** @type {Array<gluShaderProgram.ShaderInfo>} */ this.sources = [];
    419    this.attribLocationBindings = [];
    420    /** @type {Array<string>} */ this.transformFeedbackVaryings = [];
    421    this.transformFeedbackBufferMode = 0;
    422    this.separable = false;
    423 };
    424 
    425 gluShaderProgram.ProgramSources.prototype.getContainerType = function() {
    426    return gluShaderProgram.containerTypes.PROGRAM_SOURCES;
    427 };
    428 
    429 gluShaderProgram.ProgramSources.prototype.add = function(item) {
    430    var type = undefined;
    431    if (typeof(item.getContainerType) == 'function') {
    432        type = item.getContainerType();
    433        if (
    434            typeof(type) != 'number' ||
    435            type < gluShaderProgram.containerTypes.ATTACHABLE_BEGIN ||
    436            type >= gluShaderProgram.containerTypes.ATTACHABLE_END
    437        ) {
    438            type = undefined;
    439        }
    440    }
    441 
    442    switch (type) {
    443        case gluShaderProgram.containerTypes.ATTRIB_LOCATION_BINDING:
    444            this.attribLocationBindings.push(item);
    445            break;
    446 
    447        case gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_MODE:
    448            this.transformFeedbackBufferMode = item.mode;
    449            break;
    450 
    451        case gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_VARYING:
    452            this.transformFeedbackVaryings.push(item.name);
    453            break;
    454 
    455        case gluShaderProgram.containerTypes.TRANSFORM_FEEDBACK_VARYINGS:
    456            this.transformFeedbackVaryings = this.transformFeedbackVaryings.concat(item.array);
    457            break;
    458 
    459        case gluShaderProgram.containerTypes.SHADER_SOURCE:
    460            this.sources.push(new gluShaderProgram.ShaderInfo(item.shaderType, item.source));
    461            break;
    462 
    463        case gluShaderProgram.containerTypes.PROGRAM_SEPARABLE:
    464            this.separable = item.separable;
    465            break;
    466 
    467        default:
    468            throw new Error('Type \"' + type + '\" cannot be added to gluShaderProgram.ProgramSources.');
    469            break;
    470    }
    471 
    472    return this;
    473 };
    474 
    475 /**
    476 * //! Helper for constructing vertex-fragment source pair.
    477 * @param {string} vertexSrc
    478 * @param {string} fragmentSrc
    479 * @return {gluShaderProgram.ProgramSources}
    480 */
    481 gluShaderProgram.makeVtxFragSources = function(vertexSrc, fragmentSrc) {
    482    /** @type  {gluShaderProgram.ProgramSources} */ var sources = new gluShaderProgram.ProgramSources();
    483    sources.sources.push(gluShaderProgram.genVertexSource(vertexSrc));
    484    sources.sources.push(gluShaderProgram.genFragmentSource(fragmentSrc));
    485    return sources;
    486 };
    487 
    488 });