1use api::{MixBlendMode, units::PictureRect};
6use crate::pattern::{PatternKind, PatternShaderInput};
7use crate::renderer::BlendMode;
8use crate::{spatial_tree::SpatialNodeIndex, render_task_graph::RenderTaskId, surface::SurfaceTileDescriptor, tile_cache::TileKey, renderer::GpuBufferAddress, FastHashMap};
9use crate::gpu_types::QuadSegment;
10use crate::prim_store::storage;
11use crate::segment::EdgeMask;
12use crate::transform::GpuTransformId;
13use crate::visibility::PrimitiveDrawHeader;
14
15#[cfg_attr(feature = "capture", derive(Serialize))]
17#[cfg_attr(feature = "replay", derive(Deserialize))]
18#[derive(Debug, Copy, Clone)]
19pub struct Command(u32);
20
21impl Command {
22 const CMD_DRAW_SIMPLE_PRIM: u32 = 0x00000000;
24 const CMD_SET_SPATIAL_NODE: u32 = 0x10000000;
26 const CMD_DRAW_COMPLEX_PRIM: u32 = 0x20000000;
28 const CMD_DRAW_INSTANCE: u32 = 0x30000000;
30 const CMD_DRAW_QUAD: u32 = 0x40000000;
32 const CMD_SET_SEGMENTS: u32 = 0x50000000;
34
35 const CMD_MASK: u32 = 0xf0000000;
37 const PARAM_MASK: u32 = 0x0fffffff;
39
40 fn draw_simple_prim(draw_index: storage::Index<PrimitiveDrawHeader>) -> Self {
42 Command(Command::CMD_DRAW_SIMPLE_PRIM | draw_index.0)
43 }
44
45 fn set_spatial_node(spatial_node_index: SpatialNodeIndex) -> Self {
47 Command(Command::CMD_SET_SPATIAL_NODE | spatial_node_index.0)
48 }
49
50 fn set_segments(count: usize) -> Self {
52 Command(Command::CMD_SET_SEGMENTS | count as u32)
53 }
54
55 fn draw_complex_prim(draw_index: storage::Index<PrimitiveDrawHeader>) -> Self {
57 Command(Command::CMD_DRAW_COMPLEX_PRIM | draw_index.0)
58 }
59
60 fn draw_instance(draw_index: storage::Index<PrimitiveDrawHeader>) -> Self {
61 Command(Command::CMD_DRAW_INSTANCE | draw_index.0)
62 }
63
64 fn data(data: u32) -> Self {
66 Command(data)
67 }
68
69 fn draw_quad(draw_index: storage::Index<PrimitiveDrawHeader>) -> Self {
70 Command(Command::CMD_DRAW_QUAD | draw_index.0)
71 }
72}
73
74bitflags! {
75 #[repr(transparent)]
77 #[cfg_attr(feature = "capture", derive(Serialize))]
78 #[cfg_attr(feature = "replay", derive(Deserialize))]
79 #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
80 pub struct QuadFlags : u8 {
81 const IS_OPAQUE = 1 << 0;
82
83 const APPLY_RENDER_TASK_CLIP = 1 << 1;
86
87 const USE_AA_SEGMENTS = 1 << 3;
89
90 const IS_MASK = 1 << 4;
94 }
95}
96
97bitflags! {
98 #[repr(transparent)]
100 #[cfg_attr(feature = "capture", derive(Serialize))]
101 #[cfg_attr(feature = "replay", derive(Deserialize))]
102 #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
103 pub struct MaskFlags : i32 {
104 const PRIM_SPACE = 1 << 0;
105 }
106}
107
108#[cfg_attr(feature = "capture", derive(Serialize))]
116pub enum PrimitiveCommand {
117 Simple {
118 draw_index: storage::Index<PrimitiveDrawHeader>,
119 },
120 Complex {
121 draw_index: storage::Index<PrimitiveDrawHeader>,
122 gpu_address: GpuBufferAddress,
123 },
124 Instance {
125 draw_index: storage::Index<PrimitiveDrawHeader>,
126 gpu_buffer_address: GpuBufferAddress,
127 },
128 Quad {
129 pattern: PatternKind,
130 pattern_input: PatternShaderInput,
131 src_color_task_id: RenderTaskId,
132 draw_index: storage::Index<PrimitiveDrawHeader>,
134 gpu_buffer_address: GpuBufferAddress,
135 transform_id: GpuTransformId,
136 quad_flags: QuadFlags,
137 edge_flags: EdgeMask,
138 blend_mode: BlendMode,
139 },
140}
141
142impl PrimitiveCommand {
143 pub fn simple(
144 draw_index: storage::Index<PrimitiveDrawHeader>,
145 ) -> Self {
146 PrimitiveCommand::Simple {
147 draw_index,
148 }
149 }
150
151 pub fn complex(
152 draw_index: storage::Index<PrimitiveDrawHeader>,
153 gpu_address: GpuBufferAddress,
154 ) -> Self {
155 PrimitiveCommand::Complex {
156 draw_index,
157 gpu_address,
158 }
159 }
160
161 pub fn quad(
162 pattern: PatternKind,
163 pattern_input: PatternShaderInput,
164 src_color_task_id: RenderTaskId,
165 draw_index: storage::Index<PrimitiveDrawHeader>,
166 gpu_buffer_address: GpuBufferAddress,
167 transform_id: GpuTransformId,
168 quad_flags: QuadFlags,
169 edge_flags: EdgeMask,
170 blend_mode: BlendMode,
171 ) -> Self {
172 PrimitiveCommand::Quad {
173 pattern,
174 pattern_input,
175 src_color_task_id,
176 draw_index,
177 gpu_buffer_address,
178 transform_id,
179 quad_flags,
180 edge_flags,
181 blend_mode,
182 }
183 }
184
185 pub fn instance(
186 draw_index: storage::Index<PrimitiveDrawHeader>,
187 gpu_buffer_address: GpuBufferAddress,
188 ) -> Self {
189 PrimitiveCommand::Instance {
190 draw_index,
191 gpu_buffer_address,
192 }
193 }
194}
195
196
197fn encode_blend_mode(blend_mode: BlendMode) -> u32 {
201 match blend_mode {
202 BlendMode::None => 0,
203 BlendMode::Alpha => 1,
204 BlendMode::PremultipliedAlpha => 2,
205 BlendMode::PremultipliedDestOut => 3,
206 BlendMode::SubpixelDualSource => 4,
207 BlendMode::MultiplyDualSource => 5,
208 BlendMode::Screen => 6,
209 BlendMode::Exclusion => 7,
210 BlendMode::PlusLighter => 8,
211 BlendMode::Advanced(mode) => 9 + mode as u32,
212 }
213}
214
215fn decode_blend_mode(val: u32) -> BlendMode {
216 match val {
217 0 => BlendMode::None,
218 1 => BlendMode::Alpha,
219 2 => BlendMode::PremultipliedAlpha,
220 3 => BlendMode::PremultipliedDestOut,
221 4 => BlendMode::SubpixelDualSource,
222 5 => BlendMode::MultiplyDualSource,
223 6 => BlendMode::Screen,
224 7 => BlendMode::Exclusion,
225 8 => BlendMode::PlusLighter,
226 _ => BlendMode::Advanced(unsafe { std::mem::transmute::<u8, MixBlendMode>((val - 9) as u8) }),
227 }
228}
229
230#[cfg_attr(feature = "capture", derive(Serialize))]
232#[cfg_attr(feature = "replay", derive(Deserialize))]
233pub struct CommandBuffer {
234 commands: Vec<Command>,
236 current_spatial_node_index: SpatialNodeIndex,
238}
239
240impl CommandBuffer {
241 pub fn new() -> Self {
243 CommandBuffer {
244 commands: Vec::new(),
245 current_spatial_node_index: SpatialNodeIndex::INVALID,
246 }
247 }
248
249 pub fn set_segments(
251 &mut self,
252 segments: &[QuadSegment],
253 ) {
254 self.commands.push(Command::set_segments(segments.len()));
255 for segment in segments {
256 self.commands.push(Command::data(segment.task_id.index));
257 self.commands.push(Command::data(segment.task_id.sub_rect_index as u32));
258 }
259 }
260
261 pub fn add_prim(
263 &mut self,
264 prim_cmd: &PrimitiveCommand,
265 spatial_node_index: SpatialNodeIndex,
266 ) {
267 if self.current_spatial_node_index != spatial_node_index {
268 self.commands.push(Command::set_spatial_node(spatial_node_index));
269 self.current_spatial_node_index = spatial_node_index;
270 }
271
272 self.add_cmd(prim_cmd);
273 }
274
275 pub fn add_cmd(
277 &mut self,
278 prim_cmd: &PrimitiveCommand,
279 ) {
280 match *prim_cmd {
281 PrimitiveCommand::Simple { draw_index } => {
282 self.commands.push(Command::draw_simple_prim(draw_index));
283 }
284 PrimitiveCommand::Complex { draw_index, gpu_address } => {
285 self.commands.push(Command::draw_complex_prim(draw_index));
286 self.commands.push(Command::data(gpu_address.as_u32()));
287 }
288 PrimitiveCommand::Instance { draw_index, gpu_buffer_address } => {
289 self.commands.push(Command::draw_instance(draw_index));
290 self.commands.push(Command::data(gpu_buffer_address.as_u32()));
291 }
292 PrimitiveCommand::Quad { pattern, pattern_input, draw_index, gpu_buffer_address, transform_id, quad_flags, edge_flags, src_color_task_id, blend_mode } => {
293 self.commands.push(Command::draw_quad(draw_index));
294 self.commands.push(Command::data(pattern as u32));
295 self.commands.push(Command::data(pattern_input.0 as u32));
296 self.commands.push(Command::data(pattern_input.1 as u32));
297 self.commands.push(Command::data(src_color_task_id.index));
298 self.commands.push(Command::data(src_color_task_id.sub_rect_index as u32));
299 self.commands.push(Command::data(gpu_buffer_address.as_u32()));
300 self.commands.push(Command::data(transform_id.0));
301 self.commands.push(Command::data((quad_flags.bits() as u32) << 16 | edge_flags.bits() as u32));
302 self.commands.push(Command::data(encode_blend_mode(blend_mode)));
303 }
304 }
305 }
306
307 pub fn iter_prims<F>(
309 &self,
310 f: &mut F,
311 ) where F: FnMut(&PrimitiveCommand, SpatialNodeIndex, &[RenderTaskId]) {
312 let mut current_spatial_node_index = SpatialNodeIndex::INVALID;
313 let mut cmd_iter = self.commands.iter();
314 let mut segments = Vec::new();
316
317 while let Some(cmd) = cmd_iter.next() {
318 let command = cmd.0 & Command::CMD_MASK;
319 let param = cmd.0 & Command::PARAM_MASK;
320
321 match command {
322 Command::CMD_DRAW_SIMPLE_PRIM => {
323 let draw_index = storage::Index::from_u32(param);
324 let cmd = PrimitiveCommand::simple(draw_index);
325 f(&cmd, current_spatial_node_index, &[]);
326 }
327 Command::CMD_SET_SPATIAL_NODE => {
328 current_spatial_node_index = SpatialNodeIndex(param);
329 }
330 Command::CMD_DRAW_COMPLEX_PRIM => {
331 let draw_index = storage::Index::from_u32(param);
332 let data = cmd_iter.next().unwrap();
333 let gpu_address = GpuBufferAddress::from_u32(data.0);
334 let cmd = PrimitiveCommand::complex(
335 draw_index,
336 gpu_address,
337 );
338 f(&cmd, current_spatial_node_index, &[]);
339 }
340 Command::CMD_DRAW_QUAD => {
341 let draw_index = storage::Index::from_u32(param);
342 let pattern = PatternKind::from_u32(cmd_iter.next().unwrap().0);
343 let pattern_input = PatternShaderInput(
344 cmd_iter.next().unwrap().0 as i32,
345 cmd_iter.next().unwrap().0 as i32,
346 );
347 let src_color_task_id = RenderTaskId {
348 index: cmd_iter.next().unwrap().0,
349 sub_rect_index: cmd_iter.next().unwrap().0 as u16
350 };
351 let data = cmd_iter.next().unwrap();
352 let transform_id = GpuTransformId(cmd_iter.next().unwrap().0);
353 let bits = cmd_iter.next().unwrap().0;
354 let quad_flags = QuadFlags::from_bits((bits >> 16) as u8).unwrap();
355 let edge_flags = EdgeMask::from_bits((bits & 0xff) as u8).unwrap();
356 let blend_mode = decode_blend_mode(cmd_iter.next().unwrap().0);
357 let gpu_buffer_address = GpuBufferAddress::from_u32(data.0);
358 let cmd = PrimitiveCommand::quad(
359 pattern,
360 pattern_input,
361 src_color_task_id,
362 draw_index,
363 gpu_buffer_address,
364 transform_id,
365 quad_flags,
366 edge_flags,
367 blend_mode,
368 );
369 f(&cmd, current_spatial_node_index, &segments);
370 segments.clear()
371 }
372 Command::CMD_DRAW_INSTANCE => {
373 let draw_index = storage::Index::from_u32(param);
374 let data = cmd_iter.next().unwrap();
375 let gpu_buffer_address = GpuBufferAddress::from_u32(data.0);
376 let cmd = PrimitiveCommand::instance(
377 draw_index,
378 gpu_buffer_address,
379 );
380 f(&cmd, current_spatial_node_index, &[]);
381 }
382 Command::CMD_SET_SEGMENTS => {
383 let count = param;
384 for _ in 0 .. count {
385 segments.push(
386 RenderTaskId {
387 index: cmd_iter.next().unwrap().0,
388 sub_rect_index: cmd_iter.next().unwrap().0 as u16,
389 }
390 );
391 }
392 }
393 _ => {
394 unreachable!();
395 }
396 }
397 }
398 }
399}
400
401#[cfg_attr(feature = "capture", derive(Serialize))]
404#[cfg_attr(feature = "replay", derive(Deserialize))]
405pub enum CommandBufferBuilderKind {
406 Tiled {
407 tiles: FastHashMap<TileKey, SurfaceTileDescriptor>,
412 },
413 Simple {
414 render_task_id: RenderTaskId,
415 root_task_id: Option<RenderTaskId>,
416 dirty_rect: PictureRect,
417 },
418 Invalid,
419}
420
421#[cfg_attr(feature = "capture", derive(Serialize))]
422#[cfg_attr(feature = "replay", derive(Deserialize))]
423pub struct CommandBufferBuilder {
424 pub kind: CommandBufferBuilderKind,
425
426 pub establishes_sub_graph: bool,
431
432 pub resolve_source: Option<RenderTaskId>,
435
436 pub extra_dependencies: Vec<RenderTaskId>,
438}
439
440impl CommandBufferBuilder {
441 pub fn empty() -> Self {
442 CommandBufferBuilder {
443 kind: CommandBufferBuilderKind::Invalid,
444 establishes_sub_graph: false,
445 resolve_source: None,
446 extra_dependencies: Vec::new(),
447 }
448 }
449
450 pub fn new_tiled(
452 tiles: FastHashMap<TileKey, SurfaceTileDescriptor>,
453 ) -> Self {
454 CommandBufferBuilder {
455 kind: CommandBufferBuilderKind::Tiled {
456 tiles,
457 },
458 establishes_sub_graph: false,
459 resolve_source: None,
460 extra_dependencies: Vec::new(),
461 }
462 }
463
464 pub fn new_simple(
466 render_task_id: RenderTaskId,
467 establishes_sub_graph: bool,
468 root_task_id: Option<RenderTaskId>,
469 dirty_rect: PictureRect,
470 ) -> Self {
471 CommandBufferBuilder {
472 kind: CommandBufferBuilderKind::Simple {
473 render_task_id,
474 root_task_id,
475 dirty_rect,
476 },
477 establishes_sub_graph,
478 resolve_source: None,
479 extra_dependencies: Vec::new(),
480 }
481 }
482}
483
484#[cfg_attr(feature = "capture", derive(Serialize))]
486#[cfg_attr(feature = "replay", derive(Deserialize))]
487#[derive(Debug, Copy, Clone)]
488pub struct CommandBufferIndex(pub u32);
489
490pub struct CommandBufferList {
492 cmd_buffers: Vec<CommandBuffer>,
493}
494
495impl CommandBufferList {
496 pub fn new() -> Self {
497 CommandBufferList {
498 cmd_buffers: Vec::new(),
499 }
500 }
501
502 pub fn create_cmd_buffer(
503 &mut self,
504 ) -> CommandBufferIndex {
505 let index = CommandBufferIndex(self.cmd_buffers.len() as u32);
506 self.cmd_buffers.push(CommandBuffer::new());
507 index
508 }
509
510 pub fn get(&self, index: CommandBufferIndex) -> &CommandBuffer {
511 &self.cmd_buffers[index.0 as usize]
512 }
513
514 pub fn get_mut(&mut self, index: CommandBufferIndex) -> &mut CommandBuffer {
515 &mut self.cmd_buffers[index.0 as usize]
516 }
517}