bool
SharedFrameMetricsHelper::UpdateFromCompositorFrameMetrics(
    ContainerLayer* aLayer,
    bool aHasPendingNewThebesContent,
    bool aLowPrecision,
    ParentLayerRect& aCompositionBounds,
    CSSToParentLayerScale& aZoom)
{
  MOZ_ASSERT(aLayer);

  CompositorChild* compositor = CompositorChild::Get();

  if (!compositor) {
    FindFallbackContentFrameMetrics(aLayer, aCompositionBounds, aZoom);
    return false;
  }

  const FrameMetrics& contentMetrics = aLayer->GetFrameMetrics();
  FrameMetrics compositorMetrics;

  if (!compositor->LookupCompositorFrameMetrics(contentMetrics.mScrollId,
                                                compositorMetrics)) {
    FindFallbackContentFrameMetrics(aLayer, aCompositionBounds, aZoom);
    return false;
  }

  aCompositionBounds = ParentLayerRect(compositorMetrics.mCompositionBounds);
  aZoom = compositorMetrics.GetZoomToParent();

  // Reset the checkerboard risk flag when switching to low precision
  // rendering.
  if (aLowPrecision && !mLastProgressiveUpdateWasLowPrecision) {
    // Skip low precision rendering until we're at risk of checkerboarding.
    if (!mProgressiveUpdateWasInDanger) {
      return true;
    }
    mProgressiveUpdateWasInDanger = false;
  }
  mLastProgressiveUpdateWasLowPrecision = aLowPrecision;

  // Always abort updates if the resolution has changed. There's no use
  // in drawing at the incorrect resolution.
  if (!FuzzyEquals(compositorMetrics.GetZoom().scale, contentMetrics.GetZoom().scale)) {
    return true;
  }

  // Never abort drawing if we can't be sure we've sent a more recent
  // display-port. If we abort updating when we shouldn't, we can end up
  // with blank regions on the screen and we open up the risk of entering
  // an endless updating cycle.
  if (fabsf(contentMetrics.GetScrollOffset().x - compositorMetrics.GetScrollOffset().x) <= 2 &&
      fabsf(contentMetrics.GetScrollOffset().y - compositorMetrics.GetScrollOffset().y) <= 2 &&
      fabsf(contentMetrics.mDisplayPort.x - compositorMetrics.mDisplayPort.x) <= 2 &&
      fabsf(contentMetrics.mDisplayPort.y - compositorMetrics.mDisplayPort.y) <= 2 &&
      fabsf(contentMetrics.mDisplayPort.width - compositorMetrics.mDisplayPort.width) <= 2 &&
      fabsf(contentMetrics.mDisplayPort.height - compositorMetrics.mDisplayPort.height)) {
    return false;
  }

  // When not a low precision pass and the page is in danger of checker boarding
  // abort update.
  if (!aLowPrecision && !mProgressiveUpdateWasInDanger) {
    if (AboutToCheckerboard(contentMetrics, compositorMetrics)) {
      mProgressiveUpdateWasInDanger = true;
      return true;
    }
  }

  // Abort drawing stale low-precision content if there's a more recent
  // display-port in the pipeline.
  if (aLowPrecision && !aHasPendingNewThebesContent) {
    return true;
  }

  return false;
}