Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Streamline demo setup; update README to reflect API changes. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | ferrieux-nacl |
Files: | files | file ages | folders |
SHA1: |
91aea72dbdaf8b5f83a5efc218fcfe3d |
User & Date: | ferrieux 2011-10-18 22:03:19 |
Context
2011-10-25
| ||
04:21 | Add a local copy of reference JS demo at same fps. Add an interactive tclsh page for easy timings, i... Leaf check-in: 29517d12f7 user: ferrieux tags: ferrieux-nacl | |
2011-10-18
| ||
22:03 | Streamline demo setup; update README to reflect API changes. check-in: 91aea72dbd user: ferrieux tags: ferrieux-nacl | |
06:33 | Update to new (incompatible, stabilized) ABI. Now requires Chrome 15 or above. check-in: d6b778727b user: ferrieux tags: ferrieux-nacl | |
Changes
Changes to nacl/Makefile.patch.
︙ | ︙ | |||
59 60 61 62 63 64 65 | all: binaries libraries doc packages -binaries: ${LIB_FILE} $(STUB_LIB_FILE) ${TCL_EXE} +binaries: ${LIB_FILE} $(STUB_LIB_FILE) tcl$(arch).nexe libraries: | | > > > > > > | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | all: binaries libraries doc packages -binaries: ${LIB_FILE} $(STUB_LIB_FILE) ${TCL_EXE} +binaries: ${LIB_FILE} $(STUB_LIB_FILE) tcl$(arch).nexe libraries: @@ -634,14 +646,36 @@ # Must be empty so it doesn't conflict with rule for ${TCL_EXE} above ${NATIVE_TCLSH}: -Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in - $(SHELL) config.status +init.tcl.c: ../library/init.tcl init.natcl + cat $^ | tools/tocstr > $@ + +tclUnixPort.h: ../unix/tclUnixPort.h tclUnixPort.h.patch + cat ../unix/tclUnixPort.h > tclUnixPort.h + patch -p0 < tclUnixPort.h.patch + +naclMain.o: naclMain.c init.tcl.c + $(CC) -c $(CC_SWITCHES) naclMain.c + +tcl$(arch).nexe: naclMain.o libtcl8.6.a + $(CCPLUS) $^ $(LDFLAGS) -o $@ + +$(TCL_OBJS) $(STUB_LIB_OBJS) $(TCLSH_OBJS) $(TCLTEST_OBJS): tclUnixPort.h + +server: + tclsh trivhttpd.tcl 5103 & + +balls: + google-chrome http://localhost:5103/demo/balls.html + +#Makefile: $(UNIX_DIR)/Makefile.in $(DLTEST_DIR)/Makefile.in +# $(SHELL) config.status #tclConfig.h: $(UNIX_DIR)/tclConfig.h.in # $(SHELL) config.status clean: clean-packages rm -f *.a *.o libtcl* core errs *~ \#* TAGS *.E a.out \ |
︙ | ︙ |
Changes to nacl/README.
︙ | ︙ | |||
13 14 15 16 17 18 19 | browser (currently, Chrome only; in the future, other browsers too), one could develop client-side code mainly in Tcl, with a very thin layer of JS in the page; so, basically, Tcl to control the HTML5 DOM ! Building Tcl for Nacl --------------------- | | > | > | | > > | | | < < | | | | < | < | < < < < < < < | | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | browser (currently, Chrome only; in the future, other browsers too), one could develop client-side code mainly in Tcl, with a very thin layer of JS in the page; so, basically, Tcl to control the HTML5 DOM ! Building Tcl for Nacl --------------------- - install the NaCl SDK at http://code.google.com/chrome/nativeclient/docs/download.html - for now, only use the pepper_14 bundle - add (Nacl-SDK-top-dir)/pepper_14/native_client_sdk_0_5_1052/toolchain/linux_x86/bin to your PATH - cd (Tcl-source-tree)/nacl - run './configure' (which calls ../unix/configure with proper flags, and patches the generated Makefile) - run 'make binaries'. This creates tcl.nmf and tcl32.nexe or tcl64.nexe, depending on the kind of x86 you're currently on. You can also simply type 'make' but the libraries are not usable by NaCl yet (no dynamic linking). - (optional) to also build the other kind, do 'make distclean', then './configure -m32 (or -m64)', then 'make binaries'. The provided manifest file (tcl.nmf) points to both, to be compatible with both builds of Chrome. - run 'make sever'. This starts (on port 5103) a tiny, trivial httpd written in Tcl, whose sole purpose is to server the few demo files. Note that NaCl is explicitly disabled on file:// urls. - (once) open about:flags in Chrome and enable Native Client (note this will be saved in your per-user Chrome preferences and will even survive a Chrome upgrade) - run 'make balls' Overview of the porting method ------------------------------ Nacl comes with a very incomplete libc and set of headers. The strategy, then, is to simply "plug" missing syscalls or library functions with either explicitly failing stubs (returning -1 or NULL, |
︙ | ︙ | |||
72 73 74 75 76 77 78 | This approach allows to compile Tcl for Nacl without changing a single line of the original source distribution; all new things are in the nacl subdir. Also, much is reused from ../unix. Nacl context specifics ---------------------- | | < | | > | > | > > | < | < < | | | | | 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | This approach allows to compile Tcl for Nacl without changing a single line of the original source distribution; all new things are in the nacl subdir. Also, much is reused from ../unix. Nacl context specifics ---------------------- NaCl lets us run in our sandbox, in a dedicated process; the only possible interactions with the browser process are: - at init time, one of our functions is called - then, each side can post a string message to the other one - on reception, a callback is called with the string as argument. This happens on each side's single thread. This asynchronous communication method ensures that the JS context will never be blocked, whatever the sandboxed child does. For maximal genericity, the way NaTcl "retroacts" on the JS context is by posting back a JS string to eval(). Then you can do whatever you want, including of course arranging for future JS events to call back into NaTcl. See [domset] and [after] (in init.natcl, which is compiled into the binray .nexe) as two very simple examples. In an universe without syscalls, loading other scripts is problematic. To circumvent this (and bootstrap the loading of the main script), [source $url] is reimplemented over a JS XmlHttpRequest. And to preserve the blocking semantics of traditional [source] while XHR is purely async, this implementation is coroutine-based and calls [yield] after starting the request. When the download completes, JS |
︙ | ︙ | |||
111 112 113 114 115 116 117 | This means that all the init code in the script will run in the coro context (for [source]'s benefit, but that could be extended to other things). But once the execution has fallen back out of the main script, hopefully after setting up many (JS) event handlers, it is up to the app to establish other coro contexts if needed. | | | | > > > < | | > | | | | | | 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | This means that all the init code in the script will run in the coro context (for [source]'s benefit, but that could be extended to other things). But once the execution has fallen back out of the main script, hopefully after setting up many (JS) event handlers, it is up to the app to establish other coro contexts if needed. A few things about GUI and blocking: - a simple, ol'good-Tk-style event-driven script will work as usual - lengthy computations on the Tcl side will *not* block the JS's side autonomous GUI elements, thanks to the new async interaction described above - however, to be able ot interrupt the computation from the GUI, or to have Tcl code implement part of the GUI reactions, one must of course let the Tcl code return quickly. - in all cases, [source] works as usual to fetch scripts over HTTP (in the same domain as the page serving the NaTcl plugin). Relative URLs work: [source foo.natcl]. - in all cases, falling back out of the main scripts is equivalent to going back to the Tk eventloop in wish (except it is the JS eventloop). The "Google Balls" demo ----------------------- If you point your chrome to "demo/balls.html" (eg with 'make balls'), you'll get a full NaTcl emulation of the nice Javascript demo at: http://www.html5canvastutorials.com/labs/html5-canvas-google-bouncing-balls This uses a canvas emulation script "canv.natcl", which demonstrates a possible (among many) way of organizing Tcl-JS interaction for graphics. In the balls demo, items are never destroyed nor shuffled, which is a favourable case for lazy recompilation of the JS repaint function (basically the func is written just once, and only the coords stored in a global array get updated, hence allowing for JIT compiling of this function). Perf measurements: the NaTcl version currently costs 3x the CPU of the JS version, so at 40fps it consumes a full core of my 2GHz laptop (against 33% for the JS one). One should note that the pure string API used currently precludes any use of the internal reps of coordinates, so there are many string/integer conversions. To be continued. Comparison with native Tcl/Tk ----------------------------- With the command 'tools/natcl2tk balls.natcl', you can run the same code in pure Tcl/Tk, in a true wish canvas. You can use it for performance and rendering comparisons. Future work ----------- Coming soon: [domget], more [canvas] features, and optimizations ;-) |
Changes to nacl/demo/balls.html.
︙ | ︙ | |||
10 11 12 13 14 15 16 | .addEventListener('load', moduleDidLoad, true); </script> <embed name='nacl_module' id='tcl' width=0 height=0 | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | .addEventListener('load', moduleDidLoad, true); </script> <embed name='nacl_module' id='tcl' width=0 height=0 src='../tcl.nmf' type='application/x-nacl' verbose=0 source='balls.natcl'> <canvas id="canvas" width="578" height="200"></canvas> <h2>Status</h2> <div id="modstatus">NO-STATUS</div> |
︙ | ︙ |
Changes to nacl/demo/balls.natcl.
1 2 3 4 5 6 7 8 9 10 | source canv.natcl #set ::canv_verbose 1 domset statusField "Running..." # will be retrieved by [domget] set width 578 set height 200 # animation globals set t 0 | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | source canv.natcl #set ::canv_verbose 1 domset statusField "Running..." # will be retrieved by [domget] set width 578 set height 200 # animation globals set t 0 set frameInterval 25 # ball globals set ballRadius 10 # physics global set collisionDamper 0.3 set floorFriction [expr {0.0005*$frameInterval}] |
︙ | ︙ |
Deleted nacl/demo/tcl.nmf.
|
| < < < < < < |
Deleted nacl/tools/chrd.
|
| < < < < |
Deleted nacl/tools/chromedebug.
|
| < < < < < < |
Added nacl/trivhttpd.tcl.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | #! /bin/sh #\ exec tclsh $0 "$@" if {$argc!=1} {puts stderr "Usage: [file tail $::argv0] <port>";exit 1} set port [lindex $argv 0] proc serve {sok h p} { fconfigure $sok -translation binary -buffering full if {[catch { if {[gets $sok line]<0} {error "400 Empty request"} if {![regexp {^GET[ ]+([^ ]+)} $line -> path]} {error "403 Method Not Supported"} puts stderr "$h:$p - GET $path" if {[regexp {[.][.]} $path]} {error "403 Forbidden"} set ty text/plain switch -glob [file extension $path] { .html {set ty text/html} .nexe - .nmf {set ty application/octet-stream} } if {[catch {set ff [open .$path r]}]} {error "404 File Not Found"} fconfigure $ff -translation binary set data [read $ff] close $ff } err]} { puts $sok "HTTP/1.0 $err\r\n\r" } else { puts -nonewline $sok "HTTP/1.0 200 OK\r\nContent-Type: $ty\r\nContent-Length: [string length $data]\r\n\r\n$data" } close $sok } socket -server serve $port vwait forever |