tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

SampledAPZCState.cpp (5041B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "SampledAPZCState.h"
      8 #include "APZUtils.h"
      9 
     10 namespace mozilla {
     11 namespace layers {
     12 
     13 SampledAPZCState::SampledAPZCState() {}
     14 
     15 SampledAPZCState::SampledAPZCState(const FrameMetrics& aMetrics)
     16    : mLayoutViewport(aMetrics.GetLayoutViewport()),
     17      mVisualScrollOffset(aMetrics.GetVisualScrollOffset()),
     18      mZoom(aMetrics.GetZoom()) {
     19  RemoveFractionalAsyncDelta();
     20 }
     21 
     22 SampledAPZCState::SampledAPZCState(
     23    const FrameMetrics& aMetrics, Maybe<CompositionPayload>&& aPayload,
     24    APZScrollGeneration aGeneration,
     25    std::vector<CompositorScrollUpdate>&& aUpdates)
     26    : mLayoutViewport(aMetrics.GetLayoutViewport()),
     27      mVisualScrollOffset(aMetrics.GetVisualScrollOffset()),
     28      mZoom(aMetrics.GetZoom()),
     29      mScrollPayload(std::move(aPayload)),
     30      mGeneration(aGeneration),
     31      mUpdates(std::move(aUpdates)) {
     32  RemoveFractionalAsyncDelta();
     33 }
     34 
     35 bool SampledAPZCState::operator==(const SampledAPZCState& aOther) const {
     36  // The payload doesn't factor into equality, that just comes along for
     37  // the ride.
     38  // The compositor scroll updates also do not factor into equality.
     39  // We can think of those as not describing the current state, but the
     40  // process by which we got from the previous state to this one.
     41  // The FrameMetrics constructor of SampledAPZCState does not initialize
     42  // mUpdates, so we can't rely on them always being present.
     43  return mLayoutViewport.IsEqualEdges(aOther.mLayoutViewport) &&
     44         mVisualScrollOffset == aOther.mVisualScrollOffset &&
     45         mZoom == aOther.mZoom;
     46 }
     47 
     48 bool SampledAPZCState::operator!=(const SampledAPZCState& aOther) const {
     49  return !(*this == aOther);
     50 }
     51 
     52 Maybe<CompositionPayload> SampledAPZCState::TakeScrollPayload() {
     53  return std::move(mScrollPayload);
     54 }
     55 
     56 void SampledAPZCState::UpdateScrollProperties(const FrameMetrics& aMetrics) {
     57  mLayoutViewport = aMetrics.GetLayoutViewport();
     58  mVisualScrollOffset = aMetrics.GetVisualScrollOffset();
     59 }
     60 
     61 void SampledAPZCState::UpdateScrollPropertiesWithRelativeDelta(
     62    const FrameMetrics& aMetrics, const CSSPoint& aRelativeDelta) {
     63  mVisualScrollOffset += aRelativeDelta;
     64  KeepLayoutViewportEnclosingVisualViewport(aMetrics);
     65 }
     66 
     67 void SampledAPZCState::UpdateZoomProperties(const FrameMetrics& aMetrics) {
     68  mZoom = aMetrics.GetZoom();
     69 }
     70 
     71 void SampledAPZCState::ClampVisualScrollOffset(const FrameMetrics& aMetrics) {
     72  // Make sure that we use the local mZoom to do these calculations, because the
     73  // one on aMetrics might be newer.
     74  CSSRect scrollRange = FrameMetrics::CalculateScrollRange(
     75      aMetrics.GetScrollableRect(), aMetrics.GetCompositionBounds(), mZoom);
     76  mVisualScrollOffset = scrollRange.ClampPoint(mVisualScrollOffset);
     77 
     78  KeepLayoutViewportEnclosingVisualViewport(aMetrics);
     79 }
     80 
     81 void SampledAPZCState::ZoomBy(float aScale) { mZoom.scale *= aScale; }
     82 
     83 void SampledAPZCState::RemoveFractionalAsyncDelta() {
     84  // This function is a performance hack. With non-WebRender, having small
     85  // fractional deltas between the layout offset and scroll offset on
     86  // container layers can trigger the creation of a temporary surface during
     87  // composition, because it produces a non-integer translation that doesn't
     88  // play well with layer clips. So we detect the case where the delta is
     89  // uselessly small (0.01 parentlayer pixels or less) and tweak the sampled
     90  // scroll offset to eliminate it. By doing this here at sample time rather
     91  // than elsewhere in the pipeline we are least likely to break assumptions
     92  // and invariants elsewhere in the code, since sampling effectively takes
     93  // a snapshot of APZ state (decoupling it from APZ assumptions) and provides
     94  // it as an input to the compositor (so all compositor state should be
     95  // internally consistent based on this input).
     96  // TODO(bug 1889267): Now that we use WebRender everywhere, can this hack be
     97  // removed?
     98  if (mLayoutViewport.TopLeft() == mVisualScrollOffset) {
     99    return;
    100  }
    101  const ParentLayerCoord EPSILON = 0.01;
    102  ParentLayerPoint paintedOffset = mLayoutViewport.TopLeft() * mZoom;
    103  ParentLayerPoint asyncOffset = mVisualScrollOffset * mZoom;
    104  if (FuzzyEqualsAdditive(paintedOffset.x, asyncOffset.x, EPSILON) &&
    105      FuzzyEqualsAdditive(paintedOffset.y, asyncOffset.y, EPSILON)) {
    106    mVisualScrollOffset = mLayoutViewport.TopLeft();
    107  }
    108 }
    109 
    110 void SampledAPZCState::KeepLayoutViewportEnclosingVisualViewport(
    111    const FrameMetrics& aMetrics) {
    112  FrameMetrics::KeepLayoutViewportEnclosingVisualViewport(
    113      CSSRect(mVisualScrollOffset,
    114              FrameMetrics::CalculateCompositedSizeInCssPixels(
    115                  aMetrics.GetCompositionBounds(), mZoom)),
    116      aMetrics.GetScrollableRect(), mLayoutViewport);
    117 }
    118 
    119 }  // namespace layers
    120 }  // namespace mozilla