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 
5 use api::{AlphaType, PremultipliedColorF, YuvFormat, YuvRangedColorSpace};
6 use api::units::*;
7 use crate::composite::CompositeFeatures;
8 use crate::segment::EdgeAaSegmentMask;
9 use crate::spatial_tree::{SpatialTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex};
10 use crate::gpu_cache::{GpuCacheAddress, GpuDataRequest};
11 use crate::internal_types::FastHashMap;
12 use crate::prim_store::ClipData;
13 use crate::render_task::RenderTaskAddress;
14 use crate::renderer::ShaderColorMode;
15 use std::i32;
16 use crate::util::{TransformedRectKind, MatrixHelpers};
17 use crate::glyph_rasterizer::SubpixelDirection;
18 use crate::util::{ScaleOffset, pack_as_float};
19 
20 // Contains type that must exactly match the same structures declared in GLSL.
21 
22 pub const VECS_PER_TRANSFORM: usize = 8;
23 
24 #[derive(Copy, Clone, Debug, PartialEq)]
25 #[repr(C)]
26 #[cfg_attr(feature = "capture", derive(Serialize))]
27 #[cfg_attr(feature = "replay", derive(Deserialize))]
28 pub struct ZBufferId(pub i32);
29 
30 impl ZBufferId {
invalid() -> Self31     pub fn invalid() -> Self {
32         ZBufferId(i32::MAX)
33     }
34 }
35 
36 #[derive(Debug)]
37 #[cfg_attr(feature = "capture", derive(Serialize))]
38 #[cfg_attr(feature = "replay", derive(Deserialize))]
39 pub struct ZBufferIdGenerator {
40     next: i32,
41     max_depth_ids: i32,
42 }
43 
44 impl ZBufferIdGenerator {
new(max_depth_ids: i32) -> Self45     pub fn new(max_depth_ids: i32) -> Self {
46         ZBufferIdGenerator {
47             next: 0,
48             max_depth_ids,
49         }
50     }
51 
next(&mut self) -> ZBufferId52     pub fn next(&mut self) -> ZBufferId {
53         debug_assert!(self.next < self.max_depth_ids);
54         let id = ZBufferId(self.next);
55         self.next += 1;
56         id
57     }
58 }
59 
60 #[derive(Debug, Copy, Clone)]
61 #[cfg_attr(feature = "capture", derive(Serialize))]
62 #[cfg_attr(feature = "replay", derive(Deserialize))]
63 #[repr(C)]
64 pub enum RasterizationSpace {
65     Local = 0,
66     Screen = 1,
67 }
68 
69 #[derive(Debug, Copy, Clone, MallocSizeOf)]
70 #[cfg_attr(feature = "capture", derive(Serialize))]
71 #[cfg_attr(feature = "replay", derive(Deserialize))]
72 #[repr(C)]
73 pub enum BoxShadowStretchMode {
74     Stretch = 0,
75     Simple = 1,
76 }
77 
78 #[repr(i32)]
79 #[derive(Debug, Copy, Clone)]
80 #[cfg_attr(feature = "capture", derive(Serialize))]
81 #[cfg_attr(feature = "replay", derive(Deserialize))]
82 pub enum BlurDirection {
83     Horizontal = 0,
84     Vertical,
85 }
86 
87 #[derive(Clone, Debug)]
88 #[repr(C)]
89 #[cfg_attr(feature = "capture", derive(Serialize))]
90 #[cfg_attr(feature = "replay", derive(Deserialize))]
91 pub struct BlurInstance {
92     pub task_address: RenderTaskAddress,
93     pub src_task_address: RenderTaskAddress,
94     pub blur_direction: BlurDirection,
95 }
96 
97 #[derive(Clone, Debug)]
98 #[repr(C)]
99 #[cfg_attr(feature = "capture", derive(Serialize))]
100 #[cfg_attr(feature = "replay", derive(Deserialize))]
101 pub struct ScalingInstance {
102     pub target_rect: DeviceRect,
103     pub source_rect: DeviceRect,
104 }
105 
106 #[derive(Clone, Debug)]
107 #[repr(C)]
108 #[cfg_attr(feature = "capture", derive(Serialize))]
109 #[cfg_attr(feature = "replay", derive(Deserialize))]
110 pub struct SvgFilterInstance {
111     pub task_address: RenderTaskAddress,
112     pub input_1_task_address: RenderTaskAddress,
113     pub input_2_task_address: RenderTaskAddress,
114     pub kind: u16,
115     pub input_count: u16,
116     pub generic_int: u16,
117     pub extra_data_address: GpuCacheAddress,
118 }
119 
120 #[derive(Copy, Clone, Debug, Hash, MallocSizeOf, PartialEq, Eq)]
121 #[repr(C)]
122 #[cfg_attr(feature = "capture", derive(Serialize))]
123 #[cfg_attr(feature = "replay", derive(Deserialize))]
124 pub enum BorderSegment {
125     TopLeft,
126     TopRight,
127     BottomRight,
128     BottomLeft,
129     Left,
130     Top,
131     Right,
132     Bottom,
133 }
134 
135 #[derive(Debug, Clone)]
136 #[repr(C)]
137 #[cfg_attr(feature = "capture", derive(Serialize))]
138 #[cfg_attr(feature = "replay", derive(Deserialize))]
139 pub struct BorderInstance {
140     pub task_origin: DevicePoint,
141     pub local_rect: DeviceRect,
142     pub color0: PremultipliedColorF,
143     pub color1: PremultipliedColorF,
144     pub flags: i32,
145     pub widths: DeviceSize,
146     pub radius: DeviceSize,
147     pub clip_params: [f32; 8],
148 }
149 
150 #[derive(Copy, Clone, Debug)]
151 #[cfg_attr(feature = "capture", derive(Serialize))]
152 #[cfg_attr(feature = "replay", derive(Deserialize))]
153 #[repr(C)]
154 pub struct ClipMaskInstanceCommon {
155     pub sub_rect: DeviceRect,
156     pub task_origin: DevicePoint,
157     pub screen_origin: DevicePoint,
158     pub device_pixel_scale: f32,
159     pub clip_transform_id: TransformPaletteId,
160     pub prim_transform_id: TransformPaletteId,
161 }
162 
163 #[derive(Clone, Debug)]
164 #[cfg_attr(feature = "capture", derive(Serialize))]
165 #[cfg_attr(feature = "replay", derive(Deserialize))]
166 #[repr(C)]
167 pub struct ClipMaskInstanceImage {
168     pub common: ClipMaskInstanceCommon,
169     pub tile_rect: LayoutRect,
170     pub resource_address: GpuCacheAddress,
171     pub local_rect: LayoutRect,
172 }
173 
174 #[derive(Clone, Debug)]
175 #[cfg_attr(feature = "capture", derive(Serialize))]
176 #[cfg_attr(feature = "replay", derive(Deserialize))]
177 #[repr(C)]
178 pub struct ClipMaskInstanceRect {
179     pub common: ClipMaskInstanceCommon,
180     pub local_pos: LayoutPoint,
181     pub clip_data: ClipData,
182 }
183 
184 #[derive(Clone, Debug)]
185 #[cfg_attr(feature = "capture", derive(Serialize))]
186 #[cfg_attr(feature = "replay", derive(Deserialize))]
187 #[repr(C)]
188 pub struct BoxShadowData {
189     pub src_rect_size: LayoutSize,
190     pub clip_mode: i32,
191     pub stretch_mode_x: i32,
192     pub stretch_mode_y: i32,
193     pub dest_rect: LayoutRect,
194 }
195 
196 #[derive(Clone, Debug)]
197 #[cfg_attr(feature = "capture", derive(Serialize))]
198 #[cfg_attr(feature = "replay", derive(Deserialize))]
199 #[repr(C)]
200 pub struct ClipMaskInstanceBoxShadow {
201     pub common: ClipMaskInstanceCommon,
202     pub resource_address: GpuCacheAddress,
203     pub shadow_data: BoxShadowData,
204 }
205 
206 /// A clipping primitive drawn into the clipping mask.
207 /// Could be an image or a rectangle, which defines the
208 /// way `address` is treated.
209 #[derive(Debug, Copy, Clone)]
210 #[cfg_attr(feature = "capture", derive(Serialize))]
211 #[cfg_attr(feature = "replay", derive(Deserialize))]
212 #[repr(C)]
213 pub struct ClipMaskInstance {
214     pub clip_transform_id: TransformPaletteId,
215     pub prim_transform_id: TransformPaletteId,
216     pub clip_data_address: GpuCacheAddress,
217     pub resource_address: GpuCacheAddress,
218     pub local_pos: LayoutPoint,
219     pub tile_rect: LayoutRect,
220     pub sub_rect: DeviceRect,
221     pub task_origin: DevicePoint,
222     pub screen_origin: DevicePoint,
223     pub device_pixel_scale: f32,
224 }
225 
226 // 16 bytes per instance should be enough for anyone!
227 #[derive(Debug, Clone)]
228 #[cfg_attr(feature = "capture", derive(Serialize))]
229 #[cfg_attr(feature = "replay", derive(Deserialize))]
230 pub struct PrimitiveInstanceData {
231     data: [i32; 4],
232 }
233 
234 /// Specifies that an RGB CompositeInstance's UV coordinates are normalized.
235 const UV_TYPE_NORMALIZED: u32 = 0;
236 /// Specifies that an RGB CompositeInstance's UV coordinates are not normalized.
237 const UV_TYPE_UNNORMALIZED: u32 = 1;
238 
239 /// A GPU-friendly representation of the `ScaleOffset` type
240 #[derive(Clone, Debug)]
241 #[repr(C)]
242 pub struct CompositorTransform {
243     pub sx: f32,
244     pub sy: f32,
245     pub tx: f32,
246     pub ty: f32,
247 }
248 
249 impl CompositorTransform {
identity() -> Self250     pub fn identity() -> Self {
251         CompositorTransform {
252             sx: 1.0,
253             sy: 1.0,
254             tx: 0.0,
255             ty: 0.0,
256         }
257     }
258 }
259 
260 impl From<ScaleOffset> for CompositorTransform {
from(scale_offset: ScaleOffset) -> Self261     fn from(scale_offset: ScaleOffset) -> Self {
262         CompositorTransform {
263             sx: scale_offset.scale.x,
264             sy: scale_offset.scale.y,
265             tx: scale_offset.offset.x,
266             ty: scale_offset.offset.y,
267         }
268     }
269 }
270 
271 /// Vertex format for picture cache composite shader.
272 /// When editing the members, update desc::COMPOSITE
273 /// so its list of instance_attributes matches:
274 #[derive(Clone, Debug)]
275 #[repr(C)]
276 pub struct CompositeInstance {
277     // Picture space destination rectangle of surface
278     rect: PictureRect,
279     // Device space destination clip rect for this surface
280     clip_rect: DeviceRect,
281     // Color for solid color tiles, white otherwise
282     color: PremultipliedColorF,
283 
284     // Packed into a single vec4 (aParams)
285     z_id: f32,
286     color_space_or_uv_type: f32, // YuvColorSpace for YUV;
287                                  // UV coordinate space for RGB
288     yuv_format: f32,            // YuvFormat
289     yuv_channel_bit_depth: f32,
290 
291     // UV rectangles (pixel space) for color / yuv texture planes
292     uv_rects: [TexelRect; 3],
293 
294     // A 2d scale + offset transform for the rect
295     transform: CompositorTransform,
296 }
297 
298 impl CompositeInstance {
new( rect: PictureRect, clip_rect: DeviceRect, color: PremultipliedColorF, z_id: ZBufferId, transform: CompositorTransform, ) -> Self299     pub fn new(
300         rect: PictureRect,
301         clip_rect: DeviceRect,
302         color: PremultipliedColorF,
303         z_id: ZBufferId,
304         transform: CompositorTransform,
305     ) -> Self {
306         let uv = TexelRect::new(0.0, 0.0, 1.0, 1.0);
307         CompositeInstance {
308             rect,
309             clip_rect,
310             color,
311             z_id: z_id.0 as f32,
312             color_space_or_uv_type: pack_as_float(UV_TYPE_NORMALIZED),
313             yuv_format: 0.0,
314             yuv_channel_bit_depth: 0.0,
315             uv_rects: [uv, uv, uv],
316             transform,
317         }
318     }
319 
new_rgb( rect: PictureRect, clip_rect: DeviceRect, color: PremultipliedColorF, z_id: ZBufferId, uv_rect: TexelRect, transform: CompositorTransform, ) -> Self320     pub fn new_rgb(
321         rect: PictureRect,
322         clip_rect: DeviceRect,
323         color: PremultipliedColorF,
324         z_id: ZBufferId,
325         uv_rect: TexelRect,
326         transform: CompositorTransform,
327     ) -> Self {
328         CompositeInstance {
329             rect,
330             clip_rect,
331             color,
332             z_id: z_id.0 as f32,
333             color_space_or_uv_type: pack_as_float(UV_TYPE_UNNORMALIZED),
334             yuv_format: 0.0,
335             yuv_channel_bit_depth: 0.0,
336             uv_rects: [uv_rect, uv_rect, uv_rect],
337             transform,
338         }
339     }
340 
new_yuv( rect: PictureRect, clip_rect: DeviceRect, z_id: ZBufferId, yuv_color_space: YuvRangedColorSpace, yuv_format: YuvFormat, yuv_channel_bit_depth: u32, uv_rects: [TexelRect; 3], transform: CompositorTransform, ) -> Self341     pub fn new_yuv(
342         rect: PictureRect,
343         clip_rect: DeviceRect,
344         z_id: ZBufferId,
345         yuv_color_space: YuvRangedColorSpace,
346         yuv_format: YuvFormat,
347         yuv_channel_bit_depth: u32,
348         uv_rects: [TexelRect; 3],
349         transform: CompositorTransform,
350     ) -> Self {
351         CompositeInstance {
352             rect,
353             clip_rect,
354             color: PremultipliedColorF::WHITE,
355             z_id: z_id.0 as f32,
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             transform,
361         }
362     }
363 
364     // Returns the CompositeFeatures that can be used to composite
365     // this RGB instance.
get_rgb_features(&self) -> CompositeFeatures366     pub fn get_rgb_features(&self) -> CompositeFeatures {
367         let mut features = CompositeFeatures::empty();
368 
369         // If the UV rect covers the entire texture then we can avoid UV clamping.
370         // We should try harder to determine this for unnormalized UVs too.
371         if self.color_space_or_uv_type == pack_as_float(UV_TYPE_NORMALIZED)
372             && self.uv_rects[0] == TexelRect::new(0.0, 0.0, 1.0, 1.0)
373         {
374             features |= CompositeFeatures::NO_UV_CLAMP;
375         }
376 
377         if self.color == PremultipliedColorF::WHITE {
378             features |= CompositeFeatures::NO_COLOR_MODULATION
379         }
380 
381         features
382     }
383 }
384 
385 /// Vertex format for issuing colored quads.
386 #[derive(Debug, Clone)]
387 #[repr(C)]
388 pub struct ClearInstance {
389     pub rect: [f32; 4],
390     pub color: [f32; 4],
391 }
392 
393 #[derive(Debug, Copy, Clone)]
394 #[cfg_attr(feature = "capture", derive(Serialize))]
395 #[cfg_attr(feature = "replay", derive(Deserialize))]
396 pub struct PrimitiveHeaderIndex(pub i32);
397 
398 #[derive(Debug)]
399 #[repr(C)]
400 #[cfg_attr(feature = "capture", derive(Serialize))]
401 #[cfg_attr(feature = "replay", derive(Deserialize))]
402 pub struct PrimitiveHeaders {
403     // The integer-type headers for a primitive.
404     pub headers_int: Vec<PrimitiveHeaderI>,
405     // The float-type headers for a primitive.
406     pub headers_float: Vec<PrimitiveHeaderF>,
407 }
408 
409 impl PrimitiveHeaders {
new() -> PrimitiveHeaders410     pub fn new() -> PrimitiveHeaders {
411         PrimitiveHeaders {
412             headers_int: Vec::new(),
413             headers_float: Vec::new(),
414         }
415     }
416 
417     // Add a new primitive header.
push( &mut self, prim_header: &PrimitiveHeader, z: ZBufferId, user_data: [i32; 4], ) -> PrimitiveHeaderIndex418     pub fn push(
419         &mut self,
420         prim_header: &PrimitiveHeader,
421         z: ZBufferId,
422         user_data: [i32; 4],
423     ) -> PrimitiveHeaderIndex {
424         debug_assert_eq!(self.headers_int.len(), self.headers_float.len());
425         let id = self.headers_float.len();
426 
427         self.headers_float.push(PrimitiveHeaderF {
428             local_rect: prim_header.local_rect,
429             local_clip_rect: prim_header.local_clip_rect,
430         });
431 
432         self.headers_int.push(PrimitiveHeaderI {
433             z,
434             unused: 0,
435             specific_prim_address: prim_header.specific_prim_address.as_int(),
436             transform_id: prim_header.transform_id,
437             user_data,
438         });
439 
440         PrimitiveHeaderIndex(id as i32)
441     }
442 }
443 
444 // This is a convenience type used to make it easier to pass
445 // the common parts around during batching.
446 #[derive(Debug)]
447 pub struct PrimitiveHeader {
448     pub local_rect: LayoutRect,
449     pub local_clip_rect: LayoutRect,
450     pub specific_prim_address: GpuCacheAddress,
451     pub transform_id: TransformPaletteId,
452 }
453 
454 // f32 parts of a primitive header
455 #[derive(Debug)]
456 #[repr(C)]
457 #[cfg_attr(feature = "capture", derive(Serialize))]
458 #[cfg_attr(feature = "replay", derive(Deserialize))]
459 pub struct PrimitiveHeaderF {
460     pub local_rect: LayoutRect,
461     pub local_clip_rect: LayoutRect,
462 }
463 
464 // i32 parts of a primitive header
465 // TODO(gw): Compress parts of these down to u16
466 #[derive(Debug)]
467 #[repr(C)]
468 #[cfg_attr(feature = "capture", derive(Serialize))]
469 #[cfg_attr(feature = "replay", derive(Deserialize))]
470 pub struct PrimitiveHeaderI {
471     pub z: ZBufferId,
472     pub specific_prim_address: i32,
473     pub transform_id: TransformPaletteId,
474     pub unused: i32,                    // To ensure required 16 byte alignment of vertex textures
475     pub user_data: [i32; 4],
476 }
477 
478 pub struct GlyphInstance {
479     pub prim_header_index: PrimitiveHeaderIndex,
480 }
481 
482 impl GlyphInstance {
new( prim_header_index: PrimitiveHeaderIndex, ) -> Self483     pub fn new(
484         prim_header_index: PrimitiveHeaderIndex,
485     ) -> Self {
486         GlyphInstance {
487             prim_header_index,
488         }
489     }
490 
491     // TODO(gw): Some of these fields can be moved to the primitive
492     //           header since they are constant, and some can be
493     //           compressed to a smaller size.
build(&self, render_task: RenderTaskAddress, clip_task: RenderTaskAddress, subpx_dir: SubpixelDirection, glyph_index_in_text_run: i32, glyph_uv_rect: GpuCacheAddress, color_mode: ShaderColorMode, ) -> PrimitiveInstanceData494     pub fn build(&self,
495         render_task: RenderTaskAddress,
496         clip_task: RenderTaskAddress,
497         subpx_dir: SubpixelDirection,
498         glyph_index_in_text_run: i32,
499         glyph_uv_rect: GpuCacheAddress,
500         color_mode: ShaderColorMode,
501     ) -> PrimitiveInstanceData {
502         PrimitiveInstanceData {
503             data: [
504                 self.prim_header_index.0 as i32,
505                 ((render_task.0 as i32) << 16)
506                 | clip_task.0 as i32,
507                 (subpx_dir as u32 as i32) << 24
508                 | (color_mode as u32 as i32) << 16
509                 | glyph_index_in_text_run,
510                 glyph_uv_rect.as_int(),
511             ],
512         }
513     }
514 }
515 
516 pub struct SplitCompositeInstance {
517     pub prim_header_index: PrimitiveHeaderIndex,
518     pub polygons_address: GpuCacheAddress,
519     pub z: ZBufferId,
520     pub render_task_address: RenderTaskAddress,
521 }
522 
523 impl From<SplitCompositeInstance> for PrimitiveInstanceData {
from(instance: SplitCompositeInstance) -> Self524     fn from(instance: SplitCompositeInstance) -> Self {
525         PrimitiveInstanceData {
526             data: [
527                 instance.prim_header_index.0,
528                 instance.polygons_address.as_int(),
529                 instance.z.0,
530                 instance.render_task_address.0 as i32,
531             ],
532         }
533     }
534 }
535 
536 bitflags! {
537     /// Flags that define how the common brush shader
538     /// code should process this instance.
539     #[cfg_attr(feature = "capture", derive(Serialize))]
540     #[cfg_attr(feature = "replay", derive(Deserialize))]
541     #[derive(MallocSizeOf)]
542     pub struct BrushFlags: u8 {
543         /// Apply perspective interpolation to UVs
544         const PERSPECTIVE_INTERPOLATION = 1;
545         /// Do interpolation relative to segment rect,
546         /// rather than primitive rect.
547         const SEGMENT_RELATIVE = 2;
548         /// Repeat UVs horizontally.
549         const SEGMENT_REPEAT_X = 4;
550         /// Repeat UVs vertically.
551         const SEGMENT_REPEAT_Y = 8;
552         /// Horizontally follow border-image-repeat: round.
553         const SEGMENT_REPEAT_X_ROUND = 16;
554         /// Vertically follow border-image-repeat: round.
555         const SEGMENT_REPEAT_Y_ROUND = 32;
556         /// Middle (fill) area of a border-image-repeat.
557         const SEGMENT_NINEPATCH_MIDDLE = 64;
558         /// The extra segment data is a texel rect.
559         const SEGMENT_TEXEL_RECT = 128;
560     }
561 }
562 
563 /// Convenience structure to encode into PrimitiveInstanceData.
564 pub struct BrushInstance {
565     pub prim_header_index: PrimitiveHeaderIndex,
566     pub render_task_address: RenderTaskAddress,
567     pub clip_task_address: RenderTaskAddress,
568     pub segment_index: i32,
569     pub edge_flags: EdgeAaSegmentMask,
570     pub brush_flags: BrushFlags,
571     pub resource_address: i32,
572 }
573 
574 impl From<BrushInstance> for PrimitiveInstanceData {
from(instance: BrushInstance) -> Self575     fn from(instance: BrushInstance) -> Self {
576         PrimitiveInstanceData {
577             data: [
578                 instance.prim_header_index.0,
579                 ((instance.render_task_address.0 as i32) << 16)
580                 | instance.clip_task_address.0 as i32,
581                 instance.segment_index
582                 | ((instance.edge_flags.bits() as i32) << 16)
583                 | ((instance.brush_flags.bits() as i32) << 24),
584                 instance.resource_address,
585             ]
586         }
587     }
588 }
589 
590 /// Convenience structure to encode into the image brush's user data.
591 #[derive(Copy, Clone, Debug)]
592 pub struct ImageBrushData {
593     pub color_mode: ShaderColorMode,
594     pub alpha_type: AlphaType,
595     pub raster_space: RasterizationSpace,
596     pub opacity: f32,
597 }
598 
599 impl ImageBrushData {
600     #[inline]
encode(&self) -> [i32; 4]601     pub fn encode(&self) -> [i32; 4] {
602         [
603             self.color_mode as i32 | ((self.alpha_type as i32) << 16),
604             self.raster_space as i32,
605             get_shader_opacity(self.opacity),
606             0,
607         ]
608     }
609 }
610 
611 // Represents the information about a transform palette
612 // entry that is passed to shaders. It includes an index
613 // into the transform palette, and a set of flags. The
614 // only flag currently used determines whether the
615 // transform is axis-aligned (and this should have
616 // pixel snapping applied).
617 #[derive(Copy, Debug, Clone, PartialEq)]
618 #[cfg_attr(feature = "capture", derive(Serialize))]
619 #[cfg_attr(feature = "replay", derive(Deserialize))]
620 #[repr(C)]
621 pub struct TransformPaletteId(pub u32);
622 
623 impl TransformPaletteId {
624     /// Identity transform ID.
625     pub const IDENTITY: Self = TransformPaletteId(0);
626 
627     /// Extract the transform kind from the id.
transform_kind(&self) -> TransformedRectKind628     pub fn transform_kind(&self) -> TransformedRectKind {
629         if (self.0 >> 24) == 0 {
630             TransformedRectKind::AxisAligned
631         } else {
632             TransformedRectKind::Complex
633         }
634     }
635 
636     /// Override the kind of transform stored in this id. This can be useful in
637     /// cases where we don't want shaders to consider certain transforms axis-
638     /// aligned (i.e. perspective warp) even though we may still want to for the
639     /// general case.
override_transform_kind(&self, kind: TransformedRectKind) -> Self640     pub fn override_transform_kind(&self, kind: TransformedRectKind) -> Self {
641         TransformPaletteId((self.0 & 0xFFFFFFu32) | ((kind as u32) << 24))
642     }
643 }
644 
645 /// The GPU data payload for a transform palette entry.
646 #[derive(Debug, Clone)]
647 #[cfg_attr(feature = "capture", derive(Serialize))]
648 #[cfg_attr(feature = "replay", derive(Deserialize))]
649 #[repr(C)]
650 pub struct TransformData {
651     transform: LayoutToPictureTransform,
652     inv_transform: PictureToLayoutTransform,
653 }
654 
655 impl TransformData {
invalid() -> Self656     fn invalid() -> Self {
657         TransformData {
658             transform: LayoutToPictureTransform::identity(),
659             inv_transform: PictureToLayoutTransform::identity(),
660         }
661     }
662 }
663 
664 // Extra data stored about each transform palette entry.
665 #[derive(Clone)]
666 pub struct TransformMetadata {
667     transform_kind: TransformedRectKind,
668 }
669 
670 impl TransformMetadata {
invalid() -> Self671     pub fn invalid() -> Self {
672         TransformMetadata {
673             transform_kind: TransformedRectKind::AxisAligned,
674         }
675     }
676 }
677 
678 #[derive(Debug, Hash, Eq, PartialEq)]
679 struct RelativeTransformKey {
680     from_index: SpatialNodeIndex,
681     to_index: SpatialNodeIndex,
682 }
683 
684 // Stores a contiguous list of TransformData structs, that
685 // are ready for upload to the GPU.
686 // TODO(gw): For now, this only stores the complete local
687 //           to world transform for each spatial node. In
688 //           the future, the transform palette will support
689 //           specifying a coordinate system that the transform
690 //           should be relative to.
691 pub struct TransformPalette {
692     transforms: Vec<TransformData>,
693     metadata: Vec<TransformMetadata>,
694     map: FastHashMap<RelativeTransformKey, usize>,
695 }
696 
697 impl TransformPalette {
new(count: usize) -> Self698     pub fn new(count: usize) -> Self {
699         let _ = VECS_PER_TRANSFORM;
700         TransformPalette {
701             transforms: vec![TransformData::invalid(); count],
702             metadata: vec![TransformMetadata::invalid(); count],
703             map: FastHashMap::default(),
704         }
705     }
706 
finish(self) -> Vec<TransformData>707     pub fn finish(self) -> Vec<TransformData> {
708         self.transforms
709     }
710 
set_world_transform( &mut self, index: SpatialNodeIndex, transform: LayoutToWorldTransform, )711     pub fn set_world_transform(
712         &mut self,
713         index: SpatialNodeIndex,
714         transform: LayoutToWorldTransform,
715     ) {
716         register_transform(
717             &mut self.metadata,
718             &mut self.transforms,
719             index,
720             ROOT_SPATIAL_NODE_INDEX,
721             // We know the root picture space == world space
722             transform.with_destination::<PicturePixel>(),
723         );
724     }
725 
get_index( &mut self, child_index: SpatialNodeIndex, parent_index: SpatialNodeIndex, spatial_tree: &SpatialTree, ) -> usize726     fn get_index(
727         &mut self,
728         child_index: SpatialNodeIndex,
729         parent_index: SpatialNodeIndex,
730         spatial_tree: &SpatialTree,
731     ) -> usize {
732         if parent_index == ROOT_SPATIAL_NODE_INDEX {
733             child_index.0 as usize
734         } else if child_index == parent_index {
735             0
736         } else {
737             let key = RelativeTransformKey {
738                 from_index: child_index,
739                 to_index: parent_index,
740             };
741 
742             let metadata = &mut self.metadata;
743             let transforms = &mut self.transforms;
744 
745             *self.map
746                 .entry(key)
747                 .or_insert_with(|| {
748                     let transform = spatial_tree.get_relative_transform(
749                         child_index,
750                         parent_index,
751                     )
752                     .into_transform()
753                     .with_destination::<PicturePixel>();
754 
755                     register_transform(
756                         metadata,
757                         transforms,
758                         child_index,
759                         parent_index,
760                         transform,
761                     )
762                 })
763         }
764     }
765 
766     // Get a transform palette id for the given spatial node.
767     // TODO(gw): In the future, it will be possible to specify
768     //           a coordinate system id here, to allow retrieving
769     //           transforms in the local space of a given spatial node.
get_id( &mut self, from_index: SpatialNodeIndex, to_index: SpatialNodeIndex, spatial_tree: &SpatialTree, ) -> TransformPaletteId770     pub fn get_id(
771         &mut self,
772         from_index: SpatialNodeIndex,
773         to_index: SpatialNodeIndex,
774         spatial_tree: &SpatialTree,
775     ) -> TransformPaletteId {
776         let index = self.get_index(
777             from_index,
778             to_index,
779             spatial_tree,
780         );
781         let transform_kind = self.metadata[index].transform_kind as u32;
782         TransformPaletteId(
783             (index as u32) |
784             (transform_kind << 24)
785         )
786     }
787 }
788 
789 // Texture cache resources can be either a simple rect, or define
790 // a polygon within a rect by specifying a UV coordinate for each
791 // corner. This is useful for rendering screen-space rasterized
792 // off-screen surfaces.
793 #[derive(Debug, Copy, Clone)]
794 #[cfg_attr(feature = "capture", derive(Serialize))]
795 #[cfg_attr(feature = "replay", derive(Deserialize))]
796 pub enum UvRectKind {
797     // The 2d bounds of the texture cache entry define the
798     // valid UV space for this texture cache entry.
799     Rect,
800     // The four vertices below define a quad within
801     // the texture cache entry rect. The shader can
802     // use a bilerp() to correctly interpolate a
803     // UV coord in the vertex shader.
804     Quad {
805         top_left: DeviceHomogeneousVector,
806         top_right: DeviceHomogeneousVector,
807         bottom_left: DeviceHomogeneousVector,
808         bottom_right: DeviceHomogeneousVector,
809     },
810 }
811 
812 #[derive(Debug, Copy, Clone)]
813 #[cfg_attr(feature = "capture", derive(Serialize))]
814 #[cfg_attr(feature = "replay", derive(Deserialize))]
815 pub struct ImageSource {
816     pub p0: DevicePoint,
817     pub p1: DevicePoint,
818     // TODO: It appears that only glyphs make use of user_data (to store glyph offset
819     // and scale).
820     // Perhaps we should separate the two so we don't have to push an empty unused vec4
821     // for all image sources.
822     pub user_data: [f32; 4],
823     pub uv_rect_kind: UvRectKind,
824 }
825 
826 impl ImageSource {
write_gpu_blocks(&self, request: &mut GpuDataRequest)827     pub fn write_gpu_blocks(&self, request: &mut GpuDataRequest) {
828         // see fetch_image_resource in GLSL
829         // has to be VECS_PER_IMAGE_RESOURCE vectors
830         request.push([
831             self.p0.x,
832             self.p0.y,
833             self.p1.x,
834             self.p1.y,
835         ]);
836         request.push(self.user_data);
837 
838         // If this is a polygon uv kind, then upload the four vertices.
839         if let UvRectKind::Quad { top_left, top_right, bottom_left, bottom_right } = self.uv_rect_kind {
840             // see fetch_image_resource_extra in GLSL
841             //Note: we really need only 3 components per point here: X, Y, and W
842             request.push(top_left);
843             request.push(top_right);
844             request.push(bottom_left);
845             request.push(bottom_right);
846         }
847     }
848 }
849 
850 // Set the local -> world transform for a given spatial
851 // node in the transform palette.
register_transform( metadatas: &mut Vec<TransformMetadata>, transforms: &mut Vec<TransformData>, from_index: SpatialNodeIndex, to_index: SpatialNodeIndex, transform: LayoutToPictureTransform, ) -> usize852 fn register_transform(
853     metadatas: &mut Vec<TransformMetadata>,
854     transforms: &mut Vec<TransformData>,
855     from_index: SpatialNodeIndex,
856     to_index: SpatialNodeIndex,
857     transform: LayoutToPictureTransform,
858 ) -> usize {
859     // TODO: refactor the calling code to not even try
860     // registering a non-invertible transform.
861     let inv_transform = transform
862         .inverse()
863         .unwrap_or_else(PictureToLayoutTransform::identity);
864 
865     let metadata = TransformMetadata {
866         transform_kind: transform.transform_kind()
867     };
868     let data = TransformData {
869         transform,
870         inv_transform,
871     };
872 
873     if to_index == ROOT_SPATIAL_NODE_INDEX {
874         let index = from_index.0 as usize;
875         metadatas[index] = metadata;
876         transforms[index] = data;
877         index
878     } else {
879         let index = transforms.len();
880         metadatas.push(metadata);
881         transforms.push(data);
882         index
883     }
884 }
885 
get_shader_opacity(opacity: f32) -> i32886 pub fn get_shader_opacity(opacity: f32) -> i32 {
887     (opacity * 65535.0).round() as i32
888 }
889