I think you do a lot of calculations and drawings for something that could have been much easier.
In other words, this is not Firefox, which is slow ... it is just that Chrome quickly flashes: -D
An alternative approach may be, for example, the presence of a partially transparent image displayed by the browser on top of the canvas, and then drawing operations are performed on the canvas directly without special masking.
What this can allow is to see a picture through a mask without performing complex clipping manipulations.
These operations can be performed in reality on one canvas only when the user asks to export the image as png, if that is what you need to provide.
To see an example of this approach in action, check this out.
the source code is in lisp, but it should not be read too hard (full program - only 116 lines)
source share