1pub 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 TextureExternal = 5,
36 TextureExternalBT709 = 6,
37 TextureRect = 7,
38 }
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#[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
173pub 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}