brush.glsl (10015B)
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 /// # Brush vertex shaders memory layout 6 /// 7 /// The overall memory layout is the same for all brush shaders. 8 /// 9 /// The vertex shader receives a minimal amount of data from vertex attributes (packed into a single 10 /// ivec4 per instance) and the rest is fetched from various uniform samplers using offsets decoded 11 /// from the vertex attributes. 12 /// 13 /// The diagram below shows the the various pieces of data fectched in the vertex shader: 14 /// 15 ///```ascii 16 /// (sPrimitiveHeadersI) 17 /// (VBO) +-----------------------+ 18 /// +----------------------------+ +----------------------------> | Int header | 19 /// | Instance vertex attributes | | (sPrimitiveHeadersF) | | 20 /// | | | +---------------------+ | z | 21 /// | x: prim_header_address +-------+---> | Float header | | specific_address +-----+ 22 /// | y: picture_task_address +---------+ | | | transform_address +---+ | 23 /// | clip_address +-----+ | | local_rect | | user_data | | | 24 /// | z: flags | | | | local_clip_rect | +-----------------------+ | | 25 /// | segment_index | | | +---------------------+ | | 26 /// | w: resource_address +--+ | | | | 27 /// +----------------------------+ | | | (float gpu buffer) | | 28 /// | | | (float gpu buffer) +------------+ | | 29 /// | | | +---------------+ | Transform | <--------+ | 30 /// (float gpu buffer) | | +-> | Picture task | +------------+ | 31 /// +-------------+ | | | | | 32 /// | Resource | <---+ | | ... | | 33 /// | | | +---------------+ +--------------------------------+ 34 /// | | | | 35 /// +-------------+ | (float gpu buffer) v (float gpu buffer) 36 /// | +---------------+ +--------------+---------------+-+-+ 37 /// +-----> | Clip area | | Brush data | Segment data | | | 38 /// | | | | | | | 39 /// | ... | | ... | ... | | | ... 40 /// +---------------+ +--------------+---------------+-+-+ 41 ///``` 42 /// 43 /// - Segment data address is obtained by combining the address stored in the int header and the 44 /// segment index decoded from the vertex attributes. 45 /// - Resource data is optional, some brush types (such as images) store some extra data there while 46 /// other brush types don't use it. 47 /// 48 49 #if (defined(WR_FEATURE_ALPHA_PASS) || defined(WR_FEATURE_ANTIALIASING)) && !defined(SWGL_ANTIALIAS) 50 varying highp vec2 v_local_pos; 51 #endif 52 53 #ifdef WR_VERTEX_SHADER 54 55 void brush_vs( 56 VertexInfo vi, 57 int prim_address, 58 RectWithEndpoint local_rect, 59 RectWithEndpoint segment_rect, 60 ivec4 prim_user_data, 61 int specific_resource_address, 62 mat4 transform, 63 PictureTask pic_task, 64 int brush_flags, 65 vec4 segment_data 66 ); 67 68 // Forward-declare the text vertex shader entry point which is currently 69 // different from other brushes. 70 void text_shader_main( 71 Instance instance, 72 PrimitiveHeader ph, 73 Transform transform, 74 PictureTask task, 75 ClipArea clip_area 76 ); 77 78 #define VECS_PER_SEGMENT 2 79 80 #define BRUSH_FLAG_PERSPECTIVE_INTERPOLATION 1 81 #define BRUSH_FLAG_SEGMENT_RELATIVE 2 82 #define BRUSH_FLAG_SEGMENT_REPEAT_X 4 83 #define BRUSH_FLAG_SEGMENT_REPEAT_Y 8 84 #define BRUSH_FLAG_SEGMENT_REPEAT_X_ROUND 16 85 #define BRUSH_FLAG_SEGMENT_REPEAT_Y_ROUND 32 86 #define BRUSH_FLAG_SEGMENT_REPEAT_X_CENTERED 64 87 #define BRUSH_FLAG_SEGMENT_REPEAT_Y_CENTERED 128 88 #define BRUSH_FLAG_SEGMENT_NINEPATCH_MIDDLE 256 89 #define BRUSH_FLAG_TEXEL_RECT 512 90 #define BRUSH_FLAG_FORCE_AA 1024 91 #define BRUSH_FLAG_NORMALIZED_UVS 2048 92 93 #define INVALID_SEGMENT_INDEX 0xffff 94 95 void brush_shader_main_vs( 96 Instance instance, 97 PrimitiveHeader ph, 98 Transform transform, 99 PictureTask pic_task, 100 ClipArea clip_area 101 ) { 102 int edge_flags = (instance.flags >> 12) & 0xf; 103 int brush_flags = instance.flags & 0xfff; 104 105 // Fetch the segment of this brush primitive we are drawing. 106 vec4 segment_data; 107 RectWithEndpoint segment_rect; 108 if (instance.segment_index == INVALID_SEGMENT_INDEX) { 109 segment_rect = ph.local_rect; 110 segment_data = vec4(0.0); 111 } else { 112 // See BrushSegmentGpuData 113 int segment_address = ph.specific_prim_address + 114 VECS_PER_SPECIFIC_BRUSH + 115 instance.segment_index * VECS_PER_SEGMENT; 116 117 vec4[2] segment_info = fetch_from_gpu_buffer_2f(segment_address); 118 segment_rect = RectWithEndpoint(segment_info[0].xy, segment_info[0].zw); 119 segment_rect.p0 += ph.local_rect.p0; 120 segment_rect.p1 += ph.local_rect.p0; 121 segment_data = segment_info[1]; 122 } 123 124 // Most of the time this is the segment rect, but when doing the edge AA 125 // it is inflated. 126 RectWithEndpoint adjusted_segment_rect = segment_rect; 127 128 bool antialiased = !transform.is_axis_aligned || ((brush_flags & BRUSH_FLAG_FORCE_AA) != 0); 129 130 // Write the normal vertex information out. 131 if (antialiased) { 132 adjusted_segment_rect = clip_and_init_antialiasing( 133 segment_rect, 134 ph.local_rect, 135 ph.local_clip_rect, 136 edge_flags, 137 ph.z, 138 transform, 139 pic_task 140 ); 141 142 // The clip was taken into account in clip_and_init_antialiasing, remove 143 // it so that it doesn't interfere with the aa. 144 ph.local_clip_rect.p0 = vec2(-1.0e16); 145 ph.local_clip_rect.p1 = vec2(1.0e16); 146 } else { 147 // The common case for most CSS content. 148 149 // TODO(gw): transform bounds may be referenced by 150 // the fragment shader when running in 151 // the alpha pass, even on non-transformed 152 // items. For now, just ensure it has no 153 // effect. We can tidy this up as we move 154 // more items to be brush shaders. 155 #if defined(WR_FEATURE_ALPHA_PASS) && !defined(SWGL_ANTIALIAS) 156 rectangle_aa_vertex(vec4(vec2(-1.0e16), vec2(1.0e16))); 157 #endif 158 } 159 160 // Select the corner of the local rect that we are processing. 161 vec2 local_pos = mix(adjusted_segment_rect.p0, adjusted_segment_rect.p1, aPosition.xy); 162 163 VertexInfo vi = write_vertex( 164 local_pos, 165 ph.local_clip_rect, 166 ph.z, 167 transform, 168 pic_task 169 ); 170 171 // For brush instances in the alpha pass, always write 172 // out clip information. 173 // TODO(gw): It's possible that we might want alpha 174 // shaders that don't clip in the future, 175 // but it's reasonable to assume that one 176 // implies the other, for now. 177 // SW-WR may decay some requests for alpha-pass shaders to 178 // the opaque version if only the clip-mask is required. In 179 // that case the opaque vertex shader must still write out 180 // the clip information, which is cheap to do for SWGL. 181 #if defined(WR_FEATURE_ALPHA_PASS) || defined(SWGL_CLIP_MASK) 182 write_clip( 183 vi.world_pos, 184 clip_area, 185 pic_task 186 ); 187 #endif 188 189 // Run the specific brush VS code to write interpolators. 190 brush_vs( 191 vi, 192 ph.specific_prim_address, 193 ph.local_rect, 194 segment_rect, 195 ph.user_data, 196 instance.resource_address, 197 transform.m, 198 pic_task, 199 brush_flags, 200 segment_data 201 ); 202 203 #if (defined(WR_FEATURE_ALPHA_PASS) || defined(WR_FEATURE_ANTIALIASING)) && !defined(SWGL_ANTIALIAS) 204 v_local_pos = vi.local_pos; 205 #endif 206 } 207 208 #ifndef WR_VERTEX_SHADER_MAIN_FUNCTION 209 // If the entry-point was not overridden before including the brush shader, 210 // use the default one. 211 #define WR_VERTEX_SHADER_MAIN_FUNCTION brush_shader_main_vs 212 #endif 213 214 void main(void) { 215 216 Instance instance = decode_instance_attributes(); 217 PrimitiveHeader ph = fetch_prim_header(instance.prim_header_address); 218 Transform transform = fetch_transform(ph.transform_id); 219 PictureTask task = fetch_picture_task(ph.picture_task_address); 220 ClipArea clip_area = fetch_clip_area(instance.clip_address); 221 222 WR_VERTEX_SHADER_MAIN_FUNCTION(instance, ph, transform, task, clip_area); 223 } 224 225 #endif // WR_VERTEX_SHADER 226 227 #ifdef WR_FRAGMENT_SHADER 228 229 float antialias_brush() { 230 #if (defined(WR_FEATURE_ALPHA_PASS) || defined(WR_FEATURE_ANTIALIASING)) && !defined(SWGL_ANTIALIAS) 231 return rectangle_aa_fragment(v_local_pos); 232 #else 233 return 1.0; 234 #endif 235 } 236 237 Fragment brush_fs(); 238 239 void main(void) { 240 #ifdef WR_FEATURE_DEBUG_OVERDRAW 241 oFragColor = WR_DEBUG_OVERDRAW_COLOR; 242 #else 243 244 Fragment frag = brush_fs(); 245 246 #ifdef WR_FEATURE_ALPHA_PASS 247 // Apply the clip mask 248 float clip_alpha = do_clip(); 249 250 frag.color *= clip_alpha; 251 252 #ifdef WR_FEATURE_DUAL_SOURCE_BLENDING 253 oFragBlend = frag.blend * clip_alpha; 254 #endif 255 #endif 256 257 write_output(frag.color); 258 #endif 259 } 260 #endif