1 // Copyright (c) 2012 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 "gpu/config/gpu_test_config.h"
6 
7 #include <stddef.h>
8 #include <stdint.h>
9 
10 #include "base/command_line.h"
11 #include "base/logging.h"
12 #include "base/system/sys_info.h"
13 #include "build/build_config.h"
14 #include "build/chromeos_buildflags.h"
15 #include "gpu/config/gpu_info.h"
16 #include "gpu/config/gpu_info_collector.h"
17 #include "gpu/config/gpu_test_expectations_parser.h"
18 #include "ui/gl/gl_utils.h"
19 
20 #if defined(OS_WIN)
21 #include "base/win/windows_version.h"
22 #endif
23 
24 namespace gpu {
25 
26 namespace {
27 
GetCurrentOS()28 GPUTestConfig::OS GetCurrentOS() {
29 #if BUILDFLAG(IS_ASH)
30   return GPUTestConfig::kOsChromeOS;
31 #elif defined(OS_LINUX) || defined(OS_BSD)
32   return GPUTestConfig::kOsLinux;
33 #elif defined(OS_WIN)
34   int32_t major_version = 0;
35   int32_t minor_version = 0;
36   int32_t bugfix_version = 0;
37   base::SysInfo::OperatingSystemVersionNumbers(
38       &major_version, &minor_version, &bugfix_version);
39   if (major_version == 5)
40     return GPUTestConfig::kOsWinXP;
41   if (major_version == 6 && minor_version == 0)
42     return GPUTestConfig::kOsWinVista;
43   if (major_version == 6 && minor_version == 1)
44     return GPUTestConfig::kOsWin7;
45   if (major_version == 6 && (minor_version == 2 || minor_version == 3))
46     return GPUTestConfig::kOsWin8;
47   if (major_version == 10)
48     return GPUTestConfig::kOsWin10;
49   return GPUTestConfig::kOsUnknown;
50 #elif defined(OS_MAC)
51   int32_t major_version = 0;
52   int32_t minor_version = 0;
53   int32_t bugfix_version = 0;
54   base::SysInfo::OperatingSystemVersionNumbers(
55       &major_version, &minor_version, &bugfix_version);
56   switch (major_version) {
57     case 10:
58       switch (minor_version) {
59         case 5:
60           return GPUTestConfig::kOsMacLeopard;
61         case 6:
62           return GPUTestConfig::kOsMacSnowLeopard;
63         case 7:
64           return GPUTestConfig::kOsMacLion;
65         case 8:
66           return GPUTestConfig::kOsMacMountainLion;
67         case 9:
68           return GPUTestConfig::kOsMacMavericks;
69         case 10:
70           return GPUTestConfig::kOsMacYosemite;
71         case 11:
72           return GPUTestConfig::kOsMacElCapitan;
73         case 12:
74           return GPUTestConfig::kOsMacSierra;
75         case 13:
76           return GPUTestConfig::kOsMacHighSierra;
77         case 14:
78           return GPUTestConfig::kOsMacMojave;
79         case 15:
80           return GPUTestConfig::kOsMacCatalina;
81       }
82       break;
83     case 11:
84       switch (minor_version) {
85         case 0:
86           return GPUTestConfig::kOsMacBigSur;
87       }
88       break;
89   }
90   return GPUTestConfig::kOsUnknown;
91 #elif defined(OS_ANDROID)
92   return GPUTestConfig::kOsAndroid;
93 #elif defined(OS_FUCHSIA)
94   return GPUTestConfig::kOsFuchsia;
95 #else
96 #error "unknown os"
97 #endif
98 }
99 
100 }  // namespace anonymous
101 
GPUTestConfig()102 GPUTestConfig::GPUTestConfig()
103     : os_(kOsUnknown),
104       gpu_device_id_(0),
105       build_type_(kBuildTypeUnknown),
106       api_(kAPIUnknown),
107       command_decoder_(kCommandDecoderUnknown) {}
108 
109 GPUTestConfig::GPUTestConfig(const GPUTestConfig& other) = default;
110 
111 GPUTestConfig::~GPUTestConfig() = default;
112 
set_os(int32_t os)113 void GPUTestConfig::set_os(int32_t os) {
114   DCHECK_EQ(0, os & ~(kOsAndroid | kOsWin | kOsMac | kOsLinux | kOsChromeOS |
115                       kOsFuchsia));
116   os_ = os;
117 }
118 
AddGPUVendor(uint32_t gpu_vendor)119 void GPUTestConfig::AddGPUVendor(uint32_t gpu_vendor) {
120   DCHECK_NE(0u, gpu_vendor);
121   for (size_t i = 0; i < gpu_vendor_.size(); ++i)
122     DCHECK_NE(gpu_vendor_[i], gpu_vendor);
123   gpu_vendor_.push_back(gpu_vendor);
124 }
125 
set_gpu_device_id(uint32_t id)126 void GPUTestConfig::set_gpu_device_id(uint32_t id) {
127   gpu_device_id_ = id;
128 }
129 
set_build_type(int32_t build_type)130 void GPUTestConfig::set_build_type(int32_t build_type) {
131   DCHECK_EQ(0, build_type & ~(kBuildTypeRelease | kBuildTypeDebug));
132   build_type_ = build_type;
133 }
134 
set_api(int32_t api)135 void GPUTestConfig::set_api(int32_t api) {
136   DCHECK_EQ(0, api & ~(kAPID3D9 | kAPID3D11 | kAPIGLDesktop | kAPIGLES));
137   api_ = api;
138 }
139 
set_command_decoder(int32_t command_decoder)140 void GPUTestConfig::set_command_decoder(int32_t command_decoder) {
141   DCHECK_EQ(0, command_decoder &
142                    ~(kCommandDecoderPassthrough | kCommandDecoderValidating));
143   command_decoder_ = command_decoder;
144 }
145 
IsValid() const146 bool GPUTestConfig::IsValid() const {
147   if (gpu_device_id_ != 0 && (gpu_vendor_.size() != 1 || gpu_vendor_[0] == 0))
148     return false;
149   return true;
150 }
151 
OverlapsWith(const GPUTestConfig & config) const152 bool GPUTestConfig::OverlapsWith(const GPUTestConfig& config) const {
153   DCHECK(IsValid());
154   DCHECK(config.IsValid());
155   if (config.os_ != kOsUnknown && os_ != kOsUnknown &&
156       (os_ & config.os_) == 0)
157     return false;
158   if (config.gpu_vendor_.size() > 0 && gpu_vendor_.size() > 0) {
159     bool shared = false;
160     for (size_t i = 0; i < config.gpu_vendor_.size() && !shared; ++i) {
161       for (size_t j = 0; j < gpu_vendor_.size(); ++j) {
162         if (config.gpu_vendor_[i] == gpu_vendor_[j]) {
163           shared = true;
164           break;
165         }
166       }
167     }
168     if (!shared)
169       return false;
170   }
171   if (config.gpu_device_id_ != 0 && gpu_device_id_ != 0 &&
172       gpu_device_id_ != config.gpu_device_id_)
173     return false;
174   if (config.build_type_ != kBuildTypeUnknown &&
175       build_type_ != kBuildTypeUnknown &&
176       (build_type_ & config.build_type_) == 0)
177     return false;
178   if (config.api() != kAPIUnknown && api_ != kAPIUnknown && api_ != config.api_)
179     return false;
180   return true;
181 }
182 
ClearGPUVendor()183 void GPUTestConfig::ClearGPUVendor() {
184   gpu_vendor_.clear();
185 }
186 
187 GPUTestBotConfig::~GPUTestBotConfig() = default;
188 
AddGPUVendor(uint32_t gpu_vendor)189 void GPUTestBotConfig::AddGPUVendor(uint32_t gpu_vendor) {
190   DCHECK_EQ(0u, GPUTestConfig::gpu_vendor().size());
191   GPUTestConfig::AddGPUVendor(gpu_vendor);
192 }
193 
SetGPUInfo(const GPUInfo & gpu_info)194 bool GPUTestBotConfig::SetGPUInfo(const GPUInfo& gpu_info) {
195   if (gpu_info.gpu.vendor_id == 0)
196     return false;
197 #if !defined(OS_MAC)
198   // ARM-based Mac GPUs do not have valid PCI device IDs.
199   // https://crbug.com/1110421
200   if (gpu_info.gpu.device_id == 0)
201     return false;
202 #endif
203   ClearGPUVendor();
204   AddGPUVendor(gpu_info.gpu.vendor_id);
205   set_gpu_device_id(gpu_info.gpu.device_id);
206   if (gpu_info.passthrough_cmd_decoder) {
207     set_command_decoder(kCommandDecoderPassthrough);
208   } else {
209     set_command_decoder(kCommandDecoderValidating);
210   }
211   return true;
212 }
213 
IsValid() const214 bool GPUTestBotConfig::IsValid() const {
215   switch (os()) {
216     case kOsWinXP:
217     case kOsWinVista:
218     case kOsWin7:
219     case kOsWin8:
220     case kOsWin10:
221     case kOsMacLeopard:
222     case kOsMacSnowLeopard:
223     case kOsMacLion:
224     case kOsMacMountainLion:
225     case kOsMacMavericks:
226     case kOsMacYosemite:
227     case kOsMacElCapitan:
228     case kOsMacSierra:
229     case kOsMacHighSierra:
230     case kOsMacMojave:
231     case kOsMacCatalina:
232     case kOsMacBigSur:
233     case kOsLinux:
234     case kOsChromeOS:
235     case kOsAndroid:
236     case kOsFuchsia:
237       break;
238     default:
239       return false;
240   }
241   if (gpu_vendor().size() != 1 || gpu_vendor()[0] == 0)
242     return false;
243   if (!(os() & gpu::GPUTestConfig::kOsMac)) {
244     // ARM-based Mac GPUs do not have valid PCI device IDs.
245     // https://crbug.com/1110421
246     if (gpu_device_id() == 0)
247       return false;
248   }
249   switch (build_type()) {
250     case kBuildTypeRelease:
251     case kBuildTypeDebug:
252       break;
253     default:
254       return false;
255   }
256   return true;
257 }
258 
Matches(const GPUTestConfig & config) const259 bool GPUTestBotConfig::Matches(const GPUTestConfig& config) const {
260   DCHECK(IsValid());
261   DCHECK(config.IsValid());
262   if (config.os() != kOsUnknown && (os() & config.os()) == 0)
263     return false;
264   if (config.gpu_vendor().size() > 0) {
265     bool contained = false;
266     for (size_t i = 0; i < config.gpu_vendor().size(); ++i) {
267       if (config.gpu_vendor()[i] == gpu_vendor()[0]) {
268         contained = true;
269         break;
270       }
271     }
272     if (!contained)
273       return false;
274   }
275   if (config.gpu_device_id() != 0 &&
276       gpu_device_id() != config.gpu_device_id())
277     return false;
278   if (config.build_type() != kBuildTypeUnknown &&
279       (build_type() & config.build_type()) == 0)
280     return false;
281   if (config.api() != 0 && (api() & config.api()) == 0)
282     return false;
283   if (config.command_decoder() != 0 &&
284       command_decoder() != config.command_decoder())
285     return false;
286   return true;
287 }
288 
Matches(const std::string & config_data) const289 bool GPUTestBotConfig::Matches(const std::string& config_data) const {
290   GPUTestExpectationsParser parser;
291   GPUTestConfig config;
292 
293   if (!parser.ParseConfig(config_data, &config))
294     return false;
295   return Matches(config);
296 }
297 
LoadCurrentConfig(const GPUInfo * gpu_info)298 bool GPUTestBotConfig::LoadCurrentConfig(const GPUInfo* gpu_info) {
299   bool rt;
300   if (!gpu_info) {
301 #if defined(OS_ANDROID)
302     // TODO(zmo): Implement this.
303     rt = false;
304 #else
305     GPUInfo my_gpu_info;
306     if (!CollectBasicGraphicsInfo(base::CommandLine::ForCurrentProcess(),
307                                   &my_gpu_info)) {
308       LOG(ERROR) << "Fail to identify GPU";
309       rt = false;
310     } else {
311       rt = SetGPUInfo(my_gpu_info);
312     }
313 #endif  // OS_ANDROID
314   } else {
315     rt = SetGPUInfo(*gpu_info);
316   }
317   set_os(GetCurrentOS());
318   if (os() == kOsUnknown) {
319     LOG(ERROR) << "Unknown OS";
320     rt = false;
321   }
322 #if defined(NDEBUG)
323   set_build_type(kBuildTypeRelease);
324 #else
325   set_build_type(kBuildTypeDebug);
326 #endif
327   return rt;
328 }
329 
330 // static
CurrentConfigMatches(const std::string & config_data)331 bool GPUTestBotConfig::CurrentConfigMatches(const std::string& config_data) {
332   GPUTestBotConfig my_config;
333   if (!my_config.LoadCurrentConfig(nullptr))
334     return false;
335   return my_config.Matches(config_data);
336 }
337 
338 // static
CurrentConfigMatches(const std::vector<std::string> & configs)339 bool GPUTestBotConfig::CurrentConfigMatches(
340     const std::vector<std::string>& configs) {
341   GPUTestBotConfig my_config;
342   if (!my_config.LoadCurrentConfig(nullptr))
343     return false;
344   for (size_t i = 0 ; i < configs.size(); ++i) {
345     if (my_config.Matches(configs[i]))
346       return true;
347   }
348   return false;
349 }
350 
351 // static
GpuBlocklistedOnBot()352 bool GPUTestBotConfig::GpuBlocklistedOnBot() {
353   return false;
354 }
355 
356 }  // namespace gpu
357