renderStereo method

void renderStereo(
  1. Canvas canvas,
  2. Size fullSize
)

Renders stereo: left eye then right eye, side by side. Renders offline, then applies FFR/FSR scaling, chromatic aberration, and ATW warping. Reuses cached image buffers if useATWFallback is true.

Implementation

void renderStereo(Canvas canvas, Size fullSize) {
  final halfWidth = fullSize.width / 2;
  final eyeSize = Size(halfWidth, fullSize.height);
  final aspect = halfWidth / fullSize.height;

  final Image leftImg;
  final Image rightImg;

  if (useATWFallback && _lastLeftImage != null && _lastRightImage != null) {
    // Re-use last frame's successfully rendered images
    leftImg = _lastLeftImage!;
    rightImg = _lastRightImage!;
  } else {
    // Render new images and update cache
    final newLeft = _renderEyeToImage(eyeSize, cameraRig.leftViewProjection(aspect));
    final newRight = _renderEyeToImage(eyeSize, cameraRig.rightViewProjection(aspect));

    _lastLeftImage?.dispose();
    _lastRightImage?.dispose();

    _lastLeftImage = newLeft;
    _lastRightImage = newRight;

    leftImg = newLeft;
    rightImg = newRight;
  }

  // Left eye (offline warp)
  canvas.save();
  canvas.clipRect(Rect.fromLTWH(0, 0, halfWidth, fullSize.height));
  _leftDistortionMesh.drawDistortedImage(
    canvas,
    leftImg,
    eyeSize,
    atwTransform: leftAtwMatrix,
    enableChromaticAberration: enableChromaticAberration,
  );
  canvas.restore();

  // Right eye (offline warp)
  canvas.save();
  canvas.clipRect(Rect.fromLTWH(halfWidth, 0, halfWidth, fullSize.height));
  canvas.translate(halfWidth, 0);
  _rightDistortionMesh.drawDistortedImage(
    canvas,
    rightImg,
    eyeSize,
    atwTransform: rightAtwMatrix,
    enableChromaticAberration: enableChromaticAberration,
  );
  canvas.restore();

  // Clear fallback flag after frame completion
  useATWFallback = false;

  // Divider
  canvas.drawRect(
    Rect.fromLTWH(halfWidth - 2, 0, 4, fullSize.height),
    Paint()..color = const Color(0xFF000000),
  );
}