Skip to content

Commit 5622daa

Browse files
committed
Single-canvas inline, drop XRPresentationContext
Fixes #636 This change adds a path for using a single WebGL canvas to drive inline sessions, rather than needing both a WebGL context and an XRPresentationContext before the inline session can function. The way to do this is to create an `XRWebGLLayer` with the `useDefaultFramebuffer` option set to `true` and set it as the session's `baseLayer`. In addition to the above, this change removes the XRPresentationContext entirely, and along with it the ability to do desktop mirroring (and more advanced inline scenarios.) This is to simplify the core API, and equivalent functionality will be reconsidered in the future because the functionality that they represent is valuable.
1 parent 6868682 commit 5622daa

File tree

1 file changed

+55
-53
lines changed

1 file changed

+55
-53
lines changed

index.bs

Lines changed: 55 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,13 @@ urlPrefix: https://www.khronos.org/registry/webgl/specs/latest/1.0/
4949
type: method; text: getFramebufferAttachmentParameter; url: 5.14.6
5050
type: method; text: getRenderbufferParameter; url: 5.14.7
5151
type: method; text: checkFramebufferStatus; url: 5.14.6
52-
type: dictionary; text: WebGLContextAttributes; url: WebGLContextAttributes
52+
type: dictionary; text: WebGLContextAttributes; url: #WebGLContextAttributes
5353
type: dfn; text: Create the WebGL context; url:#2.1
5454
type: dfn; text: WebGL viewport; url:#5.14.4
5555
type: dfn; text: WebGL context lost flag; url:#webgl-context-lost-flag
5656
type: dfn; text: handle the context loss; url:#CONTEXT_LOST
5757
type: dfn; text: Restore the context; url: #restore-the-drawing-buffer
58+
type: dfn; text: actual context parameters; url: #actual-context-parameters
5859
urlPrefix: https://www.khronos.org/registry/webgl/specs/latest/2.0/
5960
type: interface; text: WebGL2RenderingContext; url: WebGL2RenderingContext
6061
urlPrefix: https://w3c.github.io/orientation-sensor/; spec: ORIENTATION-SENSOR
@@ -457,7 +458,6 @@ When requested, the {{XRSession}} MUST <dfn>apply pending render states</dfn> by
457458
1. If |newState|'s {{XRRenderStateInit/depthFar}} value is set, set |activeState|'s {{XRRenderState/depthFar}} to |newState|'s {{XRRenderStateInit/depthFar}}.
458459
1. If |newState|'s {{XRRenderStateInit/inlineVerticalFieldOfView}} is set, set |activeState|'s {{XRRenderState/inlineVerticalFieldOfView}} to |newState|'s {{XRRenderStateInit/inlineVerticalFieldOfView}}.
459460
1. If |newState|'s {{XRRenderStateInit/baseLayer}} is set, set |activeState|'s {{XRRenderState/baseLayer}} to |newState|'s {{XRRenderStateInit/baseLayer}}.
460-
1. If |newState|'s {{XRRenderStateInit/outputContext}} is set, set |activeState|'s {{XRRenderState/outputContext}} to |newState|'s {{XRRenderStateInit/outputContext}} and [=update the XRPresentationContext session=] to |session|.
461461
1. If |activeState|'s {{XRRenderState/inlineVerticalFieldOfView}} is less than |session|'s [=minimum inline field of view=] set |activeState|'s {{XRRenderState/inlineVerticalFieldOfView}} to |session|'s [=minimum inline field of view=].
462462
1. If |activeState|'s {{XRRenderState/inlineVerticalFieldOfView}} is greater than |session|'s [=maximum inline field of view=] set |activeState|'s {{XRRenderState/inlineVerticalFieldOfView}} to |session|'s [=maximum inline field of view=].
463463

@@ -537,7 +537,32 @@ The <dfn attribute for="XRSession">environmentBlendMode</dfn> attribute returns
537537

538538
NOTE: Most Virtual Reality devices exhibit {{XREnvironmentBlendMode/opaque}} blending behavior. Augmented Reality devices that use transparent optical elements frequently exhibit {{XREnvironmentBlendMode/additive}} blending behavior, and Augmented Reality devices that use passthrough cameras frequently exhibit {{XREnvironmentBlendMode/alpha-blend}} blending behavior.
539539

540-
Each {{XRSession}} has a <dfn for="XRSession">viewer reference space</dfn>, which is an {{XRReferenceSpace}} of type {{XRReferenceSpaceType/viewer}} with an [=identity transform=] [=XRSpace/origin offset=]. The [=XRSession/viewer reference space=] has a <dfn for="XRSession/viewer reference space">list of views</dfn>, which is a [=/list=] of [=view=]s corresponding to the views provided by the [=/XR device=].
540+
Each {{XRSession}} has a <dfn for="XRSession">output canvas</dfn>, which is an {{HTMLCanvasElement}}. The [=XRSession/output canvas=] is the DOM element that will display any content rendered for an {{XRSessionMode/inline}} {{XRSession}}.
541+
542+
<div class="algorithm" data-algorithm="determine-output-canvas">
543+
544+
To determine the [=XRSession/output canvas=] for an {{XRSession}} |session|, the user agent MUST run the following steps:
545+
546+
1. Let |baseLayer| be |session|'s {{XRSession/renderState}}'s {{XRRenderState/baseLayer}}.
547+
1. If |baseLayer| is an instance of an {{XRWebGLLayer}} with a [=XRWebGLLayer/use default framebuffer=] boolean set to <code>true</code>, return |baseLayer|'s {{XRWebGLLayer/context}}'s {{WebGLRenderingContext|canvas}}.
548+
1. return <code>null</code>.
549+
550+
</div>
551+
552+
An {{XRSessionMode/inline}} {{XRSession}} is considered a <dfn for="XRSession">direct output session</dfn> if rendering commands performed for the {{XRSession}} are executed in such a way that they are directly displayed on the page, rather than being processed by the [=XR Compositor=].
553+
554+
<div class="algorithm" data-algorithm="determine-direct-output-session">
555+
556+
To determine if an {{XRSession}} |session| is a [=direct output session=], the user agent MUST run the following steps:
557+
558+
1. If |session|'s [=XRSession/mode=] is not {{XRSessionMode/inline}}, return <code>false</code>.
559+
1. Let |baseLayer| be |session|'s {{XRSession/renderState}}'s {{XRRenderState/baseLayer}}.
560+
1. If |baseLayer| is an instance of an {{XRWebGLLayer}} with a [=XRWebGLLayer/use default framebuffer=] boolean set to <code>true</code>, return <code>true</code>.
561+
1. return <code>false</code>.
562+
563+
</div>
564+
565+
Each {{XRSession}} has a <dfn for="XRSession">viewer reference space</dfn>, which is an {{XRReferenceSpace}} of type {{XRReferenceSpaceType/viewer}} with an [=identity transform=] [=XRSpace/origin offset=]. The [=XRSession/viewer reference space=] has a <dfn for="XRSession/viewer reference space">list of views</dfn>, which is a [=/list=] of [=view=]s corresponding to the views provided by the [=/XR device=]. If the {{XRSession}} is a [=direct output session=] the [=list of views=] MUST contain a single [=view=].
541566

542567
<section class="unstable">
543568
The <dfn attribute for="XRSession">onblur</dfn> attribute is an [=Event handler IDL attribute=] for the {{blur}} event type.
@@ -574,15 +599,13 @@ dictionary XRRenderStateInit {
574599
double depthFar;
575600
double inlineVerticalFieldOfView;
576601
XRLayer? baseLayer;
577-
XRPresentationContext? outputContext;
578602
};
579603

580604
[SecureContext, Exposed=Window] interface XRRenderState {
581605
readonly attribute double depthNear;
582606
readonly attribute double depthFar;
583607
readonly attribute double? inlineVerticalFieldOfView;
584608
readonly attribute XRLayer? baseLayer;
585-
readonly attribute XRPresentationContext? outputContext;
586609
};
587610
</pre>
588611

@@ -596,15 +619,14 @@ When an {{XRRenderState}} object is created for an {{XRSession}} |session|, the
596619
1. If |session| is an [=immersive session=], initialize |state|'s {{XRRenderState/inlineVerticalFieldOfView}} to <code>null</code>.
597620
1. Else initialize |state|'s {{XRRenderState/inlineVerticalFieldOfView}} to <code>PI * 0.5</code>.
598621
1. Initialize |state|'s {{XRRenderState/baseLayer}} to <code>null</code>.
599-
1. Initialize |state|'s {{XRRenderState/outputContext}} to <code>null</code>.
600622

601623
</div>
602624

603625
The <dfn attribute for="XRRenderState">depthNear</dfn> attribute defines the distance, in meters, of the near clip plane from the viewer. The <dfn attribute for="XRRenderState">depthFar</dfn> attribute defines the distance, in meters, of the far clip plane from the viewer.
604626

605627
{{XRRenderState/depthNear}} and {{XRRenderState/depthFar}} is used in the computation of the {{XRView/projectionMatrix}} of {{XRView}}s and determines how the values of an {{XRWebGLLayer}} depth buffer are interpreted. {{XRRenderState/depthNear}} MAY be greater than {{XRRenderState/depthFar}}.
606628

607-
The <dfn attribute for="XRRenderState">inlineVerticalFieldOfView</dfn> attribute defines the default vertical field of view in radians used when computing projection matrices for {{XRSessionMode/inline}} {{XRSession}}s. The projection matrix calculation also takes into account the aspect ratio of the {{XRRenderState/outputContext}}'s {{XRPresentationContext/canvas}}. This value MUST be <code>null</code> for [=immersive sessions=].
629+
The <dfn attribute for="XRRenderState">inlineVerticalFieldOfView</dfn> attribute defines the default vertical field of view in radians used when computing projection matrices for {{XRSessionMode/inline}} {{XRSession}}s. The projection matrix calculation also takes into account the aspect ratio of the [=XRSession/output canvas=]. This value MUST be <code>null</code> for [=immersive sessions=].
608630

609631
Animation Frames {#animation-frames}
610632
----------------
@@ -646,7 +668,7 @@ When an {{XRSession}} |session| receives updated [=viewer=] state from the [=/XR
646668

647669
1. If |session|'s [=list of pending render states=] is not empty, [=apply pending render states=].
648670
1. If |session|'s {{XRSession/renderState}}'s {{XRRenderState/baseLayer}} is <code>null</code>, abort these steps.
649-
1. If |session|'s [=XRSession/mode=] is {{XRSessionMode/"inline"}} and |session|'s {{XRSession/renderState}}'s {{XRRenderState/outputContext}} is <code>null</code>, abort these steps.
671+
1. If |session|'s [=XRSession/mode=] is {{XRSessionMode/"inline"}} and |session|'s [=XRSession/output canvas=] is <code>null</code>, abort these steps.
650672
1. Let |callbacks| be a list of the entries in |session|'s [=list of animation frame callback=], in the order in which they were added to the list.
651673
1. Set |session|'s [=list of animation frame callbacks=] to the empty list.
652674
1. Set |frame|'s [=active=] boolean to <code>true</code>.
@@ -1423,6 +1445,7 @@ typedef (WebGLRenderingContext or
14231445
WebGL2RenderingContext) XRWebGLRenderingContext;
14241446

14251447
dictionary XRWebGLLayerInit {
1448+
boolean useDefaultFramebuffer = false;
14261449
boolean antialias = true;
14271450
boolean depth = true;
14281451
boolean stencil = false;
@@ -1462,35 +1485,48 @@ The <dfn constructor for="XRWebGLLayer">XRWebGLLayer(|session|, |context|, |laye
14621485
1. If |context| is lost, throw an {{InvalidStateError}} and abort these steps.
14631486
1. If |context|'s [=XR compatible=] boolean is false, throw an {{InvalidStateError}} and abort these steps.
14641487
1. Initialize |layer|'s {{XRWebGLLayer/context}} to |context|.
1465-
1. Initialize |layer|'s {{XRWebGLLayer/antialias}} to |layerInit|'s {{XRWebGLLayerInit/antialias}} value.
1466-
1. If |layerInit|'s {{XRWebGLLayerInit/ignoreDepthValues}} value is <code>false</code> and the [=XR Compositor=] will make use of depth values, Initialize |layer|'s {{XRWebGLLayer/ignoreDepthValues}} to <code>false</code>.
1467-
1. Else Initialize |layer|'s {{XRWebGLLayer/ignoreDepthValues}} to <code>true</code>
1468-
1. Initialize |layer|'s {{XRWebGLLayer/framebuffer}} to a new [=opaque framebuffer=] created with |context|.
1469-
1. Initialize the |layer|'s [=swap chain=].
1470-
1. If |layer|'s [=swap chain=] was unable to be created for any reason, throw an {{OperationError}} and abort these steps.
1488+
1. Initialize |layer|'s [=XRWebGLLayer/use default framebuffer=] to |layerInit|'s {{XRWebGLLayerInit/useDefaultFramebuffer}}.
1489+
1. If |layer|'s [=XRWebGLLayer/use default framebuffer=] boolean is <code>false</code>:
1490+
1. Initialize |layer|'s {{XRWebGLLayer/antialias}} to |layerInit|'s {{XRWebGLLayerInit/antialias}} value.
1491+
1. If |layerInit|'s {{XRWebGLLayerInit/ignoreDepthValues}} value is <code>false</code> and the [=XR Compositor=] will make use of depth values, Initialize |layer|'s {{XRWebGLLayer/ignoreDepthValues}} to <code>false</code>.
1492+
1. Else Initialize |layer|'s {{XRWebGLLayer/ignoreDepthValues}} to <code>true</code>
1493+
1. Initialize |layer|'s {{XRWebGLLayer/framebuffer}} to a new [=opaque framebuffer=] created with |context|.
1494+
1. Initialize the |layer|'s [=swap chain=].
1495+
1. If |layer|'s [=swap chain=] was unable to be created for any reason, throw an {{OperationError}} and abort these steps.
1496+
1. Else if |layer|'s [=XRWebGLLayer/use default framebuffer=] boolean is <code>true</code>:
1497+
1. If |session|'s [=mode=] is not {{XRSessionMode/inline}}, throw an {{InvalidStateError}} and abort these steps.
1498+
1. Initialize |layer|'s {{XRWebGLLayer/antialias}} to |layer|'s {{XRWebGLLayer/context}}'s [=actual context parameters=] {{WebGLContextAttributes|antialias}} value.
1499+
1. Initialize |layer|'s {{XRWebGLLayer/ignoreDepthValues}} to <code>true</code>.
1500+
1. Initialize |layer|'s {{XRWebGLLayer/framebuffer}} to <code>null</code>.
14711501
1. Return |layer|.
14721502

14731503
</div>
14741504

14751505
The <dfn attribute for="XRWebGLLayer">context</dfn> attribute is the {{WebGLRenderingContext}} the {{XRWebGLLayer}} was created with.
14761506

1477-
The <dfn attribute for="XRWebGLLayer">framebuffer</dfn> attribute of an {{XRWebGLLayer}} is an instance of a {{WebGLFramebuffer}} which has been marked as [=opaque framebuffer|opaque=]. An <dfn>opaque framebuffer</dfn> functions identically to a standard {{WebGLFramebuffer}} with the following changes that make it behave more like the default framebuffer:
1507+
Each {{XRWebGLLayer}} has a <dfn for="XRWebGLLayer">use default framebuffer</dfn> boolean which is initially set to <code>false</code>. If set to <code>true</code> it indicates that the {{XRWebGLLayer}} MUST NOT allocate its own {{WebGLFramebuffer}}, and all properties of the {{XRWebGLLayer}} that reflect {{XRWebGLLayer/framebuffer}} properties MUST instead reflect the properties of the {{XRWebGLLayer/context}}'s default framebuffer.
1508+
1509+
The <dfn attribute for="XRWebGLLayer">framebuffer</dfn> attribute of an {{XRWebGLLayer}} is an instance of a {{WebGLFramebuffer}} which has been marked as [=opaque framebuffer|opaque=] if [=XRWebGLLayer/use default framebuffer=] is <code>false</code>, and <code>null</code> otherwise. The {{framebuffer}} size cannot be adjusted by the developer after the {{XRWebGLLayer}} has been created.
1510+
1511+
An <dfn>opaque framebuffer</dfn> functions identically to a standard {{WebGLFramebuffer}} with the following changes that make it behave more like the default framebuffer:
14781512

14791513
- An [=opaque framebuffer=] MAY support antialiasing, even in WebGL 1.0.
14801514
- An [=opaque framebuffer=]'s attachments cannot be inspected or changed. Calling {{framebufferTexture2D}}, {{framebufferRenderbuffer}}, {{getFramebufferAttachmentParameter}}, or {{getRenderbufferParameter}} with an [=opaque framebuffer=] MUST generate an {{INVALID_OPERATION}} error.
14811515
- An [=opaque framebuffer=] is considered incomplete outside of an {{XRSession/requestAnimationFrame()}} callback. When not in a {{XRSession/requestAnimationFrame()}} callback calls to {{checkFramebufferStatus}} outside of an {{XRSession/requestAnimationFrame()}} callback MUST generate a {{FRAMEBUFFER_UNSUPPORTED}} error and attempts to clear, draw to, or read from the [=opaque framebuffer=] MUST generate an {{INVALID_FRAMEBUFFER_OPERATION}} error.
14821516

1483-
The <dfn attribute for="XRWebGLLayer">framebufferWidth</dfn> and <dfn attribute for="XRWebGLLayer">framebufferHeight</dfn> attributes return the width and height of the {{framebuffer}}'s attachments, respectively. The {{framebuffer}} size cannot be adjusted by the developer after the {{XRWebGLLayer}} has been created.
1517+
Each {{XRWebGLLayer}} has a <dfn for="XRWebGLLayer">target framebuffer</dfn>, which is the {{XRWebGLLayer/framebuffer}} if [=XRWebGLLayer/use default framebuffer=] is <code>false</code>, and the {{XRWebGLLayer/context}}'s default framebuffer otherwise.
14841518

1485-
The <dfn attribute for="XRWebGLLayer">antialias</dfn> attribute is <code>true</code> if the {{framebuffer}} supports antialiasing using a technique of the UAs choosing, and <code>false</code> if no antialiasing will be performed.
1519+
The <dfn attribute for="XRWebGLLayer">framebufferWidth</dfn> and <dfn attribute for="XRWebGLLayer">framebufferHeight</dfn> attributes return the width and height of the [=XRWebGLLayer/target framebuffer=]'s attachments, respectively.
1520+
1521+
The <dfn attribute for="XRWebGLLayer">antialias</dfn> attribute is <code>true</code> if the [=XRWebGLLayer/target framebuffer=] supports antialiasing using a technique of the UAs choosing, and <code>false</code> if no antialiasing will be performed.
14861522

14871523
The <dfn attribute for="XRWebGLLayer">ignoreDepthValues</dfn> attribute, if <code>true</code>, indicates the [=XR Compositor=] MUST NOT make use of values in the depth buffer attachment when rendering. When the attribute is <code>false</code> it indicates that the content of the depth buffer attachment will be used by the [=XR Compositor=] and is expected to be representative of the scene rendered into the layer.
14881524

14891525
Depth values stored in the buffer are expected to be between <code>0.0</code> and <code>1.0</code>, with <code>0.0</code> representing the distance of {{XRRenderState/depthNear}} and <code>1.0</code> representing the distance of {{XRRenderState/depthFar}}, with intermediate values interpolated linearly. This is the default behavior of WebGL. (See documentation for the <a href="https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glDepthRangef.xml">depthRange function</a> for additional details.))
14901526

14911527
NOTE: Making the scene's depth buffer available to the compositor allows some platforms to provide quality and comfort improvements such as improved reprojection.
14921528

1493-
Each {{XRWebGLLayer}} MUST have a <dfn>list of viewports</dfn> which contains one [=WebGL viewport=] for each {{XRView}} the {{XRSession}} currently exposes. The viewports MUST NOT be overlapping.
1529+
Each {{XRWebGLLayer}} MUST have a <dfn>list of viewports</dfn> which is a [=/list=] containing one [=WebGL viewport=] for each {{XRView}} the {{XRSession}} currently exposes. The viewports MUST NOT be overlapping. If [=XRWebGLLayer/use default framebuffer=] is <code>true</code>, the [=list of viewports=] MUST contain a single [=WebGL viewport=] that covers the {{XRWebGLLayer/context}}'s entire default framebuffer.
14941530

14951531
{{getViewport()}} queries the {{XRViewport}} the given {{XRView}} should use when rendering to the layer.
14961532

@@ -1517,7 +1553,7 @@ The [=native WebGL framebuffer resolution=] is determined by running the followi
15171553

15181554
1. Let |session| be the target {{XRSession}}.
15191555
1. If |session|'s [=XRSession/mode=] value is not <code>"inline"</code>, set the [=native WebGL framebuffer resolution=] to the resolution required to have a 1:1 ratio between the pixels of a framebuffer large enough to contain all of the session's {{XRView}}s and the physical screen pixels in the area of the display under the highest magnification and abort these steps. If no method exists to determine the native resolution as described, the [=recommended WebGL framebuffer resolution=] MAY be used.
1520-
1. If |session|'s [=XRSession/mode=] value is <code>"inline"</code>, set the [=native WebGL framebuffer resolution=] to the size of the |session|'s {{XRSession/renderState}}'s {{XRRenderState/outputContext}}'s {{XRPresentationContext/canvas}} in physical display pixels and reevaluate these steps every time the size of the canvas changes or the {{XRRenderState/outputContext}} is changed.
1556+
1. Else the set the [=native WebGL framebuffer resolution=] to <code>1 x 1</code>.
15211557

15221558
</div>
15231559

@@ -1646,40 +1682,6 @@ function onXRSessionStarted(xrSession) {
16461682
</div>
16471683
</section>
16481684

1649-
Canvas Rendering Context {#canvas-rendering-context}
1650-
========================
1651-
1652-
<section class="unstable">
1653-
XRPresentationContext {#xrpresentationcontext-interface}
1654-
---------------------
1655-
1656-
When the {{HTMLCanvasElement/getContext()}} method of an {{HTMLCanvasElement}} |canvas| is to return a new object for the <var ignore>contextId</var> <code>present-xr</code>, the user agent must return an {{XRPresentationContext}} with {{XRPresentationContext/canvas}} set to |canvas|.
1657-
1658-
<pre class="idl">
1659-
[SecureContext, Exposed=Window] interface XRPresentationContext {
1660-
[SameObject] readonly attribute HTMLCanvasElement canvas;
1661-
};
1662-
</pre>
1663-
1664-
The <dfn attribute for="XRPresentationContext">canvas</dfn> attribute indicates the {{HTMLCanvasElement}} that created this context.
1665-
1666-
Each {{XRPresentationContext}} has an <dfn for="XRPresentationContext">session</dfn> which is an {{XRSession}} initially set to <code>null</code>.
1667-
1668-
<div class="algorithm" data-algorithm="presentation-context-session-update">
1669-
1670-
When another algorithm indicates it will <dfn>update the XRPresentationContext session</dfn> to {{XRSession}} |session|, run the following steps:
1671-
1672-
1. Let |context| be the target {{XRPresentationContext}}.
1673-
1. Let |prevSession| be |context|'s [=XRPresentationContext/session=].
1674-
1. If |prevSession| is equal to |session| abort these steps.
1675-
1. If |prevSession| is not <code>null</code>:
1676-
1. If |prevSession|'s {{XRSession/renderState}}'s {{XRRenderState/outputContext}} is equal to |context| set |prevSession|'s {{XRSession/renderState}}'s {{XRRenderState/outputContext}} to <code>null</code>.
1677-
1. Set |context|'s [=XRPresentationContext/session=] to |session|.
1678-
1679-
</div>
1680-
1681-
</section>
1682-
16831685
Events {#events}
16841686
========
16851687

0 commit comments

Comments
 (0)