• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2019 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 
7 // system_utils: Defines common utility functions
8 
9 #include "util/test_utils.h"
10 
11 #include <EGL/egl.h>
12 #include <EGL/eglext.h>
13 
14 #include <cstring>
15 #include <fstream>
16 #include <iostream>
17 
18 namespace angle
19 {
20 
21 namespace
22 {
DeleteArg(int * argc,char ** argv,int argIndex)23 void DeleteArg(int *argc, char **argv, int argIndex)
24 {
25     // Shift the remainder of the argv list left by one.  Note that argv has (*argc + 1) elements,
26     // the last one always being NULL.  The following loop moves the trailing NULL element as well.
27     for (int index = argIndex; index < *argc; ++index)
28     {
29         argv[index] = argv[index + 1];
30     }
31     (*argc)--;
32 }
33 
GetSingleArg(const char * flag,int * argc,char ** argv,int argIndex,ArgHandling handling)34 const char *GetSingleArg(const char *flag,
35                          int *argc,
36                          char **argv,
37                          int argIndex,
38                          ArgHandling handling)
39 {
40     if (strstr(argv[argIndex], flag) == argv[argIndex])
41     {
42         const char *ptr = argv[argIndex] + strlen(flag);
43 
44         if (*ptr == '=')
45         {
46             if (handling == ArgHandling::Delete)
47             {
48                 DeleteArg(argc, argv, argIndex);
49             }
50             return ptr + 1;
51         }
52 
53         if (*ptr == '\0' && argIndex < *argc - 1)
54         {
55             ptr = argv[argIndex + 1];
56             if (handling == ArgHandling::Delete)
57             {
58                 DeleteArg(argc, argv, argIndex);
59                 DeleteArg(argc, argv, argIndex);
60             }
61             return ptr;
62         }
63     }
64 
65     return nullptr;
66 }
67 
68 using DisplayTypeInfo = std::pair<const char *, EGLint>;
69 
70 const DisplayTypeInfo kDisplayTypes[] = {
71     {"d3d9", EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE},
72     {"d3d11", EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE},
73     {"gl", EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE},
74     {"gles", EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE},
75     {"metal", EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE},
76     {"null", EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE},
77     {"swiftshader", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
78     {"vulkan", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
79     {"vulkan-null", EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE},
80 };
81 }  // anonymous namespace
82 
GetFileSize(const char * filePath,uint32_t * sizeOut)83 bool GetFileSize(const char *filePath, uint32_t *sizeOut)
84 {
85     std::ifstream stream(filePath);
86     if (!stream)
87     {
88         return false;
89     }
90 
91     stream.seekg(0, std::ios::end);
92     *sizeOut = static_cast<uint32_t>(stream.tellg());
93     return true;
94 }
95 
ReadEntireFileToString(const char * filePath,std::string * contentsOut)96 bool ReadEntireFileToString(const char *filePath, std::string *contentsOut)
97 {
98     std::ifstream stream(filePath);
99     if (!stream)
100     {
101         return false;
102     }
103 
104     stream.seekg(0, std::ios::end);
105     contentsOut->reserve(static_cast<unsigned int>(stream.tellg()));
106     stream.seekg(0, std::ios::beg);
107 
108     contentsOut->assign((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
109 
110     return true;
111 }
112 
113 // static
114 Process::~Process() = default;
115 
ProcessHandle()116 ProcessHandle::ProcessHandle() : mProcess(nullptr) {}
117 
ProcessHandle(Process * process)118 ProcessHandle::ProcessHandle(Process *process) : mProcess(process) {}
119 
ProcessHandle(const std::vector<const char * > & args,ProcessOutputCapture captureOutput)120 ProcessHandle::ProcessHandle(const std::vector<const char *> &args,
121                              ProcessOutputCapture captureOutput)
122     : mProcess(LaunchProcess(args, captureOutput))
123 {}
124 
~ProcessHandle()125 ProcessHandle::~ProcessHandle()
126 {
127     reset();
128 }
129 
ProcessHandle(ProcessHandle && other)130 ProcessHandle::ProcessHandle(ProcessHandle &&other) : mProcess(other.mProcess)
131 {
132     other.mProcess = nullptr;
133 }
134 
operator =(ProcessHandle && rhs)135 ProcessHandle &ProcessHandle::operator=(ProcessHandle &&rhs)
136 {
137     std::swap(mProcess, rhs.mProcess);
138     return *this;
139 }
140 
reset()141 void ProcessHandle::reset()
142 {
143     if (mProcess)
144     {
145         delete mProcess;
146         mProcess = nullptr;
147     }
148 }
149 
ParseIntArgWithHandling(const char * flag,int * argc,char ** argv,int argIndex,int * valueOut,ArgHandling handling)150 bool ParseIntArgWithHandling(const char *flag,
151                              int *argc,
152                              char **argv,
153                              int argIndex,
154                              int *valueOut,
155                              ArgHandling handling)
156 {
157     const char *value = GetSingleArg(flag, argc, argv, argIndex, handling);
158     if (!value)
159     {
160         return false;
161     }
162 
163     char *end            = nullptr;
164     const long longValue = strtol(value, &end, 10);
165 
166     if (*end != '\0')
167     {
168         printf("Error parsing integer flag value.\n");
169         exit(EXIT_FAILURE);
170     }
171 
172     if (longValue == LONG_MAX || longValue == LONG_MIN || static_cast<int>(longValue) != longValue)
173     {
174         printf("Overflow when parsing integer flag value.\n");
175         exit(EXIT_FAILURE);
176     }
177 
178     *valueOut = static_cast<int>(longValue);
179     // Note: return value is always false with ArgHandling::Preserve handling
180     return handling == ArgHandling::Delete;
181 }
182 
ParseIntArg(const char * flag,int * argc,char ** argv,int argIndex,int * valueOut)183 bool ParseIntArg(const char *flag, int *argc, char **argv, int argIndex, int *valueOut)
184 {
185     return ParseIntArgWithHandling(flag, argc, argv, argIndex, valueOut, ArgHandling::Delete);
186 }
187 
ParseFlag(const char * flag,int * argc,char ** argv,int argIndex,bool * flagOut)188 bool ParseFlag(const char *flag, int *argc, char **argv, int argIndex, bool *flagOut)
189 {
190     if (strcmp(flag, argv[argIndex]) == 0)
191     {
192         *flagOut = true;
193         DeleteArg(argc, argv, argIndex);
194         return true;
195     }
196     return false;
197 }
198 
ParseStringArg(const char * flag,int * argc,char ** argv,int argIndex,std::string * valueOut)199 bool ParseStringArg(const char *flag, int *argc, char **argv, int argIndex, std::string *valueOut)
200 {
201     const char *value = GetSingleArg(flag, argc, argv, argIndex, ArgHandling::Delete);
202     if (!value)
203     {
204         return false;
205     }
206 
207     *valueOut = value;
208     return true;
209 }
210 
ParseCStringArgWithHandling(const char * flag,int * argc,char ** argv,int argIndex,const char ** valueOut,ArgHandling handling)211 bool ParseCStringArgWithHandling(const char *flag,
212                                  int *argc,
213                                  char **argv,
214                                  int argIndex,
215                                  const char **valueOut,
216                                  ArgHandling handling)
217 {
218     const char *value = GetSingleArg(flag, argc, argv, argIndex, handling);
219     if (!value)
220     {
221         return false;
222     }
223 
224     *valueOut = value;
225     // Note: return value is always false with ArgHandling::Preserve handling
226     return handling == ArgHandling::Delete;
227 }
228 
ParseCStringArg(const char * flag,int * argc,char ** argv,int argIndex,const char ** valueOut)229 bool ParseCStringArg(const char *flag, int *argc, char **argv, int argIndex, const char **valueOut)
230 {
231     return ParseCStringArgWithHandling(flag, argc, argv, argIndex, valueOut, ArgHandling::Delete);
232 }
233 
AddArg(int * argc,char ** argv,const char * arg)234 void AddArg(int *argc, char **argv, const char *arg)
235 {
236     // This unsafe const_cast is necessary to work around gtest limitations.
237     argv[*argc]     = const_cast<char *>(arg);
238     argv[*argc + 1] = nullptr;
239     (*argc)++;
240 }
241 
GetPlatformANGLETypeFromArg(const char * useANGLEArg,uint32_t defaultPlatformType)242 uint32_t GetPlatformANGLETypeFromArg(const char *useANGLEArg, uint32_t defaultPlatformType)
243 {
244     if (!useANGLEArg)
245     {
246         return defaultPlatformType;
247     }
248 
249     for (const DisplayTypeInfo &displayTypeInfo : kDisplayTypes)
250     {
251         if (strcmp(displayTypeInfo.first, useANGLEArg) == 0)
252         {
253             std::cout << "Using ANGLE back-end API: " << displayTypeInfo.first << std::endl;
254             return displayTypeInfo.second;
255         }
256     }
257 
258     std::cout << "Unknown ANGLE back-end API: " << useANGLEArg << std::endl;
259     exit(EXIT_FAILURE);
260 }
261 
GetANGLEDeviceTypeFromArg(const char * useANGLEArg,uint32_t defaultDeviceType)262 uint32_t GetANGLEDeviceTypeFromArg(const char *useANGLEArg, uint32_t defaultDeviceType)
263 {
264     if (useANGLEArg)
265     {
266         if (strcmp(useANGLEArg, "swiftshader") == 0)
267         {
268             return EGL_PLATFORM_ANGLE_DEVICE_TYPE_SWIFTSHADER_ANGLE;
269         }
270         if (strstr(useANGLEArg, "null") != 0)
271         {
272             return EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE;
273         }
274     }
275     return defaultDeviceType;
276 }
277 }  // namespace angle
278