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// 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 <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
39namespace angle
40{
41struct FeaturesD3D;
42struct FeaturesVk;
43struct FeaturesMtl;
44using TraceEventHandle = uint64_t;
45using EGLDisplayType = void *;
46struct 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
56using CurrentTimeFunc = double (*)(PlatformMethods *platform);
57inline 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.
65using MonotonicallyIncreasingTimeFunc = double (*)(PlatformMethods *platform);
66inline double DefaultMonotonicallyIncreasingTime(PlatformMethods *platform)
67{
68 return 0.0;
69}
70
71// Logging ------------------------------------------------------------
72
73// Log an error message within the platform implementation.
74using LogErrorFunc = void (*)(PlatformMethods *platform, const char *errorMessage);
75inline void DefaultLogError(PlatformMethods *platform, const char *errorMessage) {}
76
77// Log a warning message within the platform implementation.
78using LogWarningFunc = void (*)(PlatformMethods *platform, const char *warningMessage);
79inline void DefaultLogWarning(PlatformMethods *platform, const char *warningMessage) {}
80
81// Log an info message within the platform implementation.
82using LogInfoFunc = void (*)(PlatformMethods *platform, const char *infoMessage);
83inline 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.
94using GetTraceCategoryEnabledFlagFunc = const unsigned char *(*)(PlatformMethods *platform,
95 const char *categoryName);
96inline 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.
149using 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);
160inline 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.
176using UpdateTraceEventDurationFunc = void (*)(PlatformMethods *platform,
177 const unsigned char *categoryEnabledFlag,
178 const char *name,
179 angle::TraceEventHandle eventHandle);
180inline 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.
189using HistogramCustomCountsFunc = void (*)(PlatformMethods *platform,
190 const char *name,
191 int sample,
192 int min,
193 int max,
194 int bucketCount);
195inline 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.
204using HistogramEnumerationFunc = void (*)(PlatformMethods *platform,
205 const char *name,
206 int sample,
207 int boundaryValue);
208inline 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.
214using HistogramSparseFunc = void (*)(PlatformMethods *platform, const char *name, int sample);
215inline void DefaultHistogramSparse(PlatformMethods *platform, const char *name, int sample) {}
216// Boolean histograms track two-state variables.
217using HistogramBooleanFunc = void (*)(PlatformMethods *platform, const char *name, bool sample);
218inline void DefaultHistogramBoolean(PlatformMethods *platform, const char *name, bool sample) {}
219
220// Allows us to programatically override ANGLE's default workarounds for testing purposes.
221using OverrideWorkaroundsD3DFunc = void (*)(PlatformMethods *platform,
222 angle::FeaturesD3D *featuresD3D);
223inline void DefaultOverrideWorkaroundsD3D(PlatformMethods *platform,
224 angle::FeaturesD3D *featuresD3D)
225{}
226
227using OverrideFeaturesVkFunc = void (*)(PlatformMethods *platform,
228 angle::FeaturesVk *featuresVulkan);
229inline void DefaultOverrideFeaturesVk(PlatformMethods *platform, angle::FeaturesVk *featuresVulkan)
230{}
231
232using OverrideFeaturesMtlFunc = void (*)(PlatformMethods *platform,
233 angle::FeaturesMtl *featuresMetal);
234inline 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.
239using ProgramKeyType = std::array<uint8_t, 20>;
240using CacheProgramFunc = void (*)(PlatformMethods *platform,
241 const ProgramKeyType &key,
242 size_t programSize,
243 const uint8_t *programBytes);
244inline void DefaultCacheProgram(PlatformMethods *platform,
245 const ProgramKeyType &key,
246 size_t programSize,
247 const uint8_t *programBytes)
248{}
249
250// Platform methods are enumerated here once.
251#define ANGLE_PLATFORM_OP(OP) \
252 OP(currentTime, CurrentTime) \
253 OP(monotonicallyIncreasingTime, MonotonicallyIncreasingTime) \
254 OP(logError, LogError) \
255 OP(logWarning, LogWarning) \
256 OP(logInfo, LogInfo) \
257 OP(getTraceCategoryEnabledFlag, GetTraceCategoryEnabledFlag) \
258 OP(addTraceEvent, AddTraceEvent) \
259 OP(updateTraceEventDuration, UpdateTraceEventDuration) \
260 OP(histogramCustomCounts, HistogramCustomCounts) \
261 OP(histogramEnumeration, HistogramEnumeration) \
262 OP(histogramSparse, HistogramSparse) \
263 OP(histogramBoolean, HistogramBoolean) \
264 OP(overrideWorkaroundsD3D, OverrideWorkaroundsD3D) \
265 OP(overrideFeaturesVk, OverrideFeaturesVk) \
266 OP(cacheProgram, CacheProgram) \
267 OP(overrideFeaturesMtl, OverrideFeaturesMtl)
268
269#define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName;
270
271struct ANGLE_PLATFORM_EXPORT PlatformMethods
272{
273 inline PlatformMethods();
274
275 // User data pointer for any implementation specific members. Put it at the start of the
276 // platform structure so it doesn't become overwritten if one version of the platform
277 // adds or removes new members.
278 void *context = 0;
279
280 ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_DEF)
281};
282
283inline PlatformMethods::PlatformMethods() = default;
284
285#undef ANGLE_PLATFORM_METHOD_DEF
286
287// Subtract one to account for the context pointer.
288constexpr unsigned int g_NumPlatformMethods = (sizeof(PlatformMethods) / sizeof(uintptr_t)) - 1;
289
290#define ANGLE_PLATFORM_METHOD_STRING(Name) #Name
291#define ANGLE_PLATFORM_METHOD_STRING2(Name, CapsName) ANGLE_PLATFORM_METHOD_STRING(Name),
292
293constexpr const char *const g_PlatformMethodNames[g_NumPlatformMethods] = {
294 ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_STRING2)};
295
296#undef ANGLE_PLATFORM_METHOD_STRING2
297#undef ANGLE_PLATFORM_METHOD_STRING
298
299} // namespace angle
300
301extern "C" {
302
303// Gets the platform methods on the passed-in EGL display. If the method name signature does not
304// match the compiled signature for this ANGLE, false is returned. On success true is returned.
305// The application should set any platform methods it cares about on the returned pointer.
306// If display is not valid, behaviour is undefined.
307
308ANGLE_PLATFORM_EXPORT bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
309 const char *const methodNames[],
310 unsigned int methodNameCount,
311 void *context,
312 void *platformMethodsOut);
313
314// Sets the platform methods back to their defaults.
315// If display is not valid, behaviour is undefined.
316ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display);
317
318} // extern "C"
319
320namespace angle
321{
322typedef bool(ANGLE_APIENTRY *GetDisplayPlatformFunc)(angle::EGLDisplayType,
323 const char *const *,
324 unsigned int,
325 void *,
326 void *);
327typedef void(ANGLE_APIENTRY *ResetDisplayPlatformFunc)(angle::EGLDisplayType);
328} // namespace angle
329
330// This function is not exported
331angle::PlatformMethods *ANGLEPlatformCurrent();
332
333#endif // ANGLE_PLATFORM_H
334