From 20ed33930bb4e7beb604abbca671e22318c5013f Mon Sep 17 00:00:00 2001 From: Rik Cabanier Date: Tue, 11 Aug 2026 13:47:00 -0700 Subject: [PATCH] Define destroyed layer lifecycle --- webxrlayers-1.bs | 47 +++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/webxrlayers-1.bs b/webxrlayers-1.bs index cafbf12..21d9274 100755 --- a/webxrlayers-1.bs +++ b/webxrlayers-1.bs @@ -396,7 +396,30 @@ the user agent MUST run the following steps: -{{destroy()}} will delete the underlying attachments. If there are no attachments, this function does nothing. +Each {{XRCompositionLayer}} has an associated destroyed boolean, initially false. + +{{destroy()}} immediately marks the layer as [=XRCompositionLayer/destroyed=] and makes its graphics resources unavailable for future rendering. +Calling {{destroy()}} on a layer that is already [=XRCompositionLayer/destroyed=] does nothing. +A [=XRCompositionLayer/destroyed=] layer MUST NOT be presented by the [=XR Compositor=], even if the layer is still present in the {{XRRenderState/layers}} array while a pending render state update is applied. + +If a method is invoked to obtain an {{XRSubImage}} for a [=XRCompositionLayer/destroyed=] layer, the method MUST throw an {{InvalidStateError}}. + +Previously returned {{XRSubImage}} objects are not themselves destroyed when their layer is destroyed. Their attributes continue to return the same objects and values, but any graphics resources exposed by those objects MUST be invalidated for future rendering operations. GPU work queued before the resources were invalidated MAY complete. + +
+ +To destroy the resources for a layer with an {{XRCompositionLayer}} |layer|, the user agent MUST run the following steps: + 1. For each [=opaque texture=] in any of |layer|'s [=colorTextures=], [=depthStencilTextures=], or [=motionVectorTextures=] arrays that exist, mark the texture for deletion as though {{deleteTexture}} had been called with the texture on |layer|'s [=XRCompositionLayer/context=]. This is an internal user-agent operation and MUST NOT generate an {{INVALID_OPERATION}} error. + 1. If |layer| is an {{XRProjectionLayer}}: + 1. If |layer|'s [=XRProjectionLayer/colorTextures for secondary views=] is not null, for each [=opaque texture=] in that array, mark the texture for deletion in the same manner. + 1. If |layer|'s [=XRProjectionLayer/depthStencilTextures for secondary views=] is not null, for each [=opaque texture=] in that array, mark the texture for deletion in the same manner. + 1. If |layer| has a [=colorTextures=] array, set it to an empty array. + 1. If |layer| has a [=depthStencilTextures=] array, set it to an empty array. + 1. If |layer| has a [=motionVectorTextures=] array, set it to an empty array. + 1. If |layer| is an {{XRProjectionLayer}}, set its [=XRProjectionLayer/colorTextures for secondary views=] and [=XRProjectionLayer/depthStencilTextures for secondary views=] to empty arrays. + 1. For each of |layer|'s underlying resources, once all GPU work queued before the resource was invalidated has completed and the [=XR Compositor=] no longer accesses the resource, the user agent MAY physically release it. + +
@@ -404,6 +427,7 @@ To initialize a composition layer with a {{XRSession}} |session| and or a {{WebGL2RenderingContext}} |context|, the user agent MUST run the following steps: 1. Set [=this=] [=XRCompositionLayer/session=] to |session|. 1. If |context| is defined, set [=this=] [=XRCompositionLayer/context=] to |context|. + 1. Set [=this=] [=XRCompositionLayer/destroyed=] to false. 1. Set [=this=] {{XRCompositionLayer/blendTextureSourceAlpha}} to true. 1. Set [=this=] {{XRCompositionLayer/opacity}} to 1.0. @@ -411,10 +435,17 @@ or a {{WebGL2RenderingContext}} |context|, the user agent MUST run the following
-When calling {{destroy()}}, the user agent MUST run the following steps: - 1. Set [=this=] [=colorTextures=] array to an empty array. - 1. Set [=this=] [=depthStencilTextures=] array to an empty array. - 1. Destroy the underlying GL attachments. +When calling {{destroy()}} on an {{XRCompositionLayer}} |layer|, the user agent MUST run the following steps: + 1. If |layer|'s [=XRCompositionLayer/destroyed=] is true, return. + 1. Set |layer|'s [=XRCompositionLayer/destroyed=] to true. + 1. Run [=destroy the resources for a layer=] with |layer|. + 1. Let |session| be |layer|'s [=XRCompositionLayer/session=]. + 1. If |session|'s [=pending render state=] is null: + 1. If |session|'s [=active render state=]'s {{XRRenderState/layers}} does not contain |layer|, return. + 1. Set |session|'s [=pending render state=] to a copy of |session|'s [=active render state=]. + 1. Let |state| be |session|'s [=pending render state=]. + 1. If |state|'s {{XRRenderState/layers}} is null or does not contain |layer|, return. + 1. Set |state|'s {{XRRenderState/layers}} to a new frozen array containing, in order, each entry in |state|'s {{XRRenderState/layers}} other than |layer|.
@@ -1678,6 +1709,7 @@ When this method is invoked on an {{XRWebGLBinding}} |binding|, it MUST run the
Let |subimage|'s {{XRSubImage/viewport}} be a [=new=] {{XRViewport}} in the [=relevant realm=] of [=this=]. 1. Let |session| be [=this=] [=XRWebGLBinding/session=]. + 1. If |layer|'s [=XRCompositionLayer/destroyed=] is true, throw an {{InvalidStateError}} and abort these steps. 1. If |layer| is not in the |session|'s {{XRRenderState/layers}} array, throw a {{TypeError}} and abort these steps. 1. If |layer|'s type is {{XRProjectionLayer}}, throw a {{TypeError}} and abort these steps. 1. If |layer|'s {{XRCompositionLayer/layout}} attribute is {{XRLayerLayout/"default"}}, throw a {{TypeError}} and abort these steps. @@ -1743,6 +1775,7 @@ When this method is invoked on an {{XRWebGLBinding}} |binding|, it MUST run the 1. Let |frame| be |view|'s {{frame}}. 1. Let |session| be [=this=] [=XRWebGLBinding/session=]. + 1. If |layer|'s [=XRCompositionLayer/destroyed=] is true, throw an {{InvalidStateError}} and abort these steps. 1. If [=validate the state of the XRWebGLSubImage creation function=] with |layer| and |frame| is false, throw an {{InvalidStateError}} and abort these steps. 1. If |layer| is not in the |session|'s {{XRRenderState/layers}} array, throw a {{TypeError}} and abort these steps. 1. If |view|'s [=view/active=] flag is false, throw an {{InvalidStateError}} and abort these steps. @@ -2147,6 +2180,7 @@ This module replaces the steps given by "[=/update the pending layers state=]" f 1. If |session|'s [=pending render state=] is null, set it to a copy of |activeState|. 1. Set |session|'s [=pending render state=]'s {{XRRenderState/layers}} to null. 1. If |newState|'s {{XRRenderStateInit/layers}} is set: + 1. If |newState|'s {{XRRenderStateInit/layers}} contains an {{XRCompositionLayer}} whose [=XRCompositionLayer/destroyed=] boolean is true, throw an {{InvalidStateError}} and abort these steps. 1. If |session| was not created with "[=feature descriptor/layers=]" enabled and |newState|'s {{XRRenderStateInit/layers}} contains more than 1 instance, throw a {{NotSupportedError}} and abort these steps. 1. If |newState|'s {{XRRenderState/layers}} contains more than {{XRSession/maxRenderLayers}} entries, throw a {{NotSupportedError}} and abort these steps. 1. If |session|'s [=pending render state=] is null, set it to a copy of |activeState|. @@ -2196,7 +2230,8 @@ This module replaces the steps given by "[=check the layers state=]" from the We with {{XRSession/renderState}} |state|, the user agent MUST run the following steps: 1. If |state|'s {{XRRenderState/baseLayer}} is not null, return true. - 1. If |state|'s {{XRRenderStateInit/layers}} is not empty, return true. + 1. For each |layer| in |state|'s {{XRRenderState/layers}}: + 1. If |layer| is not an {{XRCompositionLayer}} or |layer|'s [=XRCompositionLayer/destroyed=] boolean is false, return true. 1. return false. XRSession changes {#xrsessionchanges}