1 // 2 // Copyright (c) 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 // Platform.h: The public interface ANGLE exposes to the API layer, for 7 // doing platform-specific tasks like gathering data, or for tracing. 8 9 #ifndef ANGLE_PLATFORM_H 10 #define ANGLE_PLATFORM_H 11 12 #include <stdint.h> 13 #include <array> 14 15 #define EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX 0x3482 16 17 #if defined(_WIN32) 18 # if !defined(LIBANGLE_IMPLEMENTATION) 19 # define ANGLE_PLATFORM_EXPORT __declspec(dllimport) 20 # else 21 # define ANGLE_PLATFORM_EXPORT __declspec(dllexport) 22 # endif 23 #elif defined(__GNUC__) || defined(__clang__) 24 # define ANGLE_PLATFORM_EXPORT __attribute__((visibility ("default"))) 25 #endif 26 #if !defined(ANGLE_PLATFORM_EXPORT) 27 # define ANGLE_PLATFORM_EXPORT 28 #endif 29 30 #if defined(_WIN32) 31 # define ANGLE_APIENTRY __stdcall 32 #else 33 # define ANGLE_APIENTRY 34 #endif 35 36 namespace angle 37 { 38 struct WorkaroundsD3D; 39 struct FeaturesVk; 40 using TraceEventHandle = uint64_t; 41 using EGLDisplayType = void *; 42 struct PlatformMethods; 43 44 // Use a C-like API to not trigger undefined calling behaviour. 45 // Avoid using decltype here to work around sanitizer limitations. 46 // TODO(jmadill): Use decltype here if/when UBSAN is fixed. 47 48 // System -------------------------------------------------------------- 49 50 // Wall clock time in seconds since the epoch. 51 // TODO(jmadill): investigate using an ANGLE internal time library 52 using CurrentTimeFunc = double (*)(PlatformMethods *platform); 53 inline double DefaultCurrentTime(PlatformMethods *platform) 54 { 55 return 0.0; 56 } 57 58 // Monotonically increasing time in seconds from an arbitrary fixed point in the past. 59 // This function is expected to return at least millisecond-precision values. For this reason, 60 // it is recommended that the fixed point be no further in the past than the epoch. 61 using MonotonicallyIncreasingTimeFunc = double (*)(PlatformMethods *platform); 62 inline double DefaultMonotonicallyIncreasingTime(PlatformMethods *platform) 63 { 64 return 0.0; 65 } 66 67 // Logging ------------------------------------------------------------ 68 69 // Log an error message within the platform implementation. 70 using LogErrorFunc = void (*)(PlatformMethods *platform, const char *errorMessage); 71 inline void DefaultLogError(PlatformMethods *platform, const char *errorMessage) 72 { 73 } 74 75 // Log a warning message within the platform implementation. 76 using LogWarningFunc = void (*)(PlatformMethods *platform, const char *warningMessage); 77 inline void DefaultLogWarning(PlatformMethods *platform, const char *warningMessage) 78 { 79 } 80 81 // Log an info message within the platform implementation. 82 using LogInfoFunc = void (*)(PlatformMethods *platform, const char *infoMessage); 83 inline void DefaultLogInfo(PlatformMethods *platform, const char *infoMessage) 84 { 85 } 86 87 // Tracing -------- 88 89 // Get a pointer to the enabled state of the given trace category. The 90 // embedder can dynamically change the enabled state as trace event 91 // recording is started and stopped by the application. Only long-lived 92 // literal strings should be given as the category name. The implementation 93 // expects the returned pointer to be held permanently in a local static. If 94 // the unsigned char is non-zero, tracing is enabled. If tracing is enabled, 95 // addTraceEvent is expected to be called by the trace event macros. 96 using GetTraceCategoryEnabledFlagFunc = const unsigned char *(*)(PlatformMethods *platform, 97 const char *categoryName); 98 inline const unsigned char *DefaultGetTraceCategoryEnabledFlag(PlatformMethods *platform, 99 const char *categoryName) 100 { 101 return nullptr; 102 } 103 104 // 105 // Add a trace event to the platform tracing system. Depending on the actual 106 // enabled state, this event may be recorded or dropped. 107 // - phase specifies the type of event: 108 // - BEGIN ('B'): Marks the beginning of a scoped event. 109 // - END ('E'): Marks the end of a scoped event. 110 // - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't 111 // need a matching END event. Instead, at the end of the scope, 112 // updateTraceEventDuration() must be called with the TraceEventHandle 113 // returned from addTraceEvent(). 114 // - INSTANT ('I'): Standalone, instantaneous event. 115 // - START ('S'): Marks the beginning of an asynchronous event (the end 116 // event can occur in a different scope or thread). The id parameter is 117 // used to match START/FINISH pairs. 118 // - FINISH ('F'): Marks the end of an asynchronous event. 119 // - COUNTER ('C'): Used to trace integer quantities that change over 120 // time. The argument values are expected to be of type int. 121 // - METADATA ('M'): Reserved for internal use. 122 // - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag. 123 // - name is the name of the event. Also used to match BEGIN/END and 124 // START/FINISH pairs. 125 // - id optionally allows events of the same name to be distinguished from 126 // each other. For example, to trace the construction and destruction of 127 // objects, specify the pointer as the id parameter. 128 // - timestamp should be a time value returned from monotonicallyIncreasingTime. 129 // - numArgs specifies the number of elements in argNames, argTypes, and 130 // argValues. 131 // - argNames is the array of argument names. Use long-lived literal strings 132 // or specify the COPY flag. 133 // - argTypes is the array of argument types: 134 // - BOOL (1): bool 135 // - UINT (2): unsigned long long 136 // - INT (3): long long 137 // - DOUBLE (4): double 138 // - POINTER (5): void* 139 // - STRING (6): char* (long-lived null-terminated char* string) 140 // - COPY_STRING (7): char* (temporary null-terminated char* string) 141 // - CONVERTABLE (8): WebConvertableToTraceFormat 142 // - argValues is the array of argument values. Each value is the unsigned 143 // long long member of a union of all supported types. 144 // - flags can be 0 or one or more of the following, ORed together: 145 // - COPY (0x1): treat all strings (name, argNames and argValues of type 146 // string) as temporary so that they will be copied by addTraceEvent. 147 // - HAS_ID (0x2): use the id argument to uniquely identify the event for 148 // matching with other events of the same name. 149 // - MANGLE_ID (0x4): specify this flag if the id parameter is the value 150 // of a pointer. 151 using AddTraceEventFunc = angle::TraceEventHandle (*)(PlatformMethods *platform, 152 char phase, 153 const unsigned char *categoryEnabledFlag, 154 const char *name, 155 unsigned long long id, 156 double timestamp, 157 int numArgs, 158 const char **argNames, 159 const unsigned char *argTypes, 160 const unsigned long long *argValues, 161 unsigned char flags); 162 inline angle::TraceEventHandle DefaultAddTraceEvent(PlatformMethods *platform, 163 char phase, 164 const unsigned char *categoryEnabledFlag, 165 const char *name, 166 unsigned long long id, 167 double timestamp, 168 int numArgs, 169 const char **argNames, 170 const unsigned char *argTypes, 171 const unsigned long long *argValues, 172 unsigned char flags) 173 { 174 return 0; 175 } 176 177 // Set the duration field of a COMPLETE trace event. 178 using UpdateTraceEventDurationFunc = void (*)(PlatformMethods *platform, 179 const unsigned char *categoryEnabledFlag, 180 const char *name, 181 angle::TraceEventHandle eventHandle); 182 inline void DefaultUpdateTraceEventDuration(PlatformMethods *platform, 183 const unsigned char *categoryEnabledFlag, 184 const char *name, 185 angle::TraceEventHandle eventHandle) 186 { 187 } 188 189 // Callbacks for reporting histogram data. 190 // CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50 191 // would do. 192 using HistogramCustomCountsFunc = void (*)(PlatformMethods *platform, 193 const char *name, 194 int sample, 195 int min, 196 int max, 197 int bucketCount); 198 inline void DefaultHistogramCustomCounts(PlatformMethods *platform, 199 const char *name, 200 int sample, 201 int min, 202 int max, 203 int bucketCount) 204 { 205 } 206 // Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample 207 // value. 208 using HistogramEnumerationFunc = void (*)(PlatformMethods *platform, 209 const char *name, 210 int sample, 211 int boundaryValue); 212 inline void DefaultHistogramEnumeration(PlatformMethods *platform, 213 const char *name, 214 int sample, 215 int boundaryValue) 216 { 217 } 218 // Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets. 219 using HistogramSparseFunc = void (*)(PlatformMethods *platform, const char *name, int sample); 220 inline void DefaultHistogramSparse(PlatformMethods *platform, const char *name, int sample) 221 { 222 } 223 // Boolean histograms track two-state variables. 224 using HistogramBooleanFunc = void (*)(PlatformMethods *platform, const char *name, bool sample); 225 inline void DefaultHistogramBoolean(PlatformMethods *platform, const char *name, bool sample) 226 { 227 } 228 229 // Allows us to programatically override ANGLE's default workarounds for testing purposes. 230 using OverrideWorkaroundsD3DFunc = void (*)(PlatformMethods *platform, 231 angle::WorkaroundsD3D *workaroundsD3D); 232 inline void DefaultOverrideWorkaroundsD3D(PlatformMethods *platform, 233 angle::WorkaroundsD3D *workaroundsD3D) 234 { 235 } 236 237 using OverrideFeaturesVkFunc = void (*)(PlatformMethods *platform, 238 angle::FeaturesVk *workaroundsVulkan); 239 inline void DefaultOverrideFeaturesVk(PlatformMethods *platform, 240 angle::FeaturesVk *workaroundsVulkan) 241 { 242 } 243 244 // Callback on a successful program link with the program binary. Can be used to store 245 // shaders to disk. Keys are a 160-bit SHA-1 hash. 246 using ProgramKeyType = std::array<uint8_t, 20>; 247 using CacheProgramFunc = void (*)(PlatformMethods *platform, 248 const ProgramKeyType &key, 249 size_t programSize, 250 const uint8_t *programBytes); 251 inline void DefaultCacheProgram(PlatformMethods *platform, 252 const ProgramKeyType &key, 253 size_t programSize, 254 const uint8_t *programBytes) 255 { 256 } 257 258 // Platform methods are enumerated here once. 259 #define ANGLE_PLATFORM_OP(OP) \ 260 OP(currentTime, CurrentTime) \ 261 OP(monotonicallyIncreasingTime, MonotonicallyIncreasingTime) \ 262 OP(logError, LogError) \ 263 OP(logWarning, LogWarning) \ 264 OP(logInfo, LogInfo) \ 265 OP(getTraceCategoryEnabledFlag, GetTraceCategoryEnabledFlag) \ 266 OP(addTraceEvent, AddTraceEvent) \ 267 OP(updateTraceEventDuration, UpdateTraceEventDuration) \ 268 OP(histogramCustomCounts, HistogramCustomCounts) \ 269 OP(histogramEnumeration, HistogramEnumeration) \ 270 OP(histogramSparse, HistogramSparse) \ 271 OP(histogramBoolean, HistogramBoolean) \ 272 OP(overrideWorkaroundsD3D, OverrideWorkaroundsD3D) \ 273 OP(overrideFeaturesVk, OverrideFeaturesVk) \ 274 OP(cacheProgram, CacheProgram) 275 276 #define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName; 277 278 struct ANGLE_PLATFORM_EXPORT PlatformMethods 279 { 280 PlatformMethods() {} 281 282 // User data pointer for any implementation specific members. Put it at the start of the 283 // platform structure so it doesn't become overwritten if one version of the platform 284 // adds or removes new members. 285 void *context = 0; 286 287 ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_DEF); 288 }; 289 290 #undef ANGLE_PLATFORM_METHOD_DEF 291 292 // Subtract one to account for the context pointer. 293 constexpr unsigned int g_NumPlatformMethods = (sizeof(PlatformMethods) / sizeof(uintptr_t)) - 1; 294 295 #define ANGLE_PLATFORM_METHOD_STRING(Name) #Name 296 #define ANGLE_PLATFORM_METHOD_STRING2(Name, CapsName) ANGLE_PLATFORM_METHOD_STRING(Name), 297 298 constexpr const char *const g_PlatformMethodNames[g_NumPlatformMethods] = { 299 ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_STRING2)}; 300 301 #undef ANGLE_PLATFORM_METHOD_STRING2 302 #undef ANGLE_PLATFORM_METHOD_STRING 303 304 } // namespace angle 305 306 extern "C" { 307 308 // Gets the platform methods on the passed-in EGL display. If the method name signature does not 309 // match the compiled signature for this ANGLE, false is returned. On success true is returned. 310 // The application should set any platform methods it cares about on the returned pointer. 311 // If display is not valid, behaviour is undefined. 312 313 ANGLE_PLATFORM_EXPORT bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display, 314 const char *const methodNames[], 315 unsigned int methodNameCount, 316 void *context, 317 void *platformMethodsOut); 318 319 // Sets the platform methods back to their defaults. 320 // If display is not valid, behaviour is undefined. 321 ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display); 322 323 } // extern "C" 324 325 namespace angle 326 { 327 typedef bool(ANGLE_APIENTRY *GetDisplayPlatformFunc)(angle::EGLDisplayType, 328 const char *const *, 329 unsigned int, 330 void *, 331 void *); 332 typedef void(ANGLE_APIENTRY *ResetDisplayPlatformFunc)(angle::EGLDisplayType); 333 } // namespace angle 334 335 // This function is not exported 336 angle::PlatformMethods *ANGLEPlatformCurrent(); 337 338 #endif // ANGLE_PLATFORM_H 339