1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 struct VertexAttrib;
6 
7 namespace glsl {
8 
9 // Type holding group of scalars interpolated across rasterized rows and spans,
10 // shuttling values between vertex shaders and fragment shaders.
11 // GCC requires power-of-two vector sizes, so must use glsl type as workaround
12 // to operate in Float-sized chunks.
13 typedef vec3 Interpolants;
14 
15 // Clip distances, if enabled, are always stored in the first SIMD chunk of the
16 // interpolants.
get_clip_distances(const Interpolants & interp)17 static ALWAYS_INLINE Float get_clip_distances(const Interpolants& interp) {
18   return interp.x;
19 }
20 
21 struct VertexShaderImpl;
22 struct FragmentShaderImpl;
23 
24 struct ProgramImpl {
~ProgramImplProgramImpl25   virtual ~ProgramImpl() {}
26   virtual int get_uniform(const char* name) const = 0;
27   virtual void bind_attrib(const char* name, int index) = 0;
28   virtual int get_attrib(const char* name) const = 0;
29   virtual size_t interpolants_size() const = 0;
30   virtual VertexShaderImpl* get_vertex_shader() = 0;
31   virtual FragmentShaderImpl* get_fragment_shader() = 0;
32   virtual const char* get_name() const = 0;
33 };
34 
35 typedef ProgramImpl* (*ProgramLoader)();
36 
37 // The maximum size of the gl_ClipDistance array.
38 constexpr int32_t gl_MaxClipDistances = 4;
39 
40 struct VertexShaderImpl {
41   typedef void (*SetUniform1iFunc)(VertexShaderImpl*, int index, int value);
42   typedef void (*SetUniform4fvFunc)(VertexShaderImpl*, int index,
43                                     const float* value);
44   typedef void (*SetUniformMatrix4fvFunc)(VertexShaderImpl*, int index,
45                                           const float* value);
46   typedef void (*InitBatchFunc)(VertexShaderImpl*);
47   typedef void (*LoadAttribsFunc)(VertexShaderImpl*, VertexAttrib* attribs,
48                                   uint32_t start, int instance, int count);
49   typedef void (*RunPrimitiveFunc)(VertexShaderImpl*, char* interps,
50                                    size_t interp_stride);
51 
52   SetUniform1iFunc set_uniform_1i_func = nullptr;
53   SetUniform4fvFunc set_uniform_4fv_func = nullptr;
54   SetUniformMatrix4fvFunc set_uniform_matrix4fv_func = nullptr;
55   InitBatchFunc init_batch_func = nullptr;
56   LoadAttribsFunc load_attribs_func = nullptr;
57   RunPrimitiveFunc run_primitive_func = nullptr;
58 
59   enum FLAGS {
60     CLIP_DISTANCE = 1 << 0,
61   };
62   int flags = 0;
enable_clip_distanceVertexShaderImpl63   void enable_clip_distance() { flags |= CLIP_DISTANCE; }
use_clip_distanceVertexShaderImpl64   ALWAYS_INLINE bool use_clip_distance() const {
65     return (flags & CLIP_DISTANCE) != 0;
66   }
67 
68   vec4 gl_Position;
69   Float gl_ClipDistance[gl_MaxClipDistances];
70 
set_uniform_1iVertexShaderImpl71   void set_uniform_1i(int index, int value) {
72     (*set_uniform_1i_func)(this, index, value);
73   }
74 
set_uniform_4fvVertexShaderImpl75   void set_uniform_4fv(int index, const float* value) {
76     (*set_uniform_4fv_func)(this, index, value);
77   }
78 
set_uniform_matrix4fvVertexShaderImpl79   void set_uniform_matrix4fv(int index, const float* value) {
80     (*set_uniform_matrix4fv_func)(this, index, value);
81   }
82 
init_batchVertexShaderImpl83   void init_batch() { (*init_batch_func)(this); }
84 
load_attribsVertexShaderImpl85   ALWAYS_INLINE void load_attribs(VertexAttrib* attribs, uint32_t start,
86                                   int instance, int count) {
87     (*load_attribs_func)(this, attribs, start, instance, count);
88   }
89 
run_primitiveVertexShaderImpl90   ALWAYS_INLINE void run_primitive(char* interps, size_t interp_stride) {
91     (*run_primitive_func)(this, interps, interp_stride);
92   }
93 };
94 
95 // The number of pixels in a step.
96 constexpr int32_t swgl_StepSize = 4;
97 
98 struct FragmentShaderImpl {
99   typedef void (*InitSpanFunc)(FragmentShaderImpl*, const void* interps,
100                                const void* step);
101   typedef void (*RunFunc)(FragmentShaderImpl*);
102   typedef void (*SkipFunc)(FragmentShaderImpl*, int steps);
103   typedef void (*InitSpanWFunc)(FragmentShaderImpl*, const void* interps,
104                                 const void* step);
105   typedef void (*RunWFunc)(FragmentShaderImpl*);
106   typedef void (*SkipWFunc)(FragmentShaderImpl*, int steps);
107   typedef int (*DrawSpanRGBA8Func)(FragmentShaderImpl*);
108   typedef int (*DrawSpanR8Func)(FragmentShaderImpl*);
109 
110   InitSpanFunc init_span_func = nullptr;
111   RunFunc run_func = nullptr;
112   SkipFunc skip_func = nullptr;
113   InitSpanWFunc init_span_w_func = nullptr;
114   RunWFunc run_w_func = nullptr;
115   SkipWFunc skip_w_func = nullptr;
116   DrawSpanRGBA8Func draw_span_RGBA8_func = nullptr;
117   DrawSpanR8Func draw_span_R8_func = nullptr;
118 
119   enum FLAGS {
120     DISCARD = 1 << 0,
121     PERSPECTIVE = 1 << 1,
122   };
123   int flags = 0;
enable_discardFragmentShaderImpl124   void enable_discard() { flags |= DISCARD; }
enable_perspectiveFragmentShaderImpl125   void enable_perspective() { flags |= PERSPECTIVE; }
use_discardFragmentShaderImpl126   ALWAYS_INLINE bool use_discard() const { return (flags & DISCARD) != 0; }
use_perspectiveFragmentShaderImpl127   ALWAYS_INLINE bool use_perspective() const {
128     return (flags & PERSPECTIVE) != 0;
129   }
130 
131   vec4 gl_FragCoord;
132   vec4 gl_FragColor;
133   vec4 gl_SecondaryFragColor;
134 
135   vec2_scalar swgl_StepZW;
136   Bool swgl_IsPixelDiscarded = false;
137   // The current buffer position for committing span output.
138   uint32_t* swgl_OutRGBA8 = nullptr;
139   uint8_t* swgl_OutR8 = nullptr;
140   // The remaining number of pixels in the span.
141   int32_t swgl_SpanLength = 0;
142 
143   ALWAYS_INLINE void step_fragcoord(int steps = 4) { gl_FragCoord.x += steps; }
144 
145   ALWAYS_INLINE void step_perspective(int steps = 4) {
146     gl_FragCoord.z += swgl_StepZW.x * steps;
147     gl_FragCoord.w += swgl_StepZW.y * steps;
148   }
149 
150   template <bool W = false>
init_spanFragmentShaderImpl151   ALWAYS_INLINE void init_span(const void* interps, const void* step) {
152     (*(W ? init_span_w_func : init_span_func))(this, interps, step);
153   }
154 
155   template <bool W = false>
runFragmentShaderImpl156   ALWAYS_INLINE void run() {
157     (*(W ? run_w_func : run_func))(this);
158   }
159 
160   template <bool W = false>
161   ALWAYS_INLINE void skip(int steps = 4) {
162     (*(W ? skip_w_func : skip_func))(this, steps);
163   }
164 
draw_spanFragmentShaderImpl165   ALWAYS_INLINE int draw_span(uint32_t* buf, int len) {
166     swgl_OutRGBA8 = buf;
167     swgl_SpanLength = len;
168     return (*draw_span_RGBA8_func)(this);
169   }
170 
has_draw_spanFragmentShaderImpl171   ALWAYS_INLINE bool has_draw_span(uint32_t*) {
172     return draw_span_RGBA8_func != nullptr;
173   }
174 
draw_spanFragmentShaderImpl175   ALWAYS_INLINE int draw_span(uint8_t* buf, int len) {
176     swgl_OutR8 = buf;
177     swgl_SpanLength = len;
178     return (*draw_span_R8_func)(this);
179   }
180 
has_draw_spanFragmentShaderImpl181   ALWAYS_INLINE bool has_draw_span(uint8_t*) {
182     return draw_span_R8_func != nullptr;
183   }
184 };
185 
186 }  // namespace glsl
187