1/*
2 * Copyright 2016 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SKSL_UTIL
9#define SKSL_UTIL
10
11#include <cstdarg>
12#include <memory>
13#include "stdlib.h"
14#include "string.h"
15#include "src/sksl/SkSLDefines.h"
16#include "src/sksl/SkSLLexer.h"
17
18#ifndef SKSL_STANDALONE
19#include "include/core/SkTypes.h"
20#include "include/private/GrTypesPriv.h"
21#if SK_SUPPORT_GPU
22#include "include/gpu/GrContextOptions.h"
23#include "src/gpu/GrShaderCaps.h"
24#endif // SK_SUPPORT_GPU
25#endif // SKSL_STANDALONE
26
27class GrShaderCaps;
28
29namespace SkSL {
30
31class Context;
32class OutputStream;
33class StringStream;
34class Type;
35
36#if defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU
37
38// we're being compiled standalone, so we don't have access to caps...
39enum GrGLSLGeneration {
40 k110_GrGLSLGeneration,
41 k130_GrGLSLGeneration,
42 k140_GrGLSLGeneration,
43 k150_GrGLSLGeneration,
44 k330_GrGLSLGeneration,
45 k400_GrGLSLGeneration,
46 k420_GrGLSLGeneration,
47 k310es_GrGLSLGeneration,
48 k320es_GrGLSLGeneration,
49};
50
51#define SKSL_CAPS_CLASS StandaloneShaderCaps
52class StandaloneShaderCaps {
53public:
54 GrGLSLGeneration generation() const {
55 return k400_GrGLSLGeneration;
56 }
57
58 bool atan2ImplementedAsAtanYOverX() const {
59 return false;
60 }
61
62 bool canUseMinAndAbsTogether() const {
63 return true;
64 }
65
66 bool mustForceNegatedAtanParamToFloat() const {
67 return false;
68 }
69
70 bool shaderDerivativeSupport() const {
71 return true;
72 }
73
74 bool usesPrecisionModifiers() const {
75 return true;
76 }
77
78 bool mustDeclareFragmentShaderOutput() const {
79 return true;
80 }
81
82 bool fbFetchSupport() const {
83 return true;
84 }
85
86 bool fbFetchNeedsCustomOutput() const {
87 return false;
88 }
89
90 bool flatInterpolationSupport() const {
91 return true;
92 }
93
94 bool noperspectiveInterpolationSupport() const {
95 return true;
96 }
97
98 bool multisampleInterpolationSupport() const {
99 return true;
100 }
101
102 bool sampleMaskSupport() const {
103 return true;
104 }
105
106 bool externalTextureSupport() const {
107 return true;
108 }
109
110 bool mustDoOpBetweenFloorAndAbs() const {
111 return false;
112 }
113
114 bool mustGuardDivisionEvenAfterExplicitZeroCheck() const {
115 return false;
116 }
117
118 bool inBlendModesFailRandomlyForAllZeroVec() const {
119 return false;
120 }
121
122 bool mustEnableAdvBlendEqs() const {
123 return false;
124 }
125
126 bool mustEnableSpecificAdvBlendEqs() const {
127 return false;
128 }
129
130 bool canUseAnyFunctionInShader() const {
131 return false;
132 }
133
134 bool noDefaultPrecisionForExternalSamplers() const {
135 return false;
136 }
137
138 bool floatIs32Bits() const {
139 return true;
140 }
141
142 bool integerSupport() const {
143 return false;
144 }
145
146 bool builtinFMASupport() const {
147 return true;
148 }
149
150 bool canUseDoLoops() const {
151 // we define this to false in standalone so we don't use do loops while inlining in FP files
152 // (which would then, being baked in, end up being used even in contexts where do loops are
153 // not allowed)
154 return false;
155 }
156
157 const char* shaderDerivativeExtensionString() const {
158 return nullptr;
159 }
160
161 const char* fragCoordConventionsExtensionString() const {
162 return nullptr;
163 }
164
165 const char* geometryShaderExtensionString() const {
166 return nullptr;
167 }
168
169 const char* gsInvocationsExtensionString() const {
170 return nullptr;
171 }
172
173 const char* externalTextureExtensionString() const {
174 return nullptr;
175 }
176
177 const char* secondExternalTextureExtensionString() const {
178 return nullptr;
179 }
180
181 const char* versionDeclString() const {
182 return "";
183 }
184
185 bool gsInvocationsSupport() const {
186 return true;
187 }
188
189 bool canUseFractForNegativeValues() const {
190 return true;
191 }
192
193 bool canUseFragCoord() const {
194 return true;
195 }
196
197 bool incompleteShortIntPrecision() const {
198 return false;
199 }
200
201 bool addAndTrueToLoopCondition() const {
202 return false;
203 }
204
205 bool unfoldShortCircuitAsTernary() const {
206 return false;
207 }
208
209 bool emulateAbsIntFunction() const {
210 return false;
211 }
212
213 bool rewriteDoWhileLoops() const {
214 return false;
215 }
216
217 bool removePowWithConstantExponent() const {
218 return false;
219 }
220
221 const char* fbFetchColorName() const {
222 return nullptr;
223 }
224};
225
226extern StandaloneShaderCaps standaloneCaps;
227
228#else
229
230#define SKSL_CAPS_CLASS GrShaderCaps
231// Various sets of caps for use in tests
232class ShaderCapsFactory {
233public:
234 static sk_sp<GrShaderCaps> Default() {
235 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
236 result->fVersionDeclString = "#version 400";
237 result->fShaderDerivativeSupport = true;
238 return result;
239 }
240
241 static sk_sp<GrShaderCaps> Version450Core() {
242 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
243 result->fVersionDeclString = "#version 450 core";
244 return result;
245 }
246
247 static sk_sp<GrShaderCaps> Version110() {
248 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
249 result->fVersionDeclString = "#version 110";
250 result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration;
251 return result;
252 }
253
254 static sk_sp<GrShaderCaps> UsesPrecisionModifiers() {
255 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
256 result->fVersionDeclString = "#version 400";
257 result->fUsesPrecisionModifiers = true;
258 return result;
259 }
260
261 static sk_sp<GrShaderCaps> CannotUseMinAndAbsTogether() {
262 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
263 result->fVersionDeclString = "#version 400";
264 result->fCanUseMinAndAbsTogether = false;
265 return result;
266 }
267
268 static sk_sp<GrShaderCaps> CannotUseFractForNegativeValues() {
269 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
270 result->fVersionDeclString = "#version 400";
271 result->fCanUseFractForNegativeValues = false;
272 return result;
273 }
274
275 static sk_sp<GrShaderCaps> MustForceNegatedAtanParamToFloat() {
276 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
277 result->fVersionDeclString = "#version 400";
278 result->fMustForceNegatedAtanParamToFloat = true;
279 return result;
280 }
281
282 static sk_sp<GrShaderCaps> ShaderDerivativeExtensionString() {
283 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
284 result->fVersionDeclString = "#version 400";
285 result->fShaderDerivativeSupport = true;
286 result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives";
287 result->fUsesPrecisionModifiers = true;
288 return result;
289 }
290
291 static sk_sp<GrShaderCaps> FragCoordsOld() {
292 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
293 result->fVersionDeclString = "#version 110";
294 result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration;
295 result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions";
296 return result;
297 }
298
299 static sk_sp<GrShaderCaps> FragCoordsNew() {
300 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
301 result->fVersionDeclString = "#version 400";
302 result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions";
303 return result;
304 }
305
306 static sk_sp<GrShaderCaps> GeometryShaderSupport() {
307 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
308 result->fVersionDeclString = "#version 400";
309 result->fGeometryShaderSupport = true;
310 result->fGSInvocationsSupport = true;
311 return result;
312 }
313
314 static sk_sp<GrShaderCaps> NoGSInvocationsSupport() {
315 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
316 result->fVersionDeclString = "#version 400";
317 result->fGeometryShaderSupport = true;
318 result->fGSInvocationsSupport = false;
319 return result;
320 }
321
322 static sk_sp<GrShaderCaps> GeometryShaderExtensionString() {
323 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
324 result->fVersionDeclString = "#version 310es";
325 result->fGeometryShaderSupport = true;
326 result->fGeometryShaderExtensionString = "GL_EXT_geometry_shader";
327 result->fGSInvocationsSupport = true;
328 return result;
329 }
330
331 static sk_sp<GrShaderCaps> GSInvocationsExtensionString() {
332 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
333 result->fVersionDeclString = "#version 400";
334 result->fGeometryShaderSupport = true;
335 result->fGSInvocationsSupport = true;
336 result->fGSInvocationsExtensionString = "GL_ARB_gpu_shader5";
337 return result;
338 }
339
340 static sk_sp<GrShaderCaps> VariousCaps() {
341 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
342 result->fVersionDeclString = "#version 400";
343 result->fExternalTextureSupport = true;
344 result->fFBFetchSupport = false;
345 result->fCanUseAnyFunctionInShader = false;
346 return result;
347 }
348
349 static sk_sp<GrShaderCaps> CannotUseFragCoord() {
350 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
351 result->fVersionDeclString = "#version 400";
352 result->fCanUseFragCoord = false;
353 return result;
354 }
355
356 static sk_sp<GrShaderCaps> IncompleteShortIntPrecision() {
357 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
358 result->fVersionDeclString = "#version 310es";
359 result->fUsesPrecisionModifiers = true;
360 result->fIncompleteShortIntPrecision = true;
361 return result;
362 }
363
364 static sk_sp<GrShaderCaps> AddAndTrueToLoopCondition() {
365 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
366 result->fVersionDeclString = "#version 400";
367 result->fAddAndTrueToLoopCondition = true;
368 return result;
369 }
370
371 static sk_sp<GrShaderCaps> UnfoldShortCircuitAsTernary() {
372 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
373 result->fVersionDeclString = "#version 400";
374 result->fUnfoldShortCircuitAsTernary = true;
375 return result;
376 }
377
378 static sk_sp<GrShaderCaps> EmulateAbsIntFunction() {
379 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
380 result->fVersionDeclString = "#version 400";
381 result->fEmulateAbsIntFunction = true;
382 return result;
383 }
384
385 static sk_sp<GrShaderCaps> RewriteDoWhileLoops() {
386 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
387 result->fVersionDeclString = "#version 400";
388 result->fRewriteDoWhileLoops = true;
389 return result;
390 }
391
392 static sk_sp<GrShaderCaps> RemovePowWithConstantExponent() {
393 sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
394 result->fVersionDeclString = "#version 400";
395 result->fRemovePowWithConstantExponent = true;
396 return result;
397 }
398
399 static sk_sp<GrShaderCaps> SampleMaskSupport() {
400 sk_sp<GrShaderCaps> result = Default();
401 result->fSampleMaskSupport = true;
402 return result;
403 }
404};
405#endif
406
407#if !defined(SKSL_STANDALONE)
408bool type_to_grsltype(const Context& context, const Type& type, GrSLType* outType);
409#endif
410
411void write_stringstream(const StringStream& d, OutputStream& out);
412
413// Returns true if op is '=' or any compound assignment operator ('+=', '-=', etc.)
414bool is_assignment(Token::Kind op);
415
416// Given a compound assignment operator, returns the non-assignment version of the operator (e.g.
417// '+=' becomes '+')
418Token::Kind remove_assignment(Token::Kind op);
419
420NORETURN void sksl_abort();
421
422} // namespace SkSL
423
424#endif
425