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