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 "assert.h"
16 #include "SkSLString.h"
17 #include "SkSLStringStream.h"
18 
19 #ifndef SKSL_STANDALONE
20 #include "GrContextOptions.h"
21 #include "GrShaderCaps.h"
22 #endif
23 
24 #ifdef SKSL_STANDALONE
25 #if defined(_WIN32) || defined(__SYMBIAN32__)
26 #define SKSL_BUILD_FOR_WIN
27 #endif
28 #else
29 #ifdef SK_BUILD_FOR_WIN
30 #define SKSL_BUILD_FOR_WIN
31 #endif // SK_BUILD_FOR_WIN
32 #endif // SKSL_STANDALONE
33 
34 namespace SkSL {
35 
36 #ifdef SKSL_STANDALONE
37 
38 // we're being compiled standalone, so we don't have access to caps...
39 enum 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
52 class StandaloneShaderCaps {
53 public:
generation()54     GrGLSLGeneration generation() const {
55         return k400_GrGLSLGeneration;
56     }
57 
canUseMinAndAbsTogether()58     bool canUseMinAndAbsTogether() const {
59         return true;
60     }
61 
mustForceNegatedAtanParamToFloat()62     bool mustForceNegatedAtanParamToFloat() const {
63         return false;
64     }
65 
shaderDerivativeSupport()66     bool shaderDerivativeSupport() const {
67         return true;
68     }
69 
usesPrecisionModifiers()70     bool usesPrecisionModifiers() const {
71         return true;
72     }
73 
mustDeclareFragmentShaderOutput()74     bool mustDeclareFragmentShaderOutput() const {
75         return true;
76     }
77 
fbFetchSupport()78     bool fbFetchSupport() const {
79         return true;
80     }
81 
fbFetchNeedsCustomOutput()82     bool fbFetchNeedsCustomOutput() const {
83         return false;
84     }
85 
bindlessTextureSupport()86     bool bindlessTextureSupport() const {
87         return false;
88     }
89 
dropsTileOnZeroDivide()90     bool dropsTileOnZeroDivide() const {
91         return false;
92     }
93 
flatInterpolationSupport()94     bool flatInterpolationSupport() const {
95         return true;
96     }
97 
noperspectiveInterpolationSupport()98     bool noperspectiveInterpolationSupport() const {
99         return true;
100     }
101 
multisampleInterpolationSupport()102     bool multisampleInterpolationSupport() const {
103         return true;
104     }
105 
sampleVariablesSupport()106     bool sampleVariablesSupport() const {
107         return true;
108     }
109 
sampleMaskOverrideCoverageSupport()110     bool sampleMaskOverrideCoverageSupport() const {
111         return true;
112     }
113 
externalTextureSupport()114     bool externalTextureSupport() const {
115         return true;
116     }
117 
texelFetchSupport()118     bool texelFetchSupport() const {
119         return true;
120     }
121 
imageLoadStoreSupport()122     bool imageLoadStoreSupport() const {
123         return true;
124     }
125 
mustEnableAdvBlendEqs()126     bool mustEnableAdvBlendEqs() const {
127         return false;
128     }
129 
mustEnableSpecificAdvBlendEqs()130     bool mustEnableSpecificAdvBlendEqs() const {
131         return false;
132     }
133 
canUseAnyFunctionInShader()134     bool canUseAnyFunctionInShader() const {
135         return false;
136     }
137 
floatIs32Bits()138     bool floatIs32Bits() const {
139         return true;
140     }
141 
integerSupport()142     bool integerSupport() const {
143         return false;
144     }
145 
shaderDerivativeExtensionString()146     const char* shaderDerivativeExtensionString() const {
147         return nullptr;
148     }
149 
fragCoordConventionsExtensionString()150     const char* fragCoordConventionsExtensionString() const {
151         return nullptr;
152     }
153 
imageLoadStoreExtensionString()154     const char* imageLoadStoreExtensionString() const {
155         return nullptr;
156     }
157 
geometryShaderExtensionString()158     const char* geometryShaderExtensionString() const {
159         return nullptr;
160     }
161 
gsInvocationsExtensionString()162     const char* gsInvocationsExtensionString() const {
163         return nullptr;
164     }
165 
versionDeclString()166     const char* versionDeclString() const {
167         return "";
168     }
169 
gsInvocationsSupport()170     bool gsInvocationsSupport() const {
171         return true;
172     }
173 
canUseFractForNegativeValues()174     bool canUseFractForNegativeValues() const {
175         return true;
176     }
177 
canUseFragCoord()178     bool canUseFragCoord() const {
179         return true;
180     }
181 };
182 
183 extern StandaloneShaderCaps standaloneCaps;
184 
185 #else
186 
187 #define SKSL_CAPS_CLASS GrShaderCaps
188 // Various sets of caps for use in tests
189 class ShaderCapsFactory {
190 public:
191     static sk_sp<GrShaderCaps> Default() {
192         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
193         result->fVersionDeclString = "#version 400";
194         result->fShaderDerivativeSupport = true;
195         return result;
196     }
197 
198     static sk_sp<GrShaderCaps> Version450Core() {
199         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
200         result->fVersionDeclString = "#version 450 core";
201         return result;
202     }
203 
204     static sk_sp<GrShaderCaps> Version110() {
205         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
206         result->fVersionDeclString = "#version 110";
207         result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration;
208         return result;
209     }
210 
211     static sk_sp<GrShaderCaps> UsesPrecisionModifiers() {
212         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
213         result->fVersionDeclString = "#version 400";
214         result->fUsesPrecisionModifiers = true;
215         return result;
216     }
217 
218     static sk_sp<GrShaderCaps> CannotUseMinAndAbsTogether() {
219         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
220         result->fVersionDeclString = "#version 400";
221         result->fCanUseMinAndAbsTogether = false;
222         return result;
223     }
224 
225     static sk_sp<GrShaderCaps> CannotUseFractForNegativeValues() {
226         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
227         result->fVersionDeclString = "#version 400";
228         result->fCanUseFractForNegativeValues = false;
229         return result;
230     }
231 
232     static sk_sp<GrShaderCaps> MustForceNegatedAtanParamToFloat() {
233         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
234         result->fVersionDeclString = "#version 400";
235         result->fMustForceNegatedAtanParamToFloat = true;
236         return result;
237     }
238 
239     static sk_sp<GrShaderCaps> ShaderDerivativeExtensionString() {
240         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
241         result->fVersionDeclString = "#version 400";
242         result->fShaderDerivativeSupport = true;
243         result->fShaderDerivativeExtensionString = "GL_OES_standard_derivatives";
244         result->fUsesPrecisionModifiers = true;
245         return result;
246     }
247 
248     static sk_sp<GrShaderCaps> FragCoordsOld() {
249         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
250         result->fVersionDeclString = "#version 110";
251         result->fGLSLGeneration = GrGLSLGeneration::k110_GrGLSLGeneration;
252         result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions";
253         return result;
254     }
255 
256     static sk_sp<GrShaderCaps> FragCoordsNew() {
257         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
258         result->fVersionDeclString = "#version 400";
259         result->fFragCoordConventionsExtensionString = "GL_ARB_fragment_coord_conventions";
260         return result;
261     }
262 
263     static sk_sp<GrShaderCaps> GeometryShaderSupport() {
264         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
265         result->fVersionDeclString = "#version 400";
266         result->fGeometryShaderSupport = true;
267         result->fGSInvocationsSupport = true;
268         return result;
269     }
270 
271     static sk_sp<GrShaderCaps> NoGSInvocationsSupport() {
272         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
273         result->fVersionDeclString = "#version 400";
274         result->fGeometryShaderSupport = true;
275         result->fGSInvocationsSupport = false;
276         return result;
277     }
278 
279     static sk_sp<GrShaderCaps> GeometryShaderExtensionString() {
280         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
281         result->fVersionDeclString = "#version 310es";
282         result->fGeometryShaderSupport = true;
283         result->fGeometryShaderExtensionString = "GL_EXT_geometry_shader";
284         result->fGSInvocationsSupport = true;
285         return result;
286     }
287 
288     static sk_sp<GrShaderCaps> GSInvocationsExtensionString() {
289         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
290         result->fVersionDeclString = "#version 400";
291         result->fGeometryShaderSupport = true;
292         result->fGSInvocationsSupport = true;
293         result->fGSInvocationsExtensionString = "GL_ARB_gpu_shader5";
294         return result;
295     }
296 
297     static sk_sp<GrShaderCaps> VariousCaps() {
298         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
299         result->fVersionDeclString = "#version 400";
300         result->fExternalTextureSupport = true;
301         result->fFBFetchSupport = false;
302         result->fDropsTileOnZeroDivide = true;
303         result->fTexelFetchSupport = true;
304         result->fCanUseAnyFunctionInShader = false;
305         return result;
306     }
307 
308     static sk_sp<GrShaderCaps> CannotUseFragCoord() {
309         sk_sp<GrShaderCaps> result = sk_make_sp<GrShaderCaps>(GrContextOptions());
310         result->fVersionDeclString = "#version 400";
311         result->fCanUseFragCoord = false;
312         return result;
313     }
314 };
315 #endif
316 
317 void write_stringstream(const StringStream& d, OutputStream& out);
318 
319 #if _MSC_VER
320 #define NORETURN __declspec(noreturn)
321 #else
322 #define NORETURN __attribute__((__noreturn__))
323 #endif
324 
325 NORETURN void sksl_abort();
326 
327 } // namespace
328 
329 #ifdef SKSL_STANDALONE
330 #define ASSERT(x) (void)((x) || (ABORT("failed assert(%s): %s:%d\n", #x, __FILE__, __LINE__), 0))
331 #define ASSERT_RESULT(x) ASSERT(x)
332 #define SKSL_DEBUGCODE(x) x
333 #else
334 #define ASSERT SkASSERT
335 #define ASSERT_RESULT(x) SkAssertResult(x)
336 #define SKSL_DEBUGCODE(x) SkDEBUGCODE(x)
337 #endif
338 
339 #define SKSL_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
340 
341 #if defined(__clang__) || defined(__GNUC__)
342 #define SKSL_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
343 #else
344 #define SKSL_PRINTF_LIKE(A, B)
345 #endif
346 
347 #define ABORT(...) (printf(__VA_ARGS__), sksl_abort())
348 
349 #endif
350