1 // Copyright 2019 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 #include "device/vr/windows_mixed_reality/wrappers/wmr_holographic_space.h"
5 
6 #include <Windows.Graphics.DirectX.Direct3D11.interop.h>
7 #include <windows.graphics.holographic.h>
8 #include <wrl.h>
9 
10 #include <vector>
11 
12 #include "base/logging.h"
13 #include "base/strings/string_util.h"
14 #include "base/win/core_winrt_util.h"
15 #include "base/win/scoped_hstring.h"
16 #include "device/vr/windows_mixed_reality/mixed_reality_statics.h"
17 #include "device/vr/windows_mixed_reality/wrappers/test/mock_wmr_holographic_frame.h"
18 #include "device/vr/windows_mixed_reality/wrappers/test/mock_wmr_holographic_space.h"
19 #include "device/vr/windows_mixed_reality/wrappers/wmr_holographic_frame.h"
20 
21 using ABI::Windows::Foundation::ITypedEventHandler;
22 using ABI::Windows::Graphics::DirectX::Direct3D11::IDirect3DDevice;
23 using ABI::Windows::Graphics::Holographic::HolographicAdapterId;
24 using ABI::Windows::Graphics::Holographic::HolographicSpace;
25 using HolographicSpaceUserPresence =
26     ABI::Windows::Graphics::Holographic::HolographicSpaceUserPresence;
27 using ABI::Windows::Graphics::Holographic::IHolographicFrame;
28 using ABI::Windows::Graphics::Holographic::IHolographicSpace;
29 using ABI::Windows::Graphics::Holographic::IHolographicSpace2;
30 using Microsoft::WRL::Callback;
31 using Microsoft::WRL::ComPtr;
32 
33 typedef ITypedEventHandler<HolographicSpace*, IInspectable*>
34     HolographicSpaceEventHandler;
35 
36 namespace device {
37 
WMRHolographicSpaceImpl(ComPtr<IHolographicSpace> space)38 WMRHolographicSpaceImpl::WMRHolographicSpaceImpl(
39     ComPtr<IHolographicSpace> space)
40     : space_(space) {
41   DCHECK(space_);
42   HRESULT hr = space_.As(&space2_);
43   if (SUCCEEDED(hr)) {
44     SubscribeEvents();
45   }
46 }
47 
~WMRHolographicSpaceImpl()48 WMRHolographicSpaceImpl::~WMRHolographicSpaceImpl() {
49   UnsubscribeEvents();
50 }
51 
PrimaryAdapterId()52 HolographicAdapterId WMRHolographicSpaceImpl::PrimaryAdapterId() {
53   HolographicAdapterId id;
54   HRESULT hr = space_->get_PrimaryAdapterId(&id);
55   DCHECK(SUCCEEDED(hr));
56   return id;
57 }
58 
59 std::unique_ptr<WMRHolographicFrame>
TryCreateNextFrame()60 WMRHolographicSpaceImpl::TryCreateNextFrame() {
61   ComPtr<IHolographicFrame> frame;
62   HRESULT hr = space_->CreateNextFrame(&frame);
63   if (FAILED(hr))
64     return nullptr;
65   return std::make_unique<WMRHolographicFrameImpl>(frame);
66 }
67 
TrySetDirect3D11Device(const ComPtr<IDirect3DDevice> & device)68 bool WMRHolographicSpaceImpl::TrySetDirect3D11Device(
69     const ComPtr<IDirect3DDevice>& device) {
70   HRESULT hr = space_->SetDirect3D11Device(device.Get());
71   return SUCCEEDED(hr);
72 }
73 
UserPresence()74 HolographicSpaceUserPresence WMRHolographicSpaceImpl::UserPresence() {
75   HolographicSpaceUserPresence user_presence =
76       HolographicSpaceUserPresence::HolographicSpaceUserPresence_PresentActive;
77   if (space2_) {
78     HRESULT hr = space2_->get_UserPresence(&user_presence);
79     DCHECK(SUCCEEDED(hr));
80   }
81   return user_presence;
82 }
83 
84 std::unique_ptr<base::CallbackList<void()>::Subscription>
AddUserPresenceChangedCallback(const base::RepeatingCallback<void ()> & cb)85 WMRHolographicSpaceImpl::AddUserPresenceChangedCallback(
86     const base::RepeatingCallback<void()>& cb) {
87   return user_presence_changed_callback_list_.Add(cb);
88 }
89 
OnUserPresenceChanged(IHolographicSpace *,IInspectable *)90 HRESULT WMRHolographicSpaceImpl::OnUserPresenceChanged(IHolographicSpace*,
91                                                        IInspectable*) {
92   user_presence_changed_callback_list_.Notify();
93   return S_OK;
94 }
95 
SubscribeEvents()96 void WMRHolographicSpaceImpl::SubscribeEvents() {
97   if (!space2_) {
98     return;
99   }
100   // The destructor ensures that we're unsubscribed so raw this is fine.
101   auto user_presence_changed_callback = Callback<HolographicSpaceEventHandler>(
102       this, &WMRHolographicSpaceImpl::OnUserPresenceChanged);
103   HRESULT hr = space2_->add_UserPresenceChanged(
104       user_presence_changed_callback.Get(), &user_presence_changed_token_);
105   DCHECK(SUCCEEDED(hr));
106 }
107 
UnsubscribeEvents()108 void WMRHolographicSpaceImpl::UnsubscribeEvents() {
109   if (!space2_) {
110     return;
111   }
112 
113   HRESULT hr = S_OK;
114   if (user_presence_changed_token_.value != 0) {
115     hr = space2_->remove_UserPresenceChanged(user_presence_changed_token_);
116     user_presence_changed_token_.value = 0;
117     DCHECK(SUCCEEDED(hr));
118   }
119 }
120 
121 }  // namespace device
122