OLD | NEW |
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 "modules/vr/VRDisplay.h" | 5 #include "modules/vr/VRDisplay.h" |
6 | 6 |
7 #include "core/dom/DOMException.h" | 7 #include "core/dom/DOMException.h" |
8 #include "core/dom/Fullscreen.h" | 8 #include "core/dom/Fullscreen.h" |
9 #include "core/frame/UseCounter.h" | 9 #include "core/frame/UseCounter.h" |
10 #include "core/inspector/ConsoleMessage.h" | 10 #include "core/inspector/ConsoleMessage.h" |
| 11 #include "gpu/command_buffer/client/gles2_interface.h" |
11 #include "modules/vr/NavigatorVR.h" | 12 #include "modules/vr/NavigatorVR.h" |
12 #include "modules/vr/VRController.h" | 13 #include "modules/vr/VRController.h" |
13 #include "modules/vr/VRDisplayCapabilities.h" | 14 #include "modules/vr/VRDisplayCapabilities.h" |
14 #include "modules/vr/VREyeParameters.h" | 15 #include "modules/vr/VREyeParameters.h" |
15 #include "modules/vr/VRFrameData.h" | 16 #include "modules/vr/VRFrameData.h" |
16 #include "modules/vr/VRLayer.h" | 17 #include "modules/vr/VRLayer.h" |
17 #include "modules/vr/VRPose.h" | 18 #include "modules/vr/VRPose.h" |
18 #include "modules/vr/VRStageParameters.h" | 19 #include "modules/vr/VRStageParameters.h" |
19 #include "modules/webgl/WebGLRenderingContextBase.h" | 20 #include "modules/webgl/WebGLRenderingContextBase.h" |
20 #include "platform/UserGestureIndicator.h" | 21 #include "platform/UserGestureIndicator.h" |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 m_layer.source()->renderingContext(); | 199 m_layer.source()->renderingContext(); |
199 | 200 |
200 if (!renderingContext || !renderingContext->is3d()) { | 201 if (!renderingContext || !renderingContext->is3d()) { |
201 forceExitPresent(); | 202 forceExitPresent(); |
202 DOMException* exception = DOMException::create( | 203 DOMException* exception = DOMException::create( |
203 InvalidStateError, "Layer source must have a WebGLRenderingContext"); | 204 InvalidStateError, "Layer source must have a WebGLRenderingContext"); |
204 resolver->reject(exception); | 205 resolver->reject(exception); |
205 return promise; | 206 return promise; |
206 } | 207 } |
207 | 208 |
| 209 // Save the WebGL script and underlying GL contexts for use by submitFrame(). |
| 210 m_renderingContext = toWebGLRenderingContextBase(renderingContext); |
| 211 m_contextGL = m_renderingContext->contextGL(); |
| 212 |
208 if ((m_layer.leftBounds().size() != 0 && m_layer.leftBounds().size() != 4) || | 213 if ((m_layer.leftBounds().size() != 0 && m_layer.leftBounds().size() != 4) || |
209 (m_layer.rightBounds().size() != 0 && | 214 (m_layer.rightBounds().size() != 0 && |
210 m_layer.rightBounds().size() != 4)) { | 215 m_layer.rightBounds().size() != 4)) { |
211 forceExitPresent(); | 216 forceExitPresent(); |
212 DOMException* exception = DOMException::create( | 217 DOMException* exception = DOMException::create( |
213 InvalidStateError, | 218 InvalidStateError, |
214 "Layer bounds must either be an empty array or have 4 values"); | 219 "Layer bounds must either be an empty array or have 4 values"); |
215 resolver->reject(exception); | 220 resolver->reject(exception); |
216 return promise; | 221 return promise; |
217 } | 222 } |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 if (!m_capabilities->hasExternalDisplay()) { | 292 if (!m_capabilities->hasExternalDisplay()) { |
288 Fullscreen::fullyExitFullscreen(m_layer.source()->document()); | 293 Fullscreen::fullyExitFullscreen(m_layer.source()->document()); |
289 m_fullscreenCheckTimer.stop(); | 294 m_fullscreenCheckTimer.stop(); |
290 } else { | 295 } else { |
291 // Can't get into this presentation mode, so nothing to do here. | 296 // Can't get into this presentation mode, so nothing to do here. |
292 } | 297 } |
293 m_navigatorVR->fireVRDisplayPresentChange(this); | 298 m_navigatorVR->fireVRDisplayPresentChange(this); |
294 } | 299 } |
295 | 300 |
296 m_isPresenting = false; | 301 m_isPresenting = false; |
| 302 m_renderingContext = nullptr; |
| 303 m_contextGL = nullptr; |
297 } | 304 } |
298 | 305 |
299 void VRDisplay::updateLayerBounds() { | 306 void VRDisplay::updateLayerBounds() { |
300 // Set up the texture bounds for the provided layer | 307 // Set up the texture bounds for the provided layer |
301 device::blink::VRLayerBoundsPtr leftBounds = | 308 device::blink::VRLayerBoundsPtr leftBounds = |
302 device::blink::VRLayerBounds::New(); | 309 device::blink::VRLayerBounds::New(); |
303 device::blink::VRLayerBoundsPtr rightBounds = | 310 device::blink::VRLayerBoundsPtr rightBounds = |
304 device::blink::VRLayerBounds::New(); | 311 device::blink::VRLayerBounds::New(); |
305 | 312 |
306 if (m_layer.leftBounds().size() == 4) { | 313 if (m_layer.leftBounds().size() == 4) { |
(...skipping 30 matching lines...) Expand all Loading... |
337 HeapVector<VRLayer> layers; | 344 HeapVector<VRLayer> layers; |
338 | 345 |
339 if (m_isPresenting) { | 346 if (m_isPresenting) { |
340 layers.append(m_layer); | 347 layers.append(m_layer); |
341 } | 348 } |
342 | 349 |
343 return layers; | 350 return layers; |
344 } | 351 } |
345 | 352 |
346 void VRDisplay::submitFrame() { | 353 void VRDisplay::submitFrame() { |
| 354 if (!m_isPresenting || !m_contextGL) { |
| 355 // Something got confused, we can't submit frames if we're not presenting. |
| 356 return; |
| 357 } |
| 358 |
| 359 // Write the frame number for the pose used into a bottom left pixel block. |
| 360 // It is read by chrome/browser/android/vr_shell/vr_shell.cc to associate |
| 361 // the correct corresponding pose for submission. |
| 362 auto gl = m_contextGL; |
| 363 |
| 364 // We must ensure that the WebGL app's GL state is preserved. We do this by |
| 365 // calling low-level GL commands directly so that the rendering context's |
| 366 // saved parameters don't get overwritten. |
| 367 |
| 368 gl->Enable(GL_SCISSOR_TEST); |
| 369 // Use a few pixels to ensure we get a clean color. The resolution for the |
| 370 // WebGL buffer may not match the final rendered destination size, and |
| 371 // texture filtering could interfere for single pixels. This isn't visible |
| 372 // since the final rendering hides the edges via a vignette effect. |
| 373 gl->Scissor(0, 0, 4, 4); |
| 374 gl->ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| 375 int idx = m_framePose->poseIndex; |
| 376 // Careful with the arithmetic here. Float color 1.f is equivalent to int 255. |
| 377 gl->ClearColor((idx & 255) / 255.0f, ((idx >> 8) & 255) / 255.0f, |
| 378 ((idx >> 16) & 255) / 255.0f, 1.0f); |
| 379 gl->Clear(GL_COLOR_BUFFER_BIT); |
| 380 |
| 381 // Set the GL state back to what was set by the WebVR application. |
| 382 m_renderingContext->restoreScissorEnabled(); |
| 383 m_renderingContext->restoreScissorBox(); |
| 384 m_renderingContext->restoreColorMask(); |
| 385 m_renderingContext->restoreClearColor(); |
| 386 |
347 controller()->submitFrame(m_displayId, m_framePose.Clone()); | 387 controller()->submitFrame(m_displayId, m_framePose.Clone()); |
348 m_canUpdateFramePose = true; | 388 m_canUpdateFramePose = true; |
349 } | 389 } |
350 | 390 |
351 void VRDisplay::onFullscreenCheck(TimerBase*) { | 391 void VRDisplay::onFullscreenCheck(TimerBase*) { |
352 // TODO: This is a temporary measure to track if fullscreen mode has been | 392 // TODO: This is a temporary measure to track if fullscreen mode has been |
353 // exited by the UA. If so we need to end VR presentation. Soon we won't | 393 // exited by the UA. If so we need to end VR presentation. Soon we won't |
354 // depend on the Fullscreen API to fake VR presentation, so this will | 394 // depend on the Fullscreen API to fake VR presentation, so this will |
355 // become unnessecary. Until that point, though, this seems preferable to | 395 // become unnessecary. Until that point, though, this seems preferable to |
356 // adding a bunch of notification plumbing to Fullscreen. | 396 // adding a bunch of notification plumbing to Fullscreen. |
357 if (!Fullscreen::isCurrentFullScreenElement(*m_layer.source())) { | 397 if (!Fullscreen::isCurrentFullScreenElement(*m_layer.source())) { |
358 m_isPresenting = false; | 398 m_isPresenting = false; |
359 m_navigatorVR->fireVRDisplayPresentChange(this); | 399 m_navigatorVR->fireVRDisplayPresentChange(this); |
360 m_fullscreenCheckTimer.stop(); | 400 m_fullscreenCheckTimer.stop(); |
361 controller()->exitPresent(m_displayId); | 401 controller()->exitPresent(m_displayId); |
362 } | 402 } |
363 } | 403 } |
364 | 404 |
365 DEFINE_TRACE(VRDisplay) { | 405 DEFINE_TRACE(VRDisplay) { |
366 visitor->trace(m_navigatorVR); | 406 visitor->trace(m_navigatorVR); |
367 visitor->trace(m_capabilities); | 407 visitor->trace(m_capabilities); |
368 visitor->trace(m_stageParameters); | 408 visitor->trace(m_stageParameters); |
369 visitor->trace(m_eyeParametersLeft); | 409 visitor->trace(m_eyeParametersLeft); |
370 visitor->trace(m_eyeParametersRight); | 410 visitor->trace(m_eyeParametersRight); |
371 visitor->trace(m_layer); | 411 visitor->trace(m_layer); |
| 412 visitor->trace(m_renderingContext); |
372 } | 413 } |
373 | 414 |
374 } // namespace blink | 415 } // namespace blink |
OLD | NEW |