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 0x3482
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);
DefaultCurrentTime(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);
DefaultMonotonicallyIncreasingTime(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);
DefaultLogError(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);
DefaultLogWarning(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);
DefaultLogInfo(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);
DefaultGetTraceCategoryEnabledFlag(PlatformMethods * platform,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);
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)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);
DefaultUpdateTraceEventDuration(PlatformMethods * platform,const unsigned char * categoryEnabledFlag,const char * name,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);
DefaultHistogramCustomCounts(PlatformMethods * platform,const char * name,int sample,int min,int max,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);
DefaultHistogramEnumeration(PlatformMethods * platform,const char * name,int sample,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);
DefaultHistogramSparse(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);
DefaultHistogramBoolean(PlatformMethods * platform,const char * name,bool sample)218 inline void DefaultHistogramBoolean(PlatformMethods *platform, const char *name, bool sample) {}
219
220 // Allows us to programatically override ANGLE's default workarounds for testing purposes.
221 using OverrideWorkaroundsD3DFunc = void (*)(PlatformMethods *platform,
222 angle::FeaturesD3D *featuresD3D);
DefaultOverrideWorkaroundsD3D(PlatformMethods * platform,angle::FeaturesD3D * featuresD3D)223 inline void DefaultOverrideWorkaroundsD3D(PlatformMethods *platform,
224 angle::FeaturesD3D *featuresD3D)
225 {}
226
227 using OverrideFeaturesVkFunc = void (*)(PlatformMethods *platform,
228 angle::FeaturesVk *featuresVulkan);
DefaultOverrideFeaturesVk(PlatformMethods * platform,angle::FeaturesVk * featuresVulkan)229 inline void DefaultOverrideFeaturesVk(PlatformMethods *platform, angle::FeaturesVk *featuresVulkan)
230 {}
231
232 using OverrideFeaturesMtlFunc = void (*)(PlatformMethods *platform,
233 angle::FeaturesMtl *featuresMetal);
DefaultOverrideFeaturesMtl(PlatformMethods * platform,angle::FeaturesMtl * featuresMetal)234 inline void DefaultOverrideFeaturesMtl(PlatformMethods *platform, angle::FeaturesMtl *featuresMetal)
235 {}
236
237 // Callback on a successful program link with the program binary. Can be used to store
238 // shaders to disk. Keys are a 160-bit SHA-1 hash.
239 using ProgramKeyType = std::array<uint8_t, 20>;
240 using CacheProgramFunc = void (*)(PlatformMethods *platform,
241 const ProgramKeyType &key,
242 size_t programSize,
243 const uint8_t *programBytes);
DefaultCacheProgram(PlatformMethods * platform,const ProgramKeyType & key,size_t programSize,const uint8_t * programBytes)244 inline void DefaultCacheProgram(PlatformMethods *platform,
245 const ProgramKeyType &key,
246 size_t programSize,
247 const uint8_t *programBytes)
248 {}
249
250 using PostWorkerTaskCallback = void (*)(void *userData);
251 using PostWorkerTaskFunc = void (*)(PlatformMethods *platform,
252 PostWorkerTaskCallback callback,
253 void *userData);
254 constexpr PostWorkerTaskFunc DefaultPostWorkerTask = nullptr;
255
256 // Platform methods are enumerated here once.
257 #define ANGLE_PLATFORM_OP(OP) \
258 OP(currentTime, CurrentTime) \
259 OP(monotonicallyIncreasingTime, MonotonicallyIncreasingTime) \
260 OP(logError, LogError) \
261 OP(logWarning, LogWarning) \
262 OP(logInfo, LogInfo) \
263 OP(getTraceCategoryEnabledFlag, GetTraceCategoryEnabledFlag) \
264 OP(addTraceEvent, AddTraceEvent) \
265 OP(updateTraceEventDuration, UpdateTraceEventDuration) \
266 OP(histogramCustomCounts, HistogramCustomCounts) \
267 OP(histogramEnumeration, HistogramEnumeration) \
268 OP(histogramSparse, HistogramSparse) \
269 OP(histogramBoolean, HistogramBoolean) \
270 OP(overrideWorkaroundsD3D, OverrideWorkaroundsD3D) \
271 OP(overrideFeaturesVk, OverrideFeaturesVk) \
272 OP(cacheProgram, CacheProgram) \
273 OP(overrideFeaturesMtl, OverrideFeaturesMtl) \
274 OP(postWorkerTask, PostWorkerTask)
275
276 #define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName;
277
278 struct ANGLE_PLATFORM_EXPORT PlatformMethods
279 {
280 inline 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 inline PlatformMethods::PlatformMethods() = default;
291
292 #undef ANGLE_PLATFORM_METHOD_DEF
293
294 // Subtract one to account for the context pointer.
295 constexpr unsigned int g_NumPlatformMethods = (sizeof(PlatformMethods) / sizeof(uintptr_t)) - 1;
296
297 #define ANGLE_PLATFORM_METHOD_STRING(Name) #Name
298 #define ANGLE_PLATFORM_METHOD_STRING2(Name, CapsName) ANGLE_PLATFORM_METHOD_STRING(Name),
299
300 constexpr const char *const g_PlatformMethodNames[g_NumPlatformMethods] = {
301 ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_STRING2)};
302
303 #undef ANGLE_PLATFORM_METHOD_STRING2
304 #undef ANGLE_PLATFORM_METHOD_STRING
305
306 } // namespace angle
307
308 extern "C" {
309
310 // Gets the platform methods on the passed-in EGL display. If the method name signature does not
311 // match the compiled signature for this ANGLE, false is returned. On success true is returned.
312 // The application should set any platform methods it cares about on the returned pointer.
313 // If display is not valid, behaviour is undefined.
314
315 ANGLE_PLATFORM_EXPORT bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
316 const char *const methodNames[],
317 unsigned int methodNameCount,
318 void *context,
319 void *platformMethodsOut);
320
321 // Sets the platform methods back to their defaults.
322 // If display is not valid, behaviour is undefined.
323 ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display);
324 } // extern "C"
325
326 namespace angle
327 {
328 typedef bool(ANGLE_APIENTRY *GetDisplayPlatformFunc)(angle::EGLDisplayType,
329 const char *const *,
330 unsigned int,
331 void *,
332 void *);
333 typedef void(ANGLE_APIENTRY *ResetDisplayPlatformFunc)(angle::EGLDisplayType);
334 } // namespace angle
335
336 // This function is not exported
337 angle::PlatformMethods *ANGLEPlatformCurrent();
338
339 #endif // ANGLE_PLATFORMMETHODS_H
340