You could use a 2D canvas as the on-screen canvas, and draw the WebGL canvas to it when updating the WebGL canvas before drawing whatever annotations on.
drawWebGLStuff(webGLCtx);
// Copy image data of WebGL canvas to 2D canvas.
// This should be done right after WebGL rendering,
// unless preserveDrawingBuffer: true is passed during WebGL context creation,
// since WebGL will swap buffers by default, leaving no image in the drawing buffer,
// which is what we want to copy.
ctx2D.drawImage(webGLCanvas, 0, 0);
drawAnnotations(ctx2D);
(The annotations could be rendered each frame from a list of shapes or drawn to another offscreen canvas, which is then drawn to the main (on-screen) canvas similar to the WebGL canvas.)
Or you can simply layer the canvases on the page with absolute positioning and z-index
:
<div style="position: relative;">
<canvas id="layer1" width="100" height="100"
style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
<canvas id="layer2" width="100" height="100"
style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>