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 channel
  • CM_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.