'loadTexture' is the wrong function to use! It will allocate a whole new texture every call which will kill performance and leak memory.
Call glw.createEmptyTexture(w, h, linearsampling) to create an empty texture, and update its contents with glw.videoToTexture(canvas, texture). Despite the name it can also copy a canvas to a texture. This may still be a bottleneck; on some system's WebGL implementations it could do a slow CPU-readback-and-upload, but efficient implementations should be able to do a GPU copy. If it turns out it's still slow, consider just having a separate canvas underlay as you already considered.
In canvas2d mode you should just be able to drawImage() the canvas directly.