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);
DefaultCurrentTime(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);
DefaultMonotonicallyIncreasingTime(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);
DefaultLogError(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);
DefaultLogWarning(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);
DefaultLogInfo(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);
DefaultGetTraceCategoryEnabledFlag(PlatformMethods * platform,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);
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)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);
DefaultUpdateTraceEventDuration(PlatformMethods * platform,const unsigned char * categoryEnabledFlag,const char * name,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);
DefaultHistogramCustomCounts(PlatformMethods * platform,const char * name,int sample,int min,int max,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);
DefaultHistogramEnumeration(PlatformMethods * platform,const char * name,int sample,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);
DefaultHistogramSparse(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);
DefaultHistogramBoolean(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);
DefaultOverrideWorkaroundsD3D(PlatformMethods * platform,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);
DefaultOverrideFeaturesVk(PlatformMethods * platform,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);
DefaultCacheProgram(PlatformMethods * platform,const ProgramKeyType & key,size_t programSize,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 {
PlatformMethodsPlatformMethods280     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