@covas-labs/electron-vr 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -1
- package/dist/bridge.d.ts +4 -0
- package/dist/bridge.js +36 -3
- package/dist/compatibility.d.ts +2 -1
- package/dist/compatibility.js +15 -3
- package/dist/openxrApiLayer.d.ts +1 -0
- package/dist/openxrApiLayer.js +3 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -106,6 +106,8 @@ await VROverlay.uninstallOpenXRApiLayer();
|
|
|
106
106
|
|
|
107
107
|
The methods return `Promise<OpenXRApiLayerStatus>` and reject when the platform is unsupported or the utility fails. Installation should require explicit user consent. It affects subsequently started OpenXR applications, so restart an already running game after installing, enabling, disabling, or uninstalling the layer. These methods support Linux x64 and Windows x64 and do not require administrator/root access for the normal per-user installation.
|
|
108
108
|
|
|
109
|
+
`getOpenXRApiLayerStatus()` reports `requiresUpdate: true` when the installed layer assets differ from those bundled with the package. Re-run `installOpenXRApiLayer()` after confirmation to update them.
|
|
110
|
+
|
|
109
111
|
For product UI, prefer the combined readiness report instead of interpreting raw probe fields:
|
|
110
112
|
|
|
111
113
|
```ts
|
|
@@ -115,4 +117,4 @@ console.log(report.launch.verdict, report.launch.requiredActions);
|
|
|
115
117
|
|
|
116
118
|
`report.launch.wouldWorkNow` answers whether launching a browser overlay now is expected to produce real VR output. Otherwise, the verdict distinguishes an actionable setup/runtime/host requirement from a fundamental incompatibility. The report also exposes detailed readiness states, actionable issues, and per-feature support. See `PRODUCT_INTEGRATION.md` in the repository for the recommended consent, IPC, restart, recovery, diagnostics, and production UI flow.
|
|
117
119
|
|
|
118
|
-
`getRuntimeInfo()` also includes `openvrRuntimeInstalled`, `openvrRuntimePath`, `openxrMode`, API-layer installation
|
|
120
|
+
`getRuntimeInfo()` also includes `openvrRuntimeInstalled`, `openvrRuntimePath`, `openxrMode`, API-layer installation state, `openxrHostDetected`, companion connection state, protocol version, and OpenXR host metadata. `openxrHostDetected` can become true before the overlay companion connects. `probeMode` includes the backend-selection decision.
|
package/dist/bridge.d.ts
CHANGED
|
@@ -22,11 +22,14 @@ export interface RuntimeInfo {
|
|
|
22
22
|
openxrApiLayerEnabled: boolean;
|
|
23
23
|
openxrApiLayerManifestPath: string;
|
|
24
24
|
openxrCompanionConnected: boolean;
|
|
25
|
+
openxrHostDetected: boolean;
|
|
25
26
|
openxrHostProcessId: number;
|
|
26
27
|
openxrHostApplicationName: string;
|
|
27
28
|
openxrHostGraphicsApi: string;
|
|
28
29
|
openxrHostAdapterLuid: string;
|
|
29
30
|
openxrProtocolVersion: number;
|
|
31
|
+
openxrSubmittedFrameSequence: number;
|
|
32
|
+
openxrConsumedFrameSequence: number;
|
|
30
33
|
openvrAvailable: boolean;
|
|
31
34
|
openvrRuntimeInstalled: boolean;
|
|
32
35
|
openvrRuntimePath: string;
|
|
@@ -117,6 +120,7 @@ export declare class VrBridge {
|
|
|
117
120
|
private linuxOpenVRVisibleTexture;
|
|
118
121
|
private windowsReadbackInFlight;
|
|
119
122
|
private windowsReadbackPending;
|
|
123
|
+
private windowsOpenXRTextures;
|
|
120
124
|
private linuxReadbackInFlight;
|
|
121
125
|
private linuxReadbackPending;
|
|
122
126
|
private invalidationTimer;
|
package/dist/bridge.js
CHANGED
|
@@ -116,11 +116,14 @@ function sanitizeRuntimeInfo(runtimeInfo) {
|
|
|
116
116
|
openxrApiLayerEnabled: runtimeInfo.openxrApiLayerEnabled ?? false,
|
|
117
117
|
openxrApiLayerManifestPath: runtimeInfo.openxrApiLayerManifestPath ?? "",
|
|
118
118
|
openxrCompanionConnected: runtimeInfo.openxrCompanionConnected ?? false,
|
|
119
|
+
openxrHostDetected: runtimeInfo.openxrHostDetected ?? false,
|
|
119
120
|
openxrHostProcessId: runtimeInfo.openxrHostProcessId ?? 0,
|
|
120
121
|
openxrHostApplicationName: runtimeInfo.openxrHostApplicationName ?? "",
|
|
121
122
|
openxrHostGraphicsApi: runtimeInfo.openxrHostGraphicsApi ?? "",
|
|
122
123
|
openxrHostAdapterLuid: runtimeInfo.openxrHostAdapterLuid ?? "",
|
|
123
124
|
openxrProtocolVersion: runtimeInfo.openxrProtocolVersion ?? 0,
|
|
125
|
+
openxrSubmittedFrameSequence: runtimeInfo.openxrSubmittedFrameSequence ?? 0,
|
|
126
|
+
openxrConsumedFrameSequence: runtimeInfo.openxrConsumedFrameSequence ?? 0,
|
|
124
127
|
openvrSceneApplicationState: runtimeInfo.openvrSceneApplicationState ?? "",
|
|
125
128
|
openvrSceneProcessId: runtimeInfo.openvrSceneProcessId ?? 0,
|
|
126
129
|
openvrSceneApplicationKey: runtimeInfo.openvrSceneApplicationKey ?? "",
|
|
@@ -211,6 +214,7 @@ export class VrBridge {
|
|
|
211
214
|
linuxOpenVRVisibleTexture = null;
|
|
212
215
|
windowsReadbackInFlight = false;
|
|
213
216
|
windowsReadbackPending = false;
|
|
217
|
+
windowsOpenXRTextures = [];
|
|
214
218
|
linuxReadbackInFlight = false;
|
|
215
219
|
linuxReadbackPending = false;
|
|
216
220
|
invalidationTimer = null;
|
|
@@ -242,6 +246,9 @@ export class VrBridge {
|
|
|
242
246
|
return;
|
|
243
247
|
}
|
|
244
248
|
this.linuxReadbackPending = false;
|
|
249
|
+
for (const retained of this.windowsOpenXRTextures)
|
|
250
|
+
releaseTexture(retained.texture);
|
|
251
|
+
this.windowsOpenXRTextures = [];
|
|
245
252
|
const offscreenContents = this.attachedWindow.webContents;
|
|
246
253
|
offscreenContents.removeListener("paint", this.onPaint);
|
|
247
254
|
this.attachedWindow = null;
|
|
@@ -472,6 +479,19 @@ export class VrBridge {
|
|
|
472
479
|
console.log(`VR overlay received first paint event (platform=${process.platform}, backend=${this.getSelectedBackend()}, hasTexture=${texture ? "yes" : "no"}, hasBitmap=${nativeImage ? "yes" : "no"}).`);
|
|
473
480
|
}
|
|
474
481
|
const runtimeInfo = this.getRuntimeInfo();
|
|
482
|
+
if (process.platform === "win32" && this.windowsOpenXRTextures.length > 0) {
|
|
483
|
+
const consumedSequence = runtimeInfo.openxrConsumedFrameSequence;
|
|
484
|
+
const pending = [];
|
|
485
|
+
for (const retained of this.windowsOpenXRTextures) {
|
|
486
|
+
if (retained.sequence <= consumedSequence) {
|
|
487
|
+
releaseTexture(retained.texture);
|
|
488
|
+
}
|
|
489
|
+
else {
|
|
490
|
+
pending.push(retained);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
this.windowsOpenXRTextures = pending;
|
|
494
|
+
}
|
|
475
495
|
if (process.platform === "linux" &&
|
|
476
496
|
runtimeInfo.selectedBackend === "openvr" &&
|
|
477
497
|
isTruthyEnvironmentVariable("ELECTRON_VR_OPENVR_VULKAN_SOFTWARE")) {
|
|
@@ -548,9 +568,22 @@ export class VrBridge {
|
|
|
548
568
|
this.useWindowsSoftwareFallback(nativeImage, "Windows shared texture submission failed; falling back to software RGBA upload.");
|
|
549
569
|
}
|
|
550
570
|
}
|
|
551
|
-
else
|
|
552
|
-
|
|
553
|
-
|
|
571
|
+
else {
|
|
572
|
+
if (runtimeInfo.selectedBackend === "openxr" && runtimeInfo.openxrMode === "api-layer" &&
|
|
573
|
+
runtimeInfo.openxrHostGraphicsApi === "d3d11") {
|
|
574
|
+
const updatedRuntimeInfo = this.getRuntimeInfo();
|
|
575
|
+
if (updatedRuntimeInfo.openxrSubmittedFrameSequence > runtimeInfo.openxrSubmittedFrameSequence) {
|
|
576
|
+
this.windowsOpenXRTextures.push({
|
|
577
|
+
sequence: updatedRuntimeInfo.openxrSubmittedFrameSequence,
|
|
578
|
+
texture
|
|
579
|
+
});
|
|
580
|
+
releaseCurrentTexture = false;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
if (!this.loggedFirstWindowsSubmit) {
|
|
584
|
+
this.loggedFirstWindowsSubmit = true;
|
|
585
|
+
console.log("VR overlay submitted first Windows frame to the native bridge.");
|
|
586
|
+
}
|
|
554
587
|
}
|
|
555
588
|
}
|
|
556
589
|
else if (this.getSelectedBackend() === "openvr") {
|
package/dist/compatibility.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export type VRReadiness = "ready" | "setup-required" | "waiting-for-host" | "fal
|
|
|
4
4
|
export type VRLaunchVerdict = "works-now" | "action-required" | "incompatible";
|
|
5
5
|
export type VRFeatureSupport = "supported" | "unsupported" | "runtime-dependent";
|
|
6
6
|
export type VRIssueSeverity = "info" | "warning" | "error";
|
|
7
|
-
export type VRSetupAction = "install-openxr-api-layer" | "enable-openxr-api-layer" | "restart-openxr-apps" | "start-openxr-app" | "install-xr-runtime" | "use-supported-openxr-host" | "none";
|
|
7
|
+
export type VRSetupAction = "install-openxr-api-layer" | "reinstall-openxr-api-layer" | "enable-openxr-api-layer" | "restart-openxr-apps" | "start-openxr-app" | "install-xr-runtime" | "use-supported-openxr-host" | "none";
|
|
8
8
|
export interface VRFeatureCompatibility {
|
|
9
9
|
flatOverlay: VRFeatureSupport;
|
|
10
10
|
curvature: VRFeatureSupport;
|
|
@@ -25,6 +25,7 @@ export interface VRCompatibilityIssue {
|
|
|
25
25
|
export interface VRLaunchAssessment {
|
|
26
26
|
verdict: VRLaunchVerdict;
|
|
27
27
|
wouldWorkNow: boolean;
|
|
28
|
+
canStartNow: boolean;
|
|
28
29
|
fundamentalIncompatibility: boolean;
|
|
29
30
|
message: string;
|
|
30
31
|
requiredActions: VRSetupAction[];
|
package/dist/compatibility.js
CHANGED
|
@@ -37,6 +37,7 @@ export function analyzeVRCompatibility(runtime, context = {}) {
|
|
|
37
37
|
(context.architecture ?? process.arch) === "x64";
|
|
38
38
|
const layerInstalled = apiLayer?.installed ?? runtime.openxrApiLayerInstalled;
|
|
39
39
|
const layerEnabled = apiLayer?.enabled ?? runtime.openxrApiLayerEnabled;
|
|
40
|
+
const layerRequiresUpdate = apiLayer?.requiresUpdate ?? false;
|
|
40
41
|
let readiness = "unavailable";
|
|
41
42
|
let backendLabel = "No compatible VR backend";
|
|
42
43
|
let summary = "No compatible XR runtime is ready.";
|
|
@@ -56,9 +57,15 @@ export function analyzeVRCompatibility(runtime, context = {}) {
|
|
|
56
57
|
features = { ...realFeatures };
|
|
57
58
|
compatibleHostGraphicsApis = runtime.platform === "win32" ? ["D3D11", "D3D12"] : ["Vulkan", "OpenGL Xlib/GLX"];
|
|
58
59
|
backendLabel = "OpenXR application integration";
|
|
59
|
-
if (
|
|
60
|
+
if (layerRequiresUpdate) {
|
|
61
|
+
readiness = "setup-required";
|
|
62
|
+
summary = "OpenXR application integration must be updated before overlays can appear.";
|
|
63
|
+
recommendedAction = "reinstall-openxr-api-layer";
|
|
64
|
+
issues.push(issue("openxr-api-layer-update-required", "warning", "Update OpenXR integration", "Reinstall the per-user integration and restart OpenXR applications.", "reinstall-openxr-api-layer"));
|
|
65
|
+
}
|
|
66
|
+
else if (runtime.openxrCompanionConnected || runtime.openxrHostDetected) {
|
|
60
67
|
readiness = "ready";
|
|
61
|
-
summary =
|
|
68
|
+
summary = `${runtime.openxrCompanionConnected ? "Connected to" : "Detected"} ${runtime.openxrHostApplicationName || "an OpenXR application"} using ${runtime.openxrHostGraphicsApi || "a supported graphics API"}.`;
|
|
62
69
|
}
|
|
63
70
|
else if (!layerEnabled) {
|
|
64
71
|
readiness = "setup-required";
|
|
@@ -131,6 +138,7 @@ export function analyzeVRCompatibility(runtime, context = {}) {
|
|
|
131
138
|
launch = {
|
|
132
139
|
verdict: "works-now",
|
|
133
140
|
wouldWorkNow: true,
|
|
141
|
+
canStartNow: true,
|
|
134
142
|
fundamentalIncompatibility: false,
|
|
135
143
|
message: "Launching the browser overlay now is expected to produce real VR output.",
|
|
136
144
|
requiredActions: []
|
|
@@ -143,6 +151,7 @@ export function analyzeVRCompatibility(runtime, context = {}) {
|
|
|
143
151
|
launch = {
|
|
144
152
|
verdict: "action-required",
|
|
145
153
|
wouldWorkNow: false,
|
|
154
|
+
canStartNow: false,
|
|
146
155
|
fundamentalIncompatibility: false,
|
|
147
156
|
message: "The overlay is compatible, but setup must be completed before launching it.",
|
|
148
157
|
requiredActions: actions
|
|
@@ -152,6 +161,7 @@ export function analyzeVRCompatibility(runtime, context = {}) {
|
|
|
152
161
|
launch = {
|
|
153
162
|
verdict: "action-required",
|
|
154
163
|
wouldWorkNow: false,
|
|
164
|
+
canStartNow: true,
|
|
155
165
|
fundamentalIncompatibility: false,
|
|
156
166
|
message: `The overlay is ready, but real VR output requires a compatible ${compatibleHostGraphicsApis.join(" or ")} OpenXR application to be started or restarted.`,
|
|
157
167
|
requiredActions: ["start-openxr-app"]
|
|
@@ -161,6 +171,7 @@ export function analyzeVRCompatibility(runtime, context = {}) {
|
|
|
161
171
|
launch = {
|
|
162
172
|
verdict: "action-required",
|
|
163
173
|
wouldWorkNow: false,
|
|
174
|
+
canStartNow: false,
|
|
164
175
|
fundamentalIncompatibility: false,
|
|
165
176
|
message: "Launching now would not produce real VR output. Install and configure a supported OpenXR or SteamVR runtime first.",
|
|
166
177
|
requiredActions: ["install-xr-runtime"]
|
|
@@ -170,6 +181,7 @@ export function analyzeVRCompatibility(runtime, context = {}) {
|
|
|
170
181
|
launch = {
|
|
171
182
|
verdict: "incompatible",
|
|
172
183
|
wouldWorkNow: false,
|
|
184
|
+
canStartNow: false,
|
|
173
185
|
fundamentalIncompatibility: true,
|
|
174
186
|
message: "This platform or execution mode cannot provide a production VR overlay with the current implementation.",
|
|
175
187
|
requiredActions: []
|
|
@@ -185,7 +197,7 @@ export function analyzeVRCompatibility(runtime, context = {}) {
|
|
|
185
197
|
canRenderOverlay,
|
|
186
198
|
isRealVrBackend: runtime.selectedBackend === "openxr" || runtime.selectedBackend === "openvr",
|
|
187
199
|
requiresApiLayer,
|
|
188
|
-
requiresOpenXRAppRestart: requiresApiLayer && (!runtime.openxrCompanionConnected || !layerEnabled),
|
|
200
|
+
requiresOpenXRAppRestart: requiresApiLayer && (!(runtime.openxrHostDetected || runtime.openxrCompanionConnected) || !layerEnabled),
|
|
189
201
|
apiLayer,
|
|
190
202
|
compatibleHostGraphicsApis,
|
|
191
203
|
features,
|
package/dist/openxrApiLayer.d.ts
CHANGED
package/dist/openxrApiLayer.js
CHANGED
|
@@ -52,7 +52,8 @@ function runCommand(command) {
|
|
|
52
52
|
...process.env,
|
|
53
53
|
ELECTRON_RUN_AS_NODE: "1"
|
|
54
54
|
},
|
|
55
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
55
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
56
|
+
windowsHide: true
|
|
56
57
|
});
|
|
57
58
|
let stdout = "";
|
|
58
59
|
let stderr = "";
|
|
@@ -84,6 +85,7 @@ export function parseOpenXRApiLayerStatus(output) {
|
|
|
84
85
|
installed: values.get("installed") === "true",
|
|
85
86
|
enabled: values.get("enabled") === "true",
|
|
86
87
|
registered: values.has("registered") ? values.get("registered") === "true" : null,
|
|
88
|
+
requiresUpdate: values.get("requires_update") === "true",
|
|
87
89
|
manifestPath: values.get("manifest") ?? "",
|
|
88
90
|
scope: values.get("scope") ?? "current-user"
|
|
89
91
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@covas-labs/electron-vr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Electron VR overlay bridge with OpenXR, OpenVR, and mock fallback backends.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"electron": ">=37"
|
|
23
23
|
},
|
|
24
24
|
"optionalDependencies": {
|
|
25
|
-
"@covas-labs/electron-vr-prebuilt-linux-x64": "0.
|
|
26
|
-
"@covas-labs/electron-vr-prebuilt-win32-x64": "0.
|
|
25
|
+
"@covas-labs/electron-vr-prebuilt-linux-x64": "0.8.0",
|
|
26
|
+
"@covas-labs/electron-vr-prebuilt-win32-x64": "0.8.0"
|
|
27
27
|
},
|
|
28
28
|
"publishConfig": {
|
|
29
29
|
"registry": "https://registry.npmjs.org",
|