← All reports

[visionOS] Introduce Connected Volumetric Scenes

Component: WebKit visionOS model element / Spatial Portal | a216b77

LayoutTests/model-element/volumetric/resources/volumetric-utils.js

+// Presentation 여부는 UI process가 확정하므로, 모든 전환은 비동기적으로 완료됩니다.
+const waitForPresentationMode = (test, element, expected) =>
+ test.step_wait(() => presentationMode(element) === expected, `presentation mode becomes "${expected}"`);
+
+// requestVolumetricScene()은 호출 시 transient activation을 사용하므로, 매 호출마다 새로운 activation이 필요합니다.
+const requestVolumetricScene = element => {
+ let promise;
+ internals.withUserGesture(() => { promise = element.requestVolumetricScene(); });
+ return promise;
+};
...

LayoutTests/model-element/volumetric/volumetric-scene-api-disabled.html

+<!DOCTYPE html> <!-- webkit-test-runner [ SpatialPortalEnabled=false ModelElementEnabled=true ModelProcessEnabled=true ] -->
+ assert_false('requestVolumetricScene' in div, 'requestVolumetricScene should be absent from Element');
+ assert_false('exitVolumetricScene' in model, 'exitVolumetricScene should be absent from a model');

visionOS에서 <model> content는 별도의 ModelProcess(RealityKit)가 rendering합니다. WebContent는 player proxy와 layer hosting context만 보유하며, UI process가 이를 page에 composite합니다. 한편 spatial: portal element는 하위 model들을 SpatialPortalController 아래에 묶어 관리합니다. 별도의 volumetric window에 표시하려면, 평소 page가 점유하던 layer hosting context를 UI process가 새로 생성한 UIScene에 넘겨야 합니다. 이때 생성된 scene은 자신을 요청한 request와 다시 짝지어져야 합니다.

이 commit은 실험적 기능인 Connected Volumetric Scenes를 추가했습니다. 기본값은 비활성화 상태입니다. 먼저 spatial: portal element와 단독 <model> element를 대상으로, Element에 requestVolumetricScene()과 exitVolumetricScene()이 노출되었습니다. 이를 호출하면 page가 계속 동작하는 상태에서 model content가 별도의 volumetric window에 표시됩니다. 새로 추가된 ElementVolumetricScene은 호출을 SpatialPortalController 또는 HTMLModelElement로 분기합니다.

또한 기존의 immersive detach flag는 inline, immersive, volumetric을 통합한 ModelPresentationMode로 대체되었습니다. enter, exit, resize는 새 message를 통해 WebPage, WebPageProxy, ModelProcessModelPlayer, ModelProcessModelPlayerProxy를 거쳐 전달됩니다. 결과적으로 UI process는 새로운 WKPortalVolumetricSceneController 안에서 model process의 layer를 hosting하게 됩니다.

WebContent                    UIProcess                         ModelProcess
   │                              │                                  │
   │ requestVolumetricScene()     │                                  │
   │ (transient activation        │                                  │
   │  consumed)                   │                                  │
   ├─ enterVolumetricScene… ─────►│ presentVolumetricScene           │
   │  (scene-limit check first)   │  ├─ create token + pending ctrl  │
   │                              │  ├─ activate UIScene(token)      │
   │                              │  │   └─ scene:willConnect…       │
   │                              │  │      match token → ctrl       │
   │                              │  └─ hostContent(ctx, pid) ──────►│ layer hosted in
   │                              │                                  │ volume
   │◄─ updateVolumetricSceneSize ─┤ volume size change               │
   │                              │                                  │
   │◄─ volumetricSceneDidClose ───┤ window closed / dismissed        │
   │ (also on navigation/detach   │                                  │
   │  → dismissVolumetricScenes…) │                                  │

Page가 보유하던 layer hosting context를 UI process 소유의 window로 옮기는, web에서 도달 가능한 신규 API입니다. 이와 함께 WebContent, ModelProcess, UIProcess를 잇는 IPC와 token 기반 scene activation flow가 추가되었습니다.

새로 생긴 surface는 DOM API에서 시작해 WebPage, WebPageProxy IPC, PortalPresentationManagerProxy, WKPortalVolumetricSceneController로 이어집니다. 이와 병렬로 ModelProcessModelPlayerProxy로 향하는 message 경로도 존재합니다.