mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 18:08:58 +00:00
Backout 6ea008b301da, 14d17919e235, b15fb3603bfe & f89ae41eed63 (bug 772679) for turning test_offsets.html perma-orange on native Android mochitest-7
This commit is contained in:
parent
d3209cdece
commit
5be29bb8fd
@ -2505,53 +2505,44 @@ FrameLayerBuilder::GetDedicatedLayer(nsIFrame* aFrame, PRUint32 aDisplayItemKey)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static gfxSize
|
||||
PredictScaleForContent(nsIFrame* aFrame, nsIFrame* aAncestorWithScale,
|
||||
const gfxSize& aScale)
|
||||
bool
|
||||
FrameLayerBuilder::GetThebesLayerResolutionForFrame(nsIFrame* aFrame,
|
||||
double* aXres, double* aYres,
|
||||
gfxPoint* aPoint)
|
||||
{
|
||||
gfx3DMatrix transform =
|
||||
gfx3DMatrix::ScalingMatrix(aScale.width, aScale.height, 1.0);
|
||||
// aTransform is applied first, then the scale is applied to the result
|
||||
transform = nsLayoutUtils::GetTransformToAncestor(aFrame, aAncestorWithScale)*transform;
|
||||
gfxMatrix transform2d;
|
||||
if (transform.CanDraw2D(&transform2d)) {
|
||||
return transform2d.ScaleFactors(true);
|
||||
}
|
||||
return gfxSize(1.0, 1.0);
|
||||
}
|
||||
|
||||
gfxSize
|
||||
FrameLayerBuilder::GetThebesLayerScaleForFrame(nsIFrame* aFrame)
|
||||
{
|
||||
nsIFrame* last;
|
||||
for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
|
||||
last = f;
|
||||
if (f->GetStateBits() & NS_FRAME_HAS_CONTAINER_LAYER) {
|
||||
nsTArray<DisplayItemData>* array = GetDisplayItemDataArrayForFrame(f);
|
||||
// Some frames with NS_FRAME_HAS_CONTAINER_LAYER may not have display items.
|
||||
// In particular the root frame probably doesn't!
|
||||
if (!array)
|
||||
continue;
|
||||
for (PRUint32 i = 0; i < array->Length(); ++i) {
|
||||
Layer* layer = array->ElementAt(i).mLayer;
|
||||
ContainerLayer* container = layer->AsContainerLayer();
|
||||
if (!container) {
|
||||
continue;
|
||||
}
|
||||
for (Layer* l = container->GetFirstChild(); l; l = l->GetNextSibling()) {
|
||||
ThebesDisplayItemLayerUserData* data =
|
||||
static_cast<ThebesDisplayItemLayerUserData*>
|
||||
(l->GetUserData(&gThebesDisplayItemLayerUserData));
|
||||
if (data) {
|
||||
return PredictScaleForContent(aFrame, f, gfxSize(data->mXScale, data->mYScale));
|
||||
}
|
||||
}
|
||||
nsTArray<DisplayItemData> *array = GetDisplayItemDataArrayForFrame(aFrame);
|
||||
if (array) {
|
||||
for (PRUint32 i = 0; i < array->Length(); ++i) {
|
||||
Layer* layer = array->ElementAt(i).mLayer;
|
||||
if (layer->HasUserData(&gThebesDisplayItemLayerUserData)) {
|
||||
ThebesDisplayItemLayerUserData* data =
|
||||
static_cast<ThebesDisplayItemLayerUserData*>
|
||||
(layer->GetUserData(&gThebesDisplayItemLayerUserData));
|
||||
*aXres = data->mXScale;
|
||||
*aYres = data->mYScale;
|
||||
*aPoint = data->mActiveScrolledRootPosition;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return PredictScaleForContent(aFrame, last,
|
||||
last->PresContext()->PresShell()->GetResolution());
|
||||
nsIFrame::ChildListIterator lists(aFrame);
|
||||
for (; !lists.IsDone(); lists.Next()) {
|
||||
if (lists.CurrentID() == nsIFrame::kPopupList ||
|
||||
lists.CurrentID() == nsIFrame::kSelectPopupList) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
||||
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
||||
if (GetThebesLayerResolutionForFrame(childFrames.get(),
|
||||
aXres, aYres, aPoint)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
|
@ -369,13 +369,15 @@ public:
|
||||
nsIntPoint GetLastPaintOffset(ThebesLayer* aLayer);
|
||||
|
||||
/**
|
||||
* Return the resolution at which we expect to render aFrame's contents,
|
||||
* assuming they are being painted to retained layers. This takes into account
|
||||
* the resolution the contents of the ContainerLayer containing aFrame are
|
||||
* being rendered at, as well as any currently-inactive transforms between
|
||||
* aFrame and that container layer.
|
||||
* Return resolution and scroll offset of ThebesLayer content associated
|
||||
* with aFrame's subtree.
|
||||
* Returns true if some ThebesLayer was found.
|
||||
* This just looks for the first ThebesLayer and returns its data. There
|
||||
* could be other ThebesLayers with different resolution and offsets.
|
||||
*/
|
||||
static gfxSize GetThebesLayerScaleForFrame(nsIFrame* aFrame);
|
||||
static bool GetThebesLayerResolutionForFrame(nsIFrame* aFrame,
|
||||
double* aXRes, double* aYRes,
|
||||
gfxPoint* aPoint);
|
||||
|
||||
/**
|
||||
* Clip represents the intersection of an optional rectangle with a
|
||||
|
@ -1196,7 +1196,6 @@ public:
|
||||
* The resolution defaults to 1.0.
|
||||
*/
|
||||
virtual nsresult SetResolution(float aXResolution, float aYResolution) = 0;
|
||||
gfxSize GetResolution() { return gfxSize(mXResolution, mYResolution); }
|
||||
float GetXResolution() { return mXResolution; }
|
||||
float GetYResolution() { return mYResolution; }
|
||||
|
||||
|
@ -40,7 +40,6 @@ MOCHITEST_CHROME_FILES = \
|
||||
printpreview_bug396024_helper.xul \
|
||||
test_printpreview_bug482976.xul \
|
||||
printpreview_bug482976_helper.xul \
|
||||
test_scrolling_repaints.html \
|
||||
test_transformed_scrolling_repaints.html \
|
||||
test_transformed_scrolling_repaints_2.html \
|
||||
$(NULL)
|
||||
|
@ -1,49 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test that we don't get unnecessary repaints due to subpixel shifts</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="paint_listener.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<!-- Need a timeout here to allow paint unsuppression before we start the test -->
|
||||
<body onload="setTimeout(startTest,0)">
|
||||
<div id="t" style="width:400px; height:100px; background:yellow; overflow:hidden">
|
||||
<div style="height:40px;"></div>
|
||||
<div id="e" style="height:30px; background:lime"></div>
|
||||
<div style="height:60.4px; background:pink"></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var t = document.getElementById("t");
|
||||
var e = document.getElementById("e");
|
||||
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
|
||||
function startTest() {
|
||||
// Do a scroll to ensure we trigger activity heuristics.
|
||||
waitForAllPaintsFlushed(function () {
|
||||
t.scrollTop = 5;
|
||||
// Scroll down as far as we can, to put our rendering layer at a subpixel offset within the layer
|
||||
waitForAllPaintsFlushed(function () {
|
||||
t.scrollTop = 1000;
|
||||
waitForAllPaintsFlushed(function () {
|
||||
// Clear paint state now and scroll again.
|
||||
utils.checkAndClearPaintedState(e);
|
||||
// scroll up a little bit. This should not cause anything to be repainted.
|
||||
t.scrollTop = t.scrollTop - 10;
|
||||
waitForAllPaintsFlushed(function () {
|
||||
var painted = utils.checkAndClearPaintedState(e);
|
||||
is(painted, false, "Fully-visible scrolled element should not have been painted");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -34,7 +34,11 @@ function startTest() {
|
||||
t.scrollTop = 33;
|
||||
waitForAllPaintsFlushed(function () {
|
||||
var painted = utils.checkAndClearPaintedState(e);
|
||||
is(painted, false, "Fully-visible scrolled element should not have been painted");
|
||||
if (navigator.platform.indexOf("Mac") >= 0) {
|
||||
todo_is(painted, false, "Fully-visible scrolled element should not have been painted (disabled on Mac, see bug 753497)");
|
||||
} else {
|
||||
is(painted, false, "Fully-visible scrolled element should not have been painted");
|
||||
}
|
||||
SimpleTest.finish();
|
||||
});
|
||||
});
|
||||
|
@ -1967,34 +1967,38 @@ void nsGfxScrollFrameInner::ScrollVisual(nsPoint aOldScrolledFramePos)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an appunit value close to aDesired and between aLower and aUpper
|
||||
* such that (aDesired - aCurrent)*aRes/aAppUnitsPerPixel is an integer (or
|
||||
* as close as we can get modulo rounding to appunits). If that
|
||||
* can't be done, just returns aDesired.
|
||||
* Adjust the desired scroll value in given range
|
||||
* in order to get resulting scroll by whole amount of layer pixels.
|
||||
* Current implementation is not checking that result value is the best.
|
||||
* Ideally it's would be possible to find best value by implementing
|
||||
* test function which is repeating last part of CreateOrRecycleThebesLayer,
|
||||
* and checking other points in allowed range, but that may cause another perf hit.
|
||||
* Let's keep it as TODO.
|
||||
*/
|
||||
static nscoord
|
||||
AlignWithLayerPixels(nscoord aDesired, nscoord aLower,
|
||||
nscoord aUpper, nscoord aAppUnitsPerPixel,
|
||||
double aRes, nscoord aCurrent)
|
||||
RestrictToLayerPixels(nscoord aDesired, nscoord aLower,
|
||||
nscoord aUpper, nscoord aAppUnitsPerPixel,
|
||||
double aRes, double aCurrentLayerOffset)
|
||||
{
|
||||
double currentLayerVal = (aRes*aCurrent)/aAppUnitsPerPixel;
|
||||
double desiredLayerVal = (aRes*aDesired)/aAppUnitsPerPixel;
|
||||
double delta = desiredLayerVal - currentLayerVal;
|
||||
double nearestVal = NS_round(delta) + currentLayerVal;
|
||||
// convert the result to layer pixels
|
||||
double layerVal = aRes * double(aDesired) / aAppUnitsPerPixel;
|
||||
|
||||
// Convert back from ThebesLayer space to appunits relative to the top-left
|
||||
// of the scrolled frame.
|
||||
// Correct value using current layer offset
|
||||
layerVal -= aCurrentLayerOffset;
|
||||
|
||||
// Try nearest pixel bound first
|
||||
double nearestVal = NS_round(layerVal);
|
||||
nscoord nearestAppUnitVal =
|
||||
NSToCoordRoundWithClamp(nearestVal*aAppUnitsPerPixel/aRes);
|
||||
NSToCoordRoundWithClamp(nearestVal * aAppUnitsPerPixel / aRes);
|
||||
|
||||
// Check if nearest layer pixel result fit into allowed and scroll range
|
||||
if (nearestAppUnitVal >= aLower && nearestAppUnitVal <= aUpper) {
|
||||
return nearestAppUnitVal;
|
||||
} else if (nearestVal != desiredLayerVal) {
|
||||
} else if (nearestVal != layerVal) {
|
||||
// Check if opposite pixel boundary fit into scroll range
|
||||
double oppositeVal = nearestVal + ((nearestVal < desiredLayerVal) ? 1 : -1);
|
||||
double oppositeVal = nearestVal + ((nearestVal < layerVal) ? 1 : -1);
|
||||
nscoord oppositeAppUnitVal =
|
||||
NSToCoordRoundWithClamp(oppositeVal*aAppUnitsPerPixel/aRes);
|
||||
NSToCoordRoundWithClamp(oppositeVal * aAppUnitsPerPixel / aRes);
|
||||
if (oppositeAppUnitVal >= aLower && oppositeAppUnitVal <= aUpper) {
|
||||
return oppositeAppUnitVal;
|
||||
}
|
||||
@ -2003,17 +2007,17 @@ AlignWithLayerPixels(nscoord aDesired, nscoord aLower,
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamp desired scroll position aPt to aBounds and then snap
|
||||
* it to the same layer pixel edges as aCurrent, keeping it within aRange
|
||||
* during snapping. aCurrent is the current scroll position.
|
||||
* Clamp desired scroll position aPt to aBounds (if aBounds is non-null) and then snap
|
||||
* it to the nearest layer pixel edges, keeping it within aRange during snapping
|
||||
* (if aRange is non-null). aCurrScroll is the current scroll position.
|
||||
*/
|
||||
static nsPoint
|
||||
ClampAndAlignWithLayerPixels(const nsPoint& aPt,
|
||||
const nsRect& aBounds,
|
||||
const nsRect& aRange,
|
||||
const nsPoint& aCurrent,
|
||||
nscoord aAppUnitsPerPixel,
|
||||
const gfxSize& aScale)
|
||||
ClampAndRestrictToLayerPixels(const nsPoint& aPt,
|
||||
const nsRect& aBounds,
|
||||
nscoord aAppUnitsPerPixel,
|
||||
const nsRect& aRange,
|
||||
double aXRes, double aYRes,
|
||||
const gfxPoint& aCurrScroll)
|
||||
{
|
||||
nsPoint pt = aBounds.ClampPoint(aPt);
|
||||
// Intersect scroll range with allowed range, by clamping the corners
|
||||
@ -2021,10 +2025,10 @@ ClampAndAlignWithLayerPixels(const nsPoint& aPt,
|
||||
nsPoint rangeTopLeft = aBounds.ClampPoint(aRange.TopLeft());
|
||||
nsPoint rangeBottomRight = aBounds.ClampPoint(aRange.BottomRight());
|
||||
|
||||
return nsPoint(AlignWithLayerPixels(pt.x, rangeTopLeft.x, rangeBottomRight.x,
|
||||
aAppUnitsPerPixel, aScale.width, aCurrent.x),
|
||||
AlignWithLayerPixels(pt.y, rangeTopLeft.y, rangeBottomRight.y,
|
||||
aAppUnitsPerPixel, aScale.height, aCurrent.y));
|
||||
return nsPoint(RestrictToLayerPixels(pt.x, rangeTopLeft.x, rangeBottomRight.x,
|
||||
aAppUnitsPerPixel, aXRes, aCurrScroll.x),
|
||||
RestrictToLayerPixels(pt.y, rangeTopLeft.y, rangeBottomRight.y,
|
||||
aAppUnitsPerPixel, aYRes, aCurrScroll.y));
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
@ -2057,28 +2061,19 @@ nsGfxScrollFrameInner::ScrollToImpl(nsPoint aPt, const nsRect& aRange)
|
||||
{
|
||||
nsPresContext* presContext = mOuter->PresContext();
|
||||
nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
|
||||
// 'scale' is our estimate of the scale factor that will be applied
|
||||
// when rendering the scrolled content to its own ThebesLayer.
|
||||
gfxSize scale = FrameLayerBuilder::GetThebesLayerScaleForFrame(mScrolledFrame);
|
||||
nsPoint curPos = GetScrollPosition();
|
||||
// Try to align aPt with curPos so they have an integer number of layer
|
||||
// pixels between them. This gives us the best chance of scrolling without
|
||||
// having to invalidate due to changes in subpixel rendering.
|
||||
// Note that when we actually draw into a ThebesLayer, the coordinates
|
||||
// that get mapped onto the layer buffer pixels are from the display list,
|
||||
// which are relative to the display root frame's top-left increasing down,
|
||||
// whereas here our coordinates are scroll positions which increase upward
|
||||
// and are relative to the scrollport top-left. This difference doesn't actually
|
||||
// matter since all we are about is that there be an integer number of
|
||||
// layer pixels between pt and curPos.
|
||||
nsPoint pt =
|
||||
ClampAndAlignWithLayerPixels(aPt,
|
||||
GetScrollRangeForClamping(),
|
||||
aRange,
|
||||
curPos,
|
||||
appUnitsPerDevPixel,
|
||||
scale);
|
||||
|
||||
double xres = 1.0, yres = 1.0;
|
||||
gfxPoint activeScrolledRootPosition;
|
||||
FrameLayerBuilder::GetThebesLayerResolutionForFrame(mScrolledFrame, &xres, &yres,
|
||||
&activeScrolledRootPosition);
|
||||
nsPoint pt =
|
||||
ClampAndRestrictToLayerPixels(aPt,
|
||||
GetScrollRangeForClamping(),
|
||||
appUnitsPerDevPixel,
|
||||
aRange, xres, yres,
|
||||
activeScrolledRootPosition);
|
||||
|
||||
nsPoint curPos = GetScrollPosition();
|
||||
if (pt == curPos) {
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user