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 #if defined(_WIN32)
16 # if !defined(LIBANGLE_IMPLEMENTATION)
17 # define ANGLE_PLATFORM_EXPORT __declspec(dllimport)
18 # else
19 # define ANGLE_PLATFORM_EXPORT __declspec(dllexport)
20 # endif
21 #elif defined(__GNUC__) || defined(__clang__)
22 # define ANGLE_PLATFORM_EXPORT __attribute__((visibility ("default")))
23 #endif
24 #if !defined(ANGLE_PLATFORM_EXPORT)
25 # define ANGLE_PLATFORM_EXPORT
26 #endif
27
28 #if defined(_WIN32)
29 # define ANGLE_APIENTRY __stdcall
30 #else
31 # define ANGLE_APIENTRY
32 #endif
33
34 namespace angle
35 {
36 struct WorkaroundsD3D;
37 using TraceEventHandle = uint64_t;
38 using EGLDisplayType = void *;
39 struct PlatformMethods;
40
41 // Use a C-like API to not trigger undefined calling behaviour.
42 // Avoid using decltype here to work around sanitizer limitations.
43 // TODO(jmadill): Use decltype here if/when UBSAN is fixed.
44
45 // System --------------------------------------------------------------
46
47 // Wall clock time in seconds since the epoch.
48 // TODO(jmadill): investigate using an ANGLE internal time library
49 using CurrentTimeFunc = double (*)(PlatformMethods *platform);
DefaultCurrentTime(PlatformMethods * platform)50 inline double DefaultCurrentTime(PlatformMethods *platform)
51 {
52 return 0.0;
53 }
54
55 // Monotonically increasing time in seconds from an arbitrary fixed point in the past.
56 // This function is expected to return at least millisecond-precision values. For this reason,
57 // it is recommended that the fixed point be no further in the past than the epoch.
58 using MonotonicallyIncreasingTimeFunc = double (*)(PlatformMethods *platform);
DefaultMonotonicallyIncreasingTime(PlatformMethods * platform)59 inline double DefaultMonotonicallyIncreasingTime(PlatformMethods *platform)
60 {
61 return 0.0;
62 }
63
64 // Logging ------------------------------------------------------------
65
66 // Log an error message within the platform implementation.
67 using LogErrorFunc = void (*)(PlatformMethods *platform, const char *errorMessage);
DefaultLogError(PlatformMethods * platform,const char * errorMessage)68 inline void DefaultLogError(PlatformMethods *platform, const char *errorMessage)
69 {
70 }
71
72 // Log a warning message within the platform implementation.
73 using LogWarningFunc = void (*)(PlatformMethods *platform, const char *warningMessage);
DefaultLogWarning(PlatformMethods * platform,const char * warningMessage)74 inline void DefaultLogWarning(PlatformMethods *platform, const char *warningMessage)
75 {
76 }
77
78 // Log an info message within the platform implementation.
79 using LogInfoFunc = void (*)(PlatformMethods *platform, const char *infoMessage);
DefaultLogInfo(PlatformMethods * platform,const char * infoMessage)80 inline void DefaultLogInfo(PlatformMethods *platform, const char *infoMessage)
81 {
82 }
83
84 // Tracing --------
85
86 // Get a pointer to the enabled state of the given trace category. The
87 // embedder can dynamically change the enabled state as trace event
88 // recording is started and stopped by the application. Only long-lived
89 // literal strings should be given as the category name. The implementation
90 // expects the returned pointer to be held permanently in a local static. If
91 // the unsigned char is non-zero, tracing is enabled. If tracing is enabled,
92 // addTraceEvent is expected to be called by the trace event macros.
93 using GetTraceCategoryEnabledFlagFunc = const unsigned char *(*)(PlatformMethods *platform,
94 const char *categoryName);
DefaultGetTraceCategoryEnabledFlag(PlatformMethods * platform,const char * categoryName)95 inline const unsigned char *DefaultGetTraceCategoryEnabledFlag(PlatformMethods *platform,
96 const char *categoryName)
97 {
98 return nullptr;
99 }
100
101 //
102 // Add a trace event to the platform tracing system. Depending on the actual
103 // enabled state, this event may be recorded or dropped.
104 // - phase specifies the type of event:
105 // - BEGIN ('B'): Marks the beginning of a scoped event.
106 // - END ('E'): Marks the end of a scoped event.
107 // - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't
108 // need a matching END event. Instead, at the end of the scope,
109 // updateTraceEventDuration() must be called with the TraceEventHandle
110 // returned from addTraceEvent().
111 // - INSTANT ('I'): Standalone, instantaneous event.
112 // - START ('S'): Marks the beginning of an asynchronous event (the end
113 // event can occur in a different scope or thread). The id parameter is
114 // used to match START/FINISH pairs.
115 // - FINISH ('F'): Marks the end of an asynchronous event.
116 // - COUNTER ('C'): Used to trace integer quantities that change over
117 // time. The argument values are expected to be of type int.
118 // - METADATA ('M'): Reserved for internal use.
119 // - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag.
120 // - name is the name of the event. Also used to match BEGIN/END and
121 // START/FINISH pairs.
122 // - id optionally allows events of the same name to be distinguished from
123 // each other. For example, to trace the consutruction and destruction of
124 // objects, specify the pointer as the id parameter.
125 // - timestamp should be a time value returned from monotonicallyIncreasingTime.
126 // - numArgs specifies the number of elements in argNames, argTypes, and
127 // argValues.
128 // - argNames is the array of argument names. Use long-lived literal strings
129 // or specify the COPY flag.
130 // - argTypes is the array of argument types:
131 // - BOOL (1): bool
132 // - UINT (2): unsigned long long
133 // - INT (3): long long
134 // - DOUBLE (4): double
135 // - POINTER (5): void*
136 // - STRING (6): char* (long-lived null-terminated char* string)
137 // - COPY_STRING (7): char* (temporary null-terminated char* string)
138 // - CONVERTABLE (8): WebConvertableToTraceFormat
139 // - argValues is the array of argument values. Each value is the unsigned
140 // long long member of a union of all supported types.
141 // - flags can be 0 or one or more of the following, ORed together:
142 // - COPY (0x1): treat all strings (name, argNames and argValues of type
143 // string) as temporary so that they will be copied by addTraceEvent.
144 // - HAS_ID (0x2): use the id argument to uniquely identify the event for
145 // matching with other events of the same name.
146 // - MANGLE_ID (0x4): specify this flag if the id parameter is the value
147 // of a pointer.
148 using AddTraceEventFunc = angle::TraceEventHandle (*)(PlatformMethods *platform,
149 char phase,
150 const unsigned char *categoryEnabledFlag,
151 const char *name,
152 unsigned long long id,
153 double timestamp,
154 int numArgs,
155 const char **argNames,
156 const unsigned char *argTypes,
157 const unsigned long long *argValues,
158 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)159 inline angle::TraceEventHandle DefaultAddTraceEvent(PlatformMethods *platform,
160 char phase,
161 const unsigned char *categoryEnabledFlag,
162 const char *name,
163 unsigned long long id,
164 double timestamp,
165 int numArgs,
166 const char **argNames,
167 const unsigned char *argTypes,
168 const unsigned long long *argValues,
169 unsigned char flags)
170 {
171 return 0;
172 }
173
174 // Set the duration field of a COMPLETE trace event.
175 using UpdateTraceEventDurationFunc = void (*)(PlatformMethods *platform,
176 const unsigned char *categoryEnabledFlag,
177 const char *name,
178 angle::TraceEventHandle eventHandle);
DefaultUpdateTraceEventDuration(PlatformMethods * platform,const unsigned char * categoryEnabledFlag,const char * name,angle::TraceEventHandle eventHandle)179 inline void DefaultUpdateTraceEventDuration(PlatformMethods *platform,
180 const unsigned char *categoryEnabledFlag,
181 const char *name,
182 angle::TraceEventHandle eventHandle)
183 {
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 }
203 // Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample
204 // value.
205 using HistogramEnumerationFunc = void (*)(PlatformMethods *platform,
206 const char *name,
207 int sample,
208 int boundaryValue);
DefaultHistogramEnumeration(PlatformMethods * platform,const char * name,int sample,int boundaryValue)209 inline void DefaultHistogramEnumeration(PlatformMethods *platform,
210 const char *name,
211 int sample,
212 int boundaryValue)
213 {
214 }
215 // Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets.
216 using HistogramSparseFunc = void (*)(PlatformMethods *platform, const char *name, int sample);
DefaultHistogramSparse(PlatformMethods * platform,const char * name,int sample)217 inline void DefaultHistogramSparse(PlatformMethods *platform, const char *name, int sample)
218 {
219 }
220 // Boolean histograms track two-state variables.
221 using HistogramBooleanFunc = void (*)(PlatformMethods *platform, const char *name, bool sample);
DefaultHistogramBoolean(PlatformMethods * platform,const char * name,bool sample)222 inline void DefaultHistogramBoolean(PlatformMethods *platform, const char *name, bool sample)
223 {
224 }
225
226 // Allows us to programatically override ANGLE's default workarounds for testing purposes.
227 using OverrideWorkaroundsD3DFunc = void (*)(PlatformMethods *platform,
228 angle::WorkaroundsD3D *workaroundsD3D);
DefaultOverrideWorkaroundsD3D(PlatformMethods * platform,angle::WorkaroundsD3D * workaroundsD3D)229 inline void DefaultOverrideWorkaroundsD3D(PlatformMethods *platform,
230 angle::WorkaroundsD3D *workaroundsD3D)
231 {
232 }
233
234 // Callback on a successful program link with the program binary. Can be used to store
235 // shaders to disk. Keys are a 160-bit SHA-1 hash.
236 using ProgramKeyType = std::array<uint8_t, 20>;
237 using CacheProgramFunc = void (*)(PlatformMethods *platform,
238 const ProgramKeyType &key,
239 size_t programSize,
240 const uint8_t *programBytes);
DefaultCacheProgram(PlatformMethods * platform,const ProgramKeyType & key,size_t programSize,const uint8_t * programBytes)241 inline void DefaultCacheProgram(PlatformMethods *platform,
242 const ProgramKeyType &key,
243 size_t programSize,
244 const uint8_t *programBytes)
245 {
246 }
247
248 // Platform methods are enumerated here once.
249 #define ANGLE_PLATFORM_OP(OP) \
250 OP(currentTime, CurrentTime) \
251 OP(monotonicallyIncreasingTime, MonotonicallyIncreasingTime) \
252 OP(logError, LogError) \
253 OP(logWarning, LogWarning) \
254 OP(logInfo, LogInfo) \
255 OP(getTraceCategoryEnabledFlag, GetTraceCategoryEnabledFlag) \
256 OP(addTraceEvent, AddTraceEvent) \
257 OP(updateTraceEventDuration, UpdateTraceEventDuration) \
258 OP(histogramCustomCounts, HistogramCustomCounts) \
259 OP(histogramEnumeration, HistogramEnumeration) \
260 OP(histogramSparse, HistogramSparse) \
261 OP(histogramBoolean, HistogramBoolean) \
262 OP(overrideWorkaroundsD3D, OverrideWorkaroundsD3D) \
263 OP(cacheProgram, CacheProgram)
264
265 #define ANGLE_PLATFORM_METHOD_DEF(Name, CapsName) CapsName##Func Name = Default##CapsName;
266
267 struct ANGLE_PLATFORM_EXPORT PlatformMethods
268 {
269 PlatformMethods();
270
271 // User data pointer for any implementation specific members. Put it at the start of the
272 // platform structure so it doesn't become overwritten if one version of the platform
273 // adds or removes new members.
274 void *context = 0;
275
276 ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_DEF);
277 };
278
279 #undef ANGLE_PLATFORM_METHOD_DEF
280
281 // Subtract one to account for the context pointer.
282 constexpr unsigned int g_NumPlatformMethods = (sizeof(PlatformMethods) / sizeof(uintptr_t)) - 1;
283
284 #define ANGLE_PLATFORM_METHOD_STRING(Name) #Name
285 #define ANGLE_PLATFORM_METHOD_STRING2(Name, CapsName) ANGLE_PLATFORM_METHOD_STRING(Name),
286
287 constexpr const char *const g_PlatformMethodNames[g_NumPlatformMethods] = {
288 ANGLE_PLATFORM_OP(ANGLE_PLATFORM_METHOD_STRING2)};
289
290 #undef ANGLE_PLATFORM_METHOD_STRING2
291 #undef ANGLE_PLATFORM_METHOD_STRING
292
293 } // namespace angle
294
295 extern "C" {
296
297 // Gets the platform methods on the passed-in EGL display. If the method name signature does not
298 // match the compiled signature for this ANGLE, false is returned. On success true is returned.
299 // The application should set any platform methods it cares about on the returned pointer.
300 // If display is not valid, behaviour is undefined.
301
302 ANGLE_PLATFORM_EXPORT bool ANGLE_APIENTRY ANGLEGetDisplayPlatform(angle::EGLDisplayType display,
303 const char *const methodNames[],
304 unsigned int methodNameCount,
305 void *context,
306 void *platformMethodsOut);
307
308 // Sets the platform methods back to their defaults.
309 // If display is not valid, behaviour is undefined.
310 ANGLE_PLATFORM_EXPORT void ANGLE_APIENTRY ANGLEResetDisplayPlatform(angle::EGLDisplayType display);
311
312 } // extern "C"
313
314 namespace angle
315 {
316 typedef bool(ANGLE_APIENTRY *GetDisplayPlatformFunc)(angle::EGLDisplayType,
317 const char *const *,
318 unsigned int,
319 void *,
320 void *);
321 typedef void(ANGLE_APIENTRY *ResetDisplayPlatformFunc)(angle::EGLDisplayType);
322 } // namespace angle
323
324 // This function is not exported
325 angle::PlatformMethods *ANGLEPlatformCurrent();
326
327 #endif // ANGLE_PLATFORM_H
328