Bug 876626 - Always redraw the entire reftest canvas for async animations tests. r=roc
authorMatt Woodrow <mwoodrow@mozilla.com>
Tue, 18 Jun 2013 19:59:46 +1200
changeset 135444 a2662face321193f133ebc4b29352622720ed298
parent 135443 0b87ce69f43fc7b9989b3c72df3ade772ab47c96
child 135445 ad0fa6692a65eef51e8e6ac7c40bd6a0f445e006
push id24841
push userryanvm@gmail.com
push dateTue, 18 Jun 2013 23:04:53 +0000
treeherdermozilla-central@d2a7cfa34154 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs876626
milestone24.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 876626 - Always redraw the entire reftest canvas for async animations tests. r=roc
layout/reftests/bugs/598726-1.html
layout/tools/reftest/reftest-content.js
layout/tools/reftest/reftest.js
--- a/layout/reftests/bugs/598726-1.html
+++ b/layout/reftests/bugs/598726-1.html
@@ -1,10 +1,10 @@
 <!DOCTYPE html>
-<html class="reftest-wait">
+<html class="reftest-wait reftest-snapshot-all">
   <head>
     <style type="text/css">
       input {
           -webkit-transition: -webkit-transform 200ms ease-in-out;
           transition: transform 200ms ease-in-out;
       }
       input:focus {
           -webkit-transform: scale(1.05);
@@ -26,17 +26,17 @@
           i.getClientRects();
           i.addEventListener("transitionend", function(aEvent) {
             if (aEvent.propertyName != 'transform' &&
                 aEvent.propertyName != '-webkit-transform') {
               return;
             }
             i.removeEventListener("transitionend", arguments.callee, true);
             i.getClientRects();
-            document.documentElement.removeAttribute("class");
+            document.documentElement.setAttribute("class", "reftest-snapshot-all");
           }, true);
           i.blur();
           i.getClientRects();
         }, true);
         i.focus();
         i.getClientRects();
       }
     </script>
--- a/layout/tools/reftest/reftest-content.js
+++ b/layout/tools/reftest/reftest-content.js
@@ -236,16 +236,24 @@ function shouldWaitForPendingPaints() {
 function shouldWaitForReftestWaitRemoval(contentRootElement) {
     // use getAttribute because className works differently in HTML and SVG
     return contentRootElement &&
            contentRootElement.hasAttribute('class') &&
            contentRootElement.getAttribute('class').split(/\s+/)
                              .indexOf("reftest-wait") != -1;
 }
 
+function shouldSnapshotWholePage(contentRootElement) {
+    // use getAttribute because className works differently in HTML and SVG
+    return contentRootElement &&
+           contentRootElement.hasAttribute('class') &&
+           contentRootElement.getAttribute('class').split(/\s+/)
+                             .indexOf("reftest-snapshot-all") != -1;
+}
+
 function getNoPaintElements(contentRootElement) {
   return contentRootElement.getElementsByClassName('reftest-no-paint');
 }
 
 // Initial state. When the document has loaded and all MozAfterPaint events and
 // all explicit paint waits are flushed, we can fire the MozReftestInvalidate
 // event and move to the next state.
 const STATE_WAITING_TO_FIRE_INVALIDATE_EVENT = 0;
@@ -301,17 +309,17 @@ function WaitForTestEnd(contentRootEleme
     function AfterPaintListener(event) {
         LogInfo("AfterPaintListener in " + event.target.document.location.href);
         if (event.target.document != currentDoc) {
             // ignore paint events for subframes or old documents in the window.
             // Invalidation in subframes will cause invalidation in the toplevel document anyway.
             return;
         }
 
-        SendUpdateCanvasForEvent(event);
+        SendUpdateCanvasForEvent(event, contentRootElement);
         // These events are fired immediately after a paint. Don't
         // confuse ourselves by firing synchronously if we triggered the
         // paint ourselves.
         setTimeout(MakeProgress, 0);
     }
 
     function AttrModifiedListener() {
         LogInfo("AttrModifiedListener fired");
@@ -835,22 +843,34 @@ function SendTestDone(runtimeMs)
     sendAsyncMessage("reftest:TestDone", { runtimeMs: runtimeMs });
 }
 
 function roundTo(x, fraction)
 {
     return Math.round(x/fraction)*fraction;
 }
 
-function SendUpdateCanvasForEvent(event)
+function SendUpdateCanvasForEvent(event, contentRootElement)
 {
     var win = content;
     var scale = markupDocumentViewer().fullZoom;
 
     var rects = [ ];
+    if (shouldSnapshotWholePage) {
+      // See comments in SendInitCanvasWithSnapshot() re: the split
+      // logic here.
+      if (!gBrowserIsRemote) {
+          sendSyncMessage("reftest:UpdateWholeCanvasForInvalidation");
+      } else {
+          SynchronizeForSnapshot(SYNC_ALLOW_DISABLE);
+          sendAsyncMessage("reftest:UpdateWholeCanvasForInvalidation");
+      }
+      return;
+    }
+    
     var rectList = event.clientRects;
     LogInfo("SendUpdateCanvasForEvent with " + rectList.length + " rects");
     for (var i = 0; i < rectList.length; ++i) {
         var r = rectList[i];
         // Set left/top/right/bottom to "device pixel" boundaries
         var left = Math.floor(roundTo(r.left*scale, 0.001));
         var top = Math.floor(roundTo(r.top*scale, 0.001));
         var right = Math.ceil(roundTo(r.right*scale, 0.001));
--- a/layout/tools/reftest/reftest.js
+++ b/layout/tools/reftest/reftest.js
@@ -1387,16 +1387,28 @@ function UpdateCurrentCanvasForInvalidat
 
         ctx.save();
         ctx.translate(left, top);
         DoDrawWindow(ctx, left, top, right - left, bottom - top);
         ctx.restore();
     }
 }
 
+function UpdateWholeCurrentCanvasForInvalidation()
+{
+    LogInfo("Updating entire canvas for invalidation");
+
+    if (!gCurrentCanvas) {
+        return;
+    }
+
+    var ctx = gCurrentCanvas.getContext("2d");
+    DoDrawWindow(ctx, 0, 0, gCurrentCanvas.width, gCurrentCanvas.height);
+}
+
 function RecordResult(testRunTime, errorMsg, scriptResults)
 {
     LogInfo("RecordResult fired");
 
     // Keep track of which test was slowest, and how long it took.
     if (testRunTime > gSlowestTestTime) {
         gSlowestTestTime = testRunTime;
         gSlowestTestURL  = gCurrentURL;
@@ -1786,16 +1798,20 @@ function RegisterMessageListenersAndLoad
         "reftest:TestDone",
         function (m) { RecvTestDone(m.json.runtimeMs); }
     );
     gBrowserMessageManager.addMessageListener(
         "reftest:UpdateCanvasForInvalidation",
         function (m) { RecvUpdateCanvasForInvalidation(m.json.rects); }
     );
     gBrowserMessageManager.addMessageListener(
+        "reftest:UpdateWholeCanvasForInvalidation",
+        function (m) { RecvUpdateWholeCanvasForInvalidation(); }
+    );
+    gBrowserMessageManager.addMessageListener(
         "reftest:ExpectProcessCrash",
         function (m) { RecvExpectProcessCrash(); }
     );
     gBrowserMessageManager.addMessageListener(
         "reftest:EnableAsyncScroll",
         function (m) { SetAsyncScroll(true); }
     );
 
@@ -1865,16 +1881,21 @@ function RecvTestDone(runtimeMs)
     RecordResult(runtimeMs, '', [ ]);
 }
 
 function RecvUpdateCanvasForInvalidation(rects)
 {
     UpdateCurrentCanvasForInvalidation(rects);
 }
 
+function RecvUpdateWholeCanvasForInvalidation()
+{
+    UpdateWholeCurrentCanvasForInvalidation();
+}
+
 function OnProcessCrashed(subject, topic, data)
 {
     var id;
     subject = subject.QueryInterface(CI.nsIPropertyBag2);
     if (topic == "plugin-crashed") {
         id = subject.getPropertyAsAString("pluginDumpID");
     } else if (topic == "ipc:content-shutdown") {
         id = subject.getPropertyAsAString("dumpID");