diff --git a/content/base/src/nsRuleNode.cpp b/content/base/src/nsRuleNode.cpp
index fbf4dc045798..f4d109d4008c 100644
--- a/content/base/src/nsRuleNode.cpp
+++ b/content/base/src/nsRuleNode.cpp
@@ -2509,6 +2509,15 @@ nsRuleNode::ComputeDisplayData(nsStyleStruct* aStartStruct,
parentDisplay = parentContext->GetStyleDisplay();
PRBool inherited = aInherited;
+ // opacity: factor, inherit
+ if (eCSSUnit_Number == displayData.mOpacity.GetUnit()) {
+ display->mOpacity = displayData.mOpacity.GetFloatValue();
+ }
+ else if (eCSSUnit_Inherit == displayData.mOpacity.GetUnit()) {
+ inherited = PR_TRUE;
+ display->mOpacity = parentDisplay->mOpacity;
+ }
+
// display: enum, none, inherit
if (eCSSUnit_Enumerated == displayData.mDisplay.GetUnit()) {
display->mDisplay = displayData.mDisplay.GetIntValue();
@@ -2769,15 +2778,6 @@ nsRuleNode::ComputeVisibilityData(nsStyleStruct* aStartStruct,
if (!parentVisibility)
parentVisibility = visibility;
- // opacity: factor, inherit
- if (eCSSUnit_Number == displayData.mOpacity.GetUnit()) {
- visibility->mOpacity = displayData.mOpacity.GetFloatValue();
- }
- else if (eCSSUnit_Inherit == displayData.mOpacity.GetUnit()) {
- inherited = PR_TRUE;
- visibility->mOpacity = parentVisibility->mOpacity;
- }
-
// direction: enum, inherit
if (eCSSUnit_Enumerated == displayData.mDirection.GetUnit()) {
visibility->mDirection = displayData.mDirection.GetIntValue();
diff --git a/content/base/src/nsStyleContext.cpp b/content/base/src/nsStyleContext.cpp
index 13728180b0fa..788f7f1a550f 100644
--- a/content/base/src/nsStyleContext.cpp
+++ b/content/base/src/nsStyleContext.cpp
@@ -711,9 +711,10 @@ void nsStyleContext::DumpRegressionData(nsIPresContext* aPresContext, FILE* out,
// DISPLAY
IndentBy(out,aIndent);
const nsStyleDisplay* disp = GetStyleDisplay();
- fprintf(out, "\n",
+ fprintf(out, "\n",
(int)disp->mPosition,
(int)disp->mDisplay,
+ (float)disp->mOpacity,
(int)disp->mFloats,
(int)disp->mBreakType,
(int)disp->mBreakBefore,
@@ -730,10 +731,9 @@ void nsStyleContext::DumpRegressionData(nsIPresContext* aPresContext, FILE* out,
// VISIBILITY
IndentBy(out,aIndent);
const nsStyleVisibility* vis = GetStyleVisibility();
- fprintf(out, "\n",
+ fprintf(out, "\n",
(int)vis->mDirection,
- (int)vis->mVisible,
- (float)vis->mOpacity
+ (int)vis->mVisible
);
// TABLE
diff --git a/content/html/style/src/nsComputedDOMStyle.cpp b/content/html/style/src/nsComputedDOMStyle.cpp
index 39430a63fa3f..599b3c13fcaf 100644
--- a/content/html/style/src/nsComputedDOMStyle.cpp
+++ b/content/html/style/src/nsComputedDOMStyle.cpp
@@ -460,12 +460,11 @@ nsComputedDOMStyle::GetOpacity(nsIFrame *aFrame,
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
- const nsStyleVisibility *visibility = nsnull;
- GetStyleData(eStyleStruct_Visibility, (const nsStyleStruct*&)visibility,
- aFrame);
+ const nsStyleDisplay *display = nsnull;
+ GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display, aFrame);
- if (visibility) {
- val->SetNumber(visibility->mOpacity);
+ if (display) {
+ val->SetNumber(display->mOpacity);
} else {
val->SetNumber(1.0f);
}
diff --git a/content/html/style/src/nsHTMLCSSStyleSheet.cpp b/content/html/style/src/nsHTMLCSSStyleSheet.cpp
index dc2ae81ee7b9..07b5d8a82c86 100644
--- a/content/html/style/src/nsHTMLCSSStyleSheet.cpp
+++ b/content/html/style/src/nsHTMLCSSStyleSheet.cpp
@@ -162,7 +162,6 @@ CSSDisablePropsRule::CommonMapRuleInfoInto(nsRuleData* aData)
nsCSSValue inherit(eCSSUnit_Inherit);
aData->mDisplayData->mVisibility = inherit;
aData->mDisplayData->mDirection = inherit;
- aData->mDisplayData->mOpacity = inherit;
}
if (aData->mSID == eStyleStruct_Display) {
@@ -175,6 +174,9 @@ CSSDisablePropsRule::CommonMapRuleInfoInto(nsRuleData* aData)
aData->mDisplayData->mClip.mBottom = autovalue;
aData->mDisplayData->mClip.mLeft = autovalue;
+ nsCSSValue one(1.0f, eCSSUnit_Number);
+ aData->mDisplayData->mOpacity = one;
+
nsCSSValue inlinevalue(NS_STYLE_DISPLAY_INLINE, eCSSUnit_Enumerated);
aData->mDisplayData->mDisplay = inlinevalue;
diff --git a/content/shared/public/nsCSSPropList.h b/content/shared/public/nsCSSPropList.h
index 3c0f9a14c42d..0e3d4e7b0101 100644
--- a/content/shared/public/nsCSSPropList.h
+++ b/content/shared/public/nsCSSPropList.h
@@ -362,7 +362,7 @@ CSS_PROP_POSITION(max-height, max_height, MaxHeight, Position, mMaxHeight, eCSST
CSS_PROP_POSITION(max-width, max_width, MaxWidth, Position, mMaxWidth, eCSSType_Value, PR_TRUE)
CSS_PROP_POSITION(min-height, min_height, MinHeight, Position, mMinHeight, eCSSType_Value, PR_TRUE)
CSS_PROP_POSITION(min-width, min_width, MinWidth, Position, mMinWidth, eCSSType_Value, PR_TRUE)
-CSS_PROP_VISIBILITY(-moz-opacity, opacity, MozOpacity, Display, mOpacity, eCSSType_Value, PR_FALSE) // XXX bug 3935
+CSS_PROP_DISPLAY(-moz-opacity, opacity, MozOpacity, Display, mOpacity, eCSSType_Value, PR_FALSE) // XXX bug 3935
CSS_PROP_BACKENDONLY(orphans, orphans, Orphans, Breaks, mOrphans, eCSSType_Value, PR_FALSE)
CSS_PROP_NOTIMPLEMENTED(outline, outline, Outline)
CSS_PROP_NOTIMPLEMENTED(outline-color, outline_color, OutlineColor)
diff --git a/content/shared/public/nsStyleStruct.h b/content/shared/public/nsStyleStruct.h
index 547960a1b259..78dfdee93502 100644
--- a/content/shared/public/nsStyleStruct.h
+++ b/content/shared/public/nsStyleStruct.h
@@ -702,7 +702,6 @@ struct nsStyleVisibility : public nsStyleStruct {
PRUint8 mDirection; // [inherited] see nsStyleConsts.h NS_STYLE_DIRECTION_*
PRUint8 mVisible; // [inherited]
nsCOMPtr mLanguage; // [inherited]
- float mOpacity; // [inherited]
PRBool IsVisible() const {
return (mVisible == NS_STYLE_VISIBILITY_VISIBLE);
@@ -742,6 +741,7 @@ struct nsStyleDisplay : public nsStyleStruct {
#else
nsRect mClip; // [reset] offsets from upper-left border edge
#endif
+ float mOpacity; // [reset]
PRUint8 mDisplay; // [reset] see nsStyleConsts.h NS_STYLE_DISPLAY_*
PRUint8 mOriginalDisplay; // [reset] saved mDisplay for position:absolute/fixed
PRUint8 mAppearance; // [reset]
@@ -751,7 +751,6 @@ struct nsStyleDisplay : public nsStyleStruct {
PRPackedBool mBreakBefore; // [reset]
PRPackedBool mBreakAfter; // [reset]
PRUint8 mOverflow; // [reset] see nsStyleConsts.h
-
PRUint8 mClipFlags; // [reset] see nsStyleConsts.h
PRBool IsBlockLevel() const {return (NS_STYLE_DISPLAY_BLOCK == mDisplay) ||
diff --git a/content/shared/src/nsStyleStruct.cpp b/content/shared/src/nsStyleStruct.cpp
index 670d0f4216f4..fe3ad4c309e7 100644
--- a/content/shared/src/nsStyleStruct.cpp
+++ b/content/shared/src/nsStyleStruct.cpp
@@ -1068,6 +1068,7 @@ nsStyleDisplay::nsStyleDisplay()
mOverflow = NS_STYLE_OVERFLOW_VISIBLE;
mClipFlags = NS_STYLE_CLIP_AUTO;
mClip.SetRect(0,0,0,0);
+ mOpacity = 1.0f;
}
nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
@@ -1084,6 +1085,7 @@ nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
mOverflow = aSource.mOverflow;
mClipFlags = aSource.mClipFlags;
mClip = aSource.mClip;
+ mOpacity = aSource.mOpacity;
}
nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
@@ -1094,7 +1096,10 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
|| mPosition != aOther.mPosition
|| mDisplay != aOther.mDisplay
|| mFloats != aOther.mFloats
- || mOverflow != aOther.mOverflow)
+ || mOverflow != aOther.mOverflow
+ // might need to create a view to handle change from 1.0 to partial opacity
+ || (mOpacity != aOther.mOpacity
+ && ((mOpacity < 1.0) != (aOther.mOpacity < 1.0))))
NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
// XXX the following is conservative, for now: changing float breaking shouldn't
@@ -1106,7 +1111,8 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame));
if (mClipFlags != aOther.mClipFlags
- || mClip != aOther.mClip)
+ || mClip != aOther.mClip
+ || mOpacity != aOther.mOpacity)
NS_UpdateHint(hint, nsChangeHint_SyncFrameView);
return hint;
@@ -1127,7 +1133,6 @@ nsStyleVisibility::nsStyleVisibility(nsIPresContext* aPresContext)
aPresContext->GetLanguage(getter_AddRefs(mLanguage));
mVisible = NS_STYLE_VISIBILITY_VISIBLE;
- mOpacity = 1.0f;
}
nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
@@ -1135,23 +1140,14 @@ nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
mDirection = aSource.mDirection;
mVisible = aSource.mVisible;
mLanguage = aSource.mLanguage;
- mOpacity = aSource.mOpacity;
}
nsChangeHint nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) const
{
- if (mOpacity != aOther.mOpacity
- && ((mOpacity < 1.0) != (aOther.mOpacity < 1.0)))
- // might need to create a view to handle change from 1.0 to partial opacity
- return NS_STYLE_HINT_FRAMECHANGE;
-
if ((mDirection == aOther.mDirection) &&
(mLanguage == aOther.mLanguage)) {
if ((mVisible == aOther.mVisible)) {
- if (mOpacity == aOther.mOpacity)
- return NS_STYLE_HINT_NONE;
- else
- return NS_STYLE_HINT_VISUAL;
+ return NS_STYLE_HINT_NONE;
}
if ((mVisible != aOther.mVisible) &&
((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
diff --git a/layout/forms/nsHTMLButtonControlFrame.cpp b/layout/forms/nsHTMLButtonControlFrame.cpp
index 31f25d5ecedc..0a2d6b53ba54 100644
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -450,8 +450,7 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext* aPresContext,
SetView(view);
// set the opacity
- viewMan->SetViewOpacity(view, GetStyleColor()->mOpacity);
-
+ viewMan->SetViewOpacity(view, GetStyleDisplay()->mOpacity);
}
mDidInit = PR_TRUE;
}
diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp
index 1c7787fdf01e..dc3a3076c6f5 100644
--- a/layout/generic/nsContainerFrame.cpp
+++ b/layout/generic/nsContainerFrame.cpp
@@ -798,13 +798,15 @@ nsContainerFrame::SyncFrameViewProperties(nsIPresContext* aPresContext,
aStyleContext = aFrame->GetStyleContext();
}
- const nsStyleVisibility* vis = aStyleContext->GetStyleVisibility();
+ const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
// Set the view's opacity
- vm->SetViewOpacity(aView, vis->mOpacity);
+ vm->SetViewOpacity(aView, display->mOpacity);
// Make sure visibility is correct
if (0 == (aFlags & NS_FRAME_NO_VISIBILITY)) {
+ const nsStyleVisibility* vis = aStyleContext->GetStyleVisibility();
+
// See if the view should be hidden or visible
PRBool viewIsVisible = PR_TRUE;
@@ -834,7 +836,6 @@ nsContainerFrame::SyncFrameViewProperties(nsIPresContext* aPresContext,
nsViewVisibility_kHide);
}
- const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
// See if the frame is being relatively positioned or absolutely
// positioned
PRBool isTopMostView = display->IsPositioned();
@@ -860,9 +861,8 @@ PRBool
nsContainerFrame::FrameNeedsView(nsIFrame* aFrame)
{
nsStyleContext* sc = aFrame->GetStyleContext();
- const nsStyleVisibility* vis = sc->GetStyleVisibility();
-
- if (vis->mOpacity != 1.0f) {
+ const nsStyleDisplay* display = sc->GetStyleDisplay();
+ if (display->mOpacity != 1.0f) {
return PR_TRUE;
}
@@ -877,8 +877,6 @@ nsContainerFrame::FrameNeedsView(nsIFrame* aFrame)
return PR_TRUE;
}
- const nsStyleDisplay* display = sc->GetStyleDisplay();
-
if (NS_STYLE_POSITION_RELATIVE == display->mPosition) {
return PR_TRUE;
} else if (display->IsAbsolutelyPositioned()) {
diff --git a/layout/html/base/src/nsContainerFrame.cpp b/layout/html/base/src/nsContainerFrame.cpp
index 1c7787fdf01e..dc3a3076c6f5 100644
--- a/layout/html/base/src/nsContainerFrame.cpp
+++ b/layout/html/base/src/nsContainerFrame.cpp
@@ -798,13 +798,15 @@ nsContainerFrame::SyncFrameViewProperties(nsIPresContext* aPresContext,
aStyleContext = aFrame->GetStyleContext();
}
- const nsStyleVisibility* vis = aStyleContext->GetStyleVisibility();
+ const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
// Set the view's opacity
- vm->SetViewOpacity(aView, vis->mOpacity);
+ vm->SetViewOpacity(aView, display->mOpacity);
// Make sure visibility is correct
if (0 == (aFlags & NS_FRAME_NO_VISIBILITY)) {
+ const nsStyleVisibility* vis = aStyleContext->GetStyleVisibility();
+
// See if the view should be hidden or visible
PRBool viewIsVisible = PR_TRUE;
@@ -834,7 +836,6 @@ nsContainerFrame::SyncFrameViewProperties(nsIPresContext* aPresContext,
nsViewVisibility_kHide);
}
- const nsStyleDisplay* display = aStyleContext->GetStyleDisplay();
// See if the frame is being relatively positioned or absolutely
// positioned
PRBool isTopMostView = display->IsPositioned();
@@ -860,9 +861,8 @@ PRBool
nsContainerFrame::FrameNeedsView(nsIFrame* aFrame)
{
nsStyleContext* sc = aFrame->GetStyleContext();
- const nsStyleVisibility* vis = sc->GetStyleVisibility();
-
- if (vis->mOpacity != 1.0f) {
+ const nsStyleDisplay* display = sc->GetStyleDisplay();
+ if (display->mOpacity != 1.0f) {
return PR_TRUE;
}
@@ -877,8 +877,6 @@ nsContainerFrame::FrameNeedsView(nsIFrame* aFrame)
return PR_TRUE;
}
- const nsStyleDisplay* display = sc->GetStyleDisplay();
-
if (NS_STYLE_POSITION_RELATIVE == display->mPosition) {
return PR_TRUE;
} else if (display->IsAbsolutelyPositioned()) {
diff --git a/layout/html/forms/src/nsHTMLButtonControlFrame.cpp b/layout/html/forms/src/nsHTMLButtonControlFrame.cpp
index 31f25d5ecedc..0a2d6b53ba54 100644
--- a/layout/html/forms/src/nsHTMLButtonControlFrame.cpp
+++ b/layout/html/forms/src/nsHTMLButtonControlFrame.cpp
@@ -450,8 +450,7 @@ nsHTMLButtonControlFrame::Reflow(nsIPresContext* aPresContext,
SetView(view);
// set the opacity
- viewMan->SetViewOpacity(view, GetStyleColor()->mOpacity);
-
+ viewMan->SetViewOpacity(view, GetStyleDisplay()->mOpacity);
}
mDidInit = PR_TRUE;
}
diff --git a/layout/style/nsCSSPropList.h b/layout/style/nsCSSPropList.h
index 3c0f9a14c42d..0e3d4e7b0101 100644
--- a/layout/style/nsCSSPropList.h
+++ b/layout/style/nsCSSPropList.h
@@ -362,7 +362,7 @@ CSS_PROP_POSITION(max-height, max_height, MaxHeight, Position, mMaxHeight, eCSST
CSS_PROP_POSITION(max-width, max_width, MaxWidth, Position, mMaxWidth, eCSSType_Value, PR_TRUE)
CSS_PROP_POSITION(min-height, min_height, MinHeight, Position, mMinHeight, eCSSType_Value, PR_TRUE)
CSS_PROP_POSITION(min-width, min_width, MinWidth, Position, mMinWidth, eCSSType_Value, PR_TRUE)
-CSS_PROP_VISIBILITY(-moz-opacity, opacity, MozOpacity, Display, mOpacity, eCSSType_Value, PR_FALSE) // XXX bug 3935
+CSS_PROP_DISPLAY(-moz-opacity, opacity, MozOpacity, Display, mOpacity, eCSSType_Value, PR_FALSE) // XXX bug 3935
CSS_PROP_BACKENDONLY(orphans, orphans, Orphans, Breaks, mOrphans, eCSSType_Value, PR_FALSE)
CSS_PROP_NOTIMPLEMENTED(outline, outline, Outline)
CSS_PROP_NOTIMPLEMENTED(outline-color, outline_color, OutlineColor)
diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp
index 39430a63fa3f..599b3c13fcaf 100644
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -460,12 +460,11 @@ nsComputedDOMStyle::GetOpacity(nsIFrame *aFrame,
nsROCSSPrimitiveValue *val = GetROCSSPrimitiveValue();
NS_ENSURE_TRUE(val, NS_ERROR_OUT_OF_MEMORY);
- const nsStyleVisibility *visibility = nsnull;
- GetStyleData(eStyleStruct_Visibility, (const nsStyleStruct*&)visibility,
- aFrame);
+ const nsStyleDisplay *display = nsnull;
+ GetStyleData(eStyleStruct_Display, (const nsStyleStruct*&)display, aFrame);
- if (visibility) {
- val->SetNumber(visibility->mOpacity);
+ if (display) {
+ val->SetNumber(display->mOpacity);
} else {
val->SetNumber(1.0f);
}
diff --git a/layout/style/nsHTMLCSSStyleSheet.cpp b/layout/style/nsHTMLCSSStyleSheet.cpp
index dc2ae81ee7b9..07b5d8a82c86 100644
--- a/layout/style/nsHTMLCSSStyleSheet.cpp
+++ b/layout/style/nsHTMLCSSStyleSheet.cpp
@@ -162,7 +162,6 @@ CSSDisablePropsRule::CommonMapRuleInfoInto(nsRuleData* aData)
nsCSSValue inherit(eCSSUnit_Inherit);
aData->mDisplayData->mVisibility = inherit;
aData->mDisplayData->mDirection = inherit;
- aData->mDisplayData->mOpacity = inherit;
}
if (aData->mSID == eStyleStruct_Display) {
@@ -175,6 +174,9 @@ CSSDisablePropsRule::CommonMapRuleInfoInto(nsRuleData* aData)
aData->mDisplayData->mClip.mBottom = autovalue;
aData->mDisplayData->mClip.mLeft = autovalue;
+ nsCSSValue one(1.0f, eCSSUnit_Number);
+ aData->mDisplayData->mOpacity = one;
+
nsCSSValue inlinevalue(NS_STYLE_DISPLAY_INLINE, eCSSUnit_Enumerated);
aData->mDisplayData->mDisplay = inlinevalue;
diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp
index fbf4dc045798..f4d109d4008c 100644
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -2509,6 +2509,15 @@ nsRuleNode::ComputeDisplayData(nsStyleStruct* aStartStruct,
parentDisplay = parentContext->GetStyleDisplay();
PRBool inherited = aInherited;
+ // opacity: factor, inherit
+ if (eCSSUnit_Number == displayData.mOpacity.GetUnit()) {
+ display->mOpacity = displayData.mOpacity.GetFloatValue();
+ }
+ else if (eCSSUnit_Inherit == displayData.mOpacity.GetUnit()) {
+ inherited = PR_TRUE;
+ display->mOpacity = parentDisplay->mOpacity;
+ }
+
// display: enum, none, inherit
if (eCSSUnit_Enumerated == displayData.mDisplay.GetUnit()) {
display->mDisplay = displayData.mDisplay.GetIntValue();
@@ -2769,15 +2778,6 @@ nsRuleNode::ComputeVisibilityData(nsStyleStruct* aStartStruct,
if (!parentVisibility)
parentVisibility = visibility;
- // opacity: factor, inherit
- if (eCSSUnit_Number == displayData.mOpacity.GetUnit()) {
- visibility->mOpacity = displayData.mOpacity.GetFloatValue();
- }
- else if (eCSSUnit_Inherit == displayData.mOpacity.GetUnit()) {
- inherited = PR_TRUE;
- visibility->mOpacity = parentVisibility->mOpacity;
- }
-
// direction: enum, inherit
if (eCSSUnit_Enumerated == displayData.mDirection.GetUnit()) {
visibility->mDirection = displayData.mDirection.GetIntValue();
diff --git a/layout/style/nsStyleContext.cpp b/layout/style/nsStyleContext.cpp
index 13728180b0fa..788f7f1a550f 100644
--- a/layout/style/nsStyleContext.cpp
+++ b/layout/style/nsStyleContext.cpp
@@ -711,9 +711,10 @@ void nsStyleContext::DumpRegressionData(nsIPresContext* aPresContext, FILE* out,
// DISPLAY
IndentBy(out,aIndent);
const nsStyleDisplay* disp = GetStyleDisplay();
- fprintf(out, "\n",
+ fprintf(out, "\n",
(int)disp->mPosition,
(int)disp->mDisplay,
+ (float)disp->mOpacity,
(int)disp->mFloats,
(int)disp->mBreakType,
(int)disp->mBreakBefore,
@@ -730,10 +731,9 @@ void nsStyleContext::DumpRegressionData(nsIPresContext* aPresContext, FILE* out,
// VISIBILITY
IndentBy(out,aIndent);
const nsStyleVisibility* vis = GetStyleVisibility();
- fprintf(out, "\n",
+ fprintf(out, "\n",
(int)vis->mDirection,
- (int)vis->mVisible,
- (float)vis->mOpacity
+ (int)vis->mVisible
);
// TABLE
diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp
index 670d0f4216f4..fe3ad4c309e7 100644
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1068,6 +1068,7 @@ nsStyleDisplay::nsStyleDisplay()
mOverflow = NS_STYLE_OVERFLOW_VISIBLE;
mClipFlags = NS_STYLE_CLIP_AUTO;
mClip.SetRect(0,0,0,0);
+ mOpacity = 1.0f;
}
nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
@@ -1084,6 +1085,7 @@ nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
mOverflow = aSource.mOverflow;
mClipFlags = aSource.mClipFlags;
mClip = aSource.mClip;
+ mOpacity = aSource.mOpacity;
}
nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
@@ -1094,7 +1096,10 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
|| mPosition != aOther.mPosition
|| mDisplay != aOther.mDisplay
|| mFloats != aOther.mFloats
- || mOverflow != aOther.mOverflow)
+ || mOverflow != aOther.mOverflow
+ // might need to create a view to handle change from 1.0 to partial opacity
+ || (mOpacity != aOther.mOpacity
+ && ((mOpacity < 1.0) != (aOther.mOpacity < 1.0))))
NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
// XXX the following is conservative, for now: changing float breaking shouldn't
@@ -1106,7 +1111,8 @@ nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_ReflowFrame, nsChangeHint_RepaintFrame));
if (mClipFlags != aOther.mClipFlags
- || mClip != aOther.mClip)
+ || mClip != aOther.mClip
+ || mOpacity != aOther.mOpacity)
NS_UpdateHint(hint, nsChangeHint_SyncFrameView);
return hint;
@@ -1127,7 +1133,6 @@ nsStyleVisibility::nsStyleVisibility(nsIPresContext* aPresContext)
aPresContext->GetLanguage(getter_AddRefs(mLanguage));
mVisible = NS_STYLE_VISIBILITY_VISIBLE;
- mOpacity = 1.0f;
}
nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
@@ -1135,23 +1140,14 @@ nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
mDirection = aSource.mDirection;
mVisible = aSource.mVisible;
mLanguage = aSource.mLanguage;
- mOpacity = aSource.mOpacity;
}
nsChangeHint nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) const
{
- if (mOpacity != aOther.mOpacity
- && ((mOpacity < 1.0) != (aOther.mOpacity < 1.0)))
- // might need to create a view to handle change from 1.0 to partial opacity
- return NS_STYLE_HINT_FRAMECHANGE;
-
if ((mDirection == aOther.mDirection) &&
(mLanguage == aOther.mLanguage)) {
if ((mVisible == aOther.mVisible)) {
- if (mOpacity == aOther.mOpacity)
- return NS_STYLE_HINT_NONE;
- else
- return NS_STYLE_HINT_VISUAL;
+ return NS_STYLE_HINT_NONE;
}
if ((mVisible != aOther.mVisible) &&
((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
diff --git a/layout/style/nsStyleStruct.h b/layout/style/nsStyleStruct.h
index 547960a1b259..78dfdee93502 100644
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -702,7 +702,6 @@ struct nsStyleVisibility : public nsStyleStruct {
PRUint8 mDirection; // [inherited] see nsStyleConsts.h NS_STYLE_DIRECTION_*
PRUint8 mVisible; // [inherited]
nsCOMPtr mLanguage; // [inherited]
- float mOpacity; // [inherited]
PRBool IsVisible() const {
return (mVisible == NS_STYLE_VISIBILITY_VISIBLE);
@@ -742,6 +741,7 @@ struct nsStyleDisplay : public nsStyleStruct {
#else
nsRect mClip; // [reset] offsets from upper-left border edge
#endif
+ float mOpacity; // [reset]
PRUint8 mDisplay; // [reset] see nsStyleConsts.h NS_STYLE_DISPLAY_*
PRUint8 mOriginalDisplay; // [reset] saved mDisplay for position:absolute/fixed
PRUint8 mAppearance; // [reset]
@@ -751,7 +751,6 @@ struct nsStyleDisplay : public nsStyleStruct {
PRPackedBool mBreakBefore; // [reset]
PRPackedBool mBreakAfter; // [reset]
PRUint8 mOverflow; // [reset] see nsStyleConsts.h
-
PRUint8 mClipFlags; // [reset] see nsStyleConsts.h
PRBool IsBlockLevel() const {return (NS_STYLE_DISPLAY_BLOCK == mDisplay) ||
diff --git a/layout/xul/base/src/nsBoxFrame.cpp b/layout/xul/base/src/nsBoxFrame.cpp
index aaed641581e5..b4a153b62098 100644
--- a/layout/xul/base/src/nsBoxFrame.cpp
+++ b/layout/xul/base/src/nsBoxFrame.cpp
@@ -2451,12 +2451,12 @@ nsBoxFrame::CreateViewForFrame(nsIPresContext* aPresContext,
PRBool isCanvas;
PRBool hasBG =
nsCSSRendering::FindBackground(aPresContext, aFrame, &bg, &isCanvas);
- const nsStyleVisibility* vis = aStyleContext->GetStyleVisibility();
+ const nsStyleDisplay* disp = aStyleContext->GetStyleDisplay();
- if (vis->mOpacity != 1.0f) {
+ if (disp->mOpacity != 1.0f) {
NS_FRAME_LOG(NS_FRAME_TRACE_CALLS,
("nsBoxFrame::CreateViewForFrame: frame=%p opacity=%g",
- aFrame, vis->mOpacity));
+ aFrame, disp->mOpacity));
aForce = PR_TRUE;
}
@@ -2517,6 +2517,7 @@ nsBoxFrame::CreateViewForFrame(nsIPresContext* aPresContext,
(!hasBG ||
(bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT));
+ const nsStyleVisibility* vis = aStyleContext->GetStyleVisibility();
if (NS_STYLE_VISIBILITY_COLLAPSE == vis->mVisible) {
viewIsVisible = PR_FALSE;
}
@@ -2556,7 +2557,7 @@ nsBoxFrame::CreateViewForFrame(nsIPresContext* aPresContext,
viewManager->SetViewVisibility(view, nsViewVisibility_kHide);
}
- viewManager->SetViewOpacity(view, vis->mOpacity);
+ viewManager->SetViewOpacity(view, disp->mOpacity);
}
// Remember our view
diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp
index 2c6cad038669..60730fc70def 100644
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -100,30 +100,33 @@ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
#define SUPPORT_TRANSLUCENT_VIEWS
/*
- This class encapsulates all the offscreen buffers we might want to
- render into. mOffscreen is the basic buffer for doing
- double-buffering. mBlack and mWhite are buffers for collecting an
- individual view drawn onto black and drawn onto white, from which we
- can recover the alpha values of the view's pixels. mOffscreenWhite
- is only for when the widget being rendered is transparent; it's an
- alternative double-buffer buffer that starts off white instead of
- black, and allows us to recover alpha values for the widget.
+ This class represents an offscreen buffer which may have an alpha channel.
+ Currently, if an alpha channel is required, we implement it by rendering into
+ two buffers: one with a black background, one with a white background. We can
+ recover the alpha values by comparing corresponding final values for each pixel.
*/
class BlendingBuffers {
public:
BlendingBuffers(nsIRenderingContext* aCleanupContext);
~BlendingBuffers();
+ // used by the destructor to cleanup resources
nsCOMPtr mCleanupContext;
- nsCOMPtr mOffScreenCX;
- nsCOMPtr mOffScreenWhiteCX;
+ // The primary rendering context. When an alpha channel is in use, this
+ // holds the black background.
nsCOMPtr mBlackCX;
+ // Only used when an alpha channel is required; holds the white background.
nsCOMPtr mWhiteCX;
- nsDrawingSurface mOffScreen;
- nsDrawingSurface mOffScreenWhite;
+ PRBool mOwnBlackSurface;
+ // drawing surface for mBlackCX
nsDrawingSurface mBlack;
+ // drawing surface for mWhiteCX
nsDrawingSurface mWhite;
+
+ // The offset within the current widget at which this buffer will
+ // eventually be composited
+ nsPoint mOffset;
};
// A DisplayListElement2 records the information needed to paint one view.
@@ -216,6 +219,97 @@ void nsViewManager::DestroyZTreeNode(DisplayZTreeNode* aNode)
}
}
+#ifdef DEBUG
+static PRInt32 PrintDisplayListElement(DisplayListElement2* element,
+ PRInt32 aNestCount) {
+ nsView* view = element->mView;
+ nsRect rect = element->mBounds;
+ PRUint32 flags = element->mFlags;
+ PRUint32 viewFlags = view ? view->GetViewFlags() : 0;
+ nsRect dim;
+ if (view) {
+ view->GetDimensions(dim);
+ }
+ nsPoint v = view ? view->GetPosition() : nsPoint(0, 0);
+ nsView* parent = view ? view->GetParent() : nsnull;
+ PRInt32 zindex = view ? view->GetZIndex() : 0;
+ nsView* zParent = view ? view->GetZParent() : nsnull;
+ nsViewManager* viewMan = view ? view->GetViewManager() : nsnull;
+
+ printf("%*snsIView@%p{%d,%d,%d,%d @ %d,%d; p=%p,m=%p z=%d,zp=%p} [x=%d, y=%d, w=%d, h=%d, absX=%d, absY=%d]\n",
+ aNestCount*2, "", (void*)view,
+ dim.x, dim.y, dim.width, dim.height,
+ v.x, v.y,
+ (void*)parent, (void*)viewMan, zindex, (void*)zParent,
+ rect.x, rect.y, rect.width, rect.height,
+ element->mAbsX, element->mAbsY);
+
+ PRInt32 newnestcnt = aNestCount;
+
+ if (flags)
+ {
+ printf("%*s", aNestCount*2, "");
+
+ if (flags & POP_CLIP) {
+ printf("POP_CLIP ");
+ newnestcnt--;
+ }
+
+ if (flags & PUSH_CLIP) {
+ printf("PUSH_CLIP ");
+ newnestcnt++;
+ }
+
+ if (flags & POP_FILTER) {
+ printf("POP_FILTER ");
+ newnestcnt--;
+ }
+
+ if (flags & PUSH_FILTER) {
+ printf("PUSH_FILTER ");
+ newnestcnt++;
+ }
+
+ if (flags & VIEW_RENDERED)
+ printf("VIEW_RENDERED ");
+
+ if (flags & VIEW_ISSCROLLED)
+ printf("VIEW_ISSCROLLED ");
+
+ if (flags & VIEW_CLIPPED)
+ printf("VIEW_ISCLIPPED ");
+
+ if (flags & VIEW_TRANSLUCENT)
+ printf("VIEW_ISTRANSLUCENT ");
+
+ if (flags & VIEW_TRANSPARENT)
+ printf("VIEW_ISTRANSPARENT ");
+
+ if (viewFlags & NS_VIEW_FLAG_DONT_BITBLT)
+ printf("NS_VIEW_FLAG_DONT_BITBLT ");
+
+ printf("\n");
+ }
+ return newnestcnt;
+}
+
+static void PrintZTreeNode(DisplayZTreeNode* aNode, PRInt32 aIndent)
+{
+ if (aNode) {
+ printf("%*sDisplayZTreeNode@%p\n", aIndent*2, "", (void*)aNode);
+ if (aNode->mDisplayElement) {
+ PrintDisplayListElement(aNode->mDisplayElement, 0);
+ }
+
+ aIndent += 2;
+
+ for (DisplayZTreeNode* child = aNode->mZChild; child;
+ child = child->mZSibling) {
+ PrintZTreeNode(child, aIndent);
+ }
+ }
+}
+#endif
#ifdef NS_VM_PERF_METRICS
#include "nsITimeRecorder.h"
@@ -800,7 +894,7 @@ void nsViewManager::Refresh(nsView *aView, nsIRenderingContext *aContext,
localcx->SetClipRect(damageRect, nsClipCombine_kIntersect, isClipped);
// painting will be done in aView's coordinates
- RenderViews(aView, *localcx, damageRegion, usingDoubleBuffer);
+ RenderViews(aView, *localcx, damageRegion, ds);
if (usingDoubleBuffer) {
// Flush bits back to the screen
@@ -978,19 +1072,42 @@ static void SortByZOrder(DisplayZTreeNode *aNode, nsVoidArray &aBuffer, nsVoidAr
SortByZOrder(child, aBuffer, aMergeTmp, PR_FALSE);
}
PRInt32 childEndIndex = aBuffer.Count();
+ PRInt32 sortStartIndex = childStartIndex;
+ PRInt32 sortEndIndex = childEndIndex;
PRBool hasClip = PR_FALSE;
-
- if (childEndIndex - childStartIndex >= 2) {
- DisplayListElement2* firstChild = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(childStartIndex));
- if (0 != (firstChild->mFlags & PUSH_CLIP) && firstChild->mView == aNode->mView) {
- hasClip = PR_TRUE;
+ DisplayListElement2* ePush = nsnull;
+ DisplayListElement2* ePop = nsnull;
+
+ // When we sort the children by z-index, don't sort any PUSH_ or POP_ instructions
+ // which are bracketing the children.
+ while (sortEndIndex - sortStartIndex >= 2) {
+ DisplayListElement2* childElem =
+ NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(sortStartIndex));
+ if (childElem->mView == aNode->mView) {
+ if (childElem->mFlags & PUSH_CLIP) {
+ hasClip = PR_TRUE;
+ // remember where the push and pop instructions are so we can
+ // duplicate them later, if necessary
+ ePush = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(sortStartIndex));
+ ePop = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(sortEndIndex - 1));
+ sortStartIndex++;
+ sortEndIndex--;
+ } else if (childElem->mFlags & PUSH_FILTER) {
+ NS_ASSERTION(!autoZIndex, "FILTER cannot apply to z-index:auto view");
+ sortStartIndex++;
+ sortEndIndex--;
+ } else {
+ break;
+ }
+ } else {
+ break;
}
}
if (hasClip) {
- ApplyZOrderStableSort(aBuffer, aMergeTmp, childStartIndex + 1, childEndIndex - 1);
+ ApplyZOrderStableSort(aBuffer, aMergeTmp, sortStartIndex, sortEndIndex);
- if (autoZIndex && childEndIndex - childStartIndex >= 3) {
+ if (autoZIndex && sortEndIndex - sortStartIndex >= 1) {
// If we're an auto-z-index, then we have to worry about the possibility that some of
// our children may be moved by the z-sorter beyond the bounds of the PUSH...POP clip
// instructions. So basically, we ensure that around every group of children of
@@ -999,18 +1116,19 @@ static void SortByZOrder(DisplayZTreeNode *aNode, nsVoidArray &aBuffer, nsVoidAr
// Note that if we're not an auto-z-index set, then our children will never be broken
// up so we don't need to do this.
// We also don't have to worry if we have no real children.
- DisplayListElement2* ePush = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(childStartIndex));
- DisplayListElement2* eFirstChild = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(childStartIndex + 1));
+ // We don't have to do the same thing for PUSH_FILTER/POP_FILTER because
+ // a filter always corresponds to non-auto z-index; there is no way children
+ // can be sorted beyond the PUSH/POP instructions.
+ DisplayListElement2* eFirstChild = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(sortStartIndex));
ePush->mZIndex = eFirstChild->mZIndex;
- DisplayListElement2* ePop = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(childEndIndex - 1));
- DisplayListElement2* eLastChild = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(childEndIndex - 2));
+ DisplayListElement2* eLastChild = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(sortEndIndex - 1));
ePop->mZIndex = eLastChild->mZIndex;
DisplayListElement2* e = eFirstChild;
- for (PRInt32 i = childStartIndex + 1; i < childEndIndex - 2; i++) {
+ for (PRInt32 i = sortStartIndex; i < sortEndIndex - 1; i++) {
DisplayListElement2* eNext = NS_STATIC_CAST(DisplayListElement2*, aBuffer.ElementAt(i + 1));
NS_ASSERTION(e->mZIndex <= eNext->mZIndex, "Display Z-list is not sorted!!");
if (e->mZIndex != eNext->mZIndex) {
@@ -1026,12 +1144,13 @@ static void SortByZOrder(DisplayZTreeNode *aNode, nsVoidArray &aBuffer, nsVoidAr
aBuffer.InsertElementAt(newPush, i + 2);
i += 2;
childEndIndex += 2;
+ sortEndIndex += 2;
}
e = eNext;
}
}
} else if (aForceSort || !autoZIndex) {
- ApplyZOrderStableSort(aBuffer, aMergeTmp, childStartIndex, childEndIndex);
+ ApplyZOrderStableSort(aBuffer, aMergeTmp, sortStartIndex, sortEndIndex);
}
for (PRInt32 i = childStartIndex; i < childEndIndex; i++) {
@@ -1045,22 +1164,22 @@ static void SortByZOrder(DisplayZTreeNode *aNode, nsVoidArray &aBuffer, nsVoidAr
}
}
-static void PushStateAndClip(nsIRenderingContext **aRCs, PRInt32 aRCCount, nsRect &aRect,
- PRInt32 aDX, PRInt32 aDY) {
- PRBool clipEmpty;
- nsRect rect = aRect;
- rect.x -= aDX;
- rect.y -= aDY;
- for (PRInt32 i = 0; i < aRCCount; i++) {
- aRCs[i]->PushState();
- aRCs[i]->SetClipRect(i == 0 ? aRect : rect, nsClipCombine_kIntersect, clipEmpty);
+static void PushStateAndClip(nsIRenderingContext** aRCs, PRInt32 aCount, nsRect &aRect) {
+ for (int i = 0; i < aCount; i++) {
+ if (aRCs[i]) {
+ PRBool clipEmpty;
+ aRCs[i]->PushState();
+ aRCs[i]->SetClipRect(aRect, nsClipCombine_kIntersect, clipEmpty);
+ }
}
}
-static void PopState(nsIRenderingContext **aRCs, PRInt32 aRCCount) {
- PRBool clipEmpty;
- for (PRInt32 i = 0; i < aRCCount; i++) {
- aRCs[i]->PopState(clipEmpty);
+static void PopState(nsIRenderingContext **aRCs, PRInt32 aCount) {
+ for (int i = 0; i < aCount; i++) {
+ if (aRCs[i]) {
+ PRBool clipEmpty;
+ aRCs[i]->PopState(clipEmpty);
+ }
}
}
@@ -1124,8 +1243,13 @@ void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceCo
} while (NS_SUCCEEDED(children->Next()));
}
+/*
+ aRCSurface is the drawing surface being used to double-buffer aRC, or null
+ if no double-buffering is happening. We pass this in here so that we can
+ blend directly into the double-buffer offscreen memory.
+*/
void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC,
- const nsRegion& aRegion, PRBool aRCIsOffscreen)
+ const nsRegion& aRegion, nsDrawingSurface aRCSurface)
{
nsAutoVoidArray displayList;
@@ -1138,7 +1262,7 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC,
OptimizeDisplayList(&displayList, aRegion, finalTransparentRect, opaqueRgn, PR_FALSE);
#ifdef DEBUG_roc
- // ShowDisplayList(&displayList);
+ ShowDisplayList(&displayList);
#endif
if (!finalTransparentRect.IsEmpty()) {
@@ -1157,248 +1281,139 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC,
PRBool anyRendered;
OptimizeDisplayListClipping(&displayList, PR_FALSE, fakeClipRect, index, anyRendered);
- PRInt32 translucentViewCount = 0;
- nsRect translucentArea(0, 0, 0, 0);
- PRInt32 i;
- // count number of translucent views, and
- // accumulate a rectangle of all translucent
- // views. this will be used to determine which
- // views need to be rendered into the blending
- // buffers.
- for (i = displayList.Count() - 1; i >= 0; --i) {
- DisplayListElement2* element =
- NS_STATIC_CAST(DisplayListElement2*, displayList.ElementAt(i));
- if ((element->mFlags & VIEW_TRANSLUCENT) && (element->mFlags & VIEW_RENDERED)) {
- translucentViewCount++;
- translucentArea.UnionRect(translucentArea, element->mBounds);
- }
- }
+ index = 0;
+ OptimizeTranslucentRegions(displayList, &index, nsnull);
- // We keep a list of all the rendering contexts whose clip rects
- // need to be updated.
- nsIRenderingContext* RCList[5];
- PRInt32 RCCount = 1;
- RCList[0] = &aRC;
-
nsIWidget* widget = aRootView->GetWidget();
PRBool translucentWindow = PR_FALSE;
if (widget) {
widget->GetWindowTranslucency(translucentWindow);
if (translucentWindow) {
NS_WARNING("Transparent window enabled");
- // for a translucent window, we'll pretend the whole area is
- // translucent.
- translucentArea = aRegion.GetBounds();
+ NS_ASSERTION(aRCSurface, "Cannot support transparent windows with doublebuffering disabled");
}
}
- BlendingBuffers* buffers = nsnull;
+ // Create a buffer wrapping aRC (which is usually the double-buffering offscreen buffer).
+ BlendingBuffers* buffers =
+ CreateBlendingBuffers(&aRC, PR_TRUE, aRCSurface, translucentWindow, aRegion.GetBounds());
+ NS_ASSERTION(buffers, "Failed to create rendering buffers");
+ if (!buffers)
+ return;
- // create blending buffers, if necessary.
- if (translucentViewCount > 0 || translucentWindow) {
- buffers = CreateBlendingBuffers(&aRC, translucentWindow,
- translucentViewCount > 0, translucentArea);
- NS_ASSERTION(buffers, "not enough memory to blend");
- if (!buffers) {
- // fall back by just rendering with transparency.
- translucentViewCount = 0;
- for (i = displayList.Count() - 1; i >= 0; --i) {
- DisplayListElement2* element =
- NS_STATIC_CAST(DisplayListElement2*, displayList.ElementAt(i));
- element->mFlags &= ~VIEW_TRANSLUCENT;
- }
- } else {
- RCList[RCCount++] = buffers->mOffScreenCX;
- if (translucentWindow) {
- RCList[RCCount++] = buffers->mOffScreenWhiteCX;
- }
- if (translucentViewCount > 0) {
- RCList[RCCount++] = buffers->mBlackCX;
- RCList[RCCount++] = buffers->mWhiteCX;
- }
-
- if (!translucentWindow && !finalTransparentRect.IsEmpty()) {
- // There are some bits that aren't going to be completely painted, so
- // make sure we don't leave garbage in the offscreen context
- buffers->mOffScreenCX->SetColor(NS_RGB(128, 128, 128));
- buffers->mOffScreenCX->FillRect(nsRect(0, 0, translucentArea.width, translucentArea.height));
- }
- }
-
- // DEBUGGING: fill in complete offscreen image in green, to see if we've got a blending bug.
- // mOffScreenCX->SetColor(NS_RGB(0, 255, 0));
- // mOffScreenCX->FillRect(nsRect(0, 0, gOffScreenSize.width, gOffScreenSize.height));
- }
+ nsAutoVoidArray filterStack;
// draw all views in the display list, from back to front.
- for (i = 0; i < displayList.Count(); i++) {
+ for (PRInt32 i = 0; i < displayList.Count(); i++) {
DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, displayList.ElementAt(i));
+ nsIRenderingContext* RCs[2] = { buffers->mBlackCX, buffers->mWhiteCX };
+
if (element->mFlags & PUSH_CLIP) {
- PushStateAndClip(RCList, RCCount, element->mBounds, translucentArea.x, translucentArea.y);
+ PushStateAndClip(RCs, 2, element->mBounds);
}
if (element->mFlags & PUSH_FILTER) {
- // nothing here yet
+ NS_ASSERTION(aRCSurface,
+ "Cannot support translucent elements with doublebuffering disabled");
+
+ // Save current buffer on the stack and start rendering into a new
+ // offscreen buffer
+ filterStack.AppendElement(buffers);
+ buffers = CreateBlendingBuffers(&aRC, PR_FALSE, nsnull,
+ (element->mFlags & VIEW_TRANSPARENT) != 0,
+ element->mBounds);
}
if (element->mFlags & VIEW_RENDERED) {
- // typical case, just rendering a view.
if (element->mFlags & VIEW_CLIPPED) {
- //Render the view using the clip rect set by it's ancestors
- PushStateAndClip(RCList, RCCount, element->mBounds, translucentArea.x, translucentArea.y);
- RenderDisplayListElement(element, aRC, buffers, translucentArea);
- PopState(RCList, RCCount);
- } else {
- RenderDisplayListElement(element, aRC, buffers, translucentArea);
+ PushStateAndClip(RCs, 2, element->mBounds);
+ }
+
+ RenderDisplayListElement(element, RCs[0]);
+ // RenderDisplayListElement won't do anything if the context is null
+ RenderDisplayListElement(element, RCs[1]);
+
+ if (element->mFlags & VIEW_CLIPPED) {
+ PopState(RCs, 2);
}
}
if (element->mFlags & POP_FILTER) {
- // nothing here yet
+ // Pop the last buffer off the stack and composite the current buffer into
+ // the last buffer
+ BlendingBuffers* doneBuffers = buffers;
+ buffers = NS_STATIC_CAST(BlendingBuffers*,
+ filterStack.ElementAt(filterStack.Count() - 1));
+ filterStack.RemoveElementAt(filterStack.Count() - 1);
+
+ // perform the blend itself.
+ nsRect damageRectInPixels = element->mBounds;
+ damageRectInPixels -= buffers->mOffset;
+ damageRectInPixels *= mTwipsToPixels;
+ if (damageRectInPixels.width > 0 && damageRectInPixels.height > 0) {
+ nsIRenderingContext* targets[2] = { buffers->mBlackCX, buffers->mWhiteCX };
+ for (int j = 0; j < 2; j++) {
+ if (targets[j]) {
+ mBlender->Blend(0, 0,
+ damageRectInPixels.width, damageRectInPixels.height,
+ doneBuffers->mBlackCX, targets[j],
+ damageRectInPixels.x, damageRectInPixels.y,
+ element->mView->GetOpacity(), doneBuffers->mWhiteCX,
+ NS_RGB(0, 0, 0), NS_RGB(255, 255, 255));
+ }
+ }
+ }
+ // probably should recycle these so we don't eat the cost of graphics memory
+ // allocation
+ delete doneBuffers;
}
if (element->mFlags & POP_CLIP) {
- PopState(RCList, RCCount);
+ PopState(RCs, 2);
}
delete element;
}
- // flush bits back to screen.
- // Must flush back when no clipping is in effect.
- if (buffers) {
- if (translucentWindow) {
- // Set window alphas
- nsRect r = translucentArea;
- r *= mTwipsToPixels;
- nsRect bufferRect(0, 0, r.width, r.height);
- PRUint8* alphas = nsnull;
- nsresult rv = mBlender->GetAlphas(bufferRect, buffers->mOffScreen,
- buffers->mOffScreenWhite, &alphas);
-
- if (NS_SUCCEEDED(rv)) {
- widget->UpdateTranslucentWindowAlpha(r, alphas);
- }
- delete[] alphas;
+ if (translucentWindow) {
+ // Get the alpha channel into an array so we can send it to the widget
+ nsRect r = aRegion.GetBounds();
+ r *= mTwipsToPixels;
+ nsRect bufferRect(0, 0, r.width, r.height);
+ PRUint8* alphas = nsnull;
+ nsresult rv = mBlender->GetAlphas(bufferRect, buffers->mBlack,
+ buffers->mWhite, &alphas);
+
+ if (NS_SUCCEEDED(rv)) {
+ widget->UpdateTranslucentWindowAlpha(r, alphas);
}
-
- // DEBUG: is this getting through?
- // mOffScreenCX->SetColor(NS_RGB(177, 177, 0));
- // mOffScreenCX->FillRect(nsRect(1, 1, translucentArea.width-2, translucentArea.height-2));
- aRC.CopyOffScreenBits(buffers->mOffScreen, 0, 0, translucentArea,
- NS_COPYBITS_XFORM_DEST_VALUES |
- NS_COPYBITS_TO_BACK_BUFFER);
- // DEBUG: what rectangle are we blitting?
- // aRC.SetColor(NS_RGB(0, 177, 177));
- // aRC.DrawRect(translucentArea);
-
- delete buffers;
+ delete[] alphas;
}
+
+ delete buffers;
}
void nsViewManager::RenderDisplayListElement(DisplayListElement2* element,
- nsIRenderingContext &aRC,
- BlendingBuffers* aBuffers,
- const nsRect& aTranslucentArea)
-{
+ nsIRenderingContext* aRC) {
+ if (!aRC)
+ return;
+
PRBool clipEmpty;
nsRect r;
nsView* view = element->mView;
view->GetDimensions(r);
- // if this element is contained by the translucent area, then
- // there's no point in drawing it here because it will be
- // overwritten by the final copy of the composited offscreen area
- if (!aBuffers || !aTranslucentArea.Contains(element->mBounds)) {
- aRC.PushState();
+ aRC->PushState();
- nscoord x = element->mAbsX - r.x, y = element->mAbsY - r.y;
- aRC.Translate(x, y);
+ nscoord x = element->mAbsX - r.x, y = element->mAbsY - r.y;
+ aRC->Translate(x, y);
- nsRect drect(element->mBounds.x - x, element->mBounds.y - y,
- element->mBounds.width, element->mBounds.height);
-
- element->mView->Paint(aRC, drect, 0, clipEmpty);
-
- aRC.PopState(clipEmpty);
- }
-
-#if defined(SUPPORT_TRANSLUCENT_VIEWS)
- if (aBuffers && aTranslucentArea.Intersects(element->mBounds)) {
- // compute the origin of the view, relative to the offscreen buffer, which has the
- // same dimensions as aTranslucentArea.
- nscoord x = element->mAbsX - r.x, y = element->mAbsY - r.y;
- nscoord viewX = x - aTranslucentArea.x, viewY = y - aTranslucentArea.y;
-
- nsRect damageRect(element->mBounds);
- damageRect.IntersectRect(damageRect, aTranslucentArea);
- // -> coordinates relative to element->mView origin
- damageRect.x -= x, damageRect.y -= y;
-
- // the element must be rendered into mOffscreenCX and also
- // mOffScreenWhiteCX if the window is transparent/translucent.
- nsIRenderingContext* targets[2] =
- { aBuffers->mOffScreenCX, aBuffers->mOffScreenWhiteCX };
-
- if (element->mFlags & VIEW_TRANSLUCENT) {
- // paint the view twice, first in the black buffer, then the white;
- // the blender will pick up the touched pixels only.
- PaintView(view, *aBuffers->mBlackCX, viewX, viewY, damageRect);
- // DEBUGGING ONLY
- //aRC.CopyOffScreenBits(gBlack, 0, 0, element->mBounds,
- // NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER);
-
- PaintView(view, *aBuffers->mWhiteCX, viewX, viewY, damageRect);
- // DEBUGGING ONLY
- //aRC.CopyOffScreenBits(gWhite, 0, 0, element->mBounds,
- // NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER);
- //mOffScreenCX->CopyOffScreenBits(gWhite, 0, 0, nsRect(viewX, viewY, damageRect.width, damageRect.height),
- // NS_COPYBITS_XFORM_DEST_VALUES | NS_COPYBITS_TO_BACK_BUFFER);
-
- // -> coordinates relative to aTranslucentArea origin
- damageRect.x += viewX, damageRect.y += viewY;
-
- // perform the blend itself.
- nsRect damageRectInPixels = damageRect;
- damageRectInPixels *= mTwipsToPixels;
- if (damageRectInPixels.width > 0 && damageRectInPixels.height > 0) {
- PRIntn i;
- for (i = 0; i < 2; i++) {
- if (targets[i]) {
- nsresult rv = mBlender->Blend(damageRectInPixels.x, damageRectInPixels.y,
- damageRectInPixels.width, damageRectInPixels.height,
- aBuffers->mBlackCX, targets[i],
- damageRectInPixels.x, damageRectInPixels.y,
- view->GetOpacity(), aBuffers->mWhiteCX,
- NS_RGB(0, 0, 0), NS_RGB(255, 255, 255));
- if (NS_FAILED(rv)) {
- NS_WARNING("Blend failed!");
- // let's paint SOMETHING. Paint opaquely
- damageRect.MoveBy(-viewX, -viewY);
- PaintView(view, *targets[i], viewX, viewY, damageRect);
- }
- }
- }
- }
-
- // Set the contexts back to their default colors
- // We do that here because we know that whatever the clip region is,
- // everything we just painted is within the clip region so we are
- // sure to be able to overwrite it now.
- aBuffers->mBlackCX->SetColor(NS_RGB(0, 0, 0));
- aBuffers->mBlackCX->FillRect(damageRect);
- aBuffers->mWhiteCX->SetColor(NS_RGB(255, 255, 255));
- aBuffers->mWhiteCX->FillRect(damageRect);
- } else {
- PRIntn i;
- for (i = 0; i < 2; i++) {
- if (targets[i]) {
- PaintView(view, *targets[i], viewX, viewY, damageRect);
- }
- }
- }
- }
-#endif
+ nsRect drect(element->mBounds.x - x, element->mBounds.y - y,
+ element->mBounds.width, element->mBounds.height);
+
+ element->mView->Paint(*aRC, drect, 0, clipEmpty);
+
+ aRC->PopState(clipEmpty);
}
void nsViewManager::PaintView(nsView *aView, nsIRenderingContext &aRC, nscoord x, nscoord y,
@@ -1412,7 +1427,7 @@ void nsViewManager::PaintView(nsView *aView, nsIRenderingContext &aRC, nscoord x
}
static nsresult NewOffscreenContext(nsIDeviceContext* deviceContext, nsDrawingSurface surface,
- const nsSize& size, nsIRenderingContext* *aResult)
+ const nsRect& aRect, nsIRenderingContext* *aResult)
{
nsresult rv;
nsIRenderingContext *context = nsnull;
@@ -1423,8 +1438,10 @@ static nsresult NewOffscreenContext(nsIDeviceContext* deviceContext, nsDrawingSu
// always initialize clipping, linux won't draw images otherwise.
PRBool clipEmpty;
- nsRect clip(0, 0, size.width, size.height);
+ nsRect clip(0, 0, aRect.width, aRect.height);
context->SetClipRect(clip, nsClipCombine_kReplace, clipEmpty);
+
+ context->Translate(-aRect.x, -aRect.y);
*aResult = context;
return NS_OK;
@@ -1433,30 +1450,36 @@ static nsresult NewOffscreenContext(nsIDeviceContext* deviceContext, nsDrawingSu
BlendingBuffers::BlendingBuffers(nsIRenderingContext* aCleanupContext) {
mCleanupContext = aCleanupContext;
- mOffScreen = nsnull;
- mOffScreenWhite = nsnull;
+ mOwnBlackSurface = PR_FALSE;
mWhite = nsnull;
mBlack = nsnull;
}
BlendingBuffers::~BlendingBuffers() {
- if (mOffScreen)
- mCleanupContext->DestroyDrawingSurface(mOffScreen);
-
- if (mOffScreenWhite)
- mCleanupContext->DestroyDrawingSurface(mOffScreenWhite);
-
if (mWhite)
mCleanupContext->DestroyDrawingSurface(mWhite);
- if (mBlack)
+ if (mBlack && mOwnBlackSurface)
mCleanupContext->DestroyDrawingSurface(mBlack);
}
-BlendingBuffers* nsViewManager::CreateBlendingBuffers(nsIRenderingContext *aRC,
- PRBool aTranslucentWindow,
- PRBool aTranslucentViews,
- const nsRect& aTranslucentArea)
+/*
+@param aBorrowContext set to PR_TRUE if the BlendingBuffers' "black" context
+ should be just aRC; set to PR_FALSE if we should create a new offscreen context
+@param aBorrowSurface if aBorrowContext is PR_TRUE, then this is the offscreen surface
+ corresponding to aRC, or nsnull if aRC doesn't have one; if aBorrowContext is PR_FALSE,
+ this parameter is ignored
+@param aNeedAlpha set to PR_FALSE if the caller guarantees that every pixel of the
+ BlendingBuffers will be drawn with opacity 1.0, PR_TRUE otherwise
+@param aRect the screen rectangle covered by the new BlendingBuffers, in app units, and
+ relative to the origin of aRC
+*/
+BlendingBuffers*
+nsViewManager::CreateBlendingBuffers(nsIRenderingContext *aRC,
+ PRBool aBorrowContext,
+ nsDrawingSurface aBorrowSurface,
+ PRBool aNeedAlpha,
+ const nsRect& aRect)
{
nsresult rv;
@@ -1474,74 +1497,48 @@ BlendingBuffers* nsViewManager::CreateBlendingBuffers(nsIRenderingContext *aRC,
if (!buffers)
return nsnull;
- nsRect offscreenBounds(0, 0, aTranslucentArea.width, aTranslucentArea.height);
+ buffers->mOffset = nsPoint(aRect.x, aRect.y);
+
+ nsRect offscreenBounds(0, 0, aRect.width, aRect.height);
offscreenBounds.ScaleRoundOut(mTwipsToPixels);
- nsSize offscreenSize(aTranslucentArea.width, aTranslucentArea.height);
- rv = aRC->CreateDrawingSurface(offscreenBounds, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, buffers->mOffScreen);
- if (NS_FAILED(rv)) {
- delete buffers;
- return nsnull;
- }
-
- rv = NewOffscreenContext(mContext, buffers->mOffScreen, offscreenSize, getter_AddRefs(buffers->mOffScreenCX));
- if (NS_FAILED(rv)) {
- delete buffers;
- return nsnull;
- }
-
- if (aTranslucentViews) {
+ if (aBorrowContext) {
+ buffers->mBlackCX = aRC;
+ buffers->mBlack = aBorrowSurface;
+ } else {
rv = aRC->CreateDrawingSurface(offscreenBounds, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, buffers->mBlack);
if (NS_FAILED(rv)) {
delete buffers;
return nsnull;
}
+ buffers->mOwnBlackSurface = PR_TRUE;
+
+ rv = NewOffscreenContext(mContext, buffers->mBlack, aRect, getter_AddRefs(buffers->mBlackCX));
+ if (NS_FAILED(rv)) {
+ delete buffers;
+ return nsnull;
+ }
+ }
+ if (aNeedAlpha) {
rv = aRC->CreateDrawingSurface(offscreenBounds, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, buffers->mWhite);
if (NS_FAILED(rv)) {
delete buffers;
return nsnull;
}
- rv = NewOffscreenContext(mContext, buffers->mBlack, offscreenSize, getter_AddRefs(buffers->mBlackCX));
+ rv = NewOffscreenContext(mContext, buffers->mWhite, aRect, getter_AddRefs(buffers->mWhiteCX));
if (NS_FAILED(rv)) {
delete buffers;
return nsnull;
}
-
- rv = NewOffscreenContext(mContext, buffers->mWhite, offscreenSize, getter_AddRefs(buffers->mWhiteCX));
- if (NS_FAILED(rv)) {
- delete buffers;
- return nsnull;
- }
-
- nsRect fillArea(0, 0, aTranslucentArea.width, aTranslucentArea.height);
+ // Note that we only need to fill mBlackCX with black when some pixels are going
+ // to be transparent.
buffers->mBlackCX->SetColor(NS_RGB(0, 0, 0));
- buffers->mBlackCX->FillRect(fillArea);
+ buffers->mBlackCX->FillRect(aRect);
buffers->mWhiteCX->SetColor(NS_RGB(255, 255, 255));
- buffers->mWhiteCX->FillRect(fillArea);
- }
-
- if (aTranslucentWindow) {
- rv = aRC->CreateDrawingSurface(offscreenBounds, NS_CREATEDRAWINGSURFACE_FOR_PIXEL_ACCESS, buffers->mOffScreenWhite);
- if (NS_FAILED(rv)) {
- delete buffers;
- return nsnull;
- }
-
- rv = NewOffscreenContext(mContext, buffers->mOffScreenWhite, offscreenSize, getter_AddRefs(buffers->mOffScreenWhiteCX));
- if (NS_FAILED(rv)) {
- delete buffers;
- return nsnull;
- }
-
- nsRect fillArea(0, 0, aTranslucentArea.width, aTranslucentArea.height);
-
- buffers->mOffScreenCX->SetColor(NS_RGB(0, 0, 0));
- buffers->mOffScreenCX->FillRect(fillArea);
- buffers->mOffScreenWhiteCX->SetColor(NS_RGB(255, 255, 255));
- buffers->mOffScreenWhiteCX->FillRect(fillArea);
+ buffers->mWhiteCX->FillRect(aRect);
}
return buffers;
@@ -3468,6 +3465,23 @@ PRBool nsViewManager::CreateDisplayList(nsView *aView, PRBool aReparentedViewsPr
anyChildren = PR_FALSE;
}
+ PRBool hasFilter = aView->GetOpacity() != 1.0f;
+ if (hasFilter) {
+ // -> to refresh-frame coordinates (relative to aRealView)
+ bounds.x -= aOriginX;
+ bounds.y -= aOriginY;
+
+ // Add POP first because the z-tree is in reverse order
+ retval = AddToDisplayList(aView, aResult, bounds, bounds,
+ POP_FILTER, aX - aOriginX, aY - aOriginY, PR_FALSE);
+ if (retval)
+ return retval;
+
+ // -> to global coordinates (relative to aTopView)
+ bounds.x += aOriginX;
+ bounds.y += aOriginY;
+ }
+
if (anyChildren) {
if (isClipView) {
// -> to refresh-frame coordinates (relative to aRealView)
@@ -3513,19 +3527,12 @@ PRBool nsViewManager::CreateDisplayList(nsView *aView, PRBool aReparentedViewsPr
bounds.x -= aOriginX;
bounds.y -= aOriginY;
- float opacity = aView->GetOpacity();
- PRBool transparent;
-
- aView->HasTransparency(transparent);
-
- if (aEventProcessing || opacity > 0.0f) {
+ if (aEventProcessing || aView->GetOpacity() > 0.0f) {
+ PRBool transparent;
+ aView->HasTransparency(transparent);
PRUint32 flags = VIEW_RENDERED;
if (transparent)
flags |= VIEW_TRANSPARENT;
-#if defined(SUPPORT_TRANSLUCENT_VIEWS)
- if (opacity < 1.0f)
- flags |= VIEW_TRANSLUCENT;
-#endif
retval = AddToDisplayList(aView, aResult, bounds, irect, flags,
aX - aOriginX, aY - aOriginY,
aEventProcessing && aRealView == aView);
@@ -3552,6 +3559,25 @@ PRBool nsViewManager::CreateDisplayList(nsView *aView, PRBool aReparentedViewsPr
aX - aOriginX, aY - aOriginY, PR_FALSE)) {
retval = PR_TRUE;
}
+
+ // -> to global coordinates (relative to aTopView)
+ bounds.x += aOriginX;
+ bounds.y += aOriginY;
+ }
+
+ if (hasFilter) {
+ // -> to refresh-frame coordinates (relative to aRealView)
+ bounds.x -= aOriginX;
+ bounds.y -= aOriginY;
+
+ retval = AddToDisplayList(aView, aResult, bounds, bounds,
+ PUSH_FILTER, aX - aOriginX, aY - aOriginY, PR_FALSE);
+ if (retval)
+ return retval;
+
+ // -> to global coordinates (relative to aTopView)
+ bounds.x += aOriginX;
+ bounds.y += aOriginY;
}
return retval;
@@ -3624,7 +3650,26 @@ void nsViewManager::OptimizeDisplayList(nsAutoVoidArray* aDisplayList, const nsR
nsRect& aFinalTransparentRect,
nsRegion &aOpaqueRegion, PRBool aTreatUniformAsOpaque)
{
- for (PRInt32 i = aDisplayList->Count() - 1; i >= 0; i--) {
+ // Mark all views inside a PUSH_FILTER/POP_FILTER as being translucent.
+ // If we don't do this, we'll incorrectly optimize by thinking views are
+ // opaque when they really aren't.
+ PRInt32 i;
+ PRInt32 filterDepth = 0;
+ for (i = 0; i < aDisplayList->Count(); ++i) {
+ DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*,
+ aDisplayList->ElementAt(i));
+ if (element->mFlags & PUSH_FILTER) {
+ ++filterDepth;
+ }
+ if (filterDepth > 0 && (element->mFlags & VIEW_RENDERED)) {
+ element->mFlags |= VIEW_TRANSLUCENT;
+ }
+ if (element->mFlags & POP_FILTER) {
+ --filterDepth;
+ }
+ }
+
+ for (i = aDisplayList->Count() - 1; i >= 0; --i) {
DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, aDisplayList->ElementAt(i));
if (element->mFlags & VIEW_RENDERED) {
nsRegion tmpRgn;
@@ -3706,90 +3751,76 @@ void nsViewManager::OptimizeDisplayListClipping(nsAutoVoidArray* aDisplayList,
}
}
+// Compute the bounds what's rendered between each PUSH_FILTER/POP_FILTER. Also
+// compute the region of what's rendered that's actually opaque. Then we can
+// decide for each PUSH_FILTER/POP_FILTER pair whether the contents are partially
+// transparent or fully opaque. Detecting the fully opaque case is important
+// because it's much faster to composite a fully opaque element (i.e., all alphas
+// 255).
+nsRect nsViewManager::OptimizeTranslucentRegions(
+ const nsAutoVoidArray& aDisplayList, PRInt32* aIndex, nsRegion* aOpaqueRegion)
+{
+ nsRect r;
+ while (*aIndex < aDisplayList.Count()) {
+ DisplayListElement2* element =
+ NS_STATIC_CAST(DisplayListElement2*, aDisplayList.ElementAt(*aIndex));
+ (*aIndex)++;
+
+ if (element->mFlags & VIEW_RENDERED) {
+ r.UnionRect(r, element->mBounds);
+ // the bounds of a non-transparent element are added to the opaque
+ // region
+ PRBool transparent;
+ element->mView->HasTransparency(transparent);
+ if (!transparent && aOpaqueRegion) {
+ aOpaqueRegion->Or(*aOpaqueRegion, element->mBounds);
+ }
+ }
+
+ if (element->mFlags & PUSH_FILTER) {
+ // the region inside the PUSH/POP pair that's painted opaquely
+ nsRegion opaqueRegion;
+ // save the bounds of the area that's painted by elements between the PUSH/POP
+ element->mBounds = OptimizeTranslucentRegions(aDisplayList, aIndex,
+ &opaqueRegion);
+ DisplayListElement2* popElement =
+ NS_STATIC_CAST(DisplayListElement2*, aDisplayList.ElementAt(*aIndex - 1));
+ popElement->mBounds = element->mBounds;
+ NS_ASSERTION(popElement->mFlags & POP_FILTER, "Must end with POP!");
+
+ // don't bother with filters if nothing is visible inside the filter
+ if (element->mBounds.IsEmpty()) {
+ element->mFlags &= ~PUSH_FILTER;
+ popElement->mFlags &= ~POP_FILTER;
+ } else {
+ nsRegion tmpRegion;
+ tmpRegion.Sub(element->mBounds, opaqueRegion);
+ if (!tmpRegion.IsEmpty()) {
+ // remember whether this PUSH_FILTER/POP_FILTER contents are fully opaque or not
+ element->mFlags |= VIEW_TRANSPARENT;
+ }
+ }
+
+ // The filter doesn't paint opaquely, so don't add anything to aOpaqueRegion
+ r.UnionRect(r, element->mBounds);
+ }
+ if (element->mFlags & POP_FILTER) {
+ return r;
+ }
+ }
+
+ return r;
+}
+
void nsViewManager::ShowDisplayList(nsAutoVoidArray* aDisplayList)
{
#ifdef NS_DEBUG
- char nest[400];
- PRInt32 newnestcnt, nestcnt = 0, cnt;
-
- for (cnt = 0; cnt < 400; cnt++)
- nest[cnt] = ' ';
-
printf("### display list length=%d ###\n", aDisplayList->Count());
- for (cnt = 0; cnt < aDisplayList->Count(); cnt++) {
+ PRInt32 nestcnt = 0;
+ for (PRInt32 cnt = 0; cnt < aDisplayList->Count(); cnt++) {
DisplayListElement2* element = (DisplayListElement2*)aDisplayList->ElementAt(cnt);
- nsView* view = element->mView;
- nsRect rect = element->mBounds;
- PRUint32 flags = element->mFlags;
- PRUint32 viewFlags = element->mView->GetViewFlags();
- nsRect dim;
- view->GetDimensions(dim);
- nsPoint v = view->GetPosition();
- nsView* parent = view->GetParent();
- PRInt32 zindex = view->GetZIndex();
- nsView* zParent = view->GetZParent();
-
- nest[nestcnt << 1] = 0;
-
- printf("%snsIView@%p{%d,%d,%d,%d @ %d,%d; p=%p,m=%p z=%d,zp=%p} [x=%d, y=%d, w=%d, h=%d, absX=%d, absY=%d]\n",
- nest, (void*)view,
- dim.x, dim.y, dim.width, dim.height,
- v.x, v.y,
- (void*)parent, (void*)view->GetViewManager(), zindex, (void*)zParent,
- rect.x, rect.y, rect.width, rect.height,
- element->mAbsX, element->mAbsY);
-
- newnestcnt = nestcnt;
-
- if (flags)
- {
- printf("%s", nest);
-
- if (flags & POP_CLIP) {
- printf("POP_CLIP ");
- newnestcnt--;
- }
-
- if (flags & PUSH_CLIP) {
- printf("PUSH_CLIP ");
- newnestcnt++;
- }
-
- if (flags & POP_FILTER) {
- printf("POP_FILTER ");
- newnestcnt--;
- }
-
- if (flags & PUSH_FILTER) {
- printf("PUSH_FILTER ");
- newnestcnt++;
- }
-
- if (flags & VIEW_RENDERED)
- printf("VIEW_RENDERED ");
-
- if (flags & VIEW_ISSCROLLED)
- printf("VIEW_ISSCROLLED ");
-
- if (flags & VIEW_CLIPPED)
- printf("VIEW_ISCLIPPED ");
-
- if (flags & VIEW_TRANSLUCENT)
- printf("VIEW_ISTRANSLUCENT ");
-
- if (flags & VIEW_TRANSPARENT)
- printf("VIEW_ISTRANSPARENT ");
-
- if (viewFlags & NS_VIEW_FLAG_DONT_BITBLT)
- printf("NS_VIEW_FLAG_DONT_BITBLT ");
-
- printf("\n");
- }
-
- nest[nestcnt << 1] = ' ';
-
- nestcnt = newnestcnt;
+ nestcnt = PrintDisplayListElement(element, nestcnt);
}
#endif
}
diff --git a/view/src/nsViewManager.h b/view/src/nsViewManager.h
index 136e5557f651..e65bdfdc50cb 100644
--- a/view/src/nsViewManager.h
+++ b/view/src/nsViewManager.h
@@ -249,11 +249,10 @@ private:
nsIRegion *region, PRUint32 aUpdateFlags);
void DefaultRefresh(nsView* aView, const nsRect* aRect);
void RenderViews(nsView *aRootView, nsIRenderingContext& aRC, const nsRegion& aRegion,
- PRBool aRCIsOffscreen);
+ nsDrawingSurface aRCSurface);
void RenderDisplayListElement(DisplayListElement2* element,
- nsIRenderingContext &aRC,
- BlendingBuffers* aBuffers, const nsRect& aTranslucentArea);
+ nsIRenderingContext* aRC);
void PaintView(nsView *aView, nsIRenderingContext &aRC, nscoord x, nscoord y,
const nsRect &aDamageRect);
@@ -262,9 +261,9 @@ private:
void InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut,
PRUint32 aUpdateFlags, nscoord aY1, nscoord aY2, PRBool aInCutOut);
- BlendingBuffers* CreateBlendingBuffers(nsIRenderingContext *aRC,
- PRBool aTranslucentWindow, PRBool aTranslucentViews,
- const nsRect& aTranslucentArea);
+ BlendingBuffers* CreateBlendingBuffers(nsIRenderingContext *aRC, PRBool aBorrowContext,
+ nsDrawingSurface aBorrowSurface, PRBool aNeedAlpha,
+ const nsRect& aArea);
void ReparentViews(DisplayZTreeNode* aNode);
void BuildDisplayList(nsView* aView, const nsRect& aRect, PRBool aEventProcessing,
@@ -299,6 +298,9 @@ private:
void OptimizeDisplayListClipping(nsAutoVoidArray* aDisplayList, PRBool aHaveClip,
nsRect& aClipRect, PRInt32& aIndex,
PRBool& aAnyRendered);
+ nsRect OptimizeTranslucentRegions(const nsAutoVoidArray& aDisplayList,
+ PRInt32* aIndex, nsRegion* aOpaqueRegion);
+
void ShowDisplayList(nsAutoVoidArray* aDisplayList);
// Utilities