mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 539356 - Part 28 - Cached nsDisplayBackground rasterizations with BasicLayers. r=roc
This commit is contained in:
parent
0bc8f48c38
commit
35775825fa
@ -64,7 +64,8 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||
mSyncDecodeImages(false),
|
||||
mIsPaintingToWindow(false),
|
||||
mHasDisplayPort(false),
|
||||
mHasFixedItems(false)
|
||||
mHasFixedItems(false),
|
||||
mIsCompositingCheap(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayListBuilder);
|
||||
PL_InitArenaPool(&mPool, "displayListArena", 1024,
|
||||
@ -648,8 +649,10 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
layerManager->SetRoot(root);
|
||||
layerBuilder->WillEndTransaction(layerManager);
|
||||
bool temp = aBuilder->SetIsCompositingCheap(layerManager->IsCompositingCheap());
|
||||
layerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer,
|
||||
aBuilder);
|
||||
aBuilder->SetIsCompositingCheap(temp);
|
||||
layerBuilder->DidEndTransaction(layerManager);
|
||||
|
||||
if (aFlags & PAINT_FLUSH_LAYERS) {
|
||||
@ -1090,6 +1093,65 @@ static bool RoundedRectContainsRect(const nsRect& aRoundedRect,
|
||||
return rgn.Contains(aContainedRect);
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackground::IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder, const nsRect& aClipRect)
|
||||
{
|
||||
if (mIsThemed)
|
||||
return false;
|
||||
|
||||
nsPresContext* presContext = mFrame->PresContext();
|
||||
nsStyleContext* bgSC;
|
||||
if (!nsCSSRendering::FindBackground(presContext, mFrame, &bgSC))
|
||||
return false;
|
||||
|
||||
bool drawBackgroundImage;
|
||||
bool drawBackgroundColor;
|
||||
nsCSSRendering::DetermineBackgroundColor(presContext,
|
||||
bgSC,
|
||||
mFrame,
|
||||
drawBackgroundImage,
|
||||
drawBackgroundColor);
|
||||
|
||||
// For now we don't know how to draw image layers with a background color.
|
||||
if (!drawBackgroundImage || drawBackgroundColor)
|
||||
return false;
|
||||
|
||||
const nsStyleBackground *bg = bgSC->GetStyleBackground();
|
||||
|
||||
// We could pretty easily support multiple image layers, but for now we
|
||||
// just punt here.
|
||||
if (bg->mLayers.Length() != 1)
|
||||
return false;
|
||||
|
||||
PRUint32 flags = aBuilder->GetBackgroundPaintFlags();
|
||||
nsPoint offset = ToReferenceFrame();
|
||||
nsRect borderArea = nsRect(offset, mFrame->GetSize());
|
||||
|
||||
const nsStyleBackground::Layer &layer = bg->mLayers[0];
|
||||
|
||||
if (layer.mAttachment != NS_STYLE_BG_ATTACHMENT_FIXED)
|
||||
return false;
|
||||
|
||||
nsBackgroundLayerState state =
|
||||
nsCSSRendering::PrepareBackgroundLayer(presContext,
|
||||
mFrame,
|
||||
flags,
|
||||
borderArea,
|
||||
aClipRect,
|
||||
*bg,
|
||||
layer);
|
||||
|
||||
nsImageRenderer* imageRenderer = &state.mImageRenderer;
|
||||
// We only care about images here, not gradients.
|
||||
if (!imageRenderer->IsRasterImage())
|
||||
return false;
|
||||
|
||||
PRInt32 appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
|
||||
mDestRect = nsLayoutUtils::RectToGfxRect(state.mFillArea, appUnitsPerDevPixel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayBackground::TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
@ -1456,6 +1518,7 @@ nsDisplayBackground::ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
|
||||
void
|
||||
nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx) {
|
||||
|
||||
nsPoint offset = ToReferenceFrame();
|
||||
PRUint32 flags = aBuilder->GetBackgroundPaintFlags();
|
||||
nsDisplayItem* nextItem = GetAbove();
|
||||
|
@ -221,6 +221,13 @@ public:
|
||||
*/
|
||||
void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
|
||||
bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
|
||||
|
||||
bool SetIsCompositingCheap(bool aCompositingCheap) {
|
||||
bool temp = mIsCompositingCheap;
|
||||
mIsCompositingCheap = aCompositingCheap;
|
||||
return temp;
|
||||
}
|
||||
bool IsCompositingCheap() const { return mIsCompositingCheap; }
|
||||
/**
|
||||
* Display the caret if needed.
|
||||
*/
|
||||
@ -528,6 +535,7 @@ private:
|
||||
bool mIsPaintingToWindow;
|
||||
bool mHasDisplayPort;
|
||||
bool mHasFixedItems;
|
||||
bool mIsCompositingCheap;
|
||||
};
|
||||
|
||||
class nsDisplayItem;
|
||||
@ -1607,6 +1615,7 @@ protected:
|
||||
const nsRect& aRect, bool* aSnap);
|
||||
|
||||
bool TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
|
||||
bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder, const nsRect& aClipRect);
|
||||
void ConfigureLayer(ImageLayer* aLayer);
|
||||
|
||||
/* Used to cache mFrame->IsThemed() since it isn't a cheap call */
|
||||
|
@ -185,6 +185,16 @@ nsRect nsCanvasFrame::CanvasArea() const
|
||||
return result;
|
||||
}
|
||||
|
||||
static void BlitSurface(gfxContext* aDest, const gfxRect& aRect, gfxASurface* aSource)
|
||||
{
|
||||
aDest->Translate(gfxPoint(aRect.x, aRect.y));
|
||||
aDest->SetSource(aSource);
|
||||
aDest->NewPath();
|
||||
aDest->Rectangle(gfxRect(0, 0, aRect.width, aRect.height));
|
||||
aDest->Fill();
|
||||
aDest->Translate(-gfxPoint(aRect.x, aRect.y));
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx)
|
||||
@ -192,17 +202,46 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
|
||||
nsPoint offset = ToReferenceFrame();
|
||||
nsRect bgClipRect = frame->CanvasArea() + offset;
|
||||
|
||||
if (NS_GET_A(mExtraBackgroundColor) > 0) {
|
||||
aCtx->SetColor(mExtraBackgroundColor);
|
||||
aCtx->FillRect(bgClipRect);
|
||||
}
|
||||
|
||||
nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
|
||||
mVisibleRect,
|
||||
bool snap;
|
||||
nsRect bounds = GetBounds(aBuilder, &snap);
|
||||
nsIntRect pixelRect = bounds.ToOutsidePixels(mFrame->PresContext()->AppUnitsPerDevPixel());
|
||||
nsRenderingContext context;
|
||||
nsRefPtr<gfxContext> dest = aCtx->ThebesContext();
|
||||
nsRefPtr<gfxASurface> surf;
|
||||
nsRefPtr<gfxContext> ctx;
|
||||
#ifndef MOZ_GFX_OPTIMIZE_MOBILE
|
||||
if (IsSingleFixedPositionImage(aBuilder, bgClipRect) && aBuilder->IsPaintingToWindow() && !aBuilder->IsCompositingCheap()) {
|
||||
surf = static_cast<gfxASurface*>(GetUnderlyingFrame()->Properties().Get(nsIFrame::CachedBackgroundImage()));
|
||||
nsRefPtr<gfxASurface> destSurf = dest->CurrentSurface();
|
||||
if (surf && surf->GetType() == destSurf->GetType()) {
|
||||
BlitSurface(dest, mDestRect, surf);
|
||||
return;
|
||||
}
|
||||
surf = destSurf->CreateSimilarSurface(gfxASurface::CONTENT_COLOR_ALPHA, gfxIntSize(ceil(mDestRect.width), ceil(mDestRect.height)));
|
||||
if (surf) {
|
||||
ctx = new gfxContext(surf);
|
||||
ctx->Translate(-gfxPoint(mDestRect.x, mDestRect.y));
|
||||
context.Init(aCtx->DeviceContext(), ctx);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
nsCSSRendering::PaintBackground(mFrame->PresContext(), surf ? context : *aCtx, mFrame,
|
||||
surf ? bounds : mVisibleRect,
|
||||
nsRect(offset, mFrame->GetSize()),
|
||||
aBuilder->GetBackgroundPaintFlags(),
|
||||
&bgClipRect);
|
||||
if (surf) {
|
||||
BlitSurface(dest, mDestRect, surf);
|
||||
|
||||
GetUnderlyingFrame()->Properties().Set(nsIFrame::CachedBackgroundImage(), surf.forget().get());
|
||||
GetUnderlyingFrame()->AddStateBits(NS_FRAME_HAS_CACHED_BACKGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -252,6 +252,15 @@ nsIFrame::MarkAsAbsoluteContainingBlock() {
|
||||
Properties().Set(AbsoluteContainingBlockProperty(), new nsAbsoluteContainingBlock(GetAbsoluteListID()));
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::ClearDisplayItemCache()
|
||||
{
|
||||
if (GetStateBits() & NS_FRAME_HAS_CACHED_BACKGROUND) {
|
||||
Properties().Delete(CachedBackgroundImage());
|
||||
RemoveStateBits(NS_FRAME_HAS_CACHED_BACKGROUND);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
nsIFrame::CheckAndClearPaintedState()
|
||||
{
|
||||
@ -4695,6 +4704,7 @@ void
|
||||
nsIFrame::InvalidateInternal(const nsRect& aDamageRect, nscoord aX, nscoord aY,
|
||||
nsIFrame* aForChild, PRUint32 aFlags)
|
||||
{
|
||||
ClearDisplayItemCache();
|
||||
nsSVGEffects::InvalidateDirectRenderingObservers(this);
|
||||
if (nsSVGIntegrationUtils::UsingEffectsForFrame(this)) {
|
||||
nsRect r = nsSVGIntegrationUtils::AdjustInvalidAreaForSVGEffects(this,
|
||||
|
@ -293,6 +293,9 @@ typedef PRUint64 nsFrameState;
|
||||
// the frames for future reference.
|
||||
#define NS_FRAME_NO_COMPONENT_ALPHA NS_FRAME_STATE_BIT(45)
|
||||
|
||||
// Frame has a cached rasterization of anV
|
||||
// nsDisplayBackground display item
|
||||
#define NS_FRAME_HAS_CACHED_BACKGROUND NS_FRAME_STATE_BIT(46)
|
||||
|
||||
// Box layout bits
|
||||
#define NS_STATE_IS_HORIZONTAL NS_FRAME_STATE_BIT(22)
|
||||
@ -874,6 +877,11 @@ public:
|
||||
delete static_cast<nsOverflowAreas*>(aPropertyValue);
|
||||
}
|
||||
|
||||
static void DestroySurface(void* aPropertyValue)
|
||||
{
|
||||
static_cast<gfxASurface*>(aPropertyValue)->Release();
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// XXX Workaround MSVC issue by making the static FramePropertyDescriptor
|
||||
// non-const. See bug 555727.
|
||||
@ -917,6 +925,8 @@ public:
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(LineBaselineOffset, nsnull)
|
||||
|
||||
NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImage, DestroySurface)
|
||||
|
||||
/**
|
||||
* Return the distance between the border edge of the frame and the
|
||||
* margin edge of the frame. Like GetRect(), returns the dimensions
|
||||
@ -2593,6 +2603,8 @@ NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::ParagraphDepthProperty()))
|
||||
*/
|
||||
virtual bool IsFocusable(PRInt32 *aTabIndex = nsnull, bool aWithMouse = false);
|
||||
|
||||
void ClearDisplayItemCache();
|
||||
|
||||
// BOX LAYOUT METHODS
|
||||
// These methods have been migrated from nsIBox and are in the process of
|
||||
// being refactored. DO NOT USE OUTSIDE OF XUL.
|
||||
|
Loading…
Reference in New Issue
Block a user