1 // Copyright 2018 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 
5 #include "base/environment.h"
6 #include "base/files/file.h"
7 #include "base/run_loop.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "base/threading/thread_restrictions.h"
10 #include "chrome/browser/vr/test/mock_xr_device_hook_base.h"
11 #include "chrome/browser/vr/test/multi_class_browser_test.h"
12 #include "chrome/browser/vr/test/ui_utils.h"
13 #include "chrome/browser/vr/test/webxr_vr_browser_test.h"
14 
15 #include <memory>
16 
17 namespace vr {
18 
19 class MyXRMock : public MockXRDeviceHookBase {
20  public:
21   void OnFrameSubmitted(
22       device_test::mojom::SubmittedFrameDataPtr frame_data,
23       device_test::mojom::XRTestHook::OnFrameSubmittedCallback callback) final;
24 
WaitForFrame()25   void WaitForFrame() {
26     DCHECK(!wait_loop_);
27     if (num_submitted_frames_ > 0)
28       return;
29 
30     wait_loop_ = new base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed);
31     wait_loop_->Run();
32     delete wait_loop_;
33     wait_loop_ = nullptr;
34   }
35 
36   device_test::mojom::ColorPtr last_submitted_color_ = {};
37   unsigned int num_submitted_frames_ = 0;
38 
39  private:
40   base::RunLoop* wait_loop_ = nullptr;
41 };
42 
OnFrameSubmitted(device_test::mojom::SubmittedFrameDataPtr frame_data,device_test::mojom::XRTestHook::OnFrameSubmittedCallback callback)43 void MyXRMock::OnFrameSubmitted(
44     device_test::mojom::SubmittedFrameDataPtr frame_data,
45     device_test::mojom::XRTestHook::OnFrameSubmittedCallback callback) {
46   last_submitted_color_ = std::move(frame_data->color);
47   num_submitted_frames_++;
48 
49   if (wait_loop_) {
50     wait_loop_->Quit();
51   }
52 
53   std::move(callback).Run();
54 }
55 
56 // Pixel test for WebXR - start presentation, submit frames, get data back
57 // out. Validates that a pixel was rendered with the expected color.
TestPresentationPixelsImpl(WebXrVrBrowserTestBase * t,std::string filename)58 void TestPresentationPixelsImpl(WebXrVrBrowserTestBase* t,
59                                 std::string filename) {
60   // Disable frame-timeout UI to test what WebXR renders.
61   UiUtils::DisableFrameTimeoutForTesting();
62   MyXRMock my_mock;
63 
64   // Load the test page, and enter presentation.
65   t->LoadFileAndAwaitInitialization(filename);
66   t->EnterSessionWithUserGestureOrFail();
67 
68   // Wait for JavaScript to submit at least one frame.
69   ASSERT_TRUE(
70       t->PollJavaScriptBoolean("hasPresentedFrame", t->kPollTimeoutMedium))
71       << "No frame submitted";
72 
73   // Tell JavaScript that it is done with the test.
74   t->ExecuteStepAndWait("finishTest()");
75   t->EndTest();
76 
77   my_mock.WaitForFrame();
78 
79   auto expected = device_test::mojom::Color::New(0, 0, 255, 255);
80   EXPECT_EQ(expected->r, my_mock.last_submitted_color_->r)
81       << "Red channel of submitted color does not match expectation";
82   EXPECT_EQ(expected->g, my_mock.last_submitted_color_->g)
83       << "Green channel of submitted color does not match expectation";
84   EXPECT_EQ(expected->b, my_mock.last_submitted_color_->b)
85       << "Blue channel of submitted color does not match expectation";
86   EXPECT_EQ(expected->a, my_mock.last_submitted_color_->a)
87       << "Alpha channel of submitted color does not match expectation";
88 }
89 
WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestPresentationPixels)90 WEBXR_VR_ALL_RUNTIMES_BROWSER_TEST_F(TestPresentationPixels) {
91   TestPresentationPixelsImpl(t, "test_webxr_pixels");
92 }
93 
94 }  // namespace vr
95