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