Bug 539356 - Fix mActiveScrolledRootOffset to be offset to the reference frame. r=mattwoodrow

This commit is contained in:
Robert O'Callahan 2012-09-28 01:07:40 +12:00
parent 4f2493bc70
commit e2e5bf0685
2 changed files with 39 additions and 81 deletions

View File

@ -138,16 +138,20 @@ public:
LayerManager* aManager,
FrameLayerBuilder* aLayerBuilder,
nsIFrame* aContainerFrame,
nsDisplayItem* aContainerItem,
ContainerLayer* aContainerLayer,
const FrameLayerBuilder::ContainerParameters& aParameters) :
mBuilder(aBuilder), mManager(aManager),
mLayerBuilder(aLayerBuilder),
mContainerFrame(aContainerFrame), mContainerLayer(aContainerLayer),
mContainerFrame(aContainerFrame),
mContainerLayer(aContainerLayer),
mParameters(aParameters),
mNextFreeRecycledThebesLayer(0)
{
nsPresContext* presContext = aContainerFrame->PresContext();
mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
mContainerReferenceFrame = aContainerItem ? aContainerItem->ReferenceFrame() :
mBuilder->FindReferenceFrameFor(mContainerFrame);
// When AllowResidualTranslation is false, display items will be drawn
// scaled with a translation by integer pixels, so we know how the snapping
// will work.
@ -306,7 +310,7 @@ protected:
* be non-null; all content in a ThebesLayer must have the same
* active scrolled root.
*/
const nsIFrame* mActiveScrolledRoot;
const nsIFrame* mActiveScrolledRoot;
ThebesLayer* mLayer;
/**
* If mIsSolidColorInVisibleRegion is true, this is the color of the visible
@ -367,7 +371,9 @@ protected:
* a recycled ThebesLayer, and sets up the transform on the ThebesLayer
* to account for scrolling.
*/
already_AddRefed<ThebesLayer> CreateOrRecycleThebesLayer(const nsIFrame* aActiveScrolledRoot, const nsIFrame *aReferenceFrame);
already_AddRefed<ThebesLayer> CreateOrRecycleThebesLayer(const nsIFrame* aActiveScrolledRoot,
const nsIFrame *aReferenceFrame,
const nsPoint& aTopLeft);
/**
* Grab the next recyclable ColorLayer, or create one if there are no
* more recyclable ColorLayers.
@ -432,7 +438,8 @@ protected:
const nsIntRect& aVisibleRect,
const nsIntRect& aDrawRect,
const FrameLayerBuilder::Clip& aClip,
const nsIFrame* aActiveScrolledRoot);
const nsIFrame* aActiveScrolledRoot,
const nsPoint& aTopLeft);
ThebesLayerData* GetTopThebesLayerData()
{
return mThebesLayerDataStack.IsEmpty() ? nullptr
@ -455,6 +462,7 @@ protected:
LayerManager* mManager;
FrameLayerBuilder* mLayerBuilder;
nsIFrame* mContainerFrame;
const nsIFrame* mContainerReferenceFrame;
ContainerLayer* mContainerLayer;
FrameLayerBuilder::ContainerParameters mParameters;
/**
@ -535,8 +543,9 @@ public:
nsIntRegion mRegionToInvalidate;
// The result of GetPosition() for the active scrolled root of this layer
// for the previous and current paints respectively.
// The offset between the active scrolled root of this layer
// and the root of the container for the previous and current
// paints respectively.
nsPoint mLastActiveScrolledRootOrigin;
nsPoint mActiveScrolledRootOrigin;
@ -855,6 +864,7 @@ FrameLayerBuilder::RemoveFrameFromLayerManager(nsIFrame* aFrame,
}
}
}
sDestroyedFrame = aFrame;
data->mFramesWithLayers.RemoveEntry(aFrame);
sDestroyedFrame = NULL;
@ -1361,7 +1371,9 @@ InvalidateEntireThebesLayer(ThebesLayer* aLayer, const nsIFrame* aActiveScrolled
}
already_AddRefed<ThebesLayer>
ContainerState::CreateOrRecycleThebesLayer(const nsIFrame* aActiveScrolledRoot, const nsIFrame* aReferenceFrame)
ContainerState::CreateOrRecycleThebesLayer(const nsIFrame* aActiveScrolledRoot,
const nsIFrame* aReferenceFrame,
const nsPoint& aTopLeft)
{
// We need a new thebes layer
nsRefPtr<ThebesLayer> layer;
@ -1423,7 +1435,7 @@ ContainerState::CreateOrRecycleThebesLayer(const nsIFrame* aActiveScrolledRoot,
data->mXScale = mParameters.mXScale;
data->mYScale = mParameters.mYScale;
data->mLastActiveScrolledRootOrigin = data->mActiveScrolledRootOrigin;
data->mActiveScrolledRootOrigin = aActiveScrolledRoot->GetPosition();
data->mActiveScrolledRootOrigin = aTopLeft;
data->mAppUnitsPerDevPixel = mAppUnitsPerDevPixel;
layer->SetAllowResidualTranslation(mParameters.AllowResidualTranslation());
@ -1513,30 +1525,6 @@ RestrictVisibleRegionForLayer(Layer* aLayer, const nsIntRect& aItemVisible)
}
}
static void
SetVisibleRegionForLayer(Layer* aLayer, const nsIntRect& aItemVisible, const nsIntRect& aChildBounds)
{
gfx3DMatrix transform = aLayer->GetTransform();
// if 'transform' is not invertible, then nothing will be displayed
// for the layer, so it doesn't really matter what we do here
gfxRect itemVisible(aItemVisible.x, aItemVisible.y, aItemVisible.width, aItemVisible.height);
gfxRect layerVisible = transform.Inverse().ProjectRectBounds(itemVisible);
layerVisible.RoundOut();
nsIntRect visibleRect;
if (!gfxUtils::GfxRectToIntRect(layerVisible, &visibleRect))
return;
nsIntRegion rgn = aChildBounds;
if (!visibleRect.Contains(aChildBounds)) {
rgn.And(rgn, visibleRect);
aLayer->SetVisibleRegion(rgn);
} else {
aLayer->SetVisibleRegion(aChildBounds);
}
}
nscolor
ContainerState::FindOpaqueBackgroundColorFor(int32_t aThebesLayerIndex)
{
@ -1917,7 +1905,8 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
const nsIntRect& aVisibleRect,
const nsIntRect& aDrawRect,
const FrameLayerBuilder::Clip& aClip,
const nsIFrame* aActiveScrolledRoot)
const nsIFrame* aActiveScrolledRoot,
const nsPoint& aTopLeft)
{
int32_t i;
int32_t lowestUsableLayerWithScrolledRoot = -1;
@ -1957,7 +1946,7 @@ ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
nsRefPtr<ThebesLayer> layer;
ThebesLayerData* thebesLayerData = nullptr;
if (lowestUsableLayerWithScrolledRoot < 0) {
layer = CreateOrRecycleThebesLayer(aActiveScrolledRoot, aItem->ReferenceFrame());
layer = CreateOrRecycleThebesLayer(aActiveScrolledRoot, aItem->ReferenceFrame(), aTopLeft);
NS_ASSERTION(!mNewChildLayers.Contains(layer), "Layer already in list???");
mNewChildLayers.AppendElement(layer);
@ -2096,18 +2085,20 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
bool isFixed;
bool forceInactive;
const nsIFrame* activeScrolledRoot;
nsPoint topLeft;
if (aFlags & NO_COMPONENT_ALPHA) {
// When NO_COMPONENT_ALPHA is set, items will be flattened onto the
// reference frame. In this case, force the active scrolled root to
// that frame.
forceInactive = true;
activeScrolledRoot = mBuilder->FindReferenceFrameFor(mContainerFrame);
activeScrolledRoot = mContainerReferenceFrame;
topLeft = nsPoint(0, 0);
isFixed = mBuilder->IsFixedItem(item, nullptr, activeScrolledRoot);
} else {
forceInactive = false;
isFixed = mBuilder->IsFixedItem(item, &activeScrolledRoot);
topLeft = activeScrolledRoot->GetOffsetToCrossDoc(mContainerReferenceFrame);
}
nsPoint topLeft = activeScrolledRoot->GetPosition();
// Assign the item to a layer
if (layerState == LAYER_ACTIVE_FORCE ||
@ -2200,7 +2191,7 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
} else {
ThebesLayerData* data =
FindThebesLayerFor(item, itemVisibleRect, itemDrawRect, aClip,
activeScrolledRoot);
activeScrolledRoot, topLeft);
data->mLayer->SetIsFixedPosition(isFixed);
@ -2233,10 +2224,7 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem,
Layer* oldLayer = mLayerBuilder->GetOldLayerFor(aItem, &oldGeometry, &oldClip);
if (aNewLayer != oldLayer && oldLayer) {
// The item has changed layers.
// Invalidate the bounds in the old layer and new layer.
// The bounds might have changed, but we assume that any difference
// in the bounds will have been invalidated for all Thebes layers
// in the container via regular frame invalidation.
// Invalidate the old bounds in the old layer and new bounds in the new layer.
ThebesLayer* t = oldLayer->AsThebesLayer();
if (t) {
// Note that whenever the layer's scale changes, we invalidate the whole thing,
@ -2754,36 +2742,6 @@ FrameLayerBuilder::RestoreThebesLayerItemEntries(ThebesLayerItemsEntry* aEntry,
return PL_DHASH_NEXT;
}
static nsDisplayTransform* FindTransformForContainerFrame(nsIFrame* aContainerFrame,
nsDisplayItem* aContainerItem)
{
if (!aContainerFrame->IsTransformed() ||
aContainerItem->GetType() == nsDisplayItem::TYPE_TRANSFORM)
return nullptr;
nsTArray<nsDisplayItem*> queue;
queue.AppendElement(aContainerItem);
while (queue.Length()) {
nsDisplayItem* item = queue[queue.Length() - 1];
queue.RemoveElementAt(queue.Length() - 1);
if (item->GetType() == nsDisplayItem::TYPE_TRANSFORM) {
return static_cast<nsDisplayTransform*>(item);
}
if (item->GetList()) {
for (nsDisplayItem* child = item->GetList()->GetBottom(); child;
child = child->GetAbove()) {
if (child->GetUnderlyingFrame() == aContainerFrame) {
queue.AppendElement(child);
}
}
}
}
return nullptr;
}
already_AddRefed<ContainerLayer>
FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
@ -2793,7 +2751,6 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
const ContainerParameters& aParameters,
const gfx3DMatrix* aTransform)
{
FrameProperties props = aContainerFrame->Properties();
uint32_t containerDisplayItemKey =
aContainerItem ? aContainerItem->GetPerFrameKey() : 0;
NS_ASSERTION(aContainerFrame, "Container display items here should have a frame");
@ -2904,7 +2861,8 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
(aManager->GetUserData(&gLayerManagerUserData));
while (true) {
ContainerState state(aBuilder, aManager, aManager->GetLayerBuilder(),
aContainerFrame, containerLayer, scaleParameters);
aContainerFrame, aContainerItem,
containerLayer, scaleParameters);
Clip clip;
state.ProcessDisplayItems(aChildren, clip, stateFlags);

View File

@ -64,9 +64,7 @@ public:
* The most important API in this class is BuildContainerLayerFor. This
* method takes a display list as input and constructs a ContainerLayer
* with child layers that render the contents of the display list. It
* also updates userdata for the retained layer manager, and
* DisplayItemDataProperty data for frames, to record the relationship
* between frames and layers.
* records the relationship between frames and layers.
*
* That data enables us to retain layer trees. When constructing a
* ContainerLayer, we first check to see if there's an existing
@ -85,7 +83,7 @@ public:
* FrameLayerBuilder sets up ThebesLayers so that 0,0 in the Thebes layer
* corresponds to the (pixel-snapped) top-left of the aActiveScrolledRoot.
* It sets up ContainerLayers so that 0,0 in the container layer
* corresponds to the snapped top-left of the display list reference frame.
* corresponds to the snapped top-left of the display item reference frame.
*
* When we construct a container layer, we know the transform that will be
* applied to the layer. If the transform scales the content, we can get
@ -266,6 +264,7 @@ public:
* @param aLayer Layer that the display item will be rendered into
* @param aItem Display item to be drawn.
* @param aLayerState What LayerState the item is using.
* @param aTopLeft offset from active scrolled root to reference frame
* @param aManager If the layer is in the LAYER_INACTIVE state,
* then this is the temporary layer manager to draw with.
*/
@ -282,6 +281,7 @@ public:
* aLayer, with aClipRect, where aContainerLayerFrame is the frame
* for the container layer this ThebesItem belongs to.
* aItem must have an underlying frame.
* @param aTopLeft offset from active scrolled root to reference frame
*/
void AddThebesDisplayItem(ThebesLayer* aLayer,
nsDisplayItem* aItem,
@ -574,8 +574,9 @@ protected:
/**
* We accumulate DisplayItemData elements in a hashtable during
* the paint process, and store them in the frame property only when
* paint is complete. This is the hashentry for that hashtable.
* the paint process, one per visible display item.
* There is one hashtable per layer manager, and one entry
* per frame. This is the hashentry for that hashtable.
*/
class DisplayItemDataEntry : public nsPtrHashKey<nsIFrame> {
public:
@ -640,8 +641,7 @@ protected:
/**
* A useful hashtable iteration function that removes the
* DisplayItemData property for the frame, clears its
* NS_FRAME_HAS_CONTAINER_LAYER bit and returns PL_DHASH_REMOVE.
* DisplayItemData property for the frame and returns PL_DHASH_REMOVE.
* aClosure is ignored.
*/
static PLDHashOperator RemoveDisplayItemDataForFrame(DisplayItemDataEntry* aEntry,