| OLD | NEW | 
|    1 <!DOCTYPE HTML> |    1 <!DOCTYPE HTML> | 
|    2  |    2  | 
|    3 <!-- READ BEFORE UPDATING: |    3 <!-- READ BEFORE UPDATING: | 
|    4 If this test is updated make sure to increment the "revision" value of the |    4 If this test is updated make sure to increment the "revision" value of the | 
|    5 associated test in content/test/gpu/gpu_tests/pixel_test_pages.py. This will ens
     ure |    5 associated test in content/test/gpu/gpu_tests/pixel_test_pages.py. This will ens
     ure | 
|    6 that the baseline images are regenerated on the next run. |    6 that the baseline images are regenerated on the next run. | 
|    7 --> |    7 --> | 
|    8  |    8  | 
|    9 <html> |    9 <html> | 
|   10 <head> |   10 <head> | 
|   11 <title>OffscreenCanvas 2d commit flow on worker thread: Four-color square on whi
     te background.</title> |   11 <title>OffscreenCanvas 2d commit flow on worker thread: Two Canvases</title> | 
|   12 <style type="text/css"> |   12 <style type="text/css"> | 
|   13 .nomargin { |   13 .nomargin { | 
|   14   margin: 0px auto; |   14   margin: 0px auto; | 
|   15 } |   15 } | 
|   16 </style> |   16 </style> | 
|   17 <script id="myWorker" type="text/worker"> |   17 <script id="myWorker" type="text/worker"> | 
 |   18 /* This pixel test checks the following: | 
 |   19     1. Whether submission of frames for multiple canvases happen about the same | 
 |   20        time for OffscreenCanvas.commit() that are invoked in the same JS task. | 
 |   21     2. Whether overdraw frame in one animation loop is handled well. | 
 |   22     3. Whether the drawn 2d image is position upright in commit(). | 
 |   23     4. Drawing to OffscreenCanvas without commit() has no rendering results. | 
|   18  |   24  | 
|   19 var g_offscreen2d; |   25     Correct end result of this test: The left canvas shows a seven-spike skyblue | 
|   20 var g_animationFrameNumber = 0; |   26     star on the top-left corner of a green background and the right canvas shows | 
 |   27     a sky-blue fill. | 
 |   28 */ | 
 |   29 var g_ctx1, g_ctx2; | 
 |   30 var g_asyncCallbackNumber = 2; | 
|   21  |   31  | 
|   22 self.onmessage = function(e) { |   32 self.onmessage = function(e) { | 
|   23   var transferredCanvas = e.data; |   33   g_ctx1 = e.data.offscreenCanvas1.getContext("2d"); | 
|   24   g_offscreen2d = transferredCanvas.getContext("2d"); |   34   g_ctx2 = e.data.offscreenCanvas2.getContext("2d"); | 
|   25   g_offscreen2d.fillStyle = "red"; |   35  | 
|   26   g_offscreen2d.fillRect(0, 0, 200, 200); |   36   startTest(); | 
|   27   drawLoop(); |  | 
|   28 }   |   37 }   | 
|   29  |   38  | 
|   30 function drawLoop() |   39 function startTest() { | 
|   31 { |   40   g_ctx1.fillStyle = "green"; | 
|   32   if (g_animationFrameNumber < 10) { |   41   g_ctx1.fillRect(0, 0, 300, 300); | 
|   33     g_animationFrameNumber++; |   42   // The promise returned by this g_ctx1.commit() must be resolved at | 
|   34     // Purposely intersperse overdraw and non-overdraw commit cases to see |   43   // about the same time as the other g_ctx2.commit() below as they are in the | 
|   35     // if OffscreenCanvas commit() handles both cases well. |   44   // same JS task. | 
|   36     if (0 == g_animationFrameNumber % 2) { |   45   g_ctx1.commit().then(function() { | 
|   37       // When promise is used, the next drawLoop() is called after the first |   46     g_ctx2.fillRect(0, 0, 300, 300); | 
|   38       // frame is resolved; therefore there is no overdraw in this case. |   47     // This g_ctx2.commit() must happen after the other g_ctx2.commit() below. | 
|   39       g_offscreen2d.commit().then(drawLoop); |   48     g_ctx2.commit(); | 
|   40     } else { |   49     if (--g_asyncCallbackNumber == 0) self.postMessage(""); | 
|   41       // When the next drawLoop() is invoked regardless the promise resolve |   50   }); | 
|   42       // status of the previous commit(), the frame committed in the next |   51  | 
|   43       // drawLoop() is very likely to be overdrawn. |   52   function drawStar(ctx, cx, cy, spikes, outerRadius, innerRadius) { | 
|   44       g_offscreen2d.commit(); |   53     var rot = Math.PI / 2 * 3; | 
|   45       drawLoop(); |   54     var x = cx; | 
 |   55     var y = cy; | 
 |   56     var step = Math.PI / spikes; | 
 |   57  | 
 |   58     ctx.beginPath(); | 
 |   59     ctx.moveTo(cx, cy - outerRadius); | 
 |   60     for (i = 0; i < spikes; i++) { | 
 |   61       x = cx + Math.cos(rot) * outerRadius; | 
 |   62       y = cy + Math.sin(rot) * outerRadius; | 
 |   63       ctx.lineTo(x, y); | 
 |   64       rot += step; | 
 |   65  | 
 |   66       x = cx + Math.cos(rot) * innerRadius; | 
 |   67       y = cy + Math.sin(rot) * innerRadius; | 
 |   68       ctx.lineTo(x, y); | 
 |   69       rot += step; | 
|   46     } |   70     } | 
|   47   } else { |   71     ctx.lineTo(cx, cy - outerRadius); | 
|   48     g_offscreen2d.fillStyle = "red"; |   72     ctx.closePath(); | 
|   49     g_offscreen2d.fillRect(0, 0, 100, 100); |   73     ctx.lineWidth = 5; | 
|   50     g_offscreen2d.fillStyle = "green"; |   74     ctx.strokeStyle = 'black'; | 
|   51     g_offscreen2d.fillRect(100, 0, 100, 100); |   75     ctx.stroke(); | 
|   52     g_offscreen2d.fillStyle = "blue"; |   76     ctx.fillStyle = 'skyblue'; | 
|   53     g_offscreen2d.fillRect(0, 100, 100, 100); |   77     ctx.fill(); | 
|   54     g_offscreen2d.fillStyle = "black"; |   78   } | 
|   55     g_offscreen2d.fillRect(100, 100, 100, 100); |   79  | 
|   56     g_offscreen2d.commit() |   80   // Do something complex to g_ctx2. | 
 |   81   g_ctx2.fillStyle = "blue"; | 
 |   82   g_ctx2.fillRect(0, 0, 300, 300); | 
 |   83   drawStar(g_ctx2, 150, 150, 25, 80, 60); | 
 |   84   // This g_ctx2.commit() must be resolved at about the same time as the first | 
 |   85   // g_ctx1.commit() above because they are in the same JS task, no matter how | 
 |   86   // complex the drawing operation is. | 
 |   87   g_ctx2.commit().then(function() { | 
 |   88     drawStar(g_ctx1, 100, 100, 7, 80, 30); | 
 |   89     g_ctx1.commit(); | 
|   57  |   90  | 
|   58     // The following fill is never committed |   91     // The following fill is never committed | 
|   59     g_offscreen2d.fillStyle = "blue"; |   92     g_ctx1.fillStyle = "red"; | 
|   60     g_offscreen2d.fillRect(0, 0, 200, 200);     |   93     g_ctx1.fillRect(0, 0, 200, 200); | 
|   61     self.postMessage(""); |   94     if (--g_asyncCallbackNumber == 0) self.postMessage(""); | 
|   62   } |   95   }); | 
 |   96  | 
|   63 } |   97 } | 
 |   98  | 
|   64 </script> |   99 </script> | 
|   65 <script> |  100 <script> | 
|   66 var g_swapsBeforeAck = 15; |  101 var g_swapsBeforeAck = 15; | 
|   67  |  102  | 
|   68 function makeWorker(script) |  103 function makeWorker(script) | 
|   69 { |  104 { | 
|   70    var blob = new Blob([script]); |  105    var blob = new Blob([script]); | 
|   71    return new Worker(URL.createObjectURL(blob)); |  106    return new Worker(URL.createObjectURL(blob)); | 
|   72 } |  107 } | 
|   73  |  108  | 
|   74 function waitForFinish() |  109 function waitForFinish() | 
|   75 { |  110 { | 
|   76   if (g_swapsBeforeAck == 0) { |  111   if (g_swapsBeforeAck == 0) { | 
|   77     domAutomationController.setAutomationId(1); |  112     domAutomationController.setAutomationId(1); | 
|   78     domAutomationController.send("SUCCESS"); |  113     domAutomationController.send("SUCCESS"); | 
|   79   } else { |  114   } else { | 
|   80     g_swapsBeforeAck--; |  115     g_swapsBeforeAck--; | 
|   81     document.getElementById('container').style.zIndex = g_swapsBeforeAck + 1; |  116     document.getElementById('container').style.zIndex = g_swapsBeforeAck + 1; | 
|   82     window.requestAnimationFrame(waitForFinish); |  117     requestAnimationFrame(waitForFinish); | 
|   83   } |  118   } | 
|   84 } |  119 } | 
|   85  |  120  | 
|   86 function main() |  121 function main() | 
|   87 { |  122 { | 
|   88   var canvas2D = document.getElementById("c"); |  123   var offscreenCanvas1 = document.getElementById("canvas1").transferControlToOff
     screen(); | 
|   89   var offscreenCanvas = canvas2D.transferControlToOffscreen(); |  124   var offscreenCanvas2 = document.getElementById("canvas2").transferControlToOff
     screen(); | 
 |  125    | 
|   90   var worker = makeWorker(document.getElementById("myWorker").textContent); |  126   var worker = makeWorker(document.getElementById("myWorker").textContent); | 
|   91   worker.onmessage = function (e) { |  127   worker.onmessage = function (e) { | 
|   92       waitForFinish(); |  128       waitForFinish(); | 
|   93   }; |  129   }; | 
|   94   worker.postMessage(offscreenCanvas, [offscreenCanvas]); |  130   worker.postMessage( | 
 |  131       {offscreenCanvas1: offscreenCanvas1, | 
 |  132        offscreenCanvas2: offscreenCanvas2}, | 
 |  133       [offscreenCanvas1, offscreenCanvas2]); | 
|   95 } |  134 } | 
|   96 </script> |  135 </script> | 
|   97 </head> |  136 </head> | 
|   98 <body onload="main()"> |  137 <body onload="main()"> | 
|   99 <div style="position:relative; width:300px; height:300px; background-color:white
     "> |  138 <div style="position:relative; width:600px; height:300px; background-color:white
     "> | 
|  100 </div> |  139 </div> | 
|  101 <div id="container" style="position:absolute; top:0px; left:0px"> |  140 <div id="container" style="position:absolute; top:0px; left:0px"> | 
|  102 <canvas id="c" width="200" height="200" class="nomargin"></canvas> |  141 <canvas id="canvas1" width="300" height="300" class="nomargin"></canvas> | 
 |  142 <canvas id="canvas2" width="300" height="300" class="nomargin"></canvas> | 
|  103 </div> |  143 </div> | 
|  104 </body> |  144 </body> | 
|  105 </html> |  145 </html> | 
| OLD | NEW |