title: WebGL: INVALID_VALUE: texImage2D: no video error in Chrome
body: <p>I'm attempting to add video as texture in WebGL. The project is simple and only involves one object. The code I have works fine in Firefox but claims there is no video when loaded in Chrome. The ERROR seems to be that the video is not starting in Chrome for some reason even though I have a function to start the video:</p>
  
  <pre><code>function startVideo() {
    videoElement.play();
    intervalID = setInterval(draw, 15);
  }
  </code></pre>
  
  <p>as well as </p>
  
  <pre><code>videoElement.preload = "auto";
  </code></pre>
  
  <p>tied to my video objectin JS. </p>
  
  <p>Additionally, I also have </p>
  
  <pre><code>&lt;video id="video" src="Firefox.ogv" autoplay muted&gt;
        Your browser doesn't appear to support the &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; element.
  &lt;/video&gt;
  </code></pre>
  
  <p>just to be sure, but it is not loadng the texture. The error is being referenced in this function for teximage2D:</p>
  
  <pre><code>function updateTexture() {
    gl.bindTexture(gl.TEXTURE_2D, modelTexture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, videoElement);
  } 
  </code></pre>
  
  <p>Subsequently, I also get the error:</p>
  
  <pre><code>RENDER WARNING: texture bound to texture unit 0 is not renderable. It maybe non-power-of-2 and have incompatible texture filtering.
  </code></pre>
  
  <p>I am using this tutorial combined with my own implemenation : </p>
  
  <p><a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Animating_textures_in_WebGL" rel="nofollow noreferrer">https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Tutorial/Animating_textures_in_WebGL</a></p>
  
  <p>My JS and HTML are located here:</p>
  
  <p><a href="https://github.com/TacoB0t/CSC43/tree/prog/prog5" rel="nofollow noreferrer">https://github.com/TacoB0t/CSC43/tree/prog/prog5</a></p>
  
  <p>Everything mostly takes place in the init() and draw() function of the JS</p>
  
  <p>HTML:</p>
  
  <pre><code>&lt;html&gt;
      &lt;head&gt;
              &lt;script type="text/javascript" src="webgl-utils.js"&gt;&lt;/script&gt;
              &lt;script type="text/javascript" src="webgl-debug.js"&gt;&lt;/script&gt;
              &lt;script type="text/javascript" src="cuon-utils.js"&gt;&lt;/script&gt;
              &lt;script type="text/javascript" src="cuon-matrix.js"&gt;&lt;/script&gt;
              &lt;script type="text/javascript" src="prog5.js"&gt;&lt;/script&gt;
              &lt;script type="text/javascript" src="chest.js"&gt;&lt;/script&gt;
              &lt;script type="text/javascript" src="cube.js"&gt;&lt;/script&gt;
  
      &lt;/head&gt;
      &lt;body onload="init()"&gt;
              &lt;script id="vertexShader" type="x-shader/x-vertex"&gt;
                      precision mediump float;
  
                      uniform mat4 modelMatrix;
                      uniform mat4 viewMatrix;
                      uniform mat4 projectionMatrix;
                      uniform vec4 lightPosition;
  
                      attribute vec4 vertexPosition;  
                      attribute vec3 vertexNormal;
                      attribute vec2 vertexTexCoord;                              
  
                      varying vec3 fragmentNormal;
                      varying vec3 fragmentLight;
                      varying vec3 fragmentView;
                      varying vec4 fragmentPosition; 
                      varying vec2 fragmentTexCoord;                              
  
                      void main() {
                              mat4 modelViewMatrix = viewMatrix * modelMatrix;
  
                              vec4 p = modelViewMatrix * vertexPosition;
                              vec4 q = viewMatrix * lightPosition;                            
  
                              fragmentPosition    = vertexPosition; 
                              fragmentNormal      = normalize(mat3(modelViewMatrix) * vertexNormal);
                              fragmentLight       = normalize(vec3(q - p));
                              fragmentView        = normalize(vec3(-p));
                              fragmentTexCoord    = vertexTexCoord;               
  
                              gl_Position     = projectionMatrix * modelViewMatrix * vertexPosition;
                      }
              &lt;/script&gt;
              &lt;script id="lightingFragmentShader" type="x-shader/x-fragment"&gt;
                      precision mediump float;
  
                      varying vec3 fragmentNormal;
                      varying vec3 fragmentLight;
                      varying vec3 fragmentView;
                      varying vec4 fragmentPosition; 
                      varying vec2 fragmentTexCoord;
  
                      uniform sampler2D modelTexture;
                      uniform vec3 modelColor;
                      uniform vec3 lightColor;
  
                      void main() {
                              vec3 n = normalize(fragmentNormal);
                              vec3 l = normalize(fragmentLight);
                              vec3 v = normalize(fragmentView);
                              vec3 h = normalize(l + v);
                              vec4 modelColor          = texture2D(modelTexture, fragmentTexCoord);
  
                              float d = max(dot(l,n) , 0.0);
                              float s = pow(max(dot(h, n), 0.0), 10.0);
  
                              vec3 fragmentColor  = vec3(modelColor) * lightColor * d + lightColor * s;
  
                              gl_FragColor        = vec4(fragmentColor, 1.0); 
                      }
              &lt;/script&gt; 
              &lt;center&gt;
                  &lt;canvas id="webgl" width="500px" height="500px"&gt;
                      This content requires &lt;a href="http://get.webgl.org/"&gt;WebGL&lt;/a&gt;
                  &lt;/canvas&gt;
                  &lt;font face ="Arial"&gt;
                      &lt;br&gt;
                      Light Source Position
                      &lt;br&gt;
                      X-AXIS&lt;input id="x-light" type="range" min="-5.0" max="5.0" value="0" step="0.1" oninput="refresh()"&gt;
                      &lt;br&gt;
                      Y-AXIS &lt;input id="y-light" type="range" min="-5.0" max="5.0" value="0" step="0.1" oninput="refresh()"&gt;
                      &lt;br&gt;
                      Z-AXIS&lt;input id="z-light" type="range" min="-5.0" max="5.0" value="0" step="0.1" oninput="refresh()"&gt;
                  &lt;/font&gt;
              &lt;/center&gt;
          &lt;video id="video" src="Firefox.ogv" autoplay muted style="display: none;"&gt;
         Your browser doesn't appear to support the &lt;code&gt;&amp;lt;video&amp;gt;&lt;/code&gt; element.
           &lt;/video&gt;
      &lt;/body&gt;
  &lt;/html&gt;
  </code></pre>
  
  <p>JS:</p>
  
  <pre><code>var gl;
  var canvas;
  
  var dragging = false;
  var texShader;
  var chestModel;
  
  var xValue = 0;
  var yValue = 0;
  var zValue = 0;
  
  var modelRotationX = 0;
  var modelRotationY = 0;
  var lastClientX;
  var lastClientY;
  
  var videoElement;
  var modelTexture;
  var copyVideo;
  
  //refresh function used to request animation frame after moving slider in HTML
  function refresh(){
      xValue = document.getElementById("x-light").value;
      yValue = document.getElementById("y-light").value;
      zValue = document.getElementById("z-light").value;
      requestAnimationFrame(draw);
  }
  
  //define 'flatten' function to flatten tables to single array
  function flatten(a) {    
      return a.reduce(function (b, v) { b.push.apply(b, v); return b }, [])   
  }
  
  //create tumble interaction functions to click and drag cube
  function onmousedown(event){
      dragging    = true;
      lastClientX = event.clientX;
      lastClientY = event.clientY;
  }
  
  function onmouseup(event){ 
      dragging = false;
  }
  
  /*using clientX and clientY derived from click event, use to create modelX and Y 
  rotation before passing to model matrices rotation transformations*/
  function onmousemove(event){
      //console.log(event.clientX, event.clientY);
      if (dragging){  
          var dX = event.clientX - lastClientX;
          var dY = event.clientY - lastClientY;
  
          modelRotationY = modelRotationY + dX;
          modelRotationX = modelRotationX + dY;
  
  
          if (modelRotationX &gt; 90.0){
              modelRotationX = 90.0;
          }
  
          if (modelRotationX &lt; -90.0){
              modelRotationX = -90.0;
          }
  
      requestAnimationFrame(draw);
      }
       lastClientX = event.clientX;
       lastClientY = event.clientY;
  
  }
  function startVideo() {
    videoElement.play();
    intervalID = setInterval(draw, 15);
  }
  
  function videoDone() {
    clearInterval(intervalID);
  }
  
  
  //define Shader object constructor function
  function Shader(vertexId, fragmentId){
  
      this.program = createProgram(gl, document.getElementById( vertexId).text,
                                       document.getElementById(fragmentId).text);
  
      this.modelMatrixLocation         = gl.getUniformLocation(this.program, 'modelMatrix');
      this.viewMatrixLocation          = gl.getUniformLocation(this.program, 'viewMatrix');
      this.projectionMatrixLocation    = gl.getUniformLocation(this.program, 'projectionMatrix');
      this.vertexPositionLocation      = gl.getAttribLocation(this.program, 'vertexPosition'); 
      this.lightPositionLocation       = gl.getUniformLocation(this.program, 'lightPosition');
      this.modelColorLocation          = gl.getUniformLocation(this.program, 'modelColor');
      this.lightColorLocation          = gl.getUniformLocation(this.program, 'lightColor');
      this.vertexNormalLocation        = gl.getAttribLocation(this.program, 'vertexNormal');
      this.vertexTexCoordLocation      = gl.getAttribLocation(this.program, 'vertexTexCoord');
  
      gl.enableVertexAttribArray(this.vertexPositionLocation);
      gl.enableVertexAttribArray(this.vertexNormalLocation);
      gl.enableVertexAttribArray(this.vertexTexCoordLocation);
  }
  
  //define use() method for Shader objects
  Shader.prototype.use = function(projectionMatrix, modelMatrix, viewMatrix){
  
      gl.useProgram(this.program);
  
      gl.uniformMatrix4fv(this.modelMatrixLocation, false, modelMatrix.elements);
      gl.uniformMatrix4fv(this.viewMatrixLocation, false, viewMatrix.elements);
      gl.uniformMatrix4fv(this.projectionMatrixLocation, false, projectionMatrix.elements);
  
      gl.uniform4f(this.lightPositionLocation, xValue, yValue, zValue, 0.0);
      gl.uniform3f(this.modelColorLocation, 0.6, 0.3, 0.2);
      gl.uniform3f(this.lightColorLocation, 1.0, 1.0, 1.0);
  }
  
  //define Model object constructor function
  function Model(positions, triangles, normals, texCoords){
      //initialize buffer objects
      this.positionBuffer  = gl.createBuffer();
      this.triangleBuffer  = gl.createBuffer();
      this.normalsBuffer   = gl.createBuffer();
      this.texCoordBuffer  = gl.createBuffer();
  
  
      //copy vertex data from array in CPU onto GPU
      this.positionArray = new Float32Array(flatten(positions));
      gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, this.positionArray, gl.STATIC_DRAW);    
  
      //copy triangle data from array in CPU onto GPU
      this.triangleArray = new Uint16Array(flatten(triangles));
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.triangleBuffer);
      gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.triangleArray, gl.STATIC_DRAW);
  
      this.normalsArray = new Float32Array(flatten(normals));
      gl.bindBuffer(gl.ARRAY_BUFFER, this.normalsBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, this.normalsArray, gl.STATIC_DRAW);
  
      this.textCoordArray = new Float32Array(flatten(texCoords));
      gl.bindBuffer(gl.ARRAY_BUFFER, this.texCoordBuffer);
      gl.bufferData(gl.ARRAY_BUFFER, this.textCoordArray, gl.STATIC_DRAW);
  }
  
  //define draw() method for Model objects to bind barray buffers
  Model.prototype.draw = function(shader){
  
      gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);
      gl.vertexAttribPointer(shader.vertexPositionLocation, 3, gl.FLOAT, false, 0, 0);
  
      gl.bindBuffer(gl.ARRAY_BUFFER, this.normalsBuffer);
      gl.vertexAttribPointer(shader.vertexNormalLocation, 3, gl.FLOAT, false, 0, 0);
  
      gl.bindBuffer(gl.ARRAY_BUFFER, this.texCoordBuffer);    
      gl.vertexAttribPointer(shader.vertexTexCoordLocation, 2, gl.FLOAT, false, 0, 0);
  
  
      gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.triangleBuffer);
      gl.drawElements(gl.TRIANGLES, this.triangleArray.length, gl.UNSIGNED_SHORT, 0);
  
  
  }
  
  //initizlize texture object
  function loadTexture(image, texture){
    gl.bindTexture(gl.TEXTURE_2D, texture);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
      //requestAnimationFrame(draw);                                                        
  }
  
  
  function init(){
  
      //initialize GL context
      canvas = document.getElementById('webgl');
      gl = getWebGLContext(canvas, false);
  
      canvas.onmousedown  = onmousedown;
      canvas.onmouseup    = onmouseup;
      canvas.onmousemove  = onmousemove;
  
      //instantiate shader objects for each defined shader
      texShader           = new Shader('vertexShader', 'lightingFragmentShader');
  
      //instantiate model objects for each model
      chestModel          = new Model(chest.positions, chest.triangles, chest.normals, chest.texCoords);
  
      videoElement = document.getElementById("video");
  
      modelTexture    = gl.createTexture();
  
      gl.bindTexture(gl.TEXTURE_2D, modelTexture);
      gl.texImage2D(
          gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
          new Uint8Array([255, 255, 255, 255]));
  
  
      videoElement.addEventListener("canplaythrough", startVideo, true);
      videoElement.addEventListener("playing", function (){ copyVideo = true; }, true);
      videoElement.addEventListener("ended", videoDone, true);
  
     /* videoElement.onload   = function() {
         loadTexture(videoElement, modelTexture);
      }*/ 
      loadTexture(videoElement, modelTexture);
  
      videoElement.crossOrigin  = "anonymous";
      videoElement.src = "Firefox.ogv";
  
  
      gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);                               
      gl.enable(gl.DEPTH_TEST);
  
      //request animation frame
      requestAnimationFrame(draw);    
  
  }
  
  
  function draw(){
       if (copyVideo) {
         updateTexture();
      }
      //compose matrices for transformations
      var viewMatrix          = new Matrix4();
      var projectionMatrix    = new Matrix4();  
  
      viewMatrix.translate(0.0, 0.0, -1.8);
      projectionMatrix.perspective(90, 1, 1, 10);
  
      //set color and refresh rendering for canvas       
      gl.clearColor(0.5, 0.5, 0.5, 1.0);
      gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
  
      /*instantiate model matrices for each respective model 
        and draw models with applied shader*/
      var chestModelMatrix    = new Matrix4();
      chestModelMatrix.rotate(modelRotationX, 1, 0, 0 );
      chestModelMatrix.rotate(modelRotationY, 0, 1, 0 ); 
      chestModelMatrix.translate(0.0, 0.0, 0.0, 0.0 );
  
      //set uniform locations and apply shader to designated model
      texShader.use(projectionMatrix, chestModelMatrix, viewMatrix);    
      chestModel.draw(texShader);
  
  }
  
  function updateTexture() {
    gl.bindTexture(gl.TEXTURE_2D, modelTexture);
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, videoElement);
  }
  </code></pre>