| // | |
| // Copyright 2015 The ANGLE Project Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // PlatformMethods.h: The public interface ANGLE exposes to the API layer, for | |
| // doing platform-specific tasks like gathering data, or for tracing. | |
| #ifndef ANGLE_PLATFORMMETHODS_H | |
| #define ANGLE_PLATFORMMETHODS_H | |
| #include <stdint.h> | |
| #include <stdlib.h> | |
| #include <array> | |
| #define EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX 0x6AFB | |
| #if !defined(ANGLE_PLATFORM_EXPORT) | |
| # if defined(_WIN32) | |
| # if !defined(LIBANGLE_IMPLEMENTATION) | |
| # define ANGLE_PLATFORM_EXPORT __declspec(dllimport) | |
| # else | |
| # define ANGLE_PLATFORM_EXPORT __declspec(dllexport) | |
| # endif | |
| # elif defined(__GNUC__) || defined(__clang__) | |
| # define ANGLE_PLATFORM_EXPORT __attribute__((visibility("default"))) | |
| # endif | |
| #endif | |
| #if !defined(ANGLE_PLATFORM_EXPORT) | |
| # define ANGLE_PLATFORM_EXPORT | |
| #endif | |
| #if defined(_WIN32) | |
| # define ANGLE_APIENTRY __stdcall | |
| #else | |
| # define ANGLE_APIENTRY | |
| #endif | |
| namespace angle | |
| { | |
| struct FeaturesD3D; | |
| struct FeaturesVk; | |
| struct FeaturesMtl; | |
| using TraceEventHandle = uint64_t; | |
| using EGLDisplayType = void *; | |
| struct PlatformMethods; | |
| // Use a C-like API to not trigger undefined calling behaviour. | |
| // Avoid using decltype here to work around sanitizer limitations. | |
| // TODO(jmadill): Use decltype here if/when UBSAN is fixed. | |
| // System -------------------------------------------------------------- | |
| // Wall clock time in seconds since the epoch. | |
| // TODO(jmadill): investigate using an ANGLE internal time library | |
| using CurrentTimeFunc = double (*)(PlatformMethods *platform); | |
| inline double DefaultCurrentTime(PlatformMethods *platform) | |
| { | |
| return 0.0; | |
| } | |
| // Monotonically increasing time in seconds from an arbitrary fixed point in the past. | |
| // This function is expected to return at least millisecond-precision values. For this reason, | |
| // it is recommended that the fixed point be no further in the past than the epoch. | |
| using MonotonicallyIncreasingTimeFunc = double (*)(PlatformMethods *platform); | |
| inline double DefaultMonotonicallyIncreasingTime(PlatformMethods *platform) | |
| { | |
| return 0.0; | |
| } | |
| // Logging ------------------------------------------------------------ | |
| // Log an error message within the platform implementation. | |
| using LogErrorFunc = void (*)(PlatformMethods *platform, const char *errorMessage); | |
| inline void DefaultLogError(PlatformMethods *platform, const char *errorMessage) {} | |
| // Log a warning message within the platform implementation. | |
| using LogWarningFunc = void (*)(PlatformMethods *platform, const char *warningMessage); | |
| inline void DefaultLogWarning(PlatformMethods *platform, const char *warningMessage) {} | |
| // Log an info message within the platform implementation. | |
| using LogInfoFunc = void (*)(PlatformMethods *platform, const char *infoMessage); | |
| inline void DefaultLogInfo(PlatformMethods *platform, const char *infoMessage) {} | |
| // Tracing -------- | |
| // Get a pointer to the enabled state of the given trace category. The | |
| // embedder can dynamically change the enabled state as trace event | |
| // recording is started and stopped by the application. Only long-lived | |
| // literal strings should be given as the category name. The implementation | |
| // expects the returned pointer to be held permanently in a local static. If | |
| // the unsigned char is non-zero, tracing is enabled. If tracing is enabled, | |
| // addTraceEvent is expected to be called by the trace event macros. | |
| using GetTraceCategoryEnabledFlagFunc = const unsigned char *(*)(PlatformMethods *platform, | |
| const char *categoryName); | |
| inline const unsigned char *DefaultGetTraceCategoryEnabledFlag(PlatformMethods *platform, | |
| const char *categoryName) | |
| { | |
| return nullptr; | |
| } | |
| // | |
| // Add a trace event to the platform tracing system. Depending on the actual | |
| // enabled state, this event may be recorded or dropped. | |
| // - phase specifies the type of event: | |
| // - BEGIN ('B'): Marks the beginning of a scoped event. | |
| // - END ('E'): Marks the end of a scoped event. | |
| // - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't | |
| // need a matching END event. Instead, at the end of the scope, | |
| // updateTraceEventDuration() must be called with the TraceEventHandle | |
| // returned from addTraceEvent(). | |
| // - INSTANT ('I'): Standalone, instantaneous event. | |
| // - START ('S'): Marks the beginning of an asynchronous event (the end | |
| // event can occur in a different scope or thread). The id parameter is | |
| // used to match START/FINISH pairs. | |
| // - FINISH ('F'): Marks the end of an asynchronous event. | |
| // - COUNTER ('C'): Used to trace integer quantities that change over | |
| // time. The argument values are expected to be of type int. | |
| // - METADATA ('M'): Reserved for internal use. | |
| // - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag. | |
| // - name is the name of the event. Also used to match BEGIN/END and | |
| // START/FINISH pairs. | |
| // - id optionally allows events of the same name to be distinguished from | |
| // each other. For example, to trace the construction and destruction of | |
| // objects, specify the pointer as the id parameter. | |
| // - timestamp should be a time value returned from monotonicallyIncreasingTime. | |
| // - numArgs specifies the number of elements in argNames, argTypes, and | |
| // argValues. | |
| // - argNames is the array of argument names. Use long-lived literal strings | |
| // or specify the COPY flag. | |
| // - argTypes is the array of argument types: | |
| // - BOOL (1): bool | |
| // - UINT (2): unsigned long long | |
| // - INT (3): long long | |
| // - DOUBLE (4): double | |
| // - POINTER (5): void* | |
| // - STRING (6): char* (long-lived null-terminated char* string) | |
| // - COPY_STRING (7): char* (temporary null-terminated char* string) | |
| // - CONVERTABLE (8): WebConvertableToTraceFormat | |
| // - argValues is the array of argument values. Each value is the unsigned | |
| // long long member of a union of all supported types. | |
| // - flags can be 0 or one or more of the following, ORed together: | |
| // - COPY (0x1): treat all strings (name, argNames and argValues of type | |
| // string) as temporary so that they will be copied by addTraceEvent. | |
| // - HAS_ID (0x2): use the id argument to uniquely identify the event for | |
| // matching with other events of the same name. | |
| // - MANGLE_ID (0x4): specify this flag if the id parameter is the value | |
| // of a pointer. | |
| using AddTraceEventFunc = angle::TraceEventHandle (*)(PlatformMethods *platform, | |
| char phase, | |
| const unsigned char *categoryEnabledFlag, | |
| const char *name, | |
| unsigned long long id, | |
| double timestamp, | |
| int numArgs, | |
| const char **argNames, | |
| const unsigned char *argTypes, | |
| const unsigned long long *argValues, | |
| unsigned char flags); | |
| inline angle::TraceEventHandle DefaultAddTraceEvent(PlatformMethods *platform, | |
| char phase, | |
| const unsigned char *categoryEnabledFlag, | |
| const char *name, | |
| unsigned long long id, | |
| double timestamp, | |
| int numArgs, | |
| const char **argNames, | |
| const unsigned char *argTypes, | |
| const unsigned long long *argValues, | |
| unsigned char flags) | |
| { | |
| return 0; | |
| } | |
| // Set the duration field of a COMPLETE trace event. | |
| using UpdateTraceEventDurationFunc = void (*)(PlatformMethods *platform, | |
| const unsigned char *categoryEnabledFlag, | |
| const char *name, | |
| angle::TraceEventHandle eventHandle); | |
| inline void DefaultUpdateTraceEventDuration(PlatformMethods *platform, | |
| const unsigned char *categoryEnabledFlag, | |
| const char *name, | |
| angle::TraceEventHandle eventHandle) | |
| {} | |
| // Callbacks for reporting histogram data. | |
| // CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50 | |
| // would do. | |
| using HistogramCustomCountsFunc = void (*)(PlatformMethods *platform, | |
| const char *name, | |
| int sample, | |
| int min, | |
| int max, | |
| int bucketCount); | |
| inline void DefaultHistogramCustomCounts(PlatformMethods *platform, | |
| const char *name, | |
| int sample, | |
| int min, | |
| int max, | |
| int bucketCount) | |
| {} | |
| // Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample | |
| // value. | |
| using HistogramEnumerationFunc = void (*)(PlatformMethods *platform, | |
| const char *name, | |
| int sample, | |
| int boundaryValue); | |
| inline void DefaultHistogramEnumeration(PlatformMethods *platform, | |
| const char *name, | |
| int sample, | |
| int boundaryValue) | |
| {} | |
| // Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets. | |
| using HistogramSparseFunc = void (*)(PlatformMethods *platform, const char *name, int sample); | |
| inline void DefaultHistogramSparse(PlatformMethods *platform, const char *name, int sample) {} | |
| // Boolean histograms track two-state variables. | |
| using HistogramBooleanFunc = void (*)(PlatformMethods *platform, const char *name, bool sample); | |
| inline void DefaultHistogramBoolean(PlatformMethods *platform, const char *name, bool sample) {} | |
| // Callback on a successful program link with the program binary. Can be used to store | |
| // shaders to disk. Depending on the platform the keys are either a 160-bit SHA-1 hash | |
| // (chromium) or a 128-bit XXH3 hash (all other platforms). For simplicity, ProgramKeyType | |
| // is large enough to hold either. | |
| constexpr size_t kProgramCacheControlKeySize = 20; | |
| using ProgramKeyType = std::array<uint8_t, kProgramCacheControlKeySize>; | |
| using CacheProgramFunc = void (*)(PlatformMethods *platform, | |
| const ProgramKeyType &key, | |
| size_t programSize, | |
| const uint8_t *programBytes); | |
| inline void DefaultCacheProgram(PlatformMethods *platform, | |
| const ProgramKeyType &key, | |
| size_t programSize, | |
| const uint8_t *programBytes) | |
| {} | |
| using PostWorkerTaskCallback = void (*)(void *userData); | |
| using PostWorkerTaskFunc = void (*)(PlatformMethods *platform, | |
| PostWorkerTaskCallback callback, | |
| void *userData); | |
| constexpr PostWorkerTaskFunc DefaultPostWorkerTask = nullptr; | |
| // Placeholder values where feature override callbacks used to be. They are deprecated in favor of | |
| // EGL_ANGLE_feature_control. The placeholders are there to keep the layout of the PlatformMethods | |
| // constant to support drop-in replacement of ANGLE's .so files in applications built with an older | |
| // header. | |
| using PlaceholderCallbackFunc = void (*)(...); | |
| inline void DefaultPlaceholderCallback(...) {} | |
| // The boolean indicates whether the shader was in the cache or not. A value of true indicates it | |
| // was, where as false means it was not and needed to be compiled. | |
| using RecordShaderCacheUseFunc = void (*)(bool); | |
| inline void DefaultRecordShaderCacheUse(bool) {} | |
| // Platform methods are enumerated here once. | |
| #define ANGLE_PLATFORM_OP(OP) \ | |
| OP(currentTime, CurrentTime) \ | |
| OP(monotonicallyIncreasingTime, MonotonicallyIncreasingTime) \ | |
| OP(logError, LogError) \ | |
| OP(logWarning, LogWarning) \ | |
| OP(logInfo, LogInfo) \ | |
| OP(getTraceCategoryEnabledFlag, GetTraceCategoryEnabledFlag) \ | |
| OP(addTraceEvent, AddTraceEvent) \ | |
| OP(updateTraceEventDuration, UpdateTraceEventDuration) \ | |
| OP(histogramCustomCounts, HistogramCustomCounts) \ | |
| OP(histogramEnumeration, HistogramEnumeration) \ | |
| OP(histogramSparse, HistogramSparse) \ | |
| OP(histogramBoolean, HistogramBoolean) \ | |
| OP(placeholder1, PlaceholderCallback) \ | |
| OP(placeholder2, PlaceholderCallback) \ | |
| OP(cacheProgram, CacheProgram) \ | |
| OP(placeholder3, PlaceholderCallback) \ | |
| OP(postWorkerTask, PostWorkerTask) \ | |
| OP(recordShaderCacheUse, RecordShaderCacheUse) | |
| #define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName; | |
| struct ANGLE_PLATFORM_EXPORT PlatformMethods | |
| { | |
| inline PlatformMethods(); | |
| // User data pointer for any implementation specific members. Put it at the start of the | |
| // platform structure so it doesn't become overwritten if one version of the platform | |
| // adds or removes new members. | |
| void *context = 0; | |
| ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_DEF) | |
| }; | |
| inline PlatformMethods::PlatformMethods() = default; | |
| #undef ANGLE_PLATFORM_METHOD_DEF | |
| // Subtract one to account for the context pointer. | |
| constexpr unsigned int g_NumPlatformMethods = (sizeof(PlatformMethods) / sizeof(uintptr_t)) - 1; | |
| // No further uses of platform methods is allowed. EGL extensions should be used instead. While | |
| // methods are being removed, use PlaceholderCallback to keep the layout of PlatformMethods | |
| // constant. | |
| static_assert(g_NumPlatformMethods == 18, "Avoid adding methods to PlatformMethods"); | |
| #define ANGLE_PLATFORM_METHOD_STRING(Name) #Name | |
| #define ANGLE_PLATFORM_METHOD_STRING2(Name, CapsName) ANGLE_PLATFORM_METHOD_STRING(Name), | |
| constexpr const char *const g_PlatformMethodNames[g_NumPlatformMethods] = { | |
| ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_STRING2)}; | |
| #undef ANGLE_PLATFORM_METHOD_STRING2 | |
| #undef ANGLE_PLATFORM_METHOD_STRING | |
| } // namespace angle | |
| extern "C" { | |
| // Gets the platform methods on the passed-in EGL display. If the method name signature does not | |
| // match the compiled signature for this ANGLE, false is returned. On success true is returned. | |
| // The application should set any platform methods it cares about on the returned pointer. | |
| // If display is not valid, behaviour is undefined. | |
| ANGLE_PLATFORM_EXPORT bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display, | |
| const char *const methodNames[], | |
| unsigned int methodNameCount, | |
| void *context, | |
| void *platformMethodsOut); | |
| // Sets the platform methods back to their defaults. | |
| // If display is not valid, behaviour is undefined. | |
| ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display); | |
| } // extern "C" | |
| namespace angle | |
| { | |
| typedef bool(ANGLE_APIENTRY *GetDisplayPlatformFunc)(angle::EGLDisplayType, | |
| const char *const *, | |
| unsigned int, | |
| void *, | |
| void *); | |
| typedef void(ANGLE_APIENTRY *ResetDisplayPlatformFunc)(angle::EGLDisplayType); | |
| } // namespace angle | |
| // This function is not exported | |
| angle::PlatformMethods *ANGLEPlatformCurrent(); | |
| #endif // ANGLE_PLATFORMMETHODS_H |