Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

168
Views
Use GPU to draw on HTML5 Canvas on Google Chrome

I'm using a canvas to draw a marker (in SVG) hundreds (sometimes thousands) of times. The size of the canvas is 300x300 pixels and the SVG is 18x25 pixels.

The code is quite straigth forward, I have a for loop where I draw the markers on the canvas:

   drawNewTile = (canvas, points) => {
        const drawn = {};
        const context = canvas.getContext('2d');
        if (points.length === 0) return;
        for (let i = points.length; i -= 1;) {
            const [x, y] = points[i];
            if (!drawn[`${x}:${y}`]) {
                drawn[`${x}:${y}`] = true;
                this.drawMarker(context, x, y);
            }
        }
    };

    drawMarker = (context, x, y) => {
        const x_ = Math.floor(x - this.MARKER_WIDTH / 2 + this.MAX_DIMENSION_OF_MARKER);
        const y_ = Math.floor(y - this.MARKER_HEIGHT + this.MAX_DIMENSION_OF_MARKER);
        context.drawImage(this.marker, x_, y_, this.MARKER_WIDTH, this.MARKER_HEIGHT);
    }; 

I have already put in place some optimizations: like the for loop, only draw those points which are not already drawn, use integer coordinates, etc.

After that, I have some good results, but my page it gets a little bit stuck on Google Chrome. Nonetheless, to my surprise, in Firefox it goes fast as hell, like, really really fast. So I made some digging with the performance tab of Google Chrome and I found that my code was using a lot of CPU and that's slow.

I also found this article where it says that Chrome uses some heuristics to determine if it uses a CPU or a GPU to draw the canvas.

So, my question is, how do I force the use of GPU on Chrome? Is there any flag I can set or something similar? Do you any other way to speed that the drawing process?

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

The problem is that apparently Chrome keeps SVG images in the CPU, and rasterizes it at every new call to drawImage().

Simply rasterizing it yourself will make Chrome's performances grow instantly.

To do that, use the createImageBitmap() method, which will create an ImageBitmap that the browser will be able to store directly in the GPU's memory.
Safari just did expose this method in the newest version of their browser, so you may still want to use a polyfill for it. While in this case, simply drawing on a canvas would be enough, I made such a polyfill which does include a few features that most browsers don't support yet.

(async () => {
  const canvas = document.querySelector("canvas");
  const ctx = canvas.getContext("2d");
  const select = document.querySelector("select");
  const html_img = new Image();
  const svg_str = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 18 25" width="18" height="25">
    <circle cx="9" cy="9" r="6"/>
  </svg>`;
  const svg_blob = new Blob([svg_str], {
    type: "image/svg+xml"
  });

  ctx.font = "20px sans-serif";
  ctx.fillStyle = "red";

  html_img.src = URL.createObjectURL(svg_blob);
  const sources = {
    html_img,
    bitmap: await createImageBitmap(svg_blob)
  };
  const times = [];
  await html_img.decode();

  anim();

  function anim() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    for (let y = 0; y < canvas.width; y += 10) {
      for (let x = 0; x < canvas.width; x += 5) {
        ctx.drawImage(sources[select.value], x, y);
      }
    }
    requestAnimationFrame(anim);

    // ultra rough FPS counter
    const now = performance.now();
    while (times.length > 0 && times[0] <= now - 1000) {
      times.shift();
    }
    times.push(now);
    fps = times.length;
    ctx.fillText(fps + "FPS", 30, 30);
  }
})();
<!-- createImageBitmap polyfill for old browsers --> <script src="https://cdn.jsdelivr.net/gh/Kaiido/createImageBitmap/dist/createImageBitmap.js"></script>
source: <select>
  <option value="bitmap">ImageBitmap</option>
  <option value="html_img">HTMLImage</option>
</select><br>
<canvas width="300" height="300"></canvas>

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!