зеркало из https://github.com/mozilla/pjs.git
Bug 539356 - Part 28 - Cached nsDisplayBackground rasterizations with BasicLayers. r=roc
This commit is contained in:
Родитель
07c0b565fc
Коммит
3daa95107f
|
@ -818,6 +818,7 @@ FrameLayerBuilder::ProcessRemovedDisplayItems(DisplayItemDataEntry* aEntry,
|
||||||
item.mGeometry->ComputeInvalidationRegion().
|
item.mGeometry->ComputeInvalidationRegion().
|
||||||
ScaleToOutsidePixels(data->mXScale, data->mYScale, item.mGeometry->mAppUnitsPerDevPixel),
|
ScaleToOutsidePixels(data->mXScale, data->mYScale, item.mGeometry->mAppUnitsPerDevPixel),
|
||||||
item.mGeometry->mPaintOffset);
|
item.mGeometry->mPaintOffset);
|
||||||
|
aEntry->GetKey()->ClearDisplayItemCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2003,6 +2004,7 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer,
|
||||||
GetTranslationForThebesLayer(newThebesLayer));
|
GetTranslationForThebesLayer(newThebesLayer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
aItem->GetUnderlyingFrame()->ClearDisplayItemCache();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!aNewLayer) {
|
if (!aNewLayer) {
|
||||||
|
@ -2057,6 +2059,7 @@ ContainerState::InvalidateForLayerChange(nsDisplayItem* aItem, Layer* aNewLayer,
|
||||||
InvalidatePostTransformRegion(newThebesLayer,
|
InvalidatePostTransformRegion(newThebesLayer,
|
||||||
combined.ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
|
combined.ScaleToOutsidePixels(data->mXScale, data->mYScale, mAppUnitsPerDevPixel),
|
||||||
GetTranslationForThebesLayer(newThebesLayer));
|
GetTranslationForThebesLayer(newThebesLayer));
|
||||||
|
aItem->GetUnderlyingFrame()->ClearDisplayItemCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2892,7 +2895,9 @@ FrameLayerBuilder::DrawThebesLayer(ThebesLayer* aLayer,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cdi->mInactiveLayer) {
|
if (cdi->mInactiveLayer) {
|
||||||
|
builder->SetIsCompositingCheap(false);
|
||||||
PaintInactiveLayer(builder, cdi->mInactiveLayer, cdi->mItem, aContext, rc);
|
PaintInactiveLayer(builder, cdi->mInactiveLayer, cdi->mItem, aContext, rc);
|
||||||
|
builder->SetIsCompositingCheap(aLayer->Manager()->IsCompositingCheap());
|
||||||
} else {
|
} else {
|
||||||
nsIFrame* frame = cdi->mItem->GetUnderlyingFrame();
|
nsIFrame* frame = cdi->mItem->GetUnderlyingFrame();
|
||||||
if (frame) {
|
if (frame) {
|
||||||
|
|
|
@ -65,7 +65,8 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
|
||||||
mSyncDecodeImages(false),
|
mSyncDecodeImages(false),
|
||||||
mIsPaintingToWindow(false),
|
mIsPaintingToWindow(false),
|
||||||
mHasDisplayPort(false),
|
mHasDisplayPort(false),
|
||||||
mHasFixedItems(false)
|
mHasFixedItems(false),
|
||||||
|
mIsCompositingCheap(false)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(nsDisplayListBuilder);
|
MOZ_COUNT_CTOR(nsDisplayListBuilder);
|
||||||
PL_InitArenaPool(&mPool, "displayListArena", 1024,
|
PL_InitArenaPool(&mPool, "displayListArena", 1024,
|
||||||
|
@ -668,6 +669,7 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
|
||||||
|
|
||||||
layerManager->SetRoot(root);
|
layerManager->SetRoot(root);
|
||||||
layerBuilder->WillEndTransaction();
|
layerBuilder->WillEndTransaction();
|
||||||
|
aBuilder->SetIsCompositingCheap(layerManager->IsCompositingCheap());
|
||||||
layerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer,
|
layerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer,
|
||||||
aBuilder, (aFlags & PAINT_NO_COMPOSITE) ? LayerManager::END_NO_COMPOSITE : LayerManager::END_DEFAULT);
|
aBuilder, (aFlags & PAINT_NO_COMPOSITE) ? LayerManager::END_NO_COMPOSITE : LayerManager::END_DEFAULT);
|
||||||
layerBuilder->DidEndTransaction();
|
layerBuilder->DidEndTransaction();
|
||||||
|
@ -1132,6 +1134,65 @@ static bool RoundedRectContainsRect(const nsRect& aRoundedRect,
|
||||||
return rgn.Contains(aContainedRect);
|
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
|
bool
|
||||||
nsDisplayBackground::TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder)
|
nsDisplayBackground::TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder)
|
||||||
{
|
{
|
||||||
|
@ -1528,6 +1589,7 @@ nsDisplayBackground::ShouldFixToViewport(nsDisplayListBuilder* aBuilder)
|
||||||
void
|
void
|
||||||
nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
|
nsDisplayBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||||
nsRenderingContext* aCtx) {
|
nsRenderingContext* aCtx) {
|
||||||
|
|
||||||
nsPoint offset = ToReferenceFrame();
|
nsPoint offset = ToReferenceFrame();
|
||||||
PRUint32 flags = aBuilder->GetBackgroundPaintFlags();
|
PRUint32 flags = aBuilder->GetBackgroundPaintFlags();
|
||||||
nsDisplayItem* nextItem = GetAbove();
|
nsDisplayItem* nextItem = GetAbove();
|
||||||
|
|
|
@ -224,6 +224,9 @@ public:
|
||||||
*/
|
*/
|
||||||
void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
|
void SetPaintingToWindow(bool aToWindow) { mIsPaintingToWindow = aToWindow; }
|
||||||
bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
|
bool IsPaintingToWindow() const { return mIsPaintingToWindow; }
|
||||||
|
|
||||||
|
void SetIsCompositingCheap(bool aCompositingCheap) { mIsCompositingCheap = aCompositingCheap; }
|
||||||
|
bool IsCompositingCheap() const { return mIsCompositingCheap; }
|
||||||
/**
|
/**
|
||||||
* Display the caret if needed.
|
* Display the caret if needed.
|
||||||
*/
|
*/
|
||||||
|
@ -532,6 +535,7 @@ private:
|
||||||
bool mIsPaintingToWindow;
|
bool mIsPaintingToWindow;
|
||||||
bool mHasDisplayPort;
|
bool mHasDisplayPort;
|
||||||
bool mHasFixedItems;
|
bool mHasFixedItems;
|
||||||
|
bool mIsCompositingCheap;
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsDisplayItem;
|
class nsDisplayItem;
|
||||||
|
@ -1703,6 +1707,7 @@ protected:
|
||||||
const nsRect& aRect, bool* aSnap);
|
const nsRect& aRect, bool* aSnap);
|
||||||
|
|
||||||
bool TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
|
bool TryOptimizeToImageLayer(nsDisplayListBuilder* aBuilder);
|
||||||
|
bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder, const nsRect& aClipRect);
|
||||||
void ConfigureLayer(ImageLayer* aLayer);
|
void ConfigureLayer(ImageLayer* aLayer);
|
||||||
|
|
||||||
/* Used to cache mFrame->IsThemed() since it isn't a cheap call */
|
/* Used to cache mFrame->IsThemed() since it isn't a cheap call */
|
||||||
|
|
|
@ -179,6 +179,16 @@ nsRect nsCanvasFrame::CanvasArea() const
|
||||||
return result;
|
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
|
void
|
||||||
nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
|
nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||||
nsRenderingContext* aCtx)
|
nsRenderingContext* aCtx)
|
||||||
|
@ -186,17 +196,46 @@ nsDisplayCanvasBackground::Paint(nsDisplayListBuilder* aBuilder,
|
||||||
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
|
nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
|
||||||
nsPoint offset = ToReferenceFrame();
|
nsPoint offset = ToReferenceFrame();
|
||||||
nsRect bgClipRect = frame->CanvasArea() + offset;
|
nsRect bgClipRect = frame->CanvasArea() + offset;
|
||||||
|
|
||||||
if (NS_GET_A(mExtraBackgroundColor) > 0) {
|
if (NS_GET_A(mExtraBackgroundColor) > 0) {
|
||||||
aCtx->SetColor(mExtraBackgroundColor);
|
aCtx->SetColor(mExtraBackgroundColor);
|
||||||
aCtx->FillRect(bgClipRect);
|
aCtx->FillRect(bgClipRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
|
bool snap;
|
||||||
mVisibleRect,
|
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()),
|
nsRect(offset, mFrame->GetSize()),
|
||||||
aBuilder->GetBackgroundPaintFlags(),
|
aBuilder->GetBackgroundPaintFlags(),
|
||||||
&bgClipRect);
|
&bgClipRect);
|
||||||
|
if (surf) {
|
||||||
|
BlitSurface(dest, mDestRect, surf);
|
||||||
|
|
||||||
|
GetUnderlyingFrame()->Properties().Set(nsIFrame::CachedBackgroundImage(), surf.forget().get());
|
||||||
|
GetUnderlyingFrame()->AddStateBits(NS_FRAME_HAS_CACHED_BACKGROUND);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -253,6 +253,15 @@ nsIFrame::MarkAsAbsoluteContainingBlock() {
|
||||||
Properties().Set(AbsoluteContainingBlockProperty(), new nsAbsoluteContainingBlock(GetAbsoluteListID()));
|
Properties().Set(AbsoluteContainingBlockProperty(), new nsAbsoluteContainingBlock(GetAbsoluteListID()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsIFrame::ClearDisplayItemCache()
|
||||||
|
{
|
||||||
|
if (HasAnyStateBits(NS_FRAME_HAS_CACHED_BACKGROUND)) {
|
||||||
|
Properties().Delete(CachedBackgroundImage());
|
||||||
|
RemoveStateBits(NS_FRAME_HAS_CACHED_BACKGROUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsIFrame::CheckAndClearPaintedState()
|
nsIFrame::CheckAndClearPaintedState()
|
||||||
{
|
{
|
||||||
|
|
|
@ -295,6 +295,10 @@ typedef PRUint64 nsFrameState;
|
||||||
// Frame is a descendant of a popup
|
// Frame is a descendant of a popup
|
||||||
#define NS_FRAME_IN_POPUP NS_FRAME_STATE_BIT(48)
|
#define NS_FRAME_IN_POPUP NS_FRAME_STATE_BIT(48)
|
||||||
|
|
||||||
|
// Frame has a cached rasterization of anV
|
||||||
|
// nsDisplayBackground display item
|
||||||
|
#define NS_FRAME_HAS_CACHED_BACKGROUND NS_FRAME_STATE_BIT(49)
|
||||||
|
|
||||||
// Box layout bits
|
// Box layout bits
|
||||||
#define NS_STATE_IS_HORIZONTAL NS_FRAME_STATE_BIT(22)
|
#define NS_STATE_IS_HORIZONTAL NS_FRAME_STATE_BIT(22)
|
||||||
#define NS_STATE_IS_DIRECTION_NORMAL NS_FRAME_STATE_BIT(31)
|
#define NS_STATE_IS_DIRECTION_NORMAL NS_FRAME_STATE_BIT(31)
|
||||||
|
@ -875,6 +879,11 @@ public:
|
||||||
delete static_cast<nsOverflowAreas*>(aPropertyValue);
|
delete static_cast<nsOverflowAreas*>(aPropertyValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void DestroySurface(void* aPropertyValue)
|
||||||
|
{
|
||||||
|
static_cast<gfxASurface*>(aPropertyValue)->Release();
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
// XXX Workaround MSVC issue by making the static FramePropertyDescriptor
|
// XXX Workaround MSVC issue by making the static FramePropertyDescriptor
|
||||||
// non-const. See bug 555727.
|
// non-const. See bug 555727.
|
||||||
|
@ -918,6 +927,8 @@ public:
|
||||||
|
|
||||||
NS_DECLARE_FRAME_PROPERTY(LineBaselineOffset, nsnull)
|
NS_DECLARE_FRAME_PROPERTY(LineBaselineOffset, nsnull)
|
||||||
|
|
||||||
|
NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImage, DestroySurface)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the distance between the border edge of the frame and the
|
* Return the distance between the border edge of the frame and the
|
||||||
* margin edge of the frame. Like GetRect(), returns the dimensions
|
* margin edge of the frame. Like GetRect(), returns the dimensions
|
||||||
|
@ -2547,6 +2558,8 @@ NS_PTR_TO_INT32(frame->Properties().Get(nsIFrame::ParagraphDepthProperty()))
|
||||||
*/
|
*/
|
||||||
virtual bool IsFocusable(PRInt32 *aTabIndex = nsnull, bool aWithMouse = false);
|
virtual bool IsFocusable(PRInt32 *aTabIndex = nsnull, bool aWithMouse = false);
|
||||||
|
|
||||||
|
void ClearDisplayItemCache();
|
||||||
|
|
||||||
// BOX LAYOUT METHODS
|
// BOX LAYOUT METHODS
|
||||||
// These methods have been migrated from nsIBox and are in the process of
|
// These methods have been migrated from nsIBox and are in the process of
|
||||||
// being refactored. DO NOT USE OUTSIDE OF XUL.
|
// being refactored. DO NOT USE OUTSIDE OF XUL.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче