title: CanvasRenderingContext2D.drawImage() slow when using a large WebGL canvas as source
body: <p>Why is <a href="https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage" rel="nofollow noreferrer"><code>drawImage</code></a> slow when using a large WebGL canvas as a source ?</p>
  <p>This question stems from the following observation. If you paste this function to your browser's console:</p>
  <pre class="lang-js prettyprint-override"><code>function test(sourceCanvasWidth, sourceCanvasHeight, sourceContextType, delay) {
    const srcCanvas = document.createElement('canvas');
    const srcCtx = srcCanvas.getContext(sourceContextType);
    srcCanvas.width = sourceCanvasWidth;
    srcCanvas.height = sourceCanvasHeight;
  
    const dstCanvas = document.createElement('canvas');
    const dstCtx = dstCanvas.getContext('2d');
    dstCanvas.width = 1024;
    dstCanvas.height = 1024;
  
    let start;
    let count = 0;
    function loop(timestamp) {
      count++;
      if (start === undefined) {
        start = timestamp;
      }
      dstCtx.drawImage(srcCanvas, 0, 0, 1024, 1024, 0, 0, 1024, 1024);
      // Stop after delay seconds
      if (timestamp - start &lt; delay * 1000) {
        setTimeout(() =&gt; loop(Date.now()), 0);
      } else {
        console.log(`${count} loops (${count / 10} per seconds)`);
      }
    }
  
    setTimeout(() =&gt; loop(Date.now()), 0);
  }
  </code></pre>
  <p>And then call it with different canvas sizes:</p>
  <pre class="lang-js prettyprint-override"><code>test(1024, 1024, 'webgl', 10)
  942 loops (94.2 per seconds)
  test(4096, 4096, 'webgl', 10)
  182 loops (18.2 per seconds)
  </code></pre>
  <p>You can see that performances significantly drop when using a large source canvas (Firefox 98 Linux). It is to be noted that if you use a <code>2d</code> context as a source, there is no drop:</p>
  <pre class="lang-js prettyprint-override"><code>test(1024, 1024, '2d', 10)
  1868 loops (186.8 per seconds)
  test(4096, 4096, '2d', 10)
  1825 loops (182.5 per seconds)
  </code></pre>
  <p>What the test function does is benchmark a configuration of canvas. I have a source canvas on which I can configure the size, the context type ('2d', 'webgl', 'webgl2') and a delay. I will then repeatedly draw the source canvas on the destination canvas which always have the same size (1024x1024). Note that <code>drawImage</code> always draws a 1024x1024 zone. The source canvas size does not change anything to <code>drawImage</code> parameters.</p>
  <p>The drop is dependent on the browser. On Chromium (98 Linux) it is not so significant. But raise the resolution to 8192x8192 and you will see it. That's why we can't dismiss it as a Firefox bug because it happens in both browsers but at a different degree.</p>
  <p>All in all, I see no justification of this drop specifically for WebGL canvas. In particular, <a href="https://bugs.chromium.org/p/chromium/issues/detail?id=170021" rel="nofollow noreferrer">it seems that browser will have their canvas in GPU memory above a certain size</a> anyway. If someone could enlighten me.</p>