|  | // | 
|  | // Copyright (c) 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. | 
|  |  | 
|  | // Platform.h: The public interface ANGLE exposes to the API layer, for | 
|  | //   doing platform-specific tasks like gathering data, or for tracing. | 
|  |  | 
|  | #ifndef ANGLE_PLATFORM_H | 
|  | #define ANGLE_PLATFORM_H | 
|  |  | 
|  | #include <stdint.h> | 
|  | #include <array> | 
|  |  | 
|  | #define EGL_PLATFORM_ANGLE_PLATFORM_METHODS_ANGLEX 0x3482 | 
|  |  | 
|  | #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 | 
|  | #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 WorkaroundsD3D; | 
|  | struct FeaturesVk; | 
|  | 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) | 
|  | { | 
|  | } | 
|  |  | 
|  | // Allows us to programatically override ANGLE's default workarounds for testing purposes. | 
|  | using OverrideWorkaroundsD3DFunc = void (*)(PlatformMethods *platform, | 
|  | angle::WorkaroundsD3D *workaroundsD3D); | 
|  | inline void DefaultOverrideWorkaroundsD3D(PlatformMethods *platform, | 
|  | angle::WorkaroundsD3D *workaroundsD3D) | 
|  | { | 
|  | } | 
|  |  | 
|  | using OverrideFeaturesVkFunc = void (*)(PlatformMethods *platform, | 
|  | angle::FeaturesVk *workaroundsVulkan); | 
|  | inline void DefaultOverrideFeaturesVk(PlatformMethods *platform, | 
|  | angle::FeaturesVk *workaroundsVulkan) | 
|  | { | 
|  | } | 
|  |  | 
|  | // Callback on a successful program link with the program binary. Can be used to store | 
|  | // shaders to disk. Keys are a 160-bit SHA-1 hash. | 
|  | using ProgramKeyType   = std::array<uint8_t, 20>; | 
|  | 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) | 
|  | { | 
|  | } | 
|  |  | 
|  | // 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(overrideWorkaroundsD3D, OverrideWorkaroundsD3D)           \ | 
|  | OP(overrideFeaturesVk, OverrideFeaturesVk)                   \ | 
|  | OP(cacheProgram, CacheProgram) | 
|  |  | 
|  | #define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName; | 
|  |  | 
|  | struct ANGLE_PLATFORM_EXPORT PlatformMethods | 
|  | { | 
|  | 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); | 
|  | }; | 
|  |  | 
|  | #undef ANGLE_PLATFORM_METHOD_DEF | 
|  |  | 
|  | // Subtract one to account for the context pointer. | 
|  | constexpr unsigned int g_NumPlatformMethods = (sizeof(PlatformMethods) / sizeof(uintptr_t)) - 1; | 
|  |  | 
|  | #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_PLATFORM_H |