// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. module device.mojom; import "mojo/public/mojom/base/time.mojom"; import "gpu/ipc/common/mailbox_holder.mojom"; import "gpu/ipc/common/sync_token.mojom"; import "ui/display/mojo/display.mojom"; import "ui/gfx/geometry/mojo/geometry.mojom"; import "ui/gfx/mojo/gpu_fence_handle.mojom"; import "ui/gfx/mojo/transform.mojom"; // // WebXR interfaces // // TODO: Use EnableIf to only define values on platforms that have // implementations. enum XRDeviceId { LAYOUT_TEST_DEVICE_ID = 0, // Fake device used by layout tests. GVR_DEVICE_ID = 1, OPENVR_DEVICE_ID = 2, OCULUS_DEVICE_ID = 3, ARCORE_DEVICE_ID = 4, ORIENTATION_DEVICE_ID = 5, FAKE_DEVICE_ID = 6, // Fake device used by unit tests. }; enum XRHandedness { NONE = 0, LEFT = 1, RIGHT = 2 }; enum XRTargetRayMode { GAZING = 1, POINTING = 2, TAPPING = 3 }; struct XRSessionOptions { bool immersive; bool provide_passthrough_camera; // A flag to indicate if there has been a user activation when the request // session is made. bool has_user_activation; // This flag ensures that render paths that are only supported in WebXR are // not used for WebVR 1.1. bool use_legacy_webvr_render_path; }; // This structure contains all the mojo interfaces for different kinds of // XRSession. The only interface required by all sessions is the // XRFrameDataProvider. It must always be present. Other interfaces are set as // apropriate based on the session creation options. (for example, an immersive // session ought to have a XRPresentationConnection to submit the frames to the // immersive enviroment). struct XRSession { XRFrameDataProvider data_provider; XRPresentationConnection? submit_frame_sink; XREnviromentIntegrationProvider? enviroment_provider; }; // This structure contains the infomation and interfaces needed to create a two // way connection between the renderer and a device to synchronize and submit // frames to a sink outside of Chrome. struct XRPresentationConnection { XRPresentationProvider provider; XRPresentationClient& client_request; XRPresentationTransportOptions transport_options; }; struct XRInputSourceDescription { XRTargetRayMode target_ray_mode; XRHandedness handedness; bool emulated_position; // Transform from the grip matrix to the pointer's origin and orientation. gfx.mojom.Transform? pointer_offset; }; struct XRInputSourceState { uint32 source_id; // Description of this input source's behavior. Should be mostly static, only // need periodic updates. XRInputSourceDescription? description; // Transform to the controllers grip (users palm) from start space origin. gfx.mojom.Transform? grip; // Describes the current state of the primary input. bool primary_input_pressed; // Indicates if the input's primary input has been released (clicked) since // the last report. May indicate that the button was pressed and released in // the space of a single frame, so it may not have been preceeded by a // primary_input_pressed = true; bool primary_input_clicked; }; // // WebVR/WebXR shared interfaces // // A field of view, given by 4 degrees describing the view from a center point. struct VRFieldOfView { float upDegrees; float downDegrees; float leftDegrees; float rightDegrees; }; // A display's position, orientation, velocity, and acceleration state at the // given timestamp. struct VRPose { array? orientation; array? position; array? angularVelocity; array? linearVelocity; array? angularAcceleration; array? linearAcceleration; // For WebXR sessions only, reports the state of all active input devices // synced with the head pose. array? input_state; // Indicates that a reset pose event was triggered, either by device specific // UI or by some other method, and handled on the browser side, and the // renderer should now bubble up an event to the WebXR Device API. bool pose_reset; }; struct XRRay { // TODO(https://crbug.com/845293): use Point3F and Vector3F from // ui/gfx/geometry and inline directly in requestHitTest(). array origin; array direction; }; struct XRHitResult { // A 4x4 transformation matrix representing the position of the object hit // and the orientation of the normal of the object at the hit location. // TODO(https://crbug.com/845293): use gfx.mojom.Transform. array hit_matrix; }; struct VRDisplayCapabilities { bool hasPosition; bool hasExternalDisplay; // Indicates whether the display can actively show imagery on a headset. bool canPresent; // If true, this is an AR display that can provide a background image along // with each pose. Clients who want them should send a frame image request // via getFrameData instead of getPose. // TODO(https://crbug.com/836349): this may need to change. bool can_provide_pass_through_images; }; // Information about the optical properties for an eye in a VRDisplay. struct VREyeParameters { VRFieldOfView fieldOfView; array offset; uint32 renderWidth; uint32 renderHeight; }; struct VRStageParameters { array standingTransform; float sizeX; float sizeZ; }; struct VRDisplayInfo { XRDeviceId id; string displayName; VRDisplayCapabilities capabilities; VRStageParameters? stageParameters; // Parameters required to distort a scene for viewing in a VR headset. Only // required for devices which have the canPresent capability. VREyeParameters? leftEye; VREyeParameters? rightEye; float webvr_default_framebuffer_scale = 1.0; float webxr_default_framebuffer_scale = 1.0; }; // Frame transport method from the Renderer's point of view. enum XRPresentationTransportMethod { NONE = 0, // Renderer should create a new texture handle (Windows) or // texture mailbox (Android Surface path) containing the // frame's image and supply that as a submitFrame argument. SUBMIT_AS_TEXTURE_HANDLE = 1, SUBMIT_AS_MAILBOX_HOLDER = 2, // Renderer should draw directly into a texture mailbox // provided for each frame in OnVSync. DRAW_INTO_TEXTURE_MAILBOX = 3, }; struct XRPresentationTransportOptions { XRPresentationTransportMethod transport_method; // Booleans indicating which of the XRPresentationClient callbacks // are in use. Default is false, the device implementation should set // the ones to true that it needs and can ignore the rest. bool wait_for_transfer_notification; bool wait_for_render_notification; bool wait_for_gpu_fence; }; // The data needed for each animation frame of an XRSession. struct XRFrameData { // General XRSession value // The pose may be null if the device lost tracking. The XRFrameData can still // have other data, such as pass through camera image. VRPose? pose; // TODO(https://crbug.com/838515): Is this delta since the last // frame? OR an unspecified origin? Something else? mojo_base.mojom.TimeDelta time_delta; // The buffer_holder is used for sending data imagery back and forth across // the process boundary. For application with pass through camera, it holds // the camera image to be passed to the renderer. For immersive sessions, it // is the place for the renderer to draw into to pass imagery to the device // for rendering. gpu.mojom.MailboxHolder? buffer_holder; // Exclusive session values // The frame_id maps frame data to a frame arriving from the compositor. IDs // will be reused after the frame arrives from the compositor. Negative IDs // imply no mapping. int16 frame_id; // Pass through camera values gfx.mojom.Size? buffer_size; array? projection_matrix; }; enum VRDisplayEventReason { NONE = 0, NAVIGATION = 1, MOUNTED = 2, UNMOUNTED = 3 }; // TODO(shaobo.yan@intel.com) : Add comments to describe these interfaces about // how to use and where they live. interface VRService { // TODO(shaobo.yan@intel.com, https://crbug.com/701027): Use a factory // function which takes a VRServiceClient so we will never have a // half-initialized VRService. SetClient(VRServiceClient client) => (); // Inform the service that the page is listening for vrdisplayactivate events. // TODO(mthiesse): Move SetListeningForActivate onto VRDisplay. SetListeningForActivate(bool listening); }; interface VRServiceClient { OnDisplayConnected(XRDevice device, VRDisplayClient& request, VRDisplayInfo display_info); }; // Provides a communication channel from the renderer to the browser-side host // of a (device/) VrDisplayImpl. interface XRDevice { // Request to initialize a session in the browser process. The return value // indicates if the session was successfully initialized or not. // TODO(https://crbug.com/842025): Refactor VR device interfaces to better // reflect WebXR. RequestSession( XRSessionOptions options, bool triggered_by_displayactive) => (XRSession? session); SupportsSession(XRSessionOptions options) => (bool supports_session); ExitPresent(); }; // Provides the necessary functionality for a WebXR session to get data for // drawing frames. The kind of data it gets depends on what kind of session was // requested. // This interface is hosted in the Browser process, but will move to a sandboxed // utility process on Windows. The render process communicates with it. interface XRFrameDataProvider { // frame_data is optional and will not be set if and only if the call fails // for some reason, such as device disconnection. GetFrameData() => (XRFrameData? frame_data); }; // Provides functionality for integrating enviroment information into an // XRSession. For example, some AR sessions would implement hit test to allow // developers to get the information about the world that its sensors supply. interface XREnviromentIntegrationProvider { // Different devices can have different native orientations - 0 is the native // orientation, and then increments of 90 degrees from there. Session geometry // is needed by the device when integrating enviroment image data, i.e. camera // feeds, into a session. UpdateSessionGeometry( gfx.mojom.Size frame_size, display.mojom.Rotation display_rotation); // Performs a raycast into the scene and returns a list of XRHitResults sorted // from closest to furthest hit from the ray. Each hit result contains a // hit_matrix containing the transform of the hit where the rotation // represents the normal of the surface hit. // An empty result list means there were no hits. If a nullopt is returned, // there was an error. RequestHitTest(XRRay ray) => (array? results); }; // Provides the necessary functionality for sending frames to a headset. // This interface is hosted in the Browser process, but will move to a sandboxed // utility process on Windows. The render process communicates with it. interface XRPresentationProvider { // This function tells the device which parts of the canvas should be rendered // to which view. UpdateLayerBounds(int16 frame_id, gfx.mojom.RectF left_bounds, gfx.mojom.RectF right_bounds, gfx.mojom.Size source_size); // Call this if the animation loop exited without submitting a frame to // ensure that every GetFrameData has a matching Submit call. This happens for // WebXR if there were no drawing operations to the opaque framebuffer, and // for WebVR 1.1 if the application didn't call SubmitFrame. Usable with any // XRPresentationTransportMethod. This path does *not* call the // SubmitFrameClient methods such as OnSubmitFrameTransferred. This is // intended to help separate frames while presenting, it may or may not // be called for the last animating frame when presentation ends. SubmitFrameMissing(int16 frame_id, gpu.mojom.SyncToken sync_token); // XRPresentationTransportMethod SUBMIT_AS_MAILBOX_HOLDER SubmitFrame(int16 frame_id, gpu.mojom.MailboxHolder mailbox_holder, mojo_base.mojom.TimeDelta time_waited); // XRPresentationTransportMethod SUBMIT_AS_TEXTURE_HANDLE // TODO(https://crbug.com/676224): Support preprocessing of mojom files, since // this is Windows only. SubmitFrameWithTextureHandle(int16 frameId, handle texture); // XRPresentationTransportMethod DRAW_INTO_TEXTURE_MAILBOX SubmitFrameDrawnIntoTexture(int16 frameId, gpu.mojom.SyncToken sync_token, mojo_base.mojom.TimeDelta time_waited); }; // After submitting a frame, the XRPresentationProvider will notify the client // about several stages of the render pipeline. This allows pipelining // efficiency. Following XRPresentationProvider::Submit*, the submitted frame // will be transferred (read from, perhaps copied to another texture), and then // rendered (submitted to the underlying VR API). // The client lives in the render process. // // See XRPresentationTransportOptions which configures which of these // callbacks are in use. interface XRPresentationClient { // The XRPresentationProvider calls this to indicate that the submitted frame // has been transferred, so the backing data (mailbox or GpuMemoryBuffer) can // be reused or discarded. Note that this is a convenience/optimization // feature, not a security feature - if a site discards the data early we may // drop a frame, but nothing will otherwise misbehave. // When the frame wasn't successfully transferred, the client should create a // new mailbox/GpuMemoryBuffer rather than reusing an existing one to recover // for subsequent frames. OnSubmitFrameTransferred(bool success); // The XRPresentationProvider calls this after the frame was handed off to the // underlying VR API. This allows some pipelining of CPU/GPU work, while // delaying expensive tasks for a subsequent frame until the current frame has // completed. OnSubmitFrameRendered(); // This callback provides a GpuFence corresponding to the previous frame's // rendering completion, intended for use with a server wait issued before // the following wait to prevent its rendering work from competing with // the previous frame. OnSubmitFrameGpuFence(gfx.mojom.GpuFenceHandle gpu_fence_handle); }; interface VRDisplayClient { OnChanged(VRDisplayInfo display); OnExitPresent(); OnBlur(); OnFocus(); OnActivate(VRDisplayEventReason reason) => (bool will_not_present); OnDeactivate(VRDisplayEventReason reason); };