Skip to content

Commit

Permalink
Make WebGL context attribute explicitSwapControl imply renderViaOffsc…
Browse files Browse the repository at this point in the history
…reenBackBuffer when OffscreenCanvas is not supported. Add testing for OFFSCREEN_FRAMEBUFFER mode. Add documentation for OFFSCREEN_FRAMEBUFFER.
  • Loading branch information
juj committed Jul 13, 2018
1 parent e8091d7 commit 90e38e5
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 4 deletions.
23 changes: 22 additions & 1 deletion site/source/docs/api_reference/html5.h.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1949,6 +1949,20 @@ Struct
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 :c:func:`emscripten_webgl_enable_extension` to enable each extension that you want to use. Default value: ``true``.
.. c:member:: EM_BOOL explicitSwapControl
By default, when ``explicitSwapControl`` is in its default state ``false``, rendered WebGL content is implicitly presented (displayed to the user) on the canvas when the event handler that renders with WebGL returns back to the browser event loop. If ``explicitSwapControl`` is set to ``true``, rendered content will not be displayed on screen automatically when event handler function finishes, but the control of swapping is given to the user to manage, via the ``emscripten_webgl_commit_frame()`` function.
In order to be able to set ``explicitSwapControl==true``, support for it must explicitly be enabled either 1) via adding the ``-s OFFSCREEN_FRAMEBUFFER=1`` Emscripten linker flag, and enabling ``renderViaOffscreenBackBuffer==1``, or 2) via adding the the linker flag ``-s OFFSCREENCANVAS_SUPPORT=1``, and running in a browser that supports OffscreenCanvas.
.. c:member:: EM_BOOL renderViaOffscreenBackBuffer
If ``true``, an extra intermediate backbuffer (offscreen render target) is allocated to the created WebGL context, and rendering occurs to this backbuffer instead of directly onto the WebGL "default backbuffer". This is required to be enabled if 1) ``explicitSwapControl==true`` and the browser does not support OffscreenCanvas, 2) when performing WebGL rendering in a worker thread and the browser does not support OffscreenCanvas, and 3) when performing WebGL context accesses from multiple threads simultaneously (independent of whether OffscreenCanvas is supported or not).
Because supporting offscreen framebuffer adds some amount of extra code to the compiled output, support for it must explicitly be enabled via the ``-s OFFSCREEN_FRAMEBUFFER=1`` Emscripten linker flag. When building simultaneously with both ``-s OFFSCREEN_FRAMEBUFFER=1`` and ``-s OFFSCREENCANVAS_SUPPORT=1`` linker flags enabled, offscreen backbuffer can be used as a polyfill-like compatibility fallback to enable rendering WebGL from a pthread when the browser does not support the OffscreenCanvas API.
Callback functions
------------------
Expand Down Expand Up @@ -2044,7 +2058,14 @@ Functions
:rtype: |EMSCRIPTEN_WEBGL_CONTEXT_HANDLE|
.. c:function:: EMSCRIPTEN_RESULT emscripten_webgl_commit_frame()
Presents ("swaps") the content rendered on the currently active WebGL context to be visible on the canvas. This function is available on WebGL contexts that were created with the ``explicitSwapControl==true`` context creation attribute. If ``explicitSwapControl==false``, then the rendered content is displayed on the screen "implicitly" when yielding back to the browser from the calling event handler.
:returns: :c:data:`EMSCRIPTEN_RESULT_SUCCESS`, or one of the other result values, denoting a reason for failure.
:rtype: |EMSCRIPTEN_RESULT|
.. c:function:: EMSCRIPTEN_RESULT emscripten_webgl_get_drawing_buffer_size(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context, int *width, int *height)
Gets the ``drawingBufferWidth`` and ``drawingBufferHeight`` of the specified WebGL context.
Expand Down
16 changes: 14 additions & 2 deletions src/library_html5.js
Original file line number Diff line number Diff line change
Expand Up @@ -1814,6 +1814,7 @@ var LibraryJSEvents = {
contextAttributes['minorVersion'] = {{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.minorVersion, 'i32') }}};
var enableExtensionsByDefault = {{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.enableExtensionsByDefault, 'i32') }}};
contextAttributes['explicitSwapControl'] = {{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.explicitSwapControl, 'i32') }}};
contextAttributes['renderViaOffscreenBackBuffer'] = {{{ makeGetValue('attributes', C_STRUCTS.EmscriptenWebGLContextAttributes.renderViaOffscreenBackBuffer, 'i32') }}};

target = Pointer_stringify(target);
var canvas;
Expand All @@ -1836,7 +1837,9 @@ var LibraryJSEvents = {
#if OFFSCREEN_FRAMEBUFFER
if (!contextAttributes['renderViaOffscreenBackBuffer']) {
contextAttributes['renderViaOffscreenBackBuffer'] = true;
#if GL_DEBUG
console.error('emscripten_webgl_create_context: Performance warning, OffscreenCanvas is not supported but explicitSwapControl was requested, so force-enabling renderViaOffscreenBackBuffer=true to allow explicit swapping!');
#endif
}
#else
#if GL_DEBUG
Expand All @@ -1852,14 +1855,23 @@ var LibraryJSEvents = {
canvas = GL.offscreenCanvases[canvas.id];
}
}
#else
#else // !OFFSCREENCANVAS_SUPPORT
#if !OFFSCREEN_FRAMEBUFFER
#if OFFSCREEN_FRAMEBUFFER
if (contextAttributes['explicitSwapControl'] && !contextAttributes['renderViaOffscreenBackBuffer']) {
contextAttributes['renderViaOffscreenBackBuffer'] = true;
#if GL_DEBUG
console.error('emscripten_webgl_create_context: Performance warning, not building with OffscreenCanvas support enabled but explicitSwapControl was requested, so force-enabling renderViaOffscreenBackBuffer=true to allow explicit swapping!');
#endif
}
#else
if (contextAttributes['explicitSwapControl']) {
#if GL_DEBUG
console.error('emscripten_webgl_create_context failed: explicitSwapControl is not supported, please rebuild with -s OFFSCREENCANVAS_SUPPORT=1 to enable targeting the experimental OffscreenCanvas specification, or rebuild with -s OFFSCREEN_FRAMEBUFFER=1 to emulate explicitSwapControl in the absence of OffscreenCanvas support!');
#endif
return 0;
}
#endif // ~!OFFSCREEN_FRAMEBUFFER

#endif // ~!OFFSCREENCANVAS_SUPPORT

var contextHandle = GL.createContext(canvas, contextAttributes);
Expand Down
2 changes: 1 addition & 1 deletion system/include/emscripten/html5.h
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ extern EMSCRIPTEN_RESULT emscripten_set_webglcontextrestored_callback(const char

extern EM_BOOL emscripten_is_webgl_context_lost(const char *target);

extern EMSCRIPTEN_RESULT emscripten_webgl_commit_frame();
extern EMSCRIPTEN_RESULT emscripten_webgl_commit_frame(void);

extern EMSCRIPTEN_RESULT emscripten_set_canvas_element_size(const char *target, int width, int height);
extern EMSCRIPTEN_RESULT emscripten_get_canvas_element_size(const char *target, int *width, int *height);
Expand Down
5 changes: 5 additions & 0 deletions tests/test_browser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3689,6 +3689,11 @@ def test_webgl_offscreen_canvas_in_mainthread_after_pthread(self):
for args in [[], ['-DTEST_MAIN_THREAD_EXPLICIT_COMMIT']]:
self.btest('gl_in_mainthread_after_pthread.cpp', expected='0', args=args+['-s', 'USE_PTHREADS=1', '-s', 'PTHREAD_POOL_SIZE=2', '-s', 'OFFSCREENCANVAS_SUPPORT=1', '-lGL'])

# Tests that -s OFFSCREEN_FRAMEBUFFER=1 rendering works.
@requires_graphics_hardware
def test_webgl_offscreen_framebuffer(self):
self.btest('webgl_draw_triangle.c', '0', args=['-lGL', '-s', 'OFFSCREEN_FRAMEBUFFER=1', '-DEXPLICIT_SWAP=1'])

# Tests the feature that shell html page can preallocate the typed array and place it to Module.buffer before loading the script page.
# In this build mode, the -s TOTAL_MEMORY=xxx option will be ignored.
# Preallocating the buffer in this was is asm.js only (wasm needs a Memory).
Expand Down

0 comments on commit 90e38e5

Please sign in to comment.