Bug 1034247 - Avoid propogating scale factors down to ThebesLayers if it would result in them being larger than the max texture size. r=roc

This commit is contained in:
Matt Woodrow 2014-07-09 14:01:54 +12:00
parent 025788124a
commit 6d89446227
5 changed files with 45 additions and 9 deletions

View File

@ -204,7 +204,7 @@ struct TextureFactoryIdentifier
TextureFactoryIdentifier(LayersBackend aLayersBackend = LayersBackend::LAYERS_NONE,
GeckoProcessType aParentProcessId = GeckoProcessType_Default,
int32_t aMaxTextureSize = 0,
int32_t aMaxTextureSize = 4096,
bool aSupportsTextureBlitting = false,
bool aSupportsPartialUploads = false)
: mParentBackend(aLayersBackend)

View File

@ -1410,6 +1410,8 @@ public:
mManager->Mutated(this);
}
virtual int32_t GetMaxLayerSize() { return Manager()->GetMaxTextureSize(); }
protected:
Layer(LayerManager* aManager, void* aImplData);

View File

@ -86,6 +86,12 @@ public:
void* aCallbackData,
ReadbackProcessor* aReadback) MOZ_OVERRIDE;
/**
* We don't really have a hard restriction for max layer size, but we pick
* 4096 to avoid excessive memory usage.
*/
virtual int32_t GetMaxLayerSize() MOZ_OVERRIDE { return 4096; }
protected:
BasicLayerManager* BasicManager()
{

View File

@ -3118,10 +3118,37 @@ static inline gfxSize RoundToFloatPrecision(const gfxSize& aSize)
return gfxSize(float(aSize.width), float(aSize.height));
}
static void RestrictScaleToMaxLayerSize(gfxSize& aScale,
const nsRect& aVisibleRect,
nsIFrame* aContainerFrame,
Layer* aContainerLayer)
{
if (!aContainerLayer->Manager()->IsWidgetLayerManager()) {
return;
}
nsIntRect pixelSize =
aVisibleRect.ScaleToOutsidePixels(aScale.width, aScale.height,
aContainerFrame->PresContext()->AppUnitsPerDevPixel());
int32_t maxLayerSize = aContainerLayer->GetMaxLayerSize();
if (pixelSize.width > maxLayerSize) {
float scale = (float)pixelSize.width / maxLayerSize;
scale = gfxUtils::ClampToScaleFactor(scale);
aScale.width /= scale;
}
if (pixelSize.height > maxLayerSize) {
float scale = (float)pixelSize.height / maxLayerSize;
scale = gfxUtils::ClampToScaleFactor(scale);
aScale.height /= scale;
}
}
static bool
ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
nsDisplayListBuilder* aDisplayListBuilder,
nsIFrame* aContainerFrame,
const nsRect& aVisibleRect,
const gfx3DMatrix* aTransform,
const ContainerLayerParameters& aIncomingScale,
ContainerLayer* aLayer,
@ -3212,6 +3239,12 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
if (fabs(scale.width) < 1e-8 || fabs(scale.height) < 1e-8) {
scale = gfxSize(1.0, 1.0);
}
// If this is a transform container layer, then pre-rendering might
// mean we try render a layer bigger than the max texture size. Apply
// clmaping to prevent this.
if (aTransform) {
RestrictScaleToMaxLayerSize(scale, aVisibleRect, aContainerFrame, aLayer);
}
} else {
scale = gfxSize(1.0, 1.0);
}
@ -3349,8 +3382,8 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
}
ContainerLayerParameters scaleParameters;
if (!ChooseScaleAndSetTransform(this, aBuilder, aContainerFrame, aTransform, aParameters,
containerLayer, state, scaleParameters)) {
if (!ChooseScaleAndSetTransform(this, aBuilder, aContainerFrame, aChildren.GetVisibleRect(),
aTransform, aParameters, containerLayer, state, scaleParameters)) {
return nullptr;
}

View File

@ -4731,12 +4731,7 @@ nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBui
refSize += nsSize(refSize.width / 8, refSize.height / 8);
nsSize frameSize = aFrame->GetVisualOverflowRectRelativeToSelf().Size();
if (frameSize <= refSize) {
// Bug 717521 - pre-render max 4096 x 4096 device pixels.
nscoord max = aFrame->PresContext()->DevPixelsToAppUnits(4096);
nsRect visual = aFrame->GetVisualOverflowRect();
if (visual.width <= max && visual.height <= max) {
return true;
}
return true;
}
if (aLogAnimations) {