text: /*****************************************************************************
   * Open MCT, Copyright (c) 2014-2017, United States Government
   * as represented by the Administrator of the National Aeronautics and Space
   * Administration. All rights reserved.
   *
   * Open MCT is licensed under the Apache License, Version 2.0 (the
   * "License"); you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   * http://www.apache.org/licenses/LICENSE-2.0.
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
   * License for the specific language governing permissions and limitations
   * under the License.
   *
   * Open MCT includes source code licensed under additional open source
   * licenses. See the Open Source Licenses file (LICENSES.md) included with
   * this source code distribution or the Licensing information page available
   * at runtime from the About dialog for additional information.
   *****************************************************************************/
  
  /**
   * Module defining GLPlot. Created by vwoeltje on 11/12/14.
   */
  define(
      [],
      function () {
  
          // WebGL shader sources (for drawing plain colors)
          var FRAGMENT_SHADER = [
                  "precision mediump float;",
                  "uniform vec4 uColor;",
                  "void main(void) {",
                  "gl_FragColor = uColor;",
                  "}"
              ].join('\n'),
              VERTEX_SHADER = [
                  "attribute vec2 aVertexPosition;",
                  "uniform vec2 uDimensions;",
                  "uniform vec2 uOrigin;",
                  "void main(void) {",
                  "gl_Position = vec4(2.0 * ((aVertexPosition - uOrigin) / uDimensions) - vec2(1,1), 0, 1);",
                  "}"
              ].join('\n');
  
          /**
           * Create a new chart which uses WebGL for rendering.
           *
           * @memberof platform/features/plot
           * @constructor
           * @implements {platform/features/plot.Chart}
           * @param {CanvasElement} canvas the canvas object to render upon
           * @throws {Error} an error is thrown if WebGL is unavailable.
           */
          function GLChart(canvas) {
              var gl = canvas.getContext("webgl", { preserveDrawingBuffer: true }) ||
                      canvas.getContext("experimental-webgl", { preserveDrawingBuffer: true }),
                  vertexShader,
                  fragmentShader,
                  program,
                  aVertexPosition,
                  uColor,
                  uDimensions,
                  uOrigin;
  
              // Ensure a context was actually available before proceeding
              if (!gl) {
                  throw new Error("WebGL unavailable.");
              }
  
              // Initialize shaders
              vertexShader = gl.createShader(gl.VERTEX_SHADER);
              gl.shaderSource(vertexShader, VERTEX_SHADER);
              gl.compileShader(vertexShader);
              fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
              gl.shaderSource(fragmentShader, FRAGMENT_SHADER);
              gl.compileShader(fragmentShader);
  
              // Assemble vertex/fragment shaders into programs
              program = gl.createProgram();
              gl.attachShader(program, vertexShader);
              gl.attachShader(program, fragmentShader);
              gl.linkProgram(program);
              gl.useProgram(program);
  
              // Get locations for attribs/uniforms from the
              // shader programs (to pass values into shaders at draw-time)
              aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
              uColor = gl.getUniformLocation(program, "uColor");
              uDimensions = gl.getUniformLocation(program, "uDimensions");
              uOrigin = gl.getUniformLocation(program, "uOrigin");
              gl.enableVertexAttribArray(aVertexPosition);
  
              // Create a buffer to holds points which will be drawn
              this.buffer = gl.createBuffer();
  
              // Use a line width of 2.0 for legibility
              gl.lineWidth(2.0);
  
              // Enable blending, for smoothness
              gl.enable(gl.BLEND);
              gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
  
              this.gl = gl;
              this.aVertexPosition = aVertexPosition;
              this.uColor = uColor;
              this.uDimensions = uDimensions;
              this.uOrigin = uOrigin;
          }
  
          // Utility function to handle drawing of a buffer;
          // drawType will determine whether this is a box, line, etc.
          GLChart.prototype.doDraw = function (drawType, buf, color, points) {
              var gl = this.gl;
              gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
              gl.bufferData(gl.ARRAY_BUFFER, buf, gl.DYNAMIC_DRAW);
              gl.vertexAttribPointer(this.aVertexPosition, 2, gl.FLOAT, false, 0, 0);
              gl.uniform4fv(this.uColor, color);
              gl.drawArrays(drawType, 0, points);
          };
  
          GLChart.prototype.clear = function () {
              var gl = this.gl;
  
              // Set the viewport size; note that we use the width/height
              // that our WebGL context reports, which may be lower
              // resolution than the canvas we requested.
              gl.viewport(
                  0,
                  0,
                  gl.drawingBufferWidth,
                  gl.drawingBufferHeight
              );
              gl.clear(gl.COLOR_BUFFER_BIT + gl.DEPTH_BUFFER_BIT);
          };
  
  
          GLChart.prototype.setDimensions = function (dimensions, origin) {
              var gl = this.gl;
              if (dimensions && dimensions.length > 0 &&
                  origin && origin.length > 0) {
                  gl.uniform2fv(this.uDimensions, dimensions);
                  gl.uniform2fv(this.uOrigin, origin);
              }
          };
  
          GLChart.prototype.drawLine = function (buf, color, points) {
              this.doDraw(this.gl.LINE_STRIP, buf, color, points);
          };
  
          GLChart.prototype.drawSquare = function (min, max, color) {
              this.doDraw(this.gl.TRIANGLE_FAN, new Float32Array(
                  min.concat([min[0], max[1]]).concat(max).concat([max[0], min[1]])
              ), color, 4);
          };
  
          return GLChart;
      }
  );
  