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
34namespace SkSL {
35
36#ifdef SKSL_STANDALONE
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 canUseMinAndAbsTogether() const {
59        return true;
60    }
61
62    bool mustForceNegatedAtanParamToFloat() const {
63        return false;
64    }
65
66    bool shaderDerivativeSupport() const {
67        return true;
68    }
69
70    bool usesPrecisionModifiers() const {
71        return true;
72    }
73
74    bool mustDeclareFragmentShaderOutput() const {
75        return true;
76    }
77
78    bool fbFetchSupport() const {
79        return true;
80    }
81
82    bool fbFetchNeedsCustomOutput() const {
83        return false;
84    }
85
86    bool bindlessTextureSupport() const {
87        return false;
88    }
89
90    bool dropsTileOnZeroDivide() const {
91        return false;
92    }
93
94    bool flatInterpolationSupport() const {
95        return true;
96    }
97
98    bool noperspectiveInterpolationSupport() const {
99        return true;
100    }
101
102    bool multisampleInterpolationSupport() const {
103        return true;
104    }
105
106    bool sampleVariablesSupport() const {
107        return true;
108    }
109
110    bool sampleMaskOverrideCoverageSupport() const {
111        return true;
112    }
113
114    bool externalTextureSupport() const {
115        return true;
116    }
117
118    bool texelFetchSupport() const {
119        return true;
120    }
121
122    bool imageLoadStoreSupport() const {
123        return true;
124    }
125
126    bool mustEnableAdvBlendEqs() const {
127        return false;
128    }
129
130    bool mustEnableSpecificAdvBlendEqs() const {
131        return false;
132    }
133
134    bool canUseAnyFunctionInShader() 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    const char* shaderDerivativeExtensionString() const {
147        return nullptr;
148    }
149
150    const char* fragCoordConventionsExtensionString() const {
151        return nullptr;
152    }
153
154    const char* imageLoadStoreExtensionString() const {
155        return nullptr;
156    }
157
158    const char* geometryShaderExtensionString() const {
159        return nullptr;
160    }
161
162    const char* gsInvocationsExtensionString() const {
163        return nullptr;
164    }
165
166    const char* versionDeclString() const {
167        return "";
168    }
169
170    bool gsInvocationsSupport() const {
171        return true;
172    }
173
174    bool canUseFractForNegativeValues() const {
175        return true;
176    }
177
178    bool canUseFragCoord() const {
179        return true;
180    }
181};
182
183extern StandaloneShaderCaps standaloneCaps;
184
185#else
186
187#define SKSL_CAPS_CLASS GrShaderCaps
188// Various sets of caps for use in tests
189class ShaderCapsFactory {
190public:
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
317void 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
325NORETURN 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