1use api::{AlphaType, PremultipliedColorF, YuvFormat, YuvRangedColorSpace};
6use api::units::*;
7use euclid::HomogeneousVector;
8use crate::composite::{CompositeFeatures, CompositorClip};
9use crate::pattern::PatternShaderInput;
10use crate::quad::LayoutOrDeviceRect;
11use crate::segment::EdgeMask;
12use crate::transform::GpuTransformId;
13use crate::internal_types::{FrameVec, FrameMemory};
14use crate::prim_store::{ClipData, VECS_PER_SEGMENT};
15use crate::render_task::RenderTaskAddress;
16use crate::render_task_graph::RenderTaskId;
17use crate::renderer::{GpuBufferAddress, GpuBufferBuilderF, GpuBufferHandle, GpuBufferWriterF, GpuBufferDataF, GpuBufferDataI, GpuBufferWriterI, ShaderColorMode};
18use std::i32;
19use crate::util::ScaleOffset;
20use glyph_rasterizer::SubpixelDirection;
21use crate::util::pack_as_float;
22
23
24pub const VECS_PER_TRANSFORM: usize = 8;
27pub const VECS_PER_SPECIFIC_BRUSH: usize = 3;
28
29#[derive(Copy, Clone, PartialEq)]
30#[repr(C)]
31#[cfg_attr(feature = "capture", derive(Serialize))]
32#[cfg_attr(feature = "replay", derive(Deserialize))]
33pub struct ZBufferId(pub i32);
34
35impl ZBufferId {
36 pub fn invalid() -> Self {
37 ZBufferId(i32::MAX)
38 }
39}
40
41impl std::fmt::Debug for ZBufferId {
42 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
43 if *self == Self::invalid() {
44 write!(f, "<invalid>")
45 } else {
46 write!(f, "#{}", self.0)
47 }
48 }
49}
50
51#[derive(Debug)]
52#[cfg_attr(feature = "capture", derive(Serialize))]
53#[cfg_attr(feature = "replay", derive(Deserialize))]
54pub struct ZBufferIdGenerator {
55 next: i32,
56 max_depth_ids: i32,
57}
58
59impl ZBufferIdGenerator {
60 pub fn new(max_depth_ids: i32) -> Self {
61 ZBufferIdGenerator {
62 next: 0,
63 max_depth_ids,
64 }
65 }
66
67 pub fn next(&mut self) -> ZBufferId {
68 debug_assert!(self.next < self.max_depth_ids);
69 let id = ZBufferId(self.next);
70 self.next += 1;
71 id
72 }
73}
74
75#[derive(Clone, Debug)]
76#[repr(C)]
77#[cfg_attr(feature = "capture", derive(Serialize))]
78#[cfg_attr(feature = "replay", derive(Deserialize))]
79pub struct CopyInstance {
80 pub src_rect: DeviceRect,
81 pub dst_rect: DeviceRect,
82 pub dst_texture_size: DeviceSize,
83}
84
85#[derive(Debug, Copy, Clone)]
86#[cfg_attr(feature = "capture", derive(Serialize))]
87#[cfg_attr(feature = "replay", derive(Deserialize))]
88#[repr(C)]
89pub enum RasterizationSpace {
90 Local = 0,
91 Screen = 1,
92}
93
94#[repr(i32)]
95#[derive(Debug, Copy, Clone)]
96#[cfg_attr(feature = "capture", derive(Serialize))]
97#[cfg_attr(feature = "replay", derive(Deserialize))]
98pub enum BlurDirection {
99 Horizontal = 0,
100 Vertical,
101}
102
103impl BlurDirection {
104 pub fn as_int(self) -> i32 {
105 match self {
106 BlurDirection::Horizontal => 0,
107 BlurDirection::Vertical => 1,
108 }
109 }
110}
111
112#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, MallocSizeOf)]
113#[repr(C)]
114#[cfg_attr(feature = "capture", derive(Serialize))]
115#[cfg_attr(feature = "replay", derive(Deserialize))]
116pub enum BlurEdgeMode {
117 Duplicate = 0,
118 Mirror,
119}
120
121impl BlurEdgeMode {
122 pub fn as_int(self) -> i32 {
123 match self {
124 BlurEdgeMode::Duplicate => 0,
125 BlurEdgeMode::Mirror => 1,
126 }
127 }
128}
129
130#[derive(Clone, Debug)]
131#[repr(C)]
132#[cfg_attr(feature = "capture", derive(Serialize))]
133#[cfg_attr(feature = "replay", derive(Deserialize))]
134pub struct BlurInstance {
135 pub task_address: RenderTaskAddress,
136 pub src_task_address: RenderTaskAddress,
137 pub blur_direction: i32,
138 pub edge_mode: i32,
139 pub blur_std_deviation: f32,
140 pub blur_region: DeviceSize,
141}
142
143#[derive(Clone, Debug)]
144#[repr(C)]
145#[cfg_attr(feature = "capture", derive(Serialize))]
146#[cfg_attr(feature = "replay", derive(Deserialize))]
147pub struct ScalingInstance {
148 pub target_rect: DeviceRect,
149 pub source_rect: DeviceRect,
150 source_rect_type: f32,
151}
152
153impl ScalingInstance {
154 pub fn new(target_rect: DeviceRect, source_rect: DeviceRect, source_rect_normalized: bool) -> Self {
155 let source_rect_type = match source_rect_normalized {
156 true => UV_TYPE_NORMALIZED,
157 false => UV_TYPE_UNNORMALIZED,
158 };
159 Self {
160 target_rect,
161 source_rect,
162 source_rect_type: pack_as_float(source_rect_type),
163 }
164 }
165}
166
167#[derive(Clone, Debug)]
168#[repr(C)]
169#[cfg_attr(feature = "capture", derive(Serialize))]
170#[cfg_attr(feature = "replay", derive(Deserialize))]
171pub struct SVGFEFilterInstance {
172 pub target_rect: DeviceRect,
173 pub input_1_content_scale_and_offset: [f32; 4],
174 pub input_2_content_scale_and_offset: [f32; 4],
175 pub input_1_task_address: RenderTaskAddress,
176 pub input_2_task_address: RenderTaskAddress,
177 pub kind: u16,
178 pub input_count: u16,
179 pub extra_data_address: i32,
180}
181
182#[derive(Copy, Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
183#[repr(C)]
184#[cfg_attr(feature = "capture", derive(Serialize))]
185#[cfg_attr(feature = "replay", derive(Deserialize))]
186pub enum BorderSegment {
187 TopLeft,
188 TopRight,
189 BottomRight,
190 BottomLeft,
191 Left,
192 Top,
193 Right,
194 Bottom,
195}
196
197#[derive(Debug, Clone)]
198#[repr(C)]
199#[cfg_attr(feature = "capture", derive(Serialize))]
200#[cfg_attr(feature = "replay", derive(Deserialize))]
201pub struct BorderInstance {
202 pub task_origin: DevicePoint,
203 pub local_rect: DeviceRect,
204 pub color0: PremultipliedColorF,
205 pub color1: PremultipliedColorF,
206 pub flags: i32,
207 pub widths: DeviceSize,
208 pub radius: DeviceSize,
209 pub clip_params: [f32; 8],
210}
211
212#[derive(Copy, Clone, Debug)]
213#[cfg_attr(feature = "capture", derive(Serialize))]
214#[cfg_attr(feature = "replay", derive(Deserialize))]
215#[repr(C)]
216pub struct ClipMaskInstanceCommon {
217 pub sub_rect: DeviceRect,
218 pub task_origin: DevicePoint,
219 pub screen_origin: DevicePoint,
220 pub device_pixel_scale: f32,
221 pub clip_transform_id: GpuTransformId,
222 pub prim_transform_id: GpuTransformId,
223}
224
225#[derive(Clone, Debug)]
226#[cfg_attr(feature = "capture", derive(Serialize))]
227#[cfg_attr(feature = "replay", derive(Deserialize))]
228#[repr(C)]
229pub struct ClipMaskInstanceRect {
230 pub common: ClipMaskInstanceCommon,
231 pub local_pos: LayoutPoint,
232 pub clip_data: ClipData,
233}
234
235#[repr(C)]
237#[derive(Debug, Clone)]
238#[cfg_attr(feature = "capture", derive(Serialize))]
239#[cfg_attr(feature = "replay", derive(Deserialize))]
240pub struct PrimitiveInstanceData {
241 data: [i32; 4],
242}
243
244const UV_TYPE_NORMALIZED: u32 = 0;
247const UV_TYPE_UNNORMALIZED: u32 = 1;
249
250#[derive(Clone, Debug)]
254#[repr(C)]
255pub struct CompositeInstance {
256 rect: DeviceRect,
258 clip_rect: DeviceRect,
260 color: PremultipliedColorF,
262
263 _padding: f32,
265 color_space_or_uv_type: f32, yuv_format: f32, yuv_channel_bit_depth: f32,
269
270 uv_rects: [TexelRect; 3],
272
273 flip: (f32, f32),
275
276 rounded_clip_rect: DeviceRect,
278 rounded_clip_radii: [f32; 4],
279}
280
281impl CompositeInstance {
282 pub fn new(
283 rect: DeviceRect,
284 clip_rect: DeviceRect,
285 color: PremultipliedColorF,
286 flip: (bool, bool),
287 clip: Option<&CompositorClip>,
288 ) -> Self {
289 let uv = TexelRect::new(0.0, 0.0, 1.0, 1.0);
290
291 let (rounded_clip_rect, rounded_clip_radii) = Self::vertex_clip_params(clip, rect);
292
293 CompositeInstance {
294 rect,
295 clip_rect,
296 color,
297 _padding: 0.0,
298 color_space_or_uv_type: pack_as_float(UV_TYPE_NORMALIZED),
299 yuv_format: 0.0,
300 yuv_channel_bit_depth: 0.0,
301 uv_rects: [uv, uv, uv],
302 flip: (flip.0.into(), flip.1.into()),
303 rounded_clip_rect,
304 rounded_clip_radii,
305 }
306 }
307
308 pub fn new_rgb(
309 rect: DeviceRect,
310 clip_rect: DeviceRect,
311 color: PremultipliedColorF,
312 uv_rect: TexelRect,
313 normalized_uvs: bool,
314 flip: (bool, bool),
315 clip: Option<&CompositorClip>,
316 ) -> Self {
317 let (rounded_clip_rect, rounded_clip_radii) = Self::vertex_clip_params(clip, rect);
318
319 let uv_type = match normalized_uvs {
320 true => UV_TYPE_NORMALIZED,
321 false => UV_TYPE_UNNORMALIZED,
322 };
323 CompositeInstance {
324 rect,
325 clip_rect,
326 color,
327 _padding: 0.0,
328 color_space_or_uv_type: pack_as_float(uv_type),
329 yuv_format: 0.0,
330 yuv_channel_bit_depth: 0.0,
331 uv_rects: [uv_rect, uv_rect, uv_rect],
332 flip: (flip.0.into(), flip.1.into()),
333 rounded_clip_rect,
334 rounded_clip_radii,
335 }
336 }
337
338 pub fn new_yuv(
339 rect: DeviceRect,
340 clip_rect: DeviceRect,
341 yuv_color_space: YuvRangedColorSpace,
342 yuv_format: YuvFormat,
343 yuv_channel_bit_depth: u32,
344 uv_rects: [TexelRect; 3],
345 flip: (bool, bool),
346 clip: Option<&CompositorClip>,
347 ) -> Self {
348
349 let (rounded_clip_rect, rounded_clip_radii) = Self::vertex_clip_params(clip, rect);
350
351 CompositeInstance {
352 rect,
353 clip_rect,
354 color: PremultipliedColorF::WHITE,
355 _padding: 0.0,
356 color_space_or_uv_type: pack_as_float(yuv_color_space as u32),
357 yuv_format: pack_as_float(yuv_format as u32),
358 yuv_channel_bit_depth: pack_as_float(yuv_channel_bit_depth),
359 uv_rects,
360 flip: (flip.0.into(), flip.1.into()),
361 rounded_clip_rect,
362 rounded_clip_radii,
363 }
364 }
365
366 pub fn get_rgb_features(&self) -> CompositeFeatures {
369 let mut features = CompositeFeatures::empty();
370
371 if self.color_space_or_uv_type == pack_as_float(UV_TYPE_NORMALIZED)
374 && self.uv_rects[0] == TexelRect::new(0.0, 0.0, 1.0, 1.0)
375 {
376 features |= CompositeFeatures::NO_UV_CLAMP;
377 }
378
379 if self.color == PremultipliedColorF::WHITE {
380 features |= CompositeFeatures::NO_COLOR_MODULATION
381 }
382
383 if self.rounded_clip_radii.iter().all(|r| *r <= 0.0) {
385 features |= CompositeFeatures::NO_CLIP_MASK
386 }
387
388 features
389 }
390
391 pub fn get_yuv_features(&self) -> CompositeFeatures {
394 let mut features = CompositeFeatures::empty();
395
396 if self.rounded_clip_radii.iter().all(|r| *r <= 0.0) {
398 features |= CompositeFeatures::NO_CLIP_MASK
399 }
400
401 features
402 }
403
404 fn vertex_clip_params(
405 clip: Option<&CompositorClip>,
406 default_rect: DeviceRect,
407 ) -> (DeviceRect, [f32; 4]) {
408 match clip {
409 Some(clip) => {
410 (
411 clip.rect.cast_unit(),
412 [
413 clip.radius.top_left.width,
414 clip.radius.bottom_left.width,
415 clip.radius.top_right.width,
416 clip.radius.bottom_right.width,
417 ],
418 )
419 }
420 None => {
421 (default_rect, [0.0; 4])
422 }
423 }
424 }
425}
426
427#[derive(Debug, Clone)]
429#[repr(C)]
430pub struct ClearInstance {
431 pub rect: [f32; 4],
432 pub color: [f32; 4],
433}
434
435#[derive(Debug, Copy, Clone)]
436#[cfg_attr(feature = "capture", derive(Serialize))]
437#[cfg_attr(feature = "replay", derive(Deserialize))]
438pub struct PrimitiveHeaderIndex(pub i32);
439
440#[derive(Debug)]
441#[repr(C)]
442#[cfg_attr(feature = "capture", derive(Serialize))]
443#[cfg_attr(feature = "replay", derive(Deserialize))]
444pub struct PrimitiveHeaders {
445 pub headers_int: FrameVec<PrimitiveHeaderI>,
447 pub headers_float: FrameVec<PrimitiveHeaderF>,
449}
450
451impl PrimitiveHeaders {
452 pub fn new(memory: &FrameMemory) -> PrimitiveHeaders {
453 PrimitiveHeaders {
454 headers_int: memory.new_vec(),
455 headers_float: memory.new_vec(),
456 }
457 }
458
459 pub fn push(
461 &mut self,
462 prim_header: &PrimitiveHeader,
463 ) -> PrimitiveHeaderIndex {
464 debug_assert_eq!(self.headers_int.len(), self.headers_float.len());
465 let id = self.headers_float.len();
466
467 self.headers_float.push(PrimitiveHeaderF {
468 local_rect: prim_header.local_rect,
469 local_clip_rect: prim_header.local_clip_rect,
470 });
471
472 self.headers_int.push(PrimitiveHeaderI {
473 z: prim_header.z,
474 render_task_address: prim_header.render_task_address,
475 specific_prim_address: prim_header.specific_prim_address,
476 transform_id: prim_header.transform_id,
477 user_data: prim_header.user_data,
478 });
479
480 PrimitiveHeaderIndex(id as i32)
481 }
482}
483
484#[derive(Debug)]
487pub struct PrimitiveHeader {
488 pub local_rect: LayoutRect,
489 pub local_clip_rect: LayoutRect,
490 pub specific_prim_address: i32,
491 pub transform_id: GpuTransformId,
492 pub z: ZBufferId,
493 pub render_task_address: RenderTaskAddress,
494 pub user_data: [i32; 4],
495}
496
497#[derive(Debug)]
499#[repr(C)]
500#[cfg_attr(feature = "capture", derive(Serialize))]
501#[cfg_attr(feature = "replay", derive(Deserialize))]
502pub struct PrimitiveHeaderF {
503 pub local_rect: LayoutRect,
504 pub local_clip_rect: LayoutRect,
505}
506
507#[derive(Debug)]
510#[repr(C)]
511#[cfg_attr(feature = "capture", derive(Serialize))]
512#[cfg_attr(feature = "replay", derive(Deserialize))]
513pub struct PrimitiveHeaderI {
514 pub z: ZBufferId,
515 pub specific_prim_address: i32,
516 pub transform_id: GpuTransformId,
517 pub render_task_address: RenderTaskAddress,
518 pub user_data: [i32; 4],
519}
520
521pub struct GlyphInstance {
522 pub prim_header_index: PrimitiveHeaderIndex,
523}
524
525impl GlyphInstance {
526 pub fn new(
527 prim_header_index: PrimitiveHeaderIndex,
528 ) -> Self {
529 GlyphInstance {
530 prim_header_index,
531 }
532 }
533
534 pub fn build(&self,
538 clip_task: RenderTaskAddress,
539 subpx_dir: SubpixelDirection,
540 glyph_index_in_text_run: i32,
541 glyph_uv_rect: GpuBufferAddress,
542 color_mode: ShaderColorMode,
543 subpx_offset_x: u8,
544 subpx_offset_y: u8,
545 is_packed_glyph: bool,
546 ) -> PrimitiveInstanceData {
547 let packed_flags = (((is_packed_glyph as u32) & 0x1) << 26)
552 | (((subpx_dir as u32) & 0x3) << 24)
553 | (((subpx_offset_y as u32) & 0x3) << 22)
554 | (((subpx_offset_x as u32) & 0x3) << 20)
555 | (((color_mode as u32) & 0xF) << 16);
556
557 PrimitiveInstanceData {
558 data: [
559 self.prim_header_index.0 as i32,
560 clip_task.0 as i32,
561 packed_flags as i32 | glyph_index_in_text_run,
562 glyph_uv_rect.as_int(),
563 ],
564 }
565 }
566}
567
568pub struct SplitCompositeInstance {
569 pub prim_header_index: PrimitiveHeaderIndex,
570 pub polygons_address: i32,
571 pub z: ZBufferId,
572 pub render_task_address: RenderTaskAddress,
573}
574
575impl From<SplitCompositeInstance> for PrimitiveInstanceData {
576 fn from(instance: SplitCompositeInstance) -> Self {
577 PrimitiveInstanceData {
578 data: [
579 instance.prim_header_index.0,
580 instance.polygons_address,
581 instance.z.0,
582 instance.render_task_address.0,
583 ],
584 }
585 }
586}
587
588#[derive(Copy, Clone)]
589#[cfg_attr(feature = "capture", derive(Serialize))]
590#[cfg_attr(feature = "replay", derive(Deserialize))]
591pub struct QuadInstance {
592 pub dst_task_address: RenderTaskAddress,
593 pub prim_address_i: i32,
594 pub prim_address_f: i32,
595 pub quad_flags: u8,
596 pub edge_flags: u8,
597 pub part_index: u8,
598 pub segment_index: u8,
599}
600
601impl From<QuadInstance> for PrimitiveInstanceData {
602 fn from(instance: QuadInstance) -> Self {
603 PrimitiveInstanceData {
611 data: [
612 instance.prim_address_i,
613 instance.prim_address_f,
614
615 ((instance.quad_flags as i32) << 24) |
616 ((instance.edge_flags as i32) << 16) |
617 ((instance.part_index as i32) << 8) |
618 ((instance.segment_index as i32) << 0),
619
620 instance.dst_task_address.0,
621 ],
622 }
623 }
624}
625
626pub struct QuadHeader {
628 pub transform_id: GpuTransformId,
629 pub z_id: ZBufferId,
630 pub pattern_input: PatternShaderInput,
631}
632
633impl GpuBufferDataI for QuadHeader {
634 const NUM_BLOCKS: usize = 1;
635 fn write(&self, writer: &mut GpuBufferWriterI) {
636 writer.push_one([
637 self.transform_id.0 as i32,
638 self.z_id.0,
639 self.pattern_input.0,
640 self.pattern_input.1,
641 ]);
642 }
643}
644
645pub struct QuadPrimitive {
647 pub bounds: LayoutOrDeviceRect,
648 pub clip: LayoutOrDeviceRect,
649 pub input_task: RenderTaskId,
652 pub pattern_scale_offset: ScaleOffset,
653 pub color: PremultipliedColorF,
655}
656
657impl GpuBufferDataF for QuadPrimitive {
658 const NUM_BLOCKS: usize = 5;
659 fn write(&self, writer: &mut GpuBufferWriterF) {
660 writer.push_one(self.bounds);
661 writer.push_one(self.clip);
662 writer.push_render_task(self.input_task);
663 writer.push_one(self.pattern_scale_offset);
664 writer.push_one(self.color);
665 }
666}
667
668pub const VECS_PER_QUAD_SEGMENT: usize = 2;
669
670#[derive(Debug)]
672#[cfg_attr(feature = "capture", derive(Serialize))]
673pub struct QuadSegment {
674 pub rect: LayoutOrDeviceRect,
675 pub task_id: RenderTaskId,
678}
679
680impl GpuBufferDataF for QuadSegment {
681 const NUM_BLOCKS: usize = VECS_PER_QUAD_SEGMENT;
682 fn write(&self, writer: &mut GpuBufferWriterF) {
683 writer.push_one(self.rect);
684 writer.push_render_task(self.task_id)
685 }
686}
687
688
689#[derive(Copy, Debug, Clone, PartialEq)]
694#[cfg_attr(feature = "capture", derive(Serialize))]
695#[cfg_attr(feature = "replay", derive(Deserialize))]
696#[repr(u32)]
697pub enum ClipSpace {
698 Device = 0,
699 Primitive = 1,
700}
701
702impl ClipSpace {
703 pub fn as_int(self) -> u32 {
704 match self {
705 ClipSpace::Device => 0,
706 ClipSpace::Primitive => 1,
707 }
708 }
709}
710
711#[repr(C)]
712#[derive(Clone)]
713#[cfg_attr(feature = "capture", derive(Serialize))]
714#[cfg_attr(feature = "replay", derive(Deserialize))]
715pub struct MaskInstance {
716 pub prim: PrimitiveInstanceData,
717 pub clip_transform_id: GpuTransformId,
718 pub clip_address: i32,
719 pub clip_space: u32,
720 pub unused: i32,
721}
722
723
724#[cfg_attr(feature = "capture", derive(Serialize))]
730#[cfg_attr(feature = "replay", derive(Deserialize))]
731#[derive(Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash, MallocSizeOf)]
732pub struct BrushFlags(u16);
733
734bitflags! {
735 impl BrushFlags: u16 {
736 const PERSPECTIVE_INTERPOLATION = 1;
738 const SEGMENT_RELATIVE = 2;
741 const SEGMENT_REPEAT_X = 4;
743 const SEGMENT_REPEAT_Y = 8;
745 const SEGMENT_REPEAT_X_ROUND = 16;
747 const SEGMENT_REPEAT_Y_ROUND = 32;
749 const SEGMENT_REPEAT_X_CENTERED = 64;
752 const SEGMENT_REPEAT_Y_CENTERED = 128;
755 const SEGMENT_NINEPATCH_MIDDLE = 256;
757 const SEGMENT_TEXEL_RECT = 512;
759 const FORCE_AA = 1024;
762 const NORMALIZED_UVS = 2048;
764 }
765}
766
767impl core::fmt::Debug for BrushFlags {
768 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
769 if self.is_empty() {
770 write!(f, "{:#x}", Self::empty().bits())
771 } else {
772 bitflags::parser::to_writer(self, f)
773 }
774 }
775}
776
777pub struct BrushInstance {
779 pub prim_header_index: PrimitiveHeaderIndex,
780 pub clip_task_address: RenderTaskAddress,
781 pub segment_index: i32,
782 pub edge_flags: EdgeMask,
783 pub brush_flags: BrushFlags,
784 pub resource_address: i32,
785}
786
787impl From<BrushInstance> for PrimitiveInstanceData {
788 fn from(instance: BrushInstance) -> Self {
789 PrimitiveInstanceData {
790 data: [
791 instance.prim_header_index.0,
792 instance.clip_task_address.0,
793 instance.segment_index
794 | ((instance.brush_flags.bits() as i32) << 16)
795 | ((instance.edge_flags.bits() as i32) << 28),
796 instance.resource_address,
797 ]
798 }
799 }
800}
801
802#[derive(Copy, Clone, Debug)]
804pub struct ImageBrushUserData {
805 pub color_mode: ShaderColorMode,
806 pub alpha_type: AlphaType,
807 pub raster_space: RasterizationSpace,
808 pub opacity: f32,
809}
810
811impl ImageBrushUserData {
812 #[inline]
813 pub fn encode(&self) -> [i32; 4] {
814 [
815 self.color_mode as i32 | ((self.alpha_type as i32) << 16),
816 self.raster_space as i32,
817 get_shader_opacity(self.opacity),
818 0,
819 ]
820 }
821}
822
823#[derive(Debug, Copy, Clone)]
828#[cfg_attr(feature = "capture", derive(Serialize))]
829#[cfg_attr(feature = "replay", derive(Deserialize))]
830pub enum UvRectKind {
831 Rect,
834 Quad {
839 top_left: DeviceHomogeneousVector,
840 top_right: DeviceHomogeneousVector,
841 bottom_left: DeviceHomogeneousVector,
842 bottom_right: DeviceHomogeneousVector,
843 },
844}
845
846#[derive(Debug, Copy, Clone)]
847#[cfg_attr(feature = "capture", derive(Serialize))]
848#[cfg_attr(feature = "replay", derive(Deserialize))]
849pub struct ImageSource {
850 pub p0: DevicePoint,
851 pub p1: DevicePoint,
852 pub user_data: [f32; 4],
857 pub uv_rect_kind: UvRectKind,
858}
859
860impl ImageSource {
861 pub fn write_gpu_blocks(&self, gpu_buffer: &mut GpuBufferBuilderF) -> GpuBufferHandle {
862 let mut writer = gpu_buffer.write_blocks(6);
863 self.push_gpu_blocks(&mut writer);
864 writer.finish_with_handle()
865 }
866
867 pub fn push_gpu_blocks(&self, writer: &mut GpuBufferWriterF) {
868 writer.push_one([
871 self.p0.x,
872 self.p0.y,
873 self.p1.x,
874 self.p1.y,
875 ]);
876 writer.push_one(self.user_data);
877
878 if let UvRectKind::Quad { top_left, top_right, bottom_left, bottom_right } = self.uv_rect_kind {
880 fn to_array(v: HomogeneousVector<f32, DevicePixel>) -> [f32; 4] {
883 [v.x, v.y, v.z, v.w]
884 }
885 writer.push_one(to_array(top_left));
886 writer.push_one(to_array(top_right));
887 writer.push_one(to_array(bottom_left));
888 writer.push_one(to_array(bottom_right));
889 }
890 }
891}
892
893#[derive(Copy, Clone, Debug)]
897pub struct ImageBrushPrimitiveData {
898 pub color: PremultipliedColorF,
899 pub background_color: PremultipliedColorF,
900 pub stretch_size: LayoutSize,
901}
902
903impl GpuBufferDataF for ImageBrushPrimitiveData {
904 const NUM_BLOCKS: usize = VECS_PER_SPECIFIC_BRUSH;
905 fn write(&self, writer: &mut GpuBufferWriterF) {
906 writer.push_one(self.color);
907 writer.push_one(self.background_color);
908 writer.push_one([self.stretch_size.width, self.stretch_size.height, 0.0, 0.0]);
909 }
910}
911
912#[cfg_attr(feature = "capture", derive(Serialize))]
913#[cfg_attr(feature = "replay", derive(Deserialize))]
914#[derive(Debug, Clone, MallocSizeOf)]
915pub struct BrushSegmentGpuData {
916 pub local_rect: LayoutRect,
917 pub extra_data: [f32; 4],
919}
920
921impl GpuBufferDataF for BrushSegmentGpuData {
922 const NUM_BLOCKS: usize = VECS_PER_SEGMENT;
923 fn write(&self, writer: &mut GpuBufferWriterF) {
924 writer.push_one(self.local_rect);
925 writer.push_one(self.extra_data);
926 }
927}
928
929pub struct YuvPrimitive {
931 pub channel_bit_depth: u32,
932 pub color_space: YuvRangedColorSpace,
933 pub yuv_format: YuvFormat,
934}
935
936impl GpuBufferDataF for YuvPrimitive {
937 const NUM_BLOCKS: usize = 1;
938 fn write(&self, writer: &mut GpuBufferWriterF) {
939 writer.push_one([
940 pack_as_float(self.channel_bit_depth),
941 pack_as_float(self.color_space as u32),
942 pack_as_float(self.yuv_format as u32),
943 0.0
944 ]);
945 }
946}
947
948pub fn get_shader_opacity(opacity: f32) -> i32 {
949 (opacity * 65535.0).round() as i32
950}