SW 중심대학 OSS GIT 서버 박건태, 이승준, 고기완, 이준호 새로운 배포
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1025 lines
50 KiB

4 years ago
  1. using System;
  2. using System.Collections.Generic;
  3. using Unity.Collections;
  4. namespace UnityEngine.XR.ARSubsystems
  5. {
  6. /// <summary>
  7. /// Provides access to a device's camera.
  8. /// </summary>
  9. /// <remarks>
  10. /// The <c>XRCameraSubsystem</c> links a Unity <c>Camera</c> to a device camera for video overlay (pass-thru
  11. /// rendering). It also allows developers to query for environmental light estimation, when available.
  12. /// </remarks>
  13. public abstract class XRCameraSubsystem : XRSubsystem<XRCameraSubsystemDescriptor>
  14. {
  15. /// <summary>
  16. /// The provider created by the implementation that contains the required camera functionality.
  17. /// </summary>
  18. /// <value>
  19. /// The provider created by the implementation that contains the required camera functionality.
  20. /// </value>
  21. Provider m_Provider;
  22. /// <summary>
  23. /// Construct the <c>XRCameraSubsystem</c>.
  24. /// </summary>
  25. public XRCameraSubsystem()
  26. {
  27. m_Provider = CreateProvider();
  28. Debug.Assert(m_Provider != null, "camera functionality provider cannot be null");
  29. }
  30. /// <summary>
  31. /// Interface for providing camera functionality for the implementation.
  32. /// </summary>
  33. protected class Provider
  34. {
  35. /// <summary>
  36. /// Property to be implemented by the provder to get the material used by <c>XRCameraSubsystem</c> to
  37. /// render the camera texture.
  38. /// </summary>
  39. /// <returns>
  40. /// The material to render the camera texture.
  41. /// </returns>
  42. public virtual Material cameraMaterial => null;
  43. /// <summary>
  44. /// Property to be implemented by the provider to determine whether camera permission has been granted.
  45. /// </summary>
  46. /// <value>
  47. /// <c>true</c> if camera permission has been granted. Otherwise, <c>false</c>.
  48. /// </value>
  49. public virtual bool permissionGranted => false;
  50. /// <summary>
  51. /// Whether or not culling should be inverted during rendering. Some front-facing
  52. /// camera modes may require this.
  53. /// </summary>
  54. public virtual bool invertCulling => false;
  55. /// <summary>
  56. /// Method to be implemented by provider to start the camera for the subsystem.
  57. /// </summary>
  58. public virtual void Start() { }
  59. /// <summary>
  60. /// Method to be implemented by provider to stop the camera for the subsystem.
  61. /// </summary>
  62. public virtual void Stop() { }
  63. /// <summary>
  64. /// Method to be implemented by provider to destroy the camera for the subsystem.
  65. /// </summary>
  66. public virtual void Destroy() { }
  67. /// <summary>
  68. /// Method to be implemented by provider to get the camera frame for the subsystem.
  69. /// </summary>
  70. /// <param name="cameraParams">The current Unity <c>Camera</c> parameters.</param>
  71. /// <param name="cameraFrame">The current camera frame returned by the method.</param>
  72. /// <returns>
  73. /// <c>true</c> if the method successfully got a frame. Otherwise, <c>false</c>.
  74. /// </returns>
  75. public virtual bool TryGetFrame(
  76. XRCameraParams cameraParams,
  77. out XRCameraFrame cameraFrame)
  78. {
  79. cameraFrame = default(XRCameraFrame);
  80. return false;
  81. }
  82. /// <summary>
  83. /// Property to be implemented by the provider to get or set the focus mode for the camera.
  84. /// </summary>
  85. public virtual CameraFocusMode cameraFocusMode
  86. {
  87. get => CameraFocusMode.Fixed;
  88. set { }
  89. }
  90. /// <summary>
  91. /// Method to be implemented by the provider to set the light estimation mode.
  92. /// </summary>
  93. /// <param name="lightEstimationMode">The light estimation mode to set.</param>
  94. /// <returns>
  95. /// <c>true</c> if the method successfully set the light estimation mode. Otherwise, <c>false</c>.
  96. /// </returns>
  97. public virtual bool TrySetLightEstimationMode(LightEstimationMode lightEstimationMode) => false;
  98. /// <summary>
  99. /// Method to be implemented by the provider to get the camera intrinisics information.
  100. /// </summary>
  101. /// <param name="cameraIntrinsics">The camera intrinsics information returned from the method.</param>
  102. /// <returns>
  103. /// <c>true</c> if the method successfully gets the camera intrinsics information. Otherwise, <c>false</c>.
  104. /// </returns>
  105. public virtual bool TryGetIntrinsics(
  106. out XRCameraIntrinsics cameraIntrinsics)
  107. {
  108. cameraIntrinsics = default(XRCameraIntrinsics);
  109. return false;
  110. }
  111. /// <summary>
  112. /// Method to be implemented by the provider to query the supported camera configurations.
  113. /// </summary>
  114. /// <param name="defaultCameraConfiguration">A default value used to fill the returned array before copying
  115. /// in real values. This ensures future additions to this struct are backwards compatible.</param>
  116. /// <param name="allocator">The allocation strategy to use for the returned data.</param>
  117. /// <returns>
  118. /// The supported camera configurations.
  119. /// </returns>
  120. public virtual NativeArray<XRCameraConfiguration> GetConfigurations(XRCameraConfiguration defaultCameraConfiguration,
  121. Allocator allocator)
  122. {
  123. return new NativeArray<XRCameraConfiguration>(0, allocator);
  124. }
  125. /// <summary>
  126. /// Property to be implemented by the provider to query/set the current camera configuration.
  127. /// </summary>
  128. /// <value>
  129. /// The current camera configuration if it exists. Otherise, <c>null</c>.
  130. /// </value>
  131. /// <exception cref="System.NotSupportedException">Thrown when setting the current configuration if the
  132. /// implementation does not support camera configurations.</exception>
  133. /// <exception cref="System.ArgumentException">Thrown when setting the current configuration if the given
  134. /// configuration is not a valid, supported camera configuration.</exception>
  135. /// <exception cref="System.InvalidOperationException">Thrown when setting the current configuration if the
  136. /// implementation is unable to set the current camera configuration.</exception>
  137. public virtual XRCameraConfiguration? currentConfiguration
  138. {
  139. get => null;
  140. set => throw new NotSupportedException("setting current camera configuration is not supported by this implementation");
  141. }
  142. /// <summary>
  143. /// Get the <see cref="XRTextureDescriptor"/>s associated with the current
  144. /// <see cref="XRCameraFrame"/>.
  145. /// </summary>
  146. /// <returns>The current texture descriptors.</returns>
  147. /// <param name="defaultDescriptor">A default value which should
  148. /// be used to fill the returned array before copying in the
  149. /// real values. This ensures future additions to this struct
  150. /// are backwards compatible.</param>
  151. /// <param name="allocator">The allocator to use when creating
  152. /// the returned <c>NativeArray</c>.</param>
  153. public virtual NativeArray<XRTextureDescriptor> GetTextureDescriptors(
  154. XRTextureDescriptor defaultDescriptor,
  155. Allocator allocator)
  156. {
  157. return new NativeArray<XRTextureDescriptor>(0, allocator);
  158. }
  159. /// <summary>
  160. /// Method to be implemented by the provider to get the enabled and disabled shader keywords for the
  161. /// material.
  162. /// </summary>
  163. /// <param name="enabledKeywords">The keywords to enable for the material.</param>
  164. /// <param name="disabledKeywords">The keywords to disable for the material.</param>
  165. public virtual void GetMaterialKeywords(out List<string> enabledKeywords, out List<string> disabledKeywords)
  166. {
  167. enabledKeywords = null;
  168. disabledKeywords = null;
  169. }
  170. /// <summary>
  171. /// Method to be implemented by the provider to query for the latest native camera image.
  172. /// </summary>
  173. /// <param name="cameraImageCinfo">The metadata required to construct a <see cref="XRCameraImage"/></param>
  174. /// <returns>
  175. /// <c>true</c> if the camera image is acquired. Otherwise, <c>false</c>.
  176. /// </returns>
  177. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera
  178. /// image.</exception>
  179. public virtual bool TryAcquireLatestImage(out CameraImageCinfo cameraImageCinfo)
  180. {
  181. throw new NotSupportedException("getting camera image is not supported by this implementation");
  182. }
  183. /// <summary>
  184. /// Method to be implemented by the provider to get the status of an existing asynchronous conversion
  185. /// request.
  186. /// </summary>
  187. /// <param name="requestId">The unique identifier associated with a request.</param>
  188. /// <returns>The state of the request.</returns>
  189. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera
  190. /// image.</exception>
  191. /// <seealso cref="ConvertAsync(int, XRCameraImageConversionParams)"/>
  192. public virtual AsyncCameraImageConversionStatus GetAsyncRequestStatus(int requestId)
  193. {
  194. throw new NotSupportedException("camera image conversion is not supported by this implementation");
  195. }
  196. /// <summary>
  197. /// Method to be implemented by the provider to dispose an existing native image identified by
  198. /// <paramref name="nativeHandle"/>.
  199. /// </summary>
  200. /// <param name="nativeHandle">A unique identifier for this camera image.</param>
  201. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera
  202. /// image.</exception>
  203. /// <seealso cref="TryAcquireLatestImage"/>
  204. public virtual void DisposeImage(int nativeHandle)
  205. {
  206. throw new NotSupportedException("camera image conversion is not supported by this implementation");
  207. }
  208. /// <summary>
  209. /// Method to be implemented by the provider to dispose an existing async conversion request.
  210. /// </summary>
  211. /// <param name="requestId">A unique identifier for the request.</param>
  212. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera
  213. /// image.</exception>
  214. /// <seealso cref="ConvertAsync(int, XRCameraImageConversionParams)"/>
  215. public virtual void DisposeAsyncRequest(int requestId)
  216. {
  217. throw new NotSupportedException("camera image conversion is not supported by this implementation");
  218. }
  219. /// <summary>
  220. /// Method to be implemented by the provider to get information about an image plane from a native image
  221. /// handle by index.
  222. /// </summary>
  223. /// <param name="nativeHandle">A unique identifier for this camera image.</param>
  224. /// <param name="planeIndex">The index of the plane to get.</param>
  225. /// <param name="planeCinfo">The returned camera plane information if successful.</param>
  226. /// <returns>
  227. /// <c>true</c> if the image plane was acquired. Otherwise, <c>false</c>.
  228. /// </returns>
  229. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera
  230. /// image.</exception>
  231. /// <seealso cref="TryAcquireLatestImage"/>
  232. public virtual bool TryGetPlane(
  233. int nativeHandle,
  234. int planeIndex,
  235. out CameraImagePlaneCinfo planeCinfo)
  236. {
  237. throw new NotSupportedException("camera image conversion is not supported by this implementation");
  238. }
  239. /// <summary>
  240. /// Method to be implemented by the provider to determine whether a native image handle returned by
  241. /// <see cref="TryAcquireLatestImage"/> is currently valid. An image may become invalid if it has been
  242. /// disposed.
  243. /// </summary>
  244. /// <remarks>
  245. /// If a handle is valid, <see cref="TryConvert"/> and <see cref="TryGetConvertedDataSize"/> should not fail.
  246. /// </remarks>
  247. /// <param name="nativeHandle">A unique identifier for the camera image in question.</param>
  248. /// <returns><c>true</c>, if it is a valid handle. Otherwise, <c>false</c>.</returns>
  249. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera
  250. /// image.</exception>
  251. /// <seealso cref="DisposeImage"/>
  252. public virtual bool NativeHandleValid(
  253. int nativeHandle)
  254. {
  255. throw new NotSupportedException("camera image conversion is not supported by this implementation");
  256. }
  257. /// <summary>
  258. /// Method to be implemented by the provider to get the number of bytes required to store an image with the
  259. /// given dimensions and <c>TextureFormat</c>.
  260. /// </summary>
  261. /// <param name="nativeHandle">A unique identifier for the camera image to convert.</param>
  262. /// <param name="dimensions">The dimensions of the output image.</param>
  263. /// <param name="format">The <c>TextureFormat</c> for the image.</param>
  264. /// <param name="size">The number of bytes required to store the converted image.</param>
  265. /// <returns><c>true</c> if the output <paramref name="size"/> was set.</returns>
  266. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera
  267. /// image.</exception>
  268. public virtual bool TryGetConvertedDataSize(
  269. int nativeHandle,
  270. Vector2Int dimensions,
  271. TextureFormat format,
  272. out int size)
  273. {
  274. throw new NotSupportedException("camera image conversion is not supported by this implementation");
  275. }
  276. /// <summary>
  277. /// Method to be implemented by the provider to convert the image with handle
  278. /// <paramref name="nativeHandle"/> using the provided <paramref cref="conversionParams"/>.
  279. /// </summary>
  280. /// <param name="nativeHandle">A unique identifier for the camera image to convert.</param>
  281. /// <param name="conversionParams">The parameters to use during the conversion.</param>
  282. /// <param name="destinationBuffer">A buffer to write the converted image to.</param>
  283. /// <param name="bufferLength">The number of bytes available in the buffer.</param>
  284. /// <returns>
  285. /// <c>true</c> if the image was converted and stored in <paramref name="destinationBuffer"/>.
  286. /// </returns>
  287. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera
  288. /// image.</exception>
  289. public virtual bool TryConvert(
  290. int nativeHandle,
  291. XRCameraImageConversionParams conversionParams,
  292. IntPtr destinationBuffer,
  293. int bufferLength)
  294. {
  295. throw new NotSupportedException("camera image conversion is not supported by this implementation");
  296. }
  297. /// <summary>
  298. /// Method to be implemented by the provider to create an asynchronous request to convert a camera image,
  299. /// similar to <see cref="TryConvert"/> except the conversion should happen on a thread other than the
  300. /// calling (main) thread.
  301. /// </summary>
  302. /// <param name="nativeHandle">A unique identifier for the camera image to convert.</param>
  303. /// <param name="conversionParams">The parameters to use during the conversion.</param>
  304. /// <returns>A unique identifier for this request.</returns>
  305. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera
  306. /// image.</exception>
  307. public virtual int ConvertAsync(
  308. int nativeHandle,
  309. XRCameraImageConversionParams conversionParams)
  310. {
  311. throw new NotSupportedException("camera image conversion is not supported by this implementation");
  312. }
  313. /// <summary>
  314. /// Method to be implemented by the provider to get a pointer to the image data from a completed
  315. /// asynchronous request. This method should only succeed if <see cref="GetAsyncRequestStatus"/> returns
  316. /// <see cref="AsyncCameraImageConversionStatus.Ready"/>.
  317. /// </summary>
  318. /// <param name="requestId">The unique identifier associated with a request.</param>
  319. /// <param name="dataPtr">A pointer to the native buffer containing the data.</param>
  320. /// <param name="dataLength">The number of bytes in <paramref name="dataPtr"/>.</param>
  321. /// <returns><c>true</c> if <paramref name="dataPtr"/> and <paramref name="dataLength"/> were set and point
  322. /// to the image data.</returns>
  323. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera
  324. /// image.</exception>
  325. public virtual bool TryGetAsyncRequestData(int requestId, out IntPtr dataPtr, out int dataLength)
  326. {
  327. throw new NotSupportedException("camera image conversion is not supported by this implementation");
  328. }
  329. /// <summary>
  330. /// Method to be implemented by the provider to similar to
  331. /// <see cref="ConvertAsync(int, XRCameraImageConversionParams)"/> but takes a delegate to invoke when the
  332. /// request is complete, rather than returning a request id.
  333. /// </summary>
  334. /// <remarks>
  335. /// If the first parameter to <paramref name="callback"/> is
  336. /// <see cref="AsyncCameraImageConversionStatus.Ready"/> then the <c>dataPtr</c> parameter must be valid
  337. /// for the duration of the invocation. The data may be destroyed immediately upon return. The
  338. /// <paramref name="context"/> parameter must be passed back to the <paramref name="callback"/>.
  339. /// </remarks>
  340. /// <param name="nativeHandle">A unique identifier for the camera image to convert.</param>
  341. /// <param name="conversionParams">The parameters to use during the conversion.</param>
  342. /// <param name="callback">A delegate which must be invoked when the request is complete, whether the
  343. /// conversion was successfully or not.</param>
  344. /// <param name="context">A native pointer which must be passed back unaltered to
  345. /// <paramref name="callback"/>.</param>
  346. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera
  347. /// image.</exception>
  348. public virtual void ConvertAsync(
  349. int nativeHandle,
  350. XRCameraImageConversionParams conversionParams,
  351. OnImageRequestCompleteDelegate callback,
  352. IntPtr context)
  353. {
  354. throw new NotSupportedException("camera image conversion is not supported by this implementation");
  355. }
  356. /// <summary>
  357. /// Create the camera material from the given camera shader name.
  358. /// </summary>
  359. /// <param name="cameraShaderName">The name of the camera shader.</param>
  360. /// <returns>
  361. /// The created camera material shader.
  362. /// </returns>
  363. /// <exception cref="System.InvalidOperationException">Thrown if the shader cannot be found or if a
  364. /// material cannot be created for the shader.</exception>
  365. protected Material CreateCameraMaterial(string cameraShaderName)
  366. {
  367. var shader = Shader.Find(cameraShaderName);
  368. if (shader == null)
  369. {
  370. throw new InvalidOperationException($"Could not find shader named '{cameraShaderName}' required "
  371. + $"for video overlay on camera subsystem.");
  372. }
  373. Material material = new Material(shader);
  374. if (material == null)
  375. {
  376. throw new InvalidOperationException($"Could not create a material for shader named "
  377. + $"'{cameraShaderName}' required for video overlay on camera "
  378. + $"subsystem.");
  379. }
  380. return material;
  381. }
  382. }
  383. /// <summary>
  384. /// Get or set the focus mode for the camera.
  385. /// </summary>
  386. /// <value>
  387. /// The focus mode for the camera.
  388. /// </value>
  389. public CameraFocusMode focusMode
  390. {
  391. get => m_Provider.cameraFocusMode;
  392. set => m_Provider.cameraFocusMode = value;
  393. }
  394. /// <summary>
  395. /// Specifies the light estimation mode.
  396. /// </summary>
  397. /// <value>
  398. /// The light estimation mode.
  399. /// </value>
  400. public LightEstimationMode lightEstimationMode
  401. {
  402. get => m_LightEstimationMode;
  403. set
  404. {
  405. if ((m_LightEstimationMode != value) && m_Provider.TrySetLightEstimationMode(value))
  406. {
  407. m_LightEstimationMode = value;
  408. }
  409. }
  410. }
  411. LightEstimationMode m_LightEstimationMode = LightEstimationMode.Disabled;
  412. /// <summary>
  413. /// Start the camera subsystem.
  414. /// </summary>
  415. protected sealed override void OnStart() => m_Provider.Start();
  416. /// <summary>
  417. /// Stop the camera subsystem.
  418. /// </summary>
  419. protected sealed override void OnStop() => m_Provider.Stop();
  420. /// <summary>
  421. /// Destroy the camera subsystem.
  422. /// </summary>
  423. protected sealed override void OnDestroyed() => m_Provider.Destroy();
  424. /// <summary>
  425. /// Gets the <see cref="XRTextureDescriptor"/>s associated with the
  426. /// current frame. The caller owns the returned <c>NativeArray</c>
  427. /// and is responsible for calling <c>Dispose</c> on it.
  428. /// </summary>
  429. /// <returns>An array of texture descriptors.</returns>
  430. /// <param name="allocator">The allocator to use when creating
  431. /// the returned <c>NativeArray</c>.</param>
  432. public NativeArray<XRTextureDescriptor> GetTextureDescriptors(
  433. Allocator allocator)
  434. {
  435. return m_Provider.GetTextureDescriptors(
  436. default(XRTextureDescriptor),
  437. allocator);
  438. }
  439. /// <summary>
  440. /// Get the material used by <c>XRCameraSubsystem</c> to render the camera texture.
  441. /// </summary>
  442. /// <value>
  443. /// The material to render the camera texture.
  444. /// </value>
  445. public Material cameraMaterial => m_Provider.cameraMaterial;
  446. /// <summary>
  447. /// Returns the camera intrinsics information.
  448. /// </summary>
  449. /// <param name="cameraIntrinsics">The camera intrinsics information returned from the method.</param>
  450. /// <returns>
  451. /// <c>true</c> if the method successfully gets the camera intrinsics information. Otherwise, <c>false</c>.
  452. /// </returns>
  453. public bool TryGetIntrinsics(out XRCameraIntrinsics cameraIntrinsics)
  454. {
  455. return m_Provider.TryGetIntrinsics(out cameraIntrinsics);
  456. }
  457. /// <summary>
  458. /// Queries for the supported camera configurations.
  459. /// </summary>
  460. /// <param name="allocator">The allocation strategy to use for the returned data.</param>
  461. /// <returns>
  462. /// The supported camera configurations.
  463. /// </returns>
  464. public NativeArray<XRCameraConfiguration> GetConfigurations(Allocator allocator)
  465. {
  466. return m_Provider.GetConfigurations(default(XRCameraConfiguration), allocator);
  467. }
  468. /// <summary>
  469. /// The current camera configuration.
  470. /// </summary>
  471. /// <value>
  472. /// The current camera configuration if it exists. Otherise, <c>null</c>.
  473. /// </value>
  474. /// <exception cref="System.NotSupportedException">Thrown when setting the current configuration if the
  475. /// implementation does not support camera configurations.</exception>
  476. /// <exception cref="System.ArgumentNullException">Thrown when setting the current configuration if the given
  477. /// configuration is <c>null</c>.</exception>
  478. /// <exception cref="System.ArgumentException">Thrown when setting the current configuration if the given
  479. /// configuration is not a supported camera configuration.</exception>
  480. /// <exception cref="System.InvalidOperationException">Thrown when setting the current configuration if the
  481. /// implementation is unable to set the current camera configuration.</exception>
  482. public virtual XRCameraConfiguration? currentConfiguration
  483. {
  484. get => m_Provider.currentConfiguration;
  485. set
  486. {
  487. if (value == null)
  488. {
  489. throw new ArgumentNullException("value", "cannot set the camera configuration to null");
  490. }
  491. m_Provider.currentConfiguration = value;
  492. }
  493. }
  494. /// <summary>
  495. /// Whether to invert the culling mode during rendering. Some front-facing
  496. /// camera modes may require this.
  497. /// </summary>
  498. public bool invertCulling => m_Provider.invertCulling;
  499. /// <summary>
  500. /// Method for the implementation to create the camera functionality provider.
  501. /// </summary>
  502. /// <returns>
  503. /// The camera functionality provider.
  504. /// </returns>
  505. protected abstract Provider CreateProvider();
  506. /// <summary>
  507. /// Get the latest frame from the provider.
  508. /// </summary>
  509. /// <param name="cameraParams">The Unity <c>Camera</c> parameters.</param>
  510. /// <param name="frame">The camera frame to be populated if the subsystem is running and successfully provides
  511. /// the latest camera frame.</param>
  512. /// <returns>
  513. /// <c>true</c> if the camera frame is successfully returned. Otherwise, <c>false</c>.
  514. /// </returns>
  515. public bool TryGetLatestFrame(
  516. XRCameraParams cameraParams,
  517. out XRCameraFrame frame)
  518. {
  519. if (running && m_Provider.TryGetFrame(cameraParams, out frame))
  520. {
  521. return true;
  522. }
  523. frame = default(XRCameraFrame);
  524. return false;
  525. }
  526. /// <summary>
  527. /// Determines whether camera permission has been granted.
  528. /// </summary>
  529. /// <value>
  530. /// <c>true</c> if camera permission has been granted. Otherwise, <c>false</c>.
  531. /// </value>
  532. public bool permissionGranted => m_Provider.permissionGranted;
  533. /// <summary>
  534. /// Get the enabled and disabled shader keywords for the material.
  535. /// </summary>
  536. /// <param name="enabledKeywords">The keywords to enable for the material.</param>
  537. /// <param name="disabledKeywords">The keywords to disable for the material.</param>
  538. public void GetMaterialKeywords(out List<string> enabledKeywords, out List<string> disabledKeywords)
  539. => m_Provider.GetMaterialKeywords(out enabledKeywords, out disabledKeywords);
  540. /// <summary>
  541. /// Attempt to get the latest camera image. This provides directly access to the raw pixel data, as well as
  542. /// utilities to convert to RGB and Grayscale formats.
  543. /// </summary>
  544. /// <remarks>
  545. /// The returned <see cref="XRCameraImage"/> must be disposed to avoid resource leaks.
  546. /// </remarks>
  547. /// <param name="cameraImage">A valid <see cref="XRCameraImage"/> if this method returns <c>true</c>.</param>
  548. /// <returns>
  549. /// <c>true</c> if the image was acquired. Otherwise, <c>false</c>.
  550. /// </returns>
  551. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera image.
  552. /// </exception>
  553. public bool TryGetLatestImage(out XRCameraImage cameraImage)
  554. {
  555. CameraImageCinfo cameraImageCinfo;
  556. if (m_Provider.TryAcquireLatestImage(out cameraImageCinfo))
  557. {
  558. cameraImage = new XRCameraImage(this, cameraImageCinfo.nativeHandle, cameraImageCinfo.dimensions,
  559. cameraImageCinfo.planeCount, cameraImageCinfo.timestamp,
  560. cameraImageCinfo.format);
  561. return true;
  562. }
  563. else
  564. {
  565. cameraImage = default(XRCameraImage);
  566. return false;
  567. }
  568. }
  569. /// <summary>
  570. /// Registers a camera subsystem implementation based on the given subsystem parameters.
  571. /// </summary>
  572. /// <param name="cameraSubsystemParams">The parameters defining the camera subsystem functionality implemented
  573. /// by the subsystem provider.</param>
  574. /// <returns>
  575. /// <c>true</c> if the subsystem implementation is registered. Otherwise, <c>false</c>.
  576. /// </returns>
  577. /// <exception cref="System.ArgumentException">Thrown when the values specified in the
  578. /// <see cref="XRCameraSubsystemCinfo"/> parameter are invalid. Typically, this will occur
  579. /// <list type="bullet">
  580. /// <item>
  581. /// <description>if <see cref="XRCameraSubsystemCinfo.id"/> is <c>null</c> or empty</description>
  582. /// </item>
  583. /// <item>
  584. /// <description>if <see cref="XRCameraSubsystemCinfo.implementationType"/> is <c>null</c></description>
  585. /// </item>
  586. /// <item>
  587. /// <description>if <see cref="XRCameraSubsystemCinfo.implementationType"/> does not derive from the
  588. /// <see cref="XRCameraSubsystem"/> class
  589. /// </description>
  590. /// </item>
  591. /// </list>
  592. /// </exception>
  593. public static bool Register(XRCameraSubsystemCinfo cameraSubsystemParams)
  594. {
  595. XRCameraSubsystemDescriptor cameraSubsystemDescriptor = XRCameraSubsystemDescriptor.Create(cameraSubsystemParams);
  596. return SubsystemRegistration.CreateDescriptor(cameraSubsystemDescriptor);
  597. }
  598. /// <summary>
  599. /// Get the status of an existing asynchronous conversion request.
  600. /// </summary>
  601. /// <param name="requestId">The unique identifier associated with a request.</param>
  602. /// <returns>The state of the request.</returns>
  603. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera image.
  604. /// </exception>
  605. /// <seealso cref="ConvertAsync(int, XRCameraImageConversionParams)"/>
  606. internal AsyncCameraImageConversionStatus GetAsyncRequestStatus(int requestId)
  607. {
  608. return m_Provider.GetAsyncRequestStatus(requestId);
  609. }
  610. /// <summary>
  611. /// Dispose an existing native image identified by <paramref name="nativeHandle"/>.
  612. /// </summary>
  613. /// <param name="nativeHandle">A unique identifier for this camera image.</param>
  614. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera image.
  615. /// </exception>
  616. /// <seealso cref="Provider.TryAcquireLatestImage"/>
  617. internal void DisposeImage(int nativeHandle) => m_Provider.DisposeImage(nativeHandle);
  618. /// <summary>
  619. /// Dispose an existing async conversion request.
  620. /// </summary>
  621. /// <param name="requestId">A unique identifier for the request.</param>
  622. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera image.
  623. /// </exception>
  624. /// <seealso cref="Provider.ConvertAsync(int, XRCameraImageConversionParams)"/>
  625. internal void DisposeAsyncRequest(int requestId) => m_Provider.DisposeAsyncRequest(requestId);
  626. /// <summary>
  627. /// Attempt to get information about an image plane from a native image by index.
  628. /// </summary>
  629. /// <param name="nativeHandle">A unique identifier for this camera image.</param>
  630. /// <param name="planeIndex">The index of the plane to get.</param>
  631. /// <param name="planeCinfo">The returned camera plane information if successful.</param>
  632. /// <returns>
  633. /// <c>true</c> if the image plane is successfully acquired. Otherwise, <c>false</c>.
  634. /// </returns>
  635. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera image.
  636. /// </exception>
  637. /// <seealso cref="Provider.TryAcquireLatestImage"/>
  638. internal bool TryGetPlane(
  639. int nativeHandle,
  640. int planeIndex,
  641. out CameraImagePlaneCinfo planeCinfo)
  642. {
  643. return m_Provider.TryGetPlane(nativeHandle, planeIndex, out planeCinfo);
  644. }
  645. /// <summary>
  646. /// Determine whether a native image handle returned by <see cref="Provider.TryAcquireLatestImage"/> is
  647. /// currently valid. An image may become invalid if it has been disposed.
  648. /// </summary>
  649. /// <remarks>
  650. /// If a handle is valid, <see cref="TryConvert"/> and <see cref="TryGetConvertedDataSize"/> should not fail.
  651. /// </remarks>
  652. /// <param name="nativeHandle">A unique identifier for the camera image in question.</param>
  653. /// <returns><c>true</c> if it is a valid handle, <c>false</c> otherwise.</returns>
  654. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera image.
  655. /// </exception>
  656. /// <seealso cref="DisposeImage"/>
  657. internal bool NativeHandleValid(int nativeHandle) => m_Provider.NativeHandleValid(nativeHandle);
  658. /// <summary>
  659. /// Get the number of bytes required to store an image with the given dimensions and <c>TextureFormat</c>.
  660. /// </summary>
  661. /// <param name="nativeHandle">A unique identifier for the camera image to convert.</param>
  662. /// <param name="dimensions">The dimensions of the output image.</param>
  663. /// <param name="format">The <c>TextureFormat</c> for the image.</param>
  664. /// <param name="size">The number of bytes required to store the converted image.</param>
  665. /// <returns><c>true</c> if the output <paramref name="size"/> was set.</returns>
  666. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera image.
  667. /// </exception>
  668. internal bool TryGetConvertedDataSize(
  669. int nativeHandle,
  670. Vector2Int dimensions,
  671. TextureFormat format,
  672. out int size)
  673. {
  674. return m_Provider.TryGetConvertedDataSize(nativeHandle, dimensions, format, out size);
  675. }
  676. /// <summary>
  677. /// Convert the image with handle <paramref name="nativeHandle"/> using the provided
  678. /// <see cref="XRCameraImageConversionParams"/>.
  679. /// </summary>
  680. /// <param name="nativeHandle">A unique identifier for the camera image to convert.</param>
  681. /// <param name="conversionParams">The parameters to use during the conversion.</param>
  682. /// <param name="destinationBuffer">A buffer to write the converted image to.</param>
  683. /// <param name="bufferLength">The number of bytes available in the buffer.</param>
  684. /// <returns>
  685. /// <c>true</c> if the image was converted and stored in <paramref name="destinationBuffer"/>.
  686. /// </returns>
  687. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera image.
  688. /// </exception>
  689. internal bool TryConvert(
  690. int nativeHandle,
  691. XRCameraImageConversionParams conversionParams,
  692. IntPtr destinationBuffer,
  693. int bufferLength)
  694. {
  695. return m_Provider.TryConvert(nativeHandle, conversionParams, destinationBuffer, bufferLength);
  696. }
  697. /// <summary>
  698. /// Create an asynchronous request to convert a camera image, similar to <see cref="TryConvert"/> except the
  699. /// conversion should happen on a thread other than the calling (main) thread.
  700. /// </summary>
  701. /// <param name="nativeHandle">A unique identifier for the camera image to convert.</param>
  702. /// <param name="conversionParams">The parameters to use during the conversion.</param>
  703. /// <returns>A unique identifier for this request.</returns>
  704. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera image.
  705. /// </exception>
  706. internal int ConvertAsync(
  707. int nativeHandle,
  708. XRCameraImageConversionParams conversionParams)
  709. {
  710. return m_Provider.ConvertAsync(nativeHandle, conversionParams);
  711. }
  712. /// <summary>
  713. /// Get a pointer to the image data from a completed asynchronous request. This method should only succeed if
  714. /// <see cref="GetAsyncRequestStatus"/> returns <see cref="AsyncCameraImageConversionStatus.Ready"/>.
  715. /// </summary>
  716. /// <param name="requestId">The unique identifier associated with a request.</param>
  717. /// <param name="dataPtr">A pointer to the native buffer containing the data.</param>
  718. /// <param name="dataLength">The number of bytes in <paramref name="dataPtr"/>.</param>
  719. /// <returns><c>true</c> if <paramref name="dataPtr"/> and <paramref name="dataLength"/> were set and point to
  720. /// the image data.</returns>
  721. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera image.
  722. /// </exception>
  723. internal bool TryGetAsyncRequestData(int requestId, out IntPtr dataPtr, out int dataLength)
  724. {
  725. return m_Provider.TryGetAsyncRequestData(requestId, out dataPtr, out dataLength);
  726. }
  727. /// <summary>
  728. /// Callback from native code for when the asychronous conversion is complete.
  729. /// </summary>
  730. /// <param name="status">The status of the conversion operation.</param>
  731. /// <param name="conversionParams">The parameters for the conversion.</param>
  732. /// <param name="dataPtr">The native pointer to the converted data.</param>
  733. /// <param name="dataLength">The memory size of the converted data.</param>
  734. /// <param name="context">The native context for the conversion operation.</param>
  735. protected internal delegate void OnImageRequestCompleteDelegate(
  736. AsyncCameraImageConversionStatus status,
  737. XRCameraImageConversionParams conversionParams,
  738. IntPtr dataPtr,
  739. int dataLength,
  740. IntPtr context);
  741. /// <summary>
  742. /// Similar to <see cref="ConvertAsync(int, XRCameraImageConversionParams)"/> but takes a delegate to invoke
  743. /// when the request is complete, rather than returning a request id.
  744. /// </summary>
  745. /// <remarks>
  746. /// If the first parameter to <paramref name="callback"/> is
  747. /// <see cref="AsyncCameraImageConversionStatus.Ready"/> then the <c>dataPtr</c> parameter must be valid for
  748. /// the duration of the invocation. The data may be destroyed immediately upon return. The
  749. /// <paramref name="context"/> parameter must be passed back to the <paramref name="callback"/>.
  750. /// </remarks>
  751. /// <param name="nativeHandle">A unique identifier for the camera image to convert.</param>
  752. /// <param name="conversionParams">The parameters to use during the conversion.</param>
  753. /// <param name="callback">A delegate which must be invoked when the request is complete, whether the
  754. /// conversion was successfully or not.</param>
  755. /// <param name="context">A native pointer which must be passed back unaltered to <paramref name="callback"/>.
  756. /// </param>
  757. /// <exception cref="System.NotSupportedException">Thrown if the implementation does not support camera image.
  758. /// </exception>
  759. internal void ConvertAsync(
  760. int nativeHandle,
  761. XRCameraImageConversionParams conversionParams,
  762. OnImageRequestCompleteDelegate callback,
  763. IntPtr context)
  764. {
  765. m_Provider.ConvertAsync(nativeHandle, conversionParams, callback, context);
  766. }
  767. /// <summary>
  768. /// Container for native camera image construction metadata.
  769. /// </summary>
  770. protected struct CameraImageCinfo : IEquatable<CameraImageCinfo>
  771. {
  772. /// <summary>
  773. /// The handle representing the camera image on the native level.
  774. /// </summary>
  775. /// <value>
  776. /// The handle representing the camera image on the native level.
  777. /// </value>
  778. public int nativeHandle => m_NativeHandle;
  779. int m_NativeHandle;
  780. /// <summary>
  781. /// The dimensions of the camera image.
  782. /// </summary>
  783. /// <value>
  784. /// The dimensions of the camera image.
  785. /// </value>
  786. public Vector2Int dimensions => m_Dimensions;
  787. Vector2Int m_Dimensions;
  788. /// <summary>
  789. /// The number of video planes in the camera image.
  790. /// </summary>
  791. /// <value>
  792. /// The number of video planes in the camera image.
  793. /// </value>
  794. public int planeCount => m_PlaneCount;
  795. int m_PlaneCount;
  796. /// <summary>
  797. /// The timestamp for when the camera image was captured.
  798. /// </summary>
  799. /// <value>
  800. /// The timestamp for when the camera image was captured.
  801. /// </value>
  802. public double timestamp => m_Timestamp;
  803. double m_Timestamp;
  804. /// <summary>
  805. /// The format of the camera image.
  806. /// </summary>
  807. /// <value>
  808. /// The format of the camera image.
  809. /// </value>
  810. public CameraImageFormat format => m_Format;
  811. CameraImageFormat m_Format;
  812. /// <summary>
  813. /// Constructs the camera image cinfo.
  814. /// </summary>
  815. /// <param name="nativeHandle">The handle representing the camera image on the native level.</param>
  816. /// <param name="dimensions">The dimensions of the camera image.</param>
  817. /// <param name="planeCount">The number of video planes in the camera image.</param>
  818. /// <param name="timestamp">The timestamp for when the camera image was captured.</param>
  819. /// <param name="format">The format of the camera image.</param>
  820. public CameraImageCinfo(int nativeHandle, Vector2Int dimensions, int planeCount, double timestamp,
  821. CameraImageFormat format)
  822. {
  823. this.m_NativeHandle = nativeHandle;
  824. this.m_Dimensions = dimensions;
  825. this.m_PlaneCount = planeCount;
  826. this.m_Timestamp = timestamp;
  827. this.m_Format = format;
  828. }
  829. public bool Equals(CameraImageCinfo other)
  830. {
  831. return (nativeHandle.Equals(other.nativeHandle) && dimensions.Equals(other.dimensions)
  832. && planeCount.Equals(other.planeCount) && timestamp.Equals(other.timestamp)
  833. && format.Equals(other.format));
  834. }
  835. public override bool Equals(System.Object obj)
  836. {
  837. return ReferenceEquals(this, obj) || ((obj is CameraImageCinfo) && Equals((CameraImageCinfo)obj));
  838. }
  839. public static bool operator ==(CameraImageCinfo lhs, CameraImageCinfo rhs) => lhs.Equals(rhs);
  840. public static bool operator !=(CameraImageCinfo lhs, CameraImageCinfo rhs) => !(lhs == rhs);
  841. public override int GetHashCode()
  842. {
  843. int hashCode = 486187739;
  844. unchecked
  845. {
  846. hashCode = (hashCode * 486187739) + nativeHandle.GetHashCode();
  847. hashCode = (hashCode * 486187739) + dimensions.GetHashCode();
  848. hashCode = (hashCode * 486187739) + planeCount.GetHashCode();
  849. hashCode = (hashCode * 486187739) + timestamp.GetHashCode();
  850. hashCode = (hashCode * 486187739) + ((int)format).GetHashCode();
  851. }
  852. return hashCode;
  853. }
  854. public override string ToString()
  855. {
  856. return string.Format("nativeHandle: {0} dimensions:{1} planes:{2} timestamp:{3} format:{4}",
  857. nativeHandle.ToString(), dimensions.ToString(), planeCount.ToString(),
  858. timestamp.ToString(), format.ToString());
  859. }
  860. }
  861. /// <summary>
  862. /// Container for the metadata describing access to the raw camera image plane data.
  863. /// </summary>
  864. protected internal struct CameraImagePlaneCinfo : IEquatable<CameraImagePlaneCinfo>
  865. {
  866. /// <summary>
  867. /// The pointer to the raw native image data.
  868. /// </summary>
  869. /// <value>
  870. /// The pointer to the raw native image data.
  871. /// </value>
  872. public IntPtr dataPtr => m_DataPtr;
  873. IntPtr m_DataPtr;
  874. /// <summary>
  875. /// The length of the native image data.
  876. /// </summary>
  877. /// <value>
  878. /// The length of the native image data.
  879. /// </value>
  880. public int dataLength => m_DataLength;
  881. int m_DataLength;
  882. /// <summary>
  883. /// The stride for iterating through the rows of the native image data.
  884. /// </summary>
  885. /// <value>
  886. /// The stride for iterating through the rows of the native image data.
  887. /// </value>
  888. public int rowStride => m_RowStride;
  889. int m_RowStride;
  890. /// <summary>
  891. /// The stride for iterating through the pixels of the native image data.
  892. /// </summary>
  893. /// <value>
  894. /// The stride for iterating through the pixels of the native image data.
  895. /// </value>
  896. public int pixelStride => m_PixelStride;
  897. int m_PixelStride;
  898. /// <summary>
  899. /// Constructs the camera image plane cinfo.
  900. /// </summary>
  901. /// <param name="dataPtr">The pointer to the raw native image data.</param>
  902. /// <param name="dataLength">The length of the native image data.</param>
  903. /// <param name="rowStride">The stride for iterating through the rows of the native image data.</param>
  904. /// <param name="pixelStride">The stride for iterating through the pixels of the native image data.</param>
  905. public CameraImagePlaneCinfo(IntPtr dataPtr, int dataLength, int rowStride, int pixelStride)
  906. {
  907. this.m_DataPtr = dataPtr;
  908. this.m_DataLength = dataLength;
  909. this.m_RowStride = rowStride;
  910. this.m_PixelStride = pixelStride;
  911. }
  912. public bool Equals(CameraImagePlaneCinfo other)
  913. {
  914. return (dataPtr.Equals(other.dataPtr) && dataLength.Equals(other.dataLength)
  915. && rowStride.Equals(other.rowStride) && pixelStride.Equals(other.pixelStride));
  916. }
  917. public override bool Equals(System.Object obj)
  918. {
  919. return ReferenceEquals(this, obj) || ((obj is CameraImagePlaneCinfo) && Equals((CameraImagePlaneCinfo)obj));
  920. }
  921. public static bool operator ==(CameraImagePlaneCinfo lhs, CameraImagePlaneCinfo rhs) => lhs.Equals(rhs);
  922. public static bool operator !=(CameraImagePlaneCinfo lhs, CameraImagePlaneCinfo rhs) => !(lhs == rhs);
  923. public override int GetHashCode()
  924. {
  925. int hashCode = 486187739;
  926. unchecked
  927. {
  928. hashCode = (hashCode * 486187739) + dataPtr.GetHashCode();
  929. hashCode = (hashCode * 486187739) + dataLength.GetHashCode();
  930. hashCode = (hashCode * 486187739) + rowStride.GetHashCode();
  931. hashCode = (hashCode * 486187739) + pixelStride.GetHashCode();
  932. }
  933. return hashCode;
  934. }
  935. public override string ToString()
  936. {
  937. return string.Format("dataPtr: {0} length:{1} rowStride:{2} pixelStride:{3}", dataPtr.ToString(),
  938. dataLength.ToString(), rowStride.ToString(), pixelStride.ToString());
  939. }
  940. }
  941. }
  942. }