Frame Capturing
Internally Cohtml uses the Coherent Labs Renoir graphics library. Renoir has the capability of serializing the commands sent to it for a single frame to a binary blob and then replaying them at some later point. Everything needed to execute the commands is also serialized. This includes images, fonts, and path data. Using frame capture like these is a good way to debug Renoir should they be any problems with the rendering. The rendering team can use the captures and investigate any problems in the rendering pipeline.
Capturing Frames
The frame capturing happens through the use of the View API. Each view has the methods CaptureSingleDebugFrame
, BeginCaptureDebugFrame
, and EndCaptureDebugFrame
which control the frame capturing behavior.
Single Frames
Capturing a single frame happens through the CaptureSingleDebugFrame
method. Once capture is issued, the rendering commands for the next drawn frame will be serialized and a user-supplied callback will be called.
The following snippet illustrates a basic capturing:
auto saveCallback = [](void* userData, cohtml::FrameCapture* capture) {
// here you can save the captured frame
writeToDisk(capture->Data, capture->Size);
capture->Release();
};
void* userData; // optional user data pointer
cohtmlView->CaptureSingleDebugFrame(userData, saveCallback);
Continuous capturing
In certain situations capturing several consecutive frames may be preferable. This can be achieved through the BeginCaptureDebugFrame
and EndCaptureDebugFrame
methods. When the first one is called, Cohtml will begin capturing the rendering commands of each of the next frames. The captured data is again returned through a callback which will be called for every captured frame. The capturing will stop when EndCaptureDebugFrame
is called.
The following snippet illustrates the continuous capturing:
auto saveCallback = [](void* userData, cohtml::FrameCapture* capture) {
// here you can save the captured frame
writeToDisk(capture->Data, capture->Size);
capture->Release();
};
void* userData; // optional user data pointer
cohtmlView->BeginCaptureDebugFrame(userData, saveCallback);
...
cohtmlView->EndCaptureDebugFrame();
Capturing with obfuscation
As previously stated the captured frames contain everything needed to display that frame. This includes the image data that may be used for any of the images in the current document. If you are not ok with sending a captured frame back to Coherent Labs as the capture may contain IP-protected images, there is a way to capture the frame by telling Cohtml to obfuscate the image data. In this case, all of the serialized images will be replaced with solid colors and the capture will not contain the original image data. Currently, the obfuscation happens only for images. The used fonts and paths (which can be used in SVGs) are still being serialized unchanged.
The obfuscation behavior is controlled by an optional third argument of CaptureSingleDebugFrame
and BeginCaptureDebugFrame
. The argument has a type of the CaptureMode
enum and can be one of these values:
CM_PreserveAll
– Do not alter the serialization of the pixel data. This is the default.CM_PreserveAlpha
– Obfuscate only the color channels of the images but preserve the alpha channelCM_ObfuscateAll
– Obfuscate the color channels as well as the alpha channel of the images
Important note: Only images in the formats RGBA8, RGBA16F, RGBA32F, R8, R16, BC1, BC2, BC3, BC4, BC5, BC6, and BC7 are obfuscated. These formats should cover any PNG and JPEG images.
Capturing backend commands
Another way to capture what is being rendered by Cohtml is to serialize the backend commands for a given frame. This is similar to the frame capturing described above but the captured data is the backend commands that Renoir has generated and executed through the rendering backend. These capture present move opportunities for debugging and identifying problems with the libraries.
The backend commands capturing is done through a similar to the frame capturing API:
void View::BeginCaptureBackendDebugFrame(void* userData, FrameCaptureCallback callback);
void View::EndCaptureBackendDebugFrame();
void View::CaptureSingleBackendDebugFrame(void* userData, FrameCaptureCallback callback);
The usage is analogous to the one for frame capturing.