mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 1055760 - Add a LayerMetricsWrapper and fix up APZCTreeManager FrameMetrics accessing. r=botond,BenWa
This commit is contained in:
parent
23cccb3b33
commit
4e8832c9dd
@ -71,6 +71,7 @@ public:
|
||||
static const ViewID NULL_SCROLL_ID; // This container layer does not scroll.
|
||||
static const ViewID START_SCROLL_ID = 2; // This is the ID that scrolling subframes
|
||||
// will begin at.
|
||||
static const FrameMetrics sNullMetrics; // We often need an empty metrics
|
||||
|
||||
FrameMetrics()
|
||||
: mCompositionBounds(0, 0, 0, 0)
|
||||
|
299
gfx/layers/LayerMetricsWrapper.h
Normal file
299
gfx/layers/LayerMetricsWrapper.h
Normal file
@ -0,0 +1,299 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* 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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef GFX_LAYERMETRICSWRAPPER_H
|
||||
#define GFX_LAYERMETRICSWRAPPER_H
|
||||
|
||||
#include "Layers.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
/**
|
||||
* A wrapper class around a target Layer with that allows user code to
|
||||
* walk through the FrameMetrics objects on the layer the same way it
|
||||
* would walk through a ContainerLayer hierarchy. Consider the following
|
||||
* layer tree:
|
||||
*
|
||||
* +---+
|
||||
* | A |
|
||||
* +---+
|
||||
* / | \
|
||||
* / | \
|
||||
* / | \
|
||||
* +---+ +-----+ +---+
|
||||
* | B | | C | | D |
|
||||
* +---+ +-----+ +---+
|
||||
* | FMn |
|
||||
* | . |
|
||||
* | . |
|
||||
* | . |
|
||||
* | FM1 |
|
||||
* | FM0 |
|
||||
* +-----+
|
||||
* / \
|
||||
* / \
|
||||
* +---+ +---+
|
||||
* | E | | F |
|
||||
* +---+ +---+
|
||||
*
|
||||
* In this layer tree, there are six layers with A being the root and B,D,E,F
|
||||
* being leaf nodes. Layer C is in the middle and has n+1 FrameMetrics, labelled
|
||||
* FM0...FMn. FM0 is the FrameMetrics you get by calling c->GetFrameMetrics(0)
|
||||
* and FMn is the FrameMetrics you can obtain by calling
|
||||
* c->GetFrameMetrics(c->GetFrameMetricsCount() - 1). This layer tree is
|
||||
* conceptually equivalent to this one below:
|
||||
*
|
||||
* +---+
|
||||
* | A |
|
||||
* +---+
|
||||
* / | \
|
||||
* / | \
|
||||
* / | \
|
||||
* +---+ +-----+ +---+
|
||||
* | B | | Cn | | D |
|
||||
* +---+ +-----+ +---+
|
||||
* |
|
||||
* .
|
||||
* .
|
||||
* .
|
||||
* |
|
||||
* +-----+
|
||||
* | C1 |
|
||||
* +-----+
|
||||
* |
|
||||
* +-----+
|
||||
* | C0 |
|
||||
* +-----+
|
||||
* / \
|
||||
* / \
|
||||
* +---+ +---+
|
||||
* | E | | F |
|
||||
* +---+ +---+
|
||||
*
|
||||
* In this layer tree, the layer C has been expanded into a stack of container
|
||||
* layers C1...Cn, where C1 has FrameMetrics FM1 and Cn has FrameMetrics Fn.
|
||||
* Although in this example C (in the first layer tree) and C0 (in the second
|
||||
* layer tree) are both ContainerLayers (because they have children), they
|
||||
* do not have to be. They may just be ThebesLayers or ColorLayers, for example,
|
||||
* which do not have any children. However, the type of C will always be the
|
||||
* same as the type of C0.
|
||||
*
|
||||
* The LayerMetricsWrapper class allows client code to treat the first layer
|
||||
* tree as though it were the second. That is, instead of client code having
|
||||
* to iterate through the FrameMetrics objects directly, it can use a
|
||||
* LayerMetricsWrapper to encapsulate that aspect of the layer tree and just
|
||||
* walk the tree as if it were a stack of ContainerLayers.
|
||||
*
|
||||
* The functions on this class do different things depending on which
|
||||
* simulated ContainerLayer is being wrapped. For example, if the
|
||||
* LayerMetricsWrapper is pretending to be C0, the GetNextSibling() function
|
||||
* will return null even though the underlying layer C does actually have
|
||||
* a next sibling. The LayerMetricsWrapper pretending to be Cn will return
|
||||
* D as the next sibling.
|
||||
*
|
||||
* Implementation notes:
|
||||
*
|
||||
* The AtTopLayer() and AtBottomLayer() functions in this class refer to
|
||||
* Cn and C0 in the second layer tree above; that is, they are predicates
|
||||
* to test if the LayerMetricsWrapper is simulating the topmost or bottommost
|
||||
* layer, as those will have special behaviour.
|
||||
*
|
||||
* It is possible to wrap a nullptr in a LayerMetricsWrapper, in which case
|
||||
* the IsValid() function will return false. This is required to allow
|
||||
* LayerMetricsWrapper to be a MOZ_STACK_CLASS (desirable because it is used
|
||||
* in loops and recursion).
|
||||
*
|
||||
* This class purposely does not expose the wrapped layer directly to avoid
|
||||
* user code from accidentally calling functions directly on it. Instead
|
||||
* any necessary functions should be wrapped in this class. It does expose
|
||||
* the wrapped layer as a void* for printf purposes.
|
||||
*
|
||||
* The implementation may look like it special-cases mIndex == 0 and/or
|
||||
* GetFrameMetricsCount() == 0. This is an artifact of the fact that both
|
||||
* mIndex and GetFrameMetricsCount() are uint32_t and GetFrameMetricsCount()
|
||||
* can return 0 but mIndex cannot store -1. This seems better than the
|
||||
* alternative of making mIndex a int32_t that can store -1, but then having
|
||||
* to cast to uint32_t all over the place.
|
||||
*/
|
||||
class MOZ_STACK_CLASS LayerMetricsWrapper {
|
||||
public:
|
||||
LayerMetricsWrapper()
|
||||
: mLayer(nullptr)
|
||||
, mIndex(0)
|
||||
{
|
||||
}
|
||||
|
||||
explicit LayerMetricsWrapper(Layer* aRoot)
|
||||
: mLayer(aRoot)
|
||||
, mIndex(0)
|
||||
{
|
||||
if (!mLayer) {
|
||||
return;
|
||||
}
|
||||
|
||||
mIndex = mLayer->GetFrameMetricsCount();
|
||||
if (mIndex > 0) {
|
||||
mIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
explicit LayerMetricsWrapper(Layer* aLayer, uint32_t aMetricsIndex)
|
||||
: mLayer(aLayer)
|
||||
, mIndex(aMetricsIndex)
|
||||
{
|
||||
MOZ_ASSERT(mLayer);
|
||||
MOZ_ASSERT(mIndex == 0 || mIndex < mLayer->GetFrameMetricsCount());
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return mLayer != nullptr;
|
||||
}
|
||||
|
||||
MOZ_EXPLICIT_CONVERSION operator bool() const
|
||||
{
|
||||
return IsValid();
|
||||
}
|
||||
|
||||
LayerMetricsWrapper GetLastChild() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
if (!AtBottomLayer()) {
|
||||
return LayerMetricsWrapper(mLayer, mIndex - 1);
|
||||
}
|
||||
return LayerMetricsWrapper(mLayer->GetLastChild());
|
||||
}
|
||||
|
||||
LayerMetricsWrapper GetPrevSibling() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
if (AtTopLayer()) {
|
||||
return LayerMetricsWrapper(mLayer->GetPrevSibling());
|
||||
}
|
||||
return LayerMetricsWrapper(nullptr);
|
||||
}
|
||||
|
||||
const FrameMetrics& Metrics() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
if (mIndex >= mLayer->GetFrameMetricsCount()) {
|
||||
return FrameMetrics::sNullMetrics;
|
||||
}
|
||||
return mLayer->GetFrameMetrics(mIndex);
|
||||
}
|
||||
|
||||
AsyncPanZoomController* GetApzc() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
if (mIndex >= mLayer->GetFrameMetricsCount()) {
|
||||
return nullptr;
|
||||
}
|
||||
return mLayer->GetAsyncPanZoomController(mIndex);
|
||||
}
|
||||
|
||||
void SetApzc(AsyncPanZoomController* aApzc) const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
if (mLayer->GetFrameMetricsCount() == 0) {
|
||||
MOZ_ASSERT(mIndex == 0);
|
||||
MOZ_ASSERT(aApzc == nullptr);
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mIndex < mLayer->GetFrameMetricsCount());
|
||||
mLayer->SetAsyncPanZoomController(mIndex, aApzc);
|
||||
}
|
||||
|
||||
const char* Name() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
if (AtBottomLayer()) {
|
||||
return mLayer->Name();
|
||||
}
|
||||
return "DummyContainerLayer";
|
||||
}
|
||||
|
||||
gfx::Matrix4x4 GetTransform() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
if (AtBottomLayer()) {
|
||||
return mLayer->GetTransform();
|
||||
}
|
||||
return gfx::Matrix4x4();
|
||||
}
|
||||
|
||||
RefLayer* AsRefLayer() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
if (AtBottomLayer()) {
|
||||
return mLayer->AsRefLayer();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsIntRegion GetVisibleRegion() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
if (AtBottomLayer()) {
|
||||
return mLayer->GetVisibleRegion();
|
||||
}
|
||||
nsIntRegion region = mLayer->GetVisibleRegion();
|
||||
region.Transform(gfx::To3DMatrix(mLayer->GetTransform()));
|
||||
return region;
|
||||
}
|
||||
|
||||
const nsIntRect* GetClipRect() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
return mLayer->GetClipRect();
|
||||
}
|
||||
|
||||
const std::string& GetContentDescription() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
return mLayer->GetContentDescription();
|
||||
}
|
||||
|
||||
// Expose an opaque pointer to the layer. Mostly used for printf
|
||||
// purposes. This is not intended to be a general-purpose accessor
|
||||
// for the underlying layer.
|
||||
const void* GetLayer() const
|
||||
{
|
||||
MOZ_ASSERT(IsValid());
|
||||
|
||||
return (void*)mLayer;
|
||||
}
|
||||
|
||||
private:
|
||||
bool AtBottomLayer() const
|
||||
{
|
||||
return mIndex == 0;
|
||||
}
|
||||
|
||||
bool AtTopLayer() const
|
||||
{
|
||||
return mLayer->GetFrameMetricsCount() == 0 || mIndex == mLayer->GetFrameMetricsCount() - 1;
|
||||
}
|
||||
|
||||
private:
|
||||
Layer* mLayer;
|
||||
uint32_t mIndex;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* GFX_LAYERMETRICSWRAPPER_H */
|
@ -47,6 +47,7 @@ FILEOrDefault(FILE* aFile)
|
||||
|
||||
typedef FrameMetrics::ViewID ViewID;
|
||||
const ViewID FrameMetrics::NULL_SCROLL_ID = 0;
|
||||
const FrameMetrics FrameMetrics::sNullMetrics;
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
|
||||
|
@ -841,7 +841,8 @@ public:
|
||||
* nested scrolling subdocuments. In general a Layer having multiple
|
||||
* FrameMetrics objects is conceptually equivalent to having a stack
|
||||
* of ContainerLayers that have been flattened into this Layer.
|
||||
* (A pointer to additional documentation will arrive in a future patch.)
|
||||
* See the documentation in LayerMetricsWrapper.h for a more detailed
|
||||
* explanation of this conceptual equivalence.
|
||||
*
|
||||
* Note also that there is actually a many-to-many relationship between
|
||||
* Layers and FrameMetrics, because multiple Layers may have identical
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "mozilla/gfx/Point.h" // for Point
|
||||
#include "mozilla/layers/AsyncCompositionManager.h" // for ViewTransform
|
||||
#include "mozilla/layers/AsyncPanZoomController.h"
|
||||
#include "mozilla/layers/LayerMetricsWrapper.h"
|
||||
#include "mozilla/MouseEvents.h"
|
||||
#include "mozilla/mozalloc.h" // for operator new
|
||||
#include "mozilla/TouchEvents.h"
|
||||
@ -160,7 +161,8 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
|
||||
|
||||
if (aRoot) {
|
||||
mApzcTreeLog << "[start]\n";
|
||||
UpdatePanZoomControllerTree(state, aRoot,
|
||||
LayerMetricsWrapper root(aRoot);
|
||||
UpdatePanZoomControllerTree(state, root,
|
||||
// aCompositor is null in gtest scenarios
|
||||
aCompositor ? aCompositor->RootLayerTreeId() : 0,
|
||||
Matrix4x4(), nullptr, nullptr, nsIntRegion());
|
||||
@ -205,7 +207,7 @@ ComputeTouchSensitiveRegion(GeckoContentController* aController,
|
||||
}
|
||||
|
||||
AsyncPanZoomController*
|
||||
APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer,
|
||||
APZCTreeManager::PrepareAPZCForLayer(const LayerMetricsWrapper& aLayer,
|
||||
const FrameMetrics& aMetrics,
|
||||
uint64_t aLayersId,
|
||||
const gfx::Matrix4x4& aAncestorTransform,
|
||||
@ -237,13 +239,13 @@ APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer,
|
||||
if (!insertResult.second) {
|
||||
apzc = insertResult.first->second;
|
||||
}
|
||||
APZCTM_LOG("Found APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer, guid.mLayersId, guid.mScrollId);
|
||||
APZCTM_LOG("Found APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer.GetLayer(), guid.mLayersId, guid.mScrollId);
|
||||
|
||||
// If we haven't encountered a layer already with the same metrics, then we need to
|
||||
// do the full reuse-or-make-an-APZC algorithm, which is contained inside the block
|
||||
// below.
|
||||
if (apzc == nullptr) {
|
||||
apzc = aLayer->GetAsyncPanZoomController();
|
||||
apzc = aLayer.GetApzc();
|
||||
|
||||
// If the content represented by the scrollable layer has changed (which may
|
||||
// be possible because of DLBI heuristics) then we don't want to keep using
|
||||
@ -290,7 +292,7 @@ APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer,
|
||||
apzc->SetPrevSibling(nullptr);
|
||||
apzc->SetLastChild(nullptr);
|
||||
}
|
||||
APZCTM_LOG("Using APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer, aLayersId, aMetrics.GetScrollId());
|
||||
APZCTM_LOG("Using APZC %p for layer %p with identifiers %lld %lld\n", apzc, aLayer.GetLayer(), aLayersId, aMetrics.GetScrollId());
|
||||
|
||||
apzc->NotifyLayersUpdated(aMetrics,
|
||||
aState.mIsFirstPaint && (aLayersId == aState.mOriginatingLayersId));
|
||||
@ -303,9 +305,9 @@ APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer,
|
||||
mApzcTreeLog << "APZC " << guid
|
||||
<< "\tcb=" << aMetrics.mCompositionBounds
|
||||
<< "\tsr=" << aMetrics.mScrollableRect
|
||||
<< (aLayer->GetVisibleRegion().IsEmpty() ? "\tscrollinfo" : "")
|
||||
<< (aLayer.GetVisibleRegion().IsEmpty() ? "\tscrollinfo" : "")
|
||||
<< (apzc->HasScrollgrab() ? "\tscrollgrab" : "")
|
||||
<< "\t" << aLayer->GetContentDescription();
|
||||
<< "\t" << aLayer.GetContentDescription();
|
||||
|
||||
// Bind the APZC instance into the tree of APZCs
|
||||
if (aNextSibling) {
|
||||
@ -376,7 +378,8 @@ APZCTreeManager::PrepareAPZCForLayer(const Layer* aLayer,
|
||||
|
||||
AsyncPanZoomController*
|
||||
APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState,
|
||||
Layer* aLayer, uint64_t aLayersId,
|
||||
const LayerMetricsWrapper& aLayer,
|
||||
uint64_t aLayersId,
|
||||
const gfx::Matrix4x4& aAncestorTransform,
|
||||
AsyncPanZoomController* aParent,
|
||||
AsyncPanZoomController* aNextSibling,
|
||||
@ -384,12 +387,12 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState,
|
||||
{
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
|
||||
mApzcTreeLog << aLayer->Name() << '\t';
|
||||
mApzcTreeLog << aLayer.Name() << '\t';
|
||||
|
||||
AsyncPanZoomController* apzc = PrepareAPZCForLayer(aLayer,
|
||||
aLayer->GetFrameMetrics(), aLayersId, aAncestorTransform,
|
||||
aLayer.Metrics(), aLayersId, aAncestorTransform,
|
||||
aObscured, aParent, aNextSibling, aState);
|
||||
aLayer->SetAsyncPanZoomController(apzc);
|
||||
aLayer.SetApzc(apzc);
|
||||
|
||||
mApzcTreeLog << '\n';
|
||||
|
||||
@ -400,13 +403,13 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState,
|
||||
// transform to layer L when we recurse into the children below. If we are at a layer
|
||||
// with an APZC, such as P, then we reset the ancestorTransform to just PC, to start
|
||||
// the new accumulation as we go down.
|
||||
Matrix4x4 transform = aLayer->GetTransform();
|
||||
Matrix4x4 transform = aLayer.GetTransform();
|
||||
Matrix4x4 ancestorTransform = transform;
|
||||
if (!apzc) {
|
||||
ancestorTransform = ancestorTransform * aAncestorTransform;
|
||||
}
|
||||
|
||||
uint64_t childLayersId = (aLayer->AsRefLayer() ? aLayer->AsRefLayer()->GetReferentId() : aLayersId);
|
||||
uint64_t childLayersId = (aLayer.AsRefLayer() ? aLayer.AsRefLayer()->GetReferentId() : aLayersId);
|
||||
|
||||
nsIntRegion obscured;
|
||||
if (aLayersId == childLayersId) {
|
||||
@ -428,7 +431,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState,
|
||||
// If there's no APZC at this level, any APZCs for our child layers will
|
||||
// have our siblings as siblings.
|
||||
AsyncPanZoomController* next = apzc ? nullptr : aNextSibling;
|
||||
for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) {
|
||||
for (LayerMetricsWrapper child = aLayer.GetLastChild(); child; child = child.GetPrevSibling()) {
|
||||
gfx::TreeAutoIndent indent(mApzcTreeLog);
|
||||
next = UpdatePanZoomControllerTree(aState, child, childLayersId,
|
||||
ancestorTransform, aParent, next,
|
||||
@ -436,10 +439,10 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState,
|
||||
|
||||
// Each layer obscures its previous siblings, so we augment the obscured
|
||||
// region as we loop backwards through the children.
|
||||
nsIntRegion childRegion = child->GetVisibleRegion();
|
||||
childRegion.Transform(gfx::To3DMatrix(child->GetTransform()));
|
||||
if (child->GetClipRect()) {
|
||||
childRegion.AndWith(*child->GetClipRect());
|
||||
nsIntRegion childRegion = child.GetVisibleRegion();
|
||||
childRegion.Transform(gfx::To3DMatrix(child.GetTransform()));
|
||||
if (child.GetClipRect()) {
|
||||
childRegion.AndWith(*child.GetClipRect());
|
||||
}
|
||||
|
||||
obscured.OrWith(childRegion);
|
||||
|
@ -44,6 +44,7 @@ class AsyncPanZoomController;
|
||||
class CompositorParent;
|
||||
class APZPaintLogHelper;
|
||||
class OverscrollHandoffChain;
|
||||
class LayerMetricsWrapper;
|
||||
|
||||
/**
|
||||
* ****************** NOTE ON LOCK ORDERING IN APZ **************************
|
||||
@ -378,7 +379,7 @@ private:
|
||||
void UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc,
|
||||
const ZoomConstraints& aConstraints);
|
||||
|
||||
AsyncPanZoomController* PrepareAPZCForLayer(const Layer* aLayer,
|
||||
AsyncPanZoomController* PrepareAPZCForLayer(const LayerMetricsWrapper& aLayer,
|
||||
const FrameMetrics& aMetrics,
|
||||
uint64_t aLayersId,
|
||||
const gfx::Matrix4x4& aAncestorTransform,
|
||||
@ -397,7 +398,8 @@ private:
|
||||
* code.
|
||||
*/
|
||||
AsyncPanZoomController* UpdatePanZoomControllerTree(TreeBuildingState& aState,
|
||||
Layer* aLayer, uint64_t aLayersId,
|
||||
const LayerMetricsWrapper& aLayer,
|
||||
uint64_t aLayersId,
|
||||
const gfx::Matrix4x4& aAncestorTransform,
|
||||
AsyncPanZoomController* aParent,
|
||||
AsyncPanZoomController* aNextSibling,
|
||||
|
@ -163,6 +163,7 @@ EXPORTS.mozilla.layers += [
|
||||
'ipc/SharedBufferManagerParent.h',
|
||||
'ipc/SharedPlanarYCbCrImage.h',
|
||||
'ipc/SharedRGBImage.h',
|
||||
'LayerMetricsWrapper.h',
|
||||
'LayersTypes.h',
|
||||
'opengl/CompositingRenderTargetOGL.h',
|
||||
'opengl/CompositorOGL.h',
|
||||
|
Loading…
Reference in New Issue
Block a user