1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #if SK_BUILD_FOR_MAC || SK_BUILD_FOR_UNIX || SK_BUILD_FOR_ANDROID 9 # include <unistd.h> 10 # include <sys/time.h> 11 # include <dirent.h> 12 #endif 13 14 #if SK_BUILD_FOR_MAC || SK_BUILD_FOR_UNIX 15 # include <glob.h> 16 #endif 17 18 #if SK_BUILD_FOR_MAC 19 # include <sys/syslimits.h> // PATH_MAX is here for Macs 20 #endif 21 22 #if SK_BUILD_FOR_WIN32 23 # include <windows.h> 24 #endif 25 26 #include <stdlib.h> 27 #include <time.h> 28 #include "SkOSFile.h" 29 #include "skpdiff_util.h" 30 31 #if SK_SUPPORT_OPENCL 32 const char* cl_error_to_string(cl_int err) { 33 switch (err) { 34 case CL_SUCCESS: return "CL_SUCCESS"; 35 case CL_DEVICE_NOT_FOUND: return "CL_DEVICE_NOT_FOUND"; 36 case CL_DEVICE_NOT_AVAILABLE: return "CL_DEVICE_NOT_AVAILABLE"; 37 case CL_COMPILER_NOT_AVAILABLE: return "CL_COMPILER_NOT_AVAILABLE"; 38 case CL_MEM_OBJECT_ALLOCATION_FAILURE: return "CL_MEM_OBJECT_ALLOCATION_FAILURE"; 39 case CL_OUT_OF_RESOURCES: return "CL_OUT_OF_RESOURCES"; 40 case CL_OUT_OF_HOST_MEMORY: return "CL_OUT_OF_HOST_MEMORY"; 41 case CL_PROFILING_INFO_NOT_AVAILABLE: return "CL_PROFILING_INFO_NOT_AVAILABLE"; 42 case CL_MEM_COPY_OVERLAP: return "CL_MEM_COPY_OVERLAP"; 43 case CL_IMAGE_FORMAT_MISMATCH: return "CL_IMAGE_FORMAT_MISMATCH"; 44 case CL_IMAGE_FORMAT_NOT_SUPPORTED: return "CL_IMAGE_FORMAT_NOT_SUPPORTED"; 45 case CL_BUILD_PROGRAM_FAILURE: return "CL_BUILD_PROGRAM_FAILURE"; 46 case CL_MAP_FAILURE: return "CL_MAP_FAILURE"; 47 case CL_INVALID_VALUE: return "CL_INVALID_VALUE"; 48 case CL_INVALID_DEVICE_TYPE: return "CL_INVALID_DEVICE_TYPE"; 49 case CL_INVALID_PLATFORM: return "CL_INVALID_PLATFORM"; 50 case CL_INVALID_DEVICE: return "CL_INVALID_DEVICE"; 51 case CL_INVALID_CONTEXT: return "CL_INVALID_CONTEXT"; 52 case CL_INVALID_QUEUE_PROPERTIES: return "CL_INVALID_QUEUE_PROPERTIES"; 53 case CL_INVALID_COMMAND_QUEUE: return "CL_INVALID_COMMAND_QUEUE"; 54 case CL_INVALID_HOST_PTR: return "CL_INVALID_HOST_PTR"; 55 case CL_INVALID_MEM_OBJECT: return "CL_INVALID_MEM_OBJECT"; 56 case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR: return "CL_INVALID_IMAGE_FORMAT_DESCRIPTOR"; 57 case CL_INVALID_IMAGE_SIZE: return "CL_INVALID_IMAGE_SIZE"; 58 case CL_INVALID_SAMPLER: return "CL_INVALID_SAMPLER"; 59 case CL_INVALID_BINARY: return "CL_INVALID_BINARY"; 60 case CL_INVALID_BUILD_OPTIONS: return "CL_INVALID_BUILD_OPTIONS"; 61 case CL_INVALID_PROGRAM: return "CL_INVALID_PROGRAM"; 62 case CL_INVALID_PROGRAM_EXECUTABLE: return "CL_INVALID_PROGRAM_EXECUTABLE"; 63 case CL_INVALID_KERNEL_NAME: return "CL_INVALID_KERNEL_NAME"; 64 case CL_INVALID_KERNEL_DEFINITION: return "CL_INVALID_KERNEL_DEFINITION"; 65 case CL_INVALID_KERNEL: return "CL_INVALID_KERNEL"; 66 case CL_INVALID_ARG_INDEX: return "CL_INVALID_ARG_INDEX"; 67 case CL_INVALID_ARG_VALUE: return "CL_INVALID_ARG_VALUE"; 68 case CL_INVALID_ARG_SIZE: return "CL_INVALID_ARG_SIZE"; 69 case CL_INVALID_KERNEL_ARGS: return "CL_INVALID_KERNEL_ARGS"; 70 case CL_INVALID_WORK_DIMENSION: return "CL_INVALID_WORK_DIMENSION"; 71 case CL_INVALID_WORK_GROUP_SIZE: return "CL_INVALID_WORK_GROUP_SIZE"; 72 case CL_INVALID_WORK_ITEM_SIZE: return "CL_INVALID_WORK_ITEM_SIZE"; 73 case CL_INVALID_GLOBAL_OFFSET: return "CL_INVALID_GLOBAL_OFFSET"; 74 case CL_INVALID_EVENT_WAIT_LIST: return "CL_INVALID_EVENT_WAIT_LIST"; 75 case CL_INVALID_EVENT: return "CL_INVALID_EVENT"; 76 case CL_INVALID_OPERATION: return "CL_INVALID_OPERATION"; 77 case CL_INVALID_GL_OBJECT: return "CL_INVALID_GL_OBJECT"; 78 case CL_INVALID_BUFFER_SIZE: return "CL_INVALID_BUFFER_SIZE"; 79 case CL_INVALID_MIP_LEVEL: return "CL_INVALID_MIP_LEVEL"; 80 default: return "UNKNOWN"; 81 } 82 return "UNKNOWN"; 83 } 84 #endif 85 86 // TODO refactor BenchTimer to be used here 87 double get_seconds() { 88 #if SK_BUILD_FOR_WIN32 89 LARGE_INTEGER currentTime; 90 LARGE_INTEGER frequency; 91 QueryPerformanceCounter(¤tTime); 92 QueryPerformanceFrequency(&frequency); 93 return (double)currentTime.QuadPart / (double)frequency.QuadPart; 94 #elif _POSIX_TIMERS > 0 && defined(CLOCK_REALTIME) 95 struct timespec currentTime; 96 clock_gettime(CLOCK_REALTIME, ¤tTime); 97 return currentTime.tv_sec + (double)currentTime.tv_nsec / 1e9; 98 #elif SK_BUILD_FOR_MAC || SK_BUILD_FOR_UNIX || SK_BUILD_FOR_ANDROID 99 struct timeval currentTime; 100 gettimeofday(¤tTime, NULL); 101 return currentTime.tv_sec + (double)currentTime.tv_usec / 1e6; 102 #else 103 return clock() / (double)CLOCKS_PER_SEC; 104 #endif 105 } 106 107 bool get_directory(const char path[], SkTArray<SkString>* entries) { 108 #if SK_BUILD_FOR_MAC || SK_BUILD_FOR_UNIX || SK_BUILD_FOR_ANDROID 109 // Open the directory and check for success 110 DIR* dir = opendir(path); 111 if (NULL == dir) { 112 return false; 113 } 114 115 // Loop through dir entries until there are none left (i.e. readdir returns NULL) 116 struct dirent* entry; 117 while ((entry = readdir(dir))) { 118 // dirent only gives relative paths, we need to join them to the base path to check if they 119 // are directories. 120 SkString joinedPath = SkOSPath::SkPathJoin(path, entry->d_name); 121 122 // We only care about files 123 if (!sk_isdir(joinedPath.c_str())) { 124 entries->push_back(SkString(entry->d_name)); 125 } 126 } 127 128 closedir(dir); 129 130 return true; 131 #elif SK_BUILD_FOR_WIN32 132 char pathDirGlob[MAX_PATH]; 133 char pathLength = strlen(path); 134 strncpy(pathDirGlob, path, pathLength); 135 136 if (path[pathLength - 1] == '/' || path[pathLength - 1] == '\\') { 137 SkASSERT(pathLength + 2 <= MAX_PATH); 138 pathDirGlob[pathLength] = '*'; 139 pathDirGlob[pathLength + 1] = '\0'; 140 } else { 141 SkASSERT(pathLength + 3 <= MAX_PATH); 142 pathDirGlob[pathLength] = '\\'; 143 pathDirGlob[pathLength + 1] = '*'; 144 pathDirGlob[pathLength + 2] = '\0'; 145 } 146 147 WIN32_FIND_DATA findFileData; 148 HANDLE hFind = FindFirstFile(pathDirGlob, &findFileData); 149 if (INVALID_HANDLE_VALUE == hFind) { 150 return false; 151 } 152 153 do { 154 if ((findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { 155 entries->push_back(SkString(findFileData.cFileName)); 156 } 157 } while (FindNextFile(hFind, &findFileData) != 0); 158 159 FindClose(hFind); 160 return true; 161 #else 162 return false; 163 #endif 164 } 165 166 bool glob_files(const char globPattern[], SkTArray<SkString>* entries) { 167 #if SK_BUILD_FOR_MAC || SK_BUILD_FOR_UNIX 168 // TODO Make sure this works on windows. This may require use of FindNextFile windows function. 169 glob_t globBuffer; 170 if (glob(globPattern, 0, NULL, &globBuffer) != 0) { 171 return false; 172 } 173 174 // Note these paths are in sorted order by default according to http://linux.die.net/man/3/glob 175 // Check under the flag GLOB_NOSORT 176 char** paths = globBuffer.gl_pathv; 177 while(NULL != *paths) { 178 entries->push_back(SkString(*paths)); 179 paths++; 180 } 181 182 globfree(&globBuffer); 183 184 return true; 185 #else 186 return false; 187 #endif 188 } 189 190 SkString get_absolute_path(const SkString& path) { 191 #if SK_BUILD_FOR_MAC || SK_BUILD_FOR_UNIX || SK_BUILD_FOR_ANDROID 192 SkString fullPath(PATH_MAX + 1); 193 if (realpath(path.c_str(), fullPath.writable_str()) == NULL) { 194 fullPath.reset(); 195 } 196 return fullPath; 197 #elif SK_BUILD_FOR_WIN32 198 SkString fullPath(MAX_PATH); 199 if (_fullpath(fullPath.writable_str(), path.c_str(), MAX_PATH) == NULL) { 200 fullPath.reset(); 201 } 202 return fullPath; 203 #else 204 return SkString(); 205 #endif 206 } 207