web_xr_presentation_state.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef DEVICE_VR_ANDROID_WEB_XR_PRESENTATION_STATE_H_
  5. #define DEVICE_VR_ANDROID_WEB_XR_PRESENTATION_STATE_H_
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include "base/callback.h"
  10. #include "base/containers/queue.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "base/time/time.h"
  14. #include "components/viz/common/resources/resource_id.h"
  15. #include "gpu/command_buffer/common/mailbox_holder.h"
  16. #include "ui/gfx/geometry/rect_f.h"
  17. #include "ui/gfx/geometry/size.h"
  18. #include "ui/gfx/geometry/transform.h"
  19. namespace gl {
  20. class GLFence;
  21. class GLImageEGL;
  22. } // namespace gl
  23. namespace gpu {
  24. class GpuMemoryBufferImplAndroidHardwareBuffer;
  25. } // namespace gpu
  26. namespace viz {
  27. struct BeginFrameArgs;
  28. } // namespace viz
  29. namespace device {
  30. // When composited by the browser process, WebXR frames go through a three-stage
  31. // pipeline: Animating, Processing, and Rendering. There's also an Idle state
  32. // used as the starting state before Animating and ending state after Rendering.
  33. //
  34. // The stages can overlap, but we enforce that there isn't more than one
  35. // frame in a given non-Idle state at any one time.
  36. //
  37. // <- GetFrameData
  38. // Idle
  39. // SendVSync
  40. // Animating
  41. // <- UpdateLayerBounds (optional)
  42. // <- GetFrameData
  43. // <- SubmitFrame
  44. // ProcessOrDefer
  45. // Processing
  46. // <- OnWebVrFrameAvailable
  47. // DrawFrame
  48. // DrawFrameSubmitWhenReady
  49. // <= poll prev_frame_completion_fence_
  50. // DrawFrameSubmitNow
  51. // Rendering
  52. // <= prev_frame_completion_fence_ signals
  53. // DrawFrameSubmitNow (of next frame)
  54. // Idle
  55. //
  56. // Note that the frame is considered to still be in "Animating" state until
  57. // ProcessOrDefer is called. If the current processing frame isn't done yet
  58. // at the time the incoming SubmitFrame arrives, we defer Processing the frame
  59. // until that finishes.
  60. //
  61. // The renderer may call SubmitFrameMissing instead of SubmitFrame. In that
  62. // case, the frame transitions from Animating back to Idle.
  63. //
  64. // <- GetFrameData
  65. // Idle
  66. // SendVSync
  67. // Animating
  68. // <- UpdateLayerBounds (optional)
  69. // <- GetFrameData
  70. // <- SubmitFrameMissing
  71. // Idle
  72. //
  73. //
  74. // When compositing is managed by Viz, the frames go through much the same
  75. // three-stage pipeline, but there are a few noteworthy differences:
  76. // * An "Animating" frame cannot be processed until it's BeginFrameArgs have
  77. // been set.
  78. // * Processing will generally happen synchronously, as most sync points are
  79. // passed on to be used in the Viz Compositor.
  80. // * More than one frame may be in the "Rendering" state; and Frames should
  81. // be transitioned to "Rendering" when they are handed off to the viz
  82. // Compositor. When the Compositor is no longer using the resources
  83. // associated with the frame, it can then be transitioned back to Idle.
  84. struct WebXrSharedBuffer {
  85. WebXrSharedBuffer();
  86. ~WebXrSharedBuffer();
  87. gfx::Size size = {0, 0};
  88. // Shared GpuMemoryBuffer
  89. std::unique_ptr<gpu::GpuMemoryBufferImplAndroidHardwareBuffer> gmb;
  90. // Resources in the remote GPU process command buffer context
  91. gpu::MailboxHolder mailbox_holder;
  92. // Resources in the local GL context
  93. uint32_t local_texture = 0;
  94. // This refptr keeps the image alive while processing a frame. That's
  95. // required because it owns underlying resources, and must still be
  96. // alive when the mailbox texture backed by this image is used.
  97. scoped_refptr<gl::GLImageEGL> local_glimage;
  98. // The ResourceId that was used to pass this buffer to the Viz Compositor.
  99. // Id should be set to kInvalidResourceId when it is not in use by the viz
  100. // compositor (either because the buffer was not passed to it, or because the
  101. // compositor has told us it is okay to reclaim the resource).
  102. viz::ResourceId id = viz::kInvalidResourceId;
  103. };
  104. struct WebXrFrame {
  105. WebXrFrame();
  106. WebXrFrame(const WebXrFrame&) = delete;
  107. WebXrFrame& operator=(const WebXrFrame&) = delete;
  108. ~WebXrFrame();
  109. bool IsValid() const;
  110. void Recycle();
  111. // If true, this frame cannot change state until unlocked. Used to mark
  112. // processing frames for the critical stage from drawing to Surface until
  113. // they arrive in OnWebVRFrameAvailable. See also recycle_once_unlocked.
  114. bool state_locked = false;
  115. // Start of elements that need to be reset on Recycle
  116. int16_t index = -1;
  117. // Set on an animating frame if it is waiting for being able to transition
  118. // to processing state.
  119. base::OnceClosure deferred_start_processing;
  120. // Set if a frame recycle failed due to being locked. The client should check
  121. // this after unlocking it and retry recycling it at that time.
  122. bool recycle_once_unlocked = false;
  123. std::unique_ptr<gl::GLFence> gvr_handoff_fence;
  124. std::unique_ptr<gl::GLFence> render_completion_fence;
  125. std::unique_ptr<viz::BeginFrameArgs> begin_frame_args;
  126. std::vector<gpu::SyncToken> reclaimed_sync_tokens;
  127. // End of elements that need to be reset on Recycle
  128. base::TimeTicks time_pose;
  129. base::TimeTicks time_js_submit;
  130. base::TimeTicks time_copied;
  131. gfx::Transform head_pose;
  132. // In SharedBuffer mode, keep a swap chain.
  133. std::unique_ptr<WebXrSharedBuffer> shared_buffer;
  134. std::unique_ptr<WebXrSharedBuffer> camera_image_shared_buffer;
  135. // Viewport bounds used for rendering, in texture coordinates with uv=(0, 1)
  136. // corresponding to viewport pixel (0, 0) as set by UpdateLayerBounds.
  137. //
  138. // Currently this is only used by the ARCore handheld AR mode which is
  139. // monoscopic and uses the left viewport. TODO(https://crbug.com/1134203): The
  140. // GVR device currently has its own separate bounds tracking implementation.
  141. // That should be updated to use this implementation, at that time a matching
  142. // bounds_right would need to be added.
  143. gfx::RectF bounds_left;
  144. };
  145. class WebXrPresentationState {
  146. public:
  147. enum class StateMachineType {
  148. kBrowserComposited,
  149. kVizComposited,
  150. };
  151. // WebXR frames use an arbitrary sequential ID to help catch logic errors
  152. // involving out-of-order frames. We use an 8-bit unsigned counter, wrapping
  153. // from 255 back to 0. Elsewhere we use -1 to indicate a non-WebXR frame, so
  154. // most internal APIs use int16_t to ensure that they can store a full
  155. // -1..255 value range.
  156. using FrameIndexType = uint8_t;
  157. // We have at most one frame animating, one frame being processed,
  158. // and one frame tracked after submission to GVR.
  159. static constexpr int kWebXrFrameCount = 3;
  160. WebXrPresentationState();
  161. WebXrPresentationState(const WebXrPresentationState&) = delete;
  162. WebXrPresentationState& operator=(const WebXrPresentationState&) = delete;
  163. ~WebXrPresentationState();
  164. void SetStateMachineType(StateMachineType type);
  165. // State transitions for normal flow
  166. bool CanStartFrameAnimating();
  167. FrameIndexType StartFrameAnimating();
  168. void TransitionFrameAnimatingToProcessing();
  169. void TransitionFrameProcessingToRendering();
  170. void EndFrameRendering(WebXrFrame* frame);
  171. void EndFrameRendering();
  172. // Shuts down a presentation session. This will recycle any
  173. // animating or rendering frame. A processing frame cannot be
  174. // recycled if its state is locked, it will be recycled later
  175. // once the state unlocks.
  176. void EndPresentation();
  177. // Variant transitions, if Renderer didn't call SubmitFrame,
  178. // or if we want to discard an unwanted incoming frame.
  179. void RecycleUnusedAnimatingFrame();
  180. bool RecycleProcessingFrameIfPossible();
  181. void ProcessOrDefer(base::OnceClosure callback);
  182. // Call this after state changes that could result in CanProcessFrame
  183. // becoming true.
  184. void TryDeferredProcessing();
  185. bool HaveAnimatingFrame() const { return animating_frame_; }
  186. WebXrFrame* GetAnimatingFrame() const;
  187. bool HaveProcessingFrame() const { return processing_frame_; }
  188. WebXrFrame* GetProcessingFrame() const;
  189. bool HaveRenderingFrame() const { return rendering_frame_; }
  190. WebXrFrame* GetRenderingFrame() const;
  191. bool mailbox_bridge_ready() { return mailbox_bridge_ready_; }
  192. void NotifyMailboxBridgeReady() { mailbox_bridge_ready_ = true; }
  193. // The index of the expected next animating frame, intended for logging
  194. // purposes only. Does not consume or modify the index value.
  195. FrameIndexType PeekNextFrameIndex() const { return next_frame_index_; }
  196. // Extracts the shared buffers from all frames, resetting said frames to an
  197. // invalid state.
  198. // This is intended for resource cleanup, after EndPresentation was called.
  199. std::vector<std::unique_ptr<WebXrSharedBuffer>> TakeSharedBuffers();
  200. // Used by WebVrCanAnimateFrame() to detect when ui_->CanSendWebVrVSync()
  201. // transitions from false to true, as part of starting the incoming frame
  202. // timeout.
  203. bool last_ui_allows_sending_vsync = false;
  204. // GpuMemoryBuffer creation needs a buffer ID. We don't really care about
  205. // this, but try to keep it unique to avoid confusion.
  206. int next_memory_buffer_id = 0;
  207. private:
  208. // Checks if we're in a valid state for processing the current animating
  209. // frame. Invalid states include mailbox_bridge_ready_ being false, or an
  210. // already existing processing frame that's not done yet.
  211. bool CanProcessFrame() const;
  212. std::string DebugState() const;
  213. std::unique_ptr<WebXrFrame> frames_storage_[kWebXrFrameCount];
  214. // Index of the next animating WebXR frame.
  215. FrameIndexType next_frame_index_ = 0;
  216. StateMachineType state_machine_type_ = StateMachineType::kBrowserComposited;
  217. raw_ptr<WebXrFrame> animating_frame_ = nullptr;
  218. raw_ptr<WebXrFrame> processing_frame_ = nullptr;
  219. raw_ptr<WebXrFrame> rendering_frame_ = nullptr;
  220. std::vector<WebXrFrame*> rendering_frames_;
  221. base::queue<WebXrFrame*> idle_frames_;
  222. bool mailbox_bridge_ready_ = false;
  223. };
  224. } // namespace device
  225. #endif // DEVICE_VR_ANDROID_WEB_XR_PRESENTATION_STATE_H_