I realize that was probably a bit too open-ended a question. Having done some more reading around of the Angle docs and code, I think the parts I'm really more interested in understanding are elsewhere in Chromium - specifically the WebGL -> Open GL ES mapping and the command buffer encoding / decoding.
Are there any high-level overview docs for the whole Chromium WebGL stack that someone can point me towards?
Feel free to stop reading here, but I also thought I'd provide a bit more background on my previous proof-of-concept. I've put a video
here showing a demo, which demonstrates
this three.js example.
The video shows an iOS WKWebView semi-transparent on top of a native OpenGL ES 2.0 view. The camera frame is from ARKit, so is pretty high-res and 60 FPS - rendered directly in the native context with YUV conversion in a shader.
When ARKit reports a new pose for the anchor, we send a message across to the webview, which does whatever rendering it wants into a webgl canvas as normal, but with the webgl context wrapped into a "SerializingWebGLContext".
Most webgl calls through that class are just encoded into an ArrayBuffer with a simple JS binary serializer. There's still a real underlying WebGL context too, so any creation commands can generate real WebGL objects but we add a property into the objects with a unique integer ID that we use when we need to serialize calls referencing those objects. The underlying context also allows an easy passthrough mode for debugging. Shader compilation and linking always go through the underlying context as well as being serialized, and before serialising the linkProgram call we get the locations for all the active attributes and serialize fake bindAttribLocation calls for all of them to ensure consistency between the WebGL and native contexts.
The native side then deserializes the calls and plays them back on a native OpenGL ES 2.0 context. The native deserialiser also handles the required webgl -> Open GL ES mapping (eg it tracks UNPACK_FLIP_Y_WEBGL state and flips data before calling texImage2D, etc).
There are a couple of more straightforward approaches I considered to achieve something similar:
1) Just render the camera frame in the native context, and the content in a normal webgl canvas with a transparent background in the webview. The downside is there's no control over exactly when the webgl content will appear on screen, so the content and camera are likely to be updated out of sync and the content won't look correctly anchored on the camera frame.
2) Pass across the raw camera data from native to a webview, and just texImage2d in webgl and do all the rendering in the webview, no need for compositing. Pretty simple to implement and gives a lot of flexibility for the webpage to process / render the camera frames as it wants, but adds quite a bit of overhead. It was feasible on iOS with the WKWebView API but I found the android webview APIs for passing binary data from native -> webview had too much overhead (see
Chromium Bug 1023334 where I was being somewhat more secretive on my true intentions to use this for camera textures...).
So the "serialize and playback webgl" approach was my favourite but never went beyond the PoC. Now I'm investigating officially adding support for web content with our Zapbox VR/MR product, this is again likely the best solution to give the lowest overhead and the best control over latency.
So to summarise the stack is:
1. Intercept and serialize webgl to a binary command buffer of some sort. I assume we'll need to write / maintain this bit.
2. Map webgl command stream to ES 2/3 command stream. Perhaps something in ANGLE/Chromium that can help here?
3. Native ES 2/3 context to render the content. I know ANGLE can help here for platforms without native ES2/3 backends and I'm also intending to try the iOS metal backend.
So before I dive into trying to bring my PoC implementation for 1. and 2. up to production quality and increase the API coverage I thought I'd see if anyone has ideas for leveraging anything in the chromium webgl stack that might help for those parts?
Thanks again!
Simon