imcplugin demo: Extend to support stat() call
[nativeclient.git] / tests / mandel / mandel_tiled.html
blobce400f34859a0de33e8fa8c6913323939d5e1d05
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
2 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
3 <html>
4 <!-- Copyright 2008 Google Inc. All rights reserved. -->
5 <head>
6 <title> Mandelbrot: JavaScript versus Native Client </title>
7 <style type="text/css">
8 canvas { border:solid }
9 </style>
10 <script type='application/x-javascript'>
11 <!--
12 var plugin;
14 // A utility function to get the integer value of a user input field.
15 var getValue = function(id) {
16 var element = document.getElementById(id);
17 var value = element.value;
18 return parseInt(value);
21 // Compute the color for one pixel.
22 var mandelJavaScript = function(i, j, canvas_width) {
23 var cx = (4.0 / canvas_width) * i - 3.0;
24 var cy = 1.5 - (3.0 / canvas_width) * j;
25 var re = cx;
26 var im = cy;
27 var count = 0;
28 var threshold = 1.0e8;
29 while (count < 256 && re * re + im * im < threshold) {
30 var new_re = re * re - im * im + cx;
31 var new_im = 2 * re * im + cy;
32 re = new_re;
33 im = new_im;
34 ++count;
36 var r;
37 var g;
38 var b;
39 if (count < 8) {
40 r = 128;
41 g = 0;
42 b = 0;
43 } else if (count < 16) {
44 r = 255;
45 g = 0;
46 b = 0;
47 } else if (count < 32) {
48 r = 255;
49 g = 255;
50 b = 0;
51 } else if (count < 64) {
52 r = 0;
53 g = 255;
54 b = 0;
55 } else if (count < 128) {
56 r = 0;
57 g = 255;
58 b = 255;
59 } else if (count < 256) {
60 r = 0;
61 g = 0;
62 b = 255;
63 } else {
64 r = 0;
65 g = 0;
66 b = 0;
68 return [r, g, b];
71 // Compute the JavaScript mandelbrot picture and render into canvas.
72 var drawJavaScript = function(canvas_width, tile_width, context) {
73 var call_time = 0;
74 var canvas_time = 0;
75 for (var i = 0; i < canvas_width; ++i) {
76 for (var j = 0; j < canvas_width; ++j) {
77 var before_call = new Date();
78 var arr = mandelJavaScript(i, j, canvas_width);
79 var after_call = new Date();
80 var difftime = after_call.getTime() - before_call.getTime();
81 call_time += difftime;
82 before_call = new Date();
83 context.fillStyle = 'rgb(' + arr[0] + ',' + arr[1] + ',' + arr[2] + ')';
84 context.fillRect(i, j, 1, 1);
85 after_call = new Date();
86 difftime = after_call.getTime() - before_call.getTime();
87 canvas_time += difftime;
90 return [call_time, canvas_time];
93 // Compute and display the entire JavaScript mandelbrot picture, including
94 // printing the gathered timings.
95 var testJavaScript = function() {
96 // Set up the element where the time will be reported.
97 var time_element = document.getElementById('js_time');
98 time_element.innerHTML = '<b> JavaScript';
99 // Get the test parameters.
100 var canvas_width = getValue('canvas_width');
101 var tile_width = getValue('tile_width');
102 // Set up the canvas object and clear it.
103 var canvas = document.getElementById('js_canvas');
104 canvas.width = canvas_width;
105 canvas.height = canvas_width;
106 var context = canvas.getContext('2d');
107 context.fillStyle = 'rgb(0,0,0)';
108 context.fillRect(0, 0, canvas_width, canvas_width);
109 // Run the test.
110 var test_time = drawJavaScript(canvas_width, tile_width, context);
111 // Update the time element with compute and canvas manipulation times.
112 time_element.innerHTML = '<b> JavaScript <br>' +
113 'compute time: ' + test_time[0] + ' milliseconds<br>' +
114 'canvas time: ' + test_time[1] + ' milliseconds<br>';
117 // The Native Client version uses a shared memory object to return
118 // the computed rgb values for the canvas points. As the number of
119 // points may vary as a user configuration, the size of the shared
120 // memory object may vary.
121 var getSharedMemorySize = function(canvas_width) {
122 // The picture we are computing is a square. Each element in the region
123 // is a string like 'rgb(rrr,ggg,bbb)', or 16 bytes.
124 var min_size = canvas_width * canvas_width * 16;
125 // The minimum allocation size for Native Client shared memory regions is 64K.
126 var bytes = 65536;
127 // For convenience, we find the next power of two that holds the size.
128 for (; bytes < min_size; bytes *= 2);
129 return bytes;
132 // Compute the Native Client mandelbrot picture and render into canvas.
133 var drawNativeClient = function(canvas_width,
134 tile_width,
135 context,
136 plugin) {
137 // shm_size needs to be enough to keep 16 bytes per point.
138 var shm_size = getSharedMemorySize(canvas_width);
139 var shm = plugin.__shmFactory(shm_size);
140 var tiles_per_row = canvas_width / tile_width;
141 var call_time = 0;
142 var canvas_time = 0;
143 plugin.setup(shm);
144 for (var x = 0; x < canvas_width; x += tile_width) {
145 for (var y = 0; y < canvas_width; y += tile_width) {
146 var before_call = new Date();
147 plugin.tiled(x, y, tile_width, tiles_per_row);
148 var str = shm.read(0, tile_width * tile_width * 16);
149 var after_call = new Date();
150 var difftime = after_call.getTime() - before_call.getTime();
151 call_time += difftime;
152 var shmpos = 0;
153 before_call = new Date();
154 for (var i = x; i < x + tile_width; ++i) {
155 for (var j = y; j < y + tile_width; ++j) {
156 context.fillStyle = str.substring(shmpos, shmpos + 16);
157 shmpos += 16;
158 context.fillRect(i, j, 1, 1);
161 after_call = new Date();
162 difftime = after_call.getTime() - before_call.getTime();
163 canvas_time += difftime;
166 plugin.shutdown();
167 return [call_time, canvas_time];
170 // Compute and display the entire Native Client mandelbrot picture, including
171 // printing the gathered timings.
172 var testNativeClient = function() {
173 // Set up the element where the time will be reported.
174 var time_element = document.getElementById('nacl_time');
175 time_element.innerHTML = '<b>Native Client';
176 // Get the test parameters.
177 var canvas_width = getValue('canvas_width');
178 var tile_width = getValue('tile_width');
179 var tiles_per_row = canvas_width / tile_width;
180 // Set up the canvas object and clear it.
181 var canvas = document.getElementById('nacl_canvas');
182 canvas.width = canvas_width;
183 canvas.height = canvas_width;
184 var context = canvas.getContext('2d');
185 context.fillStyle = 'rgb(0,0,0)';
186 context.fillRect(0, 0, canvas_width, canvas_width);
187 // Get the Native Client plugin element.
188 var plugin = document.getElementById('nacl');
189 // Run the test.
190 var test_time = drawNativeClient(canvas_width,
191 tile_width,
192 context,
193 plugin);
194 // Update the time element with compute and canvas manipulation times.
195 time_element.innerHTML = '<b>Native Client<br>(' +
196 tiles_per_row * tiles_per_row + ' square tiles ' +
197 tile_width + ' pixels wide)<br>' +
198 'compute time: ' + test_time[0] + ' milliseconds<br>' +
199 'canvas time: ' + test_time[1] + ' milliseconds<br>';
202 // Before running tests we need to ensure the Native Client module is loaded.
203 var startupTimeout;
205 var RunTestsAfterLoad = function() {
206 if (plugin.__moduleReady) {
207 clearTimeout(startupTimeout);
208 // Do the tests one time by default.
209 testJavaScript();
210 testNativeClient();
211 } else {
212 if (plugin.__moduleReady == undefined) {
213 alert('The Native Client plugin was unable to load');
214 return;
216 startupTimeout = setTimeout(RunTestsAfterLoad, 100);
220 // The page begins by loading the Native Client module, mandel_tiled.nexe.
221 var Init = function() {
222 // Record the Native Client module that was returned so that we can
223 // invoke methods on it quickly.
224 plugin = document.getElementById('nacl');
225 // After ensuring the Native Client module has loaded, run the tests.
226 RunTestsAfterLoad();
229 </script>
230 </head>
231 <body onload="Init();">
232 <h1> Mandelbrot: JavaScript versus Tiled Native Client </h1>
233 <table cellpadding=5% summary="Control panel on left, images on right">
234 <tr>
235 <td valign=top>
236 <table border=5 cellpadding=5% summary="Values and buttons for control">
237 <tr>
238 <td colspan=2 align=center> <b> Control Panel </b> </td>
239 </tr>
240 <tr>
241 <td align=center> Canvas width <br/> (in pixels) </td>
242 <td>
243 <input type="text" value=100 size=5 id="canvas_width" />
244 </td>
245 </tr>
246 <tr>
247 <td align=center> Tile width <br/> (in pixels) </td>
248 <td>
249 <input type="text" value=100 size=5 id="tile_width" />
250 </td>
251 </tr>
252 <tr>
253 <td colspan=2 align=center>
254 <input type="button" onclick="testJavaScript()"
255 value="Run JavaScript" />
256 </td>
257 </tr>
258 <tr>
259 <td colspan=2 align=center>
260 <input type="button" onclick="testNativeClient()"
261 value="Run Native Client" />
262 </td>
263 </tr>
264 </table>
265 </td>
266 <td align=center valign=middle>
267 <canvas id="js_canvas" width="100" height="100">
268 <code> <em> JavaScript </em> </code>
269 </canvas>
270 </td>
271 <td align=center valign=middle>
272 <canvas id="nacl_canvas" width="100" height="100">
273 <code> <em> Native Client </em> </code>
274 </canvas>
275 </td>
276 </tr>
277 <tr>
278 <td> </td>
279 <td align=center id="js_time"></td>
280 <td align=center id="nacl_time"></td>
281 </tr>
282 </table>
284 First run starts automatically. Click afterwards to re-run. <br>
285 Warning: JavaScript with a canvas width of more than about 100 pixels
286 may run very slowly.
287 </b>
288 <br/>
289 <embed type="application/x-nacl-srpc" id="nacl"
290 src="mandel_tiled.nexe" hidden="true" />
291 </body>
292 </html>