@@ -26,40 +26,45 @@ function readString(addr, len) {
2626}
2727
2828// 1 byte for making and 8 bytes for data (64 bits)
29- let pendingAnswer = new SharedArrayBuffer ( 9 ) ;
29+ let pendingAnswer = new SharedArrayBuffer ( 12 ) ;
3030/**
3131 @param {string } type The type of the answer, can only be "int"
3232**/
3333function waitForAnswer ( type ) {
3434 const WAITING = 0 ;
3535 const DONE = 1 ;
36-
37- const view = new DataView ( pendingAnswer ) ;
38- view . setUint8 ( 0 , WAITING ) ;
39- while ( view . getUint8 ( 0 ) != DONE ) {
40- wait ( 10 ) ;
36+ if ( type == "bool" ) {
37+ return waitForAnswer ( "int" ) != 0 ;
4138 }
39+
40+ const view = new Int32Array ( pendingAnswer ) ;
41+ view [ 0 ] = WAITING ;
42+ // while (view.getUint8(0) != DONE) {
43+ // wait(10);
44+ // }
45+ Atomics . wait ( view , 0 , WAITING ) ;
4246
4347 switch ( type ) {
4448 case "int" :
45- const int = view . getUint32 ( 5 , true ) << 32 | view . getUint32 ( 1 , true ) ;
46- console . log ( "Received answer " + int ) ;
49+ const int = view [ 1 ] << 32 | view [ 2 ] ;
4750 return int ;
4851 }
4952
5053 throw Error ( "Type invalid (" + type + ")" ) ;
5154}
5255
56+ /**
57+ Shared array buffer used for sleeping with Atomics.wait()
58+ **/
59+ const AB = new Int32Array ( new SharedArrayBuffer ( 4 ) ) ;
5360/**
5461 @param {int } msecs Time to wait in milliseconds
5562**/
5663function wait ( msecs ) {
5764 const start = Date . now ( ) ;
58- while ( Date . now ( ) > = start + msecs ) {
59- // Wait.
65+ while ( Date . now ( ) < = start + msecs ) {
66+ Atomics . wait ( AB , 0 , 0 , msecs - ( Date . now ( ) - start ) ) ;
6067 }
61-
62- return ;
6368}
6469
6570const memory = new WebAssembly . Memory ( {
@@ -114,99 +119,54 @@ const env = {
114119 return Date . now ( ) ;
115120 } ,
116121 hasEvent : function ( ) {
117- return pendingEvents . length > 0 ;
122+ self . postMessage ( [ "hasEvent" ] ) ;
123+ return waitForAnswer ( "bool" ) ;
118124 } ,
119125 popEvent : function ( ) {
120- if ( pendingEvents . length > 0 ) {
121- return pendingEvents . shift ( ) ;
122- } else {
123- console . error ( "Popping event even though none is available!" ) ;
124- }
126+ self . postMessage ( [ "popEvent" ] ) ;
127+ return waitForAnswer ( "int" ) ;
125128 } ,
126129 getEventType : function ( event ) {
127- return events [ event ] . type ;
130+ self . postMessage ( [ "getEventType" , event ] ) ;
131+ return waitForAnswer ( "int" ) ;
128132 } ,
129133 getEventTarget : function ( event ) {
130- if ( events [ event ] . target === undefined ) {
131- console . error ( "Tried getting the target of a global event" ) ;
132- }
133- return events [ event ] . target ;
134+ self . postMessage ( [ "getEventTarget" , event ] ) ;
135+ return waitForAnswer ( "int" ) ;
134136 } ,
135137 getEventArg : function ( event , idx ) {
136- if ( events [ event ] . args === undefined || events [ event ] . args [ idx ] === undefined ) {
137- console . error ( "Tried getting non-existent arg:" + idx ) ;
138- }
139- return events [ event ] . args [ idx ] ;
138+ self . postMessage ( [ "getEventArg" , event , idx ] ) ;
139+ return waitForAnswer ( "int" ) ;
140140 } ,
141141
142142 // Canvas
143143 openContext : function ( element ) {
144- const canvas = domObjects [ element ] ;
145- canvas . width = window . devicePixelRatio * canvas . clientWidth ;
146- canvas . height = window . devicePixelRatio * canvas . clientHeight ;
147-
148- for ( ctxId in canvasContexts ) {
149- if ( canvasContexts [ ctxId ] . owner === element ) {
150- canvasContexts [ ctxId ] . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
151- return ctxId ;
152- }
153- }
154- const ctx = canvas . getContext ( "2d" ) ;
155- ctx . owner = element ;
156- ctx . lineWidth = 2.5 ;
157- ctx . beginPath ( ) ;
158- return canvasContexts . push ( ctx ) - 1 ;
144+ self . postMessage ( [ "openContext" , element ] ) ;
145+ return waitForAnswer ( "int" ) ;
159146 } ,
160147 setColor : function ( ctx , r , g , b , a ) {
161- canvasContexts [ ctx ] . fillStyle = "rgba(" + r + "," + g + "," + b + "," + a + ")" ;
162- canvasContexts [ ctx ] . strokeStyle = canvasContexts [ ctx ] . fillStyle ;
148+ self . postMessage ( [ "setColor" , ctx , r , g , b , a ] ) ;
163149 } ,
164150 rectPath : function ( ctx , x , y , w , h ) {
165- canvasContexts [ ctx ] . rect ( x , y , w , h ) ;
151+ self . postMessage ( [ "rectPath" , ctx , x , y , w , h ] ) ;
166152 } ,
167153 moveTo : function ( ctx , x , y ) {
168- canvasContexts [ ctx ] . moveTo ( x , y ) ;
154+ self . postMessage ( [ "moveTo" , ctx , x , y ] ) ;
169155 } ,
170156 lineTo : function ( ctx , x , y ) {
171- canvasContexts [ ctx ] . lineTo ( x , y ) ;
157+ self . postMessage ( [ "lineTo" , ctx , x , y ] ) ;
172158 } ,
173159 fillText : function ( ctx , textPtr , textLen , x , y ) {
174- const text = readString ( textPtr , textLen ) ;
175- canvasContexts [ ctx ] . textAlign = "left" ;
176- canvasContexts [ ctx ] . textBaseline = "top" ;
177- canvasContexts [ ctx ] . fillText ( text , x , y ) ;
160+ throw new Error ( "TODO: fill text" ) ;
178161 } ,
179162 fillImage : function ( ctx , img , x , y ) {
180- const canvas = canvasContexts [ ctx ] ;
181- const image = resources [ img ] ;
182- if ( ! image . imageDatas [ ctx ] ) {
183- image . imageDatas [ ctx ] = canvas . createImageData ( image . width , image . height ) ;
184- const data = image . imageDatas [ ctx ] . data ;
185- const Bpp = image . stride / image . width ; // source bytes per pixel
186- for ( let y = 0 ; y < image . height ; y ++ ) {
187- for ( let x = 0 ; x < image . width ; x ++ ) {
188- data [ y * image . width * 4 + x * 4 + 0 ] = image . bytes [ y * image . stride + x * Bpp + 0 ] ;
189- data [ y * image . width * 4 + x * 4 + 1 ] = image . bytes [ y * image . stride + x * Bpp + 1 ] ;
190- data [ y * image . width * 4 + x * 4 + 2 ] = image . bytes [ y * image . stride + x * Bpp + 2 ] ;
191- if ( ! image . isRgb ) {
192- data [ y * image . width * 4 + x * 4 + 3 ] = image . bytes [ y * image . stride + x * Bpp + 3 ] ;
193- } else {
194- data [ y * image . width * 4 + x * 4 + 3 ] = 0xFF ;
195- }
196- }
197- }
198- image . bytes = undefined ; // try to free up some space
199- resources [ img ] = image ;
200- }
201- canvas . putImageData ( image . imageDatas [ ctx ] , x , y ) ;
163+ self . postMessage ( [ "fillImage" , ctx , img , x , y ] ) ;
202164 } ,
203165 fill : function ( ctx ) {
204- canvasContexts [ ctx ] . fill ( ) ;
205- canvasContexts [ ctx ] . beginPath ( ) ;
166+ self . postMessage ( [ "fill" , ctx ] ) ;
206167 } ,
207168 stroke : function ( ctx ) {
208- canvasContexts [ ctx ] . stroke ( ) ;
209- canvasContexts [ ctx ] . beginPath ( ) ;
169+ self . postMessage ( [ "stroke" , ctx ] ) ;
210170 } ,
211171
212172 // Resources
@@ -256,7 +216,11 @@ const env = {
256216
257217 return slice . length ;
258218 } ,
259-
219+ yield : function ( ) {
220+ // TODO: use Atomics.wait to wait until there is an event (if step is Blocking)
221+ // or to wait until requestAnimationFrame is called (if step is Asynchronous)
222+ wait ( 32 ) ;
223+ } ,
260224 stopExecution : function ( ) {
261225 postMessage ( [ "stopExecution" ] ) ;
262226 } ,
0 commit comments