--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -3157,16 +3157,50 @@ nsDOMWindowUtils::CheckAndClearPaintedSt
}
}
*aResult = frame->CheckAndClearPaintedState();
return NS_OK;
}
NS_IMETHODIMP
+nsDOMWindowUtils::CheckAndClearDisplayListState(nsIDOMElement* aElement, bool* aResult)
+{
+ if (!aElement) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ nsresult rv;
+ nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsIFrame* frame = content->GetPrimaryFrame();
+
+ if (!frame) {
+ *aResult = false;
+ return NS_OK;
+ }
+
+ // Get the outermost frame for the content node, so that we can test
+ // canvasframe invalidations by observing the documentElement.
+ for (;;) {
+ nsIFrame* parentFrame = frame->GetParent();
+ if (parentFrame && parentFrame->GetContent() == content) {
+ frame = parentFrame;
+ } else {
+ break;
+ }
+ }
+
+ *aResult = frame->CheckAndClearDisplayListState();
+ return NS_OK;
+
+}
+
+NS_IMETHODIMP
nsDOMWindowUtils::IsPartOfOpaqueLayer(nsIDOMElement* aElement, bool* aResult)
{
if (!aElement) {
return NS_ERROR_INVALID_ARG;
}
nsresult rv;
nsCOMPtr<nsIContent> content = do_QueryInterface(aElement, &rv);
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -1602,16 +1602,22 @@ interface nsIDOMWindowUtils : nsISupport
/**
* Check if any PaintedLayer painting has been done for this element,
* clears the painted flags if they have.
*/
boolean checkAndClearPaintedState(in nsIDOMElement aElement);
/**
+ * Check if any display list building has been done for this element,
+ * clears the display list flags if they have.
+ */
+ boolean checkAndClearDisplayListState(in nsIDOMElement aElement);
+
+ /**
* Check whether all display items of the primary frame of aElement have been
* assigned to the same single PaintedLayer in the last paint. If that is the
* case, returns whether that PaintedLayer is opaque; if it's not the case, an
* exception is thrown.
*/
boolean isPartOfOpaqueLayer(in nsIDOMElement aElement);
/**
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -384,16 +384,35 @@ nsIFrame::CheckAndClearPaintedState()
result = true;
}
}
}
return result;
}
bool
+nsIFrame::CheckAndClearDisplayListState()
+{
+ bool result = BuiltDisplayList();
+ SetBuiltDisplayList(false);
+
+ nsIFrame::ChildListIterator lists(this);
+ for (; !lists.IsDone(); lists.Next()) {
+ nsFrameList::Enumerator childFrames(lists.CurrentList());
+ for (; !childFrames.AtEnd(); childFrames.Next()) {
+ nsIFrame* child = childFrames.get();
+ if (child->CheckAndClearDisplayListState()) {
+ result = true;
+ }
+ }
+ }
+ return result;
+}
+
+bool
nsIFrame::IsVisibleConsideringAncestors(uint32_t aFlags) const
{
if (!StyleVisibility()->IsVisible()) {
return false;
}
const nsIFrame* frame = this;
while (frame) {
@@ -3182,16 +3201,18 @@ nsIFrame::BuildDisplayListForChild(nsDis
// Since we're now sure that we're adding this frame to the display list
// (which means we're painting it, modulo occlusion), mark it as visible
// within the displayport.
if (aBuilder->IsPaintingToWindow() && child->TrackingVisibility()) {
child->PresContext()->PresShell()->EnsureFrameInApproximatelyVisibleList(child);
awayFromCommonPath = true;
}
+ child->SetBuiltDisplayList(true);
+
// Child is composited if it's transformed, partially transparent, or has
// SVG effects or a blend mode..
EffectSet* effectSet = EffectSet::GetEffectSet(child);
const nsStyleDisplay* disp = child->StyleDisplay();
const nsStyleEffects* effects = child->StyleEffects();
const nsStylePosition* pos = child->StylePosition();
bool isVisuallyAtomic = child->IsVisuallyAtomic(effectSet, disp, effects);
bool isPositioned = disp->IsAbsPosContainingBlock(child);
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -620,16 +620,17 @@ public:
, mClass(aID)
, mMayHaveRoundedCorners(false)
, mHasImageRequest(false)
, mHasFirstLetterChild(false)
, mParentIsWrapperAnonBox(false)
, mIsWrapperBoxNeedingRestyle(false)
, mReflowRequestedForCharDataChange(false)
, mForceDescendIntoIfVisible(false)
+ , mBuiltDisplayList(false)
, mIsPrimaryFrame(false)
{
mozilla::PodZero(&mOverflow);
}
nsPresContext* PresContext() const {
return StyleContext()->PresContext();
}
@@ -3833,16 +3834,20 @@ public:
void MarkAsNotAbsoluteContainingBlock();
// Child frame types override this function to select their own child list name
virtual mozilla::layout::FrameChildListID GetAbsoluteListID() const { return kAbsoluteList; }
// Checks if we (or any of our descendents) have NS_FRAME_PAINTED_THEBES set, and
// clears this bit if so.
bool CheckAndClearPaintedState();
+ // Checks if we (or any of our descendents) have mBuiltDisplayList set, and
+ // clears this bit if so.
+ bool CheckAndClearDisplayListState();
+
// CSS visibility just doesn't cut it because it doesn't inherit through
// documents. Also if this frame is in a hidden card of a deck then it isn't
// visible either and that isn't expressed using CSS visibility. Also if it
// is in a hidden view (there are a few cases left and they are hopefully
// going away soon).
// If the VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY flag is passed then we
// ignore the chrome/content boundary, otherwise we stop looking when we
// reach it.
@@ -4086,16 +4091,19 @@ public:
bool HasDisplayItems();
bool HasDisplayItem(nsDisplayItem* aItem);
void DestroyAnonymousContent(already_AddRefed<nsIContent> aContent);
bool ForceDescendIntoIfVisible() { return mForceDescendIntoIfVisible; }
void SetForceDescendIntoIfVisible(bool aForce) { mForceDescendIntoIfVisible = aForce; }
+ bool BuiltDisplayList() { return mBuiltDisplayList; }
+ void SetBuiltDisplayList(bool aBuilt) { mBuiltDisplayList = aBuilt; }
+
protected:
/**
* Reparent this frame's view if it has one.
*/
void ReparentFrameViewTo(nsViewManager* aViewManager,
nsView* aNewParentView,
nsView* aOldParentView);
@@ -4254,25 +4262,33 @@ protected:
/**
* This bit is used during BuildDisplayList to mark frames that need to
* have display items rebuilt. We will descend into them if they are
* currently visible, even if they don't intersect the dirty area.
*/
bool mForceDescendIntoIfVisible : 1;
+ /**
+ * True if we have built display items for this frame since
+ * the last call to CheckAndClearDisplayListState, false
+ * otherwise. Used for the reftest harness to verify minimal
+ * display list building.
+ */
+ bool mBuiltDisplayList : 1;
+
private:
/**
* True if this is the primary frame for mContent.
*/
bool mIsPrimaryFrame : 1;
protected:
- // There is a 8-bit gap left here.
+ // There is a 7-bit gap left here.
// Helpers
/**
* Can we stop inside this frame when we're skipping non-rendered whitespace?
* @param aForward [in] Are we moving forward (or backward) in content order.
* @param aOffset [in/out] At what offset into the frame to start looking.
* on output - what offset was reached (whether or not we found a place to stop).
* @return STOP: An appropriate offset was found within this frame,
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/reftest.list
@@ -0,0 +1,9 @@
+skip-if(!retainedDisplayList) == retained-dl-style-change-1.html retained-dl-style-change-1-ref.html
+skip-if(!retainedDisplayList) == retained-dl-frame-deleted-1.html retained-dl-style-change-1-ref.html
+skip-if(!retainedDisplayList) == retained-dl-frame-created-1.html retained-dl-style-change-1-ref.html
+skip-if(!retainedDisplayList) == retained-dl-style-change-stacking-context-1.html retained-dl-style-change-stacking-context-1-ref.html
+skip-if(!retainedDisplayList||!asyncPan) == retained-dl-async-scrolled-1.html retained-dl-async-scrolled-1-ref.html
+skip-if(!retainedDisplayList) == retained-dl-remove-for-ancestor-change-1.html retained-dl-remove-for-ancestor-change-1-ref.html
+skip-if(!retainedDisplayList) == retained-dl-scroll-out-of-view-1.html retained-dl-scroll-out-of-view-1-ref.html
+skip-if(!retainedDisplayList) == retained-dl-displayport-1.html retained-dl-displayport-1-ref.html
+skip-if(!retainedDisplayList) == retained-dl-prerender-transform-1.html retained-dl-prerender-transform-1-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-async-scrolled-1-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+body {
+ margin: 0;
+}
+
+div {
+ left: 200px;
+ top: 200px;
+ position:absolute;
+}
+</style>
+</head>
+<body>
+<div style="width: 200px; height: 200px; background-color: blue;"></div>
+<div style="width: 100px; height: 100px; background-color: red;"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-async-scrolled-1.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html reftest-async-scroll
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-w="800" reftest-displayport-h="2000"
+ reftest-async-scroll-x="0" reftest-async-scroll-y="400"
+ class="reftest-wait">
+<head>
+
+<style>
+
+body {
+ margin: 0;
+ height: 4000px;
+ overflow:hidden;
+}
+
+div {
+ left: 200px;
+ top: 200px;
+ width: 200px;
+ height: 200px;
+}
+
+.scrolled {
+ position: absolute;
+ z-index: 1;
+}
+
+.fixed {
+ position: fixed;
+ background-color: red;
+}
+
+</style>
+</head>
+<body>
+
+<div class="scrolled reftest-no-display-list" style="top: 200px; background-color: green"></div>
+<div class="scrolled" style="top: 600px;" id="scrolled"></div>
+<div class="fixed" style="top: 200px"></div>
+<div class="fixed" style="top: 200px; width: 100px; height: 100px; z-index: 2"></div>
+
+</body>
+
+<script>
+function doTest() {
+ document.getElementById("scrolled").style.backgroundColor = "blue";
+ document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-displayport-1-ref.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+</head>
+<body>
+ <div id="container" style="width: 100px; height: 100px; overflow: auto;">
+ <div id="first" style="background-color:blue; width: 10px; height: 10px;"></div>
+ <div id="second" style="background-color:green; width: 10px; height: 10px;"></div>
+ <div id="spacer" style="height: 200px;"></div>
+ </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-displayport-1.html
@@ -0,0 +1,21 @@
+<html class="reftest-wait reftest-async-scroll">
+<head>
+</head>
+<body>
+ <div id="container" style="width: 100px; height: 100px; overflow: auto;"
+ reftest-displayport-x="0" reftest-displayport-y="0"
+ reftest-displayport-width="100" reftest-displayport-height="100">
+ <div id="first" style="background-color:blue; width: 10px; height: 10px;" class="reftest-no-display-list"></div>
+ <div id="second" style="background-color:red; width: 10px; height: 10px;"></div>
+ <div id="spacer" style="height: 200px;"></div>
+ </div>
+</body>
+<script>
+function doTest() {
+ document.getElementById("second").style.backgroundColor = "green";
+ document.documentElement.classList.remove("reftest-wait");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-frame-created-1.html
@@ -0,0 +1,25 @@
+<html class="reftest-wait">
+<head>
+<style>
+ div {
+ width:10px;
+ height:10px;
+ background-color:green;
+ display: inline-block;
+ }
+</style>
+</head>
+<body id="body">
+ <div id="first" class="reftest-no-display-list"></div>
+</body>
+<script>
+function doTest() {
+ var div = document.createElement("div");
+ var prev = document.getElementById("first");
+ prev.parentNode.insertBefore(div, prev.nextSibling);
+ document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-frame-deleted-1.html
@@ -0,0 +1,24 @@
+<html class="reftest-wait">
+<head>
+<style>
+ div {
+ width:10px;
+ height:10px;
+ background-color:green;
+ display: inline-block;
+ }
+</style>
+</head>
+<body id="body">
+ <div id="first" class="reftest-no-display-list"></div><div id="second" class="reftest-no-display-list"></div><div id="third"></div>
+</body>
+<script>
+function doTest() {
+ var elem = document.getElementById("third");
+ elem.parentNode.removeChild(elem);
+ document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-prerender-transform-1-ref.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<style>
+ * {
+ margin: 0px;
+ padding: 0px;
+ }
+ .inner {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+ display: inline-block;
+ }
+ body {
+ overflow: hidden;
+ }
+</style>
+</head>
+<body id="body">
+ <div id="transformed" style="transform:translateX(700px);">
+ <div id="first" class="inner"></div>
+ </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-prerender-transform-1.html
@@ -0,0 +1,36 @@
+<html class="reftest-wait">
+<head>
+<style>
+ * {
+ margin: 0px;
+ padding: 0px;
+ }
+ .inner {
+ width: 100px;
+ height: 100px;
+ background-color: green;
+ display: inline-block;
+ }
+ #third {
+ background-color: red;
+ }
+ body {
+ overflow: hidden;
+ }
+</style>
+</head>
+<body id="body">
+ <div id="transformed" style="transform:translateX(700px); will-change:transform;">
+ <div id="first" class="reftest-no-display-list inner"></div><div id="second" class="reftest-no-display-list inner"></div><div id="third" class="reftest-display-list inner"></div>
+ </div>
+</body>
+<script>
+function doTest() {
+ var third = document.getElementById("third")
+ third.style.backgroundColor = "green";
+ document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-remove-for-ancestor-change-1-ref.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+</head>
+<body>
+ <div id="container" style="height: 40px; overflow: hidden;">
+ <div id="spacer" style="height: 50px;"></div>
+ <div id="second" style="background-color:red; width: 10px; height: 10px;"></div>
+ </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-remove-for-ancestor-change-1.html
@@ -0,0 +1,18 @@
+<html class="reftest-wait">
+<head>
+</head>
+<body>
+ <div id="container" style="height: 100px; overflow: hidden;">
+ <div id="spacer" style="height: 50px;"></div>
+ <div id="second" style="background-color:red; width: 10px; height: 10px;"></div>
+ </div>
+</body>
+<script>
+function doTest() {
+ document.getElementById("container").style.height = "40px";
+ document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-scroll-out-of-view-1-ref.html
@@ -0,0 +1,8 @@
+<html>
+<head>
+</head>
+<body>
+ <div id="container" style="height: 100px; overflow: hidden;">
+ </div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-scroll-out-of-view-1.html
@@ -0,0 +1,18 @@
+<html class="reftest-wait">
+<head>
+</head>
+<body>
+ <div id="container" style="height: 100px; overflow: hidden;">
+ <div id="second" style="background-color:red; width: 10px; height: 10px;"></div>
+ <div id="spacer" style="height: 200px;"></div>
+ </div>
+</body>
+<script>
+function doTest() {
+ document.getElementById("container").scrollTop = 100;
+ document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-style-change-1-ref.html
@@ -0,0 +1,15 @@
+<html>
+<head>
+<style>
+ div {
+ width:10px;
+ height:10px;
+ background-color:green;
+ display: inline-block;
+ }
+</style>
+</head>
+<body id="body">
+ <div id="first"></div><div id="second"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-style-change-1.html
@@ -0,0 +1,23 @@
+<html class="reftest-wait">
+<head>
+<style>
+ div {
+ width:10px;
+ height:10px;
+ background-color:green;
+ display: inline-block;
+ }
+</style>
+</head>
+<body id="body">
+ <div id="first" class="reftest-no-display-list"></div><div id="second" style="background-color:red"></div>
+</body>
+<script>
+function doTest() {
+ document.getElementById("second").style.backgroundColor = "green";
+ document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-style-change-stacking-context-1-ref.html
@@ -0,0 +1,18 @@
+<html>
+<head>
+<style>
+ body {
+ margin: 0px;
+ }
+ div {
+ width:200px;
+ height:200px;
+ display: inline-block;
+ position: absolute;
+ }
+</style>
+</head>
+<body>
+ <div style="background-color:green"></div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/display-list/retained-dl-style-change-stacking-context-1.html
@@ -0,0 +1,33 @@
+<html class="reftest-wait">
+<head>
+<style>
+ body {
+ margin: 0px;
+ }
+ div {
+ width:100px;
+ height:100px;
+ display: inline-block;
+ position:absolute;
+ }
+</style>
+</head>
+<body>
+ <div id="first" style="background-color:green; width:200px; height:200px" class="reftest-no-display-list"></div>
+ <div style="transform:translateZ(1px)">
+ <div id="second" style="background-color:red"></div>
+ </div>
+ <div style="position:fixed; left:100px">
+ <div id="third" style="background-color:red"></div>
+ </div>
+</body>
+<script>
+function doTest() {
+ document.getElementById("second").style.backgroundColor = "green";
+ document.getElementById("third").style.backgroundColor = "green";
+ document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</html>
--- a/layout/reftests/reftest.list
+++ b/layout/reftests/reftest.list
@@ -438,10 +438,13 @@ include box-sizing/reftest.list
include invalidation/reftest.list
# encodings
include ../../dom/encoding/test/reftest/reftest.list
# APZ/async positioning tests
include ../../gfx/layers/apz/test/reftest/reftest.list
+# Display list building
+include display-list/reftest.list
+
# Media
include ../../dom/media/test/reftest/reftest.list
--- a/layout/tools/reftest/globals.jsm
+++ b/layout/tools/reftest/globals.jsm
@@ -123,16 +123,18 @@ for (let [key, val] of Object.entries({
drawWindowFlags: undefined,
expectingProcessCrash: false,
expectedCrashDumpFiles: [],
unexpectedCrashDumpFiles: {},
crashDumpDir: undefined,
pendingCrashDumpDir: undefined,
failedNoPaint: false,
+ failedNoDisplayList: false,
+ failedDisplayList: false,
failedOpaqueLayer: false,
failedOpaqueLayerMessages: [],
failedAssignedLayer: false,
failedAssignedLayerMessages: [],
startAfter: undefined,
suiteStarted: false,
--- a/layout/tools/reftest/manifest.jsm
+++ b/layout/tools/reftest/manifest.jsm
@@ -471,16 +471,19 @@ function BuildConditionSandbox(aURL) {
sandbox.webrender =
g.windowUtils.layerManagerType == "WebRender";
sandbox.layersOMTC =
g.windowUtils.layerManagerRemote == true;
sandbox.advancedLayers =
g.windowUtils.usingAdvancedLayers == true;
sandbox.layerChecksEnabled = !sandbox.webrender;
+ sandbox.retainedDisplayList =
+ prefs.getBoolPref("layout.display-list.retain");
+
// Shortcuts for widget toolkits.
sandbox.Android = xr.OS == "Android";
sandbox.cocoaWidget = xr.widgetToolkit == "cocoa";
sandbox.gtkWidget = xr.widgetToolkit == "gtk2"
|| xr.widgetToolkit == "gtk3";
sandbox.qtWidget = xr.widgetToolkit == "qt";
sandbox.winWidget = xr.widgetToolkit == "windows";
--- a/layout/tools/reftest/reftest-content.js
+++ b/layout/tools/reftest/reftest-content.js
@@ -435,16 +435,22 @@ function shouldSnapshotWholePage(content
contentRootElement.hasAttribute('class') &&
contentRootElement.getAttribute('class').split(/\s+/)
.indexOf("reftest-snapshot-all") != -1;
}
function getNoPaintElements(contentRootElement) {
return contentRootElement.getElementsByClassName('reftest-no-paint');
}
+function getNoDisplayListElements(contentRootElement) {
+ return contentRootElement.getElementsByClassName('reftest-no-display-list');
+}
+function getDisplayListElements(contentRootElement) {
+ return contentRootElement.getElementsByClassName('reftest-display-list');
+}
function getOpaqueLayerElements(contentRootElement) {
return contentRootElement.getElementsByClassName('reftest-opaque-layer');
}
function getAssignedLayerMap(contentRootElement) {
var layerNameToElementsMap = {};
var elements = contentRootElement.querySelectorAll('[reftest-assigned-layer]');
@@ -593,16 +599,24 @@ function WaitForTestEnd(contentRootEleme
var hasReftestWait = shouldWaitForReftestWaitRemoval(contentRootElement);
// Notify the test document that now is a good time to test some invalidation
LogInfo("MakeProgress: dispatching MozReftestInvalidate");
if (contentRootElement) {
var elements = getNoPaintElements(contentRootElement);
for (var i = 0; i < elements.length; ++i) {
windowUtils().checkAndClearPaintedState(elements[i]);
}
+ elements = getNoDisplayListElements(contentRootElement);
+ for (var i = 0; i < elements.length; ++i) {
+ windowUtils().checkAndClearDisplayListState(elements[i]);
+ }
+ elements = getDisplayListElements(contentRootElement);
+ for (var i = 0; i < elements.length; ++i) {
+ windowUtils().checkAndClearDisplayListState(elements[i]);
+ }
var notification = content.document.createEvent("Events");
notification.initEvent("MozReftestInvalidate", true, false);
contentRootElement.dispatchEvent(notification);
}
if (!inPrintMode && doPrintMode(contentRootElement)) {
LogInfo("MakeProgress: setting up print mode");
setupPrintMode();
@@ -692,16 +706,33 @@ function WaitForTestEnd(contentRootEleme
}
if (contentRootElement) {
var elements = getNoPaintElements(contentRootElement);
for (var i = 0; i < elements.length; ++i) {
if (windowUtils().checkAndClearPaintedState(elements[i])) {
SendFailedNoPaint();
}
}
+ // We only support retained display lists in the content process
+ // right now, so don't fail reftest-no-display-list tests when
+ // we don't have e10s.
+ if (gBrowserIsRemote) {
+ elements = getNoDisplayListElements(contentRootElement);
+ for (var i = 0; i < elements.length; ++i) {
+ if (windowUtils().checkAndClearDisplayListState(elements[i])) {
+ SendFailedNoDisplayList();
+ }
+ }
+ elements = getDisplayListElements(contentRootElement);
+ for (var i = 0; i < elements.length; ++i) {
+ if (!windowUtils().checkAndClearDisplayListState(elements[i])) {
+ SendFailedDisplayList();
+ }
+ }
+ }
CheckLayerAssertions(contentRootElement);
}
LogInfo("MakeProgress: Completed");
state = STATE_COMPLETED;
gFailureReason = "timed out while taking snapshot (bug in harness?)";
RemoveListeners();
CheckForProcessCrashExpectation();
setTimeout(RecordResult, 0);
@@ -1154,16 +1185,26 @@ function SendFailedLoad(why)
sendAsyncMessage("reftest:FailedLoad", { why: why });
}
function SendFailedNoPaint()
{
sendAsyncMessage("reftest:FailedNoPaint");
}
+function SendFailedNoDisplayList()
+{
+ sendAsyncMessage("reftest:FailedNoDisplayList");
+}
+
+function SendFailedDisplayList()
+{
+ sendAsyncMessage("reftest:FailedDisplayList");
+}
+
function SendFailedOpaqueLayer(why)
{
sendAsyncMessage("reftest:FailedOpaqueLayer", { why: why });
}
function SendFailedAssignedLayer(why)
{
sendAsyncMessage("reftest:FailedAssignedLayer", { why: why });
--- a/layout/tools/reftest/reftest.jsm
+++ b/layout/tools/reftest/reftest.jsm
@@ -1045,17 +1045,17 @@ function RecordResult(testRunTime, error
`(${g.urls[0].fuzzyMaxDelta}, ${g.urls[0].fuzzyMaxPixels})`);
fuzz_exceeded = maxDifference.value > g.urls[0].fuzzyMaxDelta ||
differences > g.urls[0].fuzzyMaxPixels;
equal = !fuzz_exceeded &&
maxDifference.value >= g.urls[0].fuzzyMinDelta &&
differences >= g.urls[0].fuzzyMinPixels;
}
- var failedExtraCheck = g.failedNoPaint || g.failedOpaqueLayer || g.failedAssignedLayer;
+ var failedExtraCheck = g.failedNoPaint || g.failedNoDisplayList || g.failedDisplayList || g.failedOpaqueLayer || g.failedAssignedLayer;
// whether the comparison result matches what is in the manifest
var test_passed = (equal == (g.urls[0].type == TYPE_REFTEST_EQUAL)) && !failedExtraCheck;
if (expected != EXPECTED_FUZZY) {
output = outputs[expected][test_passed];
} else if (test_passed) {
output = {s: ["PASS", "PASS"], n: "Pass"};
@@ -1082,16 +1082,22 @@ function RecordResult(testRunTime, error
// It's possible that we failed both an "extra check" and the normal comparison, but we don't
// have a way to annotate these separately, so just print an error for the extra check failures.
if (failedExtraCheck) {
var failures = [];
if (g.failedNoPaint) {
failures.push("failed reftest-no-paint");
}
+ if (g.failedNoDisplayList) {
+ failures.push("failed reftest-no-display-list");
+ }
+ if (g.failedDisplayList) {
+ failures.push("failed reftest-display-list");
+ }
// The g.failed*Messages arrays will contain messages from both the test and the reference.
if (g.failedOpaqueLayer) {
failures.push("failed reftest-opaque-layer: " + g.failedOpaqueLayerMessages.join(", "));
}
if (g.failedAssignedLayer) {
failures.push("failed reftest-assigned-layer: " + g.failedAssignedLayerMessages.join(", "));
}
var failureString = failures.join(", ");
@@ -1242,16 +1248,18 @@ function FinishTestItem()
// Replace document with BLANK_URL_FOR_CLEARING in case there are
// assertions when unloading.
logger.debug("Loading a blank page");
// After clearing, content will notify us of the assertion count
// and tests will continue.
SendClear();
g.failedNoPaint = false;
+ g.failedNoDisplayList = false;
+ g.failedDisplayList = false;
g.failedOpaqueLayer = false;
g.failedOpaqueLayerMessages = [];
g.failedAssignedLayer = false;
g.failedAssignedLayerMessages = [];
}
function DoAssertionCheck(numAsserts)
{
@@ -1327,16 +1335,24 @@ function RegisterMessageListenersAndLoad
"reftest:FailedLoad",
function (m) { RecvFailedLoad(m.json.why); }
);
g.browserMessageManager.addMessageListener(
"reftest:FailedNoPaint",
function (m) { RecvFailedNoPaint(); }
);
g.browserMessageManager.addMessageListener(
+ "reftest:FailedNoDisplayList",
+ function (m) { RecvFailedNoDisplayList(); }
+ );
+ g.browserMessageManager.addMessageListener(
+ "reftest:FailedDisplayList",
+ function (m) { RecvFailedDisplayList(); }
+ );
+ g.browserMessageManager.addMessageListener(
"reftest:FailedOpaqueLayer",
function (m) { RecvFailedOpaqueLayer(m.json.why); }
);
g.browserMessageManager.addMessageListener(
"reftest:FailedAssignedLayer",
function (m) { RecvFailedAssignedLayer(m.json.why); }
);
g.browserMessageManager.addMessageListener(
@@ -1398,16 +1414,26 @@ function RecvFailedLoad(why)
LoadFailed(why);
}
function RecvFailedNoPaint()
{
g.failedNoPaint = true;
}
+function RecvFailedNoDisplayList()
+{
+ g.failedNoDisplayList = true;
+}
+
+function RecvFailedDisplayList()
+{
+ g.failedDisplayList = true;
+}
+
function RecvFailedOpaqueLayer(why) {
g.failedOpaqueLayer = true;
g.failedOpaqueLayerMessages.push(why);
}
function RecvFailedAssignedLayer(why) {
g.failedAssignedLayer = true;
g.failedAssignedLayerMessages.push(why);