This extension exposes the ability to share WebGL resources with multiple WebGLRenderingContexts.
Background:
The OpenGL ES spec defines that you can share a resource (texture, buffer, shader, program, renderbuffer) with 2 or more GL contexts but with some caveats. To guarantee you'll see a change made in one context in other context requires calling glFinish on the context that made the change and call glBind on the context that wants to see the change.
Not calling glFinish and/or glBind does not guarantee you won't see the results which means that users may do neither and their app might just happen to work on some platforms and mysteriously have glitches, rendering corruption, gl errors or program failure on others.
WebGL must present consistent behavior for sharing and so this extension provides an API so that implementions can enforce and optimize these requirements.
Adds a new context creation parameter:
group
attribute from the WEBGL_shared_resources
object from an existing context
then resources from the existing context are shared with the newly created context.
var canvas1 = document.createElement("canvas"); var canvas2 = document.createElement("canvas"); var ctx1 = canvas1.getContext("webgl"); var sharedResourcesExtension = ctx1.getExtension("WEBGL_shared_resources"); var ctx2 = canvas2.getContext("webgl", { shareGroup: sharedResourcesExtension.group });
In order for a context to use a resouce it must first acquire it. Contexts can make a request to acquire a resource by calling acquireSharedResource in one of 2 modes, EXCLUSIVE or READ_ONLY. A resource may be acquired by multiple contexts in READ_ONLY mode. The resource may only be acquired by one context if the mode is EXCLUSIVE. acquireSharedResource returns an id you can use to cancel the acquire by calling cancelAcquireSharedResource. When the resource is available in the requested mode the callback will be invoked. Resources start their life as acquired in EXCLUSIVE mode in the context in which they are created.
To release a resource so it may be acquired by another context call releaseSharedResource and pass it the resource to be released.
After a resource is acquired it must be bound before it is used. Binding means for buffers calling bindBuffer, for textures either bindTexture or framebufferTexture2D, for renderbuffers either bindRenderbuffer or framebufferRenderbuffer, for shaders attachShader, for programs useProgram. Binding once is sufficient to satisfy this requirement. In other words, if you have a texture attached to more than one texture unit the texture only needs to be re-bound to 1 texture unit. Attemping to use a resource which has not been bound since it was acquired generates INVALID_OPERATION.
Bind Requirement Algorithm:
Each resource has a per-context bound flag. When a resource is acquired in a context its bound flag for that context is set to false. If one of the functions listed above is called the bound flag for that context is set to true. Drawing and reading functions, clear, drawArrays, drawElements, readPixels, that would access a resource whose bound flag for that context is false generate INVALID_FRAMEBUFFER_OPERATION. All other functions that use a resource whose bound flag for that context is false generate INVALID_OPERATION.
Note: In the specific case of programs, it is not an error to call draw with a program or call useProgram for a program which has shaders that have been acquired but not re-attached. Nor it is an error to draw with or call useProgram for a program which has shaders that have not been acquired. It is an error to call linkProgram for a program that is using shaders that have been acquired but not re-attached.
When an attempt is made to use a resource that is not acquired in the current context the implementation must generate the error INVALID_OPERATION or INVALID_FRAMEBUFFER_OPRATION. This includes all gl calls that would access the given resource directly or indirectly. For example, a draw call must fail if any of the resources it would access is not acquired in the correct mode for the call. In other words, if the draw call would read from a buffer or texture and that buffer or texture is not acquired for READ_ONLY or EXCLUSIVE mode the draw must fail with INVALID_FRAMEBUFFER_OPERATION. If the draw would render to a texture or renderbuffer that is not acquired for EXCLUSIVE mode the draw must fail and generate INVALID_FRAMEBUFFER_OPERATION. If a program used in the draw is not acquired for READ_ONLY or EXCLUSIVE mode the draw or clear must fail and generate INVALID_FRAMEBUFFER_OPERATION.
For buffers not acquired this includes but is not limited to
bindBuffer bufferData bufferSubData deleteBuffer drawArrays drawElements getParameter with parameter (BUFFER_SIZE or BUFFER_USAGE) isBuffer vertexAttribPointer
For a buffer acquired in READ_ONLY mode this includes but is not limited to
bufferData bufferSubData
For programs not acquired this includes but is not limited to
attachShader bindAttribLocation drawArrays drawElements deleteProgram getActiveAttrib getActiveUniform getAttribLocation getUniformLocation getProgramParameter getProgramInfoLog isProgram linkProgram useProgram validateProgram
For programs acquired in READ_ONLY mode includes but is not limited to
bindAttribLocation deleteProgram linkProgram
For renderbuffers not acquired this includes but is not limited to
bindRenderbuffer clear deleteRenderbuffer drawArrays drawElements framebufferRenderbuffer isRenderbuffer renderbufferStorage
For renderbuffers acquired in READ_ONLY mode this includes
clear deleteRenderbuffer drawArrays drawElements renderbufferStorage
For shaders not acquired this includes but is not limited to
attachShader compileShader deleteShader getShaderSource getShaderParameter isShader shaderSource
For shaders acquired in READ_ONLY mode this includes but is not limited to
deleteShader compileShader shaderSource
For textures not acquired this includes but is not limited to
bindTexture clear compressedTexImage2D compressedTexSubImage2D copyTexImage2D copyTexSubImage2D drawArrays drawElements deleteTexture framebufferTexture2D getTexParameter isTexture texImage2D texParameter texSubImage2D
For textures acquired in READ_ONLY mode this includes but is not limited to
clear compressedTexImage2D compressedTexSubImage2D copyTexImage2D copyTexSubImage2D drawArrays drawElements deleteTexture texImage2D texParameter texSubImage2D
The term "not limited to" is intended to point out that extension may enable other functions to which these rule should apply. For example drawArraysInstancedANGLE must follow the same rules as drawArrays.
Calling checkFramebufferStatus with the argument FRAMEBUFFER or DRAW_FRAMEBUFFER must return FRAMEBUFFER_INCOMPLETE_ATTACHMENT if any of the resources referenced by the currently bound framebuffer are not acquired for EXCLUSIVE access. Calling checkFramebufferStatus with the argument READ_FRAMEBUFFER will return FRAMEBUFFER_INCOMPLETE_ATTACHMENT if any of the resources referenced by the currently bound framebuffer are not acquired for EXCLUSIVE or READ_ONLY access.
Note: This extension exposes the constants READ_FRAMEBUFFER and DRAW_FRAMEBUFFER only for the purpose of calling checkFramebufferStatus. In particular, this extension does not enable calling bindFramebuffer with either constant.
A context that is deleted automatically releases all resources it has acquired. Note that currently there is no way to explicitly delete a context. Contexts are deleted through garbage collection.
Note that implementing this extension changes the base class of the sharable resources. Specifically: WebGLBuffer, WebGLProgram, WebGLRenderbuffer, WebGLShader, and WebGLTexture change their base class from WebGLObject to WebGLSharedObject.