Commit b81078b3 authored by Bill Orr's avatar Bill Orr Committed by Commit Bot

Add a basic pixel test for submitted VR frames on Windows.

This test stores a single pixels value in a file, then reads from the
file.

BUG=808232

Change-Id: I2573a1f98188d232f25ff2ceb11cc15e67cc768f
Reviewed-on: https://chromium-review.googlesource.com/963317Reviewed-by: default avatarKenneth Russell <kbr@chromium.org>
Reviewed-by: default avatarBrandon Jones <bajones@chromium.org>
Reviewed-by: default avatarBrian Sheedy <bsheedy@chromium.org>
Commit-Queue: Bill Orr <billorr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#544902}
parent af555187
......@@ -3,4 +3,5 @@ include_rules = [
"+cc/base",
"+cc/test",
"+cc/trees",
"+device/vr/openvr/test/fake_openvr_log.h"
]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/environment.h"
#include "base/files/file.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/vr/test/vr_browser_test.h"
#include "chrome/browser/vr/test/vr_transition_utils.h"
#include "device/vr/openvr/test/fake_openvr_log.h"
#include <memory>
namespace vr {
// Pixel test for WebXR - start presentation, submit frames, get data back out.
// Validates that a pixel was rendered at with the expected color.
IN_PROC_BROWSER_TEST_F(VrBrowserTestStandard,
REQUIRES_GPU(TestPresentationPixels)) {
// Set up environment variable to tell mock device to save pixel logs
std::unique_ptr<base::Environment> env = base::Environment::Create();
base::ScopedTempDir temp_dir;
base::FilePath log_path;
{
base::ScopedAllowBlockingForTesting allow_files;
EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
log_path = temp_dir.GetPath().Append(FILE_PATH_LITERAL("VRPixelTest.Log"));
EXPECT_TRUE(log_path.MaybeAsASCII() != "") << "Temp dir is non-ascii";
env->SetVar(GetVrPixelLogEnvVarName(), log_path.MaybeAsASCII());
}
// Load the test page, and enter presentation.
LoadUrlAndAwaitInitialization(GetHtmlTestFile("test_webvr_pixels"));
EnterPresentationOrFail(GetFirstTabWebContents());
// Wait for javascript to submit at least one frame.
EXPECT_TRUE(PollJavaScriptBoolean("hasPresentedFrame", kPollTimeoutShort,
GetFirstTabWebContents()))
<< "No frame submitted";
// Tell javascript that it is done with the test.
ExecuteStepAndWait("finishTest()", GetFirstTabWebContents());
EndTest(GetFirstTabWebContents());
// Try to open the log file.
{
base::ScopedAllowBlockingForTesting allow_files;
std::unique_ptr<base::File> file;
base::Time start = base::Time::Now();
while (!file) {
file = std::make_unique<base::File>(
log_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
base::File::FLAG_DELETE_ON_CLOSE);
if (!file->IsValid()) {
file = nullptr;
}
if (base::Time::Now() - start > kPollTimeoutLong)
break;
}
EXPECT_TRUE(file);
// Now parse the log to validate that we ran correctly.
VRSubmittedFrameEvent event;
int read =
file->ReadAtCurrentPos(reinterpret_cast<char*>(&event), sizeof(event));
EXPECT_EQ(read, static_cast<int>(sizeof(event)));
VRSubmittedFrameEvent::Color expected = {0, 0, 255, 255};
EXPECT_EQ(expected.r, event.color.r);
EXPECT_EQ(expected.g, event.color.g);
EXPECT_EQ(expected.b, event.color.b);
EXPECT_EQ(expected.a, event.color.a);
file = nullptr; // Make sure we destroy this before allow_files.
EXPECT_TRUE(temp_dir.Delete());
}
}
} // namespace vr
......@@ -1915,6 +1915,7 @@ test("browser_tests") {
"../browser/vr/test/vr_transition_utils.cc",
"../browser/vr/test/vr_transition_utils.h",
"../browser/vr/webvr_input_browser_test.cc",
"../browser/vr/webvr_pixel_browser_test.cc",
"../browser/vr/webvr_tab_browser_test.cc",
"../browser/vr/webvr_transition_browser_test.cc",
]
......
<!doctype html>
<!--
Tests webvr pixel data is submitted correctly.
-->
<html>
<head>
<link rel="stylesheet" type="text/css" href="../resources/webvr_e2e.css">
</head>
<body>
<canvas id="webgl-canvas"></canvas>
<script src="../../../../../../third_party/WebKit/LayoutTests/resources/testharness.js"></script>
<script src="../resources/webvr_e2e.js"></script>
<script src="../resources/webvr_boilerplate.js"></script>
<script>
var t = async_test("Pixel data is correct");
function finishTest() {
t.done();
}
</script>
</body>
</html>
......@@ -21,6 +21,7 @@ var frameData = null;
var onMagicWindowAnimationFrameCallback = null;
var onPresentingAnimationFrameCallback = null;
var shouldSubmitFrame = true;
var hasPresentedFrame = false;
function onResize() {
if (vrDisplay && vrDisplay.isPresenting) {
......@@ -64,7 +65,10 @@ function onAnimationFrame(t) {
gl.viewport(webglCanvas.width * 0.5, 0, webglCanvas.width * 0.5,
webglCanvas.height);
if (shouldSubmitFrame) vrDisplay.submitFrame();
if (shouldSubmitFrame) {
vrDisplay.submitFrame();
hasPresentedFrame = true;
}
} else {
if (onMagicWindowAnimationFrameCallback) {
onMagicWindowAnimationFrameCallback();
......
......@@ -1843,6 +1843,7 @@ COMMON_GTESTS = {
'--test-launcher-bot-mode',
'--test-launcher-jobs=1',
'--gtest_filter=VrBrowserTest*',
'--enable-pixel-output-in-tests',
'--gtest_also_run_disabled_tests',
],
'test': 'browser_tests',
......
......@@ -183,6 +183,7 @@ if (enable_openvr) {
sources = [
"openvr/test/fake_openvr_impl_api.cc",
"openvr/test/fake_openvr_log.h",
]
libs = [
......
......@@ -2,16 +2,111 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/debug/debugger.h"
#include "base/environment.h"
#include "base/files/file.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_restrictions.h"
#include "device/vr/openvr/test/fake_openvr_log.h"
#include "third_party/openvr/src/headers/openvr.h"
#include "third_party/openvr/src/src/ivrclientcore.h"
#include <D3D11_1.h>
#include <DXGI1_4.h>
#include <wrl.h>
#include <memory>
namespace vr {
class TestVRLogger {
public:
void Start() {
// Look for environment variable saying we should log data.
std::unique_ptr<base::Environment> env = base::Environment::Create();
std::string log_filename;
if (env->GetVar(GetVrPixelLogEnvVarName(), &log_filename)) {
base::ScopedAllowBlockingForTesting allow_files;
log_file_ = std::make_unique<base::File>(
base::FilePath::FromUTF8Unsafe(log_filename),
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE |
base::File::FLAG_EXCLUSIVE_WRITE);
logging_ = log_file_->IsValid();
}
}
void Stop() {
base::ScopedAllowBlockingForTesting allow_files;
if (logging_) {
log_file_->Flush();
log_file_->Close();
log_file_ = nullptr;
}
logging_ = false;
}
void OnPresentedFrame(ID3D11Texture2D* texture) {
if (!logging_)
return;
VRSubmittedFrameEvent frame;
Microsoft::WRL::ComPtr<ID3D11Device> device;
texture->GetDevice(&device);
Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
device->GetImmediateContext(&context);
// We copy the submitted texture to a new texture, so we can map it, and
// read back pixel data.
Microsoft::WRL::ComPtr<ID3D11Texture2D> texture_copy;
D3D11_TEXTURE2D_DESC desc;
texture->GetDesc(&desc);
desc.Width = 1;
desc.Height = 1;
desc.MiscFlags = 0;
desc.BindFlags = 0;
desc.Usage = D3D11_USAGE_STAGING;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
HRESULT hr = device->CreateTexture2D(&desc, nullptr, &texture_copy);
if (FAILED(hr)) {
// We'll have invalid data in log (no frame data) so test will fail.
Stop();
return;
}
D3D11_BOX box = {0, 0, 0, 1, 1, 1}; // a 1-pixel box
context->CopySubresourceRegion(texture_copy.Get(), 0, 0, 0, 0, texture, 0,
&box);
D3D11_MAPPED_SUBRESOURCE map_data = {};
hr = context->Map(texture_copy.Get(), 0, D3D11_MAP_READ, 0, &map_data);
if (FAILED(hr)) {
// We'll have invalid data in log (no frame data) so test will fail.
Stop();
return;
}
VRSubmittedFrameEvent::Color* data =
reinterpret_cast<VRSubmittedFrameEvent::Color*>(map_data.pData);
frame.color = data[0]; // Save top-left pixel value.
context->Unmap(texture_copy.Get(), 0);
WriteVRSubmittedFrameEvent(&frame);
Stop(); // For now only validate one pixel from first frame.
}
private:
void WriteVRSubmittedFrameEvent(VRSubmittedFrameEvent* frame) {
base::ScopedAllowBlockingForTesting allow_files;
log_file_->WriteAtCurrentPos(reinterpret_cast<char*>(frame),
sizeof(*frame));
}
bool logging_ = false;
std::unique_ptr<base::File> log_file_;
};
class TestVRSystem : public IVRSystem {
public:
void GetRecommendedRenderTargetSize(uint32_t* pnWidth,
......@@ -393,15 +488,19 @@ class TestVRClientCore : public IVRClientCore {
}
};
TestVRLogger g_logger;
TestVRSystem g_system;
TestVRCompositor g_compositor;
TestVRClientCore g_loader;
EVRInitError TestVRClientCore::Init(EVRApplicationType eApplicationType) {
g_logger.Start();
return VRInitError_None;
}
void TestVRClientCore::Cleanup() {}
void TestVRClientCore::Cleanup() {
g_logger.Stop();
}
EVRInitError TestVRClientCore::IsInterfaceVersionValid(
const char* pchInterfaceVersion) {
......@@ -564,9 +663,11 @@ EVRCompositorError TestVRCompositor::WaitGetPoses(TrackedDevicePose_t* poses1,
}
EVRCompositorError TestVRCompositor::Submit(EVREye,
Texture_t const*,
Texture_t const* texture,
VRTextureBounds_t const*,
EVRSubmitFlags) {
g_logger.OnPresentedFrame(
reinterpret_cast<ID3D11Texture2D*>(texture->handle));
return VRCompositorError_None;
}
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_VR_OPENVR_TEST_FAKE_OPENVR_LOG_H_
#define DEVICE_VR_OPENVR_TEST_FAKE_OPENVR_LOG_H_
namespace vr {
// We log instances of this structure when a frame is submitted.
// Tests can walk the log to validate things ran as expected.
struct VRSubmittedFrameEvent {
struct Color {
unsigned char r;
unsigned char g;
unsigned char b;
unsigned char a;
} color;
};
inline char* GetVrPixelLogEnvVarName() {
static char ret[] = "VR_MOCK_LOG_PATH";
return ret;
}
} // namespace vr
#endif // DEVICE_VR_OPENVR_TEST_FAKE_OPENVR_LOG_H_
\ No newline at end of file
......@@ -11722,6 +11722,7 @@
"--test-launcher-bot-mode",
"--test-launcher-jobs=1",
"--gtest_filter=VrBrowserTest*",
"--enable-pixel-output-in-tests",
"--gtest_also_run_disabled_tests"
],
"name": "vr_browser_tests",
......@@ -12048,6 +12049,7 @@
"--test-launcher-bot-mode",
"--test-launcher-jobs=1",
"--gtest_filter=VrBrowserTest*",
"--enable-pixel-output-in-tests",
"--gtest_also_run_disabled_tests"
],
"name": "vr_browser_tests",
......@@ -12588,6 +12590,7 @@
"--test-launcher-bot-mode",
"--test-launcher-jobs=1",
"--gtest_filter=VrBrowserTest*",
"--enable-pixel-output-in-tests",
"--gtest_also_run_disabled_tests"
],
"name": "vr_browser_tests",
......@@ -13317,6 +13320,7 @@
"--test-launcher-bot-mode",
"--test-launcher-jobs=1",
"--gtest_filter=VrBrowserTest*",
"--enable-pixel-output-in-tests",
"--gtest_also_run_disabled_tests"
],
"name": "vr_browser_tests",
......@@ -14069,6 +14073,7 @@
"--test-launcher-bot-mode",
"--test-launcher-jobs=1",
"--gtest_filter=VrBrowserTest*",
"--enable-pixel-output-in-tests",
"--gtest_also_run_disabled_tests"
],
"name": "vr_browser_tests",
......
......@@ -2439,6 +2439,7 @@
"--test-launcher-bot-mode",
"--test-launcher-jobs=1",
"--gtest_filter=VrBrowserTest*",
"--enable-pixel-output-in-tests",
"--gtest_also_run_disabled_tests"
],
"name": "vr_browser_tests",
......@@ -2876,6 +2877,7 @@
"--test-launcher-bot-mode",
"--test-launcher-jobs=1",
"--gtest_filter=VrBrowserTest*",
"--enable-pixel-output-in-tests",
"--gtest_also_run_disabled_tests"
],
"name": "vr_browser_tests",
......
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