/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use std::cell::RefCell; use std::collections::VecDeque; use std::rc::Rc;
use webrender_build::shader::{ShaderFeatures, ShaderFeatureFlags, get_shader_features};
/// Which extension version to use for texture external support. #[derive(Clone, Copy, Debug, PartialEq)] enum TextureExternalVersion { // GL_OES_EGL_image_external_essl3 (Compatible with ESSL 3.0 and // later shaders, but not supported on all GLES 3 devices.)
ESSL3, // GL_OES_EGL_image_external (Compatible with ESSL 1.0 shaders)
ESSL1,
}
letmut features = unsorted_features.to_vec();
features.sort();
// Ensure this shader config is in the available shader list so that we get // alerted if the list gets out-of-date when shaders or features are added. let config = features.join(",");
assert!(
shader_list.get(name).map_or(false, |f| f.contains(&config)), "shader \"{}\" with features \"{}\" not in available shader list",
name,
config,
);
let shader = LazilyCompiledShader {
program: None,
name,
kind, //Note: this isn't really the default state, but there is no chance // an actual projection passed here would accidentally match.
cached_projection: Transform3D::identity(),
features,
};
Ok(shader)
}
pubfn precache(
&mutself,
device: &mut Device,
flags: ShaderPrecacheFlags,
) -> Result<(), ShaderError> { let t0 = zeitstempel::now(); let timer_id = Telemetry::start_shaderload_time(); self.get_internal(device, flags, None)?;
Telemetry::stop_and_accumulate_shaderload_time(timer_id); let t1 = zeitstempel::now();
debug!("[C: {:.1} ms ] Precache {} {:?}",
(t1 - t0) as f64 / 1000000.0, self.name, self.features
);
Ok(())
}
// A brush shader supports two modes: // opaque: // Used for completely opaque primitives, // or inside segments of partially // opaque primitives. Assumes no need // for clip masks, AA etc. // alpha: // Used for brush primitives in the alpha // pass. Assumes that AA should be applied // along the primitive edge, and also that // clip mask is present. struct BrushShader {
opaque: ShaderHandle,
alpha: ShaderHandle,
advanced_blend: Option<ShaderHandle>,
dual_source: Option<ShaderHandle>,
debug_overdraw: ShaderHandle,
}
// These are "cache shaders". These shaders are used to // draw intermediate results to cache targets. The results // of these shaders are then used by the primitive shaders.
cs_blur_rgba8: ShaderHandle,
cs_border_segment: ShaderHandle,
cs_border_solid: ShaderHandle,
cs_scale: Vec<Option<ShaderHandle>>,
cs_line_decoration: ShaderHandle,
cs_svg_filter_node: ShaderHandle,
/// These are "cache clip shaders". These shaders are used to /// draw clip instances into the cached clip mask. The results /// of these shaders are also used by the primitive shaders.
cs_clip_rectangle_slow: ShaderHandle,
cs_clip_rectangle_fast: ShaderHandle,
// The are "primitive shaders". These shaders draw and blend // final results on screen. They are aware of tile boundaries. // Most draw directly to the framebuffer, but some use inputs // from the cache shaders to draw. Specifically, the box // shadow primitive shader stretches the box shadow cache // output, and the cache_image shader blits the results of // a cache shader (e.g. blur) to the screen.
ps_text_run: TextShader,
ps_text_run_dual_source: Option<TextShader>,
ps_split_composite: ShaderHandle, // ps_quad_textured comes in sampler-type-specific variants so that // external image sources (e.g. ANGLE DXGI textures) are sampled with the // matching sColor0 declaration. The variant is selected via PatternKind.
ps_quad_textured: ShaderHandle,
ps_quad_textured_external: Option<ShaderHandle>,
ps_quad_textured_external_bt709: Option<ShaderHandle>,
ps_quad_textured_rect: Option<ShaderHandle>,
ps_quad_repeat: ShaderHandle,
ps_quad_gradient: ShaderHandle,
ps_quad_box_shadow: ShaderHandle,
ps_mask: ShaderHandle,
ps_mask_fast: ShaderHandle,
ps_clear: ShaderHandle,
ps_copy: ShaderHandle,
let cs_blur_rgba8 = loader.create_shader(
ShaderKind::Cache(VertexArrayKind::Blur), "cs_blur",
&["COLOR_TARGET"],
&shader_list,
)?;
let cs_svg_filter_node = loader.create_shader(
ShaderKind::Cache(VertexArrayKind::SvgFilterNode), "cs_svg_filter_node",
&[],
&shader_list,
)?;
let ps_mask = loader.create_shader(
ShaderKind::Cache(VertexArrayKind::Mask), "ps_quad_mask",
&[],
&shader_list,
)?;
let ps_mask_fast = loader.create_shader(
ShaderKind::Cache(VertexArrayKind::Mask), "ps_quad_mask",
&[FAST_PATH_FEATURE],
&shader_list,
)?;
let cs_clip_rectangle_slow = loader.create_shader(
ShaderKind::ClipCache(VertexArrayKind::ClipRect), "cs_clip_rectangle",
&[],
&shader_list,
)?;
let cs_clip_rectangle_fast = loader.create_shader(
ShaderKind::ClipCache(VertexArrayKind::ClipRect), "cs_clip_rectangle",
&[FAST_PATH_FEATURE],
&shader_list,
)?;
letmut cs_scale = Vec::new(); let scale_shader_num = IMAGE_BUFFER_KINDS.len(); // PrimitiveShader is not clonable. Use push() to initialize the vec. for _ in0 .. scale_shader_num {
cs_scale.push(None);
} for image_buffer_kind in &IMAGE_BUFFER_KINDS { if has_platform_support(*image_buffer_kind, device) { let feature_string = get_feature_string(
*image_buffer_kind,
texture_external_version,
);
letmut features = Vec::new(); if feature_string != "" {
features.push(feature_string);
}
let shader = loader.create_shader(
ShaderKind::Cache(VertexArrayKind::Scale), "cs_scale",
&features,
&shader_list,
)?;
let index = Self::get_compositing_shader_index(
*image_buffer_kind,
);
cs_scale[index] = Some(shader);
}
}
// TODO(gw): The split composite + text shader are special cases - the only // shaders used during normal scene rendering that aren't a brush // shader. Perhaps we can unify these in future?
let ps_text_run = TextShader::new("ps_text_run",
&[],
&shader_list,
&mut loader,
)?;
let ps_text_run_dual_source = if use_dual_source_blending { let dual_source_features = vec![DUAL_SOURCE_FEATURE];
Some(TextShader::new("ps_text_run",
&dual_source_features,
&shader_list,
&mut loader,
)?)
} else {
None
};
let ps_quad_textured = loader.create_shader(
ShaderKind::Primitive, "ps_quad_textured",
&["TEXTURE_2D"],
&shader_list,
)?;
// The TextureExternal variants are only used on devices that expose // GL_OES_EGL_image_external via ESSL3. ESSL1 doesn't support the // GLSL features used by the quad shaders. let ps_quad_textured_external = if has_platform_support(
ImageBufferKind::TextureExternal, device,
) && texture_external_version == TextureExternalVersion::ESSL3
{
Some(loader.create_shader(
ShaderKind::Primitive, "ps_quad_textured",
&["TEXTURE_EXTERNAL"],
&shader_list,
)?)
} else {
None
};
let ps_quad_textured_external_bt709 = if has_platform_support(
ImageBufferKind::TextureExternalBT709, device,
) {
Some(loader.create_shader(
ShaderKind::Primitive, "ps_quad_textured",
&["TEXTURE_EXTERNAL_BT709"],
&shader_list,
)?)
} else {
None
};
let ps_quad_textured_rect = if has_platform_support(
ImageBufferKind::TextureRect, device,
) {
Some(loader.create_shader(
ShaderKind::Primitive, "ps_quad_textured",
&["TEXTURE_RECT"],
&shader_list,
)?)
} else {
None
};
let ps_quad_repeat = loader.create_shader(
ShaderKind::Primitive, "ps_quad_repeat",
&[],
&shader_list,
)?;
let ps_quad_gradient = loader.create_shader(
ShaderKind::Primitive, "ps_quad_gradient", if options.enable_dithering {
&[DITHERING_FEATURE]
} else {
&[]
},
&shader_list,
)?;
let ps_quad_box_shadow = loader.create_shader(
ShaderKind::Primitive, "ps_quad_box_shadow",
&[],
&shader_list,
)?;
let ps_split_composite = loader.create_shader(
ShaderKind::Primitive, "ps_split_composite",
&[],
&shader_list,
)?;
let ps_clear = loader.create_shader(
ShaderKind::Clear, "ps_clear",
&[],
&shader_list,
)?;
let ps_copy = loader.create_shader(
ShaderKind::Copy, "ps_copy",
&[],
&shader_list,
)?;
// All image configuration. letmut image_features = Vec::new(); letmut brush_image = Vec::new(); letmut brush_fast_image = Vec::new(); // PrimitiveShader is not clonable. Use push() to initialize the vec. for _ in0 .. IMAGE_BUFFER_KINDS.len() {
brush_image.push(None);
brush_fast_image.push(None);
} for buffer_kind in0 .. IMAGE_BUFFER_KINDS.len() { if !has_platform_support(IMAGE_BUFFER_KINDS[buffer_kind], device) // Brush shaders are not ESSL1 compatible
|| (IMAGE_BUFFER_KINDS[buffer_kind] == ImageBufferKind::TextureExternal
&& texture_external_version == TextureExternalVersion::ESSL1)
{ continue;
}
let feature_string = get_feature_string(
IMAGE_BUFFER_KINDS[buffer_kind],
texture_external_version,
); if feature_string != "" {
image_features.push(feature_string);
}
// All yuv_image configuration. letmut yuv_features = Vec::new(); letmut rgba_features = Vec::new(); letmut fast_path_features = Vec::new(); let yuv_shader_num = IMAGE_BUFFER_KINDS.len(); letmut brush_yuv_image = Vec::new(); // PrimitiveShader is not clonable. Use push() to initialize the vec. for _ in0 .. yuv_shader_num {
brush_yuv_image.push(None);
} for image_buffer_kind in &IMAGE_BUFFER_KINDS { if has_platform_support(*image_buffer_kind, device) {
yuv_features.push("YUV");
fast_path_features.push("FAST_PATH");
let index = Self::get_compositing_shader_index(
*image_buffer_kind,
);
let feature_string = get_feature_string(
*image_buffer_kind,
texture_external_version,
); if feature_string != "" {
yuv_features.push(feature_string);
rgba_features.push(feature_string);
fast_path_features.push(feature_string);
}
// YUV shaders are not compatible with ESSL1 if *image_buffer_kind != ImageBufferKind::TextureExternal ||
texture_external_version == TextureExternalVersion::ESSL3 { let brush_shader = BrushShader::new( "brush_yuv_image",
&yuv_features,
&shader_list, false/* advanced blend */, false/* dual source */,
&mut loader,
)?;
brush_yuv_image[index] = Some(brush_shader);
}
pubstruct CompositorShaders { // Composite shaders. These are very simple shaders used to composite // picture cache tiles into the framebuffer on platforms that do not have an // OS Compositor (or we cannot use it). Such an OS Compositor (such as // DirectComposite or CoreAnimation) handles the composition of the picture // cache tiles at a lower level (e.g. in DWM for Windows); in that case we // directly hand the picture cache surfaces over to the OS Compositor, and // our own Composite shaders below never run. // To composite external (RGB) surfaces we need various permutations of // shaders with WR_FEATURE flags on or off based on the type of image // buffer we're sourcing from (see IMAGE_BUFFER_KINDS).
rgba: Vec<Option<ShaderHandle>>, // A faster set of rgba composite shaders that do not support UV clamping // or color modulation.
rgba_fast_path: Vec<Option<ShaderHandle>>, // The same set of composite shaders but with WR_FEATURE_YUV added.
yuv_clip: Vec<Option<ShaderHandle>>,
yuv_fast: Vec<Option<ShaderHandle>>,
}
let index = Self::get_shader_index(*image_buffer_kind);
let feature_string = get_feature_string(
*image_buffer_kind,
texture_external_version,
); if feature_string != "" {
yuv_clip_features.push(feature_string);
yuv_fast_features.push(feature_string);
rgba_features.push(feature_string);
fast_path_features.push(feature_string);
}
// YUV shaders are not compatible with ESSL1 if *image_buffer_kind != ImageBufferKind::TextureExternal ||
texture_external_version == TextureExternalVersion::ESSL3 {
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.