Commit bd7709f2 authored by Brian Sheedy's avatar Brian Sheedy Committed by Commit Bot

Port remaining XR tests to WMR

Ports the remaining WebXR browser tests that are currently OpenVR-only
but make sense for WMR over to also run with WMR.

As a result, also properly copies texture data and provides it back
to the test in WMR like OpenVR does.

Bug: 926048
Change-Id: I12841f4adc8876089592020493cb371e38214a73
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1637610
Commit-Queue: Brian Sheedy <bsheedy@chromium.org>
Reviewed-by: default avatarAlexander Cooper <alcooper@chromium.org>
Reviewed-by: default avatarBill Orr <billorr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#665658}
parent a80b7a07
......@@ -6,6 +6,7 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "chrome/browser/vr/test/mock_xr_device_hook_base.h"
#include "chrome/browser/vr/test/multi_class_browser_test.h"
#include "chrome/browser/vr/test/ui_utils.h"
#include "chrome/browser/vr/test/webxr_vr_browser_test.h"
......@@ -158,16 +159,16 @@ std::string GetPoseAsString(const Frame& frame) {
} // namespace
// Pixel test for WebVR/WebXR - start presentation, submit frames, get data back
// out. Validates that submitted frames used expected pose.
void TestPresentationPosesImpl(WebXrVrBrowserTestBase* t,
std::string filename) {
// Pixel test for WebXR - start presentation, submit frames, get data back out.
// Validates that submitted frames used expected pose.
WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestPresentationPoses) {
// Disable frame-timeout UI to test what WebXR renders.
UiUtils::DisableFrameTimeoutForTesting();
MyXRMock my_mock;
// Load the test page, and enter presentation.
t->LoadUrlAndAwaitInitialization(t->GetFileUrlForHtmlTestFile(filename));
t->LoadUrlAndAwaitInitialization(
t->GetFileUrlForHtmlTestFile("test_webxr_poses"));
t->EnterSessionWithUserGestureOrFail();
// Wait for JavaScript to submit at least one frame.
......@@ -232,10 +233,4 @@ void TestPresentationPosesImpl(WebXrVrBrowserTestBase* t,
t->EndTest();
}
// TODO(https://crbug.com/926048): Port to WMR as well. Submitted frame data
// is not yet provided back to the test when using WMR.
IN_PROC_BROWSER_TEST_F(WebXrVrOpenVrBrowserTest, TestPresentationPoses) {
TestPresentationPosesImpl(this, "test_webxr_poses");
}
} // namespace vr
......@@ -6,36 +6,43 @@
#include "build/build_config.h"
#include "chrome/browser/vr/test/mock_xr_device_hook_base.h"
#include "chrome/browser/vr/test/multi_class_browser_test.h"
#include "chrome/browser/vr/test/webxr_vr_browser_test.h"
#include "content/public/test/browser_test_utils.h"
namespace vr {
// TODO(https://crbug.com/926048): Figure out why/fix the WMR version of this
// causes the real Mixed Reality Portal to open if it's installed.
// Tests that we can recover from a crash/disconnect on the DeviceService
IN_PROC_BROWSER_TEST_F(WebXrVrOpenVrBrowserTest, TestDeviceServiceDisconnect) {
LoadUrlAndAwaitInitialization(
GetFileUrlForHtmlTestFile("test_isolated_device_service_disconnect"));
WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestDeviceServiceDisconnect) {
t->LoadUrlAndAwaitInitialization(
t->GetFileUrlForHtmlTestFile("test_isolated_device_service_disconnect"));
// We expect one change from the initial device being available.
PollJavaScriptBooleanOrFail("deviceChanges === 1", kPollTimeoutMedium);
t->PollJavaScriptBooleanOrFail("deviceChanges === 1",
WebXrVrBrowserTestBase::kPollTimeoutMedium);
EnterSessionWithUserGestureOrFail();
t->EnterSessionWithUserGestureOrFail();
MockXRDeviceHookBase device_hook;
device_hook.TerminateDeviceServiceProcessForTesting();
// Ensure that we've actually exited the session.
PollJavaScriptBooleanOrFail(
t->PollJavaScriptBooleanOrFail(
"sessionInfos[sessionTypes.IMMERSIVE].currentSession === null",
kPollTimeoutLong);
WebXrVrBrowserTestBase::kPollTimeoutLong);
// We need to create a mock here because otherwise WMR opens the real Mixed
// Reality Portal if it's installed. The killing of the process unsets the
// hook created by the one above, and the presence of the hook is what WMR
// uses to determine whether it should uses the mock or real implementation.
MockXRDeviceHookBase another_hook;
// We expect one change indicating the device was disconnected, and then
// one more indicating that the device was re-connected.
PollJavaScriptBooleanOrFail("deviceChanges === 3", kPollTimeoutMedium);
t->PollJavaScriptBooleanOrFail("deviceChanges === 3",
WebXrVrBrowserTestBase::kPollTimeoutMedium);
// One last check now that we have the device change that we can actually
// still enter an immersive session.
EnterSessionWithUserGestureOrFail();
t->EnterSessionWithUserGestureOrFail();
}
} // namespace vr
......@@ -8,6 +8,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/vr/test/mock_xr_device_hook_base.h"
#include "chrome/browser/vr/test/multi_class_browser_test.h"
#include "chrome/browser/vr/test/ui_utils.h"
#include "chrome/browser/vr/test/webvr_browser_test.h"
#include "chrome/browser/vr/test/webxr_vr_browser_test.h"
......@@ -90,10 +91,8 @@ void TestPresentationPixelsImpl(WebXrVrBrowserTestBase* t,
IN_PROC_BROWSER_TEST_F(WebVrOpenVrBrowserTest, TestPresentationPixels) {
TestPresentationPixelsImpl(this, "test_webvr_pixels");
}
// TODO(https://crbug.com/926048): Port to WMR once the frame data is properly
// piped back to the test.
IN_PROC_BROWSER_TEST_F(WebXrVrOpenVrBrowserTest, TestPresentationPixels) {
TestPresentationPixelsImpl(this, "test_webxr_pixels");
WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestPresentationPixels) {
TestPresentationPixelsImpl(t, "test_webxr_pixels");
}
} // namespace vr
......@@ -63,8 +63,8 @@ void TestHelper::OnPresentedFrame(ID3D11Texture2D* texture,
size_t buffer_size = sizeof(device::SubmittedFrameData::raw_buffer);
size_t buffer_size_pixels = buffer_size / sizeof(device::Color);
desc.Width = 1;
desc.Height = buffer_size_pixels;
desc.Width = buffer_size_pixels;
desc.Height = 1;
desc.MiscFlags = 0;
desc.BindFlags = 0;
desc.Usage = D3D11_USAGE_STAGING;
......@@ -75,7 +75,9 @@ void TestHelper::OnPresentedFrame(ID3D11Texture2D* texture,
return;
}
D3D11_BOX box = {0, 0, 0, buffer_size_pixels, 1, 1}; // a 1-pixel box
// A strip of pixels along the top of the texture, however many will fit into
// our buffer.
D3D11_BOX box = {0, 0, 0, buffer_size_pixels, 1, 1};
context->CopySubresourceRegion(texture_copy.Get(), 0, 0, 0, 0, texture, 0,
&box);
......
......@@ -44,17 +44,94 @@ MockWMRHolographicFrame::CurrentPrediction() {
std::unique_ptr<WMRRenderingParameters>
MockWMRHolographicFrame::TryGetRenderingParameters(const WMRCameraPose* pose) {
return std::make_unique<MockWMRRenderingParameters>(d3d11_device_);
// Cache a reference to the texture so that we can use it later when
// submitting the frame.
auto params = std::make_unique<MockWMRRenderingParameters>(d3d11_device_);
backbuffer_texture_ = params->TryGetBackbufferAsTexture2D();
return params;
}
bool MockWMRHolographicFrame::TryPresentUsingCurrentPrediction() {
// TODO(https://crbug.com/926048): Actually pass in correct data.
SubmittedFrameData data;
// If we don't actually have a texture to submit, don't try.
if (!backbuffer_texture_)
return false;
// Set eye-independent data, copy, then set eye-dependent data.
SubmittedFrameData left_data;
auto viewport = CurrentPrediction()->CameraPoses().front()->Viewport();
left_data.viewport = {viewport.X, viewport.Y, viewport.X + viewport.Width,
viewport.Y + viewport.Height};
D3D11_TEXTURE2D_DESC desc;
backbuffer_texture_->GetDesc(&desc);
left_data.image_width = desc.Width;
left_data.image_height = desc.Height;
SubmittedFrameData right_data = left_data;
left_data.left_eye = true;
right_data.left_eye = false;
bool success =
CopyTextureDataIntoFrameData(&left_data, 0 /*index, left eye */);
DCHECK(success);
success = CopyTextureDataIntoFrameData(&right_data, 1 /* index, right eye */);
DCHECK(success);
auto locked_hook = MixedRealityDeviceStatics::GetLockedTestHook();
if (locked_hook.GetHook()) {
locked_hook.GetHook()->OnFrameSubmitted(data);
locked_hook.GetHook()->OnFrameSubmitted(left_data);
locked_hook.GetHook()->OnFrameSubmitted(right_data);
}
return true;
}
bool MockWMRHolographicFrame::CopyTextureDataIntoFrameData(
SubmittedFrameData* data,
unsigned int index) {
DCHECK(d3d11_device_);
DCHECK(backbuffer_texture_);
Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
d3d11_device_->GetImmediateContext(&context);
size_t buffer_size = sizeof(device::SubmittedFrameData::raw_buffer);
size_t buffer_size_pixels = buffer_size / sizeof(device::Color);
// We copy the submitted texture to a new texture, so we can map it, and
// read back pixel data.
auto desc = CD3D11_TEXTURE2D_DESC();
desc.ArraySize = 1;
desc.Width = buffer_size_pixels;
desc.Height = 1;
desc.MipLevels = 1;
desc.SampleDesc = {1, 0};
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.Usage = D3D11_USAGE_STAGING;
desc.BindFlags = 0;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture_copy;
HRESULT hr = d3d11_device_->CreateTexture2D(&desc, nullptr, &texture_copy);
if (FAILED(hr))
return false;
// A strip of pixels along the top of the texture, however many will fit into
// our buffer.
D3D11_BOX box = {0, 0, 0, buffer_size_pixels, 1, 1};
context->CopySubresourceRegion(texture_copy.Get(), 0, 0, 0, 0,
backbuffer_texture_.Get(), index, &box);
D3D11_MAPPED_SUBRESOURCE map_data = {};
hr = context->Map(texture_copy.Get(), 0, D3D11_MAP_READ, 0, &map_data);
if (FAILED(hr))
return false;
// We have a 1-pixel image, so store it in the provided SubmittedFrameData
// along with the raw data.
device::Color* color = reinterpret_cast<device::Color*>(map_data.pData);
data->color = color[0];
memcpy(&data->raw_buffer, map_data.pData, buffer_size);
context->Unmap(texture_copy.Get(), 0);
return true;
}
} // namespace device
......@@ -9,6 +9,8 @@
namespace device {
struct SubmittedFrameData;
class MockWMRHolographicFramePrediction : public WMRHolographicFramePrediction {
public:
MockWMRHolographicFramePrediction();
......@@ -32,7 +34,11 @@ class MockWMRHolographicFrame : public WMRHolographicFrame {
bool TryPresentUsingCurrentPrediction() override;
private:
bool CopyTextureDataIntoFrameData(SubmittedFrameData* data,
unsigned int index);
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_ = nullptr;
Microsoft::WRL::ComPtr<ID3D11Texture2D> backbuffer_texture_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(MockWMRHolographicFrame);
};
......
......@@ -157,24 +157,27 @@ MockWMRRenderingParameters::~MockWMRRenderingParameters() = default;
Microsoft::WRL::ComPtr<ID3D11Texture2D>
MockWMRRenderingParameters::TryGetBackbufferAsTexture2D() {
if (backbuffer_texture_)
return backbuffer_texture_;
if (!d3d11_device_)
return nullptr;
auto desc = CD3D11_TEXTURE2D_DESC();
desc.ArraySize = 2;
desc.Width = kDefaultWmrRenderWidth;
desc.Height = kDefaultWmrRenderHeight;
desc.MipLevels = 1;
desc.SampleDesc = {1, 0};
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_RENDER_TARGET;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE | D3D11_CPU_ACCESS_READ;
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture = nullptr;
auto hr = d3d11_device_->CreateTexture2D(&desc, nullptr, &texture);
auto hr =
d3d11_device_->CreateTexture2D(&desc, nullptr, &backbuffer_texture_);
if (FAILED(hr))
return nullptr;
return texture;
return backbuffer_texture_;
}
} // namespace device
......@@ -52,6 +52,7 @@ class MockWMRRenderingParameters : public WMRRenderingParameters {
private:
Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_ = nullptr;
Microsoft::WRL::ComPtr<ID3D11Texture2D> backbuffer_texture_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(MockWMRRenderingParameters);
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment