Home | History | Annotate | Download | only in EGL
      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