mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 749075. Part 1: Refactor the nsDisplayItem API for testing whether the item needs to be rendered to a transparent surface. r=mattwoodrow
Currently we return an extra out parameter on GetOpaqueRegion. This is ugly and it's also going to be inefficient because in a followup patch I'm going to avoid calls to GetOpaqueRegion, but we still need to know whether the item needs a transparent surface. So this patch removes that out parameter. Instead, we rely on the fact that only Windows' glass-window-background display item needs to force a transparent surface, and there can only be one of those per window. So we store a reference to it in the nsDisplayListBuilder if there is one, and then we can efficiently tell if any leaf display item is the one that forces a transparent surface. For display items that wrap a list, we continue to store whether they need to force a transparent surface in a boolean in the list.
This commit is contained in:
parent
db184efc0a
commit
1c1601b380
@ -1189,9 +1189,13 @@ ContainerState::ThebesLayerData::Accumulate(ContainerState* aState,
|
||||
const nsIntRect& aDrawRect,
|
||||
const FrameLayerBuilder::Clip& aClip)
|
||||
{
|
||||
if (aState->mBuilder->NeedToForceTransparentSurfaceForItem(aItem)) {
|
||||
mForceTransparentSurface = true;
|
||||
}
|
||||
|
||||
nscolor uniformColor;
|
||||
bool isUniform = aItem->IsUniform(aState->mBuilder, &uniformColor);
|
||||
|
||||
|
||||
/* Mark as available for conversion to image layer if this is a nsDisplayImage and
|
||||
* we are the first visible item in the ThebesLayerData object.
|
||||
*/
|
||||
@ -1238,10 +1242,8 @@ ContainerState::ThebesLayerData::Accumulate(ContainerState* aState,
|
||||
mDrawRegion.SimplifyOutward(4);
|
||||
}
|
||||
|
||||
bool forceTransparentSurface;
|
||||
bool snap;
|
||||
nsRegion opaque = aItem->GetOpaqueRegion(aState->mBuilder, &snap,
|
||||
&forceTransparentSurface);
|
||||
nsRegion opaque = aItem->GetOpaqueRegion(aState->mBuilder, &snap);
|
||||
if (!opaque.IsEmpty()) {
|
||||
nsRegionRectIterator iter(opaque);
|
||||
for (const nsRect* r = iter.Next(); r; r = iter.Next()) {
|
||||
@ -1284,7 +1286,6 @@ ContainerState::ThebesLayerData::Accumulate(ContainerState* aState,
|
||||
}
|
||||
}
|
||||
}
|
||||
mForceTransparentSurface = mForceTransparentSurface || forceTransparentSurface;
|
||||
}
|
||||
|
||||
already_AddRefed<ThebesLayer>
|
||||
|
@ -82,6 +82,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||
mFinalTransparentRegion(nsnull),
|
||||
mCachedOffsetFrame(aReferenceFrame),
|
||||
mCachedOffset(0, 0),
|
||||
mGlassDisplayItem(nsnull),
|
||||
mMode(aMode),
|
||||
mBuildCaret(aBuildCaret),
|
||||
mIgnoreSuppression(false),
|
||||
@ -443,11 +444,10 @@ nsDisplayList::ComputeVisibilityForRoot(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
|
||||
static nsRegion
|
||||
TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder,
|
||||
bool* aTransparentBackground)
|
||||
TreatAsOpaque(nsDisplayItem* aItem, nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
bool snap;
|
||||
nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, &snap, aTransparentBackground);
|
||||
nsRegion opaque = aItem->GetOpaqueRegion(aBuilder, &snap);
|
||||
if (aBuilder->IsForPluginGeometry()) {
|
||||
// Treat all chrome items as opaque, unless their frames are opacity:0.
|
||||
// Since opacity:0 frames generate an nsDisplayOpacity, that item will
|
||||
@ -535,11 +535,13 @@ nsDisplayList::ComputeVisibilityForSublist(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
if (item->ComputeVisibility(aBuilder, aVisibleRegion, aAllowVisibleRegionExpansion)) {
|
||||
anyVisible = true;
|
||||
bool transparentBackground = false;
|
||||
nsRegion opaque = TreatAsOpaque(item, aBuilder, &transparentBackground);
|
||||
nsRegion opaque = TreatAsOpaque(item, aBuilder);
|
||||
// Subtract opaque item from the visible region
|
||||
aBuilder->SubtractFromVisibleRegion(aVisibleRegion, opaque);
|
||||
forceTransparentSurface = forceTransparentSurface || transparentBackground;
|
||||
if (aBuilder->NeedToForceTransparentSurfaceForItem(item) ||
|
||||
(list && list->NeedsTransparentSurface())) {
|
||||
forceTransparentSurface = true;
|
||||
}
|
||||
}
|
||||
AppendToBottom(item);
|
||||
}
|
||||
@ -930,8 +932,7 @@ bool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
if (!ComputeVisibility(aBuilder, aVisibleRegion, nsRect()))
|
||||
return false;
|
||||
|
||||
bool forceTransparentBackground;
|
||||
nsRegion opaque = TreatAsOpaque(this, aBuilder, &forceTransparentBackground);
|
||||
nsRegion opaque = TreatAsOpaque(this, aBuilder);
|
||||
aBuilder->SubtractFromVisibleRegion(aVisibleRegion, opaque);
|
||||
return true;
|
||||
}
|
||||
@ -983,6 +984,9 @@ nsDisplayBackground::nsDisplayBackground(nsDisplayListBuilder* aBuilder,
|
||||
if (disp->mAppearance == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR ||
|
||||
disp->mAppearance == NS_THEME_TOOLBAR) {
|
||||
RegisterThemeGeometry(aBuilder, aFrame);
|
||||
} else if (disp->mAppearance == NS_THEME_WIN_BORDERLESS_GLASS ||
|
||||
disp->mAppearance == NS_THEME_WIN_GLASS) {
|
||||
aBuilder->SetGlassDisplayItem(this);
|
||||
}
|
||||
} else {
|
||||
// Set HasFixedItems if we construct a background-attachment:fixed item
|
||||
@ -1170,18 +1174,11 @@ nsDisplayBackground::GetInsideClipRegion(nsPresContext* aPresContext,
|
||||
|
||||
nsRegion
|
||||
nsDisplayBackground::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface) {
|
||||
bool* aSnap) {
|
||||
nsRegion result;
|
||||
*aSnap = false;
|
||||
*aForceTransparentSurface = false;
|
||||
// theme background overrides any other background
|
||||
if (mIsThemed) {
|
||||
if (aForceTransparentSurface) {
|
||||
const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
|
||||
*aForceTransparentSurface = disp->mAppearance == NS_THEME_WIN_BORDERLESS_GLASS ||
|
||||
disp->mAppearance == NS_THEME_WIN_GLASS;
|
||||
}
|
||||
if (mThemeTransparency == nsITheme::eOpaque) {
|
||||
result = GetBounds(aBuilder, aSnap);
|
||||
}
|
||||
@ -1629,9 +1626,7 @@ nsDisplayWrapList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
nsRegion
|
||||
nsDisplayWrapList::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = false;
|
||||
bool* aSnap) {
|
||||
*aSnap = false;
|
||||
nsRegion result;
|
||||
if (mList.IsOpaque()) {
|
||||
@ -1776,9 +1771,7 @@ nsDisplayOpacity::~nsDisplayOpacity() {
|
||||
#endif
|
||||
|
||||
nsRegion nsDisplayOpacity::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface) {
|
||||
*aForceTransparentSurface = false;
|
||||
bool* aSnap) {
|
||||
*aSnap = false;
|
||||
// We are never opaque, if our opacity was < 1 then we wouldn't have
|
||||
// been created.
|
||||
@ -2213,11 +2206,9 @@ nsDisplayClipRoundedRect::~nsDisplayClipRoundedRect()
|
||||
|
||||
nsRegion
|
||||
nsDisplayClipRoundedRect::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface)
|
||||
bool* aSnap)
|
||||
{
|
||||
*aSnap = false;
|
||||
*aForceTransparentSurface = false;
|
||||
return nsRegion();
|
||||
}
|
||||
|
||||
@ -2852,10 +2843,8 @@ nsRect nsDisplayTransform::GetBounds(nsDisplayListBuilder *aBuilder, bool* aSnap
|
||||
* certainly contains the actual (non-axis-aligned) untransformed rect.
|
||||
*/
|
||||
nsRegion nsDisplayTransform::GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface)
|
||||
bool* aSnap)
|
||||
{
|
||||
*aForceTransparentSurface = false;
|
||||
*aSnap = false;
|
||||
nsRect untransformedVisible;
|
||||
float factor = nsPresContext::AppUnitsPerCSSPixel();
|
||||
@ -2868,11 +2857,9 @@ nsRegion nsDisplayTransform::GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
|
||||
nsRegion result;
|
||||
gfxMatrix matrix2d;
|
||||
bool tmpSnap;
|
||||
bool forceTransparentSurface;
|
||||
if (matrix.Is2D(&matrix2d) &&
|
||||
matrix2d.PreservesAxisAlignedRectangles() &&
|
||||
mStoredList.GetOpaqueRegion(aBuilder, &tmpSnap, &forceTransparentSurface).
|
||||
Contains(untransformedVisible)) {
|
||||
mStoredList.GetOpaqueRegion(aBuilder, &tmpSnap).Contains(untransformedVisible)) {
|
||||
result = mVisibleRect;
|
||||
}
|
||||
return result;
|
||||
@ -3032,10 +3019,8 @@ nsDisplaySVGEffects::~nsDisplaySVGEffects()
|
||||
#endif
|
||||
|
||||
nsRegion nsDisplaySVGEffects::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface)
|
||||
bool* aSnap)
|
||||
{
|
||||
*aForceTransparentSurface = false;
|
||||
*aSnap = false;
|
||||
return nsRegion();
|
||||
}
|
||||
|
@ -496,6 +496,20 @@ public:
|
||||
const nsRegion& GetExcludedGlassRegion() {
|
||||
return mExcludedGlassRegion;
|
||||
}
|
||||
void SetGlassDisplayItem(nsDisplayItem* aItem) {
|
||||
if (mGlassDisplayItem) {
|
||||
// Web pages or extensions could trigger this by using
|
||||
// -moz-appearance:win-borderless-glass etc on their own elements.
|
||||
// Keep the first one, since that will be the background of the root
|
||||
// window
|
||||
NS_WARNING("Multiple glass backgrounds found?");
|
||||
} else {
|
||||
mGlassDisplayItem = aItem;
|
||||
}
|
||||
}
|
||||
bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem) {
|
||||
return aItem == mGlassDisplayItem;
|
||||
}
|
||||
|
||||
private:
|
||||
void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
|
||||
@ -529,6 +543,8 @@ private:
|
||||
nsPoint mCachedOffset;
|
||||
nsRect mDisplayPort;
|
||||
nsRegion mExcludedGlassRegion;
|
||||
// The display item for the Windows window glass background, if any
|
||||
nsDisplayItem* mGlassDisplayItem;
|
||||
Mode mMode;
|
||||
bool mBuildCaret;
|
||||
bool mIgnoreSuppression;
|
||||
@ -699,11 +715,9 @@ public:
|
||||
* culling.
|
||||
*/
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface)
|
||||
bool* aSnap)
|
||||
{
|
||||
*aSnap = false;
|
||||
*aForceTransparentSurface = false;
|
||||
return nsRegion();
|
||||
}
|
||||
/**
|
||||
@ -1217,8 +1231,7 @@ private:
|
||||
// opaque content in this list).
|
||||
bool mIsOpaque;
|
||||
// This is set to true by ComputeVisibility if any display item in this
|
||||
// list needs to force the surface to be transparent (e.g. if the
|
||||
// item "punch holes" on the surface by clearing part of its area).
|
||||
// list needs to force the surface containing this list to be transparent.
|
||||
bool mForceTransparentSurface;
|
||||
#ifdef DEBUG
|
||||
bool mDidComputeVisibility;
|
||||
@ -1554,10 +1567,8 @@ public:
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
|
||||
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aOutTransparentBackground) {
|
||||
bool* aSnap) {
|
||||
*aSnap = false;
|
||||
*aOutTransparentBackground = false;
|
||||
nsRegion result;
|
||||
if (NS_GET_A(mColor) == 255) {
|
||||
result = GetBounds(aBuilder, aSnap);
|
||||
@ -1598,8 +1609,7 @@ public:
|
||||
nsRegion* aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface);
|
||||
bool* aSnap);
|
||||
virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame);
|
||||
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
|
||||
@ -1755,8 +1765,7 @@ public:
|
||||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface);
|
||||
bool* aSnap);
|
||||
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
|
||||
virtual bool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame);
|
||||
@ -1861,8 +1870,7 @@ public:
|
||||
#endif
|
||||
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface);
|
||||
bool* aSnap);
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters);
|
||||
@ -2068,8 +2076,7 @@ public:
|
||||
#endif
|
||||
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface);
|
||||
bool* aSnap);
|
||||
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
||||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
@ -2140,8 +2147,7 @@ public:
|
||||
#endif
|
||||
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface);
|
||||
bool* aSnap);
|
||||
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
|
||||
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) {
|
||||
@ -2221,8 +2227,7 @@ public:
|
||||
HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames);
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder, bool* aSnap);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder *aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface);
|
||||
bool* aSnap);
|
||||
virtual bool IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor);
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager);
|
||||
|
@ -192,8 +192,7 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (!list || list->DidComputeVisibility()) {
|
||||
bool forceTransparentSurface;
|
||||
opaque = i->GetOpaqueRegion(aBuilder, &snap, &forceTransparentSurface);
|
||||
opaque = i->GetOpaqueRegion(aBuilder, &snap);
|
||||
}
|
||||
#endif
|
||||
if (i->Painted()) {
|
||||
|
@ -170,15 +170,12 @@ public:
|
||||
aAllowVisibleRegionExpansion);
|
||||
}
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface)
|
||||
bool* aSnap)
|
||||
{
|
||||
if (NS_GET_A(mExtraBackgroundColor) == 255) {
|
||||
*aForceTransparentSurface = false;
|
||||
return nsRegion(GetBounds(aBuilder, aSnap));
|
||||
}
|
||||
return nsDisplayBackground::GetOpaqueRegion(aBuilder, aSnap,
|
||||
aForceTransparentSurface);
|
||||
return nsDisplayBackground::GetOpaqueRegion(aBuilder, aSnap);
|
||||
}
|
||||
virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
|
||||
{
|
||||
|
@ -1000,10 +1000,8 @@ nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
nsRegion
|
||||
nsDisplayPlugin::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface)
|
||||
bool* aSnap)
|
||||
{
|
||||
*aForceTransparentSurface = false;
|
||||
*aSnap = false;
|
||||
nsRegion result;
|
||||
nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
|
||||
|
@ -301,8 +301,7 @@ public:
|
||||
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap);
|
||||
virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
|
||||
bool* aSnap,
|
||||
bool* aForceTransparentSurface);
|
||||
bool* aSnap);
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx);
|
||||
virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
|
||||
|
Loading…
Reference in New Issue
Block a user