gecko-dev/layout/base/FrameLayerBuilder.cpp

6148 lines
231 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2012-05-21 11:12:37 +00:00
* 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/. */
#include "mozilla/DebugOnly.h"
#include "FrameLayerBuilder.h"
#include "mozilla/LookAndFeel.h"
#include "mozilla/Maybe.h"
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
#include "mozilla/gfx/Matrix.h"
#include "ActiveLayerTracker.h"
#include "BasicLayers.h"
#include "DisplayItemScrollClip.h"
#include "ImageContainer.h"
#include "ImageLayers.h"
#include "LayerTreeInvalidation.h"
#include "Layers.h"
#include "LayerUserData.h"
#include "MaskLayerImageCache.h"
#include "UnitTransforms.h"
#include "Units.h"
#include "gfx2DGlue.h"
#include "gfxEnv.h"
#include "gfxUtils.h"
#include "nsAutoPtr.h"
#include "nsAnimationManager.h"
#include "nsDisplayList.h"
#include "nsDocShell.h"
#include "nsIScrollableFrame.h"
#include "nsImageFrame.h"
#include "nsLayoutUtils.h"
#include "nsPresContext.h"
#include "nsPrintfCString.h"
#include "nsRenderingContext.h"
#include "nsSVGIntegrationUtils.h"
#include "nsTransitionManager.h"
#include "mozilla/LayerTimelineMarker.h"
#include "mozilla/EffectCompositor.h"
#include "mozilla/Move.h"
#include "mozilla/ReverseIterator.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/Tools.h"
#include "mozilla/layers/ShadowLayers.h"
#include "mozilla/layers/TextureClient.h"
#include "mozilla/layers/TextureWrapperImage.h"
#include "mozilla/Unused.h"
#include "GeckoProfiler.h"
#include "LayersLogging.h"
#include "gfxPrefs.h"
#include <algorithm>
using namespace mozilla::layers;
using namespace mozilla::gfx;
namespace mozilla {
class PaintedDisplayItemLayerUserData;
static nsTHashtable<nsPtrHashKey<FrameLayerBuilder::DisplayItemData>>* sAliveDisplayItemDatas;
/**
* The address of gPaintedDisplayItemLayerUserData is used as the user
* data key for PaintedLayers created by FrameLayerBuilder.
* It identifies PaintedLayers used to draw non-layer content, which are
* therefore eligible for recycling. We want display items to be able to
* create their own dedicated PaintedLayers in BuildLayer, if necessary,
* and we wouldn't want to accidentally recycle those.
* The user data is a PaintedDisplayItemLayerUserData.
*/
uint8_t gPaintedDisplayItemLayerUserData;
/**
* The address of gColorLayerUserData is used as the user
* data key for ColorLayers created by FrameLayerBuilder.
* The user data is null.
*/
uint8_t gColorLayerUserData;
/**
* The address of gImageLayerUserData is used as the user
* data key for ImageLayers created by FrameLayerBuilder.
* The user data is null.
*/
uint8_t gImageLayerUserData;
/**
* The address of gLayerManagerUserData is used as the user
* data key for retained LayerManagers managed by FrameLayerBuilder.
* The user data is a LayerManagerData.
*/
uint8_t gLayerManagerUserData;
/**
* The address of gMaskLayerUserData is used as the user
* data key for mask layers managed by FrameLayerBuilder.
* The user data is a MaskLayerUserData.
*/
uint8_t gMaskLayerUserData;
// a global cache of image containers used for mask layers
static MaskLayerImageCache* gMaskLayerImageCache = nullptr;
static inline MaskLayerImageCache* GetMaskLayerImageCache()
{
if (!gMaskLayerImageCache) {
gMaskLayerImageCache = new MaskLayerImageCache();
}
return gMaskLayerImageCache;
}
FrameLayerBuilder::FrameLayerBuilder()
: mRetainingManager(nullptr)
, mDetectedDOMModification(false)
, mInvalidateAllLayers(false)
, mInLayerTreeCompressionMode(false)
, mContainerLayerGeneration(0)
, mMaxContainerLayerGeneration(0)
{
MOZ_COUNT_CTOR(FrameLayerBuilder);
}
FrameLayerBuilder::~FrameLayerBuilder()
{
GetMaskLayerImageCache()->Sweep();
MOZ_COUNT_DTOR(FrameLayerBuilder);
}
FrameLayerBuilder::DisplayItemData::DisplayItemData(LayerManagerData* aParent, uint32_t aKey,
Layer* aLayer, nsIFrame* aFrame)
: mParent(aParent)
, mLayer(aLayer)
, mDisplayItemKey(aKey)
, mItem(nullptr)
, mUsed(true)
, mIsInvalid(false)
{
MOZ_COUNT_CTOR(FrameLayerBuilder::DisplayItemData);
if (!sAliveDisplayItemDatas) {
sAliveDisplayItemDatas = new nsTHashtable<nsPtrHashKey<FrameLayerBuilder::DisplayItemData>>();
}
MOZ_RELEASE_ASSERT(!sAliveDisplayItemDatas->Contains(this));
sAliveDisplayItemDatas->PutEntry(this);
MOZ_RELEASE_ASSERT(mLayer);
if (aFrame) {
AddFrame(aFrame);
}
}
void
FrameLayerBuilder::DisplayItemData::AddFrame(nsIFrame* aFrame)
{
MOZ_RELEASE_ASSERT(mLayer);
mFrameList.AppendElement(aFrame);
nsTArray<DisplayItemData*>* array =
aFrame->Properties().Get(FrameLayerBuilder::LayerManagerDataProperty());
if (!array) {
array = new nsTArray<DisplayItemData*>();
aFrame->Properties().Set(FrameLayerBuilder::LayerManagerDataProperty(), array);
}
array->AppendElement(this);
}
void
FrameLayerBuilder::DisplayItemData::RemoveFrame(nsIFrame* aFrame)
{
MOZ_RELEASE_ASSERT(mLayer);
bool result = mFrameList.RemoveElement(aFrame);
MOZ_RELEASE_ASSERT(result, "Can't remove a frame that wasn't added!");
nsTArray<DisplayItemData*>* array =
aFrame->Properties().Get(FrameLayerBuilder::LayerManagerDataProperty());
MOZ_RELEASE_ASSERT(array, "Must be already stored on the frame!");
array->RemoveElement(this);
}
void
FrameLayerBuilder::DisplayItemData::EndUpdate()
{
MOZ_RELEASE_ASSERT(mLayer);
MOZ_ASSERT(!mItem);
mIsInvalid = false;
mUsed = false;
}
void
FrameLayerBuilder::DisplayItemData::EndUpdate(nsAutoPtr<nsDisplayItemGeometry> aGeometry)
{
MOZ_RELEASE_ASSERT(mLayer);
MOZ_ASSERT(mItem);
MOZ_ASSERT(mGeometry || aGeometry);
if (aGeometry) {
mGeometry = aGeometry;
}
mClip = mItem->GetClip();
mFrameListChanges.Clear();
mItem = nullptr;
EndUpdate();
}
void
FrameLayerBuilder::DisplayItemData::BeginUpdate(Layer* aLayer, LayerState aState,
uint32_t aContainerLayerGeneration,
nsDisplayItem* aItem /* = nullptr */)
{
MOZ_RELEASE_ASSERT(mLayer);
MOZ_RELEASE_ASSERT(aLayer);
mLayer = aLayer;
mOptLayer = nullptr;
mInactiveManager = nullptr;
mLayerState = aState;
mContainerLayerGeneration = aContainerLayerGeneration;
mUsed = true;
if (aLayer->AsPaintedLayer()) {
mItem = aItem;
}
if (!aItem) {
return;
}
// We avoid adding or removing element unnecessarily
// since we have to modify userdata each time
AutoTArray<nsIFrame*, 4> copy(mFrameList);
if (!copy.RemoveElement(aItem->Frame())) {
AddFrame(aItem->Frame());
mFrameListChanges.AppendElement(aItem->Frame());
}
AutoTArray<nsIFrame*,4> mergedFrames;
aItem->GetMergedFrames(&mergedFrames);
for (uint32_t i = 0; i < mergedFrames.Length(); ++i) {
if (!copy.RemoveElement(mergedFrames[i])) {
AddFrame(mergedFrames[i]);
mFrameListChanges.AppendElement(mergedFrames[i]);
}
}
for (uint32_t i = 0; i < copy.Length(); i++) {
RemoveFrame(copy[i]);
mFrameListChanges.AppendElement(copy[i]);
}
}
static const nsIFrame* sDestroyedFrame = nullptr;
FrameLayerBuilder::DisplayItemData::~DisplayItemData()
{
MOZ_COUNT_DTOR(FrameLayerBuilder::DisplayItemData);
MOZ_RELEASE_ASSERT(mLayer);
for (uint32_t i = 0; i < mFrameList.Length(); i++) {
nsIFrame* frame = mFrameList[i];
if (frame == sDestroyedFrame) {
continue;
}
nsTArray<DisplayItemData*> *array =
reinterpret_cast<nsTArray<DisplayItemData*>*>(frame->Properties().Get(LayerManagerDataProperty()));
array->RemoveElement(this);
}
MOZ_RELEASE_ASSERT(sAliveDisplayItemDatas && sAliveDisplayItemDatas->Contains(this));
sAliveDisplayItemDatas->RemoveEntry(this);
if (sAliveDisplayItemDatas->Count() == 0) {
delete sAliveDisplayItemDatas;
sAliveDisplayItemDatas = nullptr;
}
}
void
FrameLayerBuilder::DisplayItemData::ClearAnimationCompositorState()
{
if (mDisplayItemKey != nsDisplayItem::TYPE_TRANSFORM &&
mDisplayItemKey != nsDisplayItem::TYPE_OPACITY) {
return;
}
for (nsIFrame* frame : mFrameList) {
nsCSSPropertyID prop = mDisplayItemKey == nsDisplayItem::TYPE_TRANSFORM ?
eCSSProperty_transform : eCSSProperty_opacity;
EffectCompositor::ClearIsRunningOnCompositor(frame, prop);
}
}
const nsTArray<nsIFrame*>&
FrameLayerBuilder::DisplayItemData::GetFrameListChanges()
{
return mFrameListChanges;
}
/**
* This is the userdata we associate with a layer manager.
*/
class LayerManagerData : public LayerUserData {
public:
explicit LayerManagerData(LayerManager *aManager)
: mLayerManager(aManager)
#ifdef DEBUG_DISPLAY_ITEM_DATA
, mParent(nullptr)
#endif
, mInvalidateAllLayers(false)
{
MOZ_COUNT_CTOR(LayerManagerData);
}
~LayerManagerData() {
MOZ_COUNT_DTOR(LayerManagerData);
}
#ifdef DEBUG_DISPLAY_ITEM_DATA
void Dump(const char *aPrefix = "") {
printf_stderr("%sLayerManagerData %p\n", aPrefix, this);
for (auto iter = mDisplayItems.Iter(); !iter.Done(); iter.Next()) {
FrameLayerBuilder::DisplayItemData* data = iter.Get()->GetKey();
nsAutoCString prefix;
prefix += aPrefix;
prefix += " ";
const char* layerState;
switch (data->mLayerState) {
case LAYER_NONE:
layerState = "LAYER_NONE"; break;
case LAYER_INACTIVE:
layerState = "LAYER_INACTIVE"; break;
case LAYER_ACTIVE:
layerState = "LAYER_ACTIVE"; break;
case LAYER_ACTIVE_FORCE:
layerState = "LAYER_ACTIVE_FORCE"; break;
case LAYER_ACTIVE_EMPTY:
layerState = "LAYER_ACTIVE_EMPTY"; break;
case LAYER_SVG_EFFECTS:
layerState = "LAYER_SVG_EFFECTS"; break;
}
uint32_t mask = (1 << nsDisplayItem::TYPE_BITS) - 1;
nsAutoCString str;
str += prefix;
str += nsPrintfCString("Frame %p ", data->mFrameList[0]);
str += nsDisplayItem::DisplayItemTypeName(static_cast<nsDisplayItem::Type>(data->mDisplayItemKey & mask));
if ((data->mDisplayItemKey >> nsDisplayItem::TYPE_BITS)) {
str += nsPrintfCString("(%i)", data->mDisplayItemKey >> nsDisplayItem::TYPE_BITS);
}
str += nsPrintfCString(", %s, Layer %p", layerState, data->mLayer.get());
if (data->mOptLayer) {
str += nsPrintfCString(", OptLayer %p", data->mOptLayer.get());
}
if (data->mInactiveManager) {
str += nsPrintfCString(", InactiveLayerManager %p", data->mInactiveManager.get());
}
str += "\n";
printf_stderr("%s", str.get());
if (data->mInactiveManager) {
prefix += " ";
printf_stderr("%sDumping inactive layer info:\n", prefix.get());
LayerManagerData* lmd = static_cast<LayerManagerData*>
(data->mInactiveManager->GetUserData(&gLayerManagerUserData));
lmd->Dump(prefix.get());
}
}
}
#endif
/**
* Tracks which frames have layers associated with them.
*/
LayerManager *mLayerManager;
#ifdef DEBUG_DISPLAY_ITEM_DATA
LayerManagerData *mParent;
#endif
nsTHashtable<nsRefPtrHashKey<FrameLayerBuilder::DisplayItemData> > mDisplayItems;
bool mInvalidateAllLayers;
};
/* static */ void
FrameLayerBuilder::DestroyDisplayItemDataFor(nsIFrame* aFrame)
{
FrameProperties props = aFrame->Properties();
props.Delete(LayerManagerDataProperty());
}
struct AssignedDisplayItem
{
AssignedDisplayItem(nsDisplayItem* aItem,
const DisplayItemClip& aClip,
LayerState aLayerState)
: mItem(aItem)
, mClip(aClip)
, mLayerState(aLayerState)
{}
nsDisplayItem* mItem;
DisplayItemClip mClip;
LayerState mLayerState;
};
/**
* We keep a stack of these to represent the PaintedLayers that are
* currently available to have display items added to.
* We use a stack here because as much as possible we want to
* assign display items to existing PaintedLayers, and to the lowest
* PaintedLayer in z-order. This reduces the number of layers and
* makes it more likely a display item will be rendered to an opaque
* layer, giving us the best chance of getting subpixel AA.
*/
class PaintedLayerData {
public:
PaintedLayerData() :
mAnimatedGeometryRoot(nullptr),
mScrollClip(nullptr),
mReferenceFrame(nullptr),
mLayer(nullptr),
mSolidColor(NS_RGBA(0, 0, 0, 0)),
mIsSolidColorInVisibleRegion(false),
mFontSmoothingBackgroundColor(NS_RGBA(0,0,0,0)),
mSingleItemFixedToViewport(false),
mNeedComponentAlpha(false),
mForceTransparentSurface(false),
mHideAllLayersBelow(false),
mOpaqueForAnimatedGeometryRootParent(false),
mDisableFlattening(false),
mBackfaceHidden(false),
mImage(nullptr),
mCommonClipCount(-1),
mNewChildLayersIndex(-1)
{}
#ifdef MOZ_DUMP_PAINTING
/**
* Keep track of important decisions for debugging.
*/
nsCString mLog;
#define FLB_LOG_PAINTED_LAYER_DECISION(pld, ...) \
if (gfxPrefs::LayersDumpDecision()) { \
pld->mLog.AppendPrintf("\t\t\t\t"); \
pld->mLog.AppendPrintf(__VA_ARGS__); \
}
#else
#define FLB_LOG_PAINTED_LAYER_DECISION(...)
#endif
/**
* Record that an item has been added to the PaintedLayer, so we
* need to update our regions.
* @param aVisibleRect the area of the item that's visible
* @param aSolidColor if non-null, the visible area of the item is
* a constant color given by *aSolidColor
*/
void Accumulate(ContainerState* aState,
nsDisplayItem* aItem,
const nsIntRegion& aClippedOpaqueRegion,
const nsIntRect& aVisibleRect,
const DisplayItemClip& aClip,
LayerState aLayerState);
AnimatedGeometryRoot* GetAnimatedGeometryRoot() { return mAnimatedGeometryRoot; }
/**
* A region including the horizontal pan, vertical pan, and no action regions.
*/
nsRegion CombinedTouchActionRegion();
/**
* Add the given hit regions to the hit regions to the hit retions for this
* PaintedLayer.
*/
void AccumulateEventRegions(ContainerState* aState, nsDisplayLayerEventRegions* aEventRegions);
/**
* If this represents only a nsDisplayImage, and the image type supports being
* optimized to an ImageLayer, returns true.
*/
bool CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
/**
* If this represents only a nsDisplayImage, and the image type supports being
* optimized to an ImageLayer, returns an ImageContainer for the underlying
* image if one is available.
*/
already_AddRefed<ImageContainer> GetContainerForImageLayer(nsDisplayListBuilder* aBuilder);
bool VisibleAboveRegionIntersects(const nsIntRegion& aRegion) const
{ return !mVisibleAboveRegion.Intersect(aRegion).IsEmpty(); }
bool VisibleRegionIntersects(const nsIntRegion& aRegion) const
{ return !mVisibleRegion.Intersect(aRegion).IsEmpty(); }
/**
* The region of visible content in the layer, relative to the
* container layer (which is at the snapped top-left of the display
* list reference frame).
*/
nsIntRegion mVisibleRegion;
/**
* The region of visible content in the layer that is opaque.
* Same coordinate system as mVisibleRegion.
*/
nsIntRegion mOpaqueRegion;
/**
* The definitely-hit region for this PaintedLayer.
*/
nsRegion mHitRegion;
/**
* The maybe-hit region for this PaintedLayer.
*/
nsRegion mMaybeHitRegion;
/**
* The dispatch-to-content hit region for this PaintedLayer.
*/
nsRegion mDispatchToContentHitRegion;
/**
* The region for this PaintedLayer that is sensitive to events
* but disallows panning and zooming. This is an approximation
* and any deviation from the true region will be part of the
* mDispatchToContentHitRegion.
*/
nsRegion mNoActionRegion;
/**
* The region for this PaintedLayer that is sensitive to events and
* allows horizontal panning but not zooming. This is an approximation
* and any deviation from the true region will be part of the
* mDispatchToContentHitRegion.
*/
nsRegion mHorizontalPanRegion;
/**
* The region for this PaintedLayer that is sensitive to events and
* allows vertical panning but not zooming. This is an approximation
* and any deviation from the true region will be part of the
* mDispatchToContentHitRegion.
*/
nsRegion mVerticalPanRegion;
/**
* Scaled versions of the bounds of mHitRegion and mMaybeHitRegion.
* We store these because FindPaintedLayerFor() needs to consume them
* in this form, and it's a hot code path so we don't want to scale
* them inside that function.
*/
nsIntRect mScaledHitRegionBounds;
nsIntRect mScaledMaybeHitRegionBounds;
/**
* The "active scrolled root" for all content in the layer. Must
* be non-null; all content in a PaintedLayer must have the same
* active scrolled root.
*/
AnimatedGeometryRoot* mAnimatedGeometryRoot;
/**
* The scroll clip for this layer.
*/
const DisplayItemScrollClip* mScrollClip;
/**
* The offset between mAnimatedGeometryRoot and the reference frame.
*/
nsPoint mAnimatedGeometryRootOffset;
/**
* If non-null, the frame from which we'll extract "fixed positioning"
* metadata for this layer. This can be a position:fixed frame or a viewport
* frame; the latter case is used for background-attachment:fixed content.
*/
const nsIFrame* mReferenceFrame;
PaintedLayer* mLayer;
/**
* If mIsSolidColorInVisibleRegion is true, this is the color of the visible
* region.
*/
nscolor mSolidColor;
/**
* True if every pixel in mVisibleRegion will have color mSolidColor.
*/
bool mIsSolidColorInVisibleRegion;
/**
* The target background color for smoothing fonts that are drawn on top of
* transparent parts of the layer.
*/
nscolor mFontSmoothingBackgroundColor;
/**
* True if the layer contains exactly one item that returned true for
* ShouldFixToViewport.
*/
bool mSingleItemFixedToViewport;
/**
* True if there is any text visible in the layer that's over
* transparent pixels in the layer.
*/
bool mNeedComponentAlpha;
/**
* Set if the layer should be treated as transparent, even if its entire
* area is covered by opaque display items. For example, this needs to
* be set if something is going to "punch holes" in the layer by clearing
* part of its surface.
*/
bool mForceTransparentSurface;
/**
* Set if all layers below this PaintedLayer should be hidden.
*/
bool mHideAllLayersBelow;
/**
* Set if the opaque region for this layer can be applied to the parent
* animated geometry root of this layer's animated geometry root.
* We set this when a PaintedLayer's animated geometry root is a scrollframe
* and the PaintedLayer completely fills the displayport of the scrollframe.
*/
bool mOpaqueForAnimatedGeometryRootParent;
/**
* Set if there is content in the layer that must avoid being flattened.
*/
bool mDisableFlattening;
/**
* Set if the backface of this region is hidden to the user.
* Content that backface is hidden should not be draw on the layer
* with visible backface.
*/
bool mBackfaceHidden;
/**
* Stores the pointer to the nsDisplayImage if we want to
* convert this to an ImageLayer.
*/
nsDisplayImageContainer* mImage;
/**
* Stores the clip that we need to apply to the image or, if there is no
* image, a clip for SOME item in the layer. There is no guarantee which
* item's clip will be stored here and mItemClip should not be used to clip
* the whole layer - only some part of the clip should be used, as determined
* by PaintedDisplayItemLayerUserData::GetCommonClipCount() - which may even be
* no part at all.
*/
DisplayItemClip mItemClip;
/**
* The first mCommonClipCount rounded rectangle clips are identical for
* all items in the layer.
* -1 if there are no items in the layer; must be >=0 by the time that this
* data is popped from the stack.
*/
int32_t mCommonClipCount;
/**
* Index of this layer in mNewChildLayers.
*/
int32_t mNewChildLayersIndex;
/*
* Updates mCommonClipCount by checking for rounded rect clips in common
* between the clip on a new item (aCurrentClip) and the common clips
* on items already in the layer (the first mCommonClipCount rounded rects
* in mItemClip).
*/
void UpdateCommonClipCount(const DisplayItemClip& aCurrentClip);
/**
* The union of all the bounds of the display items in this layer.
*/
nsIntRect mBounds;
/**
* The region of visible content above the layer and below the
* next PaintedLayerData currently in the stack, if any.
* This is a conservative approximation: it contains the true region.
*/
nsIntRegion mVisibleAboveRegion;
/**
* All the display items that have been assigned to this painted layer.
* These items get added by Accumulate().
*/
nsTArray<AssignedDisplayItem> mAssignedDisplayItems;
};
struct NewLayerEntry {
NewLayerEntry()
: mAnimatedGeometryRoot(nullptr)
, mScrollClip(nullptr)
, mLayerContentsVisibleRect(0, 0, -1, -1)
, mLayerState(LAYER_INACTIVE)
, mHideAllLayersBelow(false)
, mOpaqueForAnimatedGeometryRootParent(false)
, mPropagateComponentAlphaFlattening(true)
, mUntransformedVisibleRegion(false)
{}
// mLayer is null if the previous entry is for a PaintedLayer that hasn't
// been optimized to some other form (yet).
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<Layer> mLayer;
AnimatedGeometryRoot* mAnimatedGeometryRoot;
const DisplayItemScrollClip* mScrollClip;
// If non-null, this ScrollMetadata is set to the be the first ScrollMetadata
// on the layer.
UniquePtr<ScrollMetadata> mBaseScrollMetadata;
// The following are only used for retained layers (for occlusion
// culling of those layers). These regions are all relative to the
// container reference frame.
nsIntRegion mVisibleRegion;
nsIntRegion mOpaqueRegion;
// This rect is in the layer's own coordinate space. The computed visible
// region for the layer cannot extend beyond this rect.
nsIntRect mLayerContentsVisibleRect;
LayerState mLayerState;
bool mHideAllLayersBelow;
// When mOpaqueForAnimatedGeometryRootParent is true, the opaque region of
// this layer is opaque in the same position even subject to the animation of
// geometry of mAnimatedGeometryRoot. For example when mAnimatedGeometryRoot
// is a scrolled frame and the scrolled content is opaque everywhere in the
// displayport, we can set this flag.
// When this flag is set, we can treat this opaque region as covering
// content whose animated geometry root is the animated geometry root for
// mAnimatedGeometryRoot->GetParent().
bool mOpaqueForAnimatedGeometryRootParent;
// If true, then the content flags for this layer should contribute
// to our decision to flatten component alpha layers, false otherwise.
bool mPropagateComponentAlphaFlattening;
// mVisibleRegion is relative to the associated frame before
// transform.
bool mUntransformedVisibleRegion;
};
class PaintedLayerDataTree;
/**
* This is tree node type for PaintedLayerDataTree.
* Each node corresponds to a different animated geometry root, and contains
* a stack of PaintedLayerDatas, in bottom-to-top order.
* There is at most one node per animated geometry root. The ancestor and
* descendant relations in PaintedLayerDataTree tree mirror those in the frame
* tree.
* Each node can have clip that describes the potential extents that items in
* this node can cover. If mHasClip is false, it means that the node's contents
* can move anywhere.
* Testing against the clip instead of the node's actual contents has the
* advantage that the node's contents can move or animate without affecting
* content in other nodes. So we don't need to re-layerize during animations
* (sync or async), and during async animations everything is guaranteed to
* look correct.
* The contents of a node's PaintedLayerData stack all share the node's
* animated geometry root. The child nodes are on top of the PaintedLayerData
* stack, in z-order, and the clip rects of the child nodes are allowed to
* intersect with the visible region or visible above region of their parent
* node's PaintedLayerDatas.
*/
class PaintedLayerDataNode {
public:
PaintedLayerDataNode(PaintedLayerDataTree& aTree,
PaintedLayerDataNode* aParent,
AnimatedGeometryRoot* aAnimatedGeometryRoot);
~PaintedLayerDataNode();
AnimatedGeometryRoot* GetAnimatedGeometryRoot() const { return mAnimatedGeometryRoot; }
/**
* Whether this node's contents can potentially intersect aRect.
* aRect is in our tree's ContainerState's coordinate space.
*/
bool Intersects(const nsIntRect& aRect) const
{ return !mHasClip || mClipRect.Intersects(aRect); }
/**
* Create a PaintedLayerDataNode for aAnimatedGeometryRoot, add it to our
* children, and return it.
*/
PaintedLayerDataNode* AddChildNodeFor(AnimatedGeometryRoot* aAnimatedGeometryRoot);
/**
* Find a PaintedLayerData in our mPaintedLayerDataStack that aItem can be
* added to. Creates a new PaintedLayerData by calling
* aNewPaintedLayerCallback if necessary.
*/
template<typename NewPaintedLayerCallbackType>
PaintedLayerData* FindPaintedLayerFor(const nsIntRect& aVisibleRect,
bool aBackfaceHidden,
const DisplayItemScrollClip* aScrollClip,
NewPaintedLayerCallbackType aNewPaintedLayerCallback);
/**
* Find an opaque background color for aRegion. Pulls a color from the parent
* geometry root if appropriate, but only if that color is present underneath
* the whole clip of this node, so that this node's contents can animate or
* move (possibly async) without having to change the background color.
* @param aUnderIndex Searching will start in mPaintedLayerDataStack right
* below aUnderIndex.
*/
enum { ABOVE_TOP = -1 };
nscolor FindOpaqueBackgroundColor(const nsIntRegion& aRegion,
int32_t aUnderIndex = ABOVE_TOP) const;
/**
* Same as FindOpaqueBackgroundColor, but only returns a color if absolutely
* nothing is in between, so that it can be used for a layer that can move
* anywhere inside our clip.
*/
nscolor FindOpaqueBackgroundColorCoveringEverything() const;
/**
* Adds aRect to this node's top PaintedLayerData's mVisibleAboveRegion,
* or mVisibleAboveBackgroundRegion if mPaintedLayerDataStack is empty.
*/
void AddToVisibleAboveRegion(const nsIntRect& aRect);
/**
* Call this if all of our existing content can potentially be covered, so
* nothing can merge with it and all new content needs to create new items
* on top. This will finish all of our children and pop our whole
* mPaintedLayerDataStack.
*/
void SetAllDrawingAbove();
/**
* Finish this node: Finish all children, finish our PaintedLayer contents,
* and (if requested) adjust our parent's visible above region to include
* our clip.
*/
void Finish(bool aParentNeedsAccurateVisibleAboveRegion);
/**
* Finish any children that intersect aRect.
*/
void FinishChildrenIntersecting(const nsIntRect& aRect);
/**
* Finish all children.
*/
void FinishAllChildren() { FinishAllChildren(true); }
protected:
/**
* Finish the topmost item in mPaintedLayerDataStack and pop it from the
* stack.
*/
void PopPaintedLayerData();
/**
* Finish all items in mPaintedLayerDataStack and clear the stack.
*/
void PopAllPaintedLayerData();
/**
* Finish all of our child nodes, but don't touch mPaintedLayerDataStack.
*/
void FinishAllChildren(bool aThisNodeNeedsAccurateVisibleAboveRegion);
/**
* Pass off opaque background color searching to our parent node, if we have
* one.
*/
nscolor FindOpaqueBackgroundColorInParentNode() const;
PaintedLayerDataTree& mTree;
PaintedLayerDataNode* mParent;
AnimatedGeometryRoot* mAnimatedGeometryRoot;
/**
* Our contents: a PaintedLayerData stack and our child nodes.
*/
nsTArray<PaintedLayerData> mPaintedLayerDataStack;
/**
* UniquePtr is used here in the sense of "unique ownership", i.e. there is
* only one owner. Not in the sense of "this is the only pointer to the
* node": There are two other, non-owning, pointers to our child nodes: The
* node's respective children point to their parent node with their mParent
* pointer, and the tree keeps a map of animated geometry root to node in its
* mNodes member. These outside pointers are the reason that mChildren isn't
* just an nsTArray<PaintedLayerDataNode> (since the pointers would become
* invalid whenever the array expands its capacity).
*/
nsTArray<UniquePtr<PaintedLayerDataNode>> mChildren;
/**
* The region that's covered between our "background" and the bottom of
* mPaintedLayerDataStack. This is used to indicate whether we can pull
* a background color from our parent node. If mVisibleAboveBackgroundRegion
* should be considered infinite, mAllDrawingAboveBackground will be true and
* the value of mVisibleAboveBackgroundRegion will be meaningless.
*/
nsIntRegion mVisibleAboveBackgroundRegion;
/**
* Our clip, if we have any. If not, that means we can move anywhere, and
* mHasClip will be false and mClipRect will be meaningless.
*/
nsIntRect mClipRect;
bool mHasClip;
/**
* Whether mVisibleAboveBackgroundRegion should be considered infinite.
*/
bool mAllDrawingAboveBackground;
};
class ContainerState;
/**
* A tree of PaintedLayerDataNodes. At any point in time, the tree only
* contains nodes for animated geometry roots that new items can potentially
* merge into. Any time content is added on top that overlaps existing things
* in such a way that we no longer want to merge new items with some existing
* content, that existing content gets "finished".
* The public-facing methods of this class are FindPaintedLayerFor,
* AddingOwnLayer, and Finish. The other public methods are for
* PaintedLayerDataNode.
* The tree calls out to its containing ContainerState for some things.
* All coordinates / rects in the tree or the tree nodes are in the
* ContainerState's coordinate space, i.e. relative to the reference frame and
* in layer pixels.
* The clip rects of sibling nodes never overlap. This is ensured by finishing
* existing nodes before adding new ones, if this property were to be violated.
* The root tree node doesn't get finished until the ContainerState is
* finished.
* The tree's root node is always the root reference frame of the builder. We
* don't stop at the container state's mContainerAnimatedGeometryRoot because
* some of our contents can have animated geometry roots that are not
* descendants of the container's animated geometry root. Every animated
* geometry root we encounter for our contents needs to have a defined place in
* the tree.
*/
class PaintedLayerDataTree {
public:
PaintedLayerDataTree(ContainerState& aContainerState,
nscolor& aBackgroundColor)
: mContainerState(aContainerState)
, mContainerUniformBackgroundColor(aBackgroundColor)
{}
~PaintedLayerDataTree()
{
MOZ_ASSERT(!mRoot);
MOZ_ASSERT(mNodes.Count() == 0);
}
/**
* Notify our contents that some non-PaintedLayer content has been added.
* *aRect needs to be a rectangle that doesn't move with respect to
* aAnimatedGeometryRoot and that contains the added item.
* If aRect is null, the extents will be considered infinite.
* If aOutUniformBackgroundColor is non-null, it will be set to an opaque
* color that can be pulled into the background of the added content, or
* transparent if that is not possible.
*/
void AddingOwnLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot,
const nsIntRect* aRect,
nscolor* aOutUniformBackgroundColor);
/**
* Find a PaintedLayerData for aItem. This can either be an existing
* PaintedLayerData from inside a node in our tree, or a new one that gets
* created by a call out to aNewPaintedLayerCallback.
*/
template<typename NewPaintedLayerCallbackType>
PaintedLayerData* FindPaintedLayerFor(AnimatedGeometryRoot* aAnimatedGeometryRoot,
const DisplayItemScrollClip* aScrollClip,
const nsIntRect& aVisibleRect,
bool aBackfaceidden,
NewPaintedLayerCallbackType aNewPaintedLayerCallback);
/**
* Finish everything.
*/
void Finish();
/**
* Get the parent animated geometry root of aAnimatedGeometryRoot.
* That's either aAnimatedGeometryRoot's animated geometry root, or, if
* that's aAnimatedGeometryRoot itself, then it's the animated geometry
* root for aAnimatedGeometryRoot's cross-doc parent frame.
*/
AnimatedGeometryRoot* GetParentAnimatedGeometryRoot(AnimatedGeometryRoot* aAnimatedGeometryRoot);
/**
* Whether aAnimatedGeometryRoot has an intrinsic clip that doesn't move with
* respect to aAnimatedGeometryRoot's parent animated geometry root.
* If aAnimatedGeometryRoot is a scroll frame, this will be the scroll frame's
* scroll port, otherwise there is no clip.
* This method doesn't have much to do with PaintedLayerDataTree, but this is
* where we have easy access to a display list builder, which we use to get
* the clip rect result into the right coordinate space.
*/
bool IsClippedWithRespectToParentAnimatedGeometryRoot(AnimatedGeometryRoot* aAnimatedGeometryRoot,
nsIntRect* aOutClip);
/**
* Called by PaintedLayerDataNode when it is finished, so that we can drop
* our pointers to it.
*/
void NodeWasFinished(AnimatedGeometryRoot* aAnimatedGeometryRoot);
nsDisplayListBuilder* Builder() const;
ContainerState& ContState() const { return mContainerState; }
nscolor UniformBackgroundColor() const { return mContainerUniformBackgroundColor; }
protected:
/**
* Finish all nodes that potentially intersect *aRect, where *aRect is a rect
* that doesn't move with respect to aAnimatedGeometryRoot.
* If aRect is null, *aRect will be considered infinite.
*/
void FinishPotentiallyIntersectingNodes(AnimatedGeometryRoot* aAnimatedGeometryRoot,
const nsIntRect* aRect);
/**
* Make sure that there is a node for aAnimatedGeometryRoot and all of its
* ancestor geometry roots. Return the node for aAnimatedGeometryRoot.
*/
PaintedLayerDataNode* EnsureNodeFor(AnimatedGeometryRoot* aAnimatedGeometryRoot);
/**
* Find an existing node in the tree for an ancestor of aAnimatedGeometryRoot.
* *aOutAncestorChild will be set to the last ancestor that was encountered
* in the search up from aAnimatedGeometryRoot; it will be a child animated
* geometry root of the result, if neither are null.
*/
PaintedLayerDataNode*
FindNodeForAncestorAnimatedGeometryRoot(AnimatedGeometryRoot* aAnimatedGeometryRoot,
AnimatedGeometryRoot** aOutAncestorChild);
ContainerState& mContainerState;
UniquePtr<PaintedLayerDataNode> mRoot;
/**
* The uniform opaque color from behind this container layer, or
* NS_RGBA(0,0,0,0) if the background behind this container layer is not
* uniform and opaque. This color can be pulled into PaintedLayers that are
* directly above the background.
*/
nscolor mContainerUniformBackgroundColor;
/**
* A hash map for quick access the node belonging to a particular animated
* geometry root.
*/
nsDataHashtable<nsPtrHashKey<AnimatedGeometryRoot>, PaintedLayerDataNode*> mNodes;
};
/**
* This is a helper object used to build up the layer children for
* a ContainerLayer.
*/
class ContainerState {
public:
ContainerState(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
FrameLayerBuilder* aLayerBuilder,
nsIFrame* aContainerFrame,
nsDisplayItem* aContainerItem,
const nsRect& aContainerBounds,
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
ContainerLayer* aContainerLayer,
const ContainerLayerParameters& aParameters,
bool aFlattenToSingleLayer,
nscolor aBackgroundColor,
const DisplayItemScrollClip* aContainerScrollClip) :
mBuilder(aBuilder), mManager(aManager),
mLayerBuilder(aLayerBuilder),
mContainerFrame(aContainerFrame),
mContainerLayer(aContainerLayer),
mContainerBounds(aContainerBounds),
mContainerScrollClip(aContainerScrollClip),
mScrollClipForPerspectiveChild(aParameters.mScrollClipForPerspectiveChild),
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
mParameters(aParameters),
mPaintedLayerDataTree(*this, aBackgroundColor),
mFlattenToSingleLayer(aFlattenToSingleLayer)
{
nsPresContext* presContext = aContainerFrame->PresContext();
mAppUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
mContainerReferenceFrame =
const_cast<nsIFrame*>(aContainerItem ? aContainerItem->ReferenceFrameForChildren() :
mBuilder->FindReferenceFrameFor(mContainerFrame));
bool isAtRoot = !aContainerItem || (aContainerItem->Frame() == mBuilder->RootReferenceFrame());
MOZ_ASSERT_IF(isAtRoot, mContainerReferenceFrame == mBuilder->RootReferenceFrame());
mContainerAnimatedGeometryRoot = isAtRoot
? aBuilder->GetRootAnimatedGeometryRoot()
: aContainerItem->GetAnimatedGeometryRoot();
MOZ_ASSERT(!mBuilder->IsPaintingToWindow() ||
nsLayoutUtils::IsAncestorFrameCrossDoc(mBuilder->RootReferenceFrame(),
*mContainerAnimatedGeometryRoot));
// When AllowResidualTranslation is false, display items will be drawn
// scaled with a translation by integer pixels, so we know how the snapping
// will work.
mSnappingEnabled = aManager->IsSnappingEffectiveTransforms() &&
!mParameters.AllowResidualTranslation();
CollectOldLayers();
}
/**
* This is the method that actually walks a display list and builds
* the child layers.
*/
void ProcessDisplayItems(nsDisplayList* aList);
/**
* This finalizes all the open PaintedLayers by popping every element off
* mPaintedLayerDataStack, then sets the children of the container layer
* to be all the layers in mNewChildLayers in that order and removes any
* layers as children of the container that aren't in mNewChildLayers.
* @param aTextContentFlags if any child layer has CONTENT_COMPONENT_ALPHA,
* set *aTextContentFlags to CONTENT_COMPONENT_ALPHA
*/
void Finish(uint32_t *aTextContentFlags,
const nsIntRect& aContainerPixelBounds,
nsDisplayList* aChildItems, bool* aHasComponentAlphaChildren);
Backed out 46 changesets (bug 1022612) for B2G mochitest permafails on a CLOSED TREE. Backed out changeset 34b3014a3112 (bug 1022612) Backed out changeset 6ae9316fd909 (bug 1022612) Backed out changeset b8f3749c95eb (bug 1022612) Backed out changeset caab10bf6ca3 (bug 1022612) Backed out changeset 0c57c620c898 (bug 1022612) Backed out changeset fac64141a00a (bug 1022612) Backed out changeset bf0df1c9d68b (bug 1022612) Backed out changeset b42054800020 (bug 1022612) Backed out changeset 667793b21194 (bug 1022612) Backed out changeset f14ada64fe1b (bug 1022612) Backed out changeset 75b837686bdf (bug 1022612) Backed out changeset 66de53183a22 (bug 1022612) Backed out changeset 0ff86ced4d46 (bug 1022612) Backed out changeset 18eecc5b1ef7 (bug 1022612) Backed out changeset 2763c4878de5 (bug 1022612) Backed out changeset b72413ecc385 (bug 1022612) Backed out changeset b23f1081afb8 (bug 1022612) Backed out changeset f7e2c6a72043 (bug 1022612) Backed out changeset 959917c9027d (bug 1022612) Backed out changeset 0268a46f4880 (bug 1022612) Backed out changeset 3388856a80ad (bug 1022612) Backed out changeset e4b17cf0f806 (bug 1022612) Backed out changeset 2f4e9da0e4b6 (bug 1022612) Backed out changeset 489f6a7c0c03 (bug 1022612) Backed out changeset 8369d9ad7ad3 (bug 1022612) Backed out changeset 0758d2a06002 (bug 1022612) Backed out changeset f2ae9cb22edb (bug 1022612) Backed out changeset 9c48c6ee5dc2 (bug 1022612) Backed out changeset fe7134400f08 (bug 1022612) Backed out changeset cc2c5397ca8b (bug 1022612) Backed out changeset a3d1a3e8b39d (bug 1022612) Backed out changeset 8974b74b0eb0 (bug 1022612) Backed out changeset 75f7dbb5a2a6 (bug 1022612) Backed out changeset 2aa04a071e60 (bug 1022612) Backed out changeset f2ab1bcd4c39 (bug 1022612) Backed out changeset da9152b6ea29 (bug 1022612) Backed out changeset 58abf5b0e148 (bug 1022612) Backed out changeset 797058a09ad2 (bug 1022612) Backed out changeset ea3e99a92ff0 (bug 1022612) Backed out changeset adc4a4a7aa73 (bug 1022612) Backed out changeset 7b18dedd1505 (bug 1022612) Backed out changeset 055dd1921e8e (bug 1022612) Backed out changeset 42fa2c97e989 (bug 1022612) Backed out changeset cd594236388f (bug 1022612) Backed out changeset 9eadc5fee43d (bug 1022612) Backed out changeset 5cc8d30ff7c9 (bug 1022612)
2014-07-17 15:24:47 +00:00
nscoord GetAppUnitsPerDevPixel() { return mAppUnitsPerDevPixel; }
nsIntRect ScaleToNearestPixels(const nsRect& aRect) const
{
return aRect.ScaleToNearestPixels(mParameters.mXScale, mParameters.mYScale,
mAppUnitsPerDevPixel);
}
nsIntRegion ScaleRegionToNearestPixels(const nsRegion& aRegion) const
{
return aRegion.ScaleToNearestPixels(mParameters.mXScale, mParameters.mYScale,
mAppUnitsPerDevPixel);
}
nsIntRect ScaleToOutsidePixels(const nsRect& aRect, bool aSnap = false) const
{
if (aSnap && mSnappingEnabled) {
return ScaleToNearestPixels(aRect);
}
return aRect.ScaleToOutsidePixels(mParameters.mXScale, mParameters.mYScale,
mAppUnitsPerDevPixel);
}
nsIntRect ScaleToInsidePixels(const nsRect& aRect, bool aSnap = false) const
{
if (aSnap && mSnappingEnabled) {
return ScaleToNearestPixels(aRect);
}
return aRect.ScaleToInsidePixels(mParameters.mXScale, mParameters.mYScale,
mAppUnitsPerDevPixel);
}
nsIntRegion ScaleRegionToInsidePixels(const nsRegion& aRegion, bool aSnap = false) const
{
if (aSnap && mSnappingEnabled) {
return ScaleRegionToNearestPixels(aRegion);
}
return aRegion.ScaleToInsidePixels(mParameters.mXScale, mParameters.mYScale,
mAppUnitsPerDevPixel);
}
nsIntRegion ScaleRegionToOutsidePixels(const nsRegion& aRegion, bool aSnap = false) const
{
if (aSnap && mSnappingEnabled) {
return ScaleRegionToNearestPixels(aRegion);
}
return aRegion.ScaleToOutsidePixels(mParameters.mXScale, mParameters.mYScale,
mAppUnitsPerDevPixel);
}
nsIFrame* GetContainerFrame() const { return mContainerFrame; }
nsDisplayListBuilder* Builder() const { return mBuilder; }
/**
* Check if we are currently inside an inactive layer.
*/
bool IsInInactiveLayer() const {
return mLayerBuilder->GetContainingPaintedLayerData();
}
/**
* Sets aOuterVisibleRegion as aLayer's visible region.
* @param aOuterVisibleRegion
* is in the coordinate space of the container reference frame.
* @param aLayerContentsVisibleRect, if non-null, is in the layer's own
* coordinate system.
* @param aOuterUntransformed is true if the given aOuterVisibleRegion
* is already untransformed with the matrix of the layer.
*/
void SetOuterVisibleRegionForLayer(Layer* aLayer,
const nsIntRegion& aOuterVisibleRegion,
const nsIntRect* aLayerContentsVisibleRect = nullptr,
bool aOuterUntransformed = false) const;
/**
* Try to determine whether the PaintedLayer aData has a single opaque color
* covering aRect. If successful, return that color, otherwise return
* NS_RGBA(0,0,0,0).
* If aRect turns out not to intersect any content in the layer,
* *aOutIntersectsLayer will be set to false.
*/
nscolor FindOpaqueBackgroundColorInLayer(const PaintedLayerData* aData,
const nsIntRect& aRect,
bool* aOutIntersectsLayer) const;
/**
* Indicate that we are done adding items to the PaintedLayer represented by
* aData. Make sure that a real PaintedLayer exists for it, and set the final
* visible region and opaque-content.
*/
template<typename FindOpaqueBackgroundColorCallbackType>
void FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor);
protected:
friend class PaintedLayerData;
LayerManager::PaintedLayerCreationHint
GetLayerCreationHint(AnimatedGeometryRoot* aAnimatedGeometryRoot);
/**
* Creates a new PaintedLayer and sets up the transform on the PaintedLayer
* to account for scrolling.
*/
already_AddRefed<PaintedLayer> CreatePaintedLayer(PaintedLayerData* aData);
/**
* Find a PaintedLayer for recycling, recycle it and prepare it for use, or
* return null if no suitable layer was found.
*/
already_AddRefed<PaintedLayer> AttemptToRecyclePaintedLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot,
nsDisplayItem* aItem,
const nsPoint& aTopLeft);
/**
* Recycle aLayer and do any necessary invalidation.
*/
PaintedDisplayItemLayerUserData* RecyclePaintedLayer(PaintedLayer* aLayer,
AnimatedGeometryRoot* aAnimatedGeometryRoot,
bool& didResetScrollPositionForLayerPixelAlignment);
/**
* Perform the last step of CreatePaintedLayer / AttemptToRecyclePaintedLayer:
* Initialize aData, set up the layer's transform for scrolling, and
* invalidate the layer for layer pixel alignment changes if necessary.
*/
void PreparePaintedLayerForUse(PaintedLayer* aLayer,
PaintedDisplayItemLayerUserData* aData,
AnimatedGeometryRoot* aAnimatedGeometryRoot,
const nsIFrame* aReferenceFrame,
const nsPoint& aTopLeft,
bool aDidResetScrollPositionForLayerPixelAlignment);
/**
* Attempt to prepare an ImageLayer based upon the provided PaintedLayerData.
* Returns nullptr on failure.
*/
already_AddRefed<Layer> PrepareImageLayer(PaintedLayerData* aData);
/**
* Attempt to prepare a ColorLayer based upon the provided PaintedLayerData.
* Returns nullptr on failure.
*/
already_AddRefed<Layer> PrepareColorLayer(PaintedLayerData* aData);
/**
* Grab the next recyclable ColorLayer, or create one if there are no
* more recyclable ColorLayers.
*/
already_AddRefed<ColorLayer> CreateOrRecycleColorLayer(PaintedLayer* aPainted);
/**
* Grab the next recyclable ImageLayer, or create one if there are no
* more recyclable ImageLayers.
*/
already_AddRefed<ImageLayer> CreateOrRecycleImageLayer(PaintedLayer* aPainted);
/**
* Grab a recyclable ImageLayer for use as a mask layer for aLayer (that is a
* mask layer which has been used for aLayer before), or create one if such
* a layer doesn't exist.
*
* Since mask layers can exist either on the layer directly, or as a side-
* attachment to FrameMetrics (for ancestor scrollframe clips), we key the
* recycle operation on both the originating layer and the mask layer's
* index in the layer, if any.
*/
struct MaskLayerKey;
already_AddRefed<ImageLayer> CreateOrRecycleMaskImageLayerFor(const MaskLayerKey& aKey);
/**
* Grabs all PaintedLayers and ColorLayers from the ContainerLayer and makes them
* available for recycling.
*/
void CollectOldLayers();
/**
* If aItem used to belong to a PaintedLayer, invalidates the area of
* aItem in that layer. If aNewLayer is a PaintedLayer, invalidates the area of
* aItem in that layer.
*/
void InvalidateForLayerChange(nsDisplayItem* aItem,
PaintedLayer* aNewLayer);
/**
* Returns true if aItem's opaque area (in aOpaque) covers the entire
* scrollable area of its presshell.
*/
bool ItemCoversScrollableArea(nsDisplayItem* aItem, const nsRegion& aOpaque);
/**
* Set FrameMetrics and scroll-induced clipping on aEntry's layer.
*/
void SetupScrollingMetadata(NewLayerEntry* aEntry);
/**
* Applies occlusion culling.
* For each layer in mNewChildLayers, remove from its visible region the
* opaque regions of the layers at higher z-index, but only if they have
* the same animated geometry root and fixed-pos frame ancestor.
* The opaque region for the child layers that share the same animated
* geometry root as the container frame is returned in
* *aOpaqueRegionForContainer.
*
* Also sets scroll metadata on the layers.
*/
void PostprocessRetainedLayers(nsIntRegion* aOpaqueRegionForContainer);
/**
* Computes the snapped opaque area of aItem. Sets aList's opaque flag
* if it covers the entire list bounds. Sets *aHideAllLayersBelow to true
* this item covers the entire viewport so that all layers below are
* permanently invisible.
*/
nsIntRegion ComputeOpaqueRect(nsDisplayItem* aItem,
AnimatedGeometryRoot* aAnimatedGeometryRoot,
const DisplayItemClip& aClip,
nsDisplayList* aList,
bool* aHideAllLayersBelow,
bool* aOpaqueForAnimatedGeometryRootParent);
/**
* Return a PaintedLayerData object that is initialized for a layer that
* aItem will be assigned to.
* @param aItem The item that is going to be added.
* @param aVisibleRect The visible rect of the item.
* @param aAnimatedGeometryRoot The item's animated geometry root.
* @param aScrollClip The scroll clip for this PaintedLayer.
* @param aTopLeft The offset between aAnimatedGeometryRoot and
* the reference frame.
* @param aShouldFixToViewport If true, aAnimatedGeometryRoot is the
* viewport and we will be adding fixed-pos
* metadata for this layer because the display
* item returned true from ShouldFixToViewport.
*/
PaintedLayerData NewPaintedLayerData(nsDisplayItem* aItem,
AnimatedGeometryRoot* aAnimatedGeometryRoot,
const DisplayItemScrollClip* aScrollClip,
const nsPoint& aTopLeft,
bool aShouldFixToViewport);
/* Build a mask layer to represent the clipping region. Will return null if
* there is no clipping specified or a mask layer cannot be built.
* Builds an ImageLayer for the appropriate backend; the mask is relative to
* aLayer's visible region.
* aLayer is the layer to be clipped.
* relative to the container reference frame
* aRoundedRectClipCount is used when building mask layers for PaintedLayers,
* SetupMaskLayer will build a mask layer for only the first
* aRoundedRectClipCount rounded rects in aClip
*/
void SetupMaskLayer(Layer *aLayer, const DisplayItemClip& aClip,
uint32_t aRoundedRectClipCount = UINT32_MAX);
/**
* If |aClip| has rounded corners, create a mask layer for them, and
* add it to |aLayer|'s ancestor mask layers, returning an index into
* the array of ancestor mask layers. Returns an empty Maybe if
* |aClip| does not have rounded corners, or if no mask layer could
* be created.
*/
Maybe<size_t> SetupMaskLayerForScrolledClip(Layer* aLayer,
const DisplayItemClip& aClip);
already_AddRefed<Layer> CreateMaskLayer(
Layer *aLayer, const DisplayItemClip& aClip,
const Maybe<size_t>& aForAncestorMaskLayer,
uint32_t aRoundedRectClipCount = UINT32_MAX);
bool ChooseAnimatedGeometryRoot(const nsDisplayList& aList,
AnimatedGeometryRoot **aAnimatedGeometryRoot);
nsDisplayListBuilder* mBuilder;
LayerManager* mManager;
FrameLayerBuilder* mLayerBuilder;
nsIFrame* mContainerFrame;
nsIFrame* mContainerReferenceFrame;
AnimatedGeometryRoot* mContainerAnimatedGeometryRoot;
ContainerLayer* mContainerLayer;
nsRect mContainerBounds;
const DisplayItemScrollClip* mContainerScrollClip;
const DisplayItemScrollClip* mScrollClipForPerspectiveChild;
#ifdef DEBUG
nsRect mAccumulatedChildBounds;
#endif
ContainerLayerParameters mParameters;
/**
* The region of PaintedLayers that should be invalidated every time
* we recycle one.
*/
nsIntRegion mInvalidPaintedContent;
PaintedLayerDataTree mPaintedLayerDataTree;
/**
* We collect the list of children in here. During ProcessDisplayItems,
* the layers in this array either have mContainerLayer as their parent,
* or no parent.
* PaintedLayers have two entries in this array: the second one is used only if
* the PaintedLayer is optimized away to a ColorLayer or ImageLayer.
* It's essential that this array is only appended to, since PaintedLayerData
* records the index of its PaintedLayer in this array.
*/
typedef AutoTArray<NewLayerEntry,1> AutoLayersArray;
AutoLayersArray mNewChildLayers;
nsTHashtable<nsRefPtrHashKey<PaintedLayer>> mPaintedLayersAvailableForRecycling;
nscoord mAppUnitsPerDevPixel;
bool mSnappingEnabled;
bool mFlattenToSingleLayer;
struct MaskLayerKey {
MaskLayerKey() : mLayer(nullptr) {}
MaskLayerKey(Layer* aLayer, const Maybe<size_t>& aAncestorIndex)
: mLayer(aLayer),
mAncestorIndex(aAncestorIndex)
{}
PLDHashNumber Hash() const {
// Hash the layer and add the layer index to the hash.
return (NS_PTR_TO_UINT32(mLayer) >> 2)
+ (mAncestorIndex ? (*mAncestorIndex + 1) : 0);
}
bool operator ==(const MaskLayerKey& aOther) const {
return mLayer == aOther.mLayer &&
mAncestorIndex == aOther.mAncestorIndex;
}
Layer* mLayer;
Maybe<size_t> mAncestorIndex;
};
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
nsDataHashtable<nsGenericHashKey<MaskLayerKey>, RefPtr<ImageLayer>>
mRecycledMaskImageLayers;
};
class PaintedDisplayItemLayerUserData : public LayerUserData
{
public:
PaintedDisplayItemLayerUserData() :
mMaskClipCount(0),
mForcedBackgroundColor(NS_RGBA(0,0,0,0)),
mFontSmoothingBackgroundColor(NS_RGBA(0,0,0,0)),
mXScale(1.f), mYScale(1.f),
mAppUnitsPerDevPixel(0),
mTranslation(0, 0),
mAnimatedGeometryRootPosition(0, 0) {}
/**
* Record the number of clips in the PaintedLayer's mask layer.
* Should not be reset when the layer is recycled since it is used to track
* changes in the use of mask layers.
*/
uint32_t mMaskClipCount;
/**
* A color that should be painted over the bounds of the layer's visible
* region before any other content is painted.
*/
nscolor mForcedBackgroundColor;
/**
* The target background color for smoothing fonts that are drawn on top of
* transparent parts of the layer.
*/
nscolor mFontSmoothingBackgroundColor;
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
/**
* The resolution scale used.
*/
float mXScale, mYScale;
/**
* The appunits per dev pixel for the items in this layer.
*/
nscoord mAppUnitsPerDevPixel;
/**
* The offset from the PaintedLayer's 0,0 to the
* reference frame. This isn't necessarily the same as the transform
* set on the PaintedLayer since we might also be applying an extra
* offset specified by the parent ContainerLayer/
*/
nsIntPoint mTranslation;
/**
* We try to make 0,0 of the PaintedLayer be the top-left of the
* border-box of the "active scrolled root" frame (i.e. the nearest ancestor
* frame for the display items that is being actively scrolled). But
* we force the PaintedLayer transform to be an integer translation, and we may
* have a resolution scale, so we have to snap the PaintedLayer transform, so
* 0,0 may not be exactly the top-left of the active scrolled root. Here we
* store the coordinates in PaintedLayer space of the top-left of the
* active scrolled root.
*/
gfxPoint mAnimatedGeometryRootPosition;
nsIntRegion mRegionToInvalidate;
// The offset between the active scrolled root of this layer
// and the root of the container for the previous and current
// paints respectively.
nsPoint mLastAnimatedGeometryRootOrigin;
nsPoint mAnimatedGeometryRootOrigin;
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<ColorLayer> mColorLayer;
RefPtr<ImageLayer> mImageLayer;
// The region for which display item visibility for this layer has already
// been calculated. Used to reduce the number of calls to
// RecomputeVisibilityForItems if it is known in advance that a larger
// region will be painted during a transaction than in a single call to
// DrawPaintedLayer, for example when progressive paint is enabled.
nsIntRegion mVisibilityComputedRegion;
};
/*
* User data for layers which will be used as masks.
*/
struct MaskLayerUserData : public LayerUserData
{
MaskLayerUserData()
: mScaleX(-1.0f)
, mScaleY(-1.0f)
, mAppUnitsPerDevPixel(-1)
{ }
bool
operator== (const MaskLayerUserData& aOther) const
{
return mRoundedClipRects == aOther.mRoundedClipRects &&
mScaleX == aOther.mScaleX &&
mScaleY == aOther.mScaleY &&
mOffset == aOther.mOffset &&
mAppUnitsPerDevPixel == aOther.mAppUnitsPerDevPixel;
}
// Keeps a MaskLayerImageKey alive by managing its mLayerCount member-var
MaskLayerImageCache::MaskLayerImageKeyRef mImageKey;
// properties of the mask layer; the mask layer may be re-used if these
// remain unchanged.
nsTArray<DisplayItemClip::RoundedRect> mRoundedClipRects;
// scale from the masked layer which is applied to the mask
float mScaleX, mScaleY;
// The ContainerLayerParameters offset which is applied to the mask's transform.
nsIntPoint mOffset;
int32_t mAppUnitsPerDevPixel;
};
class MaskImageData
{
public:
MaskImageData(const gfx::IntSize& aSize, LayerManager* aLayerManager)
: mTextureClientLocked(false)
, mSize(aSize)
, mLayerManager(aLayerManager)
{
}
~MaskImageData()
{
if (mTextureClientLocked) {
MOZ_ASSERT(mTextureClient);
// Clear DrawTarget before Unlock.
mDrawTarget = nullptr;
mTextureClient->Unlock();
}
}
gfx::DrawTarget* CreateDrawTarget()
{
MOZ_ASSERT(mLayerManager);
if (mDrawTarget) {
return mDrawTarget;
}
if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC) {
mDrawTarget = mLayerManager->CreateOptimalMaskDrawTarget(mSize);
return mDrawTarget;
}
MOZ_ASSERT(mLayerManager->GetBackendType() == LayersBackend::LAYERS_CLIENT);
ShadowLayerForwarder* fwd = mLayerManager->AsShadowForwarder();
if (!fwd) {
return nullptr;
}
mTextureClient =
TextureClient::CreateForDrawing(fwd,
SurfaceFormat::A8,
mSize,
BackendSelector::Content,
TextureFlags::DISALLOW_BIGIMAGE,
TextureAllocationFlags::ALLOC_CLEAR_BUFFER);
if (!mTextureClient) {
return nullptr;
}
mTextureClientLocked = mTextureClient->Lock(OpenMode::OPEN_READ_WRITE);
if (!mTextureClientLocked) {
return nullptr;
}
mDrawTarget = mTextureClient->BorrowDrawTarget();
return mDrawTarget;
}
already_AddRefed<Image> CreateImage()
{
if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_BASIC &&
mDrawTarget) {
RefPtr<SourceSurface> surface = mDrawTarget->Snapshot();
RefPtr<SourceSurfaceImage> image = new SourceSurfaceImage(mSize, surface);
// Disallow BIGIMAGE (splitting into multiple textures) for mask
// layer images
image->SetTextureFlags(TextureFlags::DISALLOW_BIGIMAGE);
return image.forget();
}
if (mLayerManager->GetBackendType() == LayersBackend::LAYERS_CLIENT &&
mTextureClient &&
mDrawTarget) {
RefPtr<TextureWrapperImage> image =
new TextureWrapperImage(mTextureClient, gfx::IntRect(gfx::IntPoint(0, 0), mSize));
return image.forget();
}
return nullptr;
}
private:
bool mTextureClientLocked;
gfx::IntSize mSize;
LayerManager* mLayerManager;
RefPtr<gfx::DrawTarget> mDrawTarget;
RefPtr<TextureClient> mTextureClient;
};
/**
* Helper functions for getting user data and casting it to the correct type.
* aLayer is the layer where the user data is stored.
*/
MaskLayerUserData* GetMaskLayerUserData(Layer* aLayer)
{
return static_cast<MaskLayerUserData*>(aLayer->GetUserData(&gMaskLayerUserData));
}
PaintedDisplayItemLayerUserData* GetPaintedDisplayItemLayerUserData(Layer* aLayer)
{
return static_cast<PaintedDisplayItemLayerUserData*>(
aLayer->GetUserData(&gPaintedDisplayItemLayerUserData));
}
/* static */ void
FrameLayerBuilder::Shutdown()
{
if (gMaskLayerImageCache) {
delete gMaskLayerImageCache;
gMaskLayerImageCache = nullptr;
}
}
void
FrameLayerBuilder::Init(nsDisplayListBuilder* aBuilder, LayerManager* aManager,
PaintedLayerData* aLayerData)
{
mDisplayListBuilder = aBuilder;
mRootPresContext = aBuilder->RootReferenceFrame()->PresContext()->GetRootPresContext();
if (mRootPresContext) {
mInitialDOMGeneration = mRootPresContext->GetDOMGeneration();
}
mContainingPaintedLayer = aLayerData;
aManager->SetUserData(&gLayerManagerLayerBuilder, this);
}
void
FrameLayerBuilder::FlashPaint(gfxContext *aContext)
{
float r = float(rand()) / RAND_MAX;
float g = float(rand()) / RAND_MAX;
float b = float(rand()) / RAND_MAX;
aContext->SetColor(Color(r, g, b, 0.4f));
aContext->Paint();
}
static FrameLayerBuilder::DisplayItemData*
AssertDisplayItemData(FrameLayerBuilder::DisplayItemData* aData)
{
MOZ_RELEASE_ASSERT(aData);
MOZ_RELEASE_ASSERT(sAliveDisplayItemDatas && sAliveDisplayItemDatas->Contains(aData));
MOZ_RELEASE_ASSERT(aData->mLayer);
return aData;
}
FrameLayerBuilder::DisplayItemData*
FrameLayerBuilder::GetDisplayItemData(nsIFrame* aFrame, uint32_t aKey)
{
const nsTArray<DisplayItemData*>* array =
aFrame->Properties().Get(LayerManagerDataProperty());
if (array) {
for (uint32_t i = 0; i < array->Length(); i++) {
DisplayItemData* item = AssertDisplayItemData(array->ElementAt(i));
if (item->mDisplayItemKey == aKey &&
item->mLayer->Manager() == mRetainingManager) {
return item;
}
}
}
return nullptr;
}
nsACString&
AppendToString(nsACString& s, const nsIntRect& r,
const char* pfx="", const char* sfx="")
{
s += pfx;
s += nsPrintfCString(
"(x=%d, y=%d, w=%d, h=%d)",
r.x, r.y, r.width, r.height);
return s += sfx;
}
nsACString&
AppendToString(nsACString& s, const nsIntRegion& r,
const char* pfx="", const char* sfx="")
{
s += pfx;
s += "< ";
for (auto iter = r.RectIter(); !iter.Done(); iter.Next()) {
AppendToString(s, iter.Get()) += "; ";
}
s += ">";
return s += sfx;
}
/**
* Invalidate aRegion in aLayer. aLayer is in the coordinate system
* *after* aTranslation has been applied, so we need to
* apply the inverse of that transform before calling InvalidateRegion.
*/
static void
InvalidatePostTransformRegion(PaintedLayer* aLayer, const nsIntRegion& aRegion,
const nsIntPoint& aTranslation)
{
// Convert the region from the coordinates of the container layer
// (relative to the snapped top-left of the display list reference frame)
// to the PaintedLayer's own coordinates
nsIntRegion rgn = aRegion;
rgn.MoveBy(-aTranslation);
aLayer->InvalidateRegion(rgn);
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
nsAutoCString str;
AppendToString(str, rgn);
printf_stderr("Invalidating layer %p: %s\n", aLayer, str.get());
}
#endif
}
static void
InvalidatePostTransformRegion(PaintedLayer* aLayer, const nsRect& aRect,
const DisplayItemClip& aClip,
const nsIntPoint& aTranslation)
{
PaintedDisplayItemLayerUserData* data =
static_cast<PaintedDisplayItemLayerUserData*>(aLayer->GetUserData(&gPaintedDisplayItemLayerUserData));
nsRect rect = aClip.ApplyNonRoundedIntersection(aRect);
nsIntRect pixelRect = rect.ScaleToOutsidePixels(data->mXScale, data->mYScale, data->mAppUnitsPerDevPixel);
InvalidatePostTransformRegion(aLayer, pixelRect, aTranslation);
}
static nsIntPoint
GetTranslationForPaintedLayer(PaintedLayer* aLayer)
{
PaintedDisplayItemLayerUserData* data =
static_cast<PaintedDisplayItemLayerUserData*>
(aLayer->GetUserData(&gPaintedDisplayItemLayerUserData));
NS_ASSERTION(data, "Must be a tracked painted layer!");
return data->mTranslation;
}
/**
* Some frames can have multiple, nested, retaining layer managers
* associated with them (normal manager, inactive managers, SVG effects).
* In these cases we store the 'outermost' LayerManager data property
* on the frame since we can walk down the chain from there.
*
* If one of these frames has just been destroyed, we will free the inner
* layer manager when removing the entry from mFramesWithLayers. Destroying
* the layer manager destroys the LayerManagerData and calls into
* the DisplayItemData destructor. If the inner layer manager had any
* items with the same frame, then we attempt to retrieve properties
* from the deleted frame.
*
* Cache the destroyed frame pointer here so we can avoid crashing in this case.
*/
/* static */ void
FrameLayerBuilder::RemoveFrameFromLayerManager(const nsIFrame* aFrame,
nsTArray<DisplayItemData*>* aArray)
{
MOZ_RELEASE_ASSERT(!sDestroyedFrame);
sDestroyedFrame = aFrame;
// Hold a reference to all the items so that they don't get
// deleted from under us.
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
nsTArray<RefPtr<DisplayItemData> > arrayCopy;
for (DisplayItemData* data : *aArray) {
arrayCopy.AppendElement(data);
}
#ifdef DEBUG_DISPLAY_ITEM_DATA
if (aArray->Length()) {
LayerManagerData *rootData = aArray->ElementAt(0)->mParent;
while (rootData->mParent) {
rootData = rootData->mParent;
}
printf_stderr("Removing frame %p - dumping display data\n", aFrame);
rootData->Dump();
}
#endif
for (DisplayItemData* data : *aArray) {
PaintedLayer* t = data->mLayer->AsPaintedLayer();
if (t) {
PaintedDisplayItemLayerUserData* paintedData =
static_cast<PaintedDisplayItemLayerUserData*>(t->GetUserData(&gPaintedDisplayItemLayerUserData));
if (paintedData) {
nsRegion old = data->mGeometry->ComputeInvalidationRegion();
nsIntRegion rgn = old.ScaleToOutsidePixels(paintedData->mXScale, paintedData->mYScale, paintedData->mAppUnitsPerDevPixel);
rgn.MoveBy(-GetTranslationForPaintedLayer(t));
paintedData->mRegionToInvalidate.Or(paintedData->mRegionToInvalidate, rgn);
paintedData->mRegionToInvalidate.SimplifyOutward(8);
}
}
data->mParent->mDisplayItems.RemoveEntry(data);
}
arrayCopy.Clear();
delete aArray;
sDestroyedFrame = nullptr;
}
void
FrameLayerBuilder::DidBeginRetainedLayerTransaction(LayerManager* aManager)
{
mRetainingManager = aManager;
LayerManagerData* data = static_cast<LayerManagerData*>
(aManager->GetUserData(&gLayerManagerUserData));
if (data) {
mInvalidateAllLayers = data->mInvalidateAllLayers;
} else {
data = new LayerManagerData(aManager);
aManager->SetUserData(&gLayerManagerUserData, data);
}
}
void
FrameLayerBuilder::StoreOptimizedLayerForFrame(nsDisplayItem* aItem, Layer* aLayer)
{
if (!mRetainingManager) {
return;
}
DisplayItemData* data = GetDisplayItemDataForManager(aItem, aLayer->Manager());
NS_ASSERTION(data, "Must have already stored data for this item!");
data->mOptLayer = aLayer;
}
void
FrameLayerBuilder::DidEndTransaction()
{
GetMaskLayerImageCache()->Sweep();
}
void
FrameLayerBuilder::WillEndTransaction()
{
if (!mRetainingManager) {
return;
}
// We need to save the data we'll need to support retaining.
LayerManagerData* data = static_cast<LayerManagerData*>
(mRetainingManager->GetUserData(&gLayerManagerUserData));
NS_ASSERTION(data, "Must have data!");
// Update all the frames that used to have layers.
for (auto iter = data->mDisplayItems.Iter(); !iter.Done(); iter.Next()) {
DisplayItemData* data = iter.Get()->GetKey();
if (!data->mUsed) {
// This item was visible, but isn't anymore.
PaintedLayer* t = data->mLayer->AsPaintedLayer();
if (t && data->mGeometry) {
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Invalidating unused display item (%i) belonging to frame %p from layer %p\n", data->mDisplayItemKey, data->mFrameList[0], t);
}
#endif
InvalidatePostTransformRegion(t,
data->mGeometry->ComputeInvalidationRegion(),
data->mClip,
GetLastPaintOffset(t));
}
data->ClearAnimationCompositorState();
iter.Remove();
} else {
ComputeGeometryChangeForItem(data);
}
}
data->mInvalidateAllLayers = false;
}
/* static */ FrameLayerBuilder::DisplayItemData*
FrameLayerBuilder::GetDisplayItemDataForManager(nsDisplayItem* aItem,
LayerManager* aManager)
{
const nsTArray<DisplayItemData*>* array =
aItem->Frame()->Properties().Get(LayerManagerDataProperty());
if (array) {
for (uint32_t i = 0; i < array->Length(); i++) {
DisplayItemData* item = AssertDisplayItemData(array->ElementAt(i));
if (item->mDisplayItemKey == aItem->GetPerFrameKey() &&
item->mLayer->Manager() == aManager) {
return item;
}
}
}
return nullptr;
}
bool
FrameLayerBuilder::HasRetainedDataFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
{
const nsTArray<DisplayItemData*>* array =
aFrame->Properties().Get(LayerManagerDataProperty());
if (array) {
for (uint32_t i = 0; i < array->Length(); i++) {
if (AssertDisplayItemData(array->ElementAt(i))->mDisplayItemKey == aDisplayItemKey) {
return true;
}
}
}
return false;
}
void
FrameLayerBuilder::IterateRetainedDataFor(nsIFrame* aFrame, DisplayItemDataCallback aCallback)
{
const nsTArray<DisplayItemData*>* array =
aFrame->Properties().Get(LayerManagerDataProperty());
if (!array) {
return;
}
for (uint32_t i = 0; i < array->Length(); i++) {
DisplayItemData* data = AssertDisplayItemData(array->ElementAt(i));
if (data->mDisplayItemKey != nsDisplayItem::TYPE_ZERO) {
aCallback(aFrame, data);
}
}
}
FrameLayerBuilder::DisplayItemData*
FrameLayerBuilder::GetOldLayerForFrame(nsIFrame* aFrame, uint32_t aDisplayItemKey)
{
// If we need to build a new layer tree, then just refuse to recycle
// anything.
if (!mRetainingManager || mInvalidateAllLayers)
return nullptr;
DisplayItemData *data = GetDisplayItemData(aFrame, aDisplayItemKey);
if (data && data->mLayer->Manager() == mRetainingManager) {
return data;
}
return nullptr;
}
Layer*
FrameLayerBuilder::GetOldLayerFor(nsDisplayItem* aItem,
nsDisplayItemGeometry** aOldGeometry,
DisplayItemClip** aOldClip)
{
uint32_t key = aItem->GetPerFrameKey();
nsIFrame* frame = aItem->Frame();
DisplayItemData* oldData = GetOldLayerForFrame(frame, key);
if (oldData) {
if (aOldGeometry) {
*aOldGeometry = oldData->mGeometry.get();
}
if (aOldClip) {
*aOldClip = &oldData->mClip;
}
return oldData->mLayer;
}
return nullptr;
}
void
FrameLayerBuilder::ClearCachedGeometry(nsDisplayItem* aItem)
{
uint32_t key = aItem->GetPerFrameKey();
nsIFrame* frame = aItem->Frame();
DisplayItemData* oldData = GetOldLayerForFrame(frame, key);
if (oldData) {
oldData->mGeometry = nullptr;
}
}
/* static */ Layer*
FrameLayerBuilder::GetDebugOldLayerFor(nsIFrame* aFrame, uint32_t aDisplayItemKey)
{
const nsTArray<DisplayItemData*>* array =
aFrame->Properties().Get(LayerManagerDataProperty());
if (!array) {
return nullptr;
}
for (uint32_t i = 0; i < array->Length(); i++) {
DisplayItemData *data = AssertDisplayItemData(array->ElementAt(i));
if (data->mDisplayItemKey == aDisplayItemKey) {
return data->mLayer;
}
}
return nullptr;
}
/* static */ PaintedLayer*
FrameLayerBuilder::GetDebugSingleOldPaintedLayerForFrame(nsIFrame* aFrame)
Bug 1142211 - Add layerization testing mechanisms to reftest. r=roc This adds support for class="reftest-opaque-layer" and for reftest-assigned-layer="some-layer-name" to the reftest harness. From reftest/README.txt: Opaque Layer Tests: class="reftest-opaque-layer" ================================================ If an element should be assigned to a PaintedLayer that's opaque, set the class "reftest-opaque-layer" on it. This checks whether the layer is opaque during the last paint of the test, and it works whether your test is an invalidation test or not. In order to pass the test, the element has to have a primary frame, and that frame's display items must all be assigned to a single painted layer and no other layers, so it can't be used on elements that create stacking contexts (active or inactive). Layerization Tests: reftest-assigned-layer="layer-name" ======================================================= If two elements should be assigned to the same PaintedLayer, choose any string value as the layer name and set the attribute reftest-assigned-layer="yourname" on both elements. Reftest will check whether all elements with the same reftest-assigned-layer value share the same layer. It will also test whether elements with different reftest-assigned-layer values are assigned to different layers. The same restrictions as with class="reftest-opaque-layer" apply: All elements must have a primary frame, and that frame's display items must all be assigned to the same PaintedLayer and no other layers. If these requirements are not met, the test will fail.
2015-03-11 18:51:59 +00:00
{
const nsTArray<DisplayItemData*>* array =
aFrame->Properties().Get(LayerManagerDataProperty());
Bug 1142211 - Add layerization testing mechanisms to reftest. r=roc This adds support for class="reftest-opaque-layer" and for reftest-assigned-layer="some-layer-name" to the reftest harness. From reftest/README.txt: Opaque Layer Tests: class="reftest-opaque-layer" ================================================ If an element should be assigned to a PaintedLayer that's opaque, set the class "reftest-opaque-layer" on it. This checks whether the layer is opaque during the last paint of the test, and it works whether your test is an invalidation test or not. In order to pass the test, the element has to have a primary frame, and that frame's display items must all be assigned to a single painted layer and no other layers, so it can't be used on elements that create stacking contexts (active or inactive). Layerization Tests: reftest-assigned-layer="layer-name" ======================================================= If two elements should be assigned to the same PaintedLayer, choose any string value as the layer name and set the attribute reftest-assigned-layer="yourname" on both elements. Reftest will check whether all elements with the same reftest-assigned-layer value share the same layer. It will also test whether elements with different reftest-assigned-layer values are assigned to different layers. The same restrictions as with class="reftest-opaque-layer" apply: All elements must have a primary frame, and that frame's display items must all be assigned to the same PaintedLayer and no other layers. If these requirements are not met, the test will fail.
2015-03-11 18:51:59 +00:00
if (!array) {
return nullptr;
}
Layer* layer = nullptr;
for (DisplayItemData* data : *array) {
AssertDisplayItemData(data);
if (!data->mLayer->AsPaintedLayer()) {
continue;
}
Bug 1142211 - Add layerization testing mechanisms to reftest. r=roc This adds support for class="reftest-opaque-layer" and for reftest-assigned-layer="some-layer-name" to the reftest harness. From reftest/README.txt: Opaque Layer Tests: class="reftest-opaque-layer" ================================================ If an element should be assigned to a PaintedLayer that's opaque, set the class "reftest-opaque-layer" on it. This checks whether the layer is opaque during the last paint of the test, and it works whether your test is an invalidation test or not. In order to pass the test, the element has to have a primary frame, and that frame's display items must all be assigned to a single painted layer and no other layers, so it can't be used on elements that create stacking contexts (active or inactive). Layerization Tests: reftest-assigned-layer="layer-name" ======================================================= If two elements should be assigned to the same PaintedLayer, choose any string value as the layer name and set the attribute reftest-assigned-layer="yourname" on both elements. Reftest will check whether all elements with the same reftest-assigned-layer value share the same layer. It will also test whether elements with different reftest-assigned-layer values are assigned to different layers. The same restrictions as with class="reftest-opaque-layer" apply: All elements must have a primary frame, and that frame's display items must all be assigned to the same PaintedLayer and no other layers. If these requirements are not met, the test will fail.
2015-03-11 18:51:59 +00:00
if (layer && layer != data->mLayer) {
// More than one layer assigned, bail.
return nullptr;
}
layer = data->mLayer;
}
if (!layer) {
return nullptr;
}
return layer->AsPaintedLayer();
Bug 1142211 - Add layerization testing mechanisms to reftest. r=roc This adds support for class="reftest-opaque-layer" and for reftest-assigned-layer="some-layer-name" to the reftest harness. From reftest/README.txt: Opaque Layer Tests: class="reftest-opaque-layer" ================================================ If an element should be assigned to a PaintedLayer that's opaque, set the class "reftest-opaque-layer" on it. This checks whether the layer is opaque during the last paint of the test, and it works whether your test is an invalidation test or not. In order to pass the test, the element has to have a primary frame, and that frame's display items must all be assigned to a single painted layer and no other layers, so it can't be used on elements that create stacking contexts (active or inactive). Layerization Tests: reftest-assigned-layer="layer-name" ======================================================= If two elements should be assigned to the same PaintedLayer, choose any string value as the layer name and set the attribute reftest-assigned-layer="yourname" on both elements. Reftest will check whether all elements with the same reftest-assigned-layer value share the same layer. It will also test whether elements with different reftest-assigned-layer values are assigned to different layers. The same restrictions as with class="reftest-opaque-layer" apply: All elements must have a primary frame, and that frame's display items must all be assigned to the same PaintedLayer and no other layers. If these requirements are not met, the test will fail.
2015-03-11 18:51:59 +00:00
}
// Reset state that should not persist when a layer is recycled.
static void
ResetLayerStateForRecycling(Layer* aLayer) {
// Currently, this clears the mask layer and ancestor mask layers.
// Other cleanup may be added here.
aLayer->SetMaskLayer(nullptr);
aLayer->SetAncestorMaskLayers({});
}
already_AddRefed<ColorLayer>
ContainerState::CreateOrRecycleColorLayer(PaintedLayer *aPainted)
{
PaintedDisplayItemLayerUserData* data =
static_cast<PaintedDisplayItemLayerUserData*>(aPainted->GetUserData(&gPaintedDisplayItemLayerUserData));
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<ColorLayer> layer = data->mColorLayer;
if (layer) {
ResetLayerStateForRecycling(layer);
layer->ClearExtraDumpInfo();
} else {
// Create a new layer
layer = mManager->CreateColorLayer();
if (!layer)
return nullptr;
// Mark this layer as being used for painting display items
data->mColorLayer = layer;
layer->SetUserData(&gColorLayerUserData, nullptr);
// Remove other layer types we might have stored for this PaintedLayer
data->mImageLayer = nullptr;
}
return layer.forget();
}
already_AddRefed<ImageLayer>
ContainerState::CreateOrRecycleImageLayer(PaintedLayer *aPainted)
{
PaintedDisplayItemLayerUserData* data =
static_cast<PaintedDisplayItemLayerUserData*>(aPainted->GetUserData(&gPaintedDisplayItemLayerUserData));
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<ImageLayer> layer = data->mImageLayer;
if (layer) {
ResetLayerStateForRecycling(layer);
layer->ClearExtraDumpInfo();
} else {
// Create a new layer
layer = mManager->CreateImageLayer();
if (!layer)
return nullptr;
// Mark this layer as being used for painting display items
data->mImageLayer = layer;
layer->SetUserData(&gImageLayerUserData, nullptr);
// Remove other layer types we might have stored for this PaintedLayer
data->mColorLayer = nullptr;
}
return layer.forget();
}
already_AddRefed<ImageLayer>
ContainerState::CreateOrRecycleMaskImageLayerFor(const MaskLayerKey& aKey)
{
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<ImageLayer> result = mRecycledMaskImageLayers.Get(aKey);
if (result) {
mRecycledMaskImageLayers.Remove(aKey);
aKey.mLayer->ClearExtraDumpInfo();
// XXX if we use clip on mask layers, null it out here
} else {
// Create a new layer
result = mManager->CreateImageLayer();
if (!result)
return nullptr;
result->SetUserData(&gMaskLayerUserData, new MaskLayerUserData());
}
return result.forget();
}
static const double SUBPIXEL_OFFSET_EPSILON = 0.02;
/**
* This normally computes NSToIntRoundUp(aValue). However, if that would
* give a residual near 0.5 while aOldResidual is near -0.5, or
* it would give a residual near -0.5 while aOldResidual is near 0.5, then
* instead we return the integer in the other direction so that the residual
* is close to aOldResidual.
*/
static int32_t
RoundToMatchResidual(double aValue, double aOldResidual)
{
int32_t v = NSToIntRoundUp(aValue);
double residual = aValue - v;
if (aOldResidual < 0) {
if (residual > 0 && fabs(residual - 1.0 - aOldResidual) < SUBPIXEL_OFFSET_EPSILON) {
// Round up instead
return int32_t(ceil(aValue));
}
} else if (aOldResidual > 0) {
if (residual < 0 && fabs(residual + 1.0 - aOldResidual) < SUBPIXEL_OFFSET_EPSILON) {
// Round down instead
return int32_t(floor(aValue));
}
}
return v;
}
static void
ResetScrollPositionForLayerPixelAlignment(AnimatedGeometryRoot* aAnimatedGeometryRoot)
{
nsIScrollableFrame* sf = nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot);
if (sf) {
sf->ResetScrollPositionForLayerPixelAlignment();
}
}
static void
InvalidateEntirePaintedLayer(PaintedLayer* aLayer, AnimatedGeometryRoot* aAnimatedGeometryRoot, const char *aReason)
{
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Invalidating entire layer %p: %s\n", aLayer, aReason);
}
#endif
nsIntRect invalidate = aLayer->GetValidRegion().GetBounds();
aLayer->InvalidateRegion(invalidate);
aLayer->SetInvalidRectToVisibleRegion();
ResetScrollPositionForLayerPixelAlignment(aAnimatedGeometryRoot);
}
LayerManager::PaintedLayerCreationHint
ContainerState::GetLayerCreationHint(AnimatedGeometryRoot* aAnimatedGeometryRoot)
{
// Check whether the layer will be scrollable. This is used as a hint to
// influence whether tiled layers are used or not.
// Check creation hint inherited from our parent.
if (mParameters.mLayerCreationHint == LayerManager::SCROLLABLE) {
return LayerManager::SCROLLABLE;
}
// Check whether there's any active scroll frame on the animated geometry
// root chain.
for (AnimatedGeometryRoot* agr = aAnimatedGeometryRoot;
agr && agr != mContainerAnimatedGeometryRoot;
agr = agr->mParentAGR) {
nsIFrame* fParent = nsLayoutUtils::GetCrossDocParentFrame(*agr);
if (!fParent) {
break;
}
nsIScrollableFrame* scrollable = do_QueryFrame(fParent);
if (scrollable
#ifdef MOZ_B2G
&& scrollable->WantAsyncScroll()
#endif
) {
// WantAsyncScroll() returns false when the frame has overflow:hidden,
// so we won't create tiled layers for overflow:hidden frames even if
// they have a display port. The main purpose of the WantAsyncScroll check
// is to allow the B2G camera app to use hardware composer for compositing.
return LayerManager::SCROLLABLE;
}
}
return LayerManager::NONE;
}
already_AddRefed<PaintedLayer>
ContainerState::AttemptToRecyclePaintedLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot,
nsDisplayItem* aItem,
const nsPoint& aTopLeft)
{
Layer* oldLayer = mLayerBuilder->GetOldLayerFor(aItem);
if (!oldLayer || !oldLayer->AsPaintedLayer() ||
!mPaintedLayersAvailableForRecycling.Contains(oldLayer->AsPaintedLayer())) {
return nullptr;
}
// Try to recycle a layer
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<PaintedLayer> layer = oldLayer->AsPaintedLayer();
mPaintedLayersAvailableForRecycling.RemoveEntry(layer);
// Check if the layer hint has changed and whether or not the layer should
// be recreated because of it.
if (!layer->IsOptimizedFor(GetLayerCreationHint(aAnimatedGeometryRoot))) {
return nullptr;
}
bool didResetScrollPositionForLayerPixelAlignment = false;
PaintedDisplayItemLayerUserData* data =
RecyclePaintedLayer(layer, aAnimatedGeometryRoot,
didResetScrollPositionForLayerPixelAlignment);
PreparePaintedLayerForUse(layer, data, aAnimatedGeometryRoot, aItem->ReferenceFrame(),
aTopLeft,
didResetScrollPositionForLayerPixelAlignment);
return layer.forget();
}
already_AddRefed<PaintedLayer>
ContainerState::CreatePaintedLayer(PaintedLayerData* aData)
{
LayerManager::PaintedLayerCreationHint creationHint =
GetLayerCreationHint(aData->mAnimatedGeometryRoot);
// Create a new painted layer
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<PaintedLayer> layer = mManager->CreatePaintedLayerWithHint(creationHint);
if (!layer) {
return nullptr;
}
// Mark this layer as being used for painting display items
PaintedDisplayItemLayerUserData* userData = new PaintedDisplayItemLayerUserData();
layer->SetUserData(&gPaintedDisplayItemLayerUserData, userData);
ResetScrollPositionForLayerPixelAlignment(aData->mAnimatedGeometryRoot);
PreparePaintedLayerForUse(layer, userData, aData->mAnimatedGeometryRoot,
aData->mReferenceFrame,
aData->mAnimatedGeometryRootOffset, true);
return layer.forget();
}
PaintedDisplayItemLayerUserData*
ContainerState::RecyclePaintedLayer(PaintedLayer* aLayer,
AnimatedGeometryRoot* aAnimatedGeometryRoot,
bool& didResetScrollPositionForLayerPixelAlignment)
{
// Clear clip rect and mask layer so we don't accidentally stay clipped.
// We will reapply any necessary clipping.
ResetLayerStateForRecycling(aLayer);
aLayer->ClearExtraDumpInfo();
PaintedDisplayItemLayerUserData* data =
static_cast<PaintedDisplayItemLayerUserData*>(
aLayer->GetUserData(&gPaintedDisplayItemLayerUserData));
NS_ASSERTION(data, "Recycled PaintedLayers must have user data");
// This gets called on recycled PaintedLayers that are going to be in the
// final layer tree, so it's a convenient time to invalidate the
// content that changed where we don't know what PaintedLayer it belonged
// to, or if we need to invalidate the entire layer, we can do that.
// This needs to be done before we update the PaintedLayer to its new
// transform. See nsGfxScrollFrame::InvalidateInternal, where
// we ensure that mInvalidPaintedContent is updated according to the
// scroll position as of the most recent paint.
if (!FuzzyEqual(data->mXScale, mParameters.mXScale, 0.00001f) ||
!FuzzyEqual(data->mYScale, mParameters.mYScale, 0.00001f) ||
data->mAppUnitsPerDevPixel != mAppUnitsPerDevPixel) {
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Recycled layer %p changed scale\n", aLayer);
}
#endif
InvalidateEntirePaintedLayer(aLayer, aAnimatedGeometryRoot, "recycled layer changed state");
didResetScrollPositionForLayerPixelAlignment = true;
}
if (!data->mRegionToInvalidate.IsEmpty()) {
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Invalidating deleted frame content from layer %p\n", aLayer);
}
#endif
aLayer->InvalidateRegion(data->mRegionToInvalidate);
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
nsAutoCString str;
AppendToString(str, data->mRegionToInvalidate);
printf_stderr("Invalidating layer %p: %s\n", aLayer, str.get());
}
#endif
data->mRegionToInvalidate.SetEmpty();
}
return data;
}
void
ContainerState::PreparePaintedLayerForUse(PaintedLayer* aLayer,
PaintedDisplayItemLayerUserData* aData,
AnimatedGeometryRoot* aAnimatedGeometryRoot,
const nsIFrame* aReferenceFrame,
const nsPoint& aTopLeft,
bool didResetScrollPositionForLayerPixelAlignment)
{
aData->mXScale = mParameters.mXScale;
aData->mYScale = mParameters.mYScale;
aData->mLastAnimatedGeometryRootOrigin = aData->mAnimatedGeometryRootOrigin;
aData->mAnimatedGeometryRootOrigin = aTopLeft;
aData->mAppUnitsPerDevPixel = mAppUnitsPerDevPixel;
aLayer->SetAllowResidualTranslation(mParameters.AllowResidualTranslation());
mLayerBuilder->SavePreviousDataForLayer(aLayer, aData->mMaskClipCount);
// Set up transform so that 0,0 in the PaintedLayer corresponds to the
// (pixel-snapped) top-left of the aAnimatedGeometryRoot.
nsPoint offset = (*aAnimatedGeometryRoot)->GetOffsetToCrossDoc(aReferenceFrame);
nscoord appUnitsPerDevPixel = (*aAnimatedGeometryRoot)->PresContext()->AppUnitsPerDevPixel();
gfxPoint scaledOffset(
NSAppUnitsToDoublePixels(offset.x, appUnitsPerDevPixel)*mParameters.mXScale,
NSAppUnitsToDoublePixels(offset.y, appUnitsPerDevPixel)*mParameters.mYScale);
// We call RoundToMatchResidual here so that the residual after rounding
// is close to aData->mAnimatedGeometryRootPosition if possible.
nsIntPoint pixOffset(RoundToMatchResidual(scaledOffset.x, aData->mAnimatedGeometryRootPosition.x),
RoundToMatchResidual(scaledOffset.y, aData->mAnimatedGeometryRootPosition.y));
aData->mTranslation = pixOffset;
pixOffset += mParameters.mOffset;
Matrix matrix = Matrix::Translation(pixOffset.x, pixOffset.y);
aLayer->SetBaseTransform(Matrix4x4::From2D(matrix));
aData->mVisibilityComputedRegion.SetEmpty();
// FIXME: Temporary workaround for bug 681192 and bug 724786.
#ifndef MOZ_WIDGET_ANDROID
// Calculate exact position of the top-left of the active scrolled root.
// This might not be 0,0 due to the snapping in ScaleToNearestPixels.
gfxPoint animatedGeometryRootTopLeft = scaledOffset - ThebesPoint(matrix.GetTranslation()) + mParameters.mOffset;
// If it has changed, then we need to invalidate the entire layer since the
// pixels in the layer buffer have the content at a (subpixel) offset
// from what we need.
if (!animatedGeometryRootTopLeft.WithinEpsilonOf(aData->mAnimatedGeometryRootPosition, SUBPIXEL_OFFSET_EPSILON)) {
aData->mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft;
InvalidateEntirePaintedLayer(aLayer, aAnimatedGeometryRoot, "subpixel offset");
} else if (didResetScrollPositionForLayerPixelAlignment) {
aData->mAnimatedGeometryRootPosition = animatedGeometryRootTopLeft;
}
#else
Unused << didResetScrollPositionForLayerPixelAlignment;
#endif
}
#if defined(DEBUG) || defined(MOZ_DUMP_PAINTING)
/**
* Returns the appunits per dev pixel for the item's frame
*/
static int32_t
AppUnitsPerDevPixel(nsDisplayItem* aItem)
{
// The underlying frame for zoom items is the root frame of the subdocument.
// But zoom display items report their bounds etc using the parent document's
// APD because zoom items act as a conversion layer between the two different
// APDs.
if (aItem->GetType() == nsDisplayItem::TYPE_ZOOM) {
return static_cast<nsDisplayZoom*>(aItem)->GetParentAppUnitsPerDevPixel();
}
return aItem->Frame()->PresContext()->AppUnitsPerDevPixel();
}
#endif
/**
* Set the visible region for aLayer.
* aOuterVisibleRegion is the visible region relative to the parent layer.
* aLayerContentsVisibleRect, if non-null, is a rectangle in the layer's
* own coordinate system to which the layer's visible region is restricted.
* Consumes *aOuterVisibleRegion.
*/
static void
SetOuterVisibleRegion(Layer* aLayer, nsIntRegion* aOuterVisibleRegion,
const nsIntRect* aLayerContentsVisibleRect = nullptr,
bool aOuterUntransformed = false)
{
Matrix4x4 transform = aLayer->GetTransform();
Matrix transform2D;
if (aOuterUntransformed) {
if (aLayerContentsVisibleRect) {
aOuterVisibleRegion->And(*aOuterVisibleRegion,
*aLayerContentsVisibleRect);
}
} else if (transform.Is2D(&transform2D) && !transform2D.HasNonIntegerTranslation()) {
aOuterVisibleRegion->MoveBy(-int(transform2D._31), -int(transform2D._32));
if (aLayerContentsVisibleRect) {
aOuterVisibleRegion->And(*aOuterVisibleRegion, *aLayerContentsVisibleRect);
}
} else {
nsIntRect outerRect = aOuterVisibleRegion->GetBounds();
// if 'transform' is not invertible, then nothing will be displayed
// for the layer, so it doesn't really matter what we do here
Rect outerVisible(outerRect.x, outerRect.y, outerRect.width, outerRect.height);
transform.Invert();
Rect layerContentsVisible(-float(INT32_MAX) / 2, -float(INT32_MAX) / 2,
float(INT32_MAX), float(INT32_MAX));
if (aLayerContentsVisibleRect) {
NS_ASSERTION(aLayerContentsVisibleRect->width >= 0 &&
aLayerContentsVisibleRect->height >= 0,
"Bad layer contents rectangle");
// restrict to aLayerContentsVisibleRect before call GfxRectToIntRect,
// in case layerVisible is extremely large (as it can be when
// projecting through the inverse of a 3D transform)
layerContentsVisible = Rect(
aLayerContentsVisibleRect->x, aLayerContentsVisibleRect->y,
aLayerContentsVisibleRect->width, aLayerContentsVisibleRect->height);
}
gfxRect layerVisible = ThebesRect(transform.ProjectRectBounds(outerVisible, layerContentsVisible));
layerVisible.RoundOut();
nsIntRect visRect;
if (gfxUtils::GfxRectToIntRect(layerVisible, &visRect)) {
*aOuterVisibleRegion = visRect;
} else {
aOuterVisibleRegion->SetEmpty();
}
}
aLayer->SetVisibleRegion(LayerIntRegion::FromUnknownRegion(*aOuterVisibleRegion));
}
void
ContainerState::SetOuterVisibleRegionForLayer(Layer* aLayer,
const nsIntRegion& aOuterVisibleRegion,
const nsIntRect* aLayerContentsVisibleRect,
bool aOuterUntransformed) const
{
nsIntRegion visRegion = aOuterVisibleRegion;
if (!aOuterUntransformed) {
visRegion.MoveBy(mParameters.mOffset);
}
SetOuterVisibleRegion(aLayer, &visRegion, aLayerContentsVisibleRect,
aOuterUntransformed);
}
nscolor
ContainerState::FindOpaqueBackgroundColorInLayer(const PaintedLayerData* aData,
const nsIntRect& aRect,
bool* aOutIntersectsLayer) const
{
*aOutIntersectsLayer = true;
// Scan the candidate's display items.
nsIntRect deviceRect = aRect;
nsRect appUnitRect = ToAppUnits(deviceRect, mAppUnitsPerDevPixel);
appUnitRect.ScaleInverseRoundOut(mParameters.mXScale, mParameters.mYScale);
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
for (auto& assignedItem : Reversed(aData->mAssignedDisplayItems)) {
nsDisplayItem* item = assignedItem.mItem;
bool snap;
nsRect bounds = item->GetBounds(mBuilder, &snap);
if (snap && mSnappingEnabled) {
nsIntRect snappedBounds = ScaleToNearestPixels(bounds);
if (!snappedBounds.Intersects(deviceRect))
continue;
if (!snappedBounds.Contains(deviceRect))
return NS_RGBA(0,0,0,0);
} else {
// The layer's visible rect is already (close enough to) pixel
// aligned, so no need to round out and in here.
if (!bounds.Intersects(appUnitRect))
continue;
if (!bounds.Contains(appUnitRect))
return NS_RGBA(0,0,0,0);
}
if (item->IsInvisibleInRect(appUnitRect)) {
continue;
}
if (assignedItem.mClip.IsRectAffectedByClip(deviceRect,
mParameters.mXScale,
mParameters.mYScale,
mAppUnitsPerDevPixel)) {
return NS_RGBA(0,0,0,0);
}
Maybe<nscolor> color = item->IsUniform(mBuilder);
if (color && NS_GET_A(*color) == 255)
return *color;
return NS_RGBA(0,0,0,0);
}
*aOutIntersectsLayer = false;
return NS_RGBA(0,0,0,0);
}
nscolor
PaintedLayerDataNode::FindOpaqueBackgroundColor(const nsIntRegion& aTargetVisibleRegion,
int32_t aUnderIndex) const
{
if (aUnderIndex == ABOVE_TOP) {
aUnderIndex = mPaintedLayerDataStack.Length();
}
for (int32_t i = aUnderIndex - 1; i >= 0; --i) {
const PaintedLayerData* candidate = &mPaintedLayerDataStack[i];
if (candidate->VisibleAboveRegionIntersects(aTargetVisibleRegion)) {
// Some non-PaintedLayer content between target and candidate; this is
// hopeless
return NS_RGBA(0,0,0,0);
}
if (!candidate->VisibleRegionIntersects(aTargetVisibleRegion)) {
// The layer doesn't intersect our target, ignore it and move on
continue;
}
bool intersectsLayer = true;
nsIntRect rect = aTargetVisibleRegion.GetBounds();
nscolor color = mTree.ContState().FindOpaqueBackgroundColorInLayer(
candidate, rect, &intersectsLayer);
if (!intersectsLayer) {
continue;
}
return color;
}
if (mAllDrawingAboveBackground ||
!mVisibleAboveBackgroundRegion.Intersect(aTargetVisibleRegion).IsEmpty()) {
// Some non-PaintedLayer content is between this node's background and target.
return NS_RGBA(0,0,0,0);
}
return FindOpaqueBackgroundColorInParentNode();
}
nscolor
PaintedLayerDataNode::FindOpaqueBackgroundColorCoveringEverything() const
{
if (!mPaintedLayerDataStack.IsEmpty() ||
mAllDrawingAboveBackground ||
!mVisibleAboveBackgroundRegion.IsEmpty()) {
return NS_RGBA(0,0,0,0);
}
return FindOpaqueBackgroundColorInParentNode();
}
nscolor
PaintedLayerDataNode::FindOpaqueBackgroundColorInParentNode() const
{
if (mParent) {
if (mHasClip) {
// Check whether our parent node has uniform content behind our whole
// clip.
// There's one tricky case here: If our parent node is also a scrollable,
// and is currently scrolled in such a way that this inner one is
// clipped by it, then it's not really clear how we should determine
// whether we have a uniform background in the parent: There might be
// non-uniform content in the parts that our scroll port covers in the
// parent and that are currently outside the parent's clip.
// For now, we'll fail to pull a background color in that case.
return mParent->FindOpaqueBackgroundColor(mClipRect);
}
return mParent->FindOpaqueBackgroundColorCoveringEverything();
}
// We are the root.
return mTree.UniformBackgroundColor();
}
void
PaintedLayerData::UpdateCommonClipCount(
const DisplayItemClip& aCurrentClip)
{
if (mCommonClipCount >= 0) {
mCommonClipCount = mItemClip.GetCommonRoundedRectCount(aCurrentClip, mCommonClipCount);
} else {
// first item in the layer
mCommonClipCount = aCurrentClip.GetRoundedRectCount();
}
}
bool
PaintedLayerData::CanOptimizeToImageLayer(nsDisplayListBuilder* aBuilder)
{
if (!mImage) {
return false;
}
return mImage->CanOptimizeToImageLayer(mLayer->Manager(), aBuilder);
}
already_AddRefed<ImageContainer>
PaintedLayerData::GetContainerForImageLayer(nsDisplayListBuilder* aBuilder)
{
if (!mImage) {
return nullptr;
}
return mImage->GetContainer(mLayer->Manager(), aBuilder);
}
PaintedLayerDataNode::PaintedLayerDataNode(PaintedLayerDataTree& aTree,
PaintedLayerDataNode* aParent,
AnimatedGeometryRoot* aAnimatedGeometryRoot)
: mTree(aTree)
, mParent(aParent)
, mAnimatedGeometryRoot(aAnimatedGeometryRoot)
, mAllDrawingAboveBackground(false)
{
MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(mTree.Builder()->RootReferenceFrame(), *mAnimatedGeometryRoot));
mHasClip = mTree.IsClippedWithRespectToParentAnimatedGeometryRoot(mAnimatedGeometryRoot, &mClipRect);
}
PaintedLayerDataNode::~PaintedLayerDataNode()
{
MOZ_ASSERT(mPaintedLayerDataStack.IsEmpty());
MOZ_ASSERT(mChildren.IsEmpty());
}
PaintedLayerDataNode*
PaintedLayerDataNode::AddChildNodeFor(AnimatedGeometryRoot* aAnimatedGeometryRoot)
{
MOZ_ASSERT(aAnimatedGeometryRoot->mParentAGR == mAnimatedGeometryRoot);
UniquePtr<PaintedLayerDataNode> child =
MakeUnique<PaintedLayerDataNode>(mTree, this, aAnimatedGeometryRoot);
mChildren.AppendElement(Move(child));
return mChildren.LastElement().get();
}
template<typename NewPaintedLayerCallbackType>
PaintedLayerData*
PaintedLayerDataNode::FindPaintedLayerFor(const nsIntRect& aVisibleRect,
bool aBackfaceHidden,
const DisplayItemScrollClip* aScrollClip,
NewPaintedLayerCallbackType aNewPaintedLayerCallback)
{
if (!mPaintedLayerDataStack.IsEmpty()) {
PaintedLayerData* lowestUsableLayer = nullptr;
for (auto& data : Reversed(mPaintedLayerDataStack)) {
if (data.mVisibleAboveRegion.Intersects(aVisibleRect)) {
break;
}
if (data.mBackfaceHidden == aBackfaceHidden &&
data.mScrollClip == aScrollClip) {
lowestUsableLayer = &data;
}
nsIntRegion visibleRegion = data.mVisibleRegion;
// Also check whether the event-regions intersect the visible rect,
// unless we're in an inactive layer, in which case the event-regions
// will be hoisted out into their own layer.
// For performance reasons, we check the intersection with the bounds
// of the event-regions.
if (!mTree.ContState().IsInInactiveLayer() &&
(data.mScaledHitRegionBounds.Intersects(aVisibleRect) ||
data.mScaledMaybeHitRegionBounds.Intersects(aVisibleRect))) {
break;
}
if (visibleRegion.Intersects(aVisibleRect)) {
break;
}
}
if (lowestUsableLayer) {
return lowestUsableLayer;
}
}
return mPaintedLayerDataStack.AppendElement(aNewPaintedLayerCallback());
}
void
PaintedLayerDataNode::FinishChildrenIntersecting(const nsIntRect& aRect)
{
for (int32_t i = mChildren.Length() - 1; i >= 0; i--) {
if (mChildren[i]->Intersects(aRect)) {
mChildren[i]->Finish(true);
mChildren.RemoveElementAt(i);
}
}
}
void
PaintedLayerDataNode::FinishAllChildren(bool aThisNodeNeedsAccurateVisibleAboveRegion)
{
for (int32_t i = mChildren.Length() - 1; i >= 0; i--) {
mChildren[i]->Finish(aThisNodeNeedsAccurateVisibleAboveRegion);
}
mChildren.Clear();
}
void
PaintedLayerDataNode::Finish(bool aParentNeedsAccurateVisibleAboveRegion)
{
// Skip "visible above region" maintenance, because this node is going away.
FinishAllChildren(false);
PopAllPaintedLayerData();
if (mParent && aParentNeedsAccurateVisibleAboveRegion) {
if (mHasClip) {
mParent->AddToVisibleAboveRegion(mClipRect);
} else {
mParent->SetAllDrawingAbove();
}
}
mTree.NodeWasFinished(mAnimatedGeometryRoot);
}
void
PaintedLayerDataNode::AddToVisibleAboveRegion(const nsIntRect& aRect)
{
nsIntRegion& visibleAboveRegion = mPaintedLayerDataStack.IsEmpty()
? mVisibleAboveBackgroundRegion
: mPaintedLayerDataStack.LastElement().mVisibleAboveRegion;
visibleAboveRegion.Or(visibleAboveRegion, aRect);
visibleAboveRegion.SimplifyOutward(8);
}
void
PaintedLayerDataNode::SetAllDrawingAbove()
{
PopAllPaintedLayerData();
mAllDrawingAboveBackground = true;
mVisibleAboveBackgroundRegion.SetEmpty();
}
void
PaintedLayerDataNode::PopPaintedLayerData()
{
MOZ_ASSERT(!mPaintedLayerDataStack.IsEmpty());
size_t lastIndex = mPaintedLayerDataStack.Length() - 1;
PaintedLayerData& data = mPaintedLayerDataStack[lastIndex];
mTree.ContState().FinishPaintedLayerData(data, [this, &data, lastIndex]() {
return this->FindOpaqueBackgroundColor(data.mVisibleRegion, lastIndex);
});
mPaintedLayerDataStack.RemoveElementAt(lastIndex);
}
void
PaintedLayerDataNode::PopAllPaintedLayerData()
{
while (!mPaintedLayerDataStack.IsEmpty()) {
PopPaintedLayerData();
}
}
nsDisplayListBuilder*
PaintedLayerDataTree::Builder() const
{
return mContainerState.Builder();
}
void
PaintedLayerDataTree::Finish()
{
if (mRoot) {
mRoot->Finish(false);
}
MOZ_ASSERT(mNodes.Count() == 0);
mRoot = nullptr;
}
void
PaintedLayerDataTree::NodeWasFinished(AnimatedGeometryRoot* aAnimatedGeometryRoot)
{
mNodes.Remove(aAnimatedGeometryRoot);
}
void
PaintedLayerDataTree::AddingOwnLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot,
const nsIntRect* aRect,
nscolor* aOutUniformBackgroundColor)
{
FinishPotentiallyIntersectingNodes(aAnimatedGeometryRoot, aRect);
PaintedLayerDataNode* node = EnsureNodeFor(aAnimatedGeometryRoot);
if (aRect) {
if (aOutUniformBackgroundColor) {
*aOutUniformBackgroundColor = node->FindOpaqueBackgroundColor(*aRect);
}
node->AddToVisibleAboveRegion(*aRect);
} else {
if (aOutUniformBackgroundColor) {
*aOutUniformBackgroundColor = node->FindOpaqueBackgroundColorCoveringEverything();
}
node->SetAllDrawingAbove();
}
}
template<typename NewPaintedLayerCallbackType>
PaintedLayerData*
PaintedLayerDataTree::FindPaintedLayerFor(AnimatedGeometryRoot* aAnimatedGeometryRoot,
const DisplayItemScrollClip* aScrollClip,
const nsIntRect& aVisibleRect,
bool aBackfaceHidden,
NewPaintedLayerCallbackType aNewPaintedLayerCallback)
{
const nsIntRect* bounds = &aVisibleRect;
FinishPotentiallyIntersectingNodes(aAnimatedGeometryRoot, bounds);
PaintedLayerDataNode* node = EnsureNodeFor(aAnimatedGeometryRoot);
PaintedLayerData* data =
node->FindPaintedLayerFor(aVisibleRect, aBackfaceHidden, aScrollClip,
aNewPaintedLayerCallback);
return data;
}
void
PaintedLayerDataTree::FinishPotentiallyIntersectingNodes(AnimatedGeometryRoot* aAnimatedGeometryRoot,
const nsIntRect* aRect)
{
AnimatedGeometryRoot* ancestorThatIsChildOfCommonAncestor = nullptr;
PaintedLayerDataNode* ancestorNode =
FindNodeForAncestorAnimatedGeometryRoot(aAnimatedGeometryRoot,
&ancestorThatIsChildOfCommonAncestor);
if (!ancestorNode) {
// None of our ancestors are in the tree. This should only happen if this
// is the very first item we're looking at.
MOZ_ASSERT(!mRoot);
return;
}
if (ancestorNode->GetAnimatedGeometryRoot() == aAnimatedGeometryRoot) {
// aAnimatedGeometryRoot already has a node in the tree.
// This is the common case.
MOZ_ASSERT(!ancestorThatIsChildOfCommonAncestor);
if (aRect) {
ancestorNode->FinishChildrenIntersecting(*aRect);
} else {
ancestorNode->FinishAllChildren();
}
return;
}
// We have found an existing ancestor, but it's a proper ancestor of our
// animated geometry root.
// ancestorThatIsChildOfCommonAncestor is the last animated geometry root
// encountered on the way up from aAnimatedGeometryRoot to ancestorNode.
MOZ_ASSERT(ancestorThatIsChildOfCommonAncestor);
MOZ_ASSERT(nsLayoutUtils::IsAncestorFrameCrossDoc(*ancestorThatIsChildOfCommonAncestor, *aAnimatedGeometryRoot));
MOZ_ASSERT(ancestorThatIsChildOfCommonAncestor->mParentAGR == ancestorNode->GetAnimatedGeometryRoot());
// ancestorThatIsChildOfCommonAncestor is not in the tree yet!
MOZ_ASSERT(!mNodes.Get(ancestorThatIsChildOfCommonAncestor));
// We're about to add a node for ancestorThatIsChildOfCommonAncestor, so we
// finish all intersecting siblings.
nsIntRect clip;
if (IsClippedWithRespectToParentAnimatedGeometryRoot(ancestorThatIsChildOfCommonAncestor, &clip)) {
ancestorNode->FinishChildrenIntersecting(clip);
} else {
ancestorNode->FinishAllChildren();
}
}
PaintedLayerDataNode*
PaintedLayerDataTree::EnsureNodeFor(AnimatedGeometryRoot* aAnimatedGeometryRoot)
{
MOZ_ASSERT(aAnimatedGeometryRoot);
PaintedLayerDataNode* node = mNodes.Get(aAnimatedGeometryRoot);
if (node) {
return node;
}
AnimatedGeometryRoot* parentAnimatedGeometryRoot = aAnimatedGeometryRoot->mParentAGR;
if (!parentAnimatedGeometryRoot) {
MOZ_ASSERT(!mRoot);
MOZ_ASSERT(*aAnimatedGeometryRoot == Builder()->RootReferenceFrame());
mRoot = MakeUnique<PaintedLayerDataNode>(*this, nullptr, aAnimatedGeometryRoot);
node = mRoot.get();
} else {
PaintedLayerDataNode* parentNode = EnsureNodeFor(parentAnimatedGeometryRoot);
MOZ_ASSERT(parentNode);
node = parentNode->AddChildNodeFor(aAnimatedGeometryRoot);
}
MOZ_ASSERT(node);
mNodes.Put(aAnimatedGeometryRoot, node);
return node;
}
bool
PaintedLayerDataTree::IsClippedWithRespectToParentAnimatedGeometryRoot(AnimatedGeometryRoot* aAnimatedGeometryRoot,
nsIntRect* aOutClip)
{
nsIScrollableFrame* scrollableFrame = nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot);
if (!scrollableFrame) {
return false;
}
nsIFrame* scrollFrame = do_QueryFrame(scrollableFrame);
nsRect scrollPort = scrollableFrame->GetScrollPortRect() + Builder()->ToReferenceFrame(scrollFrame);
*aOutClip = mContainerState.ScaleToNearestPixels(scrollPort);
return true;
}
PaintedLayerDataNode*
PaintedLayerDataTree::FindNodeForAncestorAnimatedGeometryRoot(AnimatedGeometryRoot* aAnimatedGeometryRoot,
AnimatedGeometryRoot** aOutAncestorChild)
{
if (!aAnimatedGeometryRoot) {
return nullptr;
}
PaintedLayerDataNode* node = mNodes.Get(aAnimatedGeometryRoot);
if (node) {
return node;
}
*aOutAncestorChild = aAnimatedGeometryRoot;
return FindNodeForAncestorAnimatedGeometryRoot(aAnimatedGeometryRoot->mParentAGR, aOutAncestorChild);
}
static bool
CanOptimizeAwayPaintedLayer(PaintedLayerData* aData,
FrameLayerBuilder* aLayerBuilder)
{
if (!aLayerBuilder->IsBuildingRetainedLayers()) {
return false;
}
// If there's no painted layer with valid content in it that we can reuse,
// always create a color or image layer (and potentially throw away an
// existing completely invalid painted layer).
if (aData->mLayer->GetValidRegion().IsEmpty()) {
return true;
}
// There is an existing painted layer we can reuse. Throwing it away can make
// compositing cheaper (see bug 946952), but it might cause us to re-allocate
// the painted layer frequently due to an animation. So we only discard it if
// we're in tree compression mode, which is triggered at a low frequency.
return aLayerBuilder->CheckInLayerTreeCompressionMode();
}
#ifdef DEBUG
static int32_t FindIndexOfLayerIn(nsTArray<NewLayerEntry>& aArray,
Layer* aLayer)
{
for (uint32_t i = 0; i < aArray.Length(); ++i) {
if (aArray[i].mLayer == aLayer) {
return i;
}
}
return -1;
}
#endif
already_AddRefed<Layer>
ContainerState::PrepareImageLayer(PaintedLayerData* aData)
{
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<ImageContainer> imageContainer =
aData->GetContainerForImageLayer(mBuilder);
if (!imageContainer) {
return nullptr;
}
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<ImageLayer> imageLayer = CreateOrRecycleImageLayer(aData->mLayer);
imageLayer->SetContainer(imageContainer);
aData->mImage->ConfigureLayer(imageLayer, mParameters);
imageLayer->SetPostScale(mParameters.mXScale,
mParameters.mYScale);
if (aData->mItemClip.HasClip()) {
ParentLayerIntRect clip =
ViewAs<ParentLayerPixel>(ScaleToNearestPixels(aData->mItemClip.GetClipRect()));
clip.MoveBy(ViewAs<ParentLayerPixel>(mParameters.mOffset));
imageLayer->SetClipRect(Some(clip));
} else {
imageLayer->SetClipRect(Nothing());
}
mLayerBuilder->StoreOptimizedLayerForFrame(aData->mImage, imageLayer);
FLB_LOG_PAINTED_LAYER_DECISION(aData,
" Selected image layer=%p\n", imageLayer.get());
return imageLayer.forget();
}
already_AddRefed<Layer>
ContainerState::PrepareColorLayer(PaintedLayerData* aData)
{
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<ColorLayer> colorLayer = CreateOrRecycleColorLayer(aData->mLayer);
colorLayer->SetColor(Color::FromABGR(aData->mSolidColor));
// Copy transform
colorLayer->SetBaseTransform(aData->mLayer->GetBaseTransform());
colorLayer->SetPostScale(aData->mLayer->GetPostXScale(),
aData->mLayer->GetPostYScale());
nsIntRect visibleRect = aData->mVisibleRegion.GetBounds();
visibleRect.MoveBy(-GetTranslationForPaintedLayer(aData->mLayer));
colorLayer->SetBounds(visibleRect);
colorLayer->SetClipRect(Nothing());
FLB_LOG_PAINTED_LAYER_DECISION(aData,
" Selected color layer=%p\n", colorLayer.get());
return colorLayer.forget();
}
static void
SetBackfaceHiddenForLayer(bool aBackfaceHidden, Layer* aLayer)
{
if (aBackfaceHidden) {
aLayer->SetContentFlags(aLayer->GetContentFlags() |
Layer::CONTENT_BACKFACE_HIDDEN);
} else {
aLayer->SetContentFlags(aLayer->GetContentFlags() &
~Layer::CONTENT_BACKFACE_HIDDEN);
}
}
template<typename FindOpaqueBackgroundColorCallbackType>
void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueBackgroundColorCallbackType aFindOpaqueBackgroundColor)
{
PaintedLayerData* data = &aData;
if (!data->mLayer) {
// No layer was recycled, so we create a new one.
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<PaintedLayer> paintedLayer = CreatePaintedLayer(data);
data->mLayer = paintedLayer;
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, paintedLayer) < 0,
"Layer already in list???");
mNewChildLayers[data->mNewChildLayersIndex].mLayer = paintedLayer.forget();
}
for (auto& item : data->mAssignedDisplayItems) {
MOZ_ASSERT(item.mItem->GetType() != nsDisplayItem::TYPE_LAYER_EVENT_REGIONS);
InvalidateForLayerChange(item.mItem, data->mLayer);
mLayerBuilder->AddPaintedDisplayItem(data, item.mItem, item.mClip,
*this, item.mLayerState,
data->mAnimatedGeometryRootOffset);
}
NewLayerEntry* newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex];
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<Layer> layer;
bool canOptimizeToImageLayer = data->CanOptimizeToImageLayer(mBuilder);
FLB_LOG_PAINTED_LAYER_DECISION(data, "Selecting layer for pld=%p\n", data);
FLB_LOG_PAINTED_LAYER_DECISION(data, " Solid=%i, hasImage=%c, canOptimizeAwayPaintedLayer=%i\n",
data->mIsSolidColorInVisibleRegion, canOptimizeToImageLayer ? 'y' : 'n',
CanOptimizeAwayPaintedLayer(data, mLayerBuilder));
if ((data->mIsSolidColorInVisibleRegion || canOptimizeToImageLayer) &&
CanOptimizeAwayPaintedLayer(data, mLayerBuilder)) {
NS_ASSERTION(!(data->mIsSolidColorInVisibleRegion && canOptimizeToImageLayer),
"Can't be a solid color as well as an image!");
layer = canOptimizeToImageLayer ? PrepareImageLayer(data)
: PrepareColorLayer(data);
if (layer) {
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, layer) < 0,
"Layer already in list???");
NS_ASSERTION(newLayerEntry->mLayer == data->mLayer,
"Painted layer at wrong index");
// Store optimized layer in reserved slot
newLayerEntry = &mNewChildLayers[data->mNewChildLayersIndex + 1];
NS_ASSERTION(!newLayerEntry->mLayer, "Slot already occupied?");
newLayerEntry->mLayer = layer;
newLayerEntry->mAnimatedGeometryRoot = data->mAnimatedGeometryRoot;
newLayerEntry->mScrollClip = data->mScrollClip;
// Hide the PaintedLayer. We leave it in the layer tree so that we
// can find and recycle it later.
ParentLayerIntRect emptyRect;
data->mLayer->SetClipRect(Some(emptyRect));
data->mLayer->SetVisibleRegion(LayerIntRegion());
data->mLayer->InvalidateRegion(data->mLayer->GetValidRegion().GetBounds());
data->mLayer->SetEventRegions(EventRegions());
}
}
if (!layer) {
// We couldn't optimize to an image layer or a color layer above.
layer = data->mLayer;
layer->SetClipRect(Nothing());
FLB_LOG_PAINTED_LAYER_DECISION(data, " Selected painted layer=%p\n", layer.get());
}
// If the layer is a fixed background layer, the clip on the fixed background
// display item was not applied to the opaque region in
// ContainerState::ComputeOpaqueRect(), but was saved in data->mItemClip.
// Apply it to the opaque region now. Note that it's important to do this
// before the opaque region is propagated to the NewLayerEntry below.
if (data->mSingleItemFixedToViewport && data->mItemClip.HasClip()) {
nsRect clipRect = data->mItemClip.GetClipRect();
nsRect insideRoundedCorners = data->mItemClip.ApproximateIntersectInward(clipRect);
nsIntRect insideRoundedCornersScaled = ScaleToInsidePixels(insideRoundedCorners);
data->mOpaqueRegion.AndWith(insideRoundedCornersScaled);
}
if (mLayerBuilder->IsBuildingRetainedLayers()) {
newLayerEntry->mVisibleRegion = data->mVisibleRegion;
newLayerEntry->mOpaqueRegion = data->mOpaqueRegion;
newLayerEntry->mHideAllLayersBelow = data->mHideAllLayersBelow;
newLayerEntry->mOpaqueForAnimatedGeometryRootParent = data->mOpaqueForAnimatedGeometryRootParent;
} else {
SetOuterVisibleRegionForLayer(layer, data->mVisibleRegion);
}
nsIntRect layerBounds = data->mBounds;
layerBounds.MoveBy(-GetTranslationForPaintedLayer(data->mLayer));
layer->SetLayerBounds(layerBounds);
#ifdef MOZ_DUMP_PAINTING
if (!data->mLog.IsEmpty()) {
if (PaintedLayerData* containingPld = mLayerBuilder->GetContainingPaintedLayerData()) {
containingPld->mLayer->AddExtraDumpInfo(nsCString(data->mLog));
} else {
layer->AddExtraDumpInfo(nsCString(data->mLog));
}
}
#endif
nsIntRegion transparentRegion;
transparentRegion.Sub(data->mVisibleRegion, data->mOpaqueRegion);
bool isOpaque = transparentRegion.IsEmpty();
// For translucent PaintedLayers, try to find an opaque background
// color that covers the entire area beneath it so we can pull that
// color into this layer to make it opaque.
if (layer == data->mLayer) {
nscolor backgroundColor = NS_RGBA(0,0,0,0);
if (!isOpaque) {
backgroundColor = aFindOpaqueBackgroundColor();
if (NS_GET_A(backgroundColor) == 255) {
isOpaque = true;
}
}
// Store the background color
PaintedDisplayItemLayerUserData* userData =
GetPaintedDisplayItemLayerUserData(data->mLayer);
NS_ASSERTION(userData, "where did our user data go?");
if (userData->mForcedBackgroundColor != backgroundColor) {
// Invalidate the entire target PaintedLayer since we're changing
// the background color
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Forced background color has changed from #%08X to #%08X on layer %p\n",
userData->mForcedBackgroundColor, backgroundColor, data->mLayer);
nsAutoCString str;
AppendToString(str, data->mLayer->GetValidRegion());
printf_stderr("Invalidating layer %p: %s\n", data->mLayer, str.get());
}
#endif
data->mLayer->InvalidateRegion(data->mLayer->GetValidRegion());
}
userData->mForcedBackgroundColor = backgroundColor;
userData->mFontSmoothingBackgroundColor = data->mFontSmoothingBackgroundColor;
// use a mask layer for rounded rect clipping.
// data->mCommonClipCount may be -1 if we haven't put any actual
// drawable items in this layer (i.e. it's only catching events).
int32_t commonClipCount;
// If the layer contains a single item fixed to the viewport, we removed
// its clip in ProcessDisplayItems() and saved it to set on the layer instead.
// Set the clip on the layer now.
if (data->mSingleItemFixedToViewport && data->mItemClip.HasClip()) {
nsIntRect layerClipRect = ScaleToNearestPixels(data->mItemClip.GetClipRect());
layerClipRect.MoveBy(mParameters.mOffset);
// The clip from such an item becomes part of the layer's scrolled clip,
// and the associated mask layer one of the layer's "ancestor mask layers".
LayerClip scrolledClip;
scrolledClip.SetClipRect(ViewAs<ParentLayerPixel>(layerClipRect));
scrolledClip.SetMaskLayerIndex(
SetupMaskLayerForScrolledClip(data->mLayer, data->mItemClip));
data->mLayer->SetScrolledClip(Some(scrolledClip));
// There is only one item, so all of the clips are in common to all items.
// data->mCommonClipCount will be zero because we removed the clip from
// the display item. (It could also be -1 if we're inside an inactive
// layer tree in which we don't call UpdateCommonClipCount() at all.)
MOZ_ASSERT(data->mCommonClipCount == -1 || data->mCommonClipCount == 0);
commonClipCount = data->mItemClip.GetRoundedRectCount();
} else {
commonClipCount = std::max(0, data->mCommonClipCount);
SetupMaskLayer(layer, data->mItemClip, commonClipCount);
}
// copy commonClipCount to the entry
FrameLayerBuilder::PaintedLayerItemsEntry* entry = mLayerBuilder->
GetPaintedLayerItemsEntry(static_cast<PaintedLayer*>(layer.get()));
entry->mCommonClipCount = commonClipCount;
} else {
// mask layer for image and color layers
SetupMaskLayer(layer, data->mItemClip);
}
uint32_t flags = 0;
nsIWidget* widget = mContainerReferenceFrame->PresContext()->GetRootWidget();
// See bug 941095. Not quite ready to disable this.
bool hidpi = false && widget && widget->GetDefaultScale().scale >= 2;
if (hidpi) {
flags |= Layer::CONTENT_DISABLE_SUBPIXEL_AA;
}
if (isOpaque && !data->mForceTransparentSurface) {
flags |= Layer::CONTENT_OPAQUE;
} else if (data->mNeedComponentAlpha && !hidpi) {
flags |= Layer::CONTENT_COMPONENT_ALPHA;
}
if (data->mDisableFlattening) {
flags |= Layer::CONTENT_DISABLE_FLATTENING;
}
layer->SetContentFlags(flags);
PaintedLayerData* containingPaintedLayerData =
mLayerBuilder->GetContainingPaintedLayerData();
if (containingPaintedLayerData) {
if (!data->mDispatchToContentHitRegion.GetBounds().IsEmpty()) {
nsRect rect = nsLayoutUtils::TransformFrameRectToAncestor(
mContainerReferenceFrame,
data->mDispatchToContentHitRegion.GetBounds(),
containingPaintedLayerData->mReferenceFrame);
containingPaintedLayerData->mDispatchToContentHitRegion.Or(
containingPaintedLayerData->mDispatchToContentHitRegion, rect);
}
if (!data->mMaybeHitRegion.GetBounds().IsEmpty()) {
nsRect rect = nsLayoutUtils::TransformFrameRectToAncestor(
mContainerReferenceFrame,
data->mMaybeHitRegion.GetBounds(),
containingPaintedLayerData->mReferenceFrame);
containingPaintedLayerData->mMaybeHitRegion.Or(
containingPaintedLayerData->mMaybeHitRegion, rect);
containingPaintedLayerData->mMaybeHitRegion.SimplifyOutward(8);
}
Maybe<Matrix4x4> matrixCache;
nsLayoutUtils::TransformToAncestorAndCombineRegions(
data->mHitRegion,
mContainerReferenceFrame,
containingPaintedLayerData->mReferenceFrame,
&containingPaintedLayerData->mHitRegion,
&containingPaintedLayerData->mMaybeHitRegion,
&matrixCache);
// See the comment in nsDisplayList::AddFrame, where the touch action regions
// are handled. The same thing applies here.
bool alreadyHadRegions =
!containingPaintedLayerData->mNoActionRegion.IsEmpty() ||
!containingPaintedLayerData->mHorizontalPanRegion.IsEmpty() ||
!containingPaintedLayerData->mVerticalPanRegion.IsEmpty();
nsLayoutUtils::TransformToAncestorAndCombineRegions(
data->mNoActionRegion,
mContainerReferenceFrame,
containingPaintedLayerData->mReferenceFrame,
&containingPaintedLayerData->mNoActionRegion,
&containingPaintedLayerData->mDispatchToContentHitRegion,
&matrixCache);
nsLayoutUtils::TransformToAncestorAndCombineRegions(
data->mHorizontalPanRegion,
mContainerReferenceFrame,
containingPaintedLayerData->mReferenceFrame,
&containingPaintedLayerData->mHorizontalPanRegion,
&containingPaintedLayerData->mDispatchToContentHitRegion,
&matrixCache);
nsLayoutUtils::TransformToAncestorAndCombineRegions(
data->mVerticalPanRegion,
mContainerReferenceFrame,
containingPaintedLayerData->mReferenceFrame,
&containingPaintedLayerData->mVerticalPanRegion,
&containingPaintedLayerData->mDispatchToContentHitRegion,
&matrixCache);
if (alreadyHadRegions) {
containingPaintedLayerData->mDispatchToContentHitRegion.OrWith(
containingPaintedLayerData->CombinedTouchActionRegion());
}
} else {
EventRegions regions;
regions.mHitRegion = ScaleRegionToOutsidePixels(data->mHitRegion);
regions.mNoActionRegion = ScaleRegionToOutsidePixels(data->mNoActionRegion);
regions.mHorizontalPanRegion = ScaleRegionToOutsidePixels(data->mHorizontalPanRegion);
regions.mVerticalPanRegion = ScaleRegionToOutsidePixels(data->mVerticalPanRegion);
// Points whose hit-region status we're not sure about need to be dispatched
// to the content thread. If a point is in both maybeHitRegion and hitRegion
// then it's not a "maybe" any more, and doesn't go into the dispatch-to-
// content region.
nsIntRegion maybeHitRegion = ScaleRegionToOutsidePixels(data->mMaybeHitRegion);
regions.mDispatchToContentHitRegion.Sub(maybeHitRegion, regions.mHitRegion);
regions.mDispatchToContentHitRegion.OrWith(
ScaleRegionToOutsidePixels(data->mDispatchToContentHitRegion));
regions.mHitRegion.OrWith(maybeHitRegion);
Matrix mat = layer->GetTransform().As2D();
mat.Invert();
regions.ApplyTranslationAndScale(mat._31, mat._32, mat._11, mat._22);
layer->SetEventRegions(regions);
}
SetBackfaceHiddenForLayer(data->mBackfaceHidden, data->mLayer);
if (layer != data->mLayer) {
SetBackfaceHiddenForLayer(data->mBackfaceHidden, layer);
}
}
static bool
IsItemAreaInWindowOpaqueRegion(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem,
const nsRect& aComponentAlphaBounds)
{
if (!aItem->Frame()->PresContext()->IsChrome()) {
// Assume that Web content is always in the window opaque region.
return true;
}
if (aItem->ReferenceFrame() != aBuilder->RootReferenceFrame()) {
// aItem is probably in some transformed subtree.
// We're not going to bother figuring out where this landed, we're just
// going to assume it might have landed over a transparent part of
// the window.
return false;
}
return aBuilder->GetWindowOpaqueRegion().Contains(aComponentAlphaBounds);
}
void
PaintedLayerData::Accumulate(ContainerState* aState,
nsDisplayItem* aItem,
const nsIntRegion& aClippedOpaqueRegion,
const nsIntRect& aVisibleRect,
const DisplayItemClip& aClip,
LayerState aLayerState)
{
FLB_LOG_PAINTED_LAYER_DECISION(this, "Accumulating dp=%s(%p), f=%p against pld=%p\n", aItem->Name(), aItem, aItem->Frame(), this);
bool snap;
nsRect itemBounds = aItem->GetBounds(aState->mBuilder, &snap);
mBounds = mBounds.Union(aState->ScaleToOutsidePixels(itemBounds, snap));
if (aState->mBuilder->NeedToForceTransparentSurfaceForItem(aItem)) {
mForceTransparentSurface = true;
}
if (aState->mParameters.mDisableSubpixelAntialiasingInDescendants) {
// Disable component alpha.
// Note that the transform (if any) on the PaintedLayer is always an integer translation so
// we don't have to factor that in here.
aItem->DisableComponentAlpha();
}
bool clipMatches = mItemClip == aClip;
mItemClip = aClip;
mAssignedDisplayItems.AppendElement(AssignedDisplayItem(aItem, aClip, aLayerState));
if (!mIsSolidColorInVisibleRegion && mOpaqueRegion.Contains(aVisibleRect) &&
mVisibleRegion.Contains(aVisibleRect) && !mImage) {
// A very common case! Most pages have a PaintedLayer with the page
// background (opaque) visible and most or all of the page content over the
// top of that background.
// The rest of this method won't do anything. mVisibleRegion and mOpaqueRegion
// don't need updating. mVisibleRegion contains aVisibleRect already,
// mOpaqueRegion contains aVisibleRect and therefore whatever the opaque
// region of the item is. mVisibleRegion must contain mOpaqueRegion
// and therefore aVisibleRect.
return;
}
/* Mark as available for conversion to image layer if this is a nsDisplayImage and
* it's the only thing visible in this layer.
*/
if (nsIntRegion(aVisibleRect).Contains(mVisibleRegion) &&
aClippedOpaqueRegion.Contains(mVisibleRegion) &&
aItem->SupportsOptimizingToImage()) {
mImage = static_cast<nsDisplayImageContainer*>(aItem);
FLB_LOG_PAINTED_LAYER_DECISION(this, " Tracking image: nsDisplayImageContainer covers the layer\n");
} else if (mImage) {
FLB_LOG_PAINTED_LAYER_DECISION(this, " No longer tracking image\n");
mImage = nullptr;
}
bool isFirstVisibleItem = mVisibleRegion.IsEmpty();
if (isFirstVisibleItem) {
nscolor fontSmoothingBGColor;
if (aItem->ProvidesFontSmoothingBackgroundColor(&fontSmoothingBGColor)) {
mFontSmoothingBackgroundColor = fontSmoothingBGColor;
}
}
Maybe<nscolor> uniformColor = aItem->IsUniform(aState->mBuilder);
// Some display items have to exist (so they can set forceTransparentSurface
// below) but don't draw anything. They'll return true for isUniform but
// a color with opacity 0.
if (!uniformColor || NS_GET_A(*uniformColor) > 0) {
// Make sure that the visible area is covered by uniform pixels. In
// particular this excludes cases where the edges of the item are not
// pixel-aligned (thus the item will not be truly uniform).
if (uniformColor) {
bool snap;
nsRect bounds = aItem->GetBounds(aState->mBuilder, &snap);
if (!aState->ScaleToInsidePixels(bounds, snap).Contains(aVisibleRect)) {
uniformColor = Nothing();
FLB_LOG_PAINTED_LAYER_DECISION(this, " Display item does not cover the visible rect\n");
}
}
if (uniformColor) {
if (isFirstVisibleItem) {
// This color is all we have
mSolidColor = *uniformColor;
mIsSolidColorInVisibleRegion = true;
} else if (mIsSolidColorInVisibleRegion &&
mVisibleRegion.IsEqual(nsIntRegion(aVisibleRect)) &&
clipMatches) {
// we can just blend the colors together
mSolidColor = NS_ComposeColors(mSolidColor, *uniformColor);
} else {
FLB_LOG_PAINTED_LAYER_DECISION(this, " Layer not a solid color: Can't blend colors togethers\n");
mIsSolidColorInVisibleRegion = false;
}
} else {
FLB_LOG_PAINTED_LAYER_DECISION(this, " Layer is not a solid color: Display item is not uniform over the visible bound\n");
mIsSolidColorInVisibleRegion = false;
}
mVisibleRegion.Or(mVisibleRegion, aVisibleRect);
mVisibleRegion.SimplifyOutward(4);
}
if (!aClippedOpaqueRegion.IsEmpty()) {
for (auto iter = aClippedOpaqueRegion.RectIter(); !iter.Done(); iter.Next()) {
// We don't use SimplifyInward here since it's not defined exactly
// what it will discard. For our purposes the most important case
// is a large opaque background at the bottom of z-order (e.g.,
// a canvas background), so we need to make sure that the first rect
// we see doesn't get discarded.
nsIntRegion tmp;
tmp.Or(mOpaqueRegion, iter.Get());
// Opaque display items in chrome documents whose window is partially
// transparent are always added to the opaque region. This helps ensure
// that we get as much subpixel-AA as possible in the chrome.
if (tmp.GetNumRects() <= 4 || aItem->Frame()->PresContext()->IsChrome()) {
mOpaqueRegion = Move(tmp);
}
}
}
if (!aState->mParameters.mDisableSubpixelAntialiasingInDescendants) {
nsRect componentAlpha = aItem->GetComponentAlphaBounds(aState->mBuilder);
if (!componentAlpha.IsEmpty()) {
nsIntRect componentAlphaRect =
aState->ScaleToOutsidePixels(componentAlpha, false).Intersect(aVisibleRect);
if (!mOpaqueRegion.Contains(componentAlphaRect)) {
if (IsItemAreaInWindowOpaqueRegion(aState->mBuilder, aItem,
componentAlpha.Intersect(aItem->GetVisibleRect()))) {
Backed out 46 changesets (bug 1022612) for B2G mochitest permafails on a CLOSED TREE. Backed out changeset 34b3014a3112 (bug 1022612) Backed out changeset 6ae9316fd909 (bug 1022612) Backed out changeset b8f3749c95eb (bug 1022612) Backed out changeset caab10bf6ca3 (bug 1022612) Backed out changeset 0c57c620c898 (bug 1022612) Backed out changeset fac64141a00a (bug 1022612) Backed out changeset bf0df1c9d68b (bug 1022612) Backed out changeset b42054800020 (bug 1022612) Backed out changeset 667793b21194 (bug 1022612) Backed out changeset f14ada64fe1b (bug 1022612) Backed out changeset 75b837686bdf (bug 1022612) Backed out changeset 66de53183a22 (bug 1022612) Backed out changeset 0ff86ced4d46 (bug 1022612) Backed out changeset 18eecc5b1ef7 (bug 1022612) Backed out changeset 2763c4878de5 (bug 1022612) Backed out changeset b72413ecc385 (bug 1022612) Backed out changeset b23f1081afb8 (bug 1022612) Backed out changeset f7e2c6a72043 (bug 1022612) Backed out changeset 959917c9027d (bug 1022612) Backed out changeset 0268a46f4880 (bug 1022612) Backed out changeset 3388856a80ad (bug 1022612) Backed out changeset e4b17cf0f806 (bug 1022612) Backed out changeset 2f4e9da0e4b6 (bug 1022612) Backed out changeset 489f6a7c0c03 (bug 1022612) Backed out changeset 8369d9ad7ad3 (bug 1022612) Backed out changeset 0758d2a06002 (bug 1022612) Backed out changeset f2ae9cb22edb (bug 1022612) Backed out changeset 9c48c6ee5dc2 (bug 1022612) Backed out changeset fe7134400f08 (bug 1022612) Backed out changeset cc2c5397ca8b (bug 1022612) Backed out changeset a3d1a3e8b39d (bug 1022612) Backed out changeset 8974b74b0eb0 (bug 1022612) Backed out changeset 75f7dbb5a2a6 (bug 1022612) Backed out changeset 2aa04a071e60 (bug 1022612) Backed out changeset f2ab1bcd4c39 (bug 1022612) Backed out changeset da9152b6ea29 (bug 1022612) Backed out changeset 58abf5b0e148 (bug 1022612) Backed out changeset 797058a09ad2 (bug 1022612) Backed out changeset ea3e99a92ff0 (bug 1022612) Backed out changeset adc4a4a7aa73 (bug 1022612) Backed out changeset 7b18dedd1505 (bug 1022612) Backed out changeset 055dd1921e8e (bug 1022612) Backed out changeset 42fa2c97e989 (bug 1022612) Backed out changeset cd594236388f (bug 1022612) Backed out changeset 9eadc5fee43d (bug 1022612) Backed out changeset 5cc8d30ff7c9 (bug 1022612)
2014-07-17 15:24:47 +00:00
mNeedComponentAlpha = true;
} else {
aItem->DisableComponentAlpha();
}
}
}
}
// Ensure animated text does not get flattened, even if it forces other
// content in the container to be layerized. The content backend might
// not support subpixel positioning of text that animated transforms can
// generate. bug 633097
if (aState->mParameters.mInActiveTransformedSubtree &&
(mNeedComponentAlpha ||
!aItem->GetComponentAlphaBounds(aState->mBuilder).IsEmpty())) {
mDisableFlattening = true;
}
}
nsRegion
PaintedLayerData::CombinedTouchActionRegion()
{
nsRegion result;
result.Or(mHorizontalPanRegion, mVerticalPanRegion);
result.OrWith(mNoActionRegion);
return result;
}
void
PaintedLayerData::AccumulateEventRegions(ContainerState* aState, nsDisplayLayerEventRegions* aEventRegions)
{
FLB_LOG_PAINTED_LAYER_DECISION(this, "Accumulating event regions %p against pld=%p\n", aEventRegions, this);
mHitRegion.OrWith(aEventRegions->HitRegion());
mMaybeHitRegion.OrWith(aEventRegions->MaybeHitRegion());
mDispatchToContentHitRegion.OrWith(aEventRegions->DispatchToContentHitRegion());
// See the comment in nsDisplayList::AddFrame, where the touch action regions
// are handled. The same thing applies here.
bool alreadyHadRegions = !mNoActionRegion.IsEmpty() ||
!mHorizontalPanRegion.IsEmpty() ||
!mVerticalPanRegion.IsEmpty();
mNoActionRegion.OrWith(aEventRegions->NoActionRegion());
mHorizontalPanRegion.OrWith(aEventRegions->HorizontalPanRegion());
mVerticalPanRegion.OrWith(aEventRegions->VerticalPanRegion());
if (alreadyHadRegions) {
mDispatchToContentHitRegion.OrWith(CombinedTouchActionRegion());
}
// Calculate scaled versions of the bounds of mHitRegion and mMaybeHitRegion
// for quick access in FindPaintedLayerFor().
mScaledHitRegionBounds = aState->ScaleToOutsidePixels(mHitRegion.GetBounds());
mScaledMaybeHitRegionBounds = aState->ScaleToOutsidePixels(mMaybeHitRegion.GetBounds());
}
PaintedLayerData
ContainerState::NewPaintedLayerData(nsDisplayItem* aItem,
AnimatedGeometryRoot* aAnimatedGeometryRoot,
const DisplayItemScrollClip* aScrollClip,
const nsPoint& aTopLeft,
bool aShouldFixToViewport)
{
PaintedLayerData data;
data.mAnimatedGeometryRoot = aAnimatedGeometryRoot;
data.mScrollClip = aScrollClip;
data.mAnimatedGeometryRootOffset = aTopLeft;
data.mReferenceFrame = aItem->ReferenceFrame();
data.mSingleItemFixedToViewport = aShouldFixToViewport;
data.mBackfaceHidden = aItem->Frame()->In3DContextAndBackfaceIsHidden();
data.mNewChildLayersIndex = mNewChildLayers.Length();
NewLayerEntry* newLayerEntry = mNewChildLayers.AppendElement();
newLayerEntry->mAnimatedGeometryRoot = aAnimatedGeometryRoot;
newLayerEntry->mScrollClip = aScrollClip;
// newLayerEntry->mOpaqueRegion is filled in later from
// paintedLayerData->mOpaqueRegion, if necessary.
// Allocate another entry for this layer's optimization to ColorLayer/ImageLayer
mNewChildLayers.AppendElement();
return data;
}
#ifdef MOZ_DUMP_PAINTING
static void
DumpPaintedImage(nsDisplayItem* aItem, SourceSurface* aSurface)
{
nsCString string(aItem->Name());
string.Append('-');
string.AppendInt((uint64_t)aItem);
fprintf_stderr(gfxUtils::sDumpPaintFile, "<script>array[\"%s\"]=\"", string.BeginReading());
gfxUtils::DumpAsDataURI(aSurface, gfxUtils::sDumpPaintFile);
fprintf_stderr(gfxUtils::sDumpPaintFile, "\";</script>\n");
}
#endif
static void
PaintInactiveLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
nsDisplayItem* aItem,
gfxContext* aContext,
nsRenderingContext* aCtx)
{
// This item has an inactive layer. Render it to a PaintedLayer
// using a temporary BasicLayerManager.
BasicLayerManager* basic = static_cast<BasicLayerManager*>(aManager);
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<gfxContext> context = aContext;
#ifdef MOZ_DUMP_PAINTING
int32_t appUnitsPerDevPixel = AppUnitsPerDevPixel(aItem);
nsIntRect itemVisibleRect =
aItem->GetVisibleRect().ToOutsidePixels(appUnitsPerDevPixel);
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<DrawTarget> tempDT;
if (gfxEnv::DumpPaint()) {
tempDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
itemVisibleRect.Size(),
SurfaceFormat::B8G8R8A8);
if (tempDT) {
context = gfxContext::CreateOrNull(tempDT);
if (!context) {
// Leave this as crash, it's in the debugging code, we want to know
gfxDevCrash(LogReason::InvalidContext) << "PaintInactive context problem " << gfx::hexa(tempDT);
return;
}
context->SetMatrix(gfxMatrix::Translation(-itemVisibleRect.x,
-itemVisibleRect.y));
}
}
#endif
basic->BeginTransaction();
basic->SetTarget(context);
if (aItem->GetType() == nsDisplayItem::TYPE_MASK) {
static_cast<nsDisplayMask*>(aItem)->PaintAsLayer(aBuilder, aCtx, basic);
if (basic->InTransaction()) {
basic->AbortTransaction();
}
} else if (aItem->GetType() == nsDisplayItem::TYPE_FILTER){
static_cast<nsDisplayFilter*>(aItem)->PaintAsLayer(aBuilder, aCtx, basic);
if (basic->InTransaction()) {
basic->AbortTransaction();
}
} else {
basic->EndTransaction(FrameLayerBuilder::DrawPaintedLayer, aBuilder);
}
FrameLayerBuilder *builder = static_cast<FrameLayerBuilder*>(basic->GetUserData(&gLayerManagerLayerBuilder));
if (builder) {
builder->DidEndTransaction();
}
basic->SetTarget(nullptr);
#ifdef MOZ_DUMP_PAINTING
if (gfxEnv::DumpPaint() && tempDT) {
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<SourceSurface> surface = tempDT->Snapshot();
DumpPaintedImage(aItem, surface);
DrawTarget* drawTarget = aContext->GetDrawTarget();
Rect rect(itemVisibleRect.x, itemVisibleRect.y,
itemVisibleRect.width, itemVisibleRect.height);
drawTarget->DrawSurface(surface, rect, Rect(Point(0,0), rect.Size()));
aItem->SetPainted();
}
#endif
}
/**
* Chooses a single active scrolled root for the entire display list, used
* when we are flattening layers.
*/
bool
ContainerState::ChooseAnimatedGeometryRoot(const nsDisplayList& aList,
AnimatedGeometryRoot **aAnimatedGeometryRoot)
{
for (nsDisplayItem* item = aList.GetBottom(); item; item = item->GetAbove()) {
LayerState layerState = item->GetLayerState(mBuilder, mManager, mParameters);
// Don't use an item that won't be part of any PaintedLayers to pick the
// active scrolled root.
if (layerState == LAYER_ACTIVE_FORCE) {
continue;
}
// Try using the actual active scrolled root of the backmost item, as that
// should result in the least invalidation when scrolling.
*aAnimatedGeometryRoot = item->GetAnimatedGeometryRoot();
return true;
}
return false;
}
nsIntRegion
ContainerState::ComputeOpaqueRect(nsDisplayItem* aItem,
AnimatedGeometryRoot* aAnimatedGeometryRoot,
const DisplayItemClip& aClip,
nsDisplayList* aList,
bool* aHideAllLayersBelow,
bool* aOpaqueForAnimatedGeometryRootParent)
{
bool snapOpaque;
nsRegion opaque = aItem->GetOpaqueRegion(mBuilder, &snapOpaque);
if (opaque.IsEmpty()) {
return nsIntRegion();
}
nsIntRegion opaquePixels;
nsRegion opaqueClipped;
for (auto iter = opaque.RectIter(); !iter.Done(); iter.Next()) {
opaqueClipped.Or(opaqueClipped,
aClip.ApproximateIntersectInward(iter.Get()));
}
if (aAnimatedGeometryRoot == mContainerAnimatedGeometryRoot &&
opaqueClipped.Contains(mContainerBounds)) {
*aHideAllLayersBelow = true;
aList->SetIsOpaque();
}
// Add opaque areas to the "exclude glass" region. Only do this when our
// container layer is going to be the rootmost layer, otherwise transforms
// etc will mess us up (and opaque contributions from other containers are
// not needed).
if (!nsLayoutUtils::GetCrossDocParentFrame(mContainerFrame)) {
mBuilder->AddWindowOpaqueRegion(opaqueClipped);
}
opaquePixels = ScaleRegionToInsidePixels(opaqueClipped, snapOpaque);
if (IsInInactiveLayer()) {
return opaquePixels;
}
nsIScrollableFrame* sf = nsLayoutUtils::GetScrollableFrameFor(*aAnimatedGeometryRoot);
if (sf) {
nsRect displayport;
bool usingDisplayport =
nsLayoutUtils::GetDisplayPort((*aAnimatedGeometryRoot)->GetContent(), &displayport,
RelativeTo::ScrollFrame);
if (!usingDisplayport) {
// No async scrolling, so all that matters is that the layer contents
// cover the scrollport.
displayport = sf->GetScrollPortRect();
}
nsIFrame* scrollFrame = do_QueryFrame(sf);
displayport += scrollFrame->GetOffsetToCrossDoc(mContainerReferenceFrame);
Bug 1012752 - Snap scrolled area to layer pixels. r=tnikkel We want the maximum scroll position to be aligned with layer pixels. That way we don't have to re-rasterize the scrolled contents once scrolling hits the edge of the scrollable area. Here's how we determine the maximum scroll position: We get the scroll port rect, snapped to layer pixels. Then we get the scrolled rect and also snap that to layer pixels. The maximum scroll position is set to the difference between right/bottom edges of these rectangles. Now the scrollable area is computed by adding this maximum scroll position to the unsnapped scroll port size. The underlying idea here is: Pretend we have overflow:visible so that the scrolled contents start at (0, 0) relative to the scroll port and spill over the scroll port edges. When these contents are rendered, their rendering is snapped to layer pixels. We want those exact pixels to be accessible by scrolling. This way of computing the snapped scrollable area ensures that, if you scroll to the maximum scroll position, the right/bottom edges of the rendered scrolled contents line up exactly with the right/bottom edges of the scroll port. The scrolled contents are neither cut off nor are they moved too far. (This is something that no other browser engine gets completely right, see the testcase in bug 1012752.) There are also a few disadvantages to this solution. We snap to layer pixels, and the size of a layer pixel can depend on the zoom level, the document resolution, the current screen's scale factor, and CSS transforms. The snap origin is the position of the reference frame. So a change to any of these things can influence the scrollable area and the maximum scroll position. This patch does not make us adjust the current scroll position in the event that the maximum scroll position changes such that the current scroll position would be out of range, unless there's a reflow of the scrolled contents. This means that we can sometimes render a slightly inconsistent state where the current scroll position exceeds the maximum scroll position. We can fix this once it turns out to be a problem; I doubt that it will be a problem because none of the other browsers seems to prevent this problem either. The size of the scrollable area is exposed through the DOM properties scrollWidth and scrollHeight. At the moment, these are integer properties, so their value is rounded to the nearest CSS pixel. Before this patch, the returned value would always be within 0.5 CSS pixels of the value that layout computed for the content's scrollable overflow based on the CSS styles of the contents. Now that scrollWidth and scrollHeight also depend on pixel snapping, their values can deviate by up to one layer pixel from what the page might expect based on the styles of the contents. This change requires a few changes to existing tests. The fact that scrollWidth and scrollHeight can change based on the position of the scrollable element and the zoom level / resolution may surprise some web pages. However, this also seems to happen in Edge. Edge seems to always round scrollWidth and scrollHeight upwards, possibly to their equivalent of layout device pixels. MozReview-Commit-ID: 3LFV7Lio4tG --HG-- extra : rebase_source : 3e4e0b60493397e61283aa1d7fd93d7c197dec29 extra : source : d43c2d5e87f31ff47d7f3ada66c3f5f27cef84a9
2016-08-05 03:51:58 +00:00
if (opaquePixels.Contains(ScaleRegionToNearestPixels(displayport))) {
*aOpaqueForAnimatedGeometryRootParent = true;
}
}
return opaquePixels;
}
static const DisplayItemScrollClip*
InnermostScrollClipApplicableToAGR(const DisplayItemScrollClip* aItemScrollClip,
AnimatedGeometryRoot* aAnimatedGeometryRoot)
{
// "Applicable" scroll clips are those that are for nsIScrollableFrames
// that are ancestors of aAnimatedGeometryRoot or ancestors of aContainerScrollClip.
// They can be applied to all items sharing this animated geometry root, so
// instead of applying to the items individually, they can be applied to the
// whole layer.
for (const DisplayItemScrollClip* scrollClip = aItemScrollClip;
scrollClip;
scrollClip = scrollClip->mParent) {
nsIFrame* scrolledFrame = scrollClip->mScrollableFrame->GetScrolledFrame();
if (nsLayoutUtils::IsAncestorFrameCrossDoc(scrolledFrame, *aAnimatedGeometryRoot)) {
// scrollClip and all its ancestors are applicable.
return scrollClip;
}
}
return nullptr;
}
Maybe<size_t>
ContainerState::SetupMaskLayerForScrolledClip(Layer* aLayer,
const DisplayItemClip& aClip)
{
if (aClip.GetRoundedRectCount() > 0) {
Maybe<size_t> maskLayerIndex = Some(aLayer->GetAncestorMaskLayerCount());
if (RefPtr<Layer> maskLayer = CreateMaskLayer(aLayer, aClip, maskLayerIndex,
aClip.GetRoundedRectCount())) {
aLayer->AddAncestorMaskLayer(maskLayer);
return maskLayerIndex;
}
// Fall through to |return Nothing()|.
}
return Nothing();
}
/*
* Iterate through the non-clip items in aList and its descendants.
* For each item we compute the effective clip rect. Each item is assigned
* to a layer. We invalidate the areas in PaintedLayers where an item
* has moved from one PaintedLayer to another. Also,
* aState->mInvalidPaintedContent is invalidated in every PaintedLayer.
* We set the clip rect for items that generated their own layer, and
* create a mask layer to do any rounded rect clipping.
* (PaintedLayers don't need a clip rect on the layer, we clip the items
* individually when we draw them.)
* We set the visible rect for all layers, although the actual setting
* of visible rects for some PaintedLayers is deferred until the calling
* of ContainerState::Finish.
*/
void
ContainerState::ProcessDisplayItems(nsDisplayList* aList)
{
PROFILER_LABEL("ContainerState", "ProcessDisplayItems",
js::ProfileEntry::Category::GRAPHICS);
AnimatedGeometryRoot* lastAnimatedGeometryRoot = mContainerAnimatedGeometryRoot;
nsPoint lastAGRTopLeft;
nsPoint topLeft(0,0);
// When NO_COMPONENT_ALPHA is set, items will be flattened into a single
// layer, so we need to choose which active scrolled root to use for all
// items.
if (mFlattenToSingleLayer) {
if (ChooseAnimatedGeometryRoot(*aList, &lastAnimatedGeometryRoot)) {
lastAGRTopLeft = (*lastAnimatedGeometryRoot)->GetOffsetToCrossDoc(mContainerReferenceFrame);
}
}
int32_t maxLayers = gfxPrefs::MaxActiveLayers();
int layerCount = 0;
nsDisplayList savedItems;
nsDisplayItem* item;
while ((item = aList->RemoveBottom()) != nullptr) {
nsDisplayItem::Type itemType = item->GetType();
// If the item is a event regions item, but is empty (has no regions in it)
// then we should just throw it out
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
nsDisplayLayerEventRegions* eventRegions =
static_cast<nsDisplayLayerEventRegions*>(item);
if (eventRegions->IsEmpty()) {
item->~nsDisplayItem();
continue;
}
}
// Peek ahead to the next item and try merging with it or swapping with it
// if necessary.
nsDisplayItem* aboveItem;
while ((aboveItem = aList->GetBottom()) != nullptr) {
if (aboveItem->TryMerge(item)) {
aList->RemoveBottom();
item->~nsDisplayItem();
item = aboveItem;
itemType = item->GetType();
} else {
break;
}
}
nsDisplayList* itemSameCoordinateSystemChildren
= item->GetSameCoordinateSystemChildren();
if (item->ShouldFlattenAway(mBuilder)) {
aList->AppendToBottom(itemSameCoordinateSystemChildren);
item->~nsDisplayItem();
continue;
}
savedItems.AppendToTop(item);
NS_ASSERTION(mAppUnitsPerDevPixel == AppUnitsPerDevPixel(item),
"items in a container layer should all have the same app units per dev pixel");
if (mBuilder->NeedToForceTransparentSurfaceForItem(item)) {
aList->SetNeedsTransparentSurface();
}
if (mParameters.mForEventsAndPluginsOnly && !item->GetChildren() &&
(itemType != nsDisplayItem::TYPE_LAYER_EVENT_REGIONS &&
itemType != nsDisplayItem::TYPE_PLUGIN)) {
continue;
}
LayerState layerState = item->GetLayerState(mBuilder, mManager, mParameters);
if (layerState == LAYER_INACTIVE &&
nsDisplayItem::ForceActiveLayers()) {
layerState = LAYER_ACTIVE;
}
bool forceInactive;
AnimatedGeometryRoot* animatedGeometryRoot;
AnimatedGeometryRoot* animatedGeometryRootForClip = nullptr;
if (mFlattenToSingleLayer && layerState != LAYER_ACTIVE_FORCE) {
forceInactive = true;
animatedGeometryRoot = lastAnimatedGeometryRoot;
topLeft = lastAGRTopLeft;
} else {
forceInactive = false;
if (mManager->IsWidgetLayerManager()) {
animatedGeometryRoot = item->GetAnimatedGeometryRoot();
animatedGeometryRootForClip = item->AnimatedGeometryRootForScrollMetadata();
} else {
// For inactive layer subtrees, splitting content into PaintedLayers
// based on animated geometry roots is pointless. It's more efficient
// to build the minimum number of layers.
animatedGeometryRoot = mContainerAnimatedGeometryRoot;
}
topLeft = (*animatedGeometryRoot)->GetOffsetToCrossDoc(mContainerReferenceFrame);
}
if (!animatedGeometryRootForClip) {
animatedGeometryRootForClip = animatedGeometryRoot;
}
const DisplayItemScrollClip* itemScrollClip = item->ScrollClip();
// Now we need to separate the item's scroll clip chain into those scroll
// clips that can be applied to the whole layer (i.e. to all items
// sharing the item's animated geometry root), and those that need to be
// applied to the item itself.
const DisplayItemScrollClip* agrScrollClip =
InnermostScrollClipApplicableToAGR(itemScrollClip, animatedGeometryRootForClip);
MOZ_ASSERT(DisplayItemScrollClip::IsAncestor(agrScrollClip, itemScrollClip));
if (agrScrollClip != itemScrollClip) {
// Pick up any scroll clips that should apply to the item and apply them.
DisplayItemClip clip = item->GetClip();
for (const DisplayItemScrollClip* scrollClip = itemScrollClip;
scrollClip && scrollClip != agrScrollClip && scrollClip != mContainerScrollClip;
scrollClip = scrollClip->mParent) {
if (scrollClip->mClip) {
clip.IntersectWith(*scrollClip->mClip);
}
}
item->SetClip(mBuilder, clip);
}
bool clipMovesWithLayer = (animatedGeometryRoot == animatedGeometryRootForClip);
bool shouldFixToViewport = !clipMovesWithLayer &&
!(*animatedGeometryRoot)->GetParent() &&
item->ShouldFixToViewport(mBuilder);
// For items that are fixed to the viewport, remove their clip at the
// display item level because additional areas could be brought into
// view by async scrolling. Save the clip so we can set it on the layer
// instead later.
DisplayItemClip fixedToViewportClip = DisplayItemClip::NoClip();
if (shouldFixToViewport) {
fixedToViewportClip = item->GetClip();
item->SetClip(mBuilder, DisplayItemClip::NoClip());
}
bool snap;
nsRect itemContent = item->GetBounds(mBuilder, &snap);
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
nsDisplayLayerEventRegions* eventRegions =
static_cast<nsDisplayLayerEventRegions*>(item);
itemContent = eventRegions->GetHitRegionBounds(mBuilder, &snap);
}
nsIntRect itemDrawRect = ScaleToOutsidePixels(itemContent, snap);
bool prerenderedTransform = itemType == nsDisplayItem::TYPE_TRANSFORM &&
static_cast<nsDisplayTransform*>(item)->MayBeAnimated(mBuilder);
ParentLayerIntRect clipRect;
const DisplayItemClip& itemClip = item->GetClip();
if (itemClip.HasClip()) {
itemContent.IntersectRect(itemContent, itemClip.GetClipRect());
clipRect = ViewAs<ParentLayerPixel>(ScaleToNearestPixels(itemClip.GetClipRect()));
if (!prerenderedTransform) {
itemDrawRect.IntersectRect(itemDrawRect, clipRect.ToUnknownRect());
}
clipRect.MoveBy(ViewAs<ParentLayerPixel>(mParameters.mOffset));
}
#ifdef DEBUG
nsRect bounds = itemContent;
bool dummy;
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
bounds = item->GetBounds(mBuilder, &dummy);
if (itemClip.HasClip()) {
bounds.IntersectRect(bounds, itemClip.GetClipRect());
}
}
bounds = fixedToViewportClip.ApplyNonRoundedIntersection(bounds);
if (!bounds.IsEmpty()) {
for (const DisplayItemScrollClip* scrollClip = itemScrollClip;
scrollClip && scrollClip != mContainerScrollClip;
scrollClip = scrollClip->mParent) {
if (scrollClip->mClip) {
if (scrollClip->mIsAsyncScrollable) {
bounds = scrollClip->mClip->GetClipRect();
} else {
bounds = scrollClip->mClip->ApplyNonRoundedIntersection(bounds);
}
}
}
}
((nsRect&)mAccumulatedChildBounds).UnionRect(mAccumulatedChildBounds, bounds);
#endif
nsIntRect itemVisibleRect = itemDrawRect;
// We haven't computed visibility at this point, so item->GetVisibleRect()
// is just the dirty rect that item was initialized with. We intersect it
// with the clipped item bounds to get a tighter visible rect.
itemVisibleRect = itemVisibleRect.Intersect(
ScaleToOutsidePixels(item->GetVisibleRect(), false));
if (maxLayers != -1 && layerCount >= maxLayers) {
forceInactive = true;
}
// Assign the item to a layer
if (layerState == LAYER_ACTIVE_FORCE ||
(layerState == LAYER_INACTIVE && !mManager->IsWidgetLayerManager()) ||
(!forceInactive &&
(layerState == LAYER_ACTIVE_EMPTY ||
layerState == LAYER_ACTIVE))) {
layerCount++;
// LAYER_ACTIVE_EMPTY means the layer is created just for its metadata.
// We should never see an empty layer with any visible content!
NS_ASSERTION(layerState != LAYER_ACTIVE_EMPTY ||
2011-10-26 02:55:51 +00:00
itemVisibleRect.IsEmpty(),
"State is LAYER_ACTIVE_EMPTY but visible rect is not.");
// As long as the new layer isn't going to be a PaintedLayer,
// InvalidateForLayerChange doesn't need the new layer pointer.
// We also need to check the old data now, because BuildLayer
// can overwrite it.
InvalidateForLayerChange(item, nullptr);
// If the item would have its own layer but is invisible, just hide it.
// Note that items without their own layers can't be skipped this
// way, since their PaintedLayer may decide it wants to draw them
// into its buffer even if they're currently covered.
if (itemVisibleRect.IsEmpty() &&
!item->ShouldBuildLayerEvenIfInvisible(mBuilder)) {
continue;
}
if (mScrollClipForPerspectiveChild) {
// We are the single transform child item of an nsDisplayPerspective.
// Our parent forwarded a scroll clip to us. Pick it up.
// We do this after any clipping has been applied, because this
// forwarded scroll clip is only used for scrolling (in the form of
// APZ frame metrics), not for clipping - the clip still belongs on
// the perspective item.
MOZ_ASSERT(itemType == nsDisplayItem::TYPE_TRANSFORM);
MOZ_ASSERT(!itemScrollClip);
MOZ_ASSERT(!agrScrollClip);
MOZ_ASSERT(DisplayItemScrollClip::IsAncestor(mContainerScrollClip,
mScrollClipForPerspectiveChild));
itemScrollClip = mScrollClipForPerspectiveChild;
agrScrollClip = mScrollClipForPerspectiveChild;
}
// 3D-transformed layers don't necessarily draw in the order in which
// they're added to their parent container layer.
bool mayDrawOutOfOrder = itemType == nsDisplayItem::TYPE_TRANSFORM &&
(item->Frame()->Combines3DTransformWithAncestors() ||
item->Frame()->Extend3DContext());
// Let mPaintedLayerDataTree know about this item, so that
// FindPaintedLayerFor and FindOpaqueBackgroundColor are aware of this
// item, even though it's not in any PaintedLayerDataStack.
// Ideally we'd only need the "else" case here and have
// mPaintedLayerDataTree figure out the right clip from the animated
// geometry root that we give it, but it can't easily figure about
// overflow:hidden clips on ancestors just by looking at the frame.
// So we'll do a little hand holding and pass the clip instead of the
// visible rect for the two important cases.
nscolor uniformColor = NS_RGBA(0,0,0,0);
nscolor* uniformColorPtr = (mayDrawOutOfOrder || IsInInactiveLayer()) ? nullptr :
&uniformColor;
nsIntRect clipRectUntyped;
const DisplayItemClip& layerClip = shouldFixToViewport ? fixedToViewportClip : itemClip;
ParentLayerIntRect layerClipRect;
nsIntRect* clipPtr = nullptr;
if (layerClip.HasClip()) {
layerClipRect = ViewAs<ParentLayerPixel>(
ScaleToNearestPixels(layerClip.GetClipRect()) + mParameters.mOffset);
clipRectUntyped = layerClipRect.ToUnknownRect();
clipPtr = &clipRectUntyped;
}
if (*animatedGeometryRoot == item->Frame() &&
*animatedGeometryRoot != mBuilder->RootReferenceFrame()) {
// This is the case for scrollbar thumbs, for example. In that case the
// clip we care about is the overflow:hidden clip on the scrollbar.
mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRoot->mParentAGR,
clipPtr,
uniformColorPtr);
} else if (prerenderedTransform) {
mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRoot,
clipPtr,
uniformColorPtr);
} else if (shouldFixToViewport) {
mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRootForClip,
clipPtr,
uniformColorPtr);
} else {
// Using itemVisibleRect here isn't perfect. itemVisibleRect can be
// larger or smaller than the potential bounds of item's contents in
// animatedGeometryRoot: It's too large if there's a clipped display
// port somewhere among item's contents (see bug 1147673), and it can
// be too small if the contents can move, because it only looks at the
// contents' current bounds and doesn't anticipate any animations.
// Time will tell whether this is good enough, or whether we need to do
// something more sophisticated here.
mPaintedLayerDataTree.AddingOwnLayer(animatedGeometryRoot,
&itemVisibleRect, uniformColorPtr);
}
ContainerLayerParameters params = mParameters;
params.mBackgroundColor = uniformColor;
params.mLayerCreationHint = GetLayerCreationHint(animatedGeometryRoot);
params.mScrollClip = agrScrollClip;
params.mScrollClipForPerspectiveChild = nullptr;
if (itemType == nsDisplayItem::TYPE_PERSPECTIVE) {
// Perspective items have a single child item, an nsDisplayTransform.
// If the perspective item is scrolled, but the perspective-inducing
// frame is outside the scroll frame (indicated by this items AGR
// being outside that scroll frame), we have to take special care to
// make APZ scrolling work properly. APZ needs us to put the scroll
// frame's FrameMetrics on our child transform ContainerLayer instead.
// Our agrScrollClip is the scroll clip that's applicable to our
// perspective frame, so it won't be the scroll clip for the scrolled
// frame in the case that we care about, and we'll forward that scroll
// clip to our child.
params.mScrollClipForPerspectiveChild = itemScrollClip;
}
// Just use its layer.
// Set layerContentsVisibleRect.width/height to -1 to indicate we
// currently don't know. If BuildContainerLayerFor gets called by
// item->BuildLayer, this will be set to a proper rect.
nsIntRect layerContentsVisibleRect(0, 0, -1, -1);
params.mLayerContentsVisibleRect = &layerContentsVisibleRect;
RefPtr<Layer> ownLayer = item->BuildLayer(mBuilder, mManager, params);
if (!ownLayer) {
continue;
}
NS_ASSERTION(!ownLayer->AsPaintedLayer(),
"Should never have created a dedicated Painted layer!");
if (item->BackfaceIsHidden()) {
ownLayer->SetContentFlags(ownLayer->GetContentFlags() |
Layer::CONTENT_BACKFACE_HIDDEN);
} else {
ownLayer->SetContentFlags(ownLayer->GetContentFlags() &
~Layer::CONTENT_BACKFACE_HIDDEN);
}
nsRect invalid;
if (item->IsInvalid(invalid)) {
ownLayer->SetInvalidRectToVisibleRegion();
}
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
// If it's not a ContainerLayer, we need to apply the scale transform
// ourselves.
if (!ownLayer->AsContainerLayer()) {
ownLayer->SetPostScale(mParameters.mXScale,
mParameters.mYScale);
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
}
// Update that layer's clip and visible rects.
NS_ASSERTION(ownLayer->Manager() == mManager, "Wrong manager");
NS_ASSERTION(!ownLayer->HasUserData(&gLayerManagerUserData),
"We shouldn't have a FrameLayerBuilder-managed layer here!");
NS_ASSERTION(layerClip.HasClip() ||
layerClip.GetRoundedRectCount() == 0,
"If we have rounded rects, we must have a clip rect");
// It has its own layer. Update that layer's clip and visible rects.
ownLayer->SetClipRect(Nothing());
ownLayer->SetScrolledClip(Nothing());
if (layerClip.HasClip()) {
// For layers fixed to the viewport, the clip becomes part of the
// layer's scrolled clip. Otherwise, it becomes part of the layer clip.
if (shouldFixToViewport) {
LayerClip scrolledClip;
scrolledClip.SetClipRect(layerClipRect);
if (layerClip.GetRoundedRectCount() > 0) {
scrolledClip.SetMaskLayerIndex(
SetupMaskLayerForScrolledClip(ownLayer.get(), layerClip));
}
ownLayer->SetScrolledClip(Some(scrolledClip));
} else {
ownLayer->SetClipRect(Some(layerClipRect));
// rounded rectangle clipping using mask layers
// (must be done after visible rect is set on layer)
if (layerClip.GetRoundedRectCount() > 0) {
SetupMaskLayer(ownLayer, layerClip);
}
}
}
ContainerLayer* oldContainer = ownLayer->GetParent();
if (oldContainer && oldContainer != mContainerLayer) {
oldContainer->RemoveChild(ownLayer);
}
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, ownLayer) < 0,
"Layer already in list???");
NewLayerEntry* newLayerEntry = mNewChildLayers.AppendElement();
newLayerEntry->mLayer = ownLayer;
newLayerEntry->mAnimatedGeometryRoot = animatedGeometryRoot;
newLayerEntry->mScrollClip = agrScrollClip;
newLayerEntry->mLayerState = layerState;
// Don't attempt to flatten compnent alpha layers that are within
// a forced active layer, or an active transform;
if (itemType == nsDisplayItem::TYPE_TRANSFORM ||
layerState == LAYER_ACTIVE_FORCE) {
newLayerEntry->mPropagateComponentAlphaFlattening = false;
}
// nsDisplayTransform::BuildLayer must set layerContentsVisibleRect.
// We rely on this to ensure 3D transforms compute a reasonable
// layer visible region.
NS_ASSERTION(itemType != nsDisplayItem::TYPE_TRANSFORM ||
layerContentsVisibleRect.width >= 0,
"Transform items must set layerContentsVisibleRect!");
if (mLayerBuilder->IsBuildingRetainedLayers()) {
newLayerEntry->mLayerContentsVisibleRect = layerContentsVisibleRect;
if (itemType == nsDisplayItem::TYPE_PERSPECTIVE ||
(itemType == nsDisplayItem::TYPE_TRANSFORM &&
(item->Frame()->Extend3DContext() ||
item->Frame()->Combines3DTransformWithAncestors() ||
item->Frame()->HasPerspective()))) {
// Give untransformed visible region as outer visible region
// to avoid failure caused by singular transforms.
newLayerEntry->mUntransformedVisibleRegion = true;
newLayerEntry->mVisibleRegion =
item->GetVisibleRectForChildren().ToOutsidePixels(mAppUnitsPerDevPixel);
} else {
newLayerEntry->mVisibleRegion = itemVisibleRect;
}
newLayerEntry->mOpaqueRegion = ComputeOpaqueRect(item,
animatedGeometryRoot, layerClip, aList,
&newLayerEntry->mHideAllLayersBelow,
&newLayerEntry->mOpaqueForAnimatedGeometryRootParent);
} else {
bool useChildrenVisible =
itemType == nsDisplayItem::TYPE_TRANSFORM &&
(item->Frame()->IsPreserve3DLeaf() ||
item->Frame()->HasPerspective());
const nsIntRegion &visible = useChildrenVisible ?
item->GetVisibleRectForChildren().ToOutsidePixels(mAppUnitsPerDevPixel):
itemVisibleRect;
SetOuterVisibleRegionForLayer(ownLayer, visible,
layerContentsVisibleRect.width >= 0 ? &layerContentsVisibleRect : nullptr,
useChildrenVisible);
}
if (itemType == nsDisplayItem::TYPE_SCROLL_INFO_LAYER) {
nsDisplayScrollInfoLayer* scrollItem = static_cast<nsDisplayScrollInfoLayer*>(item);
newLayerEntry->mOpaqueForAnimatedGeometryRootParent = false;
newLayerEntry->mBaseScrollMetadata =
scrollItem->ComputeScrollMetadata(ownLayer, mParameters);
} else if ((itemType == nsDisplayItem::TYPE_SUBDOCUMENT ||
itemType == nsDisplayItem::TYPE_ZOOM ||
itemType == nsDisplayItem::TYPE_RESOLUTION) &&
gfxPrefs::LayoutUseContainersForRootFrames())
{
newLayerEntry->mBaseScrollMetadata =
static_cast<nsDisplaySubDocument*>(item)->ComputeScrollMetadata(ownLayer, mParameters);
}
/**
* No need to allocate geometry for items that aren't
* part of a PaintedLayer.
*/
mLayerBuilder->AddLayerDisplayItem(ownLayer, item, layerState, nullptr);
} else {
PaintedLayerData* paintedLayerData =
mPaintedLayerDataTree.FindPaintedLayerFor(animatedGeometryRoot, agrScrollClip,
itemVisibleRect,
item->Frame()->In3DContextAndBackfaceIsHidden(),
[&]() {
return NewPaintedLayerData(item, animatedGeometryRoot, agrScrollClip,
topLeft, shouldFixToViewport);
});
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
nsDisplayLayerEventRegions* eventRegions =
static_cast<nsDisplayLayerEventRegions*>(item);
paintedLayerData->AccumulateEventRegions(this, eventRegions);
} else {
// check to see if the new item has rounded rect clips in common with
// other items in the layer
if (mManager->IsWidgetLayerManager()) {
paintedLayerData->UpdateCommonClipCount(itemClip);
}
nsIntRegion opaquePixels = ComputeOpaqueRect(item,
animatedGeometryRoot, itemClip, aList,
&paintedLayerData->mHideAllLayersBelow,
&paintedLayerData->mOpaqueForAnimatedGeometryRootParent);
MOZ_ASSERT(nsIntRegion(itemDrawRect).Contains(opaquePixels));
opaquePixels.AndWith(itemVisibleRect);
paintedLayerData->Accumulate(this, item, opaquePixels,
itemVisibleRect, itemClip, layerState);
// If we removed the clip from the display item above because it's
// fixed to the viewport, save it on the PaintedLayerData so we can
// set it on the layer later.
if (fixedToViewportClip.HasClip()) {
paintedLayerData->mItemClip = fixedToViewportClip;
}
if (!paintedLayerData->mLayer) {
// Try to recycle the old layer of this display item.
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<PaintedLayer> layer =
AttemptToRecyclePaintedLayer(animatedGeometryRoot, item, topLeft);
if (layer) {
paintedLayerData->mLayer = layer;
NS_ASSERTION(FindIndexOfLayerIn(mNewChildLayers, layer) < 0,
"Layer already in list???");
mNewChildLayers[paintedLayerData->mNewChildLayersIndex].mLayer = layer.forget();
}
}
Backed out 46 changesets (bug 1022612) for B2G mochitest permafails on a CLOSED TREE. Backed out changeset 34b3014a3112 (bug 1022612) Backed out changeset 6ae9316fd909 (bug 1022612) Backed out changeset b8f3749c95eb (bug 1022612) Backed out changeset caab10bf6ca3 (bug 1022612) Backed out changeset 0c57c620c898 (bug 1022612) Backed out changeset fac64141a00a (bug 1022612) Backed out changeset bf0df1c9d68b (bug 1022612) Backed out changeset b42054800020 (bug 1022612) Backed out changeset 667793b21194 (bug 1022612) Backed out changeset f14ada64fe1b (bug 1022612) Backed out changeset 75b837686bdf (bug 1022612) Backed out changeset 66de53183a22 (bug 1022612) Backed out changeset 0ff86ced4d46 (bug 1022612) Backed out changeset 18eecc5b1ef7 (bug 1022612) Backed out changeset 2763c4878de5 (bug 1022612) Backed out changeset b72413ecc385 (bug 1022612) Backed out changeset b23f1081afb8 (bug 1022612) Backed out changeset f7e2c6a72043 (bug 1022612) Backed out changeset 959917c9027d (bug 1022612) Backed out changeset 0268a46f4880 (bug 1022612) Backed out changeset 3388856a80ad (bug 1022612) Backed out changeset e4b17cf0f806 (bug 1022612) Backed out changeset 2f4e9da0e4b6 (bug 1022612) Backed out changeset 489f6a7c0c03 (bug 1022612) Backed out changeset 8369d9ad7ad3 (bug 1022612) Backed out changeset 0758d2a06002 (bug 1022612) Backed out changeset f2ae9cb22edb (bug 1022612) Backed out changeset 9c48c6ee5dc2 (bug 1022612) Backed out changeset fe7134400f08 (bug 1022612) Backed out changeset cc2c5397ca8b (bug 1022612) Backed out changeset a3d1a3e8b39d (bug 1022612) Backed out changeset 8974b74b0eb0 (bug 1022612) Backed out changeset 75f7dbb5a2a6 (bug 1022612) Backed out changeset 2aa04a071e60 (bug 1022612) Backed out changeset f2ab1bcd4c39 (bug 1022612) Backed out changeset da9152b6ea29 (bug 1022612) Backed out changeset 58abf5b0e148 (bug 1022612) Backed out changeset 797058a09ad2 (bug 1022612) Backed out changeset ea3e99a92ff0 (bug 1022612) Backed out changeset adc4a4a7aa73 (bug 1022612) Backed out changeset 7b18dedd1505 (bug 1022612) Backed out changeset 055dd1921e8e (bug 1022612) Backed out changeset 42fa2c97e989 (bug 1022612) Backed out changeset cd594236388f (bug 1022612) Backed out changeset 9eadc5fee43d (bug 1022612) Backed out changeset 5cc8d30ff7c9 (bug 1022612)
2014-07-17 15:24:47 +00:00
}
}
if (itemSameCoordinateSystemChildren &&
itemSameCoordinateSystemChildren->NeedsTransparentSurface()) {
aList->SetNeedsTransparentSurface();
}
}
aList->AppendToTop(&savedItems);
}
void
ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, PaintedLayer* aNewLayer)
{
NS_ASSERTION(aItem->GetPerFrameKey(),
"Display items that render using Thebes must have a key");
nsDisplayItemGeometry* oldGeometry = nullptr;
DisplayItemClip* oldClip = nullptr;
Layer* oldLayer = mLayerBuilder->GetOldLayerFor(aItem, &oldGeometry, &oldClip);
if (aNewLayer != oldLayer && oldLayer) {
// The item has changed layers.
// Invalidate the old bounds in the old layer and new bounds in the new layer.
PaintedLayer* t = oldLayer->AsPaintedLayer();
if (t && oldGeometry) {
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
// Note that whenever the layer's scale changes, we invalidate the whole thing,
// so it doesn't matter whether we are using the old scale at last paint
// or a new scale here
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Display item type %s(%p) changed layers %p to %p!\n", aItem->Name(), aItem->Frame(), t, aNewLayer);
}
#endif
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
InvalidatePostTransformRegion(t,
oldGeometry->ComputeInvalidationRegion(),
*oldClip,
mLayerBuilder->GetLastPaintOffset(t));
}
// Clear the old geometry so that invalidation thinks the item has been
// added this paint.
mLayerBuilder->ClearCachedGeometry(aItem);
aItem->NotifyRenderingChanged();
}
}
void
FrameLayerBuilder::ComputeGeometryChangeForItem(DisplayItemData* aData)
{
nsDisplayItem *item = aData->mItem;
PaintedLayer* paintedLayer = aData->mLayer->AsPaintedLayer();
if (!item || !paintedLayer) {
aData->EndUpdate();
return;
}
PaintedLayerItemsEntry* entry = mPaintedLayerItems.GetEntry(paintedLayer);
nsAutoPtr<nsDisplayItemGeometry> geometry;
PaintedDisplayItemLayerUserData* layerData =
static_cast<PaintedDisplayItemLayerUserData*>(aData->mLayer->GetUserData(&gPaintedDisplayItemLayerUserData));
nsPoint shift = layerData->mAnimatedGeometryRootOrigin - layerData->mLastAnimatedGeometryRootOrigin;
const DisplayItemClip& clip = item->GetClip();
// If the frame is marked as invalidated, and didn't specify a rect to invalidate then we want to
// invalidate both the old and new bounds, otherwise we only want to invalidate the changed areas.
// If we do get an invalid rect, then we want to add this on top of the change areas.
nsRect invalid;
nsRegion combined;
bool notifyRenderingChanged = true;
if (!aData->mGeometry) {
// This item is being added for the first time, invalidate its entire area.
geometry = item->AllocateGeometry(mDisplayListBuilder);
combined = clip.ApplyNonRoundedIntersection(geometry->ComputeInvalidationRegion());
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Display item type %s(%p) added to layer %p!\n", item->Name(), item->Frame(), aData->mLayer.get());
}
#endif
} else if (aData->mIsInvalid || (item->IsInvalid(invalid) && invalid.IsEmpty())) {
// Layout marked item/frame as needing repainting (without an explicit rect), invalidate the entire old and new areas.
geometry = item->AllocateGeometry(mDisplayListBuilder);
combined = aData->mClip.ApplyNonRoundedIntersection(aData->mGeometry->ComputeInvalidationRegion());
combined.MoveBy(shift);
combined.Or(combined, clip.ApplyNonRoundedIntersection(geometry->ComputeInvalidationRegion()));
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Display item type %s(%p) (in layer %p) belongs to an invalidated frame!\n", item->Name(), item->Frame(), aData->mLayer.get());
}
#endif
} else {
// Let the display item check for geometry changes and decide what needs to be
// repainted.
const nsTArray<nsIFrame*>& changedFrames = aData->GetFrameListChanges();
aData->mGeometry->MoveBy(shift);
item->ComputeInvalidationRegion(mDisplayListBuilder, aData->mGeometry, &combined);
// We have an optimization to cache the drawing of background-attachment: fixed canvas
// background images so we can scroll and just blit them when they are flattened into
// the same layer as scrolling content. NotifyRenderingChanged is only used to tell
// the canvas bg image item to purge this cache. We want to be careful not to accidentally
// purge the cache if we are just invalidating due to scrolling (ie the background image
// moves on the scrolling layer but it's rendering stays the same) so if
// AddOffsetAndComputeDifference is the only thing that will invalidate we skip the
// NotifyRenderingChanged call (ComputeInvalidationRegion for background images also calls
// NotifyRenderingChanged if anything changes).
// Only allocate a new geometry object if something actually changed, otherwise the existing
// one should be fine. We always reallocate for inactive layers, since these types don't
// implement ComputeInvalidateRegion (and rely on the ComputeDifferences call in
// AddPaintedDisplayItem instead).
if (!combined.IsEmpty() || aData->mLayerState == LAYER_INACTIVE) {
geometry = item->AllocateGeometry(mDisplayListBuilder);
} else if (aData->mClip == clip && invalid.IsEmpty() && changedFrames.Length() == 0) {
notifyRenderingChanged = false;
}
aData->mClip.AddOffsetAndComputeDifference(entry->mCommonClipCount,
shift, aData->mGeometry->ComputeInvalidationRegion(),
clip, entry->mLastCommonClipCount,
geometry ? geometry->ComputeInvalidationRegion() :
aData->mGeometry->ComputeInvalidationRegion(),
&combined);
// Add in any rect that the frame specified
combined.Or(combined, invalid);
for (uint32_t i = 0; i < changedFrames.Length(); i++) {
combined.Or(combined, changedFrames[i]->GetVisualOverflowRect());
}
// Restrict invalidation to the clipped region
nsRegion clipRegion;
if (clip.ComputeRegionInClips(&aData->mClip, shift, &clipRegion)) {
combined.And(combined, clipRegion);
}
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
if (!combined.IsEmpty()) {
printf_stderr("Display item type %s(%p) (in layer %p) changed geometry!\n", item->Name(), item->Frame(), aData->mLayer.get());
}
}
#endif
}
if (!combined.IsEmpty()) {
if (notifyRenderingChanged) {
item->NotifyRenderingChanged();
}
InvalidatePostTransformRegion(paintedLayer,
combined.ScaleToOutsidePixels(layerData->mXScale, layerData->mYScale, layerData->mAppUnitsPerDevPixel),
layerData->mTranslation);
}
aData->EndUpdate(geometry);
}
void
FrameLayerBuilder::AddPaintedDisplayItem(PaintedLayerData* aLayerData,
nsDisplayItem* aItem,
const DisplayItemClip& aClip,
ContainerState& aContainerState,
LayerState aLayerState,
const nsPoint& aTopLeft)
{
PaintedLayer* layer = aLayerData->mLayer;
PaintedDisplayItemLayerUserData* paintedData =
static_cast<PaintedDisplayItemLayerUserData*>
(layer->GetUserData(&gPaintedDisplayItemLayerUserData));
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<BasicLayerManager> tempManager;
nsIntRect intClip;
bool hasClip = false;
if (aLayerState != LAYER_NONE) {
DisplayItemData *data = GetDisplayItemDataForManager(aItem, layer->Manager());
if (data) {
tempManager = data->mInactiveManager;
}
if (!tempManager) {
tempManager = new BasicLayerManager(BasicLayerManager::BLM_INACTIVE);
}
// We need to grab these before calling AddLayerDisplayItem because it will overwrite them.
nsRegion clip;
DisplayItemClip* oldClip = nullptr;
GetOldLayerFor(aItem, nullptr, &oldClip);
hasClip = aClip.ComputeRegionInClips(oldClip,
aTopLeft - paintedData->mLastAnimatedGeometryRootOrigin,
&clip);
if (hasClip) {
intClip = clip.GetBounds().ScaleToOutsidePixels(paintedData->mXScale,
paintedData->mYScale,
paintedData->mAppUnitsPerDevPixel);
}
}
AddLayerDisplayItem(layer, aItem, aLayerState, tempManager);
PaintedLayerItemsEntry* entry = mPaintedLayerItems.PutEntry(layer);
if (entry) {
entry->mContainerLayerFrame = aContainerState.GetContainerFrame();
if (entry->mContainerLayerGeneration == 0) {
entry->mContainerLayerGeneration = mContainerLayerGeneration;
}
if (tempManager) {
FLB_LOG_PAINTED_LAYER_DECISION(aLayerData, "Creating nested FLB for item %p\n", aItem);
FrameLayerBuilder* layerBuilder = new FrameLayerBuilder();
layerBuilder->Init(mDisplayListBuilder, tempManager, aLayerData);
tempManager->BeginTransaction();
if (mRetainingManager) {
layerBuilder->DidBeginRetainedLayerTransaction(tempManager);
}
UniquePtr<LayerProperties> props(LayerProperties::CloneFrom(tempManager->GetRoot()));
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<Layer> tmpLayer =
aItem->BuildLayer(mDisplayListBuilder, tempManager, ContainerLayerParameters());
// We have no easy way of detecting if this transaction will ever actually get finished.
// For now, I've just silenced the warning with nested transactions in BasicLayers.cpp
if (!tmpLayer) {
tempManager->EndTransaction(nullptr, nullptr);
tempManager->SetUserData(&gLayerManagerLayerBuilder, nullptr);
return;
}
bool snap;
nsRect visibleRect =
aItem->GetVisibleRect().Intersect(aItem->GetBounds(mDisplayListBuilder, &snap));
nsIntRegion rgn = visibleRect.ToOutsidePixels(paintedData->mAppUnitsPerDevPixel);
SetOuterVisibleRegion(tmpLayer, &rgn);
// If BuildLayer didn't call BuildContainerLayerFor, then our new layer won't have been
// stored in layerBuilder. Manually add it now.
if (mRetainingManager) {
#ifdef DEBUG_DISPLAY_ITEM_DATA
LayerManagerData* parentLmd = static_cast<LayerManagerData*>
(layer->Manager()->GetUserData(&gLayerManagerUserData));
LayerManagerData* lmd = static_cast<LayerManagerData*>
(tempManager->GetUserData(&gLayerManagerUserData));
lmd->mParent = parentLmd;
#endif
layerBuilder->StoreDataForFrame(aItem, tmpLayer, LAYER_ACTIVE);
}
tempManager->SetRoot(tmpLayer);
layerBuilder->WillEndTransaction();
tempManager->AbortTransaction();
#ifdef MOZ_DUMP_PAINTING
if (gfxUtils::DumpDisplayList() || gfxEnv::DumpPaint()) {
fprintf_stderr(gfxUtils::sDumpPaintFile, "Basic layer tree for painting contents of display item %s(%p):\n", aItem->Name(), aItem->Frame());
std::stringstream stream;
tempManager->Dump(stream, "", gfxEnv::DumpPaintToFile());
fprint_stderr(gfxUtils::sDumpPaintFile, stream); // not a typo, fprint_stderr declared in LayersLogging.h
}
#endif
nsIntPoint offset = GetLastPaintOffset(layer) - GetTranslationForPaintedLayer(layer);
props->MoveBy(-offset);
// Effective transforms are needed by ComputeDifferences().
tmpLayer->ComputeEffectiveTransforms(Matrix4x4());
nsIntRegion invalid = props->ComputeDifferences(tmpLayer, nullptr);
if (aLayerState == LAYER_SVG_EFFECTS) {
invalid = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(aItem->Frame(),
aItem->ToReferenceFrame(),
invalid);
}
if (!invalid.IsEmpty()) {
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Inactive LayerManager(%p) for display item %s(%p) has an invalid region - invalidating layer %p\n", tempManager.get(), aItem->Name(), aItem->Frame(), layer);
}
#endif
invalid.ScaleRoundOut(paintedData->mXScale, paintedData->mYScale);
if (hasClip) {
invalid.And(invalid, intClip);
}
InvalidatePostTransformRegion(layer, invalid,
GetTranslationForPaintedLayer(layer));
}
}
ClippedDisplayItem* cdi =
entry->mItems.AppendElement(ClippedDisplayItem(aItem,
mContainerLayerGeneration));
cdi->mInactiveLayerManager = tempManager;
}
}
FrameLayerBuilder::DisplayItemData*
FrameLayerBuilder::StoreDataForFrame(nsDisplayItem* aItem, Layer* aLayer, LayerState aState)
{
DisplayItemData* oldData = GetDisplayItemDataForManager(aItem, mRetainingManager);
if (oldData) {
if (!oldData->mUsed) {
oldData->BeginUpdate(aLayer, aState, mContainerLayerGeneration, aItem);
}
return oldData;
}
LayerManagerData* lmd = static_cast<LayerManagerData*>
(mRetainingManager->GetUserData(&gLayerManagerUserData));
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<DisplayItemData> data =
new DisplayItemData(lmd, aItem->GetPerFrameKey(), aLayer);
data->BeginUpdate(aLayer, aState, mContainerLayerGeneration, aItem);
lmd->mDisplayItems.PutEntry(data);
return data;
}
void
FrameLayerBuilder::StoreDataForFrame(nsIFrame* aFrame,
uint32_t aDisplayItemKey,
Layer* aLayer,
LayerState aState)
{
DisplayItemData* oldData = GetDisplayItemData(aFrame, aDisplayItemKey);
if (oldData && oldData->mFrameList.Length() == 1) {
oldData->BeginUpdate(aLayer, aState, mContainerLayerGeneration);
return;
}
LayerManagerData* lmd = static_cast<LayerManagerData*>
(mRetainingManager->GetUserData(&gLayerManagerUserData));
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<DisplayItemData> data =
new DisplayItemData(lmd, aDisplayItemKey, aLayer, aFrame);
data->BeginUpdate(aLayer, aState, mContainerLayerGeneration);
lmd->mDisplayItems.PutEntry(data);
}
FrameLayerBuilder::ClippedDisplayItem::ClippedDisplayItem(nsDisplayItem* aItem,
uint32_t aGeneration)
: mItem(aItem)
, mContainerLayerGeneration(aGeneration)
{
}
FrameLayerBuilder::ClippedDisplayItem::~ClippedDisplayItem()
{
if (mInactiveLayerManager) {
mInactiveLayerManager->SetUserData(&gLayerManagerLayerBuilder, nullptr);
}
}
FrameLayerBuilder::PaintedLayerItemsEntry::PaintedLayerItemsEntry(const PaintedLayer *aKey)
: nsPtrHashKey<PaintedLayer>(aKey)
, mContainerLayerFrame(nullptr)
, mLastCommonClipCount(0)
, mContainerLayerGeneration(0)
, mHasExplicitLastPaintOffset(false)
, mCommonClipCount(0)
{
}
FrameLayerBuilder::PaintedLayerItemsEntry::PaintedLayerItemsEntry(const PaintedLayerItemsEntry& aOther)
: nsPtrHashKey<PaintedLayer>(aOther.mKey)
, mItems(aOther.mItems)
{
NS_ERROR("Should never be called, since we ALLOW_MEMMOVE");
}
FrameLayerBuilder::PaintedLayerItemsEntry::~PaintedLayerItemsEntry()
{
}
void
FrameLayerBuilder::AddLayerDisplayItem(Layer* aLayer,
nsDisplayItem* aItem,
LayerState aLayerState,
BasicLayerManager* aManager)
{
if (aLayer->Manager() != mRetainingManager)
return;
DisplayItemData *data = StoreDataForFrame(aItem, aLayer, aLayerState);
data->mInactiveManager = aManager;
}
nsIntPoint
FrameLayerBuilder::GetLastPaintOffset(PaintedLayer* aLayer)
{
PaintedLayerItemsEntry* entry = mPaintedLayerItems.PutEntry(aLayer);
if (entry) {
if (entry->mContainerLayerGeneration == 0) {
entry->mContainerLayerGeneration = mContainerLayerGeneration;
}
if (entry->mHasExplicitLastPaintOffset)
return entry->mLastPaintOffset;
}
return GetTranslationForPaintedLayer(aLayer);
}
void
FrameLayerBuilder::SavePreviousDataForLayer(PaintedLayer* aLayer, uint32_t aClipCount)
{
PaintedLayerItemsEntry* entry = mPaintedLayerItems.PutEntry(aLayer);
if (entry) {
if (entry->mContainerLayerGeneration == 0) {
entry->mContainerLayerGeneration = mContainerLayerGeneration;
}
entry->mLastPaintOffset = GetTranslationForPaintedLayer(aLayer);
entry->mHasExplicitLastPaintOffset = true;
entry->mLastCommonClipCount = aClipCount;
}
}
bool
FrameLayerBuilder::CheckInLayerTreeCompressionMode()
{
if (mInLayerTreeCompressionMode) {
return true;
}
// If we wanted to be in layer tree compression mode, but weren't, then scheduled
// a delayed repaint where we will be.
mRootPresContext->PresShell()->GetRootFrame()->SchedulePaint(nsIFrame::PAINT_DELAYED_COMPRESS);
return false;
}
void
ContainerState::CollectOldLayers()
{
for (Layer* layer = mContainerLayer->GetFirstChild(); layer;
layer = layer->GetNextSibling()) {
NS_ASSERTION(!layer->HasUserData(&gMaskLayerUserData),
"Mask layers should not be part of the layer tree.");
if (layer->HasUserData(&gPaintedDisplayItemLayerUserData)) {
NS_ASSERTION(layer->AsPaintedLayer(), "Wrong layer type");
mPaintedLayersAvailableForRecycling.PutEntry(static_cast<PaintedLayer*>(layer));
}
if (Layer* maskLayer = layer->GetMaskLayer()) {
NS_ASSERTION(maskLayer->GetType() == Layer::TYPE_IMAGE,
"Could not recycle mask layer, unsupported layer type.");
mRecycledMaskImageLayers.Put(MaskLayerKey(layer, Nothing()), static_cast<ImageLayer*>(maskLayer));
}
for (size_t i = 0; i < layer->GetAncestorMaskLayerCount(); i++) {
Layer* maskLayer = layer->GetAncestorMaskLayerAt(i);
NS_ASSERTION(maskLayer->GetType() == Layer::TYPE_IMAGE,
"Could not recycle mask layer, unsupported layer type.");
mRecycledMaskImageLayers.Put(MaskLayerKey(layer, Some(i)), static_cast<ImageLayer*>(maskLayer));
}
}
}
struct OpaqueRegionEntry {
AnimatedGeometryRoot* mAnimatedGeometryRoot;
nsIntRegion mOpaqueRegion;
};
static OpaqueRegionEntry*
FindOpaqueRegionEntry(nsTArray<OpaqueRegionEntry>& aEntries,
AnimatedGeometryRoot* aAnimatedGeometryRoot)
{
for (uint32_t i = 0; i < aEntries.Length(); ++i) {
OpaqueRegionEntry* d = &aEntries[i];
if (d->mAnimatedGeometryRoot == aAnimatedGeometryRoot) {
return d;
}
}
return nullptr;
}
void
ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry)
{
if (mFlattenToSingleLayer) {
// animated geometry roots are forced to all match, so we can't
// use them and we don't get async scrolling.
return;
}
if (!mBuilder->IsPaintingToWindow()) {
// async scrolling not possible, and async scrolling info not computed
// for this paint.
return;
}
AutoTArray<ScrollMetadata,2> metricsArray;
if (aEntry->mBaseScrollMetadata) {
metricsArray.AppendElement(*aEntry->mBaseScrollMetadata);
// The base FrameMetrics was not computed by the nsIScrollableframe, so it
// should not have a mask layer.
MOZ_ASSERT(!aEntry->mBaseScrollMetadata->HasMaskLayer());
}
// Any extra mask layers we need to attach to ScrollMetadatas.
// The list may already contain an entry added for the layer's scrolled clip
// so add to it rather than overwriting it (we clear the list when recycling
// a layer).
nsTArray<RefPtr<Layer>> maskLayers(aEntry->mLayer->GetAllAncestorMaskLayers());
for (const DisplayItemScrollClip* scrollClip = aEntry->mScrollClip;
scrollClip && scrollClip != mContainerScrollClip;
scrollClip = scrollClip->mParent) {
if (!scrollClip->mIsAsyncScrollable) {
// This scroll clip was created for a scroll frame that didn't know
// whether it needs to be async scrollable for scroll handoff. It was
// not activated, so we don't need to create a frame metrics for it.
continue;
}
nsIScrollableFrame* scrollFrame = scrollClip->mScrollableFrame;
const DisplayItemClip* clip = scrollClip->mClip;
Maybe<ScrollMetadata> metadata =
scrollFrame->ComputeScrollMetadata(aEntry->mLayer, mContainerReferenceFrame, mParameters, clip);
if (!metadata) {
continue;
}
if (clip &&
clip->HasClip() &&
clip->GetRoundedRectCount() > 0)
{
// The clip in between this scrollframe and its ancestor scrollframe
// requires a mask layer. Since this mask layer should not move with
// the APZC associated with this FrameMetrics, we attach the mask
// layer as an additional, separate clip.
Maybe<size_t> nextIndex = Some(maskLayers.Length());
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<Layer> maskLayer =
CreateMaskLayer(aEntry->mLayer, *clip, nextIndex, clip->GetRoundedRectCount());
if (maskLayer) {
MOZ_ASSERT(metadata->HasScrollClip());
metadata->ScrollClip().SetMaskLayerIndex(nextIndex);
maskLayers.AppendElement(maskLayer);
}
}
metricsArray.AppendElement(*metadata);
}
// Watch out for FrameMetrics copies in profiles
aEntry->mLayer->SetScrollMetadata(metricsArray);
aEntry->mLayer->SetAncestorMaskLayers(maskLayers);
}
static inline Maybe<ParentLayerIntRect>
GetStationaryClipInContainer(Layer* aLayer)
{
if (size_t metricsCount = aLayer->GetScrollMetadataCount()) {
return aLayer->GetScrollMetadata(metricsCount - 1).GetClipRect();
}
return aLayer->GetClipRect();
}
void
ContainerState::PostprocessRetainedLayers(nsIntRegion* aOpaqueRegionForContainer)
{
AutoTArray<OpaqueRegionEntry,4> opaqueRegions;
bool hideAll = false;
int32_t opaqueRegionForContainer = -1;
for (int32_t i = mNewChildLayers.Length() - 1; i >= 0; --i) {
NewLayerEntry* e = &mNewChildLayers.ElementAt(i);
if (!e->mLayer) {
continue;
}
OpaqueRegionEntry* data = FindOpaqueRegionEntry(opaqueRegions, e->mAnimatedGeometryRoot);
SetupScrollingMetadata(e);
if (hideAll) {
e->mVisibleRegion.SetEmpty();
} else if (!e->mLayer->IsScrollbarContainer()) {
Maybe<ParentLayerIntRect> clipRect = GetStationaryClipInContainer(e->mLayer);
if (clipRect && opaqueRegionForContainer >= 0 &&
opaqueRegions[opaqueRegionForContainer].mOpaqueRegion.Contains(clipRect->ToUnknownRect())) {
e->mVisibleRegion.SetEmpty();
} else if (data) {
e->mVisibleRegion.Sub(e->mVisibleRegion, data->mOpaqueRegion);
}
}
SetOuterVisibleRegionForLayer(e->mLayer,
e->mVisibleRegion,
e->mLayerContentsVisibleRect.width >= 0 ? &e->mLayerContentsVisibleRect : nullptr,
e->mUntransformedVisibleRegion);
if (!e->mOpaqueRegion.IsEmpty()) {
AnimatedGeometryRoot* animatedGeometryRootToCover = e->mAnimatedGeometryRoot;
if (e->mOpaqueForAnimatedGeometryRootParent &&
e->mAnimatedGeometryRoot->mParentAGR == mContainerAnimatedGeometryRoot) {
animatedGeometryRootToCover = mContainerAnimatedGeometryRoot;
data = FindOpaqueRegionEntry(opaqueRegions, animatedGeometryRootToCover);
}
if (!data) {
if (animatedGeometryRootToCover == mContainerAnimatedGeometryRoot) {
NS_ASSERTION(opaqueRegionForContainer == -1, "Already found it?");
opaqueRegionForContainer = opaqueRegions.Length();
}
data = opaqueRegions.AppendElement();
data->mAnimatedGeometryRoot = animatedGeometryRootToCover;
}
nsIntRegion clippedOpaque = e->mOpaqueRegion;
Maybe<ParentLayerIntRect> clipRect = e->mLayer->GetCombinedClipRect();
if (clipRect) {
clippedOpaque.AndWith(clipRect->ToUnknownRect());
}
if (e->mLayer->GetIsFixedPosition() && e->mLayer->GetScrolledClip()) {
// The clip can move asynchronously, so we can't rely on opaque parts
// staying in the same place.
clippedOpaque.SetEmpty();
} else if (e->mHideAllLayersBelow) {
hideAll = true;
}
data->mOpaqueRegion.Or(data->mOpaqueRegion, clippedOpaque);
}
if (e->mLayer->GetType() == Layer::TYPE_READBACK) {
// ReadbackLayers need to accurately read what's behind them. So,
// we don't want to do any occlusion culling of layers behind them.
// Theoretically we could just punch out the ReadbackLayer's rectangle
// from all mOpaqueRegions, but that's probably not worth doing.
opaqueRegions.Clear();
opaqueRegionForContainer = -1;
}
}
if (opaqueRegionForContainer >= 0) {
aOpaqueRegionForContainer->Or(*aOpaqueRegionForContainer,
opaqueRegions[opaqueRegionForContainer].mOpaqueRegion);
}
}
void
ContainerState::Finish(uint32_t* aTextContentFlags,
const nsIntRect& aContainerPixelBounds,
nsDisplayList* aChildItems, bool* aHasComponentAlphaChildren)
{
mPaintedLayerDataTree.Finish();
if (!mParameters.mForEventsAndPluginsOnly) {
NS_ASSERTION(mContainerBounds.IsEqualInterior(mAccumulatedChildBounds),
"Bounds computation mismatch");
}
if (mLayerBuilder->IsBuildingRetainedLayers()) {
nsIntRegion containerOpaqueRegion;
PostprocessRetainedLayers(&containerOpaqueRegion);
if (containerOpaqueRegion.Contains(aContainerPixelBounds)) {
aChildItems->SetIsOpaque();
}
}
uint32_t textContentFlags = 0;
// Make sure that current/existing layers are added to the parent and are
// in the correct order.
Layer* layer = nullptr;
Layer* prevChild = nullptr;
for (uint32_t i = 0; i < mNewChildLayers.Length(); ++i, prevChild = layer) {
if (!mNewChildLayers[i].mLayer) {
continue;
}
layer = mNewChildLayers[i].mLayer;
if (!layer->GetVisibleRegion().IsEmpty()) {
textContentFlags |=
layer->GetContentFlags() & (Layer::CONTENT_COMPONENT_ALPHA |
Layer::CONTENT_COMPONENT_ALPHA_DESCENDANT |
Layer::CONTENT_DISABLE_FLATTENING);
// Notify the parent of component alpha children unless it's coming from
// within a child that has asked not to contribute to layer flattening.
if (aHasComponentAlphaChildren &&
mNewChildLayers[i].mPropagateComponentAlphaFlattening &&
(layer->GetContentFlags() & Layer::CONTENT_COMPONENT_ALPHA)) {
for (int32_t j = i - 1; j >= 0; j--) {
if (mNewChildLayers[j].mVisibleRegion.Intersects(mNewChildLayers[i].mVisibleRegion.GetBounds())) {
if (mNewChildLayers[j].mLayerState != LAYER_ACTIVE_FORCE) {
*aHasComponentAlphaChildren = true;
}
break;
}
}
}
}
if (!layer->GetParent()) {
// This is not currently a child of the container, so just add it
// now.
mContainerLayer->InsertAfter(layer, prevChild);
} else {
NS_ASSERTION(layer->GetParent() == mContainerLayer,
"Layer shouldn't be the child of some other container");
if (layer->GetPrevSibling() != prevChild) {
mContainerLayer->RepositionChild(layer, prevChild);
}
}
}
// Remove old layers that have become unused.
if (!layer) {
layer = mContainerLayer->GetFirstChild();
} else {
layer = layer->GetNextSibling();
}
while (layer) {
Layer *layerToRemove = layer;
layer = layer->GetNextSibling();
mContainerLayer->RemoveChild(layerToRemove);
}
*aTextContentFlags = textContentFlags;
}
static inline gfxSize RoundToFloatPrecision(const gfxSize& aSize)
{
return gfxSize(float(aSize.width), float(aSize.height));
}
static void RestrictScaleToMaxLayerSize(gfxSize& aScale,
const nsRect& aVisibleRect,
nsIFrame* aContainerFrame,
Layer* aContainerLayer)
{
if (!aContainerLayer->Manager()->IsWidgetLayerManager()) {
return;
}
nsIntRect pixelSize =
aVisibleRect.ScaleToOutsidePixels(aScale.width, aScale.height,
aContainerFrame->PresContext()->AppUnitsPerDevPixel());
int32_t maxLayerSize = aContainerLayer->GetMaxLayerSize();
if (pixelSize.width > maxLayerSize) {
float scale = (float)pixelSize.width / maxLayerSize;
scale = gfxUtils::ClampToScaleFactor(scale);
aScale.width /= scale;
}
if (pixelSize.height > maxLayerSize) {
float scale = (float)pixelSize.height / maxLayerSize;
scale = gfxUtils::ClampToScaleFactor(scale);
aScale.height /= scale;
}
}
static bool
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
nsDisplayListBuilder* aDisplayListBuilder,
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
nsIFrame* aContainerFrame,
nsDisplayItem* aContainerItem,
const nsRect& aVisibleRect,
const Matrix4x4* aTransform,
const ContainerLayerParameters& aIncomingScale,
ContainerLayer* aLayer,
LayerState aState,
ContainerLayerParameters& aOutgoingScale)
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
{
nsIntPoint offset;
Matrix4x4 transform =
Matrix4x4::Scaling(aIncomingScale.mXScale, aIncomingScale.mYScale, 1.0);
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
if (aTransform) {
// aTransform is applied first, then the scale is applied to the result
transform = (*aTransform)*transform;
// Set any matrix entries close to integers to be those exact integers.
// This protects against floating-point inaccuracies causing problems
// in the checks below.
// We use the fixed epsilon version here because we don't want the nudging
// to depend on the scroll position.
transform.NudgeToIntegersFixedEpsilon();
}
Matrix transform2d;
if (aContainerFrame &&
(aState == LAYER_INACTIVE || aState == LAYER_SVG_EFFECTS) &&
(!aTransform || (aTransform->Is2D(&transform2d) &&
!transform2d.HasNonTranslation()))) {
// When we have an inactive ContainerLayer, translate the container by the offset to the
// reference frame (and offset all child layers by the reverse) so that the coordinate
// space of the child layers isn't affected by scrolling.
// This gets confusing for complicated transform (since we'd have to compute the scale
// factors for the matrix), so we don't bother. Any frames that are building an nsDisplayTransform
// for a css transform would have 0,0 as their offset to the reference frame, so this doesn't
// matter.
nsPoint appUnitOffset = aDisplayListBuilder->ToReferenceFrame(aContainerFrame);
nscoord appUnitsPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
offset = nsIntPoint(
NS_lround(NSAppUnitsToDoublePixels(appUnitOffset.x, appUnitsPerDevPixel)*aIncomingScale.mXScale),
NS_lround(NSAppUnitsToDoublePixels(appUnitOffset.y, appUnitsPerDevPixel)*aIncomingScale.mYScale));
}
transform.PostTranslate(offset.x + aIncomingScale.mOffset.x,
offset.y + aIncomingScale.mOffset.y,
0);
if (transform.IsSingular()) {
return false;
}
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
bool canDraw2D = transform.CanDraw2D(&transform2d);
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
gfxSize scale;
// XXX Should we do something for 3D transforms?
if (canDraw2D &&
!aContainerFrame->Combines3DTransformWithAncestors() &&
!aContainerFrame->HasPerspective()) {
// If the container's transform is animated off main thread, fix a suitable scale size
// for animation
if (aContainerItem &&
aContainerItem->GetType() == nsDisplayItem::TYPE_TRANSFORM &&
EffectCompositor::HasAnimationsForCompositor(
aContainerFrame, eCSSProperty_transform)) {
// Use the size of the nearest widget as the maximum size. This
// is important since it might be a popup that is bigger than the
// pres context's size.
nsPresContext* presContext = aContainerFrame->PresContext();
nsIWidget* widget = aContainerFrame->GetNearestWidget();
nsSize displaySize;
if (widget) {
LayoutDeviceIntSize widgetSize = widget->GetClientSize();
int32_t p2a = presContext->AppUnitsPerDevPixel();
displaySize.width = NSIntPixelsToAppUnits(widgetSize.width, p2a);
displaySize.height = NSIntPixelsToAppUnits(widgetSize.height, p2a);
} else {
displaySize = presContext->GetVisibleArea().Size();
}
// compute scale using the animation on the container (ignoring
// its ancestors)
scale = nsLayoutUtils::ComputeSuitableScaleForAnimation(
aContainerFrame, aVisibleRect.Size(),
displaySize);
// multiply by the scale inherited from ancestors--we use a uniform
// scale factor to prevent blurring when the layer is rotated.
float incomingScale = std::max(aIncomingScale.mXScale, aIncomingScale.mYScale);
scale.width *= incomingScale;
scale.height *= incomingScale;
} else {
// Scale factors are normalized to a power of 2 to reduce the number of resolution changes
scale = RoundToFloatPrecision(ThebesMatrix(transform2d).ScaleFactors(true));
// For frames with a changing transform that's not just a translation,
// round scale factors up to nearest power-of-2 boundary so that we don't
// keep having to redraw the content as it scales up and down. Rounding up to nearest
// power-of-2 boundary ensures we never scale up, only down --- avoiding
// jaggies. It also ensures we never scale down by more than a factor of 2,
// avoiding bad downscaling quality.
Matrix frameTransform;
if (ActiveLayerTracker::IsStyleAnimated(aDisplayListBuilder, aContainerFrame, eCSSProperty_transform) &&
aTransform &&
(!aTransform->Is2D(&frameTransform) || frameTransform.HasNonTranslationOrFlip())) {
// Don't clamp the scale factor when the new desired scale factor matches the old one
// or it was previously unscaled.
bool clamp = true;
Matrix oldFrameTransform2d;
if (aLayer->GetBaseTransform().Is2D(&oldFrameTransform2d)) {
gfxSize oldScale = RoundToFloatPrecision(ThebesMatrix(oldFrameTransform2d).ScaleFactors(true));
if (oldScale == scale || oldScale == gfxSize(1.0, 1.0)) {
clamp = false;
}
}
if (clamp) {
scale.width = gfxUtils::ClampToScaleFactor(scale.width);
scale.height = gfxUtils::ClampToScaleFactor(scale.height);
}
} else {
// XXX Do we need to move nearly-integer values to integers here?
}
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
}
// If the scale factors are too small, just use 1.0. The content is being
// scaled out of sight anyway.
if (fabs(scale.width) < 1e-8 || fabs(scale.height) < 1e-8) {
scale = gfxSize(1.0, 1.0);
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
}
// If this is a transform container layer, then pre-rendering might
// mean we try render a layer bigger than the max texture size. If we have
// tiling, that's not a problem, since we'll automatically choose a tiled
// layer for layers of that size. If not, we need to apply clamping to
// prevent this.
if (aTransform && !gfxPrefs::LayersTilesEnabled()) {
RestrictScaleToMaxLayerSize(scale, aVisibleRect, aContainerFrame, aLayer);
}
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
} else {
scale = gfxSize(1.0, 1.0);
}
// Store the inverse of our resolution-scale on the layer
aLayer->SetBaseTransform(transform);
aLayer->SetPreScale(1.0f/float(scale.width),
1.0f/float(scale.height));
aLayer->SetInheritedScale(aIncomingScale.mXScale,
aIncomingScale.mYScale);
aOutgoingScale =
ContainerLayerParameters(scale.width, scale.height, -offset, aIncomingScale);
if (aTransform) {
aOutgoingScale.mInTransformedSubtree = true;
if (ActiveLayerTracker::IsStyleAnimated(aDisplayListBuilder, aContainerFrame,
eCSSProperty_transform)) {
aOutgoingScale.mInActiveTransformedSubtree = true;
}
}
if ((aLayerBuilder->IsBuildingRetainedLayers() &&
(!canDraw2D || transform2d.HasNonIntegerTranslation())) ||
aContainerFrame->Extend3DContext() ||
aContainerFrame->Combines3DTransformWithAncestors()) {
aOutgoingScale.mDisableSubpixelAntialiasingInDescendants = true;
}
return true;
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
}
already_AddRefed<ContainerLayer>
FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
nsIFrame* aContainerFrame,
nsDisplayItem* aContainerItem,
nsDisplayList* aChildren,
const ContainerLayerParameters& aParameters,
const Matrix4x4* aTransform,
uint32_t aFlags)
{
uint32_t containerDisplayItemKey =
aContainerItem ? aContainerItem->GetPerFrameKey() : nsDisplayItem::TYPE_ZERO;
NS_ASSERTION(aContainerFrame, "Container display items here should have a frame");
NS_ASSERTION(!aContainerItem ||
aContainerItem->Frame() == aContainerFrame,
"Container display item must match given frame");
if (!aParameters.mXScale || !aParameters.mYScale) {
return nullptr;
}
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<ContainerLayer> containerLayer;
if (aManager == mRetainingManager) {
// Using GetOldLayerFor will search merged frames, as well as the underlying
// frame. The underlying frame can change when a page scrolls, so this
// avoids layer recreation in the situation that a new underlying frame is
// picked for a layer.
Layer* oldLayer = nullptr;
if (aContainerItem) {
oldLayer = GetOldLayerFor(aContainerItem);
} else {
DisplayItemData *data = GetOldLayerForFrame(aContainerFrame, containerDisplayItemKey);
if (data) {
oldLayer = data->mLayer;
}
}
if (oldLayer) {
NS_ASSERTION(oldLayer->Manager() == aManager, "Wrong manager");
if (oldLayer->HasUserData(&gPaintedDisplayItemLayerUserData)) {
// The old layer for this item is actually our PaintedLayer
// because we rendered its layer into that PaintedLayer. So we
// don't actually have a retained container layer.
} else {
NS_ASSERTION(oldLayer->GetType() == Layer::TYPE_CONTAINER,
"Wrong layer type");
containerLayer = static_cast<ContainerLayer*>(oldLayer);
ResetLayerStateForRecycling(containerLayer);
}
}
}
if (!containerLayer) {
// No suitable existing layer was found.
containerLayer = aManager->CreateContainerLayer();
if (!containerLayer)
return nullptr;
}
LayerState state = aContainerItem ? aContainerItem->GetLayerState(aBuilder, aManager, aParameters) : LAYER_ACTIVE;
if (state == LAYER_INACTIVE &&
nsDisplayItem::ForceActiveLayers()) {
state = LAYER_ACTIVE;
}
if (aContainerItem && state == LAYER_ACTIVE_EMPTY) {
// Empty layers only have metadata and should never have display items. We
// early exit because later, invalidation will walk up the frame tree to
// determine which painted layer gets invalidated. Since an empty layer
// should never have anything to paint, it should never be invalidated.
NS_ASSERTION(aChildren->IsEmpty(), "Should have no children");
return containerLayer.forget();
}
const DisplayItemScrollClip* containerScrollClip = aParameters.mScrollClip;
ContainerLayerParameters scaleParameters;
nsRect bounds = aChildren->GetScrollClippedBoundsUpTo(aBuilder, containerScrollClip);
nsRect childrenVisible =
aContainerItem ? aContainerItem->GetVisibleRectForChildren() :
aContainerFrame->GetVisualOverflowRectRelativeToSelf();
if (!ChooseScaleAndSetTransform(this, aBuilder, aContainerFrame,
aContainerItem,
bounds.Intersect(childrenVisible),
aTransform, aParameters,
containerLayer, state, scaleParameters)) {
return nullptr;
}
uint32_t oldGeneration = mContainerLayerGeneration;
mContainerLayerGeneration = ++mMaxContainerLayerGeneration;
if (mRetainingManager) {
if (aContainerItem) {
StoreDataForFrame(aContainerItem, containerLayer, LAYER_ACTIVE);
} else {
StoreDataForFrame(aContainerFrame, containerDisplayItemKey, containerLayer, LAYER_ACTIVE);
}
}
LayerManagerData* data = static_cast<LayerManagerData*>
(aManager->GetUserData(&gLayerManagerUserData));
nsIntRect pixBounds;
nscoord appUnitsPerDevPixel;
bool flattenToSingleLayer = false;
if ((aContainerFrame->GetStateBits() & NS_FRAME_NO_COMPONENT_ALPHA) &&
mRetainingManager &&
mRetainingManager->ShouldAvoidComponentAlphaLayers() &&
!nsLayoutUtils::AsyncPanZoomEnabled(aContainerFrame))
{
flattenToSingleLayer = true;
}
nscolor backgroundColor = NS_RGBA(0,0,0,0);
if (aFlags & CONTAINER_ALLOW_PULL_BACKGROUND_COLOR) {
backgroundColor = aParameters.mBackgroundColor;
}
uint32_t flags;
while (true) {
ContainerState state(aBuilder, aManager, aManager->GetLayerBuilder(),
aContainerFrame, aContainerItem, bounds,
containerLayer, scaleParameters, flattenToSingleLayer,
backgroundColor, containerScrollClip);
state.ProcessDisplayItems(aChildren);
// Set CONTENT_COMPONENT_ALPHA if any of our children have it.
// This is suboptimal ... a child could have text that's over transparent
// pixels in its own layer, but over opaque parts of previous siblings.
bool hasComponentAlphaChildren = false;
bool mayFlatten =
mRetainingManager &&
mRetainingManager->ShouldAvoidComponentAlphaLayers() &&
!flattenToSingleLayer &&
!nsLayoutUtils::AsyncPanZoomEnabled(aContainerFrame);
pixBounds = state.ScaleToOutsidePixels(bounds, false);
appUnitsPerDevPixel = state.GetAppUnitsPerDevPixel();
state.Finish(&flags, pixBounds, aChildren, mayFlatten ? &hasComponentAlphaChildren : nullptr);
if (hasComponentAlphaChildren &&
!(flags & Layer::CONTENT_DISABLE_FLATTENING) &&
containerLayer->HasMultipleChildren())
{
// Since we don't want any component alpha layers on BasicLayers, we repeat
// the layer building process with this explicitely forced off.
// We restore the previous FrameLayerBuilder state since the first set
// of layer building will have changed it.
flattenToSingleLayer = true;
// Restore DisplayItemData
for (auto iter = data->mDisplayItems.Iter(); !iter.Done(); iter.Next()) {
DisplayItemData* data = iter.Get()->GetKey();
if (data->mUsed && data->mContainerLayerGeneration >= mContainerLayerGeneration) {
iter.Remove();
}
}
// Restore PaintedLayerItemEntries
for (auto iter = mPaintedLayerItems.Iter(); !iter.Done(); iter.Next()) {
PaintedLayerItemsEntry* entry = iter.Get();
if (entry->mContainerLayerGeneration >= mContainerLayerGeneration) {
// We can just remove these items rather than attempting to revert them
// because we're going to want to invalidate everything when transitioning
// to component alpha flattening.
iter.Remove();
continue;
}
for (uint32_t i = 0; i < entry->mItems.Length(); i++) {
if (entry->mItems[i].mContainerLayerGeneration >= mContainerLayerGeneration) {
entry->mItems.TruncateLength(i);
break;
}
}
}
aContainerFrame->AddStateBits(NS_FRAME_NO_COMPONENT_ALPHA);
continue;
}
break;
}
// CONTENT_COMPONENT_ALPHA is propogated up to the nearest CONTENT_OPAQUE
// ancestor so that BasicLayerManager knows when to copy the background into
// pushed groups. Accelerated layers managers can't necessarily do this (only
// when the visible region is a simple rect), so we propogate
// CONTENT_COMPONENT_ALPHA_DESCENDANT all the way to the root.
if (flags & Layer::CONTENT_COMPONENT_ALPHA) {
flags |= Layer::CONTENT_COMPONENT_ALPHA_DESCENDANT;
}
// Make sure that rounding the visible region out didn't add any area
// we won't paint
if (aChildren->IsOpaque() && !aChildren->NeedsTransparentSurface()) {
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
bounds.ScaleRoundIn(scaleParameters.mXScale, scaleParameters.mYScale);
if (bounds.Contains(ToAppUnits(pixBounds, appUnitsPerDevPixel))) {
// Clear CONTENT_COMPONENT_ALPHA and add CONTENT_OPAQUE instead.
flags &= ~Layer::CONTENT_COMPONENT_ALPHA;
flags |= Layer::CONTENT_OPAQUE;
Bug 637852. Part 6: Implement resolution scaling in FrameLayerBuilder. r=tnikkel FrameLayerBuilder::BuildContainerLayerFor takes responsibility for resolution scaling. The ContainerParameters passed in are added to any transform requested. Then we extract the scale part of the transform, round the scale up to the nearest power of two if the transform may be actively animated (so we don't have to redraw layer contents constantly), pass that scale down to be applied by each child and set the residual transform on the ContainerLayer. For child layers built via BuildLayer, we just pass the requested scale factor in via the ContainerParameters. If the returned layer is a ContainerLayer then BuildLayer is guaranteed to have already done necessary scaling. If the returned layer is not a ContainerLayer then we apply the scale ourselves by adding the scale to the child layer's transform. For child ThebesLayers containing non-layer display items, we scale the drawing of those display items so that the child ThebesLayers are simply larger or smaller (larger or smaller visible regions). We have to scale all visible rects, clip rects etc that are in the coordinates of ThebesLayers or the parent ContainerLayer. To keep things simple we do this whenever we convert from appunits to integer layer coordinates. When a ThebesLayer's resolution changes we need to rerender the whole thing. nsDisplayList::PaintForFrame needs to respect the presshell's resolution setting. We do that by building a layer tree with a ContainerParameters requesting a scale up by the presshell resolution; once that layer tree is built, we adjust the root layer transform to scale back down by the resolution.
2011-06-22 12:11:27 +00:00
}
}
containerLayer->SetContentFlags(flags);
// If aContainerItem is non-null some BuildContainerLayer further up the
// call stack is responsible for setting containerLayer's visible region.
if (!aContainerItem) {
containerLayer->SetVisibleRegion(LayerIntRegion::FromUnknownRegion(pixBounds));
}
if (aParameters.mLayerContentsVisibleRect) {
*aParameters.mLayerContentsVisibleRect = pixBounds + scaleParameters.mOffset;
}
mContainerLayerGeneration = oldGeneration;
nsPresContext::ClearNotifySubDocInvalidationData(containerLayer);
return containerLayer.forget();
}
Layer*
FrameLayerBuilder::GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem)
{
Layer* layer = GetOldLayerFor(aItem);
if (!layer)
return nullptr;
if (layer->HasUserData(&gPaintedDisplayItemLayerUserData)) {
// This layer was created to render Thebes-rendered content for this
// display item. The display item should not use it for its own
// layer rendering.
return nullptr;
}
ResetLayerStateForRecycling(layer);
return layer;
}
/* static */ void
FrameLayerBuilder::InvalidateAllLayers(LayerManager* aManager)
{
LayerManagerData* data = static_cast<LayerManagerData*>
(aManager->GetUserData(&gLayerManagerUserData));
if (data) {
data->mInvalidateAllLayers = true;
}
}
/* static */ void
FrameLayerBuilder::InvalidateAllLayersForFrame(nsIFrame *aFrame)
{
const nsTArray<DisplayItemData*>* array =
aFrame->Properties().Get(LayerManagerDataProperty());
if (array) {
for (uint32_t i = 0; i < array->Length(); i++) {
AssertDisplayItemData(array->ElementAt(i))->mParent->mInvalidateAllLayers = true;
}
}
}
/* static */
Layer*
FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, uint32_t aDisplayItemKey)
{
//TODO: This isn't completely correct, since a frame could exist as a layer
// in the normal widget manager, and as a different layer (or no layer)
// in the secondary manager
const nsTArray<DisplayItemData*>* array =
aFrame->Properties().Get(LayerManagerDataProperty());
if (array) {
for (uint32_t i = 0; i < array->Length(); i++) {
DisplayItemData *element = AssertDisplayItemData(array->ElementAt(i));
if (!element->mParent->mLayerManager->IsWidgetLayerManager()) {
continue;
}
if (element->mDisplayItemKey == aDisplayItemKey) {
if (element->mOptLayer) {
return element->mOptLayer;
}
Layer* layer = element->mLayer;
if (!layer->HasUserData(&gColorLayerUserData) &&
!layer->HasUserData(&gImageLayerUserData) &&
!layer->HasUserData(&gPaintedDisplayItemLayerUserData)) {
return layer;
}
}
}
}
return nullptr;
}
static gfxSize
PredictScaleForContent(nsIFrame* aFrame, nsIFrame* aAncestorWithScale,
const gfxSize& aScale)
{
Matrix4x4 transform = Matrix4x4::Scaling(aScale.width, aScale.height, 1.0);
if (aFrame != aAncestorWithScale) {
// aTransform is applied first, then the scale is applied to the result
transform = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestorWithScale)*transform;
}
Matrix transform2d;
if (transform.CanDraw2D(&transform2d)) {
return ThebesMatrix(transform2d).ScaleFactors(true);
}
return gfxSize(1.0, 1.0);
}
gfxSize
FrameLayerBuilder::GetPaintedLayerScaleForFrame(nsIFrame* aFrame)
{
MOZ_ASSERT(aFrame, "need a frame");
nsIFrame* last = nullptr;
for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
last = f;
if (nsLayoutUtils::IsPopup(f)) {
// Don't examine ancestors of a popup. It won't make sense to check
// the transform from some content inside the popup to some content
// which is an ancestor of the popup.
break;
}
const nsTArray<DisplayItemData*>* array =
f->Properties().Get(LayerManagerDataProperty());
if (!array) {
continue;
}
for (uint32_t i = 0; i < array->Length(); i++) {
Layer* layer = AssertDisplayItemData(array->ElementAt(i))->mLayer;
ContainerLayer* container = layer->AsContainerLayer();
if (!container ||
!layer->Manager()->IsWidgetLayerManager()) {
continue;
}
for (Layer* l = container->GetFirstChild(); l; l = l->GetNextSibling()) {
PaintedDisplayItemLayerUserData* data =
static_cast<PaintedDisplayItemLayerUserData*>
(l->GetUserData(&gPaintedDisplayItemLayerUserData));
if (data) {
return PredictScaleForContent(aFrame, f, gfxSize(data->mXScale, data->mYScale));
}
}
}
}
float presShellResolution = last->PresContext()->PresShell()->GetResolution();
return PredictScaleForContent(aFrame, last,
gfxSize(presShellResolution, presShellResolution));
}
#ifdef MOZ_DUMP_PAINTING
static void DebugPaintItem(DrawTarget& aDrawTarget,
nsPresContext* aPresContext,
nsDisplayItem *aItem,
nsDisplayListBuilder* aBuilder)
{
bool snap;
Rect bounds = NSRectToRect(aItem->GetBounds(aBuilder, &snap),
aPresContext->AppUnitsPerDevPixel());
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<DrawTarget> tempDT =
aDrawTarget.CreateSimilarDrawTarget(IntSize::Truncate(bounds.width, bounds.height),
SurfaceFormat::B8G8R8A8);
RefPtr<gfxContext> context = gfxContext::CreateOrNull(tempDT);
if (!context) {
// Leave this as crash, it's in the debugging code, we want to know
gfxDevCrash(LogReason::InvalidContext) << "DebugPaintItem context problem " << gfx::hexa(tempDT);
return;
}
context->SetMatrix(gfxMatrix::Translation(-bounds.x, -bounds.y));
nsRenderingContext ctx(context);
aItem->Paint(aBuilder, &ctx);
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<SourceSurface> surface = tempDT->Snapshot();
DumpPaintedImage(aItem, surface);
aDrawTarget.DrawSurface(surface, bounds, Rect(Point(0,0), bounds.Size()));
aItem->SetPainted();
}
#endif
/* static */ void
FrameLayerBuilder::RecomputeVisibilityForItems(nsTArray<ClippedDisplayItem>& aItems,
nsDisplayListBuilder *aBuilder,
const nsIntRegion& aRegionToDraw,
const nsIntPoint& aOffset,
int32_t aAppUnitsPerDevPixel,
float aXScale,
float aYScale)
{
uint32_t i;
// Update visible regions. We perform visibility analysis to take account
// of occlusion culling.
nsRegion visible = aRegionToDraw.ToAppUnits(aAppUnitsPerDevPixel);
visible.MoveBy(NSIntPixelsToAppUnits(aOffset.x, aAppUnitsPerDevPixel),
NSIntPixelsToAppUnits(aOffset.y, aAppUnitsPerDevPixel));
visible.ScaleInverseRoundOut(aXScale, aYScale);
for (i = aItems.Length(); i > 0; --i) {
ClippedDisplayItem* cdi = &aItems[i - 1];
const DisplayItemClip& clip = cdi->mItem->GetClip();
NS_ASSERTION(AppUnitsPerDevPixel(cdi->mItem) == aAppUnitsPerDevPixel,
"a painted layer should contain items only at the same zoom");
MOZ_ASSERT(clip.HasClip() || clip.GetRoundedRectCount() == 0,
"If we have rounded rects, we must have a clip rect");
if (!clip.IsRectAffectedByClip(visible.GetBounds())) {
cdi->mItem->RecomputeVisibility(aBuilder, &visible);
continue;
}
// Do a little dance to account for the fact that we're clipping
// to cdi->mClipRect
nsRegion clipped;
clipped.And(visible, clip.NonRoundedIntersection());
nsRegion finalClipped = clipped;
cdi->mItem->RecomputeVisibility(aBuilder, &finalClipped);
// If we have rounded clip rects, don't subtract from the visible
// region since we aren't displaying everything inside the rect.
if (clip.GetRoundedRectCount() == 0) {
nsRegion removed;
removed.Sub(clipped, finalClipped);
nsRegion newVisible;
newVisible.Sub(visible, removed);
// Don't let the visible region get too complex.
if (newVisible.GetNumRects() <= 15) {
visible = newVisible;
}
}
}
}
void
FrameLayerBuilder::PaintItems(nsTArray<ClippedDisplayItem>& aItems,
const nsIntRect& aRect,
gfxContext *aContext,
nsRenderingContext *aRC,
nsDisplayListBuilder* aBuilder,
nsPresContext* aPresContext,
const nsIntPoint& aOffset,
float aXScale, float aYScale,
int32_t aCommonClipCount)
{
DrawTarget& aDrawTarget = *aRC->GetDrawTarget();
int32_t appUnitsPerDevPixel = aPresContext->AppUnitsPerDevPixel();
nsRect boundRect = ToAppUnits(aRect, appUnitsPerDevPixel);
boundRect.MoveBy(NSIntPixelsToAppUnits(aOffset.x, appUnitsPerDevPixel),
NSIntPixelsToAppUnits(aOffset.y, appUnitsPerDevPixel));
boundRect.ScaleInverseRoundOut(aXScale, aYScale);
DisplayItemClip currentClip;
bool currentClipIsSetInContext = false;
DisplayItemClip tmpClip;
for (uint32_t i = 0; i < aItems.Length(); ++i) {
ClippedDisplayItem* cdi = &aItems[i];
nsRect paintRect = cdi->mItem->GetVisibleRect().Intersect(boundRect);
if (paintRect.IsEmpty())
continue;
#ifdef MOZ_DUMP_PAINTING
PROFILER_LABEL_PRINTF("DisplayList", "Draw",
js::ProfileEntry::Category::GRAPHICS, "%s", cdi->mItem->Name());
#else
PROFILER_LABEL("DisplayList", "Draw",
js::ProfileEntry::Category::GRAPHICS);
#endif
// If the new desired clip state is different from the current state,
// update the clip.
const DisplayItemClip* clip = &cdi->mItem->GetClip();
if (clip->GetRoundedRectCount() > 0 &&
!clip->IsRectClippedByRoundedCorner(cdi->mItem->GetVisibleRect())) {
tmpClip = *clip;
tmpClip.RemoveRoundedCorners();
clip = &tmpClip;
}
if (currentClipIsSetInContext != clip->HasClip() ||
(clip->HasClip() && *clip != currentClip)) {
if (currentClipIsSetInContext) {
aContext->Restore();
}
currentClipIsSetInContext = clip->HasClip();
if (currentClipIsSetInContext) {
currentClip = *clip;
aContext->Save();
NS_ASSERTION(aCommonClipCount < 100,
"Maybe you really do have more than a hundred clipping rounded rects, or maybe something has gone wrong.");
currentClip.ApplyTo(aContext, aPresContext, aCommonClipCount);
aContext->NewPath();
}
}
if (cdi->mInactiveLayerManager) {
bool saved = aDrawTarget.GetPermitSubpixelAA();
PaintInactiveLayer(aBuilder, cdi->mInactiveLayerManager, cdi->mItem, aContext, aRC);
aDrawTarget.SetPermitSubpixelAA(saved);
} else {
nsIFrame* frame = cdi->mItem->Frame();
if (aBuilder->IsPaintingToWindow()) {
frame->AddStateBits(NS_FRAME_PAINTED_THEBES);
}
#ifdef MOZ_DUMP_PAINTING
if (gfxEnv::DumpPaintItems()) {
DebugPaintItem(aDrawTarget, aPresContext, cdi->mItem, aBuilder);
} else {
#else
{
#endif
cdi->mItem->Paint(aBuilder, aRC);
}
}
if (CheckDOMModified())
break;
}
if (currentClipIsSetInContext) {
aContext->Restore();
}
}
/**
* Returns true if it is preferred to draw the list of display
* items separately for each rect in the visible region rather
* than clipping to a complex region.
*/
static bool
ShouldDrawRectsSeparately(DrawTarget* aDrawTarget, DrawRegionClip aClip)
{
if (!gfxPrefs::LayoutPaintRectsSeparately() ||
aClip == DrawRegionClip::NONE) {
return false;
}
return !aDrawTarget->SupportsRegionClipping();
}
static void DrawForcedBackgroundColor(DrawTarget& aDrawTarget,
const IntRect& aBounds,
nscolor aBackgroundColor)
{
if (NS_GET_A(aBackgroundColor) > 0) {
ColorPattern color(ToDeviceColor(aBackgroundColor));
aDrawTarget.FillRect(Rect(aBounds), color);
}
}
/*
* A note on residual transforms:
*
* In a transformed subtree we sometimes apply the PaintedLayer's
* "residual transform" when drawing content into the PaintedLayer.
* This is a translation by components in the range [-0.5,0.5) provided
* by the layer system; applying the residual transform followed by the
* transforms used by layer compositing ensures that the subpixel alignment
* of the content of the PaintedLayer exactly matches what it would be if
* we used cairo/Thebes to draw directly to the screen without going through
* retained layer buffers.
*
* The visible and valid regions of the PaintedLayer are computed without
* knowing the residual transform (because we don't know what the residual
* transform is going to be until we've built the layer tree!). So we have to
* consider whether content painted in the range [x, xmost) might be painted
* outside the visible region we computed for that content. The visible region
* would be [floor(x), ceil(xmost)). The content would be rendered at
* [x + r, xmost + r), where -0.5 <= r < 0.5. So some half-rendered pixels could
* indeed fall outside the computed visible region, which is not a big deal;
* similar issues already arise when we snap cliprects to nearest pixels.
* Note that if the rendering of the content is snapped to nearest pixels ---
* which it often is --- then the content is actually rendered at
* [snap(x + r), snap(xmost + r)). It turns out that floor(x) <= snap(x + r)
* and ceil(xmost) >= snap(xmost + r), so the rendering of snapped content
* always falls within the visible region we computed.
*/
/* static */ void
FrameLayerBuilder::DrawPaintedLayer(PaintedLayer* aLayer,
gfxContext* aContext,
const nsIntRegion& aRegionToDraw,
const nsIntRegion& aDirtyRegion,
DrawRegionClip aClip,
const nsIntRegion& aRegionToInvalidate,
void* aCallbackData)
{
DrawTarget& aDrawTarget = *aContext->GetDrawTarget();
PROFILER_LABEL("FrameLayerBuilder", "DrawPaintedLayer",
js::ProfileEntry::Category::GRAPHICS);
nsDisplayListBuilder* builder = static_cast<nsDisplayListBuilder*>
(aCallbackData);
FrameLayerBuilder *layerBuilder = aLayer->Manager()->GetLayerBuilder();
NS_ASSERTION(layerBuilder, "Unexpectedly null layer builder!");
if (layerBuilder->CheckDOMModified())
return;
PaintedLayerItemsEntry* entry = layerBuilder->mPaintedLayerItems.GetEntry(aLayer);
NS_ASSERTION(entry, "We shouldn't be drawing into a layer with no items!");
if (!entry->mContainerLayerFrame) {
return;
}
PaintedDisplayItemLayerUserData* userData =
static_cast<PaintedDisplayItemLayerUserData*>
(aLayer->GetUserData(&gPaintedDisplayItemLayerUserData));
NS_ASSERTION(userData, "where did our user data go?");
bool shouldDrawRectsSeparately =
ShouldDrawRectsSeparately(&aDrawTarget, aClip);
if (!shouldDrawRectsSeparately) {
if (aClip == DrawRegionClip::DRAW) {
gfxUtils::ClipToRegion(aContext, aRegionToDraw);
}
DrawForcedBackgroundColor(aDrawTarget, aRegionToDraw.GetBounds(),
userData->mForcedBackgroundColor);
}
if (NS_GET_A(userData->mFontSmoothingBackgroundColor) > 0) {
aContext->SetFontSmoothingBackgroundColor(
Color::FromABGR(userData->mFontSmoothingBackgroundColor));
}
// make the origin of the context coincide with the origin of the
// PaintedLayer
gfxContextMatrixAutoSaveRestore saveMatrix(aContext);
nsIntPoint offset = GetTranslationForPaintedLayer(aLayer);
nsPresContext* presContext = entry->mContainerLayerFrame->PresContext();
if (!userData->mVisibilityComputedRegion.Contains(aDirtyRegion) &&
!layerBuilder->GetContainingPaintedLayerData()) {
// Recompute visibility of items in our PaintedLayer, if required. Note
// that this recomputes visibility for all descendants of our display
// items too, so there's no need to do this for the items in inactive
// PaintedLayers. If aDirtyRegion has not changed since the previous call
// then we can skip this.
int32_t appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
RecomputeVisibilityForItems(entry->mItems, builder, aDirtyRegion,
offset, appUnitsPerDevPixel,
userData->mXScale, userData->mYScale);
userData->mVisibilityComputedRegion = aDirtyRegion;
}
nsRenderingContext rc(aContext);
if (shouldDrawRectsSeparately) {
for (auto iter = aRegionToDraw.RectIter(); !iter.Done(); iter.Next()) {
const nsIntRect& iterRect = iter.Get();
gfxContextAutoSaveRestore save(aContext);
aContext->NewPath();
aContext->Rectangle(ThebesRect(iterRect));
aContext->Clip();
DrawForcedBackgroundColor(aDrawTarget, iterRect,
userData->mForcedBackgroundColor);
// Apply the residual transform if it has been enabled, to ensure that
// snapping when we draw into aContext exactly matches the ideal transform.
// See above for why this is OK.
aContext->SetMatrix(
aContext->CurrentMatrix().Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y)).
Scale(userData->mXScale, userData->mYScale));
layerBuilder->PaintItems(entry->mItems, iterRect, aContext, &rc,
builder, presContext,
offset, userData->mXScale, userData->mYScale,
entry->mCommonClipCount);
if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) {
aLayer->Manager()->AddPaintedPixelCount(iterRect.Area());
}
}
} else {
// Apply the residual transform if it has been enabled, to ensure that
// snapping when we draw into aContext exactly matches the ideal transform.
// See above for why this is OK.
aContext->SetMatrix(
aContext->CurrentMatrix().Translate(aLayer->GetResidualTranslation() - gfxPoint(offset.x, offset.y)).
Scale(userData->mXScale,userData->mYScale));
layerBuilder->PaintItems(entry->mItems, aRegionToDraw.GetBounds(), aContext, &rc,
builder, presContext,
offset, userData->mXScale, userData->mYScale,
entry->mCommonClipCount);
if (gfxPrefs::GfxLoggingPaintedPixelCountEnabled()) {
aLayer->Manager()->AddPaintedPixelCount(
aRegionToDraw.GetBounds().Area());
}
}
aContext->SetFontSmoothingBackgroundColor(Color());
bool isActiveLayerManager = !aLayer->Manager()->IsInactiveLayerManager();
if (presContext->GetPaintFlashing() && isActiveLayerManager) {
gfxContextAutoSaveRestore save(aContext);
if (shouldDrawRectsSeparately) {
if (aClip == DrawRegionClip::DRAW) {
gfxUtils::ClipToRegion(aContext, aRegionToDraw);
}
}
FlashPaint(aContext);
}
if (presContext->GetDocShell() && isActiveLayerManager) {
nsDocShell* docShell = static_cast<nsDocShell*>(presContext->GetDocShell());
RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get();
if (timelines && timelines->HasConsumer(docShell)) {
timelines->AddMarkerForDocShell(docShell, Move(
MakeUnique<LayerTimelineMarker>(aRegionToDraw)));
}
}
if (!aRegionToInvalidate.IsEmpty()) {
aLayer->AddInvalidRect(aRegionToInvalidate.GetBounds());
}
}
bool
FrameLayerBuilder::CheckDOMModified()
{
if (!mRootPresContext ||
mInitialDOMGeneration == mRootPresContext->GetDOMGeneration())
return false;
if (mDetectedDOMModification) {
// Don't spam the console with extra warnings
return true;
}
mDetectedDOMModification = true;
// Painting is not going to complete properly. There's not much
// we can do here though. Invalidating the window to get another repaint
// is likely to lead to an infinite repaint loop.
NS_WARNING("Detected DOM modification during paint, bailing out!");
return true;
}
/* static */ void
FrameLayerBuilder::DumpRetainedLayerTree(LayerManager* aManager, std::stringstream& aStream, bool aDumpHtml)
{
aManager->Dump(aStream, "", aDumpHtml);
}
nsDisplayItemGeometry*
FrameLayerBuilder::GetMostRecentGeometry(nsDisplayItem* aItem)
{
typedef nsTArray<DisplayItemData*> DataArray;
// Retrieve the array of DisplayItemData associated with our frame.
FrameProperties properties = aItem->Frame()->Properties();
const DataArray* dataArray =
properties.Get(LayerManagerDataProperty());
if (!dataArray) {
return nullptr;
}
// Find our display item data, if it exists, and return its geometry.
uint32_t itemPerFrameKey = aItem->GetPerFrameKey();
for (uint32_t i = 0; i < dataArray->Length(); i++) {
DisplayItemData* data = AssertDisplayItemData(dataArray->ElementAt(i));
if (data->GetDisplayItemKey() == itemPerFrameKey) {
return data->GetGeometry();
}
}
return nullptr;
}
gfx::Rect
CalculateBounds(const nsTArray<DisplayItemClip::RoundedRect>& aRects, int32_t A2D)
{
nsRect bounds = aRects[0].mRect;
for (uint32_t i = 1; i < aRects.Length(); ++i) {
bounds.UnionRect(bounds, aRects[i].mRect);
}
return gfx::ToRect(nsLayoutUtils::RectToGfxRect(bounds, A2D));
}
static void
SetClipCount(PaintedDisplayItemLayerUserData* apaintedData,
uint32_t aClipCount)
{
if (apaintedData) {
apaintedData->mMaskClipCount = aClipCount;
}
}
void
ContainerState::SetupMaskLayer(Layer *aLayer,
const DisplayItemClip& aClip,
uint32_t aRoundedRectClipCount)
{
// if the number of clips we are going to mask has decreased, then aLayer might have
// cached graphics which assume the existence of a soon-to-be non-existent mask layer
// in that case, invalidate the whole layer.
PaintedDisplayItemLayerUserData* paintedData = GetPaintedDisplayItemLayerUserData(aLayer);
if (paintedData &&
aRoundedRectClipCount < paintedData->mMaskClipCount) {
PaintedLayer* painted = aLayer->AsPaintedLayer();
painted->InvalidateRegion(painted->GetValidRegion().GetBounds());
}
// don't build an unnecessary mask
if (aClip.GetRoundedRectCount() == 0 ||
aRoundedRectClipCount == 0) {
SetClipCount(paintedData, 0);
return;
}
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<Layer> maskLayer =
CreateMaskLayer(aLayer, aClip, Nothing(), aRoundedRectClipCount);
if (!maskLayer) {
SetClipCount(paintedData, 0);
return;
}
aLayer->SetMaskLayer(maskLayer);
SetClipCount(paintedData, aRoundedRectClipCount);
}
already_AddRefed<Layer>
ContainerState::CreateMaskLayer(Layer *aLayer,
const DisplayItemClip& aClip,
const Maybe<size_t>& aForAncestorMaskLayer,
uint32_t aRoundedRectClipCount)
{
// check if we can re-use the mask layer
MaskLayerKey recycleKey(aLayer, aForAncestorMaskLayer);
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<ImageLayer> maskLayer = CreateOrRecycleMaskImageLayerFor(recycleKey);
MaskLayerUserData* userData = GetMaskLayerUserData(maskLayer);
MaskLayerUserData newData;
aClip.AppendRoundedRects(&newData.mRoundedClipRects, aRoundedRectClipCount);
newData.mScaleX = mParameters.mXScale;
newData.mScaleY = mParameters.mYScale;
newData.mOffset = mParameters.mOffset;
newData.mAppUnitsPerDevPixel = mContainerFrame->PresContext()->AppUnitsPerDevPixel();
if (*userData == newData) {
return maskLayer.forget();
}
// calculate a more precise bounding rect
gfx::Rect boundingRect = CalculateBounds(newData.mRoundedClipRects,
newData.mAppUnitsPerDevPixel);
boundingRect.Scale(mParameters.mXScale, mParameters.mYScale);
uint32_t maxSize = mManager->GetMaxTextureSize();
NS_ASSERTION(maxSize > 0, "Invalid max texture size");
#ifdef MOZ_GFX_OPTIMIZE_MOBILE
// Make mask image width aligned to 4. See Bug 1245552.
gfx::Size surfaceSize(std::min<gfx::Float>(GetAlignedStride<4>(NSToIntCeil(boundingRect.Width()), 1), maxSize),
std::min<gfx::Float>(boundingRect.Height(), maxSize));
#else
gfx::Size surfaceSize(std::min<gfx::Float>(boundingRect.Width(), maxSize),
std::min<gfx::Float>(boundingRect.Height(), maxSize));
#endif
// maskTransform is applied to the clip when it is painted into the mask (as a
// component of imageTransform), and its inverse used when the mask is used for
// masking.
// It is the transform from the masked layer's space to mask space
gfx::Matrix maskTransform =
Matrix::Scaling(surfaceSize.width / boundingRect.Width(),
surfaceSize.height / boundingRect.Height());
gfx::Point p = boundingRect.TopLeft();
maskTransform.PreTranslate(-p.x, -p.y);
// imageTransform is only used when the clip is painted to the mask
gfx::Matrix imageTransform = maskTransform;
imageTransform.PreScale(mParameters.mXScale, mParameters.mYScale);
nsAutoPtr<MaskLayerImageCache::MaskLayerImageKey> newKey(
new MaskLayerImageCache::MaskLayerImageKey());
// copy and transform the rounded rects
for (uint32_t i = 0; i < newData.mRoundedClipRects.Length(); ++i) {
newKey->mRoundedClipRects.AppendElement(
MaskLayerImageCache::PixelRoundedRect(newData.mRoundedClipRects[i],
mContainerFrame->PresContext()));
newKey->mRoundedClipRects[i].ScaleAndTranslate(imageTransform);
}
newKey->mForwarder = mManager->AsShadowForwarder();
const MaskLayerImageCache::MaskLayerImageKey* lookupKey = newKey;
2012-09-03 10:47:51 +00:00
// check to see if we can reuse a mask image
Bug 1207245 - part 6 - rename nsRefPtr<T> to RefPtr<T>; r=ehsan; a=Tomcat The bulk of this commit was generated with a script, executed at the top level of a typical source code checkout. The only non-machine-generated part was modifying MFBT's moz.build to reflect the new naming. CLOSED TREE makes big refactorings like this a piece of cake. # The main substitution. find . -name '*.cpp' -o -name '*.cc' -o -name '*.h' -o -name '*.mm' -o -name '*.idl'| \ xargs perl -p -i -e ' s/nsRefPtr\.h/RefPtr\.h/g; # handle includes s/nsRefPtr ?</RefPtr</g; # handle declarations and variables ' # Handle a special friend declaration in gfx/layers/AtomicRefCountedWithFinalize.h. perl -p -i -e 's/::nsRefPtr;/::RefPtr;/' gfx/layers/AtomicRefCountedWithFinalize.h # Handle nsRefPtr.h itself, a couple places that define constructors # from nsRefPtr, and code generators specially. We do this here, rather # than indiscriminantly s/nsRefPtr/RefPtr/, because that would rename # things like nsRefPtrHashtable. perl -p -i -e 's/nsRefPtr/RefPtr/g' \ mfbt/nsRefPtr.h \ xpcom/glue/nsCOMPtr.h \ xpcom/base/OwningNonNull.h \ ipc/ipdl/ipdl/lower.py \ ipc/ipdl/ipdl/builtin.py \ dom/bindings/Codegen.py \ python/lldbutils/lldbutils/utils.py # In our indiscriminate substitution above, we renamed # nsRefPtrGetterAddRefs, the class behind getter_AddRefs. Fix that up. find . -name '*.cpp' -o -name '*.h' -o -name '*.idl' | \ xargs perl -p -i -e 's/nsRefPtrGetterAddRefs/RefPtrGetterAddRefs/g' if [ -d .git ]; then git mv mfbt/nsRefPtr.h mfbt/RefPtr.h else hg mv mfbt/nsRefPtr.h mfbt/RefPtr.h fi --HG-- rename : mfbt/nsRefPtr.h => mfbt/RefPtr.h
2015-10-18 05:24:48 +00:00
RefPtr<ImageContainer> container =
GetMaskLayerImageCache()->FindImageFor(&lookupKey);
if (!container) {
IntSize surfaceSizeInt(NSToIntCeil(surfaceSize.width),
NSToIntCeil(surfaceSize.height));
// no existing mask image, so build a new one
MaskImageData imageData(surfaceSizeInt, mManager);
RefPtr<DrawTarget> dt = imageData.CreateDrawTarget();
// fail if we can't get the right surface
if (!dt || !dt->IsValid()) {
NS_WARNING("Could not create DrawTarget for mask layer.");
return nullptr;
}
RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
MOZ_ASSERT(context); // already checked the draw target above
context->Multiply(ThebesMatrix(imageTransform));
// paint the clipping rects with alpha to create the mask
aClip.FillIntersectionOfRoundedRectClips(context,
Color(1.f, 1.f, 1.f, 1.f),
newData.mAppUnitsPerDevPixel,
0,
aRoundedRectClipCount);
// build the image and container
container = aLayer->Manager()->CreateImageContainer();
NS_ASSERTION(container, "Could not create image container for mask layer.");
RefPtr<Image> image = imageData.CreateImage();
if (!image) {
return nullptr;
}
container->SetCurrentImageInTransaction(image);
GetMaskLayerImageCache()->PutImage(newKey.forget(), container);
}
maskLayer->SetContainer(container);
maskTransform.Invert();
Matrix4x4 matrix = Matrix4x4::From2D(maskTransform);
matrix.PreTranslate(mParameters.mOffset.x, mParameters.mOffset.y, 0);
maskLayer->SetBaseTransform(matrix);
// save the details of the clip in user data
userData->mScaleX = newData.mScaleX;
userData->mScaleY = newData.mScaleY;
userData->mOffset = newData.mOffset;
userData->mAppUnitsPerDevPixel = newData.mAppUnitsPerDevPixel;
userData->mRoundedClipRects.SwapElements(newData.mRoundedClipRects);
userData->mImageKey.Reset(lookupKey);
return maskLayer.forget();
}
} // namespace mozilla