1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // deqp_libtester_main.cpp: Entry point for tester DLL.
7
8 #include <cstdio>
9 #include <iostream>
10
11 #include "angle_deqp_libtester.h"
12 #include "common/angleutils.h"
13 #include "common/system_utils.h"
14 #include "deMath.h"
15 #include "deUniquePtr.hpp"
16 #include "platform/PlatformMethods.h"
17 #include "tcuApp.hpp"
18 #include "tcuCommandLine.hpp"
19 #include "tcuDefs.hpp"
20 #include "tcuPlatform.hpp"
21 #include "tcuRandomOrderExecutor.h"
22 #include "tcuResource.hpp"
23 #include "tcuTestLog.hpp"
24 #include "util/OSWindow.h"
25
26 tcu::Platform *CreateANGLEPlatform(angle::LogErrorFunc logErrorFunc, uint32_t preRotation);
27
28 namespace
29 {
30
31 tcu::Platform *g_platform = nullptr;
32 tcu::CommandLine *g_cmdLine = nullptr;
33 tcu::DirArchive *g_archive = nullptr;
34 tcu::TestLog *g_log = nullptr;
35 tcu::TestContext *g_testCtx = nullptr;
36 tcu::TestPackageRoot *g_root = nullptr;
37 tcu::RandomOrderExecutor *g_executor = nullptr;
38
GetLogFileName(std::string deqpDataDir)39 std::string GetLogFileName(std::string deqpDataDir)
40 {
41 #if (DE_OS == DE_OS_ANDROID)
42 // On Android executable dir is not writable, so use data dir instead
43 return deqpDataDir + "/" + g_cmdLine->getLogFileName();
44 #else
45 return g_cmdLine->getLogFileName();
46 #endif
47 }
48
49 } // anonymous namespace
50
deqp_libtester_init_platform(int argc,const char * argv[],void * logErrorFunc,uint32_t preRotation,bool enableRenderDocCapture)51 ANGLE_LIBTESTER_EXPORT bool deqp_libtester_init_platform(int argc,
52 const char *argv[],
53 void *logErrorFunc,
54 uint32_t preRotation,
55 bool enableRenderDocCapture)
56 {
57 try
58 {
59 #if (DE_OS != DE_OS_WIN32)
60 // Set stdout to line-buffered mode (will be fully buffered by default if stdout is pipe).
61 setvbuf(stdout, DE_NULL, _IOLBF, 4 * 1024);
62 #endif
63 g_platform =
64 CreateANGLEPlatform(reinterpret_cast<angle::LogErrorFunc>(logErrorFunc), preRotation);
65
66 if (!deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST_EVEN))
67 {
68 std::cout << "Failed to set floating point rounding mode." << std::endl;
69 return false;
70 }
71
72 constexpr size_t kMaxDataDirLen = 1000;
73 char deqpDataDir[kMaxDataDirLen];
74 if (!angle::FindTestDataPath(ANGLE_DEQP_DATA_DIR, deqpDataDir, kMaxDataDirLen))
75 {
76 std::cout << "Failed to find dEQP data directory." << std::endl;
77 return false;
78 }
79
80 g_cmdLine = new tcu::CommandLine(argc, argv);
81 g_archive = new tcu::DirArchive(deqpDataDir);
82 g_log = new tcu::TestLog(GetLogFileName(deqpDataDir).c_str(), g_cmdLine->getLogFlags());
83 g_testCtx = new tcu::TestContext(*g_platform, *g_archive, *g_log, *g_cmdLine, DE_NULL);
84 g_root = new tcu::TestPackageRoot(*g_testCtx, tcu::TestPackageRegistry::getSingleton());
85 g_executor = new tcu::RandomOrderExecutor(*g_root, *g_testCtx, enableRenderDocCapture);
86 }
87 catch (const std::exception &e)
88 {
89 tcu::die("%s", e.what());
90 return false;
91 }
92
93 return true;
94 }
95
96 // Exported to the tester app.
deqp_libtester_main(int argc,const char * argv[])97 ANGLE_LIBTESTER_EXPORT int deqp_libtester_main(int argc, const char *argv[])
98 {
99 if (!deqp_libtester_init_platform(argc, argv, nullptr, 0, false))
100 {
101 tcu::die("Could not initialize the dEQP platform");
102 }
103
104 try
105 {
106 de::UniquePtr<tcu::App> app(new tcu::App(*g_platform, *g_archive, *g_log, *g_cmdLine));
107
108 // Main loop.
109 for (;;)
110 {
111 if (!app->iterate())
112 break;
113 }
114 }
115 catch (const std::exception &e)
116 {
117 deqp_libtester_shutdown_platform();
118 tcu::die("%s", e.what());
119 }
120
121 deqp_libtester_shutdown_platform();
122 return 0;
123 }
124
deqp_libtester_shutdown_platform()125 ANGLE_LIBTESTER_EXPORT void deqp_libtester_shutdown_platform()
126 {
127 delete g_executor;
128 g_executor = nullptr;
129 delete g_root;
130 g_root = nullptr;
131 delete g_testCtx;
132 g_testCtx = nullptr;
133 delete g_log;
134 g_log = nullptr;
135 delete g_archive;
136 g_archive = nullptr;
137 delete g_cmdLine;
138 g_cmdLine = nullptr;
139 delete g_platform;
140 g_platform = nullptr;
141 }
142
deqp_libtester_run(const char * caseName)143 ANGLE_LIBTESTER_EXPORT dEQPTestResult deqp_libtester_run(const char *caseName)
144 {
145 const char *emptyString = "";
146 if (g_platform == nullptr)
147 {
148 tcu::die("Failed to initialize platform.");
149 }
150
151 try
152 {
153 // Poll platform events
154 const bool platformOk = g_platform->processEvents();
155
156 if (platformOk)
157 {
158 const tcu::TestStatus &result = g_executor->execute(caseName);
159 switch (result.getCode())
160 {
161 case QP_TEST_RESULT_PASS:
162 return dEQPTestResult::Pass;
163 case QP_TEST_RESULT_NOT_SUPPORTED:
164 std::cout << "Not supported! " << result.getDescription() << std::endl;
165 return dEQPTestResult::NotSupported;
166 case QP_TEST_RESULT_QUALITY_WARNING:
167 std::cout << "Quality warning! " << result.getDescription() << std::endl;
168 return dEQPTestResult::Pass;
169 case QP_TEST_RESULT_COMPATIBILITY_WARNING:
170 std::cout << "Compatiblity warning! " << result.getDescription() << std::endl;
171 return dEQPTestResult::Pass;
172 default:
173 return dEQPTestResult::Fail;
174 }
175 }
176 else
177 {
178 std::cout << "Aborted test!" << std::endl;
179 }
180 }
181 catch (const std::exception &e)
182 {
183 std::cout << "Exception running test: " << e.what() << std::endl;
184 return dEQPTestResult::Exception;
185 }
186
187 return dEQPTestResult::Fail;
188 }
189