Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: chrome/browser/android/vr_shell/vr_shell.cc

Issue 2301633002: Refactor Vr activity into ChromeTabbedActivity. (Closed)
Patch Set: UiElements are now structs Created 4 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/android/vr_shell/vr_shell.h" 5 #include "chrome/browser/android/vr_shell/vr_shell.h"
6 6
7 #include <thread>
8
7 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h" 9 #include "chrome/browser/android/vr_shell/vr_shell_renderer.h"
8 #include "chrome/browser/android/vr_shell/vr_util.h" 10 #include "chrome/browser/android/vr_shell/vr_util.h"
9 #include "jni/VrShell_jni.h" 11 #include "jni/VrShell_jni.h"
10 #include "ui/gl/gl_bindings.h" 12 #include "ui/gl/gl_bindings.h"
11 #include "ui/gl/init/gl_factory.h" 13 #include "ui/gl/init/gl_factory.h"
12 14
13 namespace vr_shell { 15 using base::android::JavaParamRef;
14 16
15 namespace { 17 namespace {
16 // Constant taken from treasure_hunt demo. 18 // Constant taken from treasure_hunt demo.
17 const long kPredictionTimeWithoutVsyncNanos = 50000000; 19 static constexpr long kPredictionTimeWithoutVsyncNanos = 50000000;
18 20
19 const float kZNear = 0.1f; 21 static constexpr float kZNear = 0.1f;
20 const float kZFar = 1000.0f; 22 static constexpr float kZFar = 1000.0f;
21 23
22 // Content rect in world coordinates. Height and width are currently supplied 24 static constexpr gvr::Vec3f kDesktopPositionDefault = {0.0f, 0.0f, -2.0f};
23 // as DrawFrame arguments. 25 static constexpr float kDesktopHeightDefault = 1.6f;
24 const gvr::Vec3f kContentRectPositionDefault = {0.0f, 0.0f, -1.0f};
25 26
27 // Screen angle in degrees. 0 = vertical, positive = top closer.
28 static constexpr float kDesktopScreenTiltDefault = 0;
29
30 static constexpr float kScreenHeightMeters = 2.0f;
31 static constexpr float kScreenWidthMeters = 2.0f;
26 } // namespace 32 } // namespace
27 33
28 ContentRect::ContentRect() { 34 namespace vr_shell {
29 SetIdentity(); 35
36 VrShell::VrShell(JNIEnv* env, jobject obj)
37 : desktop_screen_tilt_(kDesktopScreenTiltDefault),
38 desktop_height_(kDesktopHeightDefault),
39 desktop_position_(kDesktopPositionDefault) {
40 j_vr_shell_.Reset(env, obj);
41 ui_rects_.emplace_back(new ContentRectangle());
42 desktop_plane_ = ui_rects_.back().get();
43 desktop_plane_->id = 0;
44 desktop_plane_->copy_rect = {0.0f, 0.0f, 1.0f, 1.0f};
45 // TODO(cjgrant): If we use the native path for content clicks, fix this.
46 desktop_plane_->window_rect = {0, 0, 0, 0};
47 desktop_plane_->translation = {0.0f, 0.0f, 0.0f};
48 desktop_plane_->x_anchoring = XNONE;
49 desktop_plane_->y_anchoring = YNONE;
50 desktop_plane_->anchor_z = false;
51 desktop_plane_->orientation_axis_angle = {{1.0f, 0.0f, 0.0f, 0.0f}};
52 desktop_plane_->rotation_axis_angle = {{0.0f, 0.0f, 0.0f, 0.0f}};
30 } 53 }
31 54
32 ContentRect::~ContentRect() {} 55 void VrShell::Destroy(JNIEnv* env, const JavaParamRef<jobject>& obj) {
33
34 void ContentRect::SetIdentity() {
35 transfrom_to_world.m[0][0] = 1;
36 transfrom_to_world.m[0][1] = 0;
37 transfrom_to_world.m[0][2] = 0;
38 transfrom_to_world.m[0][3] = 0;
39 transfrom_to_world.m[1][0] = 0;
40 transfrom_to_world.m[1][1] = 1;
41 transfrom_to_world.m[1][2] = 0;
42 transfrom_to_world.m[1][3] = 0;
43 transfrom_to_world.m[2][0] = 0;
44 transfrom_to_world.m[2][1] = 0;
45 transfrom_to_world.m[2][2] = 1;
46 transfrom_to_world.m[2][3] = 0;
47 transfrom_to_world.m[3][0] = 0;
48 transfrom_to_world.m[3][1] = 0;
49 transfrom_to_world.m[3][2] = 0;
50 transfrom_to_world.m[3][3] = 1;
51 }
52
53 void ContentRect::Translate(float x, float y, float z) {
54 transfrom_to_world.m[0][3] += x;
55 transfrom_to_world.m[1][3] += y;
56 transfrom_to_world.m[2][3] += z;
57 }
58
59 VrShell::VrShell(JNIEnv* env, jobject obj) :
60 webvr_mode_(false) {
61 j_vr_shell_.Reset(env, obj);
62 }
63
64 void VrShell::Destroy(JNIEnv* env,
65 const base::android::JavaParamRef<jobject>& obj) {
66 delete this; 56 delete this;
57 gl::init::ClearGLBindings();
67 } 58 }
68 59
69 bool RegisterVrShell(JNIEnv* env) { 60 bool RegisterVrShell(JNIEnv* env) {
70 return RegisterNativesImpl(env); 61 return RegisterNativesImpl(env);
71 } 62 }
72 63
73 VrShell::~VrShell() { 64 VrShell::~VrShell() {
74 device::GvrDelegateManager::GetInstance()->Shutdown(); 65 device::GvrDelegateManager::GetInstance()->Shutdown();
75 } 66 }
76 67
77 void VrShell::GvrInit(JNIEnv* env, 68 void VrShell::GvrInit(JNIEnv* env,
78 const base::android::JavaParamRef<jobject>& obj, 69 const JavaParamRef<jobject>& obj,
79 jlong native_gvr_api) { 70 jlong native_gvr_api) {
80 gvr_api_ = 71 gvr_api_ =
81 gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(native_gvr_api)); 72 gvr::GvrApi::WrapNonOwned(reinterpret_cast<gvr_context*>(native_gvr_api));
82 73
83 device::GvrDelegateManager::GetInstance()->Initialize(this); 74 device::GvrDelegateManager::GetInstance()->Initialize(this);
84 } 75 }
85 76
86 void VrShell::InitializeGl(JNIEnv* env, 77 void VrShell::InitializeGl(JNIEnv* env,
87 const base::android::JavaParamRef<jobject>& obj, 78 const JavaParamRef<jobject>& obj,
88 jint texture_data_handle) { 79 jint texture_data_handle) {
89 gl::init::InitializeGLOneOff(); 80 CHECK(gl::GetGLImplementation() != gl::kGLImplementationNone ||
81 gl::init::InitializeGLOneOff());
82
83 content_texture_id_ = texture_data_handle;
90 gvr_api_->InitializeGl(); 84 gvr_api_->InitializeGl();
91 std::vector<gvr::BufferSpec> specs; 85 std::vector<gvr::BufferSpec> specs;
92 specs.push_back(gvr_api_->CreateBufferSpec()); 86 specs.push_back(gvr_api_->CreateBufferSpec());
93 render_size_ = specs[0].GetSize(); 87 render_size_ = specs[0].GetSize();
94 swap_chain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapchain(specs))); 88 swap_chain_.reset(new gvr::SwapChain(gvr_api_->CreateSwapchain(specs)));
95 content_rect_.reset(new ContentRect()); 89
96 content_rect_->content_texture_handle = 90 desktop_plane_->content_texture_handle = content_texture_id_;
97 reinterpret_cast<int>(texture_data_handle); 91
98 vr_shell_renderer_.reset(new VrShellRenderer()); 92 vr_shell_renderer_.reset(new VrShellRenderer());
99 buffer_viewport_list_.reset( 93 buffer_viewport_list_.reset(
100 new gvr::BufferViewportList(gvr_api_->CreateEmptyBufferViewportList())); 94 new gvr::BufferViewportList(gvr_api_->CreateEmptyBufferViewportList()));
101 buffer_viewport_.reset( 95 buffer_viewport_.reset(
102 new gvr::BufferViewport(gvr_api_->CreateBufferViewport())); 96 new gvr::BufferViewport(gvr_api_->CreateBufferViewport()));
103 } 97 }
104 98
105 void VrShell::DrawFrame(JNIEnv* env, 99 void ApplyNeckModel(gvr::Mat4f& mat_forward) {
106 const base::android::JavaParamRef<jobject>& obj) { 100 // This assumes that the input matrix is a pure rotation matrix. The
101 // input object_from_reference matrix has the inverse rotation of
102 // the head rotation. Invert it (this is just a transpose).
103 gvr::Mat4f mat = MatrixTranspose(mat_forward);
104
105 // Position of the point between the eyes, relative to the neck pivot:
106 const float kNeckHorizontalOffset = -0.080f; // meters in Z
107 const float kNeckVerticalOffset = 0.075f; // meters in Y
108
109 std::array<float, 4> neckOffset = {
110 {0.0f, kNeckVerticalOffset, kNeckHorizontalOffset, 1.0f}};
111
112 // Rotate eyes around neck pivot point.
113 auto offset = MatrixVectorMul(mat, neckOffset);
114
115 // Measure new position relative to original center of head, because
116 // applying a neck model should not elevate the camera.
117 offset[1] -= kNeckVerticalOffset;
118
119 // Right-multiply the inverse translation onto the
120 // object_from_reference_matrix.
121 TranslateMRight(mat_forward, mat_forward, -offset[0], -offset[1], -offset[2]);
122 }
123
124 void VrShell::DrawFrame(JNIEnv* env, const JavaParamRef<jobject>& obj) {
107 buffer_viewport_list_->SetToRecommendedBufferViewports(); 125 buffer_viewport_list_->SetToRecommendedBufferViewports();
126
108 gvr::Frame frame = swap_chain_->AcquireFrame(); 127 gvr::Frame frame = swap_chain_->AcquireFrame();
109 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow(); 128 gvr::ClockTimePoint target_time = gvr::GvrApi::GetTimePointNow();
110 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos; 129 target_time.monotonic_system_time_nanos += kPredictionTimeWithoutVsyncNanos;
111 head_pose_ = gvr_api_->GetHeadPoseInStartSpace(target_time); 130 head_pose_ = gvr_api_->GetHeadPoseInStartSpace(target_time);
112 131
113 // Bind back to the default framebuffer. 132 // Bind back to the default framebuffer.
114 frame.BindBuffer(0); 133 frame.BindBuffer(0);
115 134
116 if (webvr_mode_) { 135 if (webvr_mode_) {
117 DrawWebVr(); 136 DrawWebVr();
118 } else { 137 } else {
119 DrawVrShell(); 138 DrawVrShell();
120 } 139 }
121 140
122 frame.Unbind(); 141 frame.Unbind();
123 frame.Submit(*buffer_viewport_list_, head_pose_); 142 frame.Submit(*buffer_viewport_list_, head_pose_);
124 } 143 }
125 144
126 void VrShell::DrawVrShell() { 145 void VrShell::DrawVrShell() {
127 // Content area positioning. 146 float screen_width = kScreenWidthMeters * desktop_height_;
128 content_rect_->SetIdentity(); 147 float screen_height = kScreenHeightMeters * desktop_height_;
129 content_rect_->Translate(kContentRectPositionDefault.x,
130 kContentRectPositionDefault.y,
131 kContentRectPositionDefault.z);
132 148
149 float screen_tilt = desktop_screen_tilt_ * M_PI / 180.0f;
150
151 gvr::Vec3f headPos = getTranslation(head_pose_);
152 if (headPos.x == 0.0f && headPos.y == 0.0f && headPos.z == 0.0f) {
153 // This appears to be a 3DOF pose without a neck model. Add one.
154 // The head pose has redundant data. Assume we're only using the
155 // object_from_reference_matrix, we're not updating position_external.
156 // TODO: Not sure what object_from_reference_matrix is. The new api removed
157 // it. For now, removing it seems working fine.
158 ApplyNeckModel(head_pose_);
159 }
160
161 desktop_plane_->size = {screen_width, screen_height, 1.0f};
162 desktop_plane_->translation.x = desktop_position_.x;
163 desktop_plane_->translation.y = desktop_position_.y;
164 desktop_plane_->translation.z = desktop_position_.z;
165
166 // Update position of all UI elements (including desktop)
167 UpdateTransforms(screen_width, screen_height, screen_tilt);
168
169 // Everything should be positioned now, ready for drawing.
133 gvr::Mat4f left_eye_view_matrix = 170 gvr::Mat4f left_eye_view_matrix =
134 MatrixMul(gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE), head_pose_); 171 MatrixMul(gvr_api_->GetEyeFromHeadMatrix(GVR_LEFT_EYE), head_pose_);
135 gvr::Mat4f right_eye_view_matrix = 172 gvr::Mat4f right_eye_view_matrix =
136 MatrixMul(gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE), head_pose_); 173 MatrixMul(gvr_api_->GetEyeFromHeadMatrix(GVR_RIGHT_EYE), head_pose_);
137 174
138 // Use culling to remove back faces. 175 // Use culling to remove back faces.
139 glEnable(GL_CULL_FACE); 176 glEnable(GL_CULL_FACE);
140 177
141 // Enable depth testing. 178 // Enable depth testing.
142 glEnable(GL_DEPTH_TEST); 179 glEnable(GL_DEPTH_TEST);
143 glEnable(GL_SCISSOR_TEST); 180 glEnable(GL_SCISSOR_TEST);
144 181
145 glClearColor(0.1f, 0.1f, 0.1f, 1.0f); 182 glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
146 183
147 // Enable transparency.
148 glEnable(GL_BLEND);
149 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
150
151 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE, 184 buffer_viewport_list_->GetBufferViewport(GVR_LEFT_EYE,
152 buffer_viewport_.get()); 185 buffer_viewport_.get());
153 DrawEye(left_eye_view_matrix, *buffer_viewport_); 186 DrawEye(left_eye_view_matrix, *buffer_viewport_);
154 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE, 187 buffer_viewport_list_->GetBufferViewport(GVR_RIGHT_EYE,
155 buffer_viewport_.get()); 188 buffer_viewport_.get());
156 DrawEye(right_eye_view_matrix, *buffer_viewport_); 189 DrawEye(right_eye_view_matrix, *buffer_viewport_);
157 } 190 }
158 191
159 void VrShell::DrawEye(const gvr::Mat4f& view_matrix, 192 void VrShell::DrawEye(const gvr::Mat4f& view_matrix,
160 const gvr::BufferViewport& params) { 193 const gvr::BufferViewport& params) {
161 gvr::Recti pixel_rect = 194 gvr::Recti pixel_rect =
162 CalculatePixelSpaceRect(render_size_, params.GetSourceUv()); 195 CalculatePixelSpaceRect(render_size_, params.GetSourceUv());
163 glViewport(pixel_rect.left, pixel_rect.bottom, 196 glViewport(pixel_rect.left, pixel_rect.bottom,
164 pixel_rect.right - pixel_rect.left, 197 pixel_rect.right - pixel_rect.left,
165 pixel_rect.top - pixel_rect.bottom); 198 pixel_rect.top - pixel_rect.bottom);
166 glScissor(pixel_rect.left, pixel_rect.bottom, 199 glScissor(pixel_rect.left, pixel_rect.bottom,
167 pixel_rect.right - pixel_rect.left, 200 pixel_rect.right - pixel_rect.left,
168 pixel_rect.top - pixel_rect.bottom); 201 pixel_rect.top - pixel_rect.bottom);
169 202
170 view_matrix_ = view_matrix; 203 view_matrix_ = view_matrix;
171 204
172 projection_matrix_ = 205 projection_matrix_ =
173 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar); 206 PerspectiveMatrixFromView(params.GetSourceFov(), kZNear, kZFar);
174 207
175 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 208 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
176 DrawContentRect(); 209 DrawUI();
177 } 210 }
178 211
179 void VrShell::DrawContentRect() { 212 void VrShell::DrawUI() {
180 gvr::Mat4f content_rect_combined_matrix = 213 for (std::size_t i = 0; i < ui_rects_.size(); ++i) {
181 MatrixMul(view_matrix_, content_rect_->transfrom_to_world); 214 gvr::Mat4f combined_matrix =
182 content_rect_combined_matrix = 215 MatrixMul(view_matrix_, ui_rects_[i].get()->transform.to_world);
183 MatrixMul(projection_matrix_, content_rect_combined_matrix); 216 combined_matrix = MatrixMul(projection_matrix_, combined_matrix);
184 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw( 217 vr_shell_renderer_->GetTexturedQuadRenderer()->Draw(
185 content_rect_->content_texture_handle, content_rect_combined_matrix); 218 ui_rects_[i].get()->content_texture_handle, combined_matrix,
219 ui_rects_[i].get()->copy_rect);
220 }
186 } 221 }
187 222
188 void VrShell::DrawWebVr() { 223 void VrShell::DrawWebVr() {
189 // Don't need face culling, depth testing, blending, etc. Turn it all off. 224 // Don't need face culling, depth testing, blending, etc. Turn it all off.
190 glDisable(GL_CULL_FACE); 225 glDisable(GL_CULL_FACE);
191 glDepthMask(GL_FALSE); 226 glDepthMask(GL_FALSE);
192 glDisable(GL_DEPTH_TEST); 227 glDisable(GL_DEPTH_TEST);
193 glDisable(GL_SCISSOR_TEST); 228 glDisable(GL_SCISSOR_TEST);
194 glDisable(GL_BLEND); 229 glDisable(GL_BLEND);
195 glDisable(GL_POLYGON_OFFSET_FILL); 230 glDisable(GL_POLYGON_OFFSET_FILL);
196 231
197 // Don't need to clear, since we're drawing over the entire render target. 232 // Don't need to clear, since we're drawing over the entire render target.
198 233
199 glViewport(0, 0, render_size_.width, render_size_.height); 234 glViewport(0, 0, render_size_.width, render_size_.height);
200 vr_shell_renderer_->GetWebVrRenderer()->Draw( 235 vr_shell_renderer_->GetWebVrRenderer()->Draw(
201 reinterpret_cast<int>(content_rect_->content_texture_handle)); 236 reinterpret_cast<int>(desktop_plane_->content_texture_handle));
202 } 237 }
203 238
204 void VrShell::OnPause(JNIEnv* env, 239 void VrShell::OnPause(JNIEnv* env, const JavaParamRef<jobject>& obj) {
205 const base::android::JavaParamRef<jobject>& obj) {
206 if (gvr_api_ == nullptr) 240 if (gvr_api_ == nullptr)
207 return; 241 return;
208 gvr_api_->PauseTracking(); 242 gvr_api_->PauseTracking();
209 } 243 }
210 244
211 void VrShell::OnResume(JNIEnv* env, 245 void VrShell::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) {
212 const base::android::JavaParamRef<jobject>& obj) {
213 if (gvr_api_ == nullptr) 246 if (gvr_api_ == nullptr)
214 return; 247 return;
248
215 gvr_api_->RefreshViewerProfile(); 249 gvr_api_->RefreshViewerProfile();
216 gvr_api_->ResumeTracking(); 250 gvr_api_->ResumeTracking();
217 } 251 }
218 252
219 void VrShell::RequestWebVRPresent() { 253 void VrShell::RequestWebVRPresent() {
220 webvr_mode_ = true; 254 webvr_mode_ = true;
221 } 255 }
222 256
223 void VrShell::ExitWebVRPresent() { 257 void VrShell::ExitWebVRPresent() {
224 webvr_mode_ = false; 258 webvr_mode_ = false;
225 } 259 }
226 260
227 void VrShell::SubmitWebVRFrame() { 261 void VrShell::SubmitWebVRFrame() {
228 } 262 }
229 263
230 void VrShell::UpdateWebVRTextureBounds( 264 void VrShell::UpdateWebVRTextureBounds(
231 int eye, float left, float top, float width, float height) { 265 int eye, float left, float top, float width, float height) {
232 gvr::Rectf bounds = { left, top, width, height }; 266 gvr::Rectf bounds = { left, top, width, height };
233 vr_shell_renderer_->GetWebVrRenderer()->UpdateTextureBounds(eye, bounds); 267 vr_shell_renderer_->GetWebVrRenderer()->UpdateTextureBounds(eye, bounds);
234 } 268 }
235 269
236 gvr::GvrApi* VrShell::gvr_api() { 270 gvr::GvrApi* VrShell::gvr_api() {
237 return gvr_api_.get(); 271 return gvr_api_.get();
238 } 272 }
239 273
274 void VrShell::UpdateTransforms(float screen_width_meters,
275 float screen_height_meters,
276 float screen_tilt) {
277 for (std::unique_ptr<ContentRectangle>& rect : ui_rects_) {
278 rect->transform.MakeIdentity();
279 rect->transform.Scale(rect->size.x, rect->size.y, rect->size.z);
280 float x_anchor_translate;
281 switch (rect->x_anchoring) {
282 case XLEFT:
283 x_anchor_translate = desktop_position_.x - screen_width_meters * 0.5;
284 break;
285 case XRIGHT:
286 x_anchor_translate = desktop_position_.x + screen_width_meters * 0.5;
287 break;
288 case XCENTER:
289 x_anchor_translate = desktop_position_.x;
290 break;
291 case XNONE:
292 x_anchor_translate = 0;
293 break;
294 }
295 float y_anchor_translate;
296 switch (rect->y_anchoring) {
297 case YTOP:
298 y_anchor_translate = desktop_position_.y + screen_height_meters * 0.5;
299 break;
300 case YBOTTOM:
301 y_anchor_translate = desktop_position_.y - screen_height_meters * 0.5;
302 break;
303 case YCENTER:
304 y_anchor_translate = desktop_position_.y;
305 break;
306 case YNONE:
307 y_anchor_translate = 0;
308 break;
309 }
310 float z_anchor_translate = rect->anchor_z ? desktop_position_.z : 0;
311 rect->transform.Translate(x_anchor_translate + rect->translation.x,
312 y_anchor_translate + rect->translation.y,
313 z_anchor_translate + rect->translation.z);
314 // TODO(cjgrant): Establish which exact rotations we'll provide.
315 // Adjust for screen tilt.
316 rect->transform.Rotate(1.0f, 0.0f, 0.0f, screen_tilt);
317 }
318 }
319
240 // ---------------------------------------------------------------------------- 320 // ----------------------------------------------------------------------------
241 // Native JNI methods 321 // Native JNI methods
242 // ---------------------------------------------------------------------------- 322 // ----------------------------------------------------------------------------
243 323
244 jlong Init(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj) { 324 jlong Init(JNIEnv* env, const JavaParamRef<jobject>& obj) {
245 VrShell* vrShell = new VrShell(env, obj); 325 return reinterpret_cast<intptr_t>(new VrShell(env, obj));
246 return reinterpret_cast<intptr_t>(vrShell);
247 } 326 }
248 327
249 } // namespace vr_shell 328 } // namespace vr_shell
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698