Skip to main content

webrender/pattern/
mod.rs

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
5pub mod gradient;
6pub mod box_shadow;
7pub mod repeat;
8pub mod image;
9pub mod cutout;
10
11use api::units::{LayoutVector2D, LayoutPoint};
12use api::{ColorF, units::DeviceRect};
13
14use crate::frame_builder::FrameBuilderConfig;
15use crate::render_task_graph::RenderTaskId;
16use crate::renderer::{BlendMode, GpuBufferBuilder};
17use crate::spatial_tree::SpatialTree;
18use crate::transform::TransformPalette;
19
20#[repr(u32)]
21#[cfg_attr(feature = "capture", derive(Serialize))]
22#[cfg_attr(feature = "replay", derive(Deserialize))]
23#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
24pub enum PatternKind {
25    ColorOrTexture = 0,
26    Gradient = 1,
27    Repeat = 2,
28
29    Mask = 3,
30    BoxShadow = 4,
31    // Variants of ColorOrTexture that use a non-default sampler type
32    // (samplerExternalOES / __samplerExternal2DY2YEXT / sampler2DRect). The
33    // quad shader is compiled in matching per-kind variants; see
34    // ps_quad_textured.glsl.
35    TextureExternal = 5,
36    TextureExternalBT709 = 6,
37    TextureRect = 7,
38    // When adding patterns, don't forget to update the NUM_PATTERNS constant.
39}
40
41pub const NUM_PATTERNS: u32 = 8;
42
43impl PatternKind {
44    pub fn from_u32(val: u32) -> Self {
45        assert!(val < NUM_PATTERNS);
46        unsafe { std::mem::transmute(val) }
47    }
48}
49
50/// A 32bit payload used as input for the pattern-specific logic in the shader.
51///
52/// Patterns typically use it as a GpuBuffer offset to fetch their data.
53#[cfg_attr(feature = "capture", derive(Serialize))]
54#[cfg_attr(feature = "replay", derive(Deserialize))]
55#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
56pub struct PatternShaderInput(pub i32, pub i32);
57
58impl Default for PatternShaderInput {
59    fn default() -> Self {
60        PatternShaderInput(0, 0)
61    }
62}
63
64#[cfg_attr(feature = "capture", derive(Serialize))]
65#[cfg_attr(feature = "replay", derive(Deserialize))]
66#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
67pub struct PatternTextureInput {
68    pub task_id: RenderTaskId,
69}
70
71impl Default for PatternTextureInput {
72    fn default() -> Self {
73        PatternTextureInput {
74            task_id: RenderTaskId::INVALID,
75        }
76    }
77}
78
79impl PatternTextureInput {
80    pub fn new(task_id: RenderTaskId) -> Self {
81        PatternTextureInput {
82            task_id,
83        }
84    }
85}
86
87pub struct PatternBuilderContext<'a> {
88    pub spatial_tree: &'a SpatialTree,
89    pub fb_config: &'a FrameBuilderConfig,
90    pub prim_origin: LayoutPoint,
91}
92
93pub struct PatternBuilderState<'a> {
94    pub frame_gpu_data: &'a mut GpuBufferBuilder,
95    #[allow(unused)]
96    pub transforms: &'a mut TransformPalette,
97}
98
99pub trait PatternBuilder {
100    fn build(
101        &self,
102        sub_rect: Option<DeviceRect>,
103        offset: LayoutVector2D,
104        ctx: &PatternBuilderContext,
105        state: &mut PatternBuilderState,
106    ) -> Pattern;
107}
108
109#[cfg_attr(feature = "capture", derive(Serialize))]
110#[derive(Clone, Debug)]
111pub struct Pattern {
112    pub kind: PatternKind,
113    pub shader_input: PatternShaderInput,
114    pub texture_input: PatternTextureInput,
115    pub base_color: ColorF,
116    pub is_opaque: bool,
117    pub blend_mode: BlendMode,
118}
119
120impl Pattern {
121    pub fn color(color: ColorF) -> Self {
122        Pattern {
123            kind: PatternKind::ColorOrTexture,
124            shader_input: PatternShaderInput(
125                TEXTURED_SHADER_MODE_COLOR,
126                0,
127            ),
128            texture_input: PatternTextureInput::default(),
129            base_color: color,
130            is_opaque: color.a >= 1.0,
131            blend_mode: BlendMode::PremultipliedAlpha,
132        }
133    }
134
135    pub fn texture(src_task: RenderTaskId, is_opaque: bool) -> Self {
136        Pattern {
137            kind: PatternKind::ColorOrTexture,
138            shader_input: PatternShaderInput(
139                TEXTURED_SHADER_MODE_TEXTURE,
140                TEXTURED_SHADER_MAP_TO_PRIMITIVE,
141            ),
142            texture_input: PatternTextureInput::new(src_task),
143            base_color: ColorF::WHITE,
144            is_opaque,
145            blend_mode: BlendMode::PremultipliedAlpha,
146        }
147    }
148
149    pub fn with_blend_mode(mut self, blend_mode: BlendMode) -> Self {
150        self.blend_mode = blend_mode;
151
152        self
153    }
154
155    pub fn with_base_color(mut self, color: ColorF) -> Self {
156        self.base_color = color;
157
158        self
159    }
160
161    pub fn as_render_task(&self) -> Option<RenderTaskId> {
162        if self.kind != PatternKind::ColorOrTexture || self.texture_input.task_id == RenderTaskId::INVALID {
163            return None;
164        }
165
166        Some(self.texture_input.task_id)
167    }
168}
169
170pub const TEXTURED_SHADER_MODE_COLOR: i32 = 0;
171pub const TEXTURED_SHADER_MODE_TEXTURE: i32 = 1;
172
173// In the texture mode, whether to map the texture to the primitive's local rect
174// or segment rect.
175pub const TEXTURED_SHADER_MAP_TO_PRIMITIVE: i32 = 0;
176pub const TEXTURED_SHADER_MAP_TO_SEGMENT: i32 = 1;
177
178impl PatternBuilder for ColorF {
179    fn build(
180        &self,
181        _sub_rect: Option<DeviceRect>,
182        _offset: LayoutVector2D,
183        _ctx: &PatternBuilderContext,
184        _state: &mut PatternBuilderState,
185    ) -> Pattern {
186        Pattern::color(*self)
187    }
188}