diff --git a/emscripten-version.txt b/emscripten-version.txt index 6c13ae0d09f3e..5b3a48eab21e4 100644 --- a/emscripten-version.txt +++ b/emscripten-version.txt @@ -1,2 +1,2 @@ -1.21.9 +1.21.10 diff --git a/emscripten.py b/emscripten.py index a8a4dbe783f83..faf41c409a1fb 100755 --- a/emscripten.py +++ b/emscripten.py @@ -14,6 +14,7 @@ from tools import shared from tools import jsrun, cache as cache_module, tempfiles from tools.response_file import read_response_file +from tools.shared import WINDOWS __rootpath__ = os.path.abspath(os.path.dirname(__file__)) def path_from_root(*pathelems): @@ -708,13 +709,15 @@ def fix(m): funcs_js[i] = None funcs_js_item = indexize(funcs_js_item) funcs_js_item = blockaddrsize(funcs_js_item) + if WINDOWS: funcs_js_item = funcs_js_item.replace('\r\n', '\n') # Normalize to UNIX line endings, otherwise writing to text file will duplicate \r\n to \r\r\n! outfile.write(funcs_js_item) funcs_js = None - outfile.write(indexize(post)) - if DEBUG: logging.debug(' emscript: phase 3 took %s seconds' % (time.time() - t)) - + indexized = indexize(post) + if WINDOWS: indexized = indexized.replace('\r\n', '\n') # Normalize to UNIX line endings, otherwise writing to text file will duplicate \r\n to \r\r\n! + outfile.write(indexized) outfile.close() + if DEBUG: logging.debug(' emscript: phase 3 took %s seconds' % (time.time() - t)) # emscript_fast: emscript'en code using the 'fast' compilation path, using # an LLVM backend @@ -1316,9 +1319,11 @@ def fix(m): outfile.write("var SYMBOL_TABLE = %s;" % json.dumps(symbol_table).replace('"', '')) for i in range(len(funcs_js)): # do this loop carefully to save memory + if WINDOWS: funcs_js[i] = funcs_js[i].replace('\r\n', '\n') # Normalize to UNIX line endings, otherwise writing to text file will duplicate \r\n to \r\r\n! outfile.write(funcs_js[i]) funcs_js = None + if WINDOWS: post = post.replace('\r\n', '\n') # Normalize to UNIX line endings, otherwise writing to text file will duplicate \r\n to \r\r\n! outfile.write(post) outfile.close() diff --git a/site/source/_themes/emscripten_sphinx_rtd_theme/footer.html b/site/source/_themes/emscripten_sphinx_rtd_theme/footer.html index 668c9f8566ac0..d331c5abb713b 100644 --- a/site/source/_themes/emscripten_sphinx_rtd_theme/footer.html +++ b/site/source/_themes/emscripten_sphinx_rtd_theme/footer.html @@ -29,8 +29,9 @@ ('https://groups.google.com/forum/#!forum/emscripten-discuss', 'Mailing list', 'Mailing list'), ('https://github.com/kripken/emscripten/wiki', 'Wiki', 'Wiki'), ('https://plus.google.com/100622854474489221138', 'Google+', 'Google+'), - ('docs/getting_started/release_notes', 'Release notes', 'Release notes'), - ('docs/site/blogs', 'Blogs', 'Blogs'), + ('docs/introducing_emscripten/release_notes', 'Release notes', 'Release notes'), + ('docs/introducing_emscripten/community', 'Blogs', 'Blogs'), + ('docs/introducing_emscripten/community', 'Help', 'Contact'), ] -%}
``: Specifies the process return code that
-``emrun`` quits with if a page run timeout occurs. By default ``99999``.
+``emrun`` spawns its own web server to host the target html file. You should note the following security implications:
+
+- The web server is a generic file server that by default serves all files in the directory where the .html file resides, and all directories under that directory tree.
+- The web server will be visible to other computers on the same network.
+
+The following command line flags control how ``emrun`` spawns the web server:
+
+- ``--no_server``: Does not launch a web server at all. The target file is run via ``file://`` protocol, if possible.
+- ``--serve_after_close``: Does not quit ``emrun`` after the user was detected to close the web browser, but keeps serving. Use this flag for example when you want to visit the page multiple times or with different browsers during the same run.
+- ``--serve_after_exit``: Does not quit ``emrun`` after the page finishes with a call to ``exit(returncode);``, but keeps serving.
+- ``--serve_root ``: Chooses a custom directory to use as the root directory for the spawned web server. By default, the directory where the .html file resides in is used.
+- ``--port ``: Chooses the TCP port where the web server listens to. The default port is ``6931``.
+- ``--silence_timeout ``: If the application does not print anything to ``stdout`` or ``stderr`` in this many seconds, the page/browser is assumed to be hung, and ``emrun`` will quit. Disabled by default.
+- ``--timeout ``: If the whole page run lasts longer than this many seconds, the page/browser is assumed to be hung, and ``emrun`` will quit. Disabled by default.
+- ``--timeout_returncode ``: Specifies the process return code that ``emrun`` quits with if a page run timeout occurs. By default ``99999``.
Controlling log output
----------------------
The following command line flags affect messaging to logs:
-- ``--verbose``: Prints detailed information about ``emrun`` internal
- steps, for debugging purposes.
-- ``--log_stdout ``: Instead of printing to terminal, writes
- all stdout messages from the application to the given file.
-- ``--lot_stderr ``: Same as above, but for the stderr
- stream.
-- ``--system_info``: Before launching, prints detailed information
- about the current system. Useful for automated runs to capture
- hardware information to logs.
-- ``--browser_info``: Before launching, prints information about which
- browser is about to be launched.
-- ``--log_html``: If specified, application output is reformatted as
- html markup friendly.
-- ``--no_emrun_detect``: Hides the friendly reminder message that warns
- if target .html file is detected to not have been built with
- ``--emrun``.
+- ``--verbose``: Prints detailed information about ``emrun`` internal steps, for debugging purposes.
+- ``--log_stdout ``: Instead of printing to terminal, writes all ``stdout`` messages from the application to the given file.
+- ``--lot_stderr ``: Same as above, but for the ``stderr`` stream.
+- ``--system_info``: Before launching, prints detailed information about the current system. Useful for automated runs to capture hardware information to logs.
+- ``--browser_info``: Before launching, prints information about which browser is about to be launched.
+- ``--log_html``: If specified, application output is reformatted as html markup friendly.
+- ``--no_emrun_detect``: Hides the friendly reminder message that warns if target .html file is detected to not have been built with ``--emrun``.
Cleaning up after the run
-------------------------
-Especially when automating operation for build servers, it is important
-to be able to clean up properly after each run. The following command
-line flags enable this:
-
-- ``--kill_start``: If specified, all instances of the target browser
- process are terminated before starting the run. Pass this flag if you
- want to force that no old (hung) instances of the target browser
- processes could exist at the time of the launch that could interfere
- with the run. By default disabled.
-- ``--kill_exit``: If specified, all instances of the target browser
- process are terminated when ``emrun`` quits. Pass this flag to force
- that browser pages are not left around running when the run is over.
- By default disabled.
-
-It is important to understand that these operations can cause data loss,
-since these actions cause processes to be forcibly terminated. Do not
-pass these flags when running a browser that could have multiple tabs or
-windows open that you do other work in, since they will all be wiped
-out. You were warned.
+Especially when automating operation for build servers, it is important to be able to clean up properly after each run. The following command line flags enable this:
+
+- ``--kill_start``: If specified, all instances of the target browser process are terminated before starting the run. Pass this flag if you want to force that no old (hung) instances of the target browser processes could exist at the time of the launch that could interfere with the run. By default disabled.
+- ``--kill_exit``: If specified, all instances of the target browser process are terminated when ``emrun`` quits. Pass this flag to force that browser pages are not left around running when the run is over. By default disabled.
+
+It is important to understand that these operations can cause data loss, since these actions cause processes to be forcibly terminated. Do not pass these flags when running a browser that could have multiple tabs or windows open that you do other work in, since they will all be wiped out. You were warned.
Running web pages on an Android device
--------------------------------------
-It is also possible to use ``emrun`` to automate web browser runs on
-Android. For that to work, you need - An Android phone connected to the
-local system via USB and its developer mode enabled. No need to root the
-phone. - The ``adb`` tool installed to the system and present in
-``PATH`` environment variable. - Check that adb is working by calling
-``adb devices`` to see that your device is listed. - Install any browser
-apk to the device that you want to be able to run.
-
-To run on Android, add the ``--android`` command line flag, and use the
-``--browser `` command line flag to explicitly choose the browser to
-run. Omitting ``--browser`` (to launch a default Android browser) is not
-supported. The following browser ids have been tested to work:
-``firefox, firefox_beta, firefox_aurora, firefox_nightly, chrome, chrome_beta, opera``.
-The following browser ids are also supported, but have known issues: -
-``opera_mini``: The browser launches, but for some reason it times out
-when trying to load any page. - ``dolphin``: Works, but does not support
-WebGL.
-
-Otherwise, ``emrun`` works as usual, and the other command line flags
-can be combined.
+It is also possible to use ``emrun`` to automate web browser runs on Android. For that to work, you need
+
+- An Android phone connected to the local system via USB and its developer mode enabled. No need to root the phone.
+- The ``adb`` tool installed to the system and present in ``PATH`` environment variable.
+- Check that adb is working by calling ``adb devices`` to see that your device is listed.
+- Install any browser apk to the device that you want to be able to run.
+
+To run on Android, add the ``--android`` command line flag, and use the ``--browser `` command line flag to explicitly choose the browser to run. Omitting ``--browser`` (to launch a default Android browser) is not supported. The following browser ids have been tested to work: ``firefox, firefox_beta, firefox_aurora, firefox_nightly, chrome, chrome_beta, opera``.
+
+The following browser ids are also supported, but have known issues:
+- ``opera_mini``: The browser launches, but for some reason it times out when trying to load any page.
+- ``dolphin``: Works, but does not support WebGL.
+
+Otherwise, ``emrun`` works as usual, and the other command line flags can be combined.
diff --git a/site/source/docs/contributing/building_from_source/Getting-started-on-Mac-OS-X.rst b/site/source/docs/contributing/building_from_source/Getting-started-on-Mac-OS-X.rst
index 27175a9256e93..376a6580ce911 100644
--- a/site/source/docs/contributing/building_from_source/Getting-started-on-Mac-OS-X.rst
+++ b/site/source/docs/contributing/building_from_source/Getting-started-on-Mac-OS-X.rst
@@ -5,149 +5,129 @@ Getting started on Mac OS X (wiki-import)
=========================================
.. note:: This article was migrated from the wiki (Fri, 25 Jul 2014 04:21) and is now the "master copy" (the version in the wiki will be deleted). It may not be a perfect rendering of the original but we hope to fix that soon!
-This guide instructs step-by-step on how to setup emscripten on a clean
-Mac OS X box. The steps have been tested against OS X version 10.8.2.
+This guide instructs step-by-step on how to setup emscripten on a clean Mac OS X box. The steps have been tested against OS X version 10.8.2.
Note for `homebrew `__ users:
-``brew install emscripten`` does all the steps below for you (including
-installation of the llvm fastcomp compiler and patching the python
-interpreter).
+``brew install emscripten`` does all the steps below for you (including installation of the llvm fastcomp compiler and patching the python interpreter).
-1. Install svn if you do not have it yet. It is distributed with XCode
- Command Line Tools in OSX App Store. See
- http://superuser.com/questions/455214/where-is-svn-on-os-x-mountain-lion
+1. Install svn if you do not have it yet. It is distributed with XCode Command Line Tools in OSX App Store. See http://superuser.com/questions/455214/where-is-svn-on-os-x-mountain-lion
-- Install XCode from OSX App Store.
-- In XCode->Preferences->Downloads, install Command Line Tools.
-- Test that svn works from command line: type 'svn --version' in
- terminal.
+ - Install XCode from OSX App Store.
+ - In XCode->Preferences->Downloads, install Command Line Tools.
+ - Test that svn works from command line: type 'svn --version' in terminal.
2. Install git if you do not have it yet:
-- Allow installation of unsigned packages, or installing git package
- won't succeed:
- https://www.my-private-network.co.uk/knowledge-base/apple-related-questions/osx-unsigned-apps.html
-- Download and install git from http://git-scm.com/
-- Test that git works from command line: type 'git --version' in
- terminal.
+ - Allow installation of unsigned packages, or installing git package won't succeed: https://www.my-private-network.co.uk/knowledge-base/apple-related-questions/osx-unsigned-apps.html
+ - Download and install git from http://git-scm.com/
+ - Test that git works from command line: type 'git --version' in terminal.
3. Install cmake if you do not have it yet:
-- Download and install cmake-2.8.10.2-Darwin64-universal.dmg or newer
- from http://www.cmake.org/cmake/resources/software.html
-- Test that cmake works from command line: type 'cmake --version' in
- terminal.
+ - Download and install cmake-2.8.10.2-Darwin64-universal.dmg or newer from http://www.cmake.org/cmake/resources/software.html
+ - Test that cmake works from command line: type 'cmake --version' in terminal.
-4. Build LLVM+Clang 3.2 from SVN repository:
+4. Build LLVM+Clang 3.2 from SVN repository:
-- cd ~
-- svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE\_32/final
- llvm32
-- cd llvm32/tools
-- svn co http://llvm.org/svn/llvm-project/cfe/tags/RELEASE\_32/final
- clang
-- cd ../..
-- mkdir llvm32build
-- cd llvm32build
-- cmake -DCMAKE\_BUILD\_TYPE=Release -G "Unix Makefiles" ../llvm32
-- make
+ ::
-After these steps, Clang 3.2 will be built into ~/llvm32build/bin. The
-source tree ~/llvm32 is not needed anymore, if you want to conserve disk
-space.
+ cd ~
+ svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE\_32/final llvm32
+ cd llvm32/tools
+ svn co http://llvm.org/svn/llvm-project/cfe/tags/RELEASE\_32/final clang
+ cd ../..
+ mkdir llvm32build
+ cd llvm32build
+ cmake -DCMAKE\_BUILD\_TYPE=Release -G "Unix Makefiles" ../llvm32
+ make
-Note that XCode ships with a custom version of Clang (3.1svn or 3.2svn
-depending on XCode version). It may be possible to omit this step and
-just use the version provided by XCode, but the LLVM 3.2 RELEASE version
-is preferred, since that is the "officially supported version" the
-emscripten OSX unit tests are run against.
+ After these steps, Clang 3.2 will be built into ~/llvm32build/bin. The source tree ~/llvm32 is not needed anymore, if you want to conserve disk space.
-5. Set up Clang 3.2 in PATH:
+ Note that XCode ships with a custom version of Clang (3.1svn or 3.2svn depending on XCode version). It may be possible to omit this step and just use the version provided by XCode, but the LLVM 3.2 RELEASE version is preferred, since that is the "officially supported version" the Emscripten OSX unit tests are run against.
-- cd ~
-- echo "export PATH=~/llvm32build/bin:$PATH" >> .profile
+5. Set up Clang 3.2 in PATH:
-The above change is permanent and it persists between system restarts.
-It only affects the current user.
+ ::
-6. Close all terminal windows, and open a new one. Check that clang
- works ok in path:
+ cd ~
+ echo "export PATH=~/llvm32build/bin:$PATH" >> .profile
-- cd ~
-- clang --version
+ The above change is permanent and it persists between system restarts. It only affects the current user.
-The command should output: clang version 3.2 (tags/RELEASE\_32/final
-176107) Target: x86\_64-apple-darwin12.2.1 Thread model: posix
+6. Close all terminal windows, and open a new one. Check that clang works ok in path:
-7. Delete old .emscripten file if it happened to exist:
+ ::
-- rm ~/.emscripten
-- rm -rf ~/.emscripten\_cache
+ cd ~
+ clang --version
+
+ The command should output: clang version 3.2 (tags/RELEASE\_32/final 176107) Target: x86\_64-apple-darwin12.2.1 Thread model: posix
+
+7. Delete old .emscripten file if it happened to exist:
+
+ ::
+
+ rm ~/.emscripten
+ rm -rf ~/.emscripten\_cache
8. Set up node:
-- Download and install node from http://nodejs.org/
-- Test that node works from command line: type 'node --version' in
- terminal.
+ - Download and install node from http://nodejs.org/
+ - Test that node works from command line: type 'node --version' in terminal.
+
+9. Obtain Emscripten:
+
+ ::
+
+ cd ~
+ git clone https://github.com/kripken/emscripten.git
+
+ By default, git will clone the emscripten 'incoming' branch, which is the branch where the newest developments of Emscripten occur. If you want to use a more stable branch, switch to the 'master' branch: - cd ~/emscripten - git checkout master
-9. Obtain emscripten:
+10. Setup 'python2': (this step is needed to workaround a bug reported in `#763 `__)
-- cd ~
-- git clone https://github.com/kripken/emscripten.git
+ - In terminal, type 'python2 --version'. If you get a "command not found", type the following: ::
+
+ cd /usr/bin
+ sudo ln python python2
+ sudo ln ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7 python22.7
+
+ - Issue 'python2 --version' again. It should now print Python 2.7.2
-By default, git will clone the emscripten 'incoming' branch, which is
-the branch where the newest developments of emscripten occur. If you
-want to use a more stable branch, switch to the 'master' branch: - cd
-~/emscripten - git checkout master
+11. Perform emscripten "first run":
-10. Setup 'python2': (this step is needed to workaround a bug reported
- in `#763 `__)
+ ::
-- In terminal, type 'python2 --version'. If you get a "command not
- found", type the following:
-- cd /usr/bin
-- sudo ln python python2
-- sudo ln
- ../../System/Library/Frameworks/Python.framework/Versions/2.7/bin/python2.7
- python22.7
-- Issue 'python2 --version' again. It should now print Python 2.7.2
+ cd ~/emscripten
+ /emcc --help
+
+ - edit the file ~/.emscripten in a text editor to set up any required paths.
-11. Perform emscripten "first run":
+12. (Optional) Compile a simple test program to check that everything works:
-- cd ~/emscripten
-- ./emcc --help
-- edit the file ~/.emscripten in a text editor to set up any required
- paths.
+ ::
-12. (Optional) Compile a simple test program to check that everything
- works:
+ cd ~/emscripten
+ ./em++ tests/hello\_world.cpp
+ node a.out.js
-- cd ~/emscripten
-- ./em++ tests/hello\_world.cpp
-- node a.out.js
+ The first run will most likely pop up an automatic prompt that asks to install java. Proceed, and after installation finishes, rerun the above commands. Running node should output: hello, world!
-The first run will most likely pop up an automatic prompt that asks to
-install java. Proceed, and after installation finishes, rerun the above
-commands. Running node should output: hello, world!
+13. (Optional) Compile a simple WebGL program to check that .html output and GLES2/WebGL works:
-13. (Optional) Compile a simple WebGL program to check that .html output
- and GLES2/WebGL works:
+ ::
-- cd ~/emscripten
-- ./emcc tests/hello\_world\_gles.c -o hello\_world\_gles.html
-- open hello\_world\_gles.html
+ cd ~/emscripten
+ ./emcc tests/hello\_world\_gles.c -o hello\_world\_gles.html
+ open hello\_world\_gles.html
+
+ .. note:: If the Safari 6 browser pops up with a message "Could not create canvas :(", follow `these instructions `_ to enable WebGL support in Safari
-If the Safari 6 browser pops up with a message "Could not create canvas
-:(", follow these instructions to enable WebGL support in Safari:
-http://support.apple.com/kb/PH11926
-14. (Optional) Run the full battery of tests to check that emscripten is
- perfectly operational on the current platform:
+14. (Optional) Run the full battery of tests to check that Emscripten is perfectly operational on the current platform: ::
-- cd ~/emscripten
-- python tests/runner.py
-- python tests/runner.py benchmark
+ cd ~/emscripten
+ python tests/runner.py
+ python tests/runner.py benchmark
-Note that some tests will likely fail. Cross-reference the results with
-https://github.com/kripken/emscripten/issues?labels=tests to see if you
-are receiving currently unknown issues.
+ Note that some tests will likely fail. Cross-reference the results with https://github.com/kripken/emscripten/issues?labels=tests to see if you are receiving currently unknown issues.
diff --git a/site/source/docs/contributing/building_from_source/Using-Emscripten-on-Windows.rst b/site/source/docs/contributing/building_from_source/Using-Emscripten-on-Windows.rst
index dbfebdf75bdc4..1acd4870a5112 100644
--- a/site/source/docs/contributing/building_from_source/Using-Emscripten-on-Windows.rst
+++ b/site/source/docs/contributing/building_from_source/Using-Emscripten-on-Windows.rst
@@ -3,6 +3,7 @@
=========================================
Using Emscripten on Windows (wiki-import)
=========================================
+
.. note:: This article was migrated from the wiki (Fri, 25 Jul 2014 04:21) and is now the "master copy" (the version in the wiki will be deleted). It may not be a perfect rendering of the original but we hope to fix that soon!
This page describes how to use Emscripten on Windows.
@@ -10,207 +11,121 @@ This page describes how to use Emscripten on Windows.
Setting up the Emscripten Toolchain on Windows
----------------------------------------------
-This section contains basic instructions on how to start using
-Emscripten on a clean Windows box. After these steps, you can invoke
-emcc from the command line by calling 'python emcc'. 64-bit versions of
-all needed dependencies are preferred, and may be required if you are
-building large projects.
+This section contains basic instructions on how to start using Emscripten on a clean Windows box. After these steps, you can invoke emcc from the command line by calling 'python emcc'. 64-bit versions of all needed dependencies are preferred, and may be required if you are building large projects.
Installing required tools
~~~~~~~~~~~~~~~~~~~~~~~~~
1. Install Python 2.x (not 3.x) from http://www.python.org/.
-- e.g.
- `python-2.7.5.amd64.msi `__
- for a 64-bit install.
-- If you plan to use the Visual Studio integration, do NOT install the
- 64-bit version. Get the 32-bit version of python from
- `python-2.7.5.msi `__.
-- Add the Python bin directory to your PATH. (Open up System Settings,
- Advanced system properties, click Environment Variables. Add "C:27"
- to the PATH, separated by a semicolon.) If on the other hand
- ``python.exe`` appears in "C:27" and not under bin, just add "C:27".
+ - e.g. `python-2.7.5.amd64.msi `_ for a 64-bit install.
+ - If you plan to use the Visual Studio integration, do NOT install the 64-bit version. Get the 32-bit version of python from `python-2.7.5.msi `_.
+ - Add the Python bin directory to your PATH. (Open up System Settings, Advanced system properties, click Environment Variables. Add "C:27" to the PATH, separated by a semicolon.) If on the other hand ``python.exe`` appears in "C:27" and not under bin, just add "C:27".
2. Install node.js from http://nodejs.org/
-- e.g.
- `node-v0.10.17-x64.msi `__
-- If you plan to use the Visual Studio integration, do NOT install the
- 64-bit version. Get the 32-bit version of node.js from
- `node-v0.10.17-x86.msi `__.
+ - e.g. `node-v0.10.17-x64.msi `_
+ - If you plan to use the Visual Studio integration, do NOT install the 64-bit version. Get the 32-bit version of node.js from `node-v0.10.17-x86.msi `_.
3. Setup gcc 4.6 and llvm-clang 3.2.
-- If you like building the tools yourself or plan to use the Visual
- Studio integration (for which you need 32-bit versions of the tools)
- see below for how to build LLVM/Clang from source.
-- Otherwise download the following 64-bit builds
--
-
- -
-
- - `x86\_64-w64-mingw32-gcc-4.6.3-2-release-win64\_rubenvb.7z `__
-
--
-
- -
+ - If you like building the tools yourself or plan to use the Visual Studio integration (for which you need 32-bit versions of the tools) see below for how to build LLVM/Clang from source.
+ - Otherwise download the following 64-bit builds:
- - `x86\_64-w64-mingw32-clang-3.2-release-win64\_rubenvb.7z `__
+ - `x86\_64-w64-mingw32-gcc-4.6.3-2-release-win64\_rubenvb.7z `_
+ - `x86\_64-w64-mingw32-clang-3.2-release-win64\_rubenvb.7z `_
-- Extract both of them using `7zip `__ to the same
- location, e.g. C:64
+ - Extract both of them using `7zip `__ to the same location, e.g. C:64
-4. If you do not already have a git client, Install `Github for
- Windows `__.
-5. Clone the ``kripken/emscripten`` repository from github. The
- emscripten repository contains the main compiler tool for compiling
- C/C++ programs to JavaScript.
+4. If you do not already have a git client, Install `Github for Windows `_.
+5. Clone the ``kripken/emscripten`` repository from github. The emscripten repository contains the main compiler tool for compiling C/C++ programs to JavaScript.
-- Launch the GitHub for Windows Client. You may click "Skip Setup" if
- you don't have a github account.
-- (optional) Select "Options" from the gear menu, and customize the
- default storage directory. A path without spaces can save you lots of
- pain down the line.
-- In your web browser, open https://github.com/kripken/emscripten and
- press the "Clone in Windows" button.
-- Note: if you already had a different git client, the repository URL
- is ``https://github.com/kripken/emscripten.git`` (e.g.
- ``git clone https://github.com/kripken/emscripten.git``)
+ - Launch the GitHub for Windows Client. You may click "Skip Setup" if you don't have a github account.
+ - (optional) Select "Options" from the gear menu, and customize the default storage directory. A path without spaces can save you lots of pain down the line.
+ - In your web browser, open https://github.com/kripken/emscripten and press the "Clone in Windows" button.
+
+ .. note:: If you already had a different git client, the repository URL is ``https://github.com/kripken/emscripten.git`` (e.g. ``git clone https://github.com/kripken/emscripten.git``)
+
Configuring Emscripten
~~~~~~~~~~~~~~~~~~~~~~
-1. Open up a command prompt, and change to the directory where you
- cloned the emscripten repository. By default with the GitHub client,
- this will be ``C:\Users\username\Documents\GitHub\emscripten``.
+1. Open up a command prompt, and change to the directory where you cloned the Emscripten repository. By default with the GitHub client, this will be ``C:\Users\username\Documents\GitHub\emscripten``.
2. Run ``python emcc --help``
-- You should get a ``Welcome to Emscripten!`` message. Behind the
- scenes, emscripten generated a file called ``.emscripten`` in your
- Windows home folder.
-- If you do not see this message, make sure that python is properly in
- your global PATH, and that you are in the emscripten directory.
+ - You should get a ``Welcome to Emscripten!`` message. Behind the scenes, Emscripten generated a file called ``.emscripten`` in your Windows home folder.
+ - If you do not see this message, make sure that python is properly in your global PATH, and that you are in the Emscripten directory.
3. Edit ``C:\Users\username\.emscripten``:
- 1. Edit the variable ``EMSCRIPTEN_ROOT`` to point to the emscripten
- root folder, e.g.
- ``EMSCRIPTEN_ROOT = 'C:/Users/username/Documents/GitHub/emscripten'``
- (Note: use forward slashes)
- 2. Edit the variable ``LLVM_ROOT`` to point directly to the path
- where you installed clang.exe, e.g.
+ 1. Edit the variable ``EMSCRIPTEN_ROOT`` to point to the Emscripten root folder, e.g. ``EMSCRIPTEN_ROOT = 'C:/Users/username/Documents/GitHub/emscripten'`` (Note: use forward slashes)
+ 2. Edit the variable ``LLVM_ROOT`` to point directly to the path where you installed clang.exe, e.g. ::
+
``LLVM_ROOT = 'C:/mingw64/bin'``
- 3. Edit the variable TEMP\_DIR to point to a valid Windows path on
- your local system, e.g. ``TEMP_DIR = 'C:/tmp'``, and create that
- folder on the local filesystem if it doesn't exist.
- 4. If you are planning on using Cygwin and cygwin make in the future,
- copy the .emscripten file to your cygwin home folder as well, e.g.
- copy C:.emscripten C: (There is a bug in emscripten that it
- currently looks for the file .emscripten in two places (Win7 user
- home folder or cygwin user home folder), depending on the
- environment it is executed in, so as a current workaround these
- files must be present and identical on Windows. (see `issue
- #411 `__))
+
+ 3. Edit the variable TEMP\_DIR to point to a valid Windows path on your local system, e.g. ``TEMP_DIR = 'C:/tmp'``, and create that folder on the local filesystem if it doesn't exist.
+ 4. If you are planning on using Cygwin and cygwin make in the future, copy the .emscripten file to your cygwin home folder as well, e.g.
+ copy C:.emscripten C: (There is a bug in Emscripten that it currently looks for the file .emscripten in two places (Win7 user home folder or cygwin user home folder), depending on the environment it is executed in, so as a current workaround these files must be present and identical on Windows. (see `issue #411 `_))
+
Integrating Emscripten to Visual Studio 2010
--------------------------------------------
-It is possible to integrate the Emscripten compiler directly to Visual
-Studio. This allows existing VS .sln files to be directly built using
-emcc. The Microsoft compiler property pages are replaced by Clang and
-emcc -specific options.
+It is possible to integrate the Emscripten compiler directly to Visual Studio. This allows existing VS .sln files to be directly built using *emcc*. The Microsoft compiler property pages are replaced by *Clang* and emcc -specific options.
1. Install Visual Studio 2010
-- Note: Express version has not been tested, but should be ok. Please
- drop a line on emscripten IRC channel or mailing list to report your
- experience with VS2010 Express!
+ .. note:: Express version has not been tested, but should be ok. Please drop a line on Emscripten IRC channel or mailing list to report your experience with VS2010 Express!
2. Clone the juj/vs-tool repository from github:
-- git clone https://github.com/juj/vs-tool
-- The vs-tool repository contains a plugin to Visual Studio 2010 (or
- rather, to MSBuild) that instructs Visual Studio how to use the
- llvm-clang and emscripten toolchain.
+ - git clone https://github.com/juj/vs-tool
+ - The vs-tool repository contains a plugin to Visual Studio 2010 (or rather, to MSBuild) that instructs Visual Studio how to use the llvm-clang and emscripten toolchain.
3. Install vs-tool itself.
4. Navigate to folder vs-tool
5. Copy the folders Clang and Emscripten to C:Files (x86).Cpp.0\\.
6. Set up the required environment variables for vs-tool.
-7. Windows 7: Open Control Panel -- System -- Advanced System Settings
- -- Environment Variables.
-8. Create a new environment variable 'CLANG\_BIN' and set it to point
- to the folder where you built clang to (path to clang.exe) E.g.
+7. Windows 7: Open Control Panel -- System -- Advanced System Settings -- Environment Variables.
+8. Create a new environment variable 'CLANG\_BIN' and set it to point to the folder where you built clang to (path to clang.exe) E.g.
- SETX CLANG\_BIN C:-build
- - This is how vs-tool locates the folder to your llvm-clang
- compiler. Alternatively, this path can be set per-project in
- Visual Studio project property pages.
+ - This is how vs-tool locates the folder to your llvm-clang compiler. Alternatively, this path can be set per-project in Visual Studio project property pages.
-9. Create a new environment variable 'EMSCRIPTEN' and set it to point
- to the emscripten git repository root folder (the path where you
- copied emcc.exe and other exes to). E.g.
+9. Create a new environment variable 'EMSCRIPTEN' and set it to point to the Emscripten git repository root folder (the path where you copied emcc.exe and other exes to). E.g.
- SETX EMSCRIPTEN C:
- - This is how vs-tool locates the emscripten compiler. This path
+ - This is how vs-tool locates the Emscripten compiler. This path
can also be overridden per-project in VS property pages.
-10. Create a new environment variable 'EMCC\_WEBBROWSER\_EXE' and set it
- to point to an executable you want to use to browse
- emscripten-generated web pages from Visual Studio. This process is
- spawned when you tap Start (Ctrl-F5) in Visual Studio for a
- emscripten-targeted project.
+10. Create a new environment variable 'EMCC\_WEBBROWSER\_EXE' and set it to point to an executable you want to use to browse Emscripten-generated web pages from Visual Studio. This process is spawned when you tap Start (Ctrl-F5) in Visual Studio for an Emscripten-targeted project.
- SETX EMCC\_WEBBROWSER\_EXE C:Files (x86)Firefox.exe
-11. Now you are all set to start developing Emscripten-based projects
- from Visual Studio. To test the installation, open the Visual Studio
- solution file 10\_msvc10.sln.
+11. Now you are all set to start developing Emscripten-based projects from Visual Studio. To test the installation, open the Visual Studio solution file 10\_msvc10.sln.
+
Tips for using Emscripten from the Visual Studio 2010 IDE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-To build a Visual Studio solution using the Emscripten toolchain, select
-the "Emscripten" configuration from the Configuration Manager dropdown
-as the active configuration, and choose Build Solution (F7).
-
-To launch a project directly to a web browser from Visual Studio,
-right-click on the project to run, choose "Set as Startup Project", and
-select Start without Debugging (Ctrl+F5). This should launch the
-generated .html file to the browser you specified in
-EMCC\_WEBBROWSER\_EXE. A bug(?) in Visual Studio causes a "Executable
-for Debug Session" dialog to occasionally open up when you hit Ctrl+F5.
-This can be ignored by clicking Yes, then No, or simply by hitting Esc
-and then tapping Ctrl+F5 again.
-
-llvm-clang and emscripten compiler settings can be edited for the
-project in the "usual" Visual Studio fashion: First make sure that the
-Emscripten platform configuration is active, then right-click on a
-project, and choose Properties. In the Project properties dialog, two
-tree nodes Clang C/C++ and Emcc Linker should exist, which allow you to
-specify the desired compilation options.
-
-If you have an existing solution file you want to build using
-Emscripten, open the Configuration Manager.. dialog for the solution,
-and in the Active Solution Platform dropdown, choose New.... In the new
-dialog, choose Emscripten as the platform name, and Copy settings from
-Empty. After this, you can switch between building the solution for
-Win32 and Emscripten from the Configuration Manager dropdown list.
-
-When you want to create a new Visual Studio project for Emscripten, we
-recommend you start with a Visual C++ Empty Project. This will create a
-new project for the Win32 platform. Then convert that project for
-Emscripten as outlined in the previous paragraph.
+To build a Visual Studio solution using the Emscripten toolchain, select the "Emscripten" configuration from the Configuration Manager dropdown as the active configuration, and choose Build Solution (F7).
+
+To launch a project directly to a web browser from Visual Studio, right-click on the project to run, choose "Set as Startup Project", and select Start without Debugging (Ctrl+F5). This should launch the generated .html file to the browser you specified in EMCC\_WEBBROWSER\_EXE. A bug(?) in Visual Studio causes a "Executable for Debug Session" dialog to occasionally open up when you hit Ctrl+F5. This can be ignored by clicking Yes, then No, or simply by hitting Esc and then tapping Ctrl+F5 again.
+
+llvm-clang and Emscripten compiler settings can be edited for the project in the "usual" Visual Studio fashion: First make sure that the Emscripten platform configuration is active, then right-click on a project, and choose Properties. In the Project properties dialog, two
+tree nodes Clang C/C++ and Emcc Linker should exist, which allow you to specify the desired compilation options.
+
+If you have an existing solution file you want to build using Emscripten, open the Configuration Manager.. dialog for the solution, and in the Active Solution Platform dropdown, choose New.... In the new dialog, choose Emscripten as the platform name, and Copy settings from
+Empty. After this, you can switch between building the solution for Win32 and Emscripten from the Configuration Manager dropdown list.
+
+When you want to create a new Visual Studio project for Emscripten, we recommend you start with a Visual C++ Empty Project. This will create a new project for the Win32 platform. Then convert that project for Emscripten as outlined in the previous paragraph.
Building LLVM/Clang from Source
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-In case the above-referenced prebuilt binaries do not work for you, you
-can build LLVM and Clang from source.
+In case the above-referenced prebuilt binaries do not work for you, you can build LLVM and Clang from source.
-To install and set up ``llvm-clang 3.2``, open a Visual Studio 2010
-command prompt and type:
+To install and set up ``llvm-clang 3.2``, open a Visual Studio 2010 command prompt and type:
1. ``svn co http://llvm.org/svn/llvm-project/llvm/tags/RELEASE_32/final llvm``
2. ``cd llvm\tools``
@@ -221,9 +136,6 @@ command prompt and type:
7. ``cmake -G "Visual Studio 10" ..\llvm``
8. ``msbuild LLVM.sln /p:Configuration=Release``
-If you have problems with the above, see more help here:
-http://clang.llvm.org/get\_started.html
+If you have problems with the above, see more help here: http://clang.llvm.org/get\_started.html
-**NOTE**: Instead of checking out the trunk as the guide suggests, check
-out the latest tagged release of Clang (3.2 at the time of writing). An
-older version will not most likely work with Emscripten.
+.. note:: Instead of checking out the trunk as the guide suggests, check out the latest tagged release of Clang (3.2 at the time of writing). An older version will not most likely work with Emscripten.
diff --git a/site/source/docs/contributing/contributing.rst b/site/source/docs/contributing/contributing.rst
index 0844cd99c2166..6a18452c52aa8 100644
--- a/site/source/docs/contributing/contributing.rst
+++ b/site/source/docs/contributing/contributing.rst
@@ -1,10 +1,10 @@
+.. _contributing:
+
================================================
Contributing (ready-for-review)
================================================
-Anyone can contribute to Emscripten. Feel free to :doc:`join the discussion ` and share your suggestions, ideas, and `bug reports `_!
-
-If you find Emscripten useful and want to contribute, check out the information and suggestions below.
+Anyone can contribute to Emscripten — if you find it useful and want to help improve the project, follow the suggestions below. Feel free to file :ref:`bug reports `, :ref:`join the discussion ` and share your own ideas with the community!
Getting started
@@ -12,7 +12,9 @@ Getting started
A good starting point is to work on the `open issues on Github `_. Many issues can be resolved without an in-depth knowledge of compiler internals, and this is a great way to learn more about the project.
-.. tip:: We really appreciate your help. Every closed issue means more time for experienced developers to work on compiler internals.
+.. tip:: We really appreciate your help. Every existing issue closed means more time for the core contributors to work on new features, optimizations and other enhancements.
+
+As a new contributor you should read the :ref:`Developer's-Guide`, and you may also need to :ref:`install Emscripten from source `.
Branches of interest
@@ -20,7 +22,6 @@ Branches of interest
- **master** - The "master" branch. This is always safe to pull from and the test suite always passes.
- **incoming** - Branch for new code. Code in **incoming** is merged with the **master** only after it is code-reviewed and has passed all the automated tests.
-- **llvmsvn** - Branch for work to support a new version of LLVM. Activity typically begins near the end of an LLVM 6-month dev cycle. When LLVM launches the new version, we merge this branch to master and incoming, at which point our support officially moves to that new LLVM version. Only one version of LVVM is supported at a time.
Submitting patches
@@ -28,13 +29,13 @@ Submitting patches
Patches should be submitted as *pull requests* to the **incoming** branch.
-.. note:: Before submitting your first patch, add yourself to the `AUTHORS `_ file. By doing so, you agree to license your code under the project's `open source licenses (MIT/LLVM) `_.
+.. note:: Before submitting your first patch, add yourself to the `AUTHORS `_ file. By doing so, you agree to license your code under the project's :ref:`open source licenses (MIT/LLVM) `.
When submitting patches, please:
- Make pull requests to **incoming**, not master.
- Do not include merge commits in pull requests; include only commits with the new relevant code.
-- Run all the automatic tests and make sure they pass **tests/runner.py**. Some tests might not be required for very simple patches (for example, when just adding tests for new library functions).
+- :ref:`Run all the automatic tests ` and make sure they pass **tests/runner.py**. Some tests might not be required for very simple patches (for example, when just adding tests for new library functions).
- If you add any new functionality or fix a bug, add an automatic test to **tests/runner.py**.
- Record the tests that were run in the pull request or issue.
@@ -44,7 +45,7 @@ Code reviews
`@kripken `_ reviews all pull requests before merging.
-Exceptions are sub-projects that are 'owned' by other people. These developer/owners can push to incoming directly:
+Exceptions are sub-projects that are 'owned' by other people. These owners can push to incoming directly:
- OpenAL and audio in general: `@ehsan `_
- embind: `@imvu `_
@@ -55,6 +56,7 @@ Exceptions are sub-projects that are 'owned' by other people. These developer/ow
Next steps
==========
-After you've fixed some bugs and have a better understanding of the project, you may wish to contribute more "deeply". Please share your development ideas with the :doc:`community ` so that they can be evolved and planned.
+Community members make a huge difference to this project. Please :ref:`get in touch with the community ` to share your ideas and work out where you can make the most difference.
+
+
-Emscripten internal developers should also read the :doc:`PLACEHOLDER Developer's-Guide`.
\ No newline at end of file
diff --git a/site/source/docs/getting_started/Tutorial.rst b/site/source/docs/getting_started/Tutorial.rst
index 5f70e13d481f0..754408b87459f 100644
--- a/site/source/docs/getting_started/Tutorial.rst
+++ b/site/source/docs/getting_started/Tutorial.rst
@@ -195,6 +195,9 @@ Further optimizations are done in ``-O2``,
If you inspect the generated code now, you will see it looks very
different.
+
+.. _running-emscripten-tests:
+
Running the Emscripten Test Suite and Benchmarks
------------------------------------------------
diff --git a/site/source/docs/introducing_emscripten/bug_reports.rst b/site/source/docs/introducing_emscripten/bug_reports.rst
index 7cc8f712ad07a..32828a943b1b0 100644
--- a/site/source/docs/introducing_emscripten/bug_reports.rst
+++ b/site/source/docs/introducing_emscripten/bug_reports.rst
@@ -1,3 +1,5 @@
+.. _bug-reports:
+
=========================================
Bug Reporting (ready-for-review)
=========================================
@@ -6,13 +8,13 @@ All bugs should be filed in the GitHub `main `_ link on the bottom-right of every page opens the Issue Tracker pre-seeded with the current page URL and title.
diff --git a/site/source/docs/introducing_emscripten/community.rst b/site/source/docs/introducing_emscripten/community.rst
new file mode 100644
index 0000000000000..e52b9165f7e8e
--- /dev/null
+++ b/site/source/docs/introducing_emscripten/community.rst
@@ -0,0 +1,48 @@
+===========================================
+Community (ready-for-review)
+===========================================
+
+Welcome to the Emscripten community!
+
+
+.. _contact:
+
+Get in touch
+===========================================
+
+The best way to contact us is to use either the *mailing list* or *IRC*.
+
+- Mailing list: `emscripten-discuss `_
+- IRC: **#emscripten** on `irc.mozilla.org `_
+
+
+Emscripten also has an *unofficial* presence on social media:
+
+- `Google+ page `_
+- `#emscripten `_ (Emscripten Hashtag on Twitter)
+- `@kripken `_ (Emscripten Developer Account on Twitter)
+
+
+Report a bug
+=============
+
+:ref:`Bug reports ` can be posted in the GitHub `Issue Tracker `_.
+
+
+.. _blogs:
+
+
+Blogs
+=========================
+
+Get the latest official Emscripten news on the blogs: `Developer blog (azakai) `_ and `Mozilla blog `_.
+
+In addition, other interesting blogs and demos are regularly shared on Twitter by the development team `(@kripken) `_ and the broader community `(#emscripten) `_.
+
+.. todo :: **HamishW** At some point in future would be nice to actually display RSS feeds from above links here. Perhaps including @kripen in feed. In this case would need a dedicated blogs link as well.
+
+
+Contribute
+============
+
+Anyone can contribute to Emscripten. We've got some ideas to get you started on our :ref:`contributing` page.
diff --git a/site/source/docs/introducing_emscripten/contact.rst b/site/source/docs/introducing_emscripten/contact.rst
deleted file mode 100644
index 2c2d96802bf43..0000000000000
--- a/site/source/docs/introducing_emscripten/contact.rst
+++ /dev/null
@@ -1,17 +0,0 @@
-===========================================
-Get in touch (ready-for-review)
-===========================================
-
-The best channels to contact the development team (and the community) are the *mailing list* and *IRC*. Bug reports should be posted in the GitHub *Issue Tracker*:
-
-- Mailing list: `emscripten-discuss `_
-- IRC: **#emscripten** on `irc.mozilla.org `_
-- `Issue Tracker `_ (see :doc:`bug_reports`)
-
-Emscripten also has an *unofficial* presence on social media:
-
-- `Google+ page `_
-- `#emscripten `_ (Emscripten Hashtag on Twitter)
-- `@kripken `_ (Emscripten Developer Account on Twitter)
-
-
diff --git a/site/source/docs/introducing_emscripten/emscripten_license.rst b/site/source/docs/introducing_emscripten/emscripten_license.rst
index df01939e3e8a2..e75b2196b0fce 100644
--- a/site/source/docs/introducing_emscripten/emscripten_license.rst
+++ b/site/source/docs/introducing_emscripten/emscripten_license.rst
@@ -1,3 +1,5 @@
+.. _emscripten-license:
+
===================
Open Source License
===================
diff --git a/site/source/docs/introducing_emscripten/index.rst b/site/source/docs/introducing_emscripten/index.rst
index aa64e65834b36..3a624dad3b325 100644
--- a/site/source/docs/introducing_emscripten/index.rst
+++ b/site/source/docs/introducing_emscripten/index.rst
@@ -7,7 +7,7 @@ Introducing Emscripten (under-construction)
:maxdepth: 1
FAQ
- contact
+ community
emscripten_license
bug_reports
release_notes
diff --git a/site/source/docs/site/blogs.rst b/site/source/docs/site/blogs.rst
deleted file mode 100644
index 79bb5a31bb067..0000000000000
--- a/site/source/docs/site/blogs.rst
+++ /dev/null
@@ -1,14 +0,0 @@
-====================================
-Blogs (ready-for-review)
-====================================
-
-There are two main Emscripten blogs:
-
-- `Developer blog (azakai) `_.
-- `Mozilla blog `_ (for sharing important "commercial" announcements and user stories).
-
-In addition, other interesting blogs and demos are regularly shared on Twitter by the development team `(@kripken) `_ and the broader community `(#emscripten) `_.
-
-
-.. COMMENT BACKUP STUFF
- Suggestion was to actually display RSS feeds from above links here. Perhaps including @kripen in feed. Not planning to do this at this time.
diff --git a/site/source/docs/site/index.rst b/site/source/docs/site/index.rst
index 186a14a74e240..baabba6baa2d9 100644
--- a/site/source/docs/site/index.rst
+++ b/site/source/docs/site/index.rst
@@ -5,9 +5,6 @@ Site Links (under-construction)
.. toctree::
:maxdepth: 1
- blogs
about
-
-
diff --git a/site/source/index.rst b/site/source/index.rst
index ad3200f41144b..39b91857e92d8 100644
--- a/site/source/index.rst
+++ b/site/source/index.rst
@@ -14,8 +14,8 @@
News
====
-- `Unity `_ blogs about WebGL support and launches `two public demos `_ (April 29, 2014). There is `more information `_ on the Mozilla blog.
-- The new :doc:`fastcomp/LLVM backend ` has been merged to master and is present in the latest SDK release.
+- `Unity `_ blogs about WebGL support and launches `two public demos `_ (April 29, 2014). See the `Mozilla Blog `_ for more information.
+- The new :doc:`fastcomp/LLVM backend ` has been merged to master and is present in the latest SDK release.
- `Unreal Engine 4 `_ ported to the web using Emscripten (Mar 19, 2014 ). There is `more information `_ on the Mozilla blog.
@@ -27,18 +27,16 @@ News
docs/introducing_emscripten/index
docs/getting_started/index
docs/coding/index
+ docs/optimizing/index
docs/compiling/index
docs/packaging/index
docs/contributing/index
docs/api_reference/index
wiki_static/index
- deleteme_scratchpad
- deleteme_sitechanges
docs/site/about
-
-
+
.. COMMENTS Scratchpad
diff --git a/src/library_browser.js b/src/library_browser.js
index a326a0de5c43e..41ccf8fac693a 100644
--- a/src/library_browser.js
+++ b/src/library_browser.js
@@ -256,146 +256,41 @@ mergeInto(LibraryManager.library, {
},
createContext: function(canvas, useWebGL, setInModule, webGLContextAttributes) {
-#if !USE_TYPED_ARRAYS
- if (useWebGL) {
- Module.print('(USE_TYPED_ARRAYS needs to be enabled for WebGL)');
- return null;
- }
-#endif
- if (useWebGL && Module.ctx) return Module.ctx; // no need to recreate singleton GL context
+ if (useWebGL && Module.ctx && canvas == Module.canvas) return Module.ctx; // no need to recreate GL context if it's already been created for this canvas.
var ctx;
- var errorInfo = '?';
- function onContextCreationError(event) {
- errorInfo = event.statusMessage || errorInfo;
- }
- try {
- if (useWebGL) {
- var contextAttributes = {
- antialias: false,
- alpha: false
- };
-
- if (webGLContextAttributes) {
- for (var attribute in webGLContextAttributes) {
- contextAttributes[attribute] = webGLContextAttributes[attribute];
- }
- }
-
-#if GL_TESTING
- contextAttributes.preserveDrawingBuffer = true;
-#endif
-
- canvas.addEventListener('webglcontextcreationerror', onContextCreationError, false);
- try {
- ['experimental-webgl', 'webgl'].some(function(webglId) {
- return ctx = canvas.getContext(webglId, contextAttributes);
- });
- } finally {
- canvas.removeEventListener('webglcontextcreationerror', onContextCreationError, false);
- }
- } else {
- ctx = canvas.getContext('2d');
- }
- if (!ctx) throw ':(';
- } catch (e) {
- Module.print('Could not create canvas: ' + [errorInfo, e]);
- return null;
- }
+ var contextHandle;
if (useWebGL) {
-#if GL_DEBUG
- function wrapDebugGL(ctx) {
-
- var printObjectList = [];
-
- function prettyPrint(arg) {
- if (typeof arg == 'undefined') return '!UNDEFINED!';
- if (typeof arg == 'boolean') arg = arg + 0;
- if (!arg) return arg;
- var index = printObjectList.indexOf(arg);
- if (index >= 0) return '<' + arg + '|'; // + index + '>';
- if (arg.toString() == '[object HTMLImageElement]') {
- return arg + '\n\n';
- }
- if (arg.byteLength) {
- return '{' + Array.prototype.slice.call(arg, 0, Math.min(arg.length, 400)) + '}'; // Useful for correct arrays, less so for compiled arrays, see the code below for that
- var buf = new ArrayBuffer(32);
- var i8buf = new Int8Array(buf);
- var i16buf = new Int16Array(buf);
- var f32buf = new Float32Array(buf);
- switch(arg.toString()) {
- case '[object Uint8Array]':
- i8buf.set(arg.subarray(0, 32));
- break;
- case '[object Float32Array]':
- f32buf.set(arg.subarray(0, 5));
- break;
- case '[object Uint16Array]':
- i16buf.set(arg.subarray(0, 16));
- break;
- default:
- alert('unknown array for debugging: ' + arg);
- throw 'see alert';
- }
- var ret = '{' + arg.byteLength + ':\n';
- var arr = Array.prototype.slice.call(i8buf);
- ret += 'i8:' + arr.toString().replace(/,/g, ',') + '\n';
- arr = Array.prototype.slice.call(f32buf, 0, 8);
- ret += 'f32:' + arr.toString().replace(/,/g, ',') + '}';
- return ret;
- }
- if (typeof arg == 'object') {
- printObjectList.push(arg);
- return '<' + arg + '|'; // + (printObjectList.length-1) + '>';
- }
- if (typeof arg == 'number') {
- if (arg > 0) return '0x' + arg.toString(16) + ' (' + arg + ')';
- }
- return arg;
- }
+ // For GLES2/desktop GL compatibility, adjust a few defaults to be different to WebGL defaults, so that they align better with the desktop defaults.
+ var contextAttributes = {
+ antialias: false,
+ alpha: false
+ };
- var wrapper = {};
- for (var prop in ctx) {
- (function(prop) {
- switch (typeof ctx[prop]) {
- case 'function': {
- wrapper[prop] = function gl_wrapper() {
- var printArgs = Array.prototype.slice.call(arguments).map(prettyPrint);
- dump('[gl_f:' + prop + ':' + printArgs + ']\n');
- var ret = ctx[prop].apply(ctx, arguments);
- if (typeof ret != 'undefined') {
- dump('[ gl:' + prop + ':return:' + prettyPrint(ret) + ']\n');
- }
- return ret;
- }
- break;
- }
- case 'number': case 'string': {
- wrapper.__defineGetter__(prop, function() {
- //dump('[gl_g:' + prop + ':' + ctx[prop] + ']\n');
- return ctx[prop];
- });
- wrapper.__defineSetter__(prop, function(value) {
- dump('[gl_s:' + prop + ':' + value + ']\n');
- ctx[prop] = value;
- });
- break;
- }
- }
- })(prop);
+ if (webGLContextAttributes) {
+ for (var attribute in webGLContextAttributes) {
+ contextAttributes[attribute] = webGLContextAttributes[attribute];
}
- return wrapper;
}
+#if GL_TESTING
+ contextAttributes.preserveDrawingBuffer = true;
#endif
- // possible GL_DEBUG entry point: ctx = wrapDebugGL(ctx);
+ contextHandle = GL.createContext(canvas, contextAttributes);
+ ctx = GL.getContext(contextHandle).GLctx;
// Set the background of the WebGL canvas to black
canvas.style.backgroundColor = "black";
+ } else {
+ ctx = canvas.getContext('2d');
}
+
+ if (!ctx) return null;
+
if (setInModule) {
if (!useWebGL) assert(typeof GLctx === 'undefined', 'cannot set in module if GLctx is used, but we are a non-GL context that would replace it');
+
Module.ctx = ctx;
- if (useWebGL) GLctx = ctx;
+ if (useWebGL) GL.makeContextCurrent(contextHandle);
Module.useWebGL = useWebGL;
Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() });
Browser.init();
diff --git a/src/library_gl.js b/src/library_gl.js
index a4d560e74c997..79425b9f75369 100644
--- a/src/library_gl.js
+++ b/src/library_gl.js
@@ -20,9 +20,9 @@ var LibraryGL = {
uniforms: [],
shaders: [],
vaos: [],
+ contexts: [],
#if FULL_ES2
- clientBuffers: [],
currArrayBuffer: 0,
currElementArrayBuffer: 0,
#endif
@@ -59,7 +59,10 @@ var LibraryGL = {
init: function() {
GL.createLog2ceilLookup(GL.MAX_TEMP_BUFFER_SIZE);
- Browser.moduleContextCreatedCallbacks.push(GL.initExtensions);
+ GL.miniTempBuffer = new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);
+ for (var i = 0; i < GL.MINI_TEMP_BUFFER_SIZE; i++) {
+ GL.miniTempBufferViews[i] = GL.miniTempBuffer.subarray(0, i+1);
+ }
},
// Records a GL error condition that occurred, stored until user calls glGetError() to fetch it. As per GLES2 spec, only the first error
@@ -90,15 +93,9 @@ var LibraryGL = {
// could cause a GPU-CPU pipeline stall.
// Note that index buffers are not double-buffered (at the moment) in this manner.
MAX_TEMP_BUFFER_SIZE: {{{ GL_MAX_TEMP_BUFFER_SIZE }}},
- tempVertexBuffers1: [],
- tempVertexBufferCounters1: [],
- tempVertexBuffers2: [],
- tempVertexBufferCounters2: [],
// Maximum number of temp VBOs of one size to maintain, after that we start reusing old ones, which is safe but can give
// a performance impact. If CPU-GPU stalls are a problem, increasing this might help.
numTempVertexBuffersPerSize: 64, // (const)
- tempIndexBuffers: [],
- tempQuadIndexBuffer: null,
// Precompute a lookup table for the function ceil(log2(x)), i.e. how many bits are needed to represent x, or,
// if x was rounded up to next pow2, which index is the single '1' bit at?
@@ -118,19 +115,24 @@ var LibraryGL = {
}
},
- generateTempBuffers: function(quads) {
+ generateTempBuffers: function(quads, context) {
var largestIndex = GL.log2ceilLookup[GL.MAX_TEMP_BUFFER_SIZE];
- GL.tempVertexBufferCounters1.length = GL.tempVertexBufferCounters2.length = largestIndex+1;
- GL.tempVertexBuffers1.length = GL.tempVertexBuffers2.length = largestIndex+1;
- GL.tempIndexBuffers.length = largestIndex+1;
+ context.tempVertexBufferCounters1 = [];
+ context.tempVertexBufferCounters2 = [];
+ context.tempVertexBufferCounters1.length = context.tempVertexBufferCounters2.length = largestIndex+1;
+ context.tempVertexBuffers1 = [];
+ context.tempVertexBuffers2 = [];
+ context.tempVertexBuffers1.length = context.tempVertexBuffers2.length = largestIndex+1;
+ context.tempIndexBuffers = [];
+ context.tempIndexBuffers.length = largestIndex+1;
for(var i = 0; i <= largestIndex; ++i) {
- GL.tempIndexBuffers[i] = null; // Created on-demand
- GL.tempVertexBufferCounters1[i] = GL.tempVertexBufferCounters2[i] = 0;
+ context.tempIndexBuffers[i] = null; // Created on-demand
+ context.tempVertexBufferCounters1[i] = context.tempVertexBufferCounters2[i] = 0;
var ringbufferLength = GL.numTempVertexBuffersPerSize;
- GL.tempVertexBuffers1[i] = [];
- GL.tempVertexBuffers2[i] = [];
- var ringbuffer1 = GL.tempVertexBuffers1[i];
- var ringbuffer2 = GL.tempVertexBuffers2[i];
+ context.tempVertexBuffers1[i] = [];
+ context.tempVertexBuffers2[i] = [];
+ var ringbuffer1 = context.tempVertexBuffers1[i];
+ var ringbuffer2 = context.tempVertexBuffers2[i];
ringbuffer1.length = ringbuffer2.length = ringbufferLength;
for(var j = 0; j < ringbufferLength; ++j) {
ringbuffer1[j] = ringbuffer2[j] = null; // Created on-demand
@@ -139,8 +141,8 @@ var LibraryGL = {
if (quads) {
// GL_QUAD indexes can be precalculated
- GL.tempQuadIndexBuffer = GLctx.createBuffer();
- GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.tempQuadIndexBuffer);
+ context.tempQuadIndexBuffer = GLctx.createBuffer();
+ context.GLctx.bindBuffer(context.GLctx.ELEMENT_ARRAY_BUFFER, context.tempQuadIndexBuffer);
var numIndexes = GL.MAX_TEMP_BUFFER_SIZE >> 1;
var quadIndexes = new Uint16Array(numIndexes);
var i = 0, v = 0;
@@ -159,16 +161,16 @@ var LibraryGL = {
if (i >= numIndexes) break;
v += 4;
}
- GLctx.bufferData(GLctx.ELEMENT_ARRAY_BUFFER, quadIndexes, GLctx.STATIC_DRAW);
- GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, null);
+ context.GLctx.bufferData(context.GLctx.ELEMENT_ARRAY_BUFFER, quadIndexes, context.GLctx.STATIC_DRAW);
+ context.GLctx.bindBuffer(context.GLctx.ELEMENT_ARRAY_BUFFER, null);
}
},
getTempVertexBuffer: function getTempVertexBuffer(sizeBytes) {
var idx = GL.log2ceilLookup[sizeBytes];
- var ringbuffer = GL.tempVertexBuffers1[idx];
- var nextFreeBufferIndex = GL.tempVertexBufferCounters1[idx];
- GL.tempVertexBufferCounters1[idx] = (GL.tempVertexBufferCounters1[idx]+1) & (GL.numTempVertexBuffersPerSize-1);
+ var ringbuffer = GL.currentContext.tempVertexBuffers1[idx];
+ var nextFreeBufferIndex = GL.currentContext.tempVertexBufferCounters1[idx];
+ GL.currentContext.tempVertexBufferCounters1[idx] = (GL.currentContext.tempVertexBufferCounters1[idx]+1) & (GL.numTempVertexBuffersPerSize-1);
var vbo = ringbuffer[nextFreeBufferIndex];
if (vbo) {
return vbo;
@@ -183,31 +185,31 @@ var LibraryGL = {
getTempIndexBuffer: function getTempIndexBuffer(sizeBytes) {
var idx = GL.log2ceilLookup[sizeBytes];
- var ibo = GL.tempIndexBuffers[idx];
+ var ibo = GL.currentContext.tempIndexBuffers[idx];
if (ibo) {
return ibo;
}
var prevIBO = GLctx.getParameter(GLctx.ELEMENT_ARRAY_BUFFER_BINDING);
- GL.tempIndexBuffers[idx] = GLctx.createBuffer();
- GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.tempIndexBuffers[idx]);
+ GL.currentContext.tempIndexBuffers[idx] = GLctx.createBuffer();
+ GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.currentContext.tempIndexBuffers[idx]);
GLctx.bufferData(GLctx.ELEMENT_ARRAY_BUFFER, 1 << idx, GLctx.DYNAMIC_DRAW);
GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, prevIBO);
- return GL.tempIndexBuffers[idx];
+ return GL.currentContext.tempIndexBuffers[idx];
},
// Called at start of each new WebGL rendering frame. This swaps the doublebuffered temp VB memory pointers,
// so that every second frame utilizes different set of temp buffers. The aim is to keep the set of buffers
// being rendered, and the set of buffers being updated disjoint.
newRenderingFrameStarted: function newRenderingFrameStarted() {
- var vb = GL.tempVertexBuffers1;
- GL.tempVertexBuffers1 = GL.tempVertexBuffers2;
- GL.tempVertexBuffers2 = vb;
- vb = GL.tempVertexBufferCounters1;
- GL.tempVertexBufferCounters1 = GL.tempVertexBufferCounters2;
- GL.tempVertexBufferCounters2 = vb;
+ var vb = GL.currentContext.tempVertexBuffers1;
+ GL.currentContext.tempVertexBuffers1 = GL.currentContext.tempVertexBuffers2;
+ GL.currentContext.tempVertexBuffers2 = vb;
+ vb = GL.currentContext.tempVertexBufferCounters1;
+ GL.currentContext.tempVertexBufferCounters1 = GL.currentContext.tempVertexBufferCounters2;
+ GL.currentContext.tempVertexBufferCounters2 = vb;
var largestIndex = GL.log2ceilLookup[GL.MAX_TEMP_BUFFER_SIZE];
for(var i = 0; i <= largestIndex; ++i) {
- GL.tempVertexBufferCounters1[i] = 0;
+ GL.currentContext.tempVertexBufferCounters1[i] = 0;
}
},
@@ -479,7 +481,7 @@ var LibraryGL = {
break;
case 0x1406 /* GL_FLOAT */:
#if GL_ASSERTIONS
- if (!GL.floatExt) Module.printErr('Must have OES_texture_float to use float textures');
+ if (!GL.currentContext.floatExt) Module.printErr('Must have OES_texture_float to use float textures');
#endif
switch (format) {
case 0x1907 /* GL_RGB */:
@@ -582,8 +584,8 @@ var LibraryGL = {
GL.resetBufferBinding = false;
// TODO: initial pass to detect ranges we need to upload, might not need an upload per attrib
- for (var i = 0; i < GL.maxVertexAttribs; ++i) {
- var cb = GL.clientBuffers[i];
+ for (var i = 0; i < GL.currentContext.maxVertexAttribs; ++i) {
+ var cb = GL.currentContext.clientBuffers[i];
if (!cb.clientside || !cb.enabled) continue;
GL.resetBufferBinding = true;
@@ -657,48 +659,194 @@ var LibraryGL = {
}
},
#endif
+
+ // Returns the context handle to the new context.
+ createContext: function(canvas, webGLContextAttributes) {
+#if !USE_TYPED_ARRAYS
+ Module.print('(USE_TYPED_ARRAYS needs to be enabled for WebGL)');
+ return null;
+#endif
+ // Default to creating a WebGL 1.0 context if nothing else is specified.
+ if (typeof webGLContextAttributes.majorVersion === 'undefined' && typeof webGLContextAttributes.minorVersion === 'undefined') {
+ webGLContextAttributes.majorVersion = 1;
+ webGLContextAttributes.minorVersion = 0;
+ }
+ var ctx;
+ var errorInfo = '?';
+ function onContextCreationError(event) {
+ errorInfo = event.statusMessage || errorInfo;
+ }
+ try {
+ canvas.addEventListener('webglcontextcreationerror', onContextCreationError, false);
+ try {
+ if (webGLContextAttributes.majorVersion == 1 && webGLContextAttributes.minorVersion == 0) {
+ ctx = canvas.getContext("webgl", webGLContextAttributes) || canvas.getContext("experimental-webgl", webGLContextAttributes);
+ } else {
+ throw 'Unsupported WebGL context version ' + majorVersion + '.' + minorVersion + '!'
+ }
+ } finally {
+ canvas.removeEventListener('webglcontextcreationerror', onContextCreationError, false);
+ }
+ if (!ctx) throw ':(';
+ } catch (e) {
+ Module.print('Could not create canvas: ' + [errorInfo, e]);
+ return 0;
+ }
+#if GL_DEBUG
+ function wrapDebugGL(ctx) {
+
+ var printObjectList = [];
+
+ function prettyPrint(arg) {
+ if (typeof arg == 'undefined') return '!UNDEFINED!';
+ if (typeof arg == 'boolean') arg = arg + 0;
+ if (!arg) return arg;
+ var index = printObjectList.indexOf(arg);
+ if (index >= 0) return '<' + arg + '|'; // + index + '>';
+ if (arg.toString() == '[object HTMLImageElement]') {
+ return arg + '\n\n';
+ }
+ if (arg.byteLength) {
+ return '{' + Array.prototype.slice.call(arg, 0, Math.min(arg.length, 400)) + '}'; // Useful for correct arrays, less so for compiled arrays, see the code below for that
+ var buf = new ArrayBuffer(32);
+ var i8buf = new Int8Array(buf);
+ var i16buf = new Int16Array(buf);
+ var f32buf = new Float32Array(buf);
+ switch(arg.toString()) {
+ case '[object Uint8Array]':
+ i8buf.set(arg.subarray(0, 32));
+ break;
+ case '[object Float32Array]':
+ f32buf.set(arg.subarray(0, 5));
+ break;
+ case '[object Uint16Array]':
+ i16buf.set(arg.subarray(0, 16));
+ break;
+ default:
+ alert('unknown array for debugging: ' + arg);
+ throw 'see alert';
+ }
+ var ret = '{' + arg.byteLength + ':\n';
+ var arr = Array.prototype.slice.call(i8buf);
+ ret += 'i8:' + arr.toString().replace(/,/g, ',') + '\n';
+ arr = Array.prototype.slice.call(f32buf, 0, 8);
+ ret += 'f32:' + arr.toString().replace(/,/g, ',') + '}';
+ return ret;
+ }
+ if (typeof arg == 'object') {
+ printObjectList.push(arg);
+ return '<' + arg + '|'; // + (printObjectList.length-1) + '>';
+ }
+ if (typeof arg == 'number') {
+ if (arg > 0) return '0x' + arg.toString(16) + ' (' + arg + ')';
+ }
+ return arg;
+ }
+
+ var wrapper = {};
+ for (var prop in ctx) {
+ (function(prop) {
+ switch (typeof ctx[prop]) {
+ case 'function': {
+ wrapper[prop] = function gl_wrapper() {
+ var printArgs = Array.prototype.slice.call(arguments).map(prettyPrint);
+ dump('[gl_f:' + prop + ':' + printArgs + ']\n');
+ var ret = ctx[prop].apply(ctx, arguments);
+ if (typeof ret != 'undefined') {
+ dump('[ gl:' + prop + ':return:' + prettyPrint(ret) + ']\n');
+ }
+ return ret;
+ }
+ break;
+ }
+ case 'number': case 'string': {
+ wrapper.__defineGetter__(prop, function() {
+ //dump('[gl_g:' + prop + ':' + ctx[prop] + ']\n');
+ return ctx[prop];
+ });
+ wrapper.__defineSetter__(prop, function(value) {
+ dump('[gl_s:' + prop + ':' + value + ']\n');
+ ctx[prop] = value;
+ });
+ break;
+ }
+ }
+ })(prop);
+ }
+ return wrapper;
+ }
+#endif
+ // possible GL_DEBUG entry point: ctx = wrapDebugGL(ctx);
+
+ if (!ctx) return 0;
+ var handle = GL.getNewId(GL.contexts);
+ var context = { handle: handle };
+ context.GLctx = ctx;
+ GL.contexts[handle] = context;
+ if (typeof webGLContextAttributes['webGLContextAttributes'] === 'undefined' || webGLContextAttributes.enableExtensionsByDefault) {
+ GL.initExtensions(context);
+ }
+ return handle;
+ },
+
+ makeContextCurrent: function(contextHandle) {
+ var context = GL.contexts[contextHandle];
+ if (!context) return false;
+ GLctx = Module.ctx = context.GLctx; // Active WebGL context object.
+ GL.currentContext = context; // Active Emscripten GL layer context object.
+ return true;
+ },
+
+ getContext: function(contextHandle) {
+ return GL.contexts[contextHandle];
+ },
+
+ deleteContext: function(contextHandle) {
+ if (GL.currentContext === GL.contexts[contextHandle]) GL.currentContext = 0;
+ GL.contexts[contextHandle] = null;
+ },
// In WebGL, extensions must be explicitly enabled to be active, see http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.14
// In GLES2, all extensions are enabled by default without additional operations. Init all extensions we need to give to GLES2 user
// code here, so that GLES2 code can operate without changing behavior.
- initExtensions: function() {
- if (GL.initExtensions.done) return;
- GL.initExtensions.done = true;
+ initExtensions: function(context) {
- if (!Module.useWebGL) return; // an app might link both gl and 2d backends
+ // If this function is called without a specific context object, init the extensions of the currently active context.
+ if (!context) context = GL.currentContext;
- GL.miniTempBuffer = new Float32Array(GL.MINI_TEMP_BUFFER_SIZE);
- for (var i = 0; i < GL.MINI_TEMP_BUFFER_SIZE; i++) {
- GL.miniTempBufferViews[i] = GL.miniTempBuffer.subarray(0, i+1);
- }
+ if (context.initExtensionsDone) return;
+ context.initExtensionsDone = true;
+
+ var GLctx = context.GLctx;
- GL.maxVertexAttribs = GLctx.getParameter(GLctx.MAX_VERTEX_ATTRIBS);
+ context.maxVertexAttribs = GLctx.getParameter(GLctx.MAX_VERTEX_ATTRIBS);
#if FULL_ES2
- for (var i = 0; i < GL.maxVertexAttribs; i++) {
- GL.clientBuffers[i] = { enabled: false, clientside: false, size: 0, type: 0, normalized: 0, stride: 0, ptr: 0 };
+ context.clientBuffers = [];
+ for (var i = 0; i < context.maxVertexAttribs; i++) {
+ context.clientBuffers[i] = { enabled: false, clientside: false, size: 0, type: 0, normalized: 0, stride: 0, ptr: 0 };
}
- GL.generateTempBuffers();
+ GL.generateTempBuffers(false, context);
#endif
// Detect the presence of a few extensions manually, this GL interop layer itself will need to know if they exist.
- GL.compressionExt = GLctx.getExtension('WEBGL_compressed_texture_s3tc') ||
+ context.compressionExt = GLctx.getExtension('WEBGL_compressed_texture_s3tc') ||
GLctx.getExtension('MOZ_WEBGL_compressed_texture_s3tc') ||
GLctx.getExtension('WEBKIT_WEBGL_compressed_texture_s3tc');
- GL.anisotropicExt = GLctx.getExtension('EXT_texture_filter_anisotropic') ||
+ context.anisotropicExt = GLctx.getExtension('EXT_texture_filter_anisotropic') ||
GLctx.getExtension('MOZ_EXT_texture_filter_anisotropic') ||
GLctx.getExtension('WEBKIT_EXT_texture_filter_anisotropic');
- GL.floatExt = GLctx.getExtension('OES_texture_float');
+ context.floatExt = GLctx.getExtension('OES_texture_float');
// Extension available from Firefox 26 and Google Chrome 30
- GL.instancedArraysExt = GLctx.getExtension('ANGLE_instanced_arrays');
+ context.instancedArraysExt = GLctx.getExtension('ANGLE_instanced_arrays');
// Extension available from Firefox 25 and WebKit
- GL.vaoExt = Module.ctx.getExtension('OES_vertex_array_object');
+ context.vaoExt = GLctx.getExtension('OES_vertex_array_object');
- GL.drawBuffersExt = Module.ctx.getExtension('WEBGL_draw_buffers');
+ context.drawBuffersExt = GLctx.getExtension('WEBGL_draw_buffers');
// These are the 'safe' feature-enabling extensions that don't add any performance impact related to e.g. debugging, and
// should be enabled by default so that client GLES2/GL code will not need to go through extra hoops to get its stuff working.
@@ -870,7 +1018,7 @@ var LibraryGL = {
glCompressedTexImage2D__sig: 'viiiiiiii',
glCompressedTexImage2D: function(target, level, internalFormat, width, height, border, imageSize, data) {
#if ASSERTIONS
- assert(GL.compressionExt);
+ assert(GL.currentContext.compressionExt);
#endif
if (data) {
data = {{{ makeHEAPView('U8', 'data', 'data+imageSize') }}};
@@ -884,7 +1032,7 @@ var LibraryGL = {
glCompressedTexSubImage2D__sig: 'viiiiiiiii',
glCompressedTexSubImage2D: function(target, level, xoffset, yoffset, width, height, format, imageSize, data) {
#if ASSERTIONS
- assert(GL.compressionExt);
+ assert(GL.currentContext.compressionExt);
#endif
if (data) {
data = {{{ makeHEAPView('U8', 'data', 'data+imageSize') }}};
@@ -1159,7 +1307,7 @@ var LibraryGL = {
glGetVertexAttribfv__sig: 'viii',
glGetVertexAttribfv: function(index, pname, params) {
#if FULL_ES2
- if (GL.clientBuffers[index].enabled) {
+ if (GL.currentContext.clientBuffers[index].enabled) {
Module.printErr("glGetVertexAttribfv on client-side array: not supported, bad data returned");
}
#endif
@@ -1176,7 +1324,7 @@ var LibraryGL = {
glGetVertexAttribiv__sig: 'viii',
glGetVertexAttribiv: function(index, pname, params) {
#if FULL_ES2
- if (GL.clientBuffers[index].enabled) {
+ if (GL.currentContext.clientBuffers[index].enabled) {
Module.printErr("glGetVertexAttribiv on client-side array: not supported, bad data returned");
}
#endif
@@ -1193,7 +1341,7 @@ var LibraryGL = {
glGetVertexAttribPointerv__sig: 'viii',
glGetVertexAttribPointerv: function(index, pname, pointer) {
#if FULL_ES2
- if (GL.clientBuffers[index].enabled) {
+ if (GL.currentContext.clientBuffers[index].enabled) {
Module.printErr("glGetVertexAttribPointer on client-side array: not supported, bad data returned");
}
#endif
@@ -1873,12 +2021,12 @@ var LibraryGL = {
_emulGlGenVertexArrays(n, arrays);
#else
#if GL_ASSERTIONS
- assert(GL.vaoExt, 'Must have OES_vertex_array_object to use vao');
+ assert(GL.currentContext.vaoExt, 'Must have OES_vertex_array_object to use vao');
#endif
for(var i = 0; i < n; i++) {
var id = GL.getNewId(GL.vaos);
- var vao = GL.vaoExt.createVertexArrayOES();
+ var vao = GL.currentContext.vaoExt.createVertexArrayOES();
vao.name = id;
GL.vaos[id] = vao;
{{{ makeSetValue('arrays', 'i*4', 'id', 'i32') }}};
@@ -1895,11 +2043,11 @@ var LibraryGL = {
_emulGlDeleteVertexArrays(n, vaos);
#else
#if GL_ASSERTIONS
- assert(GL.vaoExt, 'Must have OES_vertex_array_object to use vao');
+ assert(GL.currentContext.vaoExt, 'Must have OES_vertex_array_object to use vao');
#endif
for(var i = 0; i < n; i++) {
var id = {{{ makeGetValue('vaos', 'i*4', 'i32') }}};
- GL.vaoExt.deleteVertexArrayOES(GL.vaos[id]);
+ GL.currentContext.vaoExt.deleteVertexArrayOES(GL.vaos[id]);
GL.vaos[id] = null;
}
#endif
@@ -1914,10 +2062,10 @@ var LibraryGL = {
_emulGlBindVertexArray(vao);
#else
#if GL_ASSERTIONS
- assert(GL.vaoExt, 'Must have OES_vertex_array_object to use vao');
+ assert(GL.currentContext.vaoExt, 'Must have OES_vertex_array_object to use vao');
#endif
- GL.vaoExt.bindVertexArrayOES(GL.vaos[vao]);
+ GL.currentContext.vaoExt.bindVertexArrayOES(GL.vaos[vao]);
#endif
},
@@ -1930,12 +2078,12 @@ var LibraryGL = {
return _emulGlIsVertexArray(array);
#else
#if GL_ASSERTIONS
- assert(GL.vaoExt, 'Must have OES_vertex_array_object to use vao');
+ assert(GL.currentContext.vaoExt, 'Must have OES_vertex_array_object to use vao');
#endif
var vao = GL.vaos[array];
if (!vao) return 0;
- return GL.vaoExt.isVertexArrayOES(vao);
+ return GL.currentContext.vaoExt.isVertexArrayOES(vao);
#endif
},
@@ -2139,8 +2287,8 @@ var LibraryGL = {
case 0x1F03 /* GL_EXTENSIONS */: // Add various extensions that we can support
var ret = allocate(intArrayFromString(GLctx.getSupportedExtensions().join(' ') +
' GL_EXT_texture_env_combine GL_ARB_texture_env_crossbar GL_ATI_texture_env_combine3 GL_NV_texture_env_combine4 GL_EXT_texture_env_dot3 GL_ARB_multitexture GL_ARB_vertex_buffer_object GL_EXT_framebuffer_object GL_ARB_vertex_program GL_ARB_fragment_program GL_ARB_shading_language_100 GL_ARB_shader_objects GL_ARB_vertex_shader GL_ARB_fragment_shader GL_ARB_texture_cube_map GL_EXT_draw_range_elements' +
- (GL.compressionExt ? ' GL_ARB_texture_compression GL_EXT_texture_compression_s3tc' : '') +
- (GL.anisotropicExt ? ' GL_EXT_texture_filter_anisotropic' : '')
+ (GL.currentContext.compressionExt ? ' GL_ARB_texture_compression GL_EXT_texture_compression_s3tc' : '') +
+ (GL.currentContext.anisotropicExt ? ' GL_EXT_texture_filter_anisotropic' : '')
), 'i8', ALLOC_NORMAL);
GL.stringCache[name_] = ret;
return ret;
@@ -4424,7 +4572,7 @@ var LibraryGL = {
GLImmediate.vertexDataU8 = new Uint8Array(GLImmediate.tempData.buffer);
- GL.generateTempBuffers(true);
+ GL.generateTempBuffers(true, GL.currentContext);
GLImmediate.clientColor = new Float32Array([1, 1, 1, 1]);
},
@@ -4602,7 +4750,7 @@ var LibraryGL = {
#if ASSERTIONS
assert(ptr + (numIndexes << 1) <= GL.MAX_TEMP_BUFFER_SIZE, 'too many immediate mode indexes (b)');
#endif
- GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.tempQuadIndexBuffer);
+ GLctx.bindBuffer(GLctx.ELEMENT_ARRAY_BUFFER, GL.currentContext.tempQuadIndexBuffer);
emulatedElementArrayBuffer = true;
}
@@ -5274,7 +5422,7 @@ var LibraryGL = {
glVertexAttribPointer__sig: 'viiiiii',
glVertexAttribPointer: function(index, size, type, normalized, stride, ptr) {
#if FULL_ES2
- var cb = GL.clientBuffers[index];
+ var cb = GL.currentContext.clientBuffers[index];
#if ASSERTIONS
assert(cb, index);
#endif
@@ -5298,7 +5446,7 @@ var LibraryGL = {
glEnableVertexAttribArray__sig: 'vi',
glEnableVertexAttribArray: function(index) {
#if FULL_ES2
- var cb = GL.clientBuffers[index];
+ var cb = GL.currentContext.clientBuffers[index];
#if ASSERTIONS
assert(cb, index);
#endif
@@ -5310,7 +5458,7 @@ var LibraryGL = {
glDisableVertexAttribArray__sig: 'vi',
glDisableVertexAttribArray: function(index) {
#if FULL_ES2
- var cb = GL.clientBuffers[index];
+ var cb = GL.currentContext.clientBuffers[index];
#if ASSERTIONS
assert(cb, index);
#endif
@@ -5393,25 +5541,25 @@ var LibraryGL = {
glVertexAttribDivisor__sig: 'vii',
glVertexAttribDivisor: function(index, divisor) {
#if GL_ASSERTIONS
- assert(GL.instancedArraysExt, 'Must have ANGLE_instanced_arrays extension to use WebGL instancing');
+ assert(GL.currentContext.instancedArraysExt, 'Must have ANGLE_instanced_arrays extension to use WebGL instancing');
#endif
- GL.instancedArraysExt.vertexAttribDivisorANGLE(index, divisor);
+ GL.currentContext.instancedArraysExt.vertexAttribDivisorANGLE(index, divisor);
},
glDrawArraysInstanced__sig: 'viiii',
glDrawArraysInstanced: function(mode, first, count, primcount) {
#if GL_ASSERTIONS
- assert(GL.instancedArraysExt, 'Must have ANGLE_instanced_arrays extension to use WebGL instancing');
+ assert(GL.currentContext.instancedArraysExt, 'Must have ANGLE_instanced_arrays extension to use WebGL instancing');
#endif
- GL.instancedArraysExt.drawArraysInstancedANGLE(mode, first, count, primcount);
+ GL.currentContext.instancedArraysExt.drawArraysInstancedANGLE(mode, first, count, primcount);
},
glDrawElementsInstanced__sig: 'viiiii',
glDrawElementsInstanced: function(mode, count, type, indices, primcount) {
#if GL_ASSERTIONS
- assert(GL.instancedArraysExt, 'Must have ANGLE_instanced_arrays extension to use WebGL instancing');
+ assert(GL.currentContext.instancedArraysExt, 'Must have ANGLE_instanced_arrays extension to use WebGL instancing');
#endif
- GL.instancedArraysExt.drawElementsInstancedANGLE(mode, count, type, indices, primcount);
+ GL.currentContext.instancedArraysExt.drawElementsInstancedANGLE(mode, count, type, indices, primcount);
},
// OpenGL Desktop/ES 2.0 instancing extensions compatibility
@@ -5430,13 +5578,13 @@ var LibraryGL = {
glDrawBuffers__sig: 'vii',
glDrawBuffers: function(n, bufs) {
#if GL_ASSERTIONS
- assert(GL.drawBuffersExt, 'Must have WEBGL_draw_buffers extension to use drawBuffers');
+ assert(GL.currentContext.drawBuffersExt, 'Must have WEBGL_draw_buffers extension to use drawBuffers');
#endif
var bufArray = [];
for (var i = 0; i < n; i++)
bufArray.push({{{ makeGetValue('bufs', 'i*4', 'i32') }}});
- GL.drawBuffersExt.drawBuffersWEBGL(bufArray);
+ GL.currentContext.drawBuffersExt.drawBuffersWEBGL(bufArray);
},
// signatures of simple pass-through functions, see later
diff --git a/src/library_html5.js b/src/library_html5.js
index 238575de574bb..7e995cdd988f1 100644
--- a/src/library_html5.js
+++ b/src/library_html5.js
@@ -1304,6 +1304,64 @@ var LibraryJSEvents = {
return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}};
},
+ emscripten_webgl_init_context_attributes: function(attributes) {
+ {{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.alpha, 1, 'i32') }}};
+ {{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.depth, 1, 'i32') }}};
+ {{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.stencil, 0, 'i32') }}};
+ {{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.antialias, 1, 'i32') }}};
+ {{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.premultipliedAlpha, 1, 'i32') }}};
+ {{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.preserveDrawingBuffer, 0, 'i32') }}};
+ {{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.preferLowPowerToHighPerformance, 0, 'i32') }}};
+ {{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.failIfMajorPerformanceCaveat, 0, 'i32') }}};
+ {{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.majorVersion, 1, 'i32') }}};
+ {{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.minorVersion, 0, 'i32') }}};
+ {{{ makeSetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.enableExtensionsByDefault, 1, 'i32') }}};
+ },
+
+ emscripten_webgl_create_context: function(target, attributes) {
+ var contextAttributes = {};
+ contextAttributes.alpha = !!{{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.alpha, 'i32') }}};
+ contextAttributes.depth = !!{{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.depth, 'i32') }}};
+ contextAttributes.stencil = !!{{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.stencil, 'i32') }}};
+ contextAttributes.antialias = !!{{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.antialias, 'i32') }}};
+ contextAttributes.premultipliedAlpha = !!{{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.premultipliedAlpha, 'i32') }}};
+ contextAttributes.preserveDrawingBuffer = !!{{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.preserveDrawingBuffer, 'i32') }}};
+ contextAttributes.preferLowPowerToHighPerformance = !!{{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.preferLowPowerToHighPerformance, 'i32') }}};
+ contextAttributes.failIfMajorPerformanceCaveat = !!{{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.failIfMajorPerformanceCaveat, 'i32') }}};
+ var majorVersion = {{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.majorVersion, 'i32') }}};
+ var minorVersion = {{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.minorVersion, 'i32') }}};
+ var enableExtensionsByDefault = {{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.enableExtensionsByDefault, 'i32') }}};
+
+ if (!target) {
+ target = Module['canvas'];
+ } else {
+ target = JSEvents.findEventTarget(target);
+ }
+ var contextHandle = GL.createContext(target, contextAttributes);
+ return contextHandle;
+ },
+
+ emscripten_webgl_make_context_current: function(contextHandle) {
+ var success = GL.makeContextCurrent(contextHandle);
+ return success ? {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}} : {{{ cDefine('EMSCRIPTEN_RESULT_INVALID_PARAM') }}};
+ },
+
+ emscripten_webgl_get_current_context: function() {
+ return GL.currentContext ? GL.currentContext.handle : 0;
+ },
+
+ emscripten_webgl_destroy_context: function(contextHandle) {
+ GL.deleteContext(contextHandle);
+ },
+
+ emscripten_webgl_enable_extension: function(contextHandle, extension) {
+ var context = GL.getContext(contextHandle);
+ var extString = Pointer_stringify(extension);
+ if (extString.indexOf('GL_') == 0) extString = extString.substr(3); // Allow enabling extensions both with "GL_" prefix and without.
+ var ext = context.GLctx.getExtension(extString);
+ return ext ? 1 : 0;
+ },
+
emscripten_set_webglcontextlost_callback: function(target, userData, useCapture, callbackfunc) {
JSEvents.registerWebGlEventCallback(target, userData, useCapture, callbackfunc, {{{ cDefine('EMSCRIPTEN_EVENT_WEBGLCONTEXTLOST') }}}, "webglcontextlost");
return {{{ cDefine('EMSCRIPTEN_RESULT_SUCCESS') }}};
diff --git a/src/library_sdl.js b/src/library_sdl.js
index c00c0d6c7925b..7025c4078aa46 100644
--- a/src/library_sdl.js
+++ b/src/library_sdl.js
@@ -1325,6 +1325,7 @@ var LibrarySDL = {
return buf;
},
+ SDL_SetVideoMode__deps: ['$GL'],
SDL_SetVideoMode: function(width, height, depth, flags) {
['touchstart', 'touchend', 'touchmove', 'mousedown', 'mouseup', 'mousemove', 'DOMMouseScroll', 'mousewheel', 'wheel', 'mouseout'].forEach(function(event) {
Module['canvas'].addEventListener(event, SDL.receiveEvent, true);
diff --git a/src/postamble.js b/src/postamble.js
index cbf6450f5c376..7fd4eb1951505 100644
--- a/src/postamble.js
+++ b/src/postamble.js
@@ -179,10 +179,15 @@ function exit(status) {
// Instead of process.exit() directly, wait for stdout flush event.
// See https://github.com/joyent/node/issues/1669 and https://github.com/kripken/emscripten/issues/2582
// Workaround is based on https://github.com/RReverser/acorn/commit/50ab143cecc9ed71a2d66f78b4aec3bb2e9844f6
- process.stdout.once('drain', function () {
+ process['stdout']['once']('drain', function () {
process['exit'](status);
});
console.log(' '); // Make sure to print something to force the drain event to occur, in case the stdout buffer was empty.
+ // Work around another node bug where sometimes 'drain' is never fired - make another effort
+ // to emit the exit status, after a significant delay (if node hasn't fired drain by then, give up)
+ setTimeout(function() {
+ process['exit'](status);
+ }, 500);
} else if (ENVIRONMENT_IS_SHELL && typeof quit === 'function') {
quit(status);
} else {
diff --git a/src/shell.js b/src/shell.js
index 7748ae72c704d..7f556fb9fde39 100644
--- a/src/shell.js
+++ b/src/shell.js
@@ -73,7 +73,9 @@ if (ENVIRONMENT_IS_NODE) {
Module['thisProgram'] = process['argv'][1];
Module['arguments'] = process['argv'].slice(2);
- module['exports'] = Module;
+ if (typeof module !== 'undefined') {
+ module['exports'] = Module;
+ }
}
else if (ENVIRONMENT_IS_SHELL) {
if (!Module['print']) Module['print'] = print;
diff --git a/src/struct_info.json b/src/struct_info.json
index 94a64845cd5f3..17545c3da0fa1 100644
--- a/src/struct_info.json
+++ b/src/struct_info.json
@@ -1297,6 +1297,19 @@
"dischargingTime",
"level",
"charging"
+ ],
+ "EmscriptenWebGLContextAttributes": [
+ "alpha",
+ "depth",
+ "stencil",
+ "antialias",
+ "premultipliedAlpha",
+ "preserveDrawingBuffer",
+ "preferLowPowerToHighPerformance",
+ "failIfMajorPerformanceCaveat",
+ "majorVersion",
+ "minorVersion",
+ "enableExtensionsByDefault"
]
}
}
diff --git a/system/include/emscripten/html5.h b/system/include/emscripten/html5.h
index 9ffb4ece9e098..98192e289e543 100644
--- a/system/include/emscripten/html5.h
+++ b/system/include/emscripten/html5.h
@@ -648,6 +648,92 @@ extern EMSCRIPTEN_RESULT emscripten_vibrate_pattern(int *msecsArray, int numEntr
typedef const char *(*em_beforeunload_callback)(int eventType, const void *reserved, void *userData);
extern EMSCRIPTEN_RESULT emscripten_set_beforeunload_callback(void *userData, em_beforeunload_callback callback);
+// Represents a handle to an Emscripten WebGL context object. The value 0 denotes an invalid/no context.
+typedef int EMSCRIPTEN_WEBGL_CONTEXT_HANDLE;
+
+/*
+ * Specifies WebGL context creation parameters, as documented at http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.2
+ */
+typedef struct EmscriptenWebGLContextAttributes {
+ // If true, request an alpha channel for the context. If you create an alpha channel, you can blend the canvas rendering with the
+ // underlying web page contents. Default value: true.
+ EM_BOOL alpha;
+ // If true, request a depth buffer of at least 16 bits. If false, no depth buffer will be initialized. Default value: true.
+ EM_BOOL depth;
+ // If true, request a stencil buffer of at least 8 bits. If false, no stencil buffer will be initialized. Default value: false.
+ EM_BOOL stencil;
+ // If true, antialiasing will be initialized with a browser-specified algorithm and quality level. If false, antialiasing is disabled. Default value: true.
+ EM_BOOL antialias;
+ // If true, the alpha channel of the rendering context will be treated as representing premultiplied alpha values. If false, the alpha
+ // channel represents non-premultiplied alpha. Default value: true.
+ EM_BOOL premultipliedAlpha;
+ // If true, the contents of the drawing buffer are preserved between consecutive requestAnimationFrame() calls. If false, color, depth
+ // and stencil are cleared at the beginning of each requestAnimationFrame(). Generally setting this to false gives better performance. Default value: false.
+ EM_BOOL preserveDrawingBuffer;
+ // If true, hints the browser to initialize a low-power GPU rendering context. If false, prefers to initialize a high-performance
+ // rendering context. Default value: false.
+ EM_BOOL preferLowPowerToHighPerformance;
+ // If true, requests context creation to abort if the browser is only able to create a context that does not give good
+ // hardware-accelerated performance. Default value: false.
+ EM_BOOL failIfMajorPerformanceCaveat;
+
+ // Emscripten-specific extensions:
+ // majorVersion x minorVersion: Specifies the WebGL context version to initialize.
+ // For example, pass in majorVersion=1, minorVersion=0 to request a WebGL 1.0 context, and
+ // majorVersion=2, minorVersion=0 to request a WebGL 2.0 context.
+ // Default value: majorVersion=1, minorVersion=0
+ int majorVersion;
+ int minorVersion;
+
+ // If true, all GLES2-compatible non-performance-impacting WebGL extensions will automatically be enabled for you after the context
+ // has been created. If false, no extensions are enabled by default, and you need to manually call emscripten_webgl_enable_extension()
+ // to enable each extension that you want to use. Default value: true.
+ EM_BOOL enableExtensionsByDefault;
+} EmscriptenWebGLContextAttributes;
+
+/*
+ * Populates all fields of the given EmscriptenWebGLContextAttributes structure to their default values for use with WebGL 1.0.
+ * Call this function as a forward-compatible way to ensure that if there are new fields added to the EmscriptenWebGLContextAttributes
+ * structure in the future, that they also will get default-initialized without having to change any code.
+ */
+extern void emscripten_webgl_init_context_attributes(EmscriptenWebGLContextAttributes *attributes);
+
+/*
+ * Creates a new WebGL context. See http://www.khronos.org/registry/webgl/specs/latest/1.0/#2.1
+ * The parameter 'target' specifies the DOM canvas element in which to initialize the WebGL context. If 0 is passed for the target,
+ * the element specified by Module.canvas will be used.
+ * On success, this function returns a strictly positive value that represents a handle to the created context.
+ * On failure, this function returns a negative number that can be casted to a EMSCRIPTEN_RESULT field to get an error reason
+ * why the context creation failed.
+ * NOTE: A successful call to emscripten_webgl_create_context() will not immediately make that rendering context active. Call
+ * emscripten_webgl_make_context_current() after creating a context to activate it.
+ * NOTE: This function will try to initialize the context version that was *exactly* requested. It will not e.g. initialize a newer
+ * backwards-compatible version or similar.
+ */
+extern EMSCRIPTEN_WEBGL_CONTEXT_HANDLE emscripten_webgl_create_context(const char *target, const EmscriptenWebGLContextAttributes *attributes);
+
+/*
+ * Activates the given WebGL context for rendering. After calling this function, all gl***() functions apply to the given GL context.
+ */
+extern EMSCRIPTEN_RESULT emscripten_webgl_make_context_current(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context);
+
+/*
+ * Returns the currently active WebGL rendering context, or 0 if no such context is active. Calling any WebGL functions when there is no active
+ * rendering context is undefined and may throw a JavaScript exception.
+ */
+extern EMSCRIPTEN_WEBGL_CONTEXT_HANDLE emscripten_webgl_get_current_context();
+
+/*
+ * Deletes the given WebGL context. If that context was active, then the no context is set to active.
+ */
+extern EMSCRIPTEN_RESULT emscripten_webgl_destroy_context(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context);
+
+/*
+ * Enables the given extension on the given context.
+ * Returns EM_TRUE if the given extension is supported by the context, and EM_FALSE if the extension was not available.
+ */
+extern EM_BOOL emscripten_webgl_enable_extension(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context, const char *extension);
+
/*
* Registers a callback function for the canvas webgl context webglcontextlost and webglcontextrestored events.
* See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
diff --git a/tests/runner.py b/tests/runner.py
index 7c5548180e49a..629047dfe5ea6 100755
--- a/tests/runner.py
+++ b/tests/runner.py
@@ -26,6 +26,7 @@ def path_from_root(*pathelems):
sys.path += [path_from_root(''), path_from_root('third_party/websockify')]
import tools.shared
from tools.shared import *
+from tools.line_endings import check_line_endings
# Utils
@@ -268,6 +269,7 @@ def run_generated_code(self, engine, filename, args=[], check_timeout=True, outp
except:
cwd = None
os.chdir(self.get_dir())
+ assert(check_line_endings(filename) == 0) # Make sure that we produced proper line endings to the .js file we are about to run.
run_js(filename, engine, args, check_timeout, stdout=open(stdout, 'w'), stderr=open(stderr, 'w'), assert_returncode=assert_returncode)
if cwd is not None:
os.chdir(cwd)
diff --git a/tests/test_browser.py b/tests/test_browser.py
index 0ff0ea8167049..281e5852fe991 100644
--- a/tests/test_browser.py
+++ b/tests/test_browser.py
@@ -1900,6 +1900,11 @@ def test_html5(self):
print opts
self.btest(path_from_root('tests', 'test_html5.c'), args=opts, expected='0')
+ def test_html5_webgl_create_context(self):
+ for opts in [[], ['-O2', '-g1', '--closure', '1']]:
+ print opts
+ self.btest(path_from_root('tests', 'webgl_create_context.cpp'), args=opts, expected='0')
+
def test_sdl_touch(self):
for opts in [[], ['-O2', '-g1', '--closure', '1']]:
print opts
diff --git a/tests/test_core.py b/tests/test_core.py
index 19bfb8680a7d4..bf33b8ef1b5db 100644
--- a/tests/test_core.py
+++ b/tests/test_core.py
@@ -3,6 +3,7 @@
import glob, hashlib, os, re, shutil, subprocess, sys
import tools.shared
from tools.shared import *
+from tools.line_endings import check_line_endings
from runner import RunnerCore, path_from_root, checked_sanity, test_modes, get_bullet_library
class T(RunnerCore): # Short name, to make it more fun to use manually on the commandline
@@ -478,6 +479,9 @@ def test_negative_zero(self):
self.do_run_from_file(src, output)
+ def test_line_endings(self):
+ self.build(open(path_from_root('tests', 'hello_world.cpp')).read(), self.get_dir(), self.in_dir('hello_world.cpp'))
+
def test_literal_negative_zero(self):
if self.emcc_args == None: return self.skip('needs emcc')
@@ -1501,6 +1505,7 @@ def test_exceptions_alias(self):
def test_bad_typeid(self):
if self.emcc_args is None: return self.skip('requires emcc')
+ if os.environ.get('EMCC_FAST_COMPILER') == '0': return self.skip('needs fastcomp')
Settings.ERROR_ON_UNDEFINED_SYMBOLS = 1
Settings.DISABLE_EXCEPTION_CATCHING = 0
diff --git a/tests/test_other.py b/tests/test_other.py
index 999ca92b8e11b..b3f6954b77fc3 100644
--- a/tests/test_other.py
+++ b/tests/test_other.py
@@ -1517,7 +1517,7 @@ def test_exclude_file(self):
Popen([PYTHON, EMCC, os.path.join(self.get_dir(), 'main.cpp'), '--embed-file', 'tst', '--exclude-file', '*.exe']).communicate()
output = run_js(os.path.join(self.get_dir(), 'a.out.js'))
- assert output == ''
+ assert output == '' or output == ' \n'
def test_multidynamic_link(self):
# Linking the same dynamic library in statically will error, normally, since we statically link it, causing dupe symbols
diff --git a/tests/webgl_create_context.cpp b/tests/webgl_create_context.cpp
new file mode 100644
index 0000000000000..f116e2ece8927
--- /dev/null
+++ b/tests/webgl_create_context.cpp
@@ -0,0 +1,116 @@
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+std::vector &split(const std::string &s, char delim, std::vector &elems) {
+ std::stringstream ss(s);
+ std::string item;
+ while (std::getline(ss, item, delim)) {
+ elems.push_back(item);
+ }
+ return elems;
+}
+std::vector split(const std::string &s, char delim) {
+ std::vector elems;
+ split(s, delim, elems);
+ return elems;
+}
+
+GLint GetInt(GLenum param)
+{
+ GLint value;
+ glGetIntegerv(param, &value);
+ return value;
+}
+
+int main()
+{
+ bool first = true;
+ EmscriptenWebGLContextAttributes attrs;
+ for(int depth = 0; depth <= 1; ++depth)
+ for(int stencil = 0; stencil <= 1; ++stencil)
+ for(int antialias = 0; antialias <= 1; ++antialias)
+ {
+ emscripten_webgl_init_context_attributes(&attrs);
+ attrs.depth = depth;
+ attrs.stencil = stencil;
+ attrs.antialias = antialias;
+ printf("Requesting depth: %d, stencil: %d, antialias: %d\n", depth, stencil, antialias);
+
+ if (!first)
+ {
+ EM_ASM(var canvas2 = Module.canvas.cloneNode();
+ Module.canvas.parentElement.appendChild(canvas2);
+ // Module.canvas.parentElement.removeChild(canvas);
+ Module.canvas = canvas2;
+ );
+ }
+ first = false;
+
+ assert(emscripten_webgl_get_current_context() == 0);
+ EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context = emscripten_webgl_create_context(0, &attrs);
+ assert(context > 0); // Must have received a valid context.
+ EMSCRIPTEN_RESULT res = emscripten_webgl_make_context_current(context);
+ assert(res == EMSCRIPTEN_RESULT_SUCCESS);
+ assert(emscripten_webgl_get_current_context() == context);
+
+ // Let's try enabling all extensions.
+ const char *extensions = (const char*)glGetString(GL_EXTENSIONS);
+ std::vector exts = split(extensions, ' ');
+ for(size_t i = 0; i < exts.size(); ++i)
+ {
+ EM_BOOL supported = emscripten_webgl_enable_extension(context, exts[i].c_str());
+ assert(supported);
+ }
+
+ // Try with a simple glClear() that we got a context.
+ glClearColor(1.f, 0.f, 0.f, 1.f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ unsigned char pixels[4];
+ glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ assert(pixels[0] == 0xFF);
+ assert(pixels[1] == 0);
+ assert(pixels[2] == 0);
+ assert(pixels[3] == 0xFF);
+
+ int numDepthBits = GetInt(GL_DEPTH_BITS);
+ int numStencilBits = GetInt(GL_STENCIL_BITS);
+ int numSamples = GetInt(GL_SAMPLES);
+ printf("RGBA: %d%d%d%d, Depth: %d, Stencil: %d, Samples: %d\n",
+ GetInt(GL_RED_BITS), GetInt(GL_GREEN_BITS), GetInt(GL_BLUE_BITS), GetInt(GL_ALPHA_BITS),
+ numDepthBits, numStencilBits, numSamples);
+
+ if (!depth && stencil && numDepthBits && numStencilBits && EM_ASM_INT_V(navigator.userAgent.toLowerCase().indexOf('firefox')) > -1)
+ {
+ numDepthBits = 0;
+ printf("Applying workaround to ignore Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=982477\n");
+ }
+ assert(!!numDepthBits == !!depth);
+ assert(!!numStencilBits == !!stencil);
+ assert(!!numSamples == !!antialias);
+ printf("\n");
+
+ // Test that deleting the context works.
+ res = emscripten_webgl_destroy_context(context);
+ assert(res == 0);
+ assert(emscripten_webgl_get_current_context() == 0);
+ }
+
+#ifdef REPORT_RESULT
+ int result = 0;
+ REPORT_RESULT();
+#endif
+ return 0;
+}
diff --git a/tools/line_endings.py b/tools/line_endings.py
new file mode 100644
index 0000000000000..e1c8797e39009
--- /dev/null
+++ b/tools/line_endings.py
@@ -0,0 +1,40 @@
+import sys
+
+# This function checks and prints out the detected line endings in the given file.
+# If the file only contains either Windows \r\n line endings or Unix \n line endings, it returns 0.
+# Otherwise, in the presence of old OSX or mixed/malformed line endings, a non-zero error code is returned.
+def check_line_endings(filename, print_errors=True):
+ try:
+ data = open(filename, 'rb').read()
+ except Exception, e:
+ if print_errors: print >> sys.stderr, "Unable to read file '" + filename + "'! " + str(e)
+ return 1
+ if len(data) == 0:
+ if print_errors: print >> sys.stderr, "Unable to read file '" + filename + "', or file was empty!"
+ return 1
+
+ if "\r\r\n" in data:
+ if print_errors: print >> sys.stderr, "File '" + filename + "' contains BAD line endings of form \\r\\r\\n!"
+ return 1 # Bad line endings in file, return a non-zero process exit code.
+
+ has_dos_line_endings = False
+ has_unix_line_endings = False
+ if '\r\n' in data:
+ has_dos_line_endings = True
+ data = data.replace('\r\n', 'A') # Replace all DOS line endings with some other character, and continue testing what's left.
+ if '\n' in data:
+ has_unix_line_endings = True
+ if '\r' in data:
+ if print_errors: print >> sys.stderr, 'File \'' + filename + '\' contains OLD OSX line endings "\\r"'
+ return 1 # Return a non-zero process exit code since we don't want to use the old OSX (9.x) line endings anywhere.
+ if has_dos_line_endings and has_unix_line_endings:
+ if print_errors: print >> sys.stderr, 'File \'' + filename + '\' contains both DOS "\\r\\n" and UNIX "\\n" line endings!'
+ return 1 # Mixed line endings
+ else: return 0
+
+if __name__ == '__main__':
+ if len(sys.argv) != 2:
+ print >> sys.stderr, 'Unknown command line ' + str(sys.argv) + '!'
+ print >> sys.stderr, 'Usage: ' + sys.argv[0] + ' '
+ sys.exit(1)
+ sys.exit(check_line_endings(sys.argv[1]))