ribir_gpu/lib.rs
1pub mod error;
2use std::ops::Range;
3
4pub use gpu_backend::Texture;
5use ribir_geom::{DevicePoint, DeviceRect, DeviceSize};
6use ribir_painter::{image::ColorFormat, Color, GradientStop, VertexBuffers};
7mod gpu_backend;
8use zerocopy::AsBytes;
9
10#[cfg(feature = "wgpu")]
11pub mod wgpu_impl;
12pub use gpu_backend::*;
13#[cfg(feature = "wgpu")]
14pub use wgpu_impl::*;
15
16/// Trait to help implement a gpu backend.
17///
18/// The call graph:
19///
20/// -- begin_frame()
21
22/// +--->-------- Draw Phase --------------------------+
23/// | |
24/// | +->- new_texture()----+ |
25/// | +-<-------<------<----+ |
26/// | v
27/// | -> load_alpha_vertices() |
28/// | |
29/// | -> + draw_alpha_triangles_with_scissor()--+ |
30/// | ^ v |
31/// | ^----<-----------<---------------------+ |
32/// | |
33/// | -> + draw_alpha_triangles()---------------+ |
34/// | ^ v |
35/// | +----<-----------<---------------------+ |
36/// | |
37/// | -> load_textures() |
38/// | -> load_mask_layers() |
39/// | |
40/// | +--------------------------+ |
41/// | | load_color_vertices() | |
42/// | +->| draw_color_triangles() | |
43/// | | +--------------------------+ |
44/// | | |
45/// | | +--------------------------+ |
46/// | | | load_img_primitives() | |
47/// | +->| load_image_vertices() | |
48/// | | | draw_img_triangles() | |
49/// | | +--------------------------+ |
50/// | | |
51/// | -> | +------------------------------------+ |
52/// | | | load_radial_gradient_primitives() | v
53/// | +->| load_radial_gradient_stops() | |
54/// | | | load_radial_gradient_vertices() | |
55/// | | | draw_radial_gradient_triangles() | |
56/// | | +------------------------------------+ |
57/// | | |
58/// | | +------------------------------------+ |
59/// | | | load_linear_gradient_primitives() | |
60/// | +->| load_linear_gradient_stops() | |
61/// | | load_linear_gradient_vertices() | |
62/// | | draw_linear_gradient_triangles() | |
63/// | +------------------------------------+ |
64/// +---<----------------------------------------------+
65///
66/// -+ ->- end_frame()
67///
68/// The coordinate always start from the left-top to right-bottom. Vertices
69/// use percent as value, and others use pixel value.
70/// Vertices Axis Device axis
71/// 0 +----x----+> 1 0 +----x-----+> width
72/// | | | |
73/// y | y |
74/// | | | |
75/// +---------+ +----------+
76/// v v
77/// 1 height
78
79pub trait GPUBackendImpl {
80 type Texture: Texture;
81
82 /// A frame start, call once per frame
83 fn begin_frame(&mut self);
84
85 /// Returns the limits of the GPU backend.
86 fn limits(&self) -> &DrawPhaseLimits;
87
88 /// Create a texture.
89 fn new_texture(&mut self, size: DeviceSize, format: ColorFormat) -> Self::Texture;
90 /// Load the vertices and indices buffer that `draw_alpha_triangles` &
91 /// `draw_alpha_triangles_with_scissor` will use.
92 fn load_alpha_vertices(&mut self, buffers: &VertexBuffers<()>);
93 /// Draw triangles only alpha channel with 1.0. Caller guarantee the texture
94 /// format is `ColorFormat::Alpha8`, caller will try to batch as much as
95 /// possible, but also possibly call multi times in a frame.
96 fn draw_alpha_triangles(&mut self, indices: &Range<u32>, texture: &mut Self::Texture);
97 /// Same behavior as `draw_alpha_triangles`, but the Vertex with a offset and
98 /// gives a clip rectangle for the texture, the path should only painting in
99 /// the rectangle.
100 fn draw_alpha_triangles_with_scissor(
101 &mut self, indices: &Range<u32>, texture: &mut Self::Texture, scissor: DeviceRect,
102 );
103
104 /// load textures that will be use in this draw phase
105 fn load_textures(&mut self, textures: &[&Self::Texture]);
106 /// load the mask layers that the current draw phase will use, called at
107 /// most once per draw phase.
108 fn load_mask_layers(&mut self, layers: &[MaskLayer]);
109 /// Load the vertices and indices buffer that `draw_color_triangles` will
110 /// use.
111 fn load_color_vertices(&mut self, buffers: &VertexBuffers<ColorAttr>);
112 /// Load the vertices and indices buffer that `draw_img_triangles` will use.
113 fn load_img_primitives(&mut self, primitives: &[ImgPrimitive]);
114 /// Load the vertices and indices buffer that `draw_img_triangles` will use.
115 fn load_img_vertices(&mut self, buffers: &VertexBuffers<ImagePrimIndex>);
116
117 /// Load the primitives that `draw_radial_gradient_triangles` will use.
118 fn load_radial_gradient_primitives(&mut self, primitives: &[RadialGradientPrimitive]);
119 /// Load the gradient color stops that `draw_radial_gradient_triangles` will
120 /// use.
121 fn load_radial_gradient_stops(&mut self, stops: &[GradientStopPrimitive]);
122 /// Load the vertices and indices buffer that `draw_radial_gradient_triangles`
123 /// will use.
124 fn load_radial_gradient_vertices(&mut self, buffers: &VertexBuffers<RadialGradientPrimIndex>);
125
126 /// Load the primitives that `draw_linear_gradient_triangles` will use.
127 fn load_linear_gradient_primitives(&mut self, primitives: &[LinearGradientPrimitive]);
128 /// Load the gradient color stops that `draw_linear_gradient_triangles` will
129 /// use.
130 fn load_linear_gradient_stops(&mut self, stops: &[GradientStopPrimitive]);
131 /// Load the vertices and indices buffer that `draw_linear_gradient_triangles`
132 /// will use.
133 fn load_linear_gradient_vertices(&mut self, buffers: &VertexBuffers<LinearGradientPrimIndex>);
134 /// Draw pure color triangles in the texture. And use the clear color clear
135 /// the texture first if it's a Some-Value
136 fn draw_color_triangles(
137 &mut self, texture: &mut Self::Texture, indices: Range<u32>, clear: Option<Color>,
138 );
139 /// Draw triangles fill with image. And use the clear color clear the texture
140 /// first if it's a Some-Value
141 fn draw_img_triangles(
142 &mut self, texture: &mut Self::Texture, indices: Range<u32>, clear: Option<Color>,
143 );
144 /// Draw triangles fill with color radial gradient. And use the clear color
145 /// clear the texture first if it's a Some-Value
146 fn draw_radial_gradient_triangles(
147 &mut self, texture: &mut Self::Texture, indices: Range<u32>, clear: Option<Color>,
148 );
149
150 /// Draw triangles fill with color linear gradient. And use the clear color
151 /// clear the texture first if it's a Some-Value
152 fn draw_linear_gradient_triangles(
153 &mut self, texture: &mut Self::Texture, indices: Range<u32>, clear: Option<Color>,
154 );
155
156 fn copy_texture_from_texture(
157 &mut self, dist_tex: &mut Self::Texture, copy_to: DevicePoint, from_tex: &Self::Texture,
158 from_rect: &DeviceRect,
159 );
160 /// A frame end, call once per frame
161 fn end_frame(&mut self);
162}
163
164/// Represents the sets of limits an GPU backend can provide in a single draw
165pub struct DrawPhaseLimits {
166 /// The maximum size of the texture that the backend can create.
167 pub texture_size: DeviceSize,
168 /// The maximum number of textures that the backend can load in a single draw
169 pub max_tex_load: usize,
170 /// The maximum number of mask layers that the backend can load in a single
171 /// draw phase
172 pub max_image_primitives: usize,
173 /// The maximum number of radial gradient primitives that the backend can load
174 /// in a single draw
175 pub max_radial_gradient_primitives: usize,
176 /// The maximum number of linear gradient primitives that the backend can load
177 /// in a single draw
178 pub max_linear_gradient_primitives: usize,
179 /// The maximum number of gradient stops that the backend can load in a single
180 /// draw phase
181 pub max_gradient_stop_primitives: usize,
182 /// The maximum number of mask layers that the backend can load in a single
183 pub max_mask_layers: usize,
184}
185
186#[repr(packed)]
187#[derive(AsBytes, PartialEq, Clone, Copy)]
188pub struct ColorAttr {
189 /// brush's Rgba color
190 pub color: [u8; 4],
191 /// The index of the head mask layer.
192 pub mask_head: i32,
193}
194
195#[repr(packed)]
196#[derive(AsBytes, PartialEq, Clone, Copy, Debug)]
197pub struct ImagePrimIndex(u32);
198
199#[repr(packed)]
200#[derive(AsBytes, PartialEq, Clone, Copy, Debug)]
201pub struct RadialGradientPrimIndex(u32);
202
203#[repr(packed)]
204#[derive(AsBytes, PartialEq, Clone, Copy, Debug)]
205pub struct LinearGradientPrimIndex(u32);
206
207#[repr(packed)]
208#[derive(AsBytes, PartialEq, Clone, Copy, Debug)]
209pub struct GradientStopPrimitive {
210 pub color: u32,
211 pub offset: f32,
212}
213
214impl GradientStopPrimitive {
215 fn new(stop: &GradientStop) -> Self {
216 GradientStopPrimitive { color: stop.color.into_u32(), offset: stop.offset }
217 }
218}
219
220#[repr(packed)]
221#[derive(AsBytes, PartialEq, Clone, Copy, Debug)]
222pub struct RadialGradientPrimitive {
223 /// A 2x3 column-major matrix, transform a vertex position to the texture
224 /// position
225 pub transform: [f32; 6],
226 /// The color stop's start index
227 pub stop_start: u32,
228 /// The size of the color stop
229 pub stop_cnt: u32,
230 /// position of the start center
231 pub start_center: [f32; 2],
232 /// position of the end center
233 pub end_center: [f32; 2],
234 /// the radius of the start circle.
235 pub start_radius: f32,
236 /// the radius of the end circle.
237 pub end_radius: f32,
238 /// The index of the head mask layer.
239 pub mask_head: i32,
240 /// the spread method of the gradient. 0 for pad, 1 for reflect and 2
241 /// for repeat
242 pub spread: u32,
243}
244
245#[repr(packed)]
246#[derive(AsBytes, PartialEq, Clone, Copy, Debug)]
247pub struct LinearGradientPrimitive {
248 /// A 2x3 column-major matrix, transform a vertex position to the texture
249 /// position
250 pub transform: [f32; 6],
251 /// position of the start center
252 pub start_position: [f32; 2],
253 /// position of the end center
254 pub end_position: [f32; 2],
255 /// The color stop information, there are two parts:
256 /// - The high 16-bit index represents the start index of the color stop.
257 /// - The low 16-bit index represents the size of the color stop.
258 pub stop: u32,
259 /// A mix of two 16-bit values:
260 /// - The high 16-bit index represents the head mask layer.
261 /// - The low 16-bit represents the spread method of the gradient. 0 for pad,
262 /// 1 for reflect and 2 for repeat
263 pub mask_head_and_spread: i32,
264}
265
266#[repr(packed)]
267#[derive(AsBytes, PartialEq, Clone, Copy)]
268pub struct ImgPrimitive {
269 /// A 2x3 column-major matrix, transform a vertex position to the image
270 /// texture slice position.
271 pub transform: [f32; 6],
272 /// The origin of the image placed in texture.
273 pub img_start: [f32; 2],
274 /// The size of the image image.
275 pub img_size: [f32; 2],
276 /// This represents a mix of two 16-bit indices:
277 /// - The high 16-bit index represents the head mask layer. It is an i16.
278 /// - The low 16-bit index represents the texture. It is a u16.
279 pub mask_head_and_tex_idx: i32,
280 /// extra alpha apply to current vertex
281 pub opacity: f32,
282}
283
284/// The mask layer describes an alpha channel layer that is used in the fragment
285/// shader to sample the alpha channel and apply it to the color.
286#[derive(AsBytes, Clone)]
287#[repr(packed)]
288pub struct MaskLayer {
289 /// A 2x3 column-major matrix, transform a vertex position to its mask texture
290 /// position.
291 pub transform: [f32; 6],
292 /// The min position this layer in the texture.
293 pub min: [f32; 2],
294 /// max min position this layer in the texture.
295 pub max: [f32; 2],
296 /// The index of the texture(alpha) that contained this layer,
297 /// `load_textures` method provide all textures a draw phase need.
298 pub mask_tex_idx: u32,
299 /// The index of the previous mask layer needs to continue to be applied. The
300 /// negative value means there isn't any more mask layer that needs to be
301 /// applied.
302 pub prev_mask_idx: i32,
303}