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