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