1use api::{precise_time_ns, ImageBufferKind, units::DeviceSize};
6use crate::batch::{BatchKey, BatchKind, BrushBatchKind, BatchFeatures};
7use crate::composite::{CompositeFeatures, CompositeSurfaceFormat};
8use crate::device::{Device, Program, ShaderError};
9use crate::pattern::PatternKind;
10use crate::telemetry::Telemetry;
11use euclid::default::Transform3D;
12use glyph_rasterizer::GlyphFormat;
13use crate::renderer::{
14 desc,
15 BlendMode, DebugFlags, RendererError, WebRenderOptions,
16 TextureSampler, VertexArrayKind, ShaderPrecacheFlags,
17};
18use crate::profiler::{self, TransactionProfile, ns_to_ms};
19
20use gleam::gl::GlType;
21
22use std::cell::RefCell;
23use std::collections::VecDeque;
24use std::rc::Rc;
25
26use webrender_build::shader::{ShaderFeatures, ShaderFeatureFlags, get_shader_features};
27
28#[derive(Clone, Copy, Debug, PartialEq)]
30enum TextureExternalVersion {
31 ESSL3,
34 ESSL1,
36}
37
38fn get_feature_string(kind: ImageBufferKind, texture_external_version: TextureExternalVersion) -> &'static str {
39 match (kind, texture_external_version) {
40 (ImageBufferKind::Texture2D, _) => "TEXTURE_2D",
41 (ImageBufferKind::TextureRect, _) => "TEXTURE_RECT",
42 (ImageBufferKind::TextureExternal, TextureExternalVersion::ESSL3) => "TEXTURE_EXTERNAL",
43 (ImageBufferKind::TextureExternal, TextureExternalVersion::ESSL1) => "TEXTURE_EXTERNAL_ESSL1",
44 (ImageBufferKind::TextureExternalBT709, _) => "TEXTURE_EXTERNAL_BT709",
45 }
46}
47
48fn has_platform_support(kind: ImageBufferKind, device: &Device) -> bool {
49 match (kind, device.gl().get_type()) {
50 (ImageBufferKind::Texture2D, _) => true,
51 (ImageBufferKind::TextureRect, GlType::Gles) => false,
52 (ImageBufferKind::TextureRect, GlType::Gl) => true,
53 (ImageBufferKind::TextureExternal, GlType::Gles) => true,
54 (ImageBufferKind::TextureExternal, GlType::Gl) => false,
55 (ImageBufferKind::TextureExternalBT709, GlType::Gles) => device.supports_extension("GL_EXT_YUV_target"),
56 (ImageBufferKind::TextureExternalBT709, GlType::Gl) => false,
57 }
58}
59
60pub const IMAGE_BUFFER_KINDS: [ImageBufferKind; 4] = [
61 ImageBufferKind::Texture2D,
62 ImageBufferKind::TextureRect,
63 ImageBufferKind::TextureExternal,
64 ImageBufferKind::TextureExternalBT709,
65];
66
67const ADVANCED_BLEND_FEATURE: &str = "ADVANCED_BLEND";
68const ALPHA_FEATURE: &str = "ALPHA_PASS";
69const DEBUG_OVERDRAW_FEATURE: &str = "DEBUG_OVERDRAW";
70const DITHERING_FEATURE: &str = "DITHERING";
71const DUAL_SOURCE_FEATURE: &str = "DUAL_SOURCE_BLENDING";
72const FAST_PATH_FEATURE: &str = "FAST_PATH";
73
74pub(crate) enum ShaderKind {
75 Primitive,
76 Cache(VertexArrayKind),
77 ClipCache(VertexArrayKind),
78 Brush,
79 Text,
80 #[allow(dead_code)]
81 VectorStencil,
82 #[allow(dead_code)]
83 VectorCover,
84 #[allow(dead_code)]
85 Resolve,
86 Composite,
87 Clear,
88 Copy,
89}
90
91pub struct LazilyCompiledShader {
92 program: Option<Program>,
93 name: &'static str,
94 kind: ShaderKind,
95 cached_projection: Transform3D<f32>,
96 features: Vec<&'static str>,
97}
98
99impl LazilyCompiledShader {
100 pub(crate) fn new(
101 kind: ShaderKind,
102 name: &'static str,
103 unsorted_features: &[&'static str],
104 shader_list: &ShaderFeatures,
105 ) -> Result<Self, ShaderError> {
106
107 let mut features = unsorted_features.to_vec();
108 features.sort();
109
110 let config = features.join(",");
113 assert!(
114 shader_list.get(name).map_or(false, |f| f.contains(&config)),
115 "shader \"{}\" with features \"{}\" not in available shader list",
116 name,
117 config,
118 );
119
120 let shader = LazilyCompiledShader {
121 program: None,
122 name,
123 kind,
124 cached_projection: Transform3D::identity(),
127 features,
128 };
129
130 Ok(shader)
131 }
132
133 pub fn precache(
134 &mut self,
135 device: &mut Device,
136 flags: ShaderPrecacheFlags,
137 ) -> Result<(), ShaderError> {
138 let t0 = precise_time_ns();
139 let timer_id = Telemetry::start_shaderload_time();
140 self.get_internal(device, flags, None)?;
141 Telemetry::stop_and_accumulate_shaderload_time(timer_id);
142 let t1 = precise_time_ns();
143 debug!("[C: {:.1} ms ] Precache {} {:?}",
144 (t1 - t0) as f64 / 1000000.0,
145 self.name,
146 self.features
147 );
148 Ok(())
149 }
150
151 pub fn bind(
152 &mut self,
153 device: &mut Device,
154 projection: &Transform3D<f32>,
155 texture_size: Option<DeviceSize>,
156 renderer_errors: &mut Vec<RendererError>,
157 profile: &mut TransactionProfile,
158 ) {
159 let update_projection = self.cached_projection != *projection;
160 let program = match self.get_internal(device, ShaderPrecacheFlags::FULL_COMPILE, Some(profile)) {
161 Ok(program) => program,
162 Err(e) => {
163 renderer_errors.push(RendererError::from(e));
164 return;
165 }
166 };
167 device.bind_program(program);
168 if let Some(texture_size) = texture_size {
169 device.set_shader_texture_size(program, texture_size);
170 }
171 if update_projection {
172 device.set_uniforms(program, projection);
173 self.cached_projection = *projection;
175 }
176 }
177
178 fn get_internal(
179 &mut self,
180 device: &mut Device,
181 precache_flags: ShaderPrecacheFlags,
182 mut profile: Option<&mut TransactionProfile>,
183 ) -> Result<&mut Program, ShaderError> {
184 if self.program.is_none() {
185 let start_time = precise_time_ns();
186 let program = match self.kind {
187 ShaderKind::Primitive | ShaderKind::Brush | ShaderKind::Text | ShaderKind::Resolve | ShaderKind::Clear | ShaderKind::Copy => {
188 create_prim_shader(
189 self.name,
190 device,
191 &self.features,
192 )
193 }
194 ShaderKind::Cache(..) => {
195 create_prim_shader(
196 self.name,
197 device,
198 &self.features,
199 )
200 }
201 ShaderKind::VectorStencil => {
202 create_prim_shader(
203 self.name,
204 device,
205 &self.features,
206 )
207 }
208 ShaderKind::VectorCover => {
209 create_prim_shader(
210 self.name,
211 device,
212 &self.features,
213 )
214 }
215 ShaderKind::Composite => {
216 create_prim_shader(
217 self.name,
218 device,
219 &self.features,
220 )
221 }
222 ShaderKind::ClipCache(..) => {
223 create_clip_shader(
224 self.name,
225 device,
226 &self.features,
227 )
228 }
229 };
230 self.program = Some(program?);
231
232 if let Some(profile) = &mut profile {
233 let end_time = precise_time_ns();
234 profile.add(profiler::SHADER_BUILD_TIME, ns_to_ms(end_time - start_time));
235 }
236 }
237
238 let program = self.program.as_mut().unwrap();
239
240 if precache_flags.contains(ShaderPrecacheFlags::FULL_COMPILE) && !program.is_initialized() {
241 let start_time = precise_time_ns();
242
243 let vertex_format = match self.kind {
244 ShaderKind::Primitive |
245 ShaderKind::Brush |
246 ShaderKind::Text => VertexArrayKind::Primitive,
247 ShaderKind::Cache(format) => format,
248 ShaderKind::VectorStencil => VertexArrayKind::VectorStencil,
249 ShaderKind::VectorCover => VertexArrayKind::VectorCover,
250 ShaderKind::ClipCache(format) => format,
251 ShaderKind::Resolve => VertexArrayKind::Resolve,
252 ShaderKind::Composite => VertexArrayKind::Composite,
253 ShaderKind::Clear => VertexArrayKind::Clear,
254 ShaderKind::Copy => VertexArrayKind::Copy,
255 };
256
257 let vertex_descriptor = match vertex_format {
258 VertexArrayKind::Primitive => &desc::PRIM_INSTANCES,
259 VertexArrayKind::LineDecoration => &desc::LINE,
260 VertexArrayKind::FastLinearGradient => &desc::FAST_LINEAR_GRADIENT,
261 VertexArrayKind::LinearGradient => &desc::LINEAR_GRADIENT,
262 VertexArrayKind::RadialGradient => &desc::RADIAL_GRADIENT,
263 VertexArrayKind::ConicGradient => &desc::CONIC_GRADIENT,
264 VertexArrayKind::Blur => &desc::BLUR,
265 VertexArrayKind::ClipRect => &desc::CLIP_RECT,
266 VertexArrayKind::ClipBoxShadow => &desc::CLIP_BOX_SHADOW,
267 VertexArrayKind::VectorStencil => &desc::VECTOR_STENCIL,
268 VertexArrayKind::VectorCover => &desc::VECTOR_COVER,
269 VertexArrayKind::Border => &desc::BORDER,
270 VertexArrayKind::Scale => &desc::SCALE,
271 VertexArrayKind::Resolve => &desc::RESOLVE,
272 VertexArrayKind::SvgFilter => &desc::SVG_FILTER,
273 VertexArrayKind::SvgFilterNode => &desc::SVG_FILTER_NODE,
274 VertexArrayKind::Composite => &desc::COMPOSITE,
275 VertexArrayKind::Clear => &desc::CLEAR,
276 VertexArrayKind::Copy => &desc::COPY,
277 VertexArrayKind::Mask => &desc::MASK,
278 };
279
280 device.link_program(program, vertex_descriptor)?;
281 device.bind_program(program);
282 match self.kind {
283 ShaderKind::ClipCache(..) => {
284 device.bind_shader_samplers(
285 &program,
286 &[
287 ("sColor0", TextureSampler::Color0),
288 ("sTransformPalette", TextureSampler::TransformPalette),
289 ("sRenderTasks", TextureSampler::RenderTasks),
290 ("sGpuCache", TextureSampler::GpuCache),
291 ("sPrimitiveHeadersF", TextureSampler::PrimitiveHeadersF),
292 ("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI),
293 ("sGpuBufferF", TextureSampler::GpuBufferF),
294 ("sGpuBufferI", TextureSampler::GpuBufferI),
295 ],
296 );
297 }
298 _ => {
299 device.bind_shader_samplers(
300 &program,
301 &[
302 ("sColor0", TextureSampler::Color0),
303 ("sColor1", TextureSampler::Color1),
304 ("sColor2", TextureSampler::Color2),
305 ("sDither", TextureSampler::Dither),
306 ("sTransformPalette", TextureSampler::TransformPalette),
307 ("sRenderTasks", TextureSampler::RenderTasks),
308 ("sGpuCache", TextureSampler::GpuCache),
309 ("sPrimitiveHeadersF", TextureSampler::PrimitiveHeadersF),
310 ("sPrimitiveHeadersI", TextureSampler::PrimitiveHeadersI),
311 ("sClipMask", TextureSampler::ClipMask),
312 ("sGpuBufferF", TextureSampler::GpuBufferF),
313 ("sGpuBufferI", TextureSampler::GpuBufferI),
314 ],
315 );
316 }
317 }
318
319 if let Some(profile) = &mut profile {
320 let end_time = precise_time_ns();
321 profile.add(profiler::SHADER_BUILD_TIME, ns_to_ms(end_time - start_time));
322 }
323 }
324
325 Ok(program)
326 }
327
328 fn deinit(self, device: &mut Device) {
329 if let Some(program) = self.program {
330 device.delete_program(program);
331 }
332 }
333}
334
335struct BrushShader {
347 opaque: ShaderHandle,
348 alpha: ShaderHandle,
349 advanced_blend: Option<ShaderHandle>,
350 dual_source: Option<ShaderHandle>,
351 debug_overdraw: ShaderHandle,
352}
353
354impl BrushShader {
355 fn new(
356 name: &'static str,
357 features: &[&'static str],
358 shader_list: &ShaderFeatures,
359 use_advanced_blend: bool,
360 use_dual_source: bool,
361 loader: &mut ShaderLoader,
362 ) -> Result<Self, ShaderError> {
363 let opaque_features = features.to_vec();
364 let opaque = loader.create_shader(
365 ShaderKind::Brush,
366 name,
367 &opaque_features,
368 &shader_list,
369 )?;
370
371 let mut alpha_features = opaque_features.to_vec();
372 alpha_features.push(ALPHA_FEATURE);
373
374 let alpha = loader.create_shader(
375 ShaderKind::Brush,
376 name,
377 &alpha_features,
378 &shader_list,
379 )?;
380
381 let advanced_blend = if use_advanced_blend {
382 let mut advanced_blend_features = alpha_features.to_vec();
383 advanced_blend_features.push(ADVANCED_BLEND_FEATURE);
384
385 let shader = loader.create_shader(
386 ShaderKind::Brush,
387 name,
388 &advanced_blend_features,
389 &shader_list,
390 )?;
391
392 Some(shader)
393 } else {
394 None
395 };
396
397 let dual_source = if use_dual_source {
398 let mut dual_source_features = alpha_features.to_vec();
399 dual_source_features.push(DUAL_SOURCE_FEATURE);
400
401 let shader = loader.create_shader(
402 ShaderKind::Brush,
403 name,
404 &dual_source_features,
405 &shader_list,
406 )?;
407
408 Some(shader)
409 } else {
410 None
411 };
412
413 let mut debug_overdraw_features = features.to_vec();
414 debug_overdraw_features.push(DEBUG_OVERDRAW_FEATURE);
415
416 let debug_overdraw = loader.create_shader(
417 ShaderKind::Brush,
418 name,
419 &debug_overdraw_features,
420 &shader_list,
421 )?;
422
423 Ok(BrushShader {
424 opaque,
425 alpha,
426 advanced_blend,
427 dual_source,
428 debug_overdraw,
429 })
430 }
431
432 fn get_handle(
433 &mut self,
434 blend_mode: BlendMode,
435 features: BatchFeatures,
436 debug_flags: DebugFlags,
437 ) -> ShaderHandle {
438 match blend_mode {
439 _ if debug_flags.contains(DebugFlags::SHOW_OVERDRAW) => self.debug_overdraw,
440 BlendMode::None => self.opaque,
441 BlendMode::Alpha |
442 BlendMode::PremultipliedAlpha |
443 BlendMode::PremultipliedDestOut |
444 BlendMode::Screen |
445 BlendMode::PlusLighter |
446 BlendMode::Exclusion => {
447 if features.contains(BatchFeatures::ALPHA_PASS) {
448 self.alpha
449 } else {
450 self.opaque
451 }
452 }
453 BlendMode::Advanced(_) => {
454 self.advanced_blend.expect("bug: no advanced blend shader loaded")
455 }
456 BlendMode::SubpixelDualSource |
457 BlendMode::MultiplyDualSource => {
458 self.dual_source.expect("bug: no dual source shader loaded")
459 }
460 }
461 }
462}
463
464pub struct TextShader {
465 simple: ShaderHandle,
466 glyph_transform: ShaderHandle,
467 debug_overdraw: ShaderHandle,
468}
469
470impl TextShader {
471 fn new(
472 name: &'static str,
473 features: &[&'static str],
474 shader_list: &ShaderFeatures,
475 loader: &mut ShaderLoader,
476 ) -> Result<Self, ShaderError> {
477 let mut simple_features = features.to_vec();
478 simple_features.push("ALPHA_PASS");
479 simple_features.push("TEXTURE_2D");
480
481 let simple = loader.create_shader(
482 ShaderKind::Text,
483 name,
484 &simple_features,
485 &shader_list,
486 )?;
487
488 let mut glyph_transform_features = features.to_vec();
489 glyph_transform_features.push("GLYPH_TRANSFORM");
490 glyph_transform_features.push("ALPHA_PASS");
491 glyph_transform_features.push("TEXTURE_2D");
492
493 let glyph_transform = loader.create_shader(
494 ShaderKind::Text,
495 name,
496 &glyph_transform_features,
497 &shader_list,
498 )?;
499
500 let mut debug_overdraw_features = features.to_vec();
501 debug_overdraw_features.push("DEBUG_OVERDRAW");
502 debug_overdraw_features.push("TEXTURE_2D");
503
504 let debug_overdraw = loader.create_shader(
505 ShaderKind::Text,
506 name,
507 &debug_overdraw_features,
508 &shader_list,
509 )?;
510
511 Ok(TextShader { simple, glyph_transform, debug_overdraw })
512 }
513
514 pub fn get_handle(
515 &mut self,
516 glyph_format: GlyphFormat,
517 debug_flags: DebugFlags,
518 ) -> ShaderHandle {
519 match glyph_format {
520 _ if debug_flags.contains(DebugFlags::SHOW_OVERDRAW) => self.debug_overdraw,
521 GlyphFormat::Alpha |
522 GlyphFormat::Subpixel |
523 GlyphFormat::Bitmap |
524 GlyphFormat::ColorBitmap => self.simple,
525 GlyphFormat::TransformedAlpha |
526 GlyphFormat::TransformedSubpixel => self.glyph_transform,
527 }
528 }
529}
530
531fn create_prim_shader(
532 name: &'static str,
533 device: &mut Device,
534 features: &[&'static str],
535) -> Result<Program, ShaderError> {
536 debug!("PrimShader {}", name);
537
538 device.create_program(name, features)
539}
540
541fn create_clip_shader(
542 name: &'static str,
543 device: &mut Device,
544 features: &[&'static str],
545) -> Result<Program, ShaderError> {
546 debug!("ClipShader {}", name);
547
548 device.create_program(name, features)
549}
550
551#[derive(Debug, Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash)]
552pub struct ShaderHandle(usize);
553
554#[derive(Default)]
555pub struct ShaderLoader {
556 shaders: Vec<LazilyCompiledShader>,
557}
558
559impl ShaderLoader {
560 pub fn new() -> Self {
561 Default::default()
562 }
563
564 pub fn create_shader(
565 &mut self,
566 kind: ShaderKind,
567 name: &'static str,
568 unsorted_features: &[&'static str],
569 shader_list: &ShaderFeatures,
570 ) -> Result<ShaderHandle, ShaderError> {
571 let index = self.shaders.len();
572 let shader = LazilyCompiledShader::new(
573 kind,
574 name,
575 unsorted_features,
576 shader_list,
577 )?;
578 self.shaders.push(shader);
579 Ok(ShaderHandle(index))
580 }
581
582 pub fn precache(
583 &mut self,
584 shader: ShaderHandle,
585 device: &mut Device,
586 flags: ShaderPrecacheFlags,
587 ) -> Result<(), ShaderError> {
588 if !flags.intersects(ShaderPrecacheFlags::ASYNC_COMPILE | ShaderPrecacheFlags::FULL_COMPILE) {
589 return Ok(());
590 }
591
592 self.shaders[shader.0].precache(device, flags)
593 }
594
595 pub fn all_handles(&self) -> Vec<ShaderHandle> {
596 self.shaders.iter().enumerate().map(|(index, _)| ShaderHandle(index)).collect()
597 }
598
599 pub fn get(&mut self, handle: ShaderHandle) -> &mut LazilyCompiledShader {
600 &mut self.shaders[handle.0]
601 }
602
603 pub fn deinit(self, device: &mut Device) {
604 for shader in self.shaders {
605 shader.deinit(device);
606 }
607 }
608}
609
610pub struct Shaders {
611 loader: ShaderLoader,
612
613 cs_blur_rgba8: ShaderHandle,
617 cs_border_segment: ShaderHandle,
618 cs_border_solid: ShaderHandle,
619 cs_scale: Vec<Option<ShaderHandle>>,
620 cs_line_decoration: ShaderHandle,
621 cs_fast_linear_gradient: ShaderHandle,
622 cs_linear_gradient: ShaderHandle,
623 cs_radial_gradient: ShaderHandle,
624 cs_conic_gradient: ShaderHandle,
625 cs_svg_filter: ShaderHandle,
626 cs_svg_filter_node: ShaderHandle,
627
628 brush_solid: BrushShader,
630 brush_image: Vec<Option<BrushShader>>,
631 brush_fast_image: Vec<Option<BrushShader>>,
632 brush_blend: BrushShader,
633 brush_mix_blend: BrushShader,
634 brush_yuv_image: Vec<Option<BrushShader>>,
635 brush_linear_gradient: BrushShader,
636 brush_opacity: BrushShader,
637 brush_opacity_aa: BrushShader,
638
639 cs_clip_rectangle_slow: ShaderHandle,
643 cs_clip_rectangle_fast: ShaderHandle,
644 cs_clip_box_shadow: ShaderHandle,
645
646 ps_text_run: TextShader,
654 ps_text_run_dual_source: Option<TextShader>,
655
656 ps_split_composite: ShaderHandle,
657 ps_quad_textured: ShaderHandle,
658 ps_quad_radial_gradient: ShaderHandle,
659 ps_quad_conic_gradient: ShaderHandle,
660 ps_mask: ShaderHandle,
661 ps_mask_fast: ShaderHandle,
662 ps_clear: ShaderHandle,
663 ps_copy: ShaderHandle,
664
665 composite: CompositorShaders,
666}
667
668pub struct PendingShadersToPrecache {
669 precache_flags: ShaderPrecacheFlags,
670 remaining_shaders: VecDeque<ShaderHandle>,
671}
672
673impl Shaders {
674 pub fn new(
675 device: &mut Device,
676 gl_type: GlType,
677 options: &WebRenderOptions,
678 ) -> Result<Self, ShaderError> {
679 let use_dual_source_blending =
680 device.get_capabilities().supports_dual_source_blending &&
681 options.allow_dual_source_blending;
682 let use_advanced_blend_equation =
683 device.get_capabilities().supports_advanced_blend_equation &&
684 options.allow_advanced_blend_equation;
685
686 let texture_external_version = if device.get_capabilities().supports_image_external_essl3 {
687 TextureExternalVersion::ESSL3
688 } else {
689 TextureExternalVersion::ESSL1
690 };
691 let mut shader_flags = get_shader_feature_flags(gl_type, texture_external_version, device);
692 shader_flags.set(ShaderFeatureFlags::ADVANCED_BLEND_EQUATION, use_advanced_blend_equation);
693 shader_flags.set(ShaderFeatureFlags::DUAL_SOURCE_BLENDING, use_dual_source_blending);
694 shader_flags.set(ShaderFeatureFlags::DITHERING, options.enable_dithering);
695 let shader_list = get_shader_features(shader_flags);
696
697 let mut loader = ShaderLoader::new();
698
699 let brush_solid = BrushShader::new(
700 "brush_solid",
701 &[],
702 &shader_list,
703 false ,
704 false ,
705 &mut loader,
706 )?;
707
708 let brush_blend = BrushShader::new(
709 "brush_blend",
710 &[],
711 &shader_list,
712 false ,
713 false ,
714 &mut loader,
715 )?;
716
717 let brush_mix_blend = BrushShader::new(
718 "brush_mix_blend",
719 &[],
720 &shader_list,
721 false ,
722 false ,
723 &mut loader,
724 )?;
725
726 let brush_linear_gradient = BrushShader::new(
727 "brush_linear_gradient",
728 if options.enable_dithering {
729 &[DITHERING_FEATURE]
730 } else {
731 &[]
732 },
733 &shader_list,
734 false ,
735 false ,
736 &mut loader,
737 )?;
738
739 let brush_opacity_aa = BrushShader::new(
740 "brush_opacity",
741 &["ANTIALIASING"],
742 &shader_list,
743 false ,
744 false ,
745 &mut loader,
746 )?;
747
748 let brush_opacity = BrushShader::new(
749 "brush_opacity",
750 &[],
751 &shader_list,
752 false ,
753 false ,
754 &mut loader,
755 )?;
756
757 let cs_blur_rgba8 = loader.create_shader(
758 ShaderKind::Cache(VertexArrayKind::Blur),
759 "cs_blur",
760 &["COLOR_TARGET"],
761 &shader_list,
762 )?;
763
764 let cs_svg_filter = loader.create_shader(
765 ShaderKind::Cache(VertexArrayKind::SvgFilter),
766 "cs_svg_filter",
767 &[],
768 &shader_list,
769 )?;
770
771 let cs_svg_filter_node = loader.create_shader(
772 ShaderKind::Cache(VertexArrayKind::SvgFilterNode),
773 "cs_svg_filter_node",
774 &[],
775 &shader_list,
776 )?;
777
778 let ps_mask = loader.create_shader(
779 ShaderKind::Cache(VertexArrayKind::Mask),
780 "ps_quad_mask",
781 &[],
782 &shader_list,
783 )?;
784
785 let ps_mask_fast = loader.create_shader(
786 ShaderKind::Cache(VertexArrayKind::Mask),
787 "ps_quad_mask",
788 &[FAST_PATH_FEATURE],
789 &shader_list,
790 )?;
791
792 let cs_clip_rectangle_slow = loader.create_shader(
793 ShaderKind::ClipCache(VertexArrayKind::ClipRect),
794 "cs_clip_rectangle",
795 &[],
796 &shader_list,
797 )?;
798
799 let cs_clip_rectangle_fast = loader.create_shader(
800 ShaderKind::ClipCache(VertexArrayKind::ClipRect),
801 "cs_clip_rectangle",
802 &[FAST_PATH_FEATURE],
803 &shader_list,
804 )?;
805
806 let cs_clip_box_shadow = loader.create_shader(
807 ShaderKind::ClipCache(VertexArrayKind::ClipBoxShadow),
808 "cs_clip_box_shadow",
809 &["TEXTURE_2D"],
810 &shader_list,
811 )?;
812
813 let mut cs_scale = Vec::new();
814 let scale_shader_num = IMAGE_BUFFER_KINDS.len();
815 for _ in 0 .. scale_shader_num {
817 cs_scale.push(None);
818 }
819 for image_buffer_kind in &IMAGE_BUFFER_KINDS {
820 if has_platform_support(*image_buffer_kind, device) {
821 let feature_string = get_feature_string(
822 *image_buffer_kind,
823 texture_external_version,
824 );
825
826 let mut features = Vec::new();
827 if feature_string != "" {
828 features.push(feature_string);
829 }
830
831 let shader = loader.create_shader(
832 ShaderKind::Cache(VertexArrayKind::Scale),
833 "cs_scale",
834 &features,
835 &shader_list,
836 )?;
837
838 let index = Self::get_compositing_shader_index(
839 *image_buffer_kind,
840 );
841 cs_scale[index] = Some(shader);
842 }
843 }
844
845 let ps_text_run = TextShader::new("ps_text_run",
850 &[],
851 &shader_list,
852 &mut loader,
853 )?;
854
855 let ps_text_run_dual_source = if use_dual_source_blending {
856 let dual_source_features = vec![DUAL_SOURCE_FEATURE];
857 Some(TextShader::new("ps_text_run",
858 &dual_source_features,
859 &shader_list,
860 &mut loader,
861 )?)
862 } else {
863 None
864 };
865
866 let ps_quad_textured = loader.create_shader(
867 ShaderKind::Primitive,
868 "ps_quad_textured",
869 &[],
870 &shader_list,
871 )?;
872
873 let ps_quad_radial_gradient = loader.create_shader(
874 ShaderKind::Primitive,
875 "ps_quad_radial_gradient",
876 &[],
877 &shader_list,
878 )?;
879
880 let ps_quad_conic_gradient = loader.create_shader(
881 ShaderKind::Primitive,
882 "ps_quad_conic_gradient",
883 &[],
884 &shader_list,
885 )?;
886
887 let ps_split_composite = loader.create_shader(
888 ShaderKind::Primitive,
889 "ps_split_composite",
890 &[],
891 &shader_list,
892 )?;
893
894 let ps_clear = loader.create_shader(
895 ShaderKind::Clear,
896 "ps_clear",
897 &[],
898 &shader_list,
899 )?;
900
901 let ps_copy = loader.create_shader(
902 ShaderKind::Copy,
903 "ps_copy",
904 &[],
905 &shader_list,
906 )?;
907
908 let mut image_features = Vec::new();
910 let mut brush_image = Vec::new();
911 let mut brush_fast_image = Vec::new();
912 for _ in 0 .. IMAGE_BUFFER_KINDS.len() {
914 brush_image.push(None);
915 brush_fast_image.push(None);
916 }
917 for buffer_kind in 0 .. IMAGE_BUFFER_KINDS.len() {
918 if !has_platform_support(IMAGE_BUFFER_KINDS[buffer_kind], device)
919 || (IMAGE_BUFFER_KINDS[buffer_kind] == ImageBufferKind::TextureExternal
921 && texture_external_version == TextureExternalVersion::ESSL1)
922 {
923 continue;
924 }
925
926 let feature_string = get_feature_string(
927 IMAGE_BUFFER_KINDS[buffer_kind],
928 texture_external_version,
929 );
930 if feature_string != "" {
931 image_features.push(feature_string);
932 }
933
934 brush_fast_image[buffer_kind] = Some(BrushShader::new(
935 "brush_image",
936 &image_features,
937 &shader_list,
938 use_advanced_blend_equation,
939 use_dual_source_blending,
940 &mut loader,
941 )?);
942
943 image_features.push("REPETITION");
944 image_features.push("ANTIALIASING");
945
946 brush_image[buffer_kind] = Some(BrushShader::new(
947 "brush_image",
948 &image_features,
949 &shader_list,
950 use_advanced_blend_equation,
951 use_dual_source_blending,
952 &mut loader,
953 )?);
954
955 image_features.clear();
956 }
957
958 let mut yuv_features = Vec::new();
960 let mut rgba_features = Vec::new();
961 let mut fast_path_features = Vec::new();
962 let yuv_shader_num = IMAGE_BUFFER_KINDS.len();
963 let mut brush_yuv_image = Vec::new();
964 for _ in 0 .. yuv_shader_num {
966 brush_yuv_image.push(None);
967 }
968 for image_buffer_kind in &IMAGE_BUFFER_KINDS {
969 if has_platform_support(*image_buffer_kind, device) {
970 yuv_features.push("YUV");
971 fast_path_features.push("FAST_PATH");
972
973 let index = Self::get_compositing_shader_index(
974 *image_buffer_kind,
975 );
976
977 let feature_string = get_feature_string(
978 *image_buffer_kind,
979 texture_external_version,
980 );
981 if feature_string != "" {
982 yuv_features.push(feature_string);
983 rgba_features.push(feature_string);
984 fast_path_features.push(feature_string);
985 }
986
987 if *image_buffer_kind != ImageBufferKind::TextureExternal ||
989 texture_external_version == TextureExternalVersion::ESSL3 {
990 let brush_shader = BrushShader::new(
991 "brush_yuv_image",
992 &yuv_features,
993 &shader_list,
994 false ,
995 false ,
996 &mut loader,
997 )?;
998 brush_yuv_image[index] = Some(brush_shader);
999 }
1000
1001 yuv_features.clear();
1002 rgba_features.clear();
1003 fast_path_features.clear();
1004 }
1005 }
1006
1007 let cs_line_decoration = loader.create_shader(
1008 ShaderKind::Cache(VertexArrayKind::LineDecoration),
1009 "cs_line_decoration",
1010 &[],
1011 &shader_list,
1012 )?;
1013
1014 let cs_fast_linear_gradient = loader.create_shader(
1015 ShaderKind::Cache(VertexArrayKind::FastLinearGradient),
1016 "cs_fast_linear_gradient",
1017 &[],
1018 &shader_list,
1019 )?;
1020
1021 let cs_linear_gradient = loader.create_shader(
1022 ShaderKind::Cache(VertexArrayKind::LinearGradient),
1023 "cs_linear_gradient",
1024 &[],
1025 &shader_list,
1026 )?;
1027
1028 let cs_radial_gradient = loader.create_shader(
1029 ShaderKind::Cache(VertexArrayKind::RadialGradient),
1030 "cs_radial_gradient",
1031 &[],
1032 &shader_list,
1033 )?;
1034
1035 let cs_conic_gradient = loader.create_shader(
1036 ShaderKind::Cache(VertexArrayKind::ConicGradient),
1037 "cs_conic_gradient",
1038 &[],
1039 &shader_list,
1040 )?;
1041
1042 let cs_border_segment = loader.create_shader(
1043 ShaderKind::Cache(VertexArrayKind::Border),
1044 "cs_border_segment",
1045 &[],
1046 &shader_list,
1047 )?;
1048
1049 let cs_border_solid = loader.create_shader(
1050 ShaderKind::Cache(VertexArrayKind::Border),
1051 "cs_border_solid",
1052 &[],
1053 &shader_list,
1054 )?;
1055
1056 let composite = CompositorShaders::new(device, gl_type, &mut loader)?;
1057
1058 Ok(Shaders {
1059 loader,
1060
1061 cs_blur_rgba8,
1062 cs_border_segment,
1063 cs_line_decoration,
1064 cs_fast_linear_gradient,
1065 cs_linear_gradient,
1066 cs_radial_gradient,
1067 cs_conic_gradient,
1068 cs_border_solid,
1069 cs_scale,
1070 cs_svg_filter,
1071 cs_svg_filter_node,
1072 brush_solid,
1073 brush_image,
1074 brush_fast_image,
1075 brush_blend,
1076 brush_mix_blend,
1077 brush_yuv_image,
1078 brush_linear_gradient,
1079 brush_opacity,
1080 brush_opacity_aa,
1081 cs_clip_rectangle_slow,
1082 cs_clip_rectangle_fast,
1083 cs_clip_box_shadow,
1084 ps_text_run,
1085 ps_text_run_dual_source,
1086 ps_quad_textured,
1087 ps_quad_radial_gradient,
1088 ps_quad_conic_gradient,
1089 ps_mask,
1090 ps_mask_fast,
1091 ps_split_composite,
1092 ps_clear,
1093 ps_copy,
1094 composite,
1095 })
1096 }
1097
1098 #[must_use]
1099 pub fn precache_all(
1100 &mut self,
1101 precache_flags: ShaderPrecacheFlags,
1102 ) -> PendingShadersToPrecache {
1103 PendingShadersToPrecache {
1104 precache_flags,
1105 remaining_shaders: self.loader.all_handles().into(),
1106 }
1107 }
1108
1109 pub fn resume_precache(
1111 &mut self,
1112 device: &mut Device,
1113 pending_shaders: &mut PendingShadersToPrecache,
1114 ) -> Result<bool, ShaderError> {
1115 let Some(next_shader) = pending_shaders.remaining_shaders.pop_front() else {
1116 return Ok(false)
1117 };
1118
1119 self.loader.precache(next_shader, device, pending_shaders.precache_flags)?;
1120 Ok(true)
1121 }
1122
1123 fn get_compositing_shader_index(buffer_kind: ImageBufferKind) -> usize {
1124 buffer_kind as usize
1125 }
1126
1127 pub fn get_composite_shader(
1128 &mut self,
1129 format: CompositeSurfaceFormat,
1130 buffer_kind: ImageBufferKind,
1131 features: CompositeFeatures,
1132 ) -> &mut LazilyCompiledShader {
1133 let shader_handle = self.composite.get_handle(format, buffer_kind, features);
1134 self.loader.get(shader_handle)
1135 }
1136
1137 pub fn get_scale_shader(
1138 &mut self,
1139 buffer_kind: ImageBufferKind,
1140 ) -> &mut LazilyCompiledShader {
1141 let shader_index = Self::get_compositing_shader_index(buffer_kind);
1142 let shader_handle = self.cs_scale[shader_index]
1143 .expect("bug: unsupported scale shader requested");
1144 self.loader.get(shader_handle)
1145 }
1146
1147 pub fn get_quad_shader(
1148 &mut self,
1149 pattern: PatternKind
1150 ) -> &mut LazilyCompiledShader {
1151 let shader_handle = match pattern {
1152 PatternKind::ColorOrTexture => self.ps_quad_textured,
1153 PatternKind::RadialGradient => self.ps_quad_radial_gradient,
1154 PatternKind::ConicGradient => self.ps_quad_conic_gradient,
1155 PatternKind::Mask => unreachable!(),
1156 };
1157 self.loader.get(shader_handle)
1158 }
1159
1160 pub fn get(
1161 &mut self,
1162 key: &BatchKey,
1163 features: BatchFeatures,
1164 debug_flags: DebugFlags,
1165 device: &Device,
1166 ) -> &mut LazilyCompiledShader {
1167 let shader_handle = self.get_handle(key, features, debug_flags, device);
1168 self.loader.get(shader_handle)
1169 }
1170
1171 pub fn get_handle(
1172 &mut self,
1173 key: &BatchKey,
1174 mut features: BatchFeatures,
1175 debug_flags: DebugFlags,
1176 device: &Device,
1177 ) -> ShaderHandle {
1178 match key.kind {
1179 BatchKind::Quad(PatternKind::ColorOrTexture) => {
1180 self.ps_quad_textured
1181 }
1182 BatchKind::Quad(PatternKind::RadialGradient) => {
1183 self.ps_quad_radial_gradient
1184 }
1185 BatchKind::Quad(PatternKind::ConicGradient) => {
1186 self.ps_quad_conic_gradient
1187 }
1188 BatchKind::Quad(PatternKind::Mask) => {
1189 unreachable!();
1190 }
1191 BatchKind::SplitComposite => {
1192 self.ps_split_composite
1193 }
1194 BatchKind::Brush(brush_kind) => {
1195 if device.get_capabilities().uses_native_antialiasing {
1199 features.remove(BatchFeatures::ANTIALIASING);
1200 }
1201 let brush_shader = match brush_kind {
1202 BrushBatchKind::Solid => {
1203 &mut self.brush_solid
1204 }
1205 BrushBatchKind::Image(image_buffer_kind) => {
1206 if features.contains(BatchFeatures::ANTIALIASING) ||
1207 features.contains(BatchFeatures::REPETITION) {
1208
1209 self.brush_image[image_buffer_kind as usize]
1210 .as_mut()
1211 .expect("Unsupported image shader kind")
1212 } else {
1213 self.brush_fast_image[image_buffer_kind as usize]
1214 .as_mut()
1215 .expect("Unsupported image shader kind")
1216 }
1217 }
1218 BrushBatchKind::Blend => {
1219 &mut self.brush_blend
1220 }
1221 BrushBatchKind::MixBlend { .. } => {
1222 &mut self.brush_mix_blend
1223 }
1224 BrushBatchKind::LinearGradient => {
1225 if device.get_capabilities().uses_native_clip_mask {
1229 features.remove(BatchFeatures::CLIP_MASK);
1230 }
1231 if !features.intersects(
1234 BatchFeatures::ANTIALIASING
1235 | BatchFeatures::REPETITION
1236 | BatchFeatures::CLIP_MASK,
1237 ) {
1238 features.remove(BatchFeatures::ALPHA_PASS);
1239 }
1240 match brush_kind {
1241 BrushBatchKind::LinearGradient => &mut self.brush_linear_gradient,
1242 _ => panic!(),
1243 }
1244 }
1245 BrushBatchKind::YuvImage(image_buffer_kind, ..) => {
1246 let shader_index =
1247 Self::get_compositing_shader_index(image_buffer_kind);
1248 self.brush_yuv_image[shader_index]
1249 .as_mut()
1250 .expect("Unsupported YUV shader kind")
1251 }
1252 BrushBatchKind::Opacity => {
1253 if features.contains(BatchFeatures::ANTIALIASING) {
1254 &mut self.brush_opacity_aa
1255 } else {
1256 &mut self.brush_opacity
1257 }
1258 }
1259 };
1260 brush_shader.get_handle(key.blend_mode, features, debug_flags)
1261 }
1262 BatchKind::TextRun(glyph_format) => {
1263 let text_shader = match key.blend_mode {
1264 BlendMode::SubpixelDualSource => self.ps_text_run_dual_source.as_mut().unwrap(),
1265 _ => &mut self.ps_text_run,
1266 };
1267 text_shader.get_handle(glyph_format, debug_flags)
1268 }
1269 }
1270 }
1271
1272 pub fn cs_blur_rgba8(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_blur_rgba8) }
1273 pub fn cs_border_segment(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_border_segment) }
1274 pub fn cs_border_solid(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_border_solid) }
1275 pub fn cs_line_decoration(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_line_decoration) }
1276 pub fn cs_fast_linear_gradient(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_fast_linear_gradient) }
1277 pub fn cs_linear_gradient(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_linear_gradient) }
1278 pub fn cs_radial_gradient(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_radial_gradient) }
1279 pub fn cs_conic_gradient(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_conic_gradient) }
1280 pub fn cs_svg_filter(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_svg_filter) }
1281 pub fn cs_svg_filter_node(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_svg_filter_node) }
1282 pub fn cs_clip_rectangle_slow(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_clip_rectangle_slow) }
1283 pub fn cs_clip_rectangle_fast(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_clip_rectangle_fast) }
1284 pub fn cs_clip_box_shadow(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.cs_clip_box_shadow) }
1285 pub fn ps_quad_textured(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.ps_quad_textured) }
1286 pub fn ps_mask(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.ps_mask) }
1287 pub fn ps_mask_fast(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.ps_mask_fast) }
1288 pub fn ps_clear(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.ps_clear) }
1289 pub fn ps_copy(&mut self) -> &mut LazilyCompiledShader { self.loader.get(self.ps_copy) }
1290
1291 pub fn deinit(self, device: &mut Device) {
1292 self.loader.deinit(device);
1293 }
1294}
1295
1296pub type SharedShaders = Rc<RefCell<Shaders>>;
1297
1298pub struct CompositorShaders {
1299 rgba: Vec<Option<ShaderHandle>>,
1310 rgba_fast_path: Vec<Option<ShaderHandle>>,
1313 yuv_clip: Vec<Option<ShaderHandle>>,
1315 yuv_fast: Vec<Option<ShaderHandle>>,
1316}
1317
1318impl CompositorShaders {
1319 pub fn new(
1320 device: &mut Device,
1321 gl_type: GlType,
1322 loader: &mut ShaderLoader,
1323 ) -> Result<Self, ShaderError> {
1324 let mut yuv_clip_features = Vec::new();
1325 let mut yuv_fast_features = Vec::new();
1326 let mut rgba_features = Vec::new();
1327 let mut fast_path_features = Vec::new();
1328 let mut rgba = Vec::new();
1329 let mut rgba_fast_path = Vec::new();
1330 let mut yuv_clip = Vec::new();
1331 let mut yuv_fast = Vec::new();
1332
1333 let texture_external_version = if device.get_capabilities().supports_image_external_essl3 {
1334 TextureExternalVersion::ESSL3
1335 } else {
1336 TextureExternalVersion::ESSL1
1337 };
1338
1339 let feature_flags = get_shader_feature_flags(gl_type, texture_external_version, device);
1340 let shader_list = get_shader_features(feature_flags);
1341
1342 for _ in 0..IMAGE_BUFFER_KINDS.len() {
1343 yuv_clip.push(None);
1344 yuv_fast.push(None);
1345 rgba.push(None);
1346 rgba_fast_path.push(None);
1347 }
1348
1349 for image_buffer_kind in &IMAGE_BUFFER_KINDS {
1350 if !has_platform_support(*image_buffer_kind, device) {
1351 continue;
1352 }
1353
1354 yuv_clip_features.push("YUV");
1355 yuv_fast_features.push("YUV");
1356 yuv_fast_features.push("FAST_PATH");
1357 fast_path_features.push("FAST_PATH");
1358
1359 let index = Self::get_shader_index(*image_buffer_kind);
1360
1361 let feature_string = get_feature_string(
1362 *image_buffer_kind,
1363 texture_external_version,
1364 );
1365 if feature_string != "" {
1366 yuv_clip_features.push(feature_string);
1367 yuv_fast_features.push(feature_string);
1368 rgba_features.push(feature_string);
1369 fast_path_features.push(feature_string);
1370 }
1371
1372 if *image_buffer_kind != ImageBufferKind::TextureExternal ||
1374 texture_external_version == TextureExternalVersion::ESSL3 {
1375
1376 yuv_clip[index] = Some(loader.create_shader(
1377 ShaderKind::Composite,
1378 "composite",
1379 &yuv_clip_features,
1380 &shader_list,
1381 )?);
1382
1383 yuv_fast[index] = Some(loader.create_shader(
1384 ShaderKind::Composite,
1385 "composite",
1386 &yuv_fast_features,
1387 &shader_list,
1388 )?);
1389 }
1390
1391 rgba[index] = Some(loader.create_shader(
1392 ShaderKind::Composite,
1393 "composite",
1394 &rgba_features,
1395 &shader_list,
1396 )?);
1397
1398 rgba_fast_path[index] = Some(loader.create_shader(
1399 ShaderKind::Composite,
1400 "composite",
1401 &fast_path_features,
1402 &shader_list,
1403 )?);
1404
1405 yuv_fast_features.clear();
1406 yuv_clip_features.clear();
1407 rgba_features.clear();
1408 fast_path_features.clear();
1409 }
1410
1411 Ok(CompositorShaders {
1412 rgba,
1413 rgba_fast_path,
1414 yuv_clip,
1415 yuv_fast,
1416 })
1417 }
1418
1419 pub fn get_handle(
1420 &mut self,
1421 format: CompositeSurfaceFormat,
1422 buffer_kind: ImageBufferKind,
1423 features: CompositeFeatures,
1424 ) -> ShaderHandle {
1425 match format {
1426 CompositeSurfaceFormat::Rgba => {
1427 if features.contains(CompositeFeatures::NO_UV_CLAMP)
1428 && features.contains(CompositeFeatures::NO_COLOR_MODULATION)
1429 && features.contains(CompositeFeatures::NO_CLIP_MASK)
1430 {
1431 let shader_index = Self::get_shader_index(buffer_kind);
1432 self.rgba_fast_path[shader_index]
1433 .expect("bug: unsupported rgba fast path shader requested")
1434 } else {
1435 let shader_index = Self::get_shader_index(buffer_kind);
1436 self.rgba[shader_index]
1437 .expect("bug: unsupported rgba shader requested")
1438 }
1439 }
1440 CompositeSurfaceFormat::Yuv => {
1441 let shader_index = Self::get_shader_index(buffer_kind);
1442 if features.contains(CompositeFeatures::NO_CLIP_MASK) {
1443 self.yuv_fast[shader_index]
1444 .expect("bug: unsupported yuv shader requested")
1445 } else {
1446 self.yuv_clip[shader_index]
1447 .expect("bug: unsupported yuv shader requested")
1448 }
1449 }
1450 }
1451 }
1452
1453 fn get_shader_index(buffer_kind: ImageBufferKind) -> usize {
1454 buffer_kind as usize
1455 }
1456}
1457
1458fn get_shader_feature_flags(
1459 gl_type: GlType,
1460 texture_external_version: TextureExternalVersion,
1461 device: &Device
1462) -> ShaderFeatureFlags {
1463 match gl_type {
1464 GlType::Gl => ShaderFeatureFlags::GL,
1465 GlType::Gles => {
1466 let mut flags = ShaderFeatureFlags::GLES;
1467 flags |= match texture_external_version {
1468 TextureExternalVersion::ESSL3 => ShaderFeatureFlags::TEXTURE_EXTERNAL,
1469 TextureExternalVersion::ESSL1 => ShaderFeatureFlags::TEXTURE_EXTERNAL_ESSL1,
1470 };
1471 if device.supports_extension("GL_EXT_YUV_target") {
1472 flags |= ShaderFeatureFlags::TEXTURE_EXTERNAL_BT709;
1473 }
1474 flags
1475 }
1476 }
1477}