Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : * This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef GFX_FRAMEMETRICS_H
7 : #define GFX_FRAMEMETRICS_H
8 :
9 : #include <stdint.h> // for uint32_t, uint64_t
10 : #include "Units.h" // for CSSRect, CSSPixel, etc
11 : #include "mozilla/DefineEnum.h" // for MOZ_DEFINE_ENUM
12 : #include "mozilla/HashFunctions.h" // for HashGeneric
13 : #include "mozilla/Maybe.h"
14 : #include "mozilla/gfx/BasePoint.h" // for BasePoint
15 : #include "mozilla/gfx/Rect.h" // for RoundedIn
16 : #include "mozilla/gfx/ScaleFactor.h" // for ScaleFactor
17 : #include "mozilla/gfx/Logging.h" // for Log
18 : #include "mozilla/StaticPtr.h" // for StaticAutoPtr
19 : #include "mozilla/TimeStamp.h" // for TimeStamp
20 : #include "nsString.h"
21 : #include "nsStyleCoord.h" // for nsStyleCoord
22 :
23 : namespace IPC {
24 : template <typename T> struct ParamTraits;
25 : } // namespace IPC
26 :
27 : namespace mozilla {
28 : namespace layers {
29 :
30 : /**
31 : * Helper struct to hold a couple of fields that can be updated as part of
32 : * an empty transaction.
33 : */
34 0 : struct ScrollUpdateInfo {
35 : uint32_t mScrollGeneration;
36 : CSSPoint mScrollOffset;
37 : };
38 :
39 : /**
40 : * The viewport and displayport metrics for the painted frame at the
41 : * time of a layer-tree transaction. These metrics are especially
42 : * useful for shadow layers, because the metrics values are updated
43 : * atomically with new pixels.
44 : */
45 96 : struct FrameMetrics {
46 : friend struct IPC::ParamTraits<mozilla::layers::FrameMetrics>;
47 : public:
48 : // We use IDs to identify frames across processes.
49 : typedef uint64_t ViewID;
50 : static const ViewID NULL_SCROLL_ID; // This container layer does not scroll.
51 : static const ViewID START_SCROLL_ID = 2; // This is the ID that scrolling subframes
52 : // will begin at.
53 :
54 : MOZ_DEFINE_ENUM_WITH_BASE_AT_CLASS_SCOPE(
55 : ScrollOffsetUpdateType, uint8_t, (
56 : eNone, // The default; the scroll offset was not updated
57 : eMainThread, // The scroll offset was updated by the main thread.
58 : ePending, // The scroll offset was updated on the main thread, but not
59 : // painted, so the layer texture data is still at the old
60 : // offset.
61 : eUserAction, // In an APZ repaint request, this means the APZ generated
62 : // the scroll position based on user action (the alternative
63 : // is eNone which means it's just request a repaint because
64 : // it got a scroll update from the main thread).
65 : eRestore // The scroll offset was updated by the main thread, but as
66 : // a restore from history or after a frame reconstruction.
67 : // In this case, APZ can ignore the offset change if the
68 : // user has done an APZ scroll already.
69 : ));
70 :
71 99 : FrameMetrics()
72 99 : : mScrollId(NULL_SCROLL_ID)
73 : , mPresShellResolution(1)
74 : , mCompositionBounds(0, 0, 0, 0)
75 : , mDisplayPort(0, 0, 0, 0)
76 : , mCriticalDisplayPort(0, 0, 0, 0)
77 : , mScrollableRect(0, 0, 0, 0)
78 : , mCumulativeResolution()
79 : , mDevPixelsPerCSSPixel(1)
80 : , mScrollOffset(0, 0)
81 : , mZoom()
82 : , mScrollGeneration(0)
83 : , mSmoothScrollOffset(0, 0)
84 : , mRootCompositionSize(0, 0)
85 : , mDisplayPortMargins(0, 0, 0, 0)
86 : , mPresShellId(-1)
87 : , mViewport(0, 0, 0, 0)
88 : , mExtraResolution()
89 : , mPaintRequestTime()
90 : , mScrollUpdateType(eNone)
91 : , mIsRootContent(false)
92 : , mDoSmoothScroll(false)
93 : , mUseDisplayPortMargins(false)
94 99 : , mIsScrollInfoLayer(false)
95 : {
96 99 : }
97 :
98 : // Default copy ctor and operator= are fine
99 :
100 98 : bool operator==(const FrameMetrics& aOther) const
101 : {
102 : // Put mScrollId at the top since it's the most likely one to fail.
103 162 : return mScrollId == aOther.mScrollId &&
104 128 : mPresShellResolution == aOther.mPresShellResolution &&
105 125 : mCompositionBounds.IsEqualEdges(aOther.mCompositionBounds) &&
106 122 : mDisplayPort.IsEqualEdges(aOther.mDisplayPort) &&
107 122 : mCriticalDisplayPort.IsEqualEdges(aOther.mCriticalDisplayPort) &&
108 122 : mScrollableRect.IsEqualEdges(aOther.mScrollableRect) &&
109 122 : mCumulativeResolution == aOther.mCumulativeResolution &&
110 122 : mDevPixelsPerCSSPixel == aOther.mDevPixelsPerCSSPixel &&
111 122 : mScrollOffset == aOther.mScrollOffset &&
112 : // don't compare mZoom
113 122 : mScrollGeneration == aOther.mScrollGeneration &&
114 122 : mSmoothScrollOffset == aOther.mSmoothScrollOffset &&
115 122 : mRootCompositionSize == aOther.mRootCompositionSize &&
116 119 : mDisplayPortMargins == aOther.mDisplayPortMargins &&
117 116 : mPresShellId == aOther.mPresShellId &&
118 116 : mViewport.IsEqualEdges(aOther.mViewport) &&
119 116 : mExtraResolution == aOther.mExtraResolution &&
120 107 : mPaintRequestTime == aOther.mPaintRequestTime &&
121 98 : mScrollUpdateType == aOther.mScrollUpdateType &&
122 98 : mIsRootContent == aOther.mIsRootContent &&
123 98 : mDoSmoothScroll == aOther.mDoSmoothScroll &&
124 196 : mUseDisplayPortMargins == aOther.mUseDisplayPortMargins &&
125 147 : mIsScrollInfoLayer == aOther.mIsScrollInfoLayer;
126 : }
127 :
128 : bool operator!=(const FrameMetrics& aOther) const
129 : {
130 : return !operator==(aOther);
131 : }
132 :
133 670 : bool IsScrollable() const
134 : {
135 670 : return mScrollId != NULL_SCROLL_ID;
136 : }
137 :
138 31 : CSSToScreenScale2D DisplayportPixelsPerCSSPixel() const
139 : {
140 : // Note: use 'mZoom * ParentLayerToLayerScale(1.0f)' as the CSS-to-Layer scale
141 : // instead of LayersPixelsPerCSSPixel(), because displayport calculations
142 : // are done in the context of a repaint request, where we ask Layout to
143 : // repaint at a new resolution that includes any async zoom. Until this
144 : // repaint request is processed, LayersPixelsPerCSSPixel() does not yet
145 : // include the async zoom, but it will when the displayport is interpreted
146 : // for the repaint.
147 31 : return mZoom * ParentLayerToLayerScale(1.0f) / mExtraResolution;
148 : }
149 :
150 62 : CSSToLayerScale2D LayersPixelsPerCSSPixel() const
151 : {
152 62 : return mDevPixelsPerCSSPixel * mCumulativeResolution;
153 : }
154 :
155 : // Get the amount by which this frame has been zoomed since the last repaint.
156 0 : LayerToParentLayerScale GetAsyncZoom() const
157 : {
158 : // The async portion of the zoom should be the same along the x and y
159 : // axes.
160 0 : return (mZoom / LayersPixelsPerCSSPixel()).ToScaleFactor();
161 : }
162 :
163 : // Ensure the scrollableRect is at least as big as the compositionBounds
164 : // because the scrollableRect can be smaller if the content is not large
165 : // and the scrollableRect hasn't been updated yet.
166 : // We move the scrollableRect up because we don't know if we can move it
167 : // down. i.e. we know that scrollableRect can go back as far as zero.
168 : // but we don't know how much further ahead it can go.
169 2 : CSSRect GetExpandedScrollableRect() const
170 : {
171 2 : CSSRect scrollableRect = mScrollableRect;
172 2 : CSSSize compSize = CalculateCompositedSizeInCssPixels();
173 2 : if (scrollableRect.width < compSize.width) {
174 0 : scrollableRect.x = std::max(0.f,
175 0 : scrollableRect.x - (compSize.width - scrollableRect.width));
176 0 : scrollableRect.width = compSize.width;
177 : }
178 :
179 2 : if (scrollableRect.height < compSize.height) {
180 0 : scrollableRect.y = std::max(0.f,
181 0 : scrollableRect.y - (compSize.height - scrollableRect.height));
182 0 : scrollableRect.height = compSize.height;
183 : }
184 :
185 2 : return scrollableRect;
186 : }
187 :
188 84 : CSSSize CalculateCompositedSizeInCssPixels() const
189 : {
190 84 : if (GetZoom() == CSSToParentLayerScale2D(0, 0)) {
191 0 : return CSSSize(); // avoid division by zero
192 : }
193 84 : return mCompositionBounds.Size() / GetZoom();
194 : }
195 :
196 2 : CSSRect CalculateCompositedRectInCssPixels() const
197 : {
198 2 : if (GetZoom() == CSSToParentLayerScale2D(0, 0)) {
199 0 : return CSSRect(); // avoid division by zero
200 : }
201 2 : return mCompositionBounds / GetZoom();
202 : }
203 :
204 6 : CSSSize CalculateBoundedCompositedSizeInCssPixels() const
205 : {
206 6 : CSSSize size = CalculateCompositedSizeInCssPixels();
207 6 : size.width = std::min(size.width, mRootCompositionSize.width);
208 6 : size.height = std::min(size.height, mRootCompositionSize.height);
209 6 : return size;
210 : }
211 :
212 1 : CSSRect CalculateScrollRange() const
213 : {
214 1 : CSSSize scrollPortSize = CalculateCompositedSizeInCssPixels();
215 1 : CSSRect scrollRange = mScrollableRect;
216 1 : scrollRange.width = std::max(scrollRange.width - scrollPortSize.width, 0.0f);
217 1 : scrollRange.height = std::max(scrollRange.height - scrollPortSize.height, 0.0f);
218 1 : return scrollRange;
219 : }
220 :
221 0 : void ScrollBy(const CSSPoint& aPoint)
222 : {
223 0 : mScrollOffset += aPoint;
224 0 : }
225 :
226 0 : void ZoomBy(float aScale)
227 : {
228 0 : ZoomBy(gfxSize(aScale, aScale));
229 0 : }
230 :
231 3 : void ZoomBy(const gfxSize& aScale)
232 : {
233 3 : mZoom.xScale *= aScale.width;
234 3 : mZoom.yScale *= aScale.height;
235 3 : }
236 :
237 0 : void CopyScrollInfoFrom(const FrameMetrics& aOther)
238 : {
239 0 : mScrollOffset = aOther.mScrollOffset;
240 0 : mScrollGeneration = aOther.mScrollGeneration;
241 0 : }
242 :
243 0 : void CopySmoothScrollInfoFrom(const FrameMetrics& aOther)
244 : {
245 0 : mSmoothScrollOffset = aOther.mSmoothScrollOffset;
246 0 : mScrollGeneration = aOther.mScrollGeneration;
247 0 : mDoSmoothScroll = aOther.mDoSmoothScroll;
248 0 : }
249 :
250 0 : void UpdatePendingScrollInfo(const ScrollUpdateInfo& aInfo)
251 : {
252 0 : mScrollOffset = aInfo.mScrollOffset;
253 0 : mScrollGeneration = aInfo.mScrollGeneration;
254 0 : mScrollUpdateType = ePending;
255 0 : }
256 :
257 2 : void SetRepaintDrivenByUserAction(bool aUserAction)
258 : {
259 2 : mScrollUpdateType = aUserAction ? eUserAction : eNone;
260 2 : }
261 :
262 : public:
263 32 : void SetPresShellResolution(float aPresShellResolution)
264 : {
265 32 : mPresShellResolution = aPresShellResolution;
266 32 : }
267 :
268 13 : float GetPresShellResolution() const
269 : {
270 13 : return mPresShellResolution;
271 : }
272 :
273 32 : void SetCompositionBounds(const ParentLayerRect& aCompositionBounds)
274 : {
275 32 : mCompositionBounds = aCompositionBounds;
276 32 : }
277 :
278 113 : const ParentLayerRect& GetCompositionBounds() const
279 : {
280 113 : return mCompositionBounds;
281 : }
282 :
283 27 : void SetDisplayPort(const CSSRect& aDisplayPort)
284 : {
285 27 : mDisplayPort = aDisplayPort;
286 27 : }
287 :
288 40 : const CSSRect& GetDisplayPort() const
289 : {
290 40 : return mDisplayPort;
291 : }
292 :
293 0 : void SetCriticalDisplayPort(const CSSRect& aCriticalDisplayPort)
294 : {
295 0 : mCriticalDisplayPort = aCriticalDisplayPort;
296 0 : }
297 :
298 5 : const CSSRect& GetCriticalDisplayPort() const
299 : {
300 5 : return mCriticalDisplayPort;
301 : }
302 :
303 32 : void SetCumulativeResolution(const LayoutDeviceToLayerScale2D& aCumulativeResolution)
304 : {
305 32 : mCumulativeResolution = aCumulativeResolution;
306 32 : }
307 :
308 100 : const LayoutDeviceToLayerScale2D& GetCumulativeResolution() const
309 : {
310 100 : return mCumulativeResolution;
311 : }
312 :
313 29 : void SetDevPixelsPerCSSPixel(const CSSToLayoutDeviceScale& aDevPixelsPerCSSPixel)
314 : {
315 29 : mDevPixelsPerCSSPixel = aDevPixelsPerCSSPixel;
316 29 : }
317 :
318 58 : const CSSToLayoutDeviceScale& GetDevPixelsPerCSSPixel() const
319 : {
320 58 : return mDevPixelsPerCSSPixel;
321 : }
322 :
323 54 : void SetIsRootContent(bool aIsRootContent)
324 : {
325 54 : mIsRootContent = aIsRootContent;
326 54 : }
327 :
328 28 : bool IsRootContent() const
329 : {
330 28 : return mIsRootContent;
331 : }
332 :
333 6 : void SetScrollOffset(const CSSPoint& aScrollOffset)
334 : {
335 6 : mScrollOffset = aScrollOffset;
336 6 : }
337 :
338 332 : const CSSPoint& GetScrollOffset() const
339 : {
340 332 : return mScrollOffset;
341 : }
342 :
343 3 : void SetSmoothScrollOffset(const CSSPoint& aSmoothScrollDestination)
344 : {
345 3 : mSmoothScrollOffset = aSmoothScrollDestination;
346 3 : }
347 :
348 0 : const CSSPoint& GetSmoothScrollOffset() const
349 : {
350 0 : return mSmoothScrollOffset;
351 : }
352 :
353 29 : void SetZoom(const CSSToParentLayerScale2D& aZoom)
354 : {
355 29 : mZoom = aZoom;
356 29 : }
357 :
358 311 : const CSSToParentLayerScale2D& GetZoom() const
359 : {
360 311 : return mZoom;
361 : }
362 :
363 3 : void SetScrollOffsetUpdated(uint32_t aScrollGeneration)
364 : {
365 3 : mScrollUpdateType = eMainThread;
366 3 : mScrollGeneration = aScrollGeneration;
367 3 : }
368 :
369 0 : void SetScrollOffsetRestored(uint32_t aScrollGeneration)
370 : {
371 0 : mScrollUpdateType = eRestore;
372 0 : mScrollGeneration = aScrollGeneration;
373 0 : }
374 :
375 0 : void SetSmoothScrollOffsetUpdated(int32_t aScrollGeneration)
376 : {
377 0 : mDoSmoothScroll = true;
378 0 : mScrollGeneration = aScrollGeneration;
379 0 : }
380 :
381 9 : ScrollOffsetUpdateType GetScrollUpdateType() const
382 : {
383 9 : return mScrollUpdateType;
384 : }
385 :
386 7 : bool GetScrollOffsetUpdated() const
387 : {
388 7 : return mScrollUpdateType != eNone;
389 : }
390 :
391 7 : bool GetDoSmoothScroll() const
392 : {
393 7 : return mDoSmoothScroll;
394 : }
395 :
396 2 : uint32_t GetScrollGeneration() const
397 : {
398 2 : return mScrollGeneration;
399 : }
400 :
401 312 : ViewID GetScrollId() const
402 : {
403 312 : return mScrollId;
404 : }
405 :
406 27 : void SetScrollId(ViewID scrollId)
407 : {
408 27 : mScrollId = scrollId;
409 27 : }
410 :
411 32 : void SetRootCompositionSize(const CSSSize& aRootCompositionSize)
412 : {
413 32 : mRootCompositionSize = aRootCompositionSize;
414 32 : }
415 :
416 5 : const CSSSize& GetRootCompositionSize() const
417 : {
418 5 : return mRootCompositionSize;
419 : }
420 :
421 31 : void SetDisplayPortMargins(const ScreenMargin& aDisplayPortMargins)
422 : {
423 31 : mDisplayPortMargins = aDisplayPortMargins;
424 31 : }
425 :
426 12 : const ScreenMargin& GetDisplayPortMargins() const
427 : {
428 12 : return mDisplayPortMargins;
429 : }
430 :
431 29 : void SetUseDisplayPortMargins(bool aValue)
432 : {
433 29 : mUseDisplayPortMargins = aValue;
434 29 : }
435 :
436 2 : bool GetUseDisplayPortMargins() const
437 : {
438 2 : return mUseDisplayPortMargins;
439 : }
440 :
441 216 : uint32_t GetPresShellId() const
442 : {
443 216 : return mPresShellId;
444 : }
445 :
446 61 : void SetPresShellId(uint32_t aPresShellId)
447 : {
448 61 : mPresShellId = aPresShellId;
449 61 : }
450 :
451 31 : void SetViewport(const CSSRect& aViewport)
452 : {
453 31 : mViewport = aViewport;
454 31 : }
455 :
456 20 : const CSSRect& GetViewport() const
457 : {
458 20 : return mViewport;
459 : }
460 :
461 27 : void SetExtraResolution(const ScreenToLayerScale2D& aExtraResolution)
462 : {
463 27 : mExtraResolution = aExtraResolution;
464 27 : }
465 :
466 0 : const ScreenToLayerScale2D& GetExtraResolution() const
467 : {
468 0 : return mExtraResolution;
469 : }
470 :
471 55 : const CSSRect& GetScrollableRect() const
472 : {
473 55 : return mScrollableRect;
474 : }
475 :
476 28 : void SetScrollableRect(const CSSRect& aScrollableRect)
477 : {
478 28 : mScrollableRect = aScrollableRect;
479 28 : }
480 :
481 4 : void SetPaintRequestTime(const TimeStamp& aTime) {
482 4 : mPaintRequestTime = aTime;
483 4 : }
484 9 : const TimeStamp& GetPaintRequestTime() const {
485 9 : return mPaintRequestTime;
486 : }
487 :
488 32 : void SetIsScrollInfoLayer(bool aIsScrollInfoLayer) {
489 32 : mIsScrollInfoLayer = aIsScrollInfoLayer;
490 32 : }
491 7 : bool IsScrollInfoLayer() const {
492 7 : return mIsScrollInfoLayer;
493 : }
494 :
495 : private:
496 : // A unique ID assigned to each scrollable frame.
497 : ViewID mScrollId;
498 :
499 : // The pres-shell resolution that has been induced on the document containing
500 : // this scroll frame as a result of zooming this scroll frame (whether via
501 : // user action, or choosing an initial zoom level on page load). This can
502 : // only be different from 1.0 for frames that are zoomable, which currently
503 : // is just the root content document's root scroll frame (mIsRoot = true).
504 : // This is a plain float rather than a ScaleFactor because in and of itself
505 : // it does not convert between any coordinate spaces for which we have names.
506 : float mPresShellResolution;
507 :
508 : // This is the area within the widget that we're compositing to. It is in the
509 : // same coordinate space as the reference frame for the scrolled frame.
510 : //
511 : // This is useful because, on mobile, the viewport and composition dimensions
512 : // are not always the same. In this case, we calculate the displayport using
513 : // an area bigger than the region we're compositing to. If we used the
514 : // viewport dimensions to calculate the displayport, we'd run into situations
515 : // where we're prerendering the wrong regions and the content may be clipped,
516 : // or too much of it prerendered. If the composition dimensions are the same
517 : // as the viewport dimensions, there is no need for this and we can just use
518 : // the viewport instead.
519 : //
520 : // This value is valid for nested scrollable layers as well, and is still
521 : // relative to the layer tree origin. This value is provided by Gecko at
522 : // layout/paint time.
523 : ParentLayerRect mCompositionBounds;
524 :
525 : // The area of a frame's contents that has been painted, relative to
526 : // mCompositionBounds.
527 : //
528 : // Note that this is structured in such a way that it doesn't depend on the
529 : // method layout uses to scroll content.
530 : //
531 : // May be larger or smaller than |mScrollableRect|.
532 : //
533 : // To pre-render a margin of 100 CSS pixels around the window,
534 : // { x = -100, y = - 100,
535 : // width = window.innerWidth + 200, height = window.innerHeight + 200 }
536 : CSSRect mDisplayPort;
537 :
538 : // If non-empty, the area of a frame's contents that is considered critical
539 : // to paint. Area outside of this area (i.e. area inside mDisplayPort, but
540 : // outside of mCriticalDisplayPort) is considered low-priority, and may be
541 : // painted with lower precision, or not painted at all.
542 : //
543 : // The same restrictions for mDisplayPort apply here.
544 : CSSRect mCriticalDisplayPort;
545 :
546 : // The scrollable bounds of a frame. This is determined by reflow.
547 : // Ordinarily the x and y will be 0 and the width and height will be the
548 : // size of the element being scrolled. However for RTL pages or elements
549 : // the x value may be negative.
550 : //
551 : // For scrollable frames that are overflow:hidden the x and y are usually
552 : // set to the value of the current scroll offset, and the width and height
553 : // will match the composition bounds width and height. In effect this reduces
554 : // the scrollable range to 0.
555 : //
556 : // This is in the same coordinate space as |mScrollOffset|, but a different
557 : // coordinate space than |mViewport| and |mDisplayPort|. Note also that this
558 : // coordinate system is understood by window.scrollTo().
559 : //
560 : // This is valid on any layer unless it has no content.
561 : CSSRect mScrollableRect;
562 :
563 : // The cumulative resolution that the current frame has been painted at.
564 : // This is the product of the pres-shell resolutions of the document
565 : // containing this scroll frame and its ancestors, and any css-driven
566 : // resolution. This information is provided by Gecko at layout/paint time.
567 : // Note that this is allowed to have different x- and y-scales, but only
568 : // for subframes (mIsRoot = false). (The same applies to other scales that
569 : // "inherit" the 2D-ness of this one, such as mZoom.)
570 : LayoutDeviceToLayerScale2D mCumulativeResolution;
571 :
572 : // New fields from now on should be made private and old fields should
573 : // be refactored to be private.
574 :
575 : // The conversion factor between CSS pixels and device pixels for this frame.
576 : // This can vary based on a variety of things, such as reflowing-zoom. The
577 : // conversion factor for device pixels to layers pixels is just the
578 : // resolution.
579 : CSSToLayoutDeviceScale mDevPixelsPerCSSPixel;
580 :
581 : // The position of the top-left of the CSS viewport, relative to the document
582 : // (or the document relative to the viewport, if that helps understand it).
583 : //
584 : // Thus it is relative to the document. It is in the same coordinate space as
585 : // |mScrollableRect|, but a different coordinate space than |mViewport| and
586 : // |mDisplayPort|.
587 : //
588 : // It is required that the rect:
589 : // { x = mScrollOffset.x, y = mScrollOffset.y,
590 : // width = mCompositionBounds.x / mResolution.scale,
591 : // height = mCompositionBounds.y / mResolution.scale }
592 : // Be within |mScrollableRect|.
593 : //
594 : // This is valid for any layer, but is always relative to this frame and
595 : // not any parents, regardless of parent transforms.
596 : CSSPoint mScrollOffset;
597 :
598 : // The "user zoom". Content is painted by gecko at mResolution * mDevPixelsPerCSSPixel,
599 : // but will be drawn to the screen at mZoom. In the steady state, the
600 : // two will be the same, but during an async zoom action the two may
601 : // diverge. This information is initialized in Gecko but updated in the APZC.
602 : CSSToParentLayerScale2D mZoom;
603 :
604 : // The scroll generation counter used to acknowledge the scroll offset update.
605 : uint32_t mScrollGeneration;
606 :
607 : // If mDoSmoothScroll is true, the scroll offset will be animated smoothly
608 : // to this value.
609 : CSSPoint mSmoothScrollOffset;
610 :
611 : // The size of the root scrollable's composition bounds, but in local CSS pixels.
612 : CSSSize mRootCompositionSize;
613 :
614 : // A display port expressed as layer margins that apply to the rect of what
615 : // is drawn of the scrollable element.
616 : ScreenMargin mDisplayPortMargins;
617 :
618 : uint32_t mPresShellId;
619 :
620 : // The CSS viewport, which is the dimensions we're using to constrain the
621 : // <html> element of this frame, relative to the top-left of the layer. Note
622 : // that its offset is structured in such a way that it doesn't depend on the
623 : // method layout uses to scroll content.
624 : //
625 : // This is mainly useful on the root layer, however nested iframes can have
626 : // their own viewport, which will just be the size of the window of the
627 : // iframe. For layers that don't correspond to a document, this metric is
628 : // meaningless and invalid.
629 : CSSRect mViewport;
630 :
631 : // The extra resolution at which content in this scroll frame is drawn beyond
632 : // that necessary to draw one Layer pixel per Screen pixel.
633 : ScreenToLayerScale2D mExtraResolution;
634 :
635 : // The time at which the APZC last requested a repaint for this scrollframe.
636 : TimeStamp mPaintRequestTime;
637 :
638 : // Whether mScrollOffset was updated by something other than the APZ code, and
639 : // if the APZC receiving this metrics should update its local copy.
640 : ScrollOffsetUpdateType mScrollUpdateType;
641 :
642 : // Whether or not this is the root scroll frame for the root content document.
643 : bool mIsRootContent:1;
644 :
645 : // When mDoSmoothScroll, the scroll offset should be animated to
646 : // smoothly transition to mScrollOffset rather than be updated instantly.
647 : bool mDoSmoothScroll:1;
648 :
649 : // If this is true then we use the display port margins on this metrics,
650 : // otherwise use the display port rect.
651 : bool mUseDisplayPortMargins:1;
652 :
653 : // Whether or not this frame has a "scroll info layer" to capture events.
654 : bool mIsScrollInfoLayer:1;
655 :
656 : // WARNING!!!!
657 : //
658 : // When adding a new field:
659 : //
660 : // - First, consider whether the field can be added to ScrollMetadata
661 : // instead. If so, prefer that.
662 : //
663 : // - Otherwise, the following places should be updated to include them
664 : // (as needed):
665 : // FrameMetrics::operator ==
666 : // AsyncPanZoomController::NotifyLayersUpdated
667 : // The ParamTraits specialization in GfxMessageUtils.h
668 : //
669 : // Please add new fields above this comment.
670 :
671 : // Private helpers for IPC purposes
672 27 : void SetDoSmoothScroll(bool aValue) {
673 27 : mDoSmoothScroll = aValue;
674 27 : }
675 : };
676 :
677 300 : struct ScrollSnapInfo {
678 98 : ScrollSnapInfo()
679 98 : : mScrollSnapTypeX(NS_STYLE_SCROLL_SNAP_TYPE_NONE)
680 98 : , mScrollSnapTypeY(NS_STYLE_SCROLL_SNAP_TYPE_NONE)
681 98 : {}
682 :
683 49 : bool operator==(const ScrollSnapInfo& aOther) const
684 : {
685 98 : return mScrollSnapTypeX == aOther.mScrollSnapTypeX &&
686 98 : mScrollSnapTypeY == aOther.mScrollSnapTypeY &&
687 98 : mScrollSnapIntervalX == aOther.mScrollSnapIntervalX &&
688 98 : mScrollSnapIntervalY == aOther.mScrollSnapIntervalY &&
689 147 : mScrollSnapDestination == aOther.mScrollSnapDestination &&
690 98 : mScrollSnapCoordinates == aOther.mScrollSnapCoordinates;
691 : }
692 :
693 : bool HasScrollSnapping() const
694 : {
695 : return mScrollSnapTypeY != NS_STYLE_SCROLL_SNAP_TYPE_NONE ||
696 : mScrollSnapTypeX != NS_STYLE_SCROLL_SNAP_TYPE_NONE;
697 : }
698 :
699 : // The scroll frame's scroll-snap-type.
700 : // One of NS_STYLE_SCROLL_SNAP_{NONE, MANDATORY, PROXIMITY}.
701 : uint8_t mScrollSnapTypeX;
702 : uint8_t mScrollSnapTypeY;
703 :
704 : // The intervals derived from the scroll frame's scroll-snap-points.
705 : Maybe<nscoord> mScrollSnapIntervalX;
706 : Maybe<nscoord> mScrollSnapIntervalY;
707 :
708 : // The scroll frame's scroll-snap-destination, in cooked form (to avoid
709 : // shipping the raw nsStyleCoord::CalcValue over IPC).
710 : nsPoint mScrollSnapDestination;
711 :
712 : // The scroll-snap-coordinates of any descendant frames of the scroll frame,
713 : // relative to the origin of the scrolled frame.
714 : nsTArray<nsPoint> mScrollSnapCoordinates;
715 : };
716 :
717 : /**
718 : * A clip that applies to a layer, that may be scrolled by some of the
719 : * scroll frames associated with the layer.
720 : */
721 66 : struct LayerClip {
722 : friend struct IPC::ParamTraits<mozilla::layers::LayerClip>;
723 :
724 : public:
725 3 : LayerClip()
726 3 : : mClipRect()
727 3 : , mMaskLayerIndex()
728 3 : {}
729 :
730 3 : explicit LayerClip(const ParentLayerIntRect& aClipRect)
731 3 : : mClipRect(aClipRect)
732 3 : , mMaskLayerIndex()
733 3 : {}
734 :
735 7 : bool operator==(const LayerClip& aOther) const
736 : {
737 14 : return mClipRect == aOther.mClipRect &&
738 14 : mMaskLayerIndex == aOther.mMaskLayerIndex;
739 : }
740 :
741 0 : void SetClipRect(const ParentLayerIntRect& aClipRect) {
742 0 : mClipRect = aClipRect;
743 0 : }
744 38 : const ParentLayerIntRect& GetClipRect() const {
745 38 : return mClipRect;
746 : }
747 :
748 0 : void SetMaskLayerIndex(const Maybe<size_t>& aIndex) {
749 0 : mMaskLayerIndex = aIndex;
750 0 : }
751 11 : const Maybe<size_t>& GetMaskLayerIndex() const {
752 11 : return mMaskLayerIndex;
753 : }
754 :
755 : private:
756 : ParentLayerIntRect mClipRect;
757 :
758 : // Optionally, specifies a mask layer that's part of the clip.
759 : // This is an index into the MetricsMaskLayers array on the Layer.
760 : Maybe<size_t> mMaskLayerIndex;
761 : };
762 :
763 : typedef Maybe<LayerClip> MaybeLayerClip; // for passing over IPDL
764 :
765 : /**
766 : * Metadata about a scroll frame that's stored in the layer tree for use by
767 : * the compositor (including APZ). This includes the scroll frame's FrameMetrics,
768 : * as well as other metadata. We don't put the other metadata into FrameMetrics
769 : * to avoid FrameMetrics becoming too bloated (as a FrameMetrics is e.g. sent
770 : * over IPC for every repaint request for every active scroll frame).
771 : */
772 279 : struct ScrollMetadata {
773 : friend struct IPC::ParamTraits<mozilla::layers::ScrollMetadata>;
774 :
775 : typedef FrameMetrics::ViewID ViewID;
776 : public:
777 : static StaticAutoPtr<const ScrollMetadata> sNullMetadata; // We sometimes need an empty metadata
778 :
779 95 : ScrollMetadata()
780 95 : : mMetrics()
781 : , mSnapInfo()
782 : , mScrollParentId(FrameMetrics::NULL_SCROLL_ID)
783 : , mBackgroundColor()
784 : , mContentDescription()
785 : , mLineScrollAmount(0, 0)
786 : , mPageScrollAmount(0, 0)
787 : , mScrollClip()
788 : , mHasScrollgrab(false)
789 : , mAllowVerticalScrollWithWheel(false)
790 : , mIsLayersIdRoot(false)
791 : , mUsesContainerScrolling(false)
792 95 : , mForceDisableApz(false)
793 95 : {}
794 :
795 98 : bool operator==(const ScrollMetadata& aOther) const
796 : {
797 147 : return mMetrics == aOther.mMetrics &&
798 98 : mSnapInfo == aOther.mSnapInfo &&
799 98 : mScrollParentId == aOther.mScrollParentId &&
800 98 : mBackgroundColor == aOther.mBackgroundColor &&
801 : // don't compare mContentDescription
802 98 : mLineScrollAmount == aOther.mLineScrollAmount &&
803 98 : mPageScrollAmount == aOther.mPageScrollAmount &&
804 98 : mScrollClip == aOther.mScrollClip &&
805 98 : mHasScrollgrab == aOther.mHasScrollgrab &&
806 98 : mAllowVerticalScrollWithWheel == aOther.mAllowVerticalScrollWithWheel &&
807 98 : mIsLayersIdRoot == aOther.mIsLayersIdRoot &&
808 196 : mUsesContainerScrolling == aOther.mUsesContainerScrolling &&
809 147 : mForceDisableApz == aOther.mForceDisableApz;
810 : }
811 :
812 0 : bool operator!=(const ScrollMetadata& aOther) const
813 : {
814 0 : return !operator==(aOther);
815 : }
816 :
817 34 : bool IsDefault() const
818 : {
819 68 : ScrollMetadata def;
820 :
821 34 : def.mMetrics.SetPresShellId(mMetrics.GetPresShellId());
822 68 : return (def == *this);
823 : }
824 :
825 66 : FrameMetrics& GetMetrics() { return mMetrics; }
826 763 : const FrameMetrics& GetMetrics() const { return mMetrics; }
827 :
828 8 : void SetSnapInfo(ScrollSnapInfo&& aSnapInfo) {
829 8 : mSnapInfo = Move(aSnapInfo);
830 8 : }
831 5 : const ScrollSnapInfo& GetSnapInfo() const { return mSnapInfo; }
832 :
833 7 : ViewID GetScrollParentId() const {
834 7 : return mScrollParentId;
835 : }
836 :
837 34 : void SetScrollParentId(ViewID aParentId) {
838 34 : mScrollParentId = aParentId;
839 34 : }
840 0 : const gfx::Color& GetBackgroundColor() const {
841 0 : return mBackgroundColor;
842 : }
843 3 : void SetBackgroundColor(const gfx::Color& aBackgroundColor) {
844 3 : mBackgroundColor = aBackgroundColor;
845 3 : }
846 66 : const nsCString& GetContentDescription() const {
847 66 : return mContentDescription;
848 : }
849 27 : void SetContentDescription(const nsCString& aContentDescription) {
850 27 : mContentDescription = aContentDescription;
851 27 : }
852 5 : const LayoutDeviceIntSize& GetLineScrollAmount() const {
853 5 : return mLineScrollAmount;
854 : }
855 8 : void SetLineScrollAmount(const LayoutDeviceIntSize& size) {
856 8 : mLineScrollAmount = size;
857 8 : }
858 5 : const LayoutDeviceIntSize& GetPageScrollAmount() const {
859 5 : return mPageScrollAmount;
860 : }
861 8 : void SetPageScrollAmount(const LayoutDeviceIntSize& size) {
862 8 : mPageScrollAmount = size;
863 8 : }
864 :
865 8 : void SetScrollClip(const Maybe<LayerClip>& aScrollClip) {
866 8 : mScrollClip = aScrollClip;
867 8 : }
868 0 : const Maybe<LayerClip>& GetScrollClip() const {
869 0 : return mScrollClip;
870 : }
871 80 : bool HasScrollClip() const {
872 80 : return mScrollClip.isSome();
873 : }
874 22 : const LayerClip& ScrollClip() const {
875 22 : return mScrollClip.ref();
876 : }
877 0 : LayerClip& ScrollClip() {
878 0 : return mScrollClip.ref();
879 : }
880 :
881 0 : bool HasMaskLayer() const {
882 0 : return HasScrollClip() && ScrollClip().GetMaskLayerIndex();
883 : }
884 279 : Maybe<ParentLayerIntRect> GetClipRect() const {
885 279 : return mScrollClip.isSome() ? Some(mScrollClip->GetClipRect()) : Nothing();
886 : }
887 :
888 32 : void SetHasScrollgrab(bool aHasScrollgrab) {
889 32 : mHasScrollgrab = aHasScrollgrab;
890 32 : }
891 44 : bool GetHasScrollgrab() const {
892 44 : return mHasScrollgrab;
893 : }
894 0 : bool AllowVerticalScrollWithWheel() const {
895 0 : return mAllowVerticalScrollWithWheel;
896 : }
897 30 : void SetAllowVerticalScrollWithWheel(bool aValue) {
898 30 : mAllowVerticalScrollWithWheel = aValue;
899 30 : }
900 59 : void SetIsLayersIdRoot(bool aValue) {
901 59 : mIsLayersIdRoot = aValue;
902 59 : }
903 5 : bool IsLayersIdRoot() const {
904 5 : return mIsLayersIdRoot;
905 : }
906 : // Implemented out of line because the implementation needs gfxPrefs.h
907 : // and we don't want to include that from FrameMetrics.h.
908 : void SetUsesContainerScrolling(bool aValue);
909 45 : bool UsesContainerScrolling() const {
910 45 : return mUsesContainerScrolling;
911 : }
912 32 : void SetForceDisableApz(bool aForceDisable) {
913 32 : mForceDisableApz = aForceDisable;
914 32 : }
915 97 : bool IsApzForceDisabled() const {
916 97 : return mForceDisableApz;
917 : }
918 :
919 : private:
920 : FrameMetrics mMetrics;
921 :
922 : // Information used to determine where to snap to for a given scroll.
923 : ScrollSnapInfo mSnapInfo;
924 :
925 : // The ViewID of the scrollable frame to which overscroll should be handed off.
926 : ViewID mScrollParentId;
927 :
928 : // The background color to use when overscrolling.
929 : gfx::Color mBackgroundColor;
930 :
931 : // A description of the content element corresponding to this frame.
932 : // This is empty unless this is a scrollable layer and the
933 : // apz.printtree pref is turned on.
934 : nsCString mContentDescription;
935 :
936 : // The value of GetLineScrollAmount(), for scroll frames.
937 : LayoutDeviceIntSize mLineScrollAmount;
938 :
939 : // The value of GetPageScrollAmount(), for scroll frames.
940 : LayoutDeviceIntSize mPageScrollAmount;
941 :
942 : // A clip to apply when compositing the layer bearing this ScrollMetadata,
943 : // after applying any transform arising from scrolling this scroll frame.
944 : // Note that, unlike most other fields of ScrollMetadata, this is allowed
945 : // to differ between different layers scrolled by the same scroll frame.
946 : // TODO: Group the fields of ScrollMetadata into sub-structures to separate
947 : // fields with this property better.
948 : Maybe<LayerClip> mScrollClip;
949 :
950 : // Whether or not this frame is for an element marked 'scrollgrab'.
951 : bool mHasScrollgrab:1;
952 :
953 : // Whether or not the frame can be vertically scrolled with a mouse wheel.
954 : bool mAllowVerticalScrollWithWheel:1;
955 :
956 : // Whether these framemetrics are for the root scroll frame (root element if
957 : // we don't have a root scroll frame) for its layers id.
958 : bool mIsLayersIdRoot:1;
959 :
960 : // True if scrolling using containers, false otherwise. This can be removed
961 : // when containerful scrolling is eliminated.
962 : bool mUsesContainerScrolling:1;
963 :
964 : // Whether or not the compositor should actually do APZ-scrolling on this
965 : // scrollframe.
966 : bool mForceDisableApz:1;
967 :
968 : // WARNING!!!!
969 : //
970 : // When adding new fields to ScrollMetadata, the following places should be
971 : // updated to include them (as needed):
972 : // ScrollMetadata::operator ==
973 : // AsyncPanZoomController::NotifyLayersUpdated
974 : // The ParamTraits specialization in GfxMessageUtils.h
975 : //
976 : // Please add new fields above this comment.
977 : };
978 :
979 : /**
980 : * This class allows us to uniquely identify a scrollable layer. The
981 : * mLayersId identifies the layer tree (corresponding to a child process
982 : * and/or tab) that the scrollable layer belongs to. The mPresShellId
983 : * is a temporal identifier (corresponding to the document loaded that
984 : * contains the scrollable layer, which may change over time). The
985 : * mScrollId corresponds to the actual frame that is scrollable.
986 : */
987 : struct ScrollableLayerGuid {
988 : uint64_t mLayersId;
989 : uint32_t mPresShellId;
990 : FrameMetrics::ViewID mScrollId;
991 :
992 53 : ScrollableLayerGuid()
993 53 : : mLayersId(0)
994 : , mPresShellId(0)
995 53 : , mScrollId(0)
996 : {
997 53 : }
998 :
999 8 : ScrollableLayerGuid(uint64_t aLayersId, uint32_t aPresShellId,
1000 : FrameMetrics::ViewID aScrollId)
1001 8 : : mLayersId(aLayersId)
1002 : , mPresShellId(aPresShellId)
1003 8 : , mScrollId(aScrollId)
1004 : {
1005 8 : }
1006 :
1007 182 : ScrollableLayerGuid(uint64_t aLayersId, const FrameMetrics& aMetrics)
1008 182 : : mLayersId(aLayersId)
1009 182 : , mPresShellId(aMetrics.GetPresShellId())
1010 364 : , mScrollId(aMetrics.GetScrollId())
1011 : {
1012 182 : }
1013 :
1014 105 : ScrollableLayerGuid(const ScrollableLayerGuid& other)
1015 105 : : mLayersId(other.mLayersId)
1016 105 : , mPresShellId(other.mPresShellId)
1017 210 : , mScrollId(other.mScrollId)
1018 : {
1019 105 : }
1020 :
1021 316 : ~ScrollableLayerGuid()
1022 316 : {
1023 316 : }
1024 :
1025 105 : bool operator==(const ScrollableLayerGuid& other) const
1026 : {
1027 105 : return mLayersId == other.mLayersId
1028 104 : && mPresShellId == other.mPresShellId
1029 209 : && mScrollId == other.mScrollId;
1030 : }
1031 :
1032 0 : bool operator!=(const ScrollableLayerGuid& other) const
1033 : {
1034 0 : return !(*this == other);
1035 : }
1036 :
1037 : bool operator<(const ScrollableLayerGuid& other) const
1038 : {
1039 : if (mLayersId < other.mLayersId) {
1040 : return true;
1041 : }
1042 : if (mLayersId == other.mLayersId) {
1043 : if (mPresShellId < other.mPresShellId) {
1044 : return true;
1045 : }
1046 : if (mPresShellId == other.mPresShellId) {
1047 : return mScrollId < other.mScrollId;
1048 : }
1049 : }
1050 : return false;
1051 : }
1052 :
1053 42 : PLDHashNumber Hash() const
1054 : {
1055 42 : return HashGeneric(mLayersId, mPresShellId, mScrollId);
1056 : }
1057 : };
1058 :
1059 : template <int LogLevel>
1060 0 : gfx::Log<LogLevel>& operator<<(gfx::Log<LogLevel>& log, const ScrollableLayerGuid& aGuid) {
1061 0 : return log << '(' << aGuid.mLayersId << ',' << aGuid.mPresShellId << ',' << aGuid.mScrollId << ')';
1062 : }
1063 :
1064 : struct ZoomConstraints {
1065 : bool mAllowZoom;
1066 : bool mAllowDoubleTapZoom;
1067 : CSSToParentLayerScale mMinZoom;
1068 : CSSToParentLayerScale mMaxZoom;
1069 :
1070 3 : ZoomConstraints()
1071 3 : : mAllowZoom(true)
1072 3 : , mAllowDoubleTapZoom(true)
1073 : {
1074 3 : MOZ_COUNT_CTOR(ZoomConstraints);
1075 3 : }
1076 :
1077 2 : ZoomConstraints(bool aAllowZoom,
1078 : bool aAllowDoubleTapZoom,
1079 : const CSSToParentLayerScale& aMinZoom,
1080 : const CSSToParentLayerScale& aMaxZoom)
1081 2 : : mAllowZoom(aAllowZoom)
1082 : , mAllowDoubleTapZoom(aAllowDoubleTapZoom)
1083 : , mMinZoom(aMinZoom)
1084 2 : , mMaxZoom(aMaxZoom)
1085 : {
1086 2 : MOZ_COUNT_CTOR(ZoomConstraints);
1087 2 : }
1088 :
1089 4 : ZoomConstraints(const ZoomConstraints& other)
1090 4 : : mAllowZoom(other.mAllowZoom)
1091 4 : , mAllowDoubleTapZoom(other.mAllowDoubleTapZoom)
1092 : , mMinZoom(other.mMinZoom)
1093 8 : , mMaxZoom(other.mMaxZoom)
1094 : {
1095 4 : MOZ_COUNT_CTOR(ZoomConstraints);
1096 4 : }
1097 :
1098 6 : ~ZoomConstraints()
1099 6 : {
1100 6 : MOZ_COUNT_DTOR(ZoomConstraints);
1101 6 : }
1102 :
1103 : bool operator==(const ZoomConstraints& other) const
1104 : {
1105 : return mAllowZoom == other.mAllowZoom
1106 : && mAllowDoubleTapZoom == other.mAllowDoubleTapZoom
1107 : && mMinZoom == other.mMinZoom
1108 : && mMaxZoom == other.mMaxZoom;
1109 : }
1110 :
1111 : bool operator!=(const ZoomConstraints& other) const
1112 : {
1113 : return !(*this == other);
1114 : }
1115 : };
1116 :
1117 29 : struct ScrollableLayerGuidHash
1118 : {
1119 42 : std::size_t operator()(const ScrollableLayerGuid& Guid) const
1120 : {
1121 42 : return Guid.Hash();
1122 : }
1123 : };
1124 :
1125 :
1126 : typedef Maybe<ZoomConstraints> MaybeZoomConstraints;
1127 :
1128 : } // namespace layers
1129 : } // namespace mozilla
1130 :
1131 : #endif /* GFX_FRAMEMETRICS_H */
|