Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at */
#include <iosfwd>
#include <stdint.h> // for uint8_t, uint32_t, uint64_t
#include "FrameMetrics.h" // for FrameMetrics
#include "mozilla/DefineEnum.h" // for MOZ_DEFINE_ENUM
#include "mozilla/gfx/BasePoint.h" // for BasePoint
#include "mozilla/gfx/Rect.h" // for RoundedIn
#include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor
#include "mozilla/ScrollSnapTargetId.h" // for ScrollSnapTargetIds
#include "mozilla/TimeStamp.h" // for TimeStamp
#include "Units.h" // for CSSRect, CSSPixel, etc
#include "UnitTransforms.h" // for ViewAs
namespace IPC {
template <typename T>
struct ParamTraits;
} // namespace IPC
namespace mozilla {
namespace layers {
struct RepaintRequest {
friend struct IPC::ParamTraits<mozilla::layers::RepaintRequest>;
// clang-format off
ScrollOffsetUpdateType, uint8_t, (
eNone, // The default; the scroll offset was not updated.
eUserAction, // The scroll offset was updated by APZ in response
// to user action.
eVisualUpdate // The scroll offset was updated by APZ in response
// to a visual scroll update request from the
// main thread.
// clang-format on
: mScrollId(ScrollableLayerGuid::NULL_SCROLL_ID),
mCompositionBounds(0, 0, 0, 0),
mScrollOffset(0, 0),
mDisplayPortMargins(0, 0, 0, 0),
mLayoutViewport(0, 0, 0, 0),
mIsInScrollingGesture(false) {}
RepaintRequest(const FrameMetrics& aOther,
const ScreenMargin& aDisplayportMargins,
const ScrollOffsetUpdateType aScrollUpdateType,
APZScrollAnimationType aScrollAnimationType,
const APZScrollGeneration& aScrollGenerationOnApz,
const ScrollSnapTargetIds& aLastSnapTargetIds,
bool aIsInScrollingGesture)
: mScrollId(aOther.GetScrollId()),
mIsInScrollingGesture(aIsInScrollingGesture) {}
// Default copy ctor and operator= are fine
bool operator==(const RepaintRequest& aOther) const {
// Put mScrollId at the top since it's the most likely one to fail.
return mScrollId == aOther.mScrollId &&
mPresShellResolution == aOther.mPresShellResolution &&
mCompositionBounds.IsEqualEdges(aOther.mCompositionBounds) &&
mCumulativeResolution == aOther.mCumulativeResolution &&
mDevPixelsPerCSSPixel == aOther.mDevPixelsPerCSSPixel &&
mScrollOffset == aOther.mScrollOffset &&
// don't compare mZoom
mScrollGeneration == aOther.mScrollGeneration &&
mDisplayPortMargins == aOther.mDisplayPortMargins &&
mPresShellId == aOther.mPresShellId &&
mLayoutViewport.IsEqualEdges(aOther.mLayoutViewport) &&
mTransformToAncestorScale == aOther.mTransformToAncestorScale &&
mPaintRequestTime == aOther.mPaintRequestTime &&
mScrollUpdateType == aOther.mScrollUpdateType &&
mScrollAnimationType == aOther.mScrollAnimationType &&
mLastSnapTargetIds == aOther.mLastSnapTargetIds &&
mIsRootContent == aOther.mIsRootContent &&
mIsScrollInfoLayer == aOther.mIsScrollInfoLayer &&
mIsInScrollingGesture == aOther.mIsInScrollingGesture;
bool operator!=(const RepaintRequest& aOther) const {
return !operator==(aOther);
friend std::ostream& operator<<(std::ostream& aOut,
const RepaintRequest& aRequest);
CSSToScreenScale2D DisplayportPixelsPerCSSPixel() const {
// Refer to FrameMetrics::DisplayportPixelsPerCSSPixel() for explanation.
return mZoom * mTransformToAncestorScale;
CSSToLayerScale LayersPixelsPerCSSPixel() const {
return mDevPixelsPerCSSPixel * mCumulativeResolution;
// Get the amount by which this frame has been zoomed since the last repaint.
LayerToParentLayerScale GetAsyncZoom() const {
return mZoom / LayersPixelsPerCSSPixel();
CSSSize CalculateCompositedSizeInCssPixels() const {
if (GetZoom() == CSSToParentLayerScale(0)) {
return CSSSize(); // avoid division by zero
return mCompositionBounds.Size() / GetZoom();
float GetPresShellResolution() const { return mPresShellResolution; }
const ParentLayerRect& GetCompositionBounds() const {
return mCompositionBounds;
const LayoutDeviceToLayerScale& GetCumulativeResolution() const {
return mCumulativeResolution;
const CSSToLayoutDeviceScale& GetDevPixelsPerCSSPixel() const {
return mDevPixelsPerCSSPixel;
bool IsAnimationInProgress() const {
return mScrollAnimationType != APZScrollAnimationType::No;
bool IsRootContent() const { return mIsRootContent; }
CSSPoint GetLayoutScrollOffset() const { return mLayoutViewport.TopLeft(); }
const CSSPoint& GetVisualScrollOffset() const { return mScrollOffset; }
const CSSToParentLayerScale& GetZoom() const { return mZoom; }
ScrollOffsetUpdateType GetScrollUpdateType() const {
return mScrollUpdateType;
bool GetScrollOffsetUpdated() const { return mScrollUpdateType != eNone; }
MainThreadScrollGeneration GetScrollGeneration() const {
return mScrollGeneration;
APZScrollGeneration GetScrollGenerationOnApz() const {
return mScrollGenerationOnApz;
ScrollableLayerGuid::ViewID GetScrollId() const { return mScrollId; }
const ScreenMargin& GetDisplayPortMargins() const {
return mDisplayPortMargins;
uint32_t GetPresShellId() const { return mPresShellId; }
const CSSRect& GetLayoutViewport() const { return mLayoutViewport; }
const ParentLayerToScreenScale2D& GetTransformToAncestorScale() const {
return mTransformToAncestorScale;
const TimeStamp& GetPaintRequestTime() const { return mPaintRequestTime; }
bool IsScrollInfoLayer() const { return mIsScrollInfoLayer; }
bool IsInScrollingGesture() const { return mIsInScrollingGesture; }
APZScrollAnimationType GetScrollAnimationType() const {
return mScrollAnimationType;
const ScrollSnapTargetIds& GetLastSnapTargetIds() const {
return mLastSnapTargetIds;
void SetIsRootContent(bool aIsRootContent) {
mIsRootContent = aIsRootContent;
void SetIsScrollInfoLayer(bool aIsScrollInfoLayer) {
mIsScrollInfoLayer = aIsScrollInfoLayer;
void SetIsInScrollingGesture(bool aIsInScrollingGesture) {
mIsInScrollingGesture = aIsInScrollingGesture;
// A ID assigned to each scrollable frame, unique within each LayersId..
ScrollableLayerGuid::ViewID mScrollId;
// The pres-shell resolution that has been induced on the document containing
// this scroll frame as a result of zooming this scroll frame (whether via
// user action, or choosing an initial zoom level on page load). This can
// only be different from 1.0 for frames that are zoomable, which currently
// is just the root content document's root scroll frame
// (mIsRootContent = true).
// This is a plain float rather than a ScaleFactor because in and of itself
// it does not convert between any coordinate spaces for which we have names.
float mPresShellResolution;
// This is the area within the widget that we're compositing to. It is in the
// layer coordinates of the scrollable content's parent layer.
// The size of the composition bounds corresponds to the size of the scroll
// frame's scroll port (but in a coordinate system where the size does not
// change during zooming).
// The origin of the composition bounds is relative to the layer tree origin.
// Unlike the scroll port's origin, it does not change during scrolling of
// the scrollable layer to which it is associated. However, it may change due
// to scrolling of ancestor layers.
// This value is provided by Gecko at layout/paint time.
ParentLayerRect mCompositionBounds;
// See FrameMetrics::mCumulativeResolution for description.
LayoutDeviceToLayerScale mCumulativeResolution;
// The conversion factor between CSS pixels and device pixels for this frame.
// This can vary based on a variety of things, such as reflowing-zoom.
CSSToLayoutDeviceScale mDevPixelsPerCSSPixel;
// The position of the top-left of the scroll frame's scroll port, relative
// to the scrollable content's origin.
CSSPoint mScrollOffset;
// The "user zoom". Content is painted by gecko at mCumulativeResolution *
// mDevPixelsPerCSSPixel, but will be drawn to the screen at mZoom. In the
// steady state, the two will be the same, but during an async zoom action the
// two may diverge. This information is initialized in Gecko but updated in
// the APZC.
CSSToParentLayerScale mZoom;
// The scroll generation counter used to acknowledge the scroll offset update
// on the main-thread.
MainThreadScrollGeneration mScrollGeneration;
// The scroll generation counter stored in each SampledAPZState and the
// scrollable frame on the main-thread and used to compare with each other
// in the WebRender renderer thread to tell which sampled scroll offset
// matches the scroll offset used on the main-thread.
APZScrollGeneration mScrollGenerationOnApz;
// A display port expressed as layer margins that apply to the rect of what
// is drawn of the scrollable element.
ScreenMargin mDisplayPortMargins;
uint32_t mPresShellId;
// For a root scroll frame (RSF), the document's layout viewport
// (sometimes called "CSS viewport" in older code).
// Its size is the dimensions we're using to constrain the <html> element
// of the document (i.e. the initial containing block (ICB) size).
// Its origin is the RSF's layout scroll position, i.e. the scroll position
// exposed to web content via window.scrollX/Y.
// Note that only the root content document's RSF has a layout viewport
// that's distinct from the visual viewport. For an iframe RSF, the two
// are the same.
// For a scroll frame that is not an RSF, this metric is meaningless and
// invalid.
CSSRect mLayoutViewport;
// See FrameMetrics::mTransformToAncestorScale for description.
ParentLayerToScreenScale2D mTransformToAncestorScale;
// The time at which the APZC last requested a repaint for this scroll frame.
TimeStamp mPaintRequestTime;
// The type of repaint request this represents.
ScrollOffsetUpdateType mScrollUpdateType;
APZScrollAnimationType mScrollAnimationType;
ScrollSnapTargetIds mLastSnapTargetIds;
// Whether or not this is the root scroll frame for the root content document.
bool mIsRootContent : 1;
// True if this scroll frame is a scroll info layer. A scroll info layer is
// not layerized and its content cannot be truly async-scrolled, but its
// metrics are still sent to and updated by the compositor, with the updates
// being reflected on the next paint rather than the next composite.
bool mIsScrollInfoLayer : 1;
// Whether the APZC is in the middle of processing a gesture.
bool mIsInScrollingGesture : 1;
} // namespace layers
} // namespace mozilla