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