1#![deny(missing_docs)]
6
7extern crate serde_bytes;
8
9use crate::channel::{self, MsgSender, Payload, PayloadSender, PayloadSenderHelperMethods};
10use peek_poke::PeekPoke;
11use std::cell::Cell;
12use std::fmt;
13use std::marker::PhantomData;
14use std::os::raw::c_void;
15use std::path::PathBuf;
16use std::sync::Arc;
17use std::u32;
18use crate::{display_item as di, font};
20use crate::color::{ColorU, ColorF};
21use crate::display_list::{BuiltDisplayList, BuiltDisplayListDescriptor};
22use crate::image::{BlobImageData, BlobImageKey, ImageData, ImageDescriptor, ImageKey};
23use crate::units::*;
24
25pub type TileSize = u16;
27
28pub type DocumentLayer = i8;
30
31#[derive(Copy, Clone, Deserialize, Serialize)]
34pub struct QualitySettings {
35 pub allow_sacrificing_subpixel_aa: bool,
40}
41
42impl Default for QualitySettings {
43 fn default() -> Self {
44 QualitySettings {
45 allow_sacrificing_subpixel_aa: true,
47 }
48 }
49}
50
51#[derive(Clone, Deserialize, Serialize)]
55pub enum ResourceUpdate {
56 AddImage(AddImage),
58 UpdateImage(UpdateImage),
60 AddBlobImage(AddBlobImage),
62 UpdateBlobImage(UpdateBlobImage),
64 DeleteImage(ImageKey),
70 SetBlobImageVisibleArea(BlobImageKey, DeviceIntRect),
72 AddFont(AddFont),
74 DeleteFont(font::FontKey),
80 AddFontInstance(AddFontInstance),
82 DeleteFontInstance(font::FontInstanceKey),
88}
89
90impl fmt::Debug for ResourceUpdate {
91 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92 match self {
93 ResourceUpdate::AddImage(ref i) => f.write_fmt(format_args!(
94 "ResourceUpdate::AddImage size({:?})",
95 &i.descriptor.size
96 )),
97 ResourceUpdate::UpdateImage(ref i) => f.write_fmt(format_args!(
98 "ResourceUpdate::UpdateImage size({:?})",
99 &i.descriptor.size
100 )),
101 ResourceUpdate::AddBlobImage(ref i) => f.write_fmt(format_args!(
102 "ResourceUpdate::AddBlobImage size({:?})",
103 &i.descriptor.size
104 )),
105 ResourceUpdate::UpdateBlobImage(i) => f.write_fmt(format_args!(
106 "ResourceUpdate::UpdateBlobImage size({:?})",
107 &i.descriptor.size
108 )),
109 ResourceUpdate::DeleteImage(..) => f.write_str("ResourceUpdate::DeleteImage"),
110 ResourceUpdate::SetBlobImageVisibleArea(..) => f.write_str("ResourceUpdate::SetBlobImageVisibleArea"),
111 ResourceUpdate::AddFont(..) => f.write_str("ResourceUpdate::AddFont"),
112 ResourceUpdate::DeleteFont(..) => f.write_str("ResourceUpdate::DeleteFont"),
113 ResourceUpdate::AddFontInstance(..) => f.write_str("ResourceUpdate::AddFontInstance"),
114 ResourceUpdate::DeleteFontInstance(..) => f.write_str("ResourceUpdate::DeleteFontInstance"),
115 }
116 }
117}
118
119pub struct Transaction {
126 scene_ops: Vec<SceneMsg>,
128 frame_ops: Vec<FrameMsg>,
130
131 payloads: Vec<Payload>,
133
134 notifications: Vec<NotificationRequest>,
135
136 pub resource_updates: Vec<ResourceUpdate>,
138
139 use_scene_builder_thread: bool,
142
143 generate_frame: bool,
144
145 pub invalidate_rendered_frame: bool,
148
149 low_priority: bool,
150}
151
152impl Transaction {
153 pub fn new() -> Self {
155 Transaction {
156 scene_ops: Vec::new(),
157 frame_ops: Vec::new(),
158 resource_updates: Vec::new(),
159 payloads: Vec::new(),
160 notifications: Vec::new(),
161 use_scene_builder_thread: true,
162 generate_frame: false,
163 invalidate_rendered_frame: false,
164 low_priority: false,
165 }
166 }
167
168 pub fn skip_scene_builder(&mut self) {
177 self.use_scene_builder_thread = false;
178 }
179
180 pub fn use_scene_builder_thread(&mut self) {
182 self.use_scene_builder_thread = true;
183 }
184
185 pub fn is_empty(&self) -> bool {
187 !self.generate_frame &&
188 !self.invalidate_rendered_frame &&
189 self.scene_ops.is_empty() &&
190 self.frame_ops.is_empty() &&
191 self.resource_updates.is_empty() &&
192 self.notifications.is_empty()
193 }
194
195 pub fn update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch) {
197 self.scene_ops.push(SceneMsg::UpdateEpoch(pipeline_id, epoch));
200 self.frame_ops.push(FrameMsg::UpdateEpoch(pipeline_id, epoch));
203 }
207
208 pub fn set_root_pipeline(&mut self, pipeline_id: PipelineId) {
222 self.scene_ops.push(SceneMsg::SetRootPipeline(pipeline_id));
223 }
224
225 pub fn remove_pipeline(&mut self, pipeline_id: PipelineId) {
229 self.scene_ops.push(SceneMsg::RemovePipeline(pipeline_id));
230 }
231
232 pub fn set_display_list(
250 &mut self,
251 epoch: Epoch,
252 background: Option<ColorF>,
253 viewport_size: LayoutSize,
254 (pipeline_id, content_size, display_list): (PipelineId, LayoutSize, BuiltDisplayList),
255 preserve_frame_state: bool,
256 ) {
257 let (display_list_data, list_descriptor) = display_list.into_data();
258 self.scene_ops.push(
259 SceneMsg::SetDisplayList {
260 epoch,
261 pipeline_id,
262 background,
263 viewport_size,
264 content_size,
265 list_descriptor,
266 preserve_frame_state,
267 }
268 );
269 self.payloads.push(Payload { epoch, pipeline_id, display_list_data });
270 }
271
272 pub fn update_resources(&mut self, mut resources: Vec<ResourceUpdate>) {
274 self.resource_updates.append(&mut resources);
275 }
276
277 pub fn notify(&mut self, event: NotificationRequest) {
289 self.notifications.push(event);
290 }
291
292 pub fn set_document_view(
294 &mut self,
295 device_rect: DeviceIntRect,
296 device_pixel_ratio: f32,
297 ) {
298 self.scene_ops.push(
299 SceneMsg::SetDocumentView {
300 device_rect,
301 device_pixel_ratio,
302 },
303 );
304 }
305
306 pub fn enable_frame_output(&mut self, pipeline_id: PipelineId, enable: bool) {
309 self.scene_ops.push(SceneMsg::EnableFrameOutput(pipeline_id, enable));
310 }
311
312 pub fn scroll(&mut self, scroll_location: ScrollLocation, cursor: WorldPoint) {
317 self.frame_ops.push(FrameMsg::Scroll(scroll_location, cursor));
318 }
319
320 pub fn scroll_node_with_id(
322 &mut self,
323 origin: LayoutPoint,
324 id: di::ExternalScrollId,
325 clamp: ScrollClamping,
326 ) {
327 self.frame_ops.push(FrameMsg::ScrollNodeWithId(origin, id, clamp));
328 }
329
330 pub fn set_quality_settings(&mut self, settings: QualitySettings) {
332 self.scene_ops.push(SceneMsg::SetQualitySettings { settings });
333 }
334
335 pub fn set_page_zoom(&mut self, page_zoom: ZoomFactor) {
337 self.scene_ops.push(SceneMsg::SetPageZoom(page_zoom));
338 }
339
340 pub fn set_pinch_zoom(&mut self, pinch_zoom: ZoomFactor) {
342 self.frame_ops.push(FrameMsg::SetPinchZoom(pinch_zoom));
343 }
344
345 pub fn set_is_transform_async_zooming(&mut self, is_zooming: bool, animation_id: PropertyBindingId) {
347 self.frame_ops.push(FrameMsg::SetIsTransformAsyncZooming(is_zooming, animation_id));
348 }
349
350 pub fn set_pan(&mut self, pan: DeviceIntPoint) {
352 self.frame_ops.push(FrameMsg::SetPan(pan));
353 }
354
355 pub fn generate_frame(&mut self) {
363 self.generate_frame = true;
364 }
365
366 pub fn invalidate_rendered_frame(&mut self) {
373 self.invalidate_rendered_frame = true;
374 }
375
376 pub fn update_dynamic_properties(&mut self, properties: DynamicProperties) {
379 self.frame_ops.push(FrameMsg::UpdateDynamicProperties(properties));
380 }
381
382 pub fn append_dynamic_properties(&mut self, properties: DynamicProperties) {
387 self.frame_ops.push(FrameMsg::AppendDynamicProperties(properties));
388 }
389
390 pub fn get_frame_ops(self) -> Vec<FrameMsg> {
392 self.frame_ops
393 }
394
395 fn finalize(self) -> (TransactionMsg, Vec<Payload>) {
396 (
397 TransactionMsg {
398 scene_ops: self.scene_ops,
399 frame_ops: self.frame_ops,
400 resource_updates: self.resource_updates,
401 notifications: self.notifications,
402 use_scene_builder_thread: self.use_scene_builder_thread,
403 generate_frame: self.generate_frame,
404 invalidate_rendered_frame: self.invalidate_rendered_frame,
405 low_priority: self.low_priority,
406 },
407 self.payloads,
408 )
409 }
410
411 pub fn add_image(
413 &mut self,
414 key: ImageKey,
415 descriptor: ImageDescriptor,
416 data: ImageData,
417 tiling: Option<TileSize>,
418 ) {
419 self.resource_updates.push(ResourceUpdate::AddImage(AddImage {
420 key,
421 descriptor,
422 data,
423 tiling,
424 }));
425 }
426
427 pub fn update_image(
429 &mut self,
430 key: ImageKey,
431 descriptor: ImageDescriptor,
432 data: ImageData,
433 dirty_rect: &ImageDirtyRect,
434 ) {
435 self.resource_updates.push(ResourceUpdate::UpdateImage(UpdateImage {
436 key,
437 descriptor,
438 data,
439 dirty_rect: *dirty_rect,
440 }));
441 }
442
443 pub fn delete_image(&mut self, key: ImageKey) {
445 self.resource_updates.push(ResourceUpdate::DeleteImage(key));
446 }
447
448 pub fn add_blob_image(
450 &mut self,
451 key: BlobImageKey,
452 descriptor: ImageDescriptor,
453 data: Arc<BlobImageData>,
454 visible_rect: DeviceIntRect,
455 tiling: Option<TileSize>,
456 ) {
457 self.resource_updates.push(
458 ResourceUpdate::AddBlobImage(AddBlobImage {
459 key,
460 descriptor,
461 data,
462 visible_rect,
463 tiling,
464 })
465 );
466 }
467
468 pub fn update_blob_image(
470 &mut self,
471 key: BlobImageKey,
472 descriptor: ImageDescriptor,
473 data: Arc<BlobImageData>,
474 visible_rect: DeviceIntRect,
475 dirty_rect: &BlobDirtyRect,
476 ) {
477 self.resource_updates.push(
478 ResourceUpdate::UpdateBlobImage(UpdateBlobImage {
479 key,
480 descriptor,
481 data,
482 visible_rect,
483 dirty_rect: *dirty_rect,
484 })
485 );
486 }
487
488 pub fn delete_blob_image(&mut self, key: BlobImageKey) {
490 self.resource_updates.push(ResourceUpdate::DeleteImage(key.as_image()));
491 }
492
493 pub fn set_blob_image_visible_area(&mut self, key: BlobImageKey, area: DeviceIntRect) {
495 self.resource_updates.push(ResourceUpdate::SetBlobImageVisibleArea(key, area))
496 }
497
498 pub fn add_raw_font(&mut self, key: font::FontKey, bytes: Vec<u8>, index: u32) {
500 self.resource_updates
501 .push(ResourceUpdate::AddFont(AddFont::Raw(key, bytes, index)));
502 }
503
504 pub fn add_native_font(&mut self, key: font::FontKey, native_handle: font::NativeFontHandle) {
506 self.resource_updates
507 .push(ResourceUpdate::AddFont(AddFont::Native(key, native_handle)));
508 }
509
510 pub fn delete_font(&mut self, key: font::FontKey) {
512 self.resource_updates.push(ResourceUpdate::DeleteFont(key));
513 }
514
515 pub fn add_font_instance(
517 &mut self,
518 key: font::FontInstanceKey,
519 font_key: font::FontKey,
520 glyph_size: Au,
521 options: Option<font::FontInstanceOptions>,
522 platform_options: Option<font::FontInstancePlatformOptions>,
523 variations: Vec<font::FontVariation>,
524 ) {
525 self.resource_updates
526 .push(ResourceUpdate::AddFontInstance(AddFontInstance {
527 key,
528 font_key,
529 glyph_size,
530 options,
531 platform_options,
532 variations,
533 }));
534 }
535
536 pub fn delete_font_instance(&mut self, key: font::FontInstanceKey) {
538 self.resource_updates.push(ResourceUpdate::DeleteFontInstance(key));
539 }
540
541 pub fn set_low_priority(&mut self, low_priority: bool) {
546 self.low_priority = low_priority;
547 }
548
549 pub fn is_low_priority(&self) -> bool {
551 self.low_priority
552 }
553}
554
555pub struct DocumentTransaction {
557 pub document_id: DocumentId,
559 pub transaction: Transaction,
561}
562
563#[derive(Clone, Deserialize, Serialize)]
565pub struct TransactionMsg {
566 pub scene_ops: Vec<SceneMsg>,
568 pub frame_ops: Vec<FrameMsg>,
570 pub resource_updates: Vec<ResourceUpdate>,
572 pub generate_frame: bool,
574 pub invalidate_rendered_frame: bool,
577 pub use_scene_builder_thread: bool,
579 pub low_priority: bool,
581
582 #[serde(skip)]
584 pub notifications: Vec<NotificationRequest>,
585}
586
587impl fmt::Debug for TransactionMsg {
588 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
589 writeln!(f, "threaded={}, genframe={}, invalidate={}, low_priority={}",
590 self.use_scene_builder_thread,
591 self.generate_frame,
592 self.invalidate_rendered_frame,
593 self.low_priority,
594 ).unwrap();
595 for scene_op in &self.scene_ops {
596 writeln!(f, "\t\t{:?}", scene_op).unwrap();
597 }
598
599 for frame_op in &self.frame_ops {
600 writeln!(f, "\t\t{:?}", frame_op).unwrap();
601 }
602
603 for resource_update in &self.resource_updates {
604 writeln!(f, "\t\t{:?}", resource_update).unwrap();
605 }
606 Ok(())
607 }
608}
609
610impl TransactionMsg {
611 pub fn is_empty(&self) -> bool {
613 !self.generate_frame &&
614 !self.invalidate_rendered_frame &&
615 self.scene_ops.is_empty() &&
616 self.frame_ops.is_empty() &&
617 self.resource_updates.is_empty() &&
618 self.notifications.is_empty()
619 }
620
621 pub fn frame_message(msg: FrameMsg) -> Self {
623 TransactionMsg {
624 scene_ops: Vec::new(),
625 frame_ops: vec![msg],
626 resource_updates: Vec::new(),
627 notifications: Vec::new(),
628 generate_frame: false,
629 invalidate_rendered_frame: false,
630 use_scene_builder_thread: false,
631 low_priority: false,
632 }
633 }
634
635 pub fn scene_message(msg: SceneMsg) -> Self {
637 TransactionMsg {
638 scene_ops: vec![msg],
639 frame_ops: Vec::new(),
640 resource_updates: Vec::new(),
641 notifications: Vec::new(),
642 generate_frame: false,
643 invalidate_rendered_frame: false,
644 use_scene_builder_thread: false,
645 low_priority: false,
646 }
647 }
648}
649
650#[derive(Clone, Deserialize, Serialize)]
654pub struct AddImage {
655 pub key: ImageKey,
657 pub descriptor: ImageDescriptor,
659 pub data: ImageData,
661 pub tiling: Option<TileSize>,
667}
668
669#[derive(Clone, Deserialize, Serialize)]
671pub struct UpdateImage {
672 pub key: ImageKey,
674 pub descriptor: ImageDescriptor,
676 pub data: ImageData,
678 pub dirty_rect: ImageDirtyRect,
683}
684
685#[derive(Clone, Deserialize, Serialize)]
689pub struct AddBlobImage {
690 pub key: BlobImageKey,
692 pub descriptor: ImageDescriptor,
694 pub data: Arc<BlobImageData>,
696 pub visible_rect: DeviceIntRect,
705 pub tiling: Option<TileSize>,
712}
713
714#[derive(Clone, Deserialize, Serialize)]
716pub struct UpdateBlobImage {
717 pub key: BlobImageKey,
719 pub descriptor: ImageDescriptor,
721 pub data: Arc<BlobImageData>,
723 pub visible_rect: DeviceIntRect,
725 pub dirty_rect: BlobDirtyRect,
728}
729
730#[derive(Clone, Deserialize, Serialize)]
735pub enum AddFont {
736 Raw(
738 font::FontKey,
739 #[serde(with = "serde_bytes")] Vec<u8>,
740 u32
741 ),
742 Native(font::FontKey, font::NativeFontHandle),
744}
745
746#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
748pub struct HitTestItem {
749 pub pipeline: PipelineId,
751
752 pub tag: di::ItemTag,
754
755 pub point_in_viewport: LayoutPoint,
759
760 pub point_relative_to_item: LayoutPoint,
763}
764
765#[derive(Clone, Debug, Default, Deserialize, Serialize)]
767pub struct HitTestResult {
768 pub items: Vec<HitTestItem>,
770}
771
772bitflags! {
773 #[derive(Deserialize, MallocSizeOf, Serialize)]
774 pub struct HitTestFlags: u8 {
776 const FIND_ALL = 0b00000001;
778 const POINT_RELATIVE_TO_PIPELINE_VIEWPORT = 0b00000010;
780 }
781}
782
783#[derive(Clone, Deserialize, Serialize)]
788pub struct AddFontInstance {
789 pub key: font::FontInstanceKey,
791 pub font_key: font::FontKey,
793 pub glyph_size: Au,
795 pub options: Option<font::FontInstanceOptions>,
797 pub platform_options: Option<font::FontInstancePlatformOptions>,
799 pub variations: Vec<font::FontVariation>,
801}
802
803#[derive(Clone, Deserialize, Serialize)]
805pub enum SceneMsg {
806 UpdateEpoch(PipelineId, Epoch),
808 SetPageZoom(ZoomFactor),
810 SetRootPipeline(PipelineId),
812 RemovePipeline(PipelineId),
814 EnableFrameOutput(PipelineId, bool),
816 SetDisplayList {
818 list_descriptor: BuiltDisplayListDescriptor,
820 epoch: Epoch,
822 pipeline_id: PipelineId,
824 background: Option<ColorF>,
826 viewport_size: LayoutSize,
828 content_size: LayoutSize,
830 preserve_frame_state: bool,
832 },
833 SetDocumentView {
835 device_rect: DeviceIntRect,
837 device_pixel_ratio: f32,
839 },
840 SetQualitySettings {
842 settings: QualitySettings,
844 },
845}
846
847#[derive(Clone, Deserialize, Serialize)]
849pub enum FrameMsg {
850 UpdateEpoch(PipelineId, Epoch),
852 HitTest(Option<PipelineId>, WorldPoint, HitTestFlags, MsgSender<HitTestResult>),
854 SetPan(DeviceIntPoint),
856 Scroll(ScrollLocation, WorldPoint),
858 ScrollNodeWithId(LayoutPoint, di::ExternalScrollId, ScrollClamping),
860 GetScrollNodeState(MsgSender<Vec<ScrollNodeState>>),
862 UpdateDynamicProperties(DynamicProperties),
864 AppendDynamicProperties(DynamicProperties),
866 SetPinchZoom(ZoomFactor),
868 SetIsTransformAsyncZooming(bool, PropertyBindingId),
870}
871
872impl fmt::Debug for SceneMsg {
873 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
874 f.write_str(match *self {
875 SceneMsg::UpdateEpoch(..) => "SceneMsg::UpdateEpoch",
876 SceneMsg::SetDisplayList { .. } => "SceneMsg::SetDisplayList",
877 SceneMsg::SetPageZoom(..) => "SceneMsg::SetPageZoom",
878 SceneMsg::RemovePipeline(..) => "SceneMsg::RemovePipeline",
879 SceneMsg::EnableFrameOutput(..) => "SceneMsg::EnableFrameOutput",
880 SceneMsg::SetDocumentView { .. } => "SceneMsg::SetDocumentView",
881 SceneMsg::SetRootPipeline(..) => "SceneMsg::SetRootPipeline",
882 SceneMsg::SetQualitySettings { .. } => "SceneMsg::SetQualitySettings",
883 })
884 }
885}
886
887impl fmt::Debug for FrameMsg {
888 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
889 f.write_str(match *self {
890 FrameMsg::UpdateEpoch(..) => "FrameMsg::UpdateEpoch",
891 FrameMsg::HitTest(..) => "FrameMsg::HitTest",
892 FrameMsg::SetPan(..) => "FrameMsg::SetPan",
893 FrameMsg::Scroll(..) => "FrameMsg::Scroll",
894 FrameMsg::ScrollNodeWithId(..) => "FrameMsg::ScrollNodeWithId",
895 FrameMsg::GetScrollNodeState(..) => "FrameMsg::GetScrollNodeState",
896 FrameMsg::UpdateDynamicProperties(..) => "FrameMsg::UpdateDynamicProperties",
897 FrameMsg::AppendDynamicProperties(..) => "FrameMsg::AppendDynamicProperties",
898 FrameMsg::SetPinchZoom(..) => "FrameMsg::SetPinchZoom",
899 FrameMsg::SetIsTransformAsyncZooming(..) => "FrameMsg::SetIsTransformAsyncZooming",
900 })
901 }
902}
903
904bitflags!{
905 #[derive(Deserialize, Serialize)]
908 pub struct CaptureBits: u8 {
909 const SCENE = 0x1;
911 const FRAME = 0x2;
913 }
914}
915
916bitflags!{
917 #[derive(Deserialize, Serialize)]
919 pub struct ClearCache: u8 {
920 const IMAGES = 0b1;
922 const GLYPHS = 0b01;
924 const GLYPH_DIMENSIONS = 0b001;
926 const RENDER_TASKS = 0b0001;
928 const TEXTURE_CACHE = 0b00001;
930 const RASTERIZED_BLOBS = 0b000001;
932 }
933}
934
935#[derive(Clone, Debug, Deserialize, Serialize)]
938pub struct CapturedDocument {
939 pub document_id: DocumentId,
941 pub root_pipeline_id: Option<PipelineId>,
943}
944
945#[derive(Clone, Deserialize, Serialize)]
947pub enum DebugCommand {
948 SetFlags(DebugFlags),
950 EnableDualSourceBlending(bool),
952 FetchDocuments,
954 FetchPasses,
956 FetchClipScrollTree,
958 FetchRenderTasks,
960 FetchScreenshot,
962 SaveCapture(PathBuf, CaptureBits),
964 LoadCapture(PathBuf, MsgSender<CapturedDocument>),
966 ClearCaches(ClearCache),
968 InvalidateGpuCache,
970 SimulateLongSceneBuild(u32),
973 SimulateLongLowPrioritySceneBuild(u32),
976 SetTransactionLogging(bool),
978}
979
980#[derive(Clone, Deserialize, Serialize)]
982pub enum ApiMsg {
983 UpdateResources(Vec<ResourceUpdate>),
985 GetGlyphDimensions(
987 font::FontInstanceKey,
988 Vec<font::GlyphIndex>,
989 MsgSender<Vec<Option<font::GlyphDimensions>>>,
990 ),
991 GetGlyphIndices(font::FontKey, String, MsgSender<Vec<Option<u32>>>),
993 CloneApi(MsgSender<IdNamespace>),
995 CloneApiByClient(IdNamespace),
997 AddDocument(DocumentId, DeviceIntSize, DocumentLayer),
999 UpdateDocuments(Vec<DocumentId>, Vec<TransactionMsg>),
1001 DeleteDocument(DocumentId),
1003 ExternalEvent(ExternalEvent),
1007 ClearNamespace(IdNamespace),
1009 MemoryPressure,
1011 ReportMemory(MsgSender<Box<MemoryReport>>),
1013 DebugCommand(DebugCommand),
1015 WakeUp,
1018 WakeSceneBuilder,
1020 FlushSceneBuilder(MsgSender<()>),
1024 ShutDown(Option<MsgSender<()>>),
1026}
1027
1028impl fmt::Debug for ApiMsg {
1029 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1030 f.write_str(match *self {
1031 ApiMsg::UpdateResources(..) => "ApiMsg::UpdateResources",
1032 ApiMsg::GetGlyphDimensions(..) => "ApiMsg::GetGlyphDimensions",
1033 ApiMsg::GetGlyphIndices(..) => "ApiMsg::GetGlyphIndices",
1034 ApiMsg::CloneApi(..) => "ApiMsg::CloneApi",
1035 ApiMsg::CloneApiByClient(..) => "ApiMsg::CloneApiByClient",
1036 ApiMsg::AddDocument(..) => "ApiMsg::AddDocument",
1037 ApiMsg::UpdateDocuments(..) => "ApiMsg::UpdateDocuments",
1038 ApiMsg::DeleteDocument(..) => "ApiMsg::DeleteDocument",
1039 ApiMsg::ExternalEvent(..) => "ApiMsg::ExternalEvent",
1040 ApiMsg::ClearNamespace(..) => "ApiMsg::ClearNamespace",
1041 ApiMsg::MemoryPressure => "ApiMsg::MemoryPressure",
1042 ApiMsg::ReportMemory(..) => "ApiMsg::ReportMemory",
1043 ApiMsg::DebugCommand(..) => "ApiMsg::DebugCommand",
1044 ApiMsg::ShutDown(..) => "ApiMsg::ShutDown",
1045 ApiMsg::WakeUp => "ApiMsg::WakeUp",
1046 ApiMsg::WakeSceneBuilder => "ApiMsg::WakeSceneBuilder",
1047 ApiMsg::FlushSceneBuilder(..) => "ApiMsg::FlushSceneBuilder",
1048 })
1049 }
1050}
1051
1052#[repr(C)]
1057#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
1058pub struct Epoch(pub u32);
1059
1060impl Epoch {
1061 pub fn invalid() -> Epoch {
1063 Epoch(u32::MAX)
1064 }
1065}
1066
1067#[repr(C)]
1071#[derive(Clone, Copy, Debug, Default, Eq, MallocSizeOf, PartialEq, Hash, Ord, PartialOrd, PeekPoke)]
1072#[derive(Deserialize, Serialize)]
1073pub struct IdNamespace(pub u32);
1074
1075#[repr(C)]
1081#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1082pub struct DocumentId {
1083 pub namespace_id: IdNamespace,
1085 pub id: u32,
1087}
1088
1089impl DocumentId {
1090 pub fn new(namespace_id: IdNamespace, id: u32) -> Self {
1092 DocumentId {
1093 namespace_id,
1094 id,
1095 }
1096 }
1097
1098 pub const INVALID: DocumentId = DocumentId { namespace_id: IdNamespace(0), id: 0 };
1100}
1101
1102pub type PipelineSourceId = u32;
1107
1108#[repr(C)]
1111#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize, PeekPoke)]
1112pub struct PipelineId(pub PipelineSourceId, pub u32);
1113
1114impl Default for PipelineId {
1115 fn default() -> Self {
1116 PipelineId::dummy()
1117 }
1118}
1119
1120impl PipelineId {
1121 pub fn dummy() -> Self {
1123 PipelineId(0, 0)
1124 }
1125}
1126
1127#[derive(Copy, Clone, Debug, MallocSizeOf, Serialize, Deserialize)]
1129pub enum ClipIntern {}
1130
1131#[derive(Copy, Clone, Debug, MallocSizeOf, Serialize, Deserialize)]
1133pub enum FilterDataIntern {}
1134
1135#[derive(Debug, Clone, Eq, MallocSizeOf, PartialEq, Hash, Serialize, Deserialize)]
1138pub enum PrimitiveKeyKind {
1139 Clear,
1141 Rectangle {
1143 color: ColorU,
1145 },
1146}
1147
1148#[macro_export]
1155macro_rules! enumerate_interners {
1156 ($macro_name: ident) => {
1157 $macro_name! {
1158 clip: ClipIntern,
1159 prim: PrimitiveKeyKind,
1160 normal_border: NormalBorderPrim,
1161 image_border: ImageBorder,
1162 image: Image,
1163 yuv_image: YuvImage,
1164 line_decoration: LineDecoration,
1165 linear_grad: LinearGradient,
1166 radial_grad: RadialGradient,
1167 picture: Picture,
1168 text_run: TextRun,
1169 filter_data: FilterDataIntern,
1170 backdrop: Backdrop,
1171 }
1172 }
1173}
1174
1175macro_rules! declare_interning_memory_report {
1176 ( $( $name:ident: $ty:ident, )+ ) => {
1177 #[repr(C)]
1179 #[derive(AddAssign, Clone, Debug, Default, Deserialize, Serialize)]
1180 pub struct InternerSubReport {
1181 $(
1182 pub $name: usize,
1184 )+
1185 }
1186 }
1187}
1188
1189enumerate_interners!(declare_interning_memory_report);
1190
1191#[repr(C)]
1194#[derive(Clone, Debug, Default, Deserialize, Serialize)]
1195pub struct InterningMemoryReport {
1196 pub interners: InternerSubReport,
1198 pub data_stores: InternerSubReport,
1200}
1201
1202impl ::std::ops::AddAssign for InterningMemoryReport {
1203 fn add_assign(&mut self, other: InterningMemoryReport) {
1204 self.interners += other.interners;
1205 self.data_stores += other.data_stores;
1206 }
1207}
1208
1209#[repr(C)]
1212#[allow(missing_docs)]
1213#[derive(AddAssign, Clone, Debug, Default, Deserialize, Serialize)]
1214pub struct MemoryReport {
1215 pub clip_stores: usize,
1219 pub gpu_cache_metadata: usize,
1220 pub gpu_cache_cpu_mirror: usize,
1221 pub render_tasks: usize,
1222 pub hit_testers: usize,
1223 pub fonts: usize,
1224 pub images: usize,
1225 pub rasterized_blobs: usize,
1226 pub shader_cache: usize,
1227 pub interning: InterningMemoryReport,
1228
1229 pub gpu_cache_textures: usize,
1233 pub vertex_data_textures: usize,
1234 pub render_target_textures: usize,
1235 pub texture_cache_textures: usize,
1236 pub depth_target_textures: usize,
1237 pub swap_chain: usize,
1238}
1239
1240pub type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
1245
1246#[repr(C)]
1247#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
1248struct ResourceId(pub u32);
1249
1250#[repr(C)]
1252#[derive(Clone, Deserialize, Serialize)]
1253pub struct ExternalEvent {
1254 raw: usize,
1255}
1256
1257unsafe impl Send for ExternalEvent {}
1258
1259impl ExternalEvent {
1260 pub fn from_raw(raw: usize) -> Self {
1262 ExternalEvent { raw }
1263 }
1264 pub fn unwrap(self) -> usize {
1266 self.raw
1267 }
1268}
1269
1270#[derive(Clone, Deserialize, Serialize)]
1272pub enum ScrollClamping {
1273 ToContentBounds,
1275 NoClamping,
1277}
1278
1279#[derive(Clone, Deserialize, Serialize)]
1284pub struct RenderApiSender {
1285 api_sender: MsgSender<ApiMsg>,
1286 payload_sender: PayloadSender,
1287}
1288
1289impl RenderApiSender {
1290 pub fn new(api_sender: MsgSender<ApiMsg>, payload_sender: PayloadSender) -> Self {
1292 RenderApiSender {
1293 api_sender,
1294 payload_sender,
1295 }
1296 }
1297
1298 pub fn create_api(&self) -> RenderApi {
1300 let (sync_tx, sync_rx) =
1301 channel::msg_channel().expect("Failed to create channel");
1302 let msg = ApiMsg::CloneApi(sync_tx);
1303 self.api_sender.send(msg).expect("Failed to send CloneApi message");
1304 let namespace_id = match sync_rx.recv() {
1305 Ok(id) => id,
1306 Err(e) => {
1307 let webrender_is_alive = self.api_sender.send(ApiMsg::WakeUp);
1309 if webrender_is_alive.is_err() {
1310 panic!("WebRender was shut down before processing CloneApi: {}", e);
1311 } else {
1312 panic!("CloneApi message response was dropped while WebRender was still alive: {}", e);
1313 }
1314 }
1315 };
1316 RenderApi {
1317 api_sender: self.api_sender.clone(),
1318 payload_sender: self.payload_sender.clone(),
1319 namespace_id,
1320 next_id: Cell::new(ResourceId(0)),
1321 }
1322 }
1323
1324 pub fn create_api_by_client(&self, namespace_id: IdNamespace) -> RenderApi {
1330 let msg = ApiMsg::CloneApiByClient(namespace_id);
1331 self.api_sender.send(msg).expect("Failed to send CloneApiByClient message");
1332 RenderApi {
1333 api_sender: self.api_sender.clone(),
1334 payload_sender: self.payload_sender.clone(),
1335 namespace_id,
1336 next_id: Cell::new(ResourceId(0)),
1337 }
1338 }
1339}
1340
1341bitflags! {
1342 #[repr(C)]
1344 #[derive(Default, Deserialize, MallocSizeOf, Serialize)]
1345 pub struct DebugFlags: u32 {
1346 const PROFILER_DBG = 1 << 0;
1348 const RENDER_TARGET_DBG = 1 << 1;
1350 const TEXTURE_CACHE_DBG = 1 << 2;
1352 const GPU_TIME_QUERIES = 1 << 3;
1354 const GPU_SAMPLE_QUERIES = 1 << 4;
1358 const DISABLE_BATCHING = 1 << 5;
1363 const EPOCHS = 1 << 6;
1365 const COMPACT_PROFILER = 1 << 7;
1368 const ECHO_DRIVER_MESSAGES = 1 << 8;
1370 const NEW_FRAME_INDICATOR = 1 << 9;
1372 const NEW_SCENE_INDICATOR = 1 << 10;
1374 const SHOW_OVERDRAW = 1 << 11;
1376 const GPU_CACHE_DBG = 1 << 12;
1378 const SLOW_FRAME_INDICATOR = 1 << 13;
1380 const TEXTURE_CACHE_DBG_CLEAR_EVICTED = 1 << 14;
1382 const PICTURE_CACHING_DBG = 1 << 15;
1384 const PRIMITIVE_DBG = 1 << 16;
1386 const ZOOM_DBG = 1 << 17;
1388 const SMALL_SCREEN = 1 << 18;
1392 const DISABLE_OPAQUE_PASS = 1 << 19;
1395 const DISABLE_ALPHA_PASS = 1 << 20;
1397 const DISABLE_CLIP_MASKS = 1 << 21;
1399 const DISABLE_TEXT_PRIMS = 1 << 22;
1401 const DISABLE_GRADIENT_PRIMS = 1 << 23;
1403 const OBSCURE_IMAGES = 1 << 24;
1405 const GLYPH_FLASHING = 1 << 25;
1408 const SMART_PROFILER = 1 << 26;
1410 const DISABLE_PICTURE_CACHING = 1 << 27;
1412 const INVALIDATION_DBG = 1 << 28;
1414 }
1415}
1416
1417pub struct RenderApi {
1419 api_sender: MsgSender<ApiMsg>,
1420 payload_sender: PayloadSender,
1421 namespace_id: IdNamespace,
1422 next_id: Cell<ResourceId>,
1423}
1424
1425impl RenderApi {
1426 pub fn get_namespace_id(&self) -> IdNamespace {
1428 self.namespace_id
1429 }
1430
1431 pub fn clone_sender(&self) -> RenderApiSender {
1433 RenderApiSender::new(self.api_sender.clone(), self.payload_sender.clone())
1434 }
1435
1436 pub fn add_document(&self, initial_size: DeviceIntSize, layer: DocumentLayer) -> DocumentId {
1442 let new_id = self.next_unique_id();
1443 self.add_document_with_id(initial_size, layer, new_id)
1444 }
1445
1446 pub fn add_document_with_id(&self,
1448 initial_size: DeviceIntSize,
1449 layer: DocumentLayer,
1450 id: u32) -> DocumentId {
1451 let document_id = DocumentId::new(self.namespace_id, id);
1452
1453 let msg = ApiMsg::AddDocument(document_id, initial_size, layer);
1454 self.api_sender.send(msg).unwrap();
1455
1456 document_id
1457 }
1458
1459 pub fn delete_document(&self, document_id: DocumentId) {
1461 let msg = ApiMsg::DeleteDocument(document_id);
1462 self.api_sender.send(msg).unwrap();
1463 }
1464
1465 pub fn generate_font_key(&self) -> font::FontKey {
1467 let new_id = self.next_unique_id();
1468 font::FontKey::new(self.namespace_id, new_id)
1469 }
1470
1471 pub fn generate_font_instance_key(&self) -> font::FontInstanceKey {
1473 let new_id = self.next_unique_id();
1474 font::FontInstanceKey::new(self.namespace_id, new_id)
1475 }
1476
1477 pub fn get_glyph_dimensions(
1483 &self,
1484 font: font::FontInstanceKey,
1485 glyph_indices: Vec<font::GlyphIndex>,
1486 ) -> Vec<Option<font::GlyphDimensions>> {
1487 let (tx, rx) = channel::msg_channel().unwrap();
1488 let msg = ApiMsg::GetGlyphDimensions(font, glyph_indices, tx);
1489 self.api_sender.send(msg).unwrap();
1490 rx.recv().unwrap()
1491 }
1492
1493 pub fn get_glyph_indices(&self, font_key: font::FontKey, text: &str) -> Vec<Option<u32>> {
1496 let (tx, rx) = channel::msg_channel().unwrap();
1497 let msg = ApiMsg::GetGlyphIndices(font_key, text.to_string(), tx);
1498 self.api_sender.send(msg).unwrap();
1499 rx.recv().unwrap()
1500 }
1501
1502 pub fn generate_image_key(&self) -> ImageKey {
1504 let new_id = self.next_unique_id();
1505 ImageKey::new(self.namespace_id, new_id)
1506 }
1507
1508 pub fn generate_blob_image_key(&self) -> BlobImageKey {
1510 BlobImageKey(self.generate_image_key())
1511 }
1512
1513 pub fn update_resources(&self, resources: Vec<ResourceUpdate>) {
1515 if resources.is_empty() {
1516 return;
1517 }
1518 self.api_sender
1519 .send(ApiMsg::UpdateResources(resources))
1520 .unwrap();
1521 }
1522
1523 pub fn send_external_event(&self, evt: ExternalEvent) {
1527 let msg = ApiMsg::ExternalEvent(evt);
1528 self.api_sender.send(msg).unwrap();
1529 }
1530
1531 pub fn notify_memory_pressure(&self) {
1534 self.api_sender.send(ApiMsg::MemoryPressure).unwrap();
1535 }
1536
1537 pub fn report_memory(&self) -> MemoryReport {
1539 let (tx, rx) = channel::msg_channel().unwrap();
1540 self.api_sender.send(ApiMsg::ReportMemory(tx)).unwrap();
1541 *rx.recv().unwrap()
1542 }
1543
1544 pub fn set_debug_flags(&self, flags: DebugFlags) {
1546 let cmd = DebugCommand::SetFlags(flags);
1547 self.api_sender.send(ApiMsg::DebugCommand(cmd)).unwrap();
1548 }
1549
1550 pub fn shut_down(&self, synchronously: bool) {
1552 if synchronously {
1553 let (tx, rx) = channel::msg_channel().unwrap();
1554 self.api_sender.send(ApiMsg::ShutDown(Some(tx))).unwrap();
1555 rx.recv().unwrap();
1556 } else {
1557 self.api_sender.send(ApiMsg::ShutDown(None)).unwrap();
1558 }
1559 }
1560
1561 pub fn generate_property_binding_key<T: Copy>(&self) -> PropertyBindingKey<T> {
1564 let new_id = self.next_unique_id();
1565 PropertyBindingKey {
1566 id: PropertyBindingId {
1567 namespace: self.namespace_id,
1568 uid: new_id,
1569 },
1570 _phantom: PhantomData,
1571 }
1572 }
1573
1574 #[inline]
1575 fn next_unique_id(&self) -> u32 {
1576 let ResourceId(id) = self.next_id.get();
1577 self.next_id.set(ResourceId(id + 1));
1578 id
1579 }
1580
1581 #[doc(hidden)]
1583 pub fn send_message(&self, msg: ApiMsg) {
1584 self.api_sender.send(msg).unwrap();
1585 }
1586
1587 #[doc(hidden)]
1589 pub fn send_payload(&self, data: &[u8]) {
1590 self.payload_sender
1591 .send_payload(Payload::from_data(data))
1592 .unwrap();
1593 }
1594
1595 fn send_scene_msg(&self, document_id: DocumentId, msg: SceneMsg) {
1597 self.api_sender
1601 .send(ApiMsg::UpdateDocuments(vec![document_id], vec![TransactionMsg::scene_message(msg)]))
1602 .unwrap()
1603 }
1604
1605 fn send_frame_msg(&self, document_id: DocumentId, msg: FrameMsg) {
1607 self.api_sender
1611 .send(ApiMsg::UpdateDocuments(vec![document_id], vec![TransactionMsg::frame_message(msg)]))
1612 .unwrap()
1613 }
1614
1615 pub fn send_transaction(&self, document_id: DocumentId, transaction: Transaction) {
1617 let (msg, payloads) = transaction.finalize();
1618 for payload in payloads {
1619 self.payload_sender.send_payload(payload).unwrap();
1620 }
1621 self.api_sender.send(ApiMsg::UpdateDocuments(vec![document_id], vec![msg])).unwrap();
1622 }
1623
1624 pub fn send_transactions(&self, document_ids: Vec<DocumentId>, mut transactions: Vec<Transaction>) {
1626 debug_assert!(document_ids.len() == transactions.len());
1627 let length = document_ids.len();
1628 let (msgs, mut document_payloads) = transactions.drain(..)
1629 .fold((Vec::with_capacity(length), Vec::with_capacity(length)),
1630 |(mut msgs, mut document_payloads), transaction| {
1631 let (msg, payloads) = transaction.finalize();
1632 msgs.push(msg);
1633 document_payloads.push(payloads);
1634 (msgs, document_payloads)
1635 });
1636 for payload in document_payloads.drain(..).flatten() {
1637 self.payload_sender.send_payload(payload).unwrap();
1638 }
1639 self.api_sender.send(ApiMsg::UpdateDocuments(document_ids, msgs)).unwrap();
1640 }
1641
1642 pub fn hit_test(&self,
1649 document_id: DocumentId,
1650 pipeline_id: Option<PipelineId>,
1651 point: WorldPoint,
1652 flags: HitTestFlags)
1653 -> HitTestResult {
1654 let (tx, rx) = channel::msg_channel().unwrap();
1655
1656 self.send_frame_msg(
1657 document_id,
1658 FrameMsg::HitTest(pipeline_id, point, flags, tx)
1659 );
1660 rx.recv().unwrap()
1661 }
1662
1663 pub fn set_document_view(
1665 &self,
1666 document_id: DocumentId,
1667 device_rect: DeviceIntRect,
1668 device_pixel_ratio: f32,
1669 ) {
1670 self.send_scene_msg(
1671 document_id,
1672 SceneMsg::SetDocumentView { device_rect, device_pixel_ratio },
1673 );
1674 }
1675
1676 pub fn enable_frame_output(
1680 &self,
1681 document_id: DocumentId,
1682 pipeline_id: PipelineId,
1683 enable: bool,
1684 ) {
1685 self.send_scene_msg(
1686 document_id,
1687 SceneMsg::EnableFrameOutput(pipeline_id, enable),
1688 );
1689 }
1690
1691 pub fn get_scroll_node_state(&self, document_id: DocumentId) -> Vec<ScrollNodeState> {
1693 let (tx, rx) = channel::msg_channel().unwrap();
1694 self.send_frame_msg(document_id, FrameMsg::GetScrollNodeState(tx));
1695 rx.recv().unwrap()
1696 }
1697
1698 #[doc(hidden)]
1701 pub fn wake_scene_builder(&self) {
1702 self.send_message(ApiMsg::WakeSceneBuilder);
1703 }
1704
1705 pub fn flush_scene_builder(&self) {
1709 let (tx, rx) = channel::msg_channel().unwrap();
1710 self.send_message(ApiMsg::FlushSceneBuilder(tx));
1711 rx.recv().unwrap(); }
1713
1714 pub fn save_capture(&self, path: PathBuf, bits: CaptureBits) {
1716 let msg = ApiMsg::DebugCommand(DebugCommand::SaveCapture(path, bits));
1717 self.send_message(msg);
1718 }
1719
1720 pub fn load_capture(&self, path: PathBuf) -> Vec<CapturedDocument> {
1722 self.flush_scene_builder();
1725
1726 let (tx, rx) = channel::msg_channel().unwrap();
1727 let msg = ApiMsg::DebugCommand(DebugCommand::LoadCapture(path, tx));
1728 self.send_message(msg);
1729
1730 let mut documents = Vec::new();
1731 while let Ok(captured_doc) = rx.recv() {
1732 documents.push(captured_doc);
1733 }
1734 documents
1735 }
1736
1737 pub fn send_debug_cmd(&self, cmd: DebugCommand) {
1739 let msg = ApiMsg::DebugCommand(cmd);
1740 self.send_message(msg);
1741 }
1742}
1743
1744impl Drop for RenderApi {
1745 fn drop(&mut self) {
1746 let msg = ApiMsg::ClearNamespace(self.namespace_id);
1747 let _ = self.api_sender.send(msg);
1748 }
1749}
1750
1751#[derive(Clone, Deserialize, Serialize)]
1753pub struct ScrollNodeState {
1754 pub id: di::ExternalScrollId,
1756 pub scroll_offset: LayoutVector2D,
1758}
1759
1760#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
1762pub enum ScrollLocation {
1763 Delta(LayoutVector2D),
1765 Start,
1767 End,
1769}
1770
1771#[derive(Clone, Copy, Serialize, Deserialize, Debug)]
1773pub struct ZoomFactor(f32);
1774
1775impl ZoomFactor {
1776 pub fn new(scale: f32) -> Self {
1778 ZoomFactor(scale)
1779 }
1780
1781 pub fn get(self) -> f32 {
1783 self.0
1784 }
1785}
1786
1787#[repr(C)]
1789#[derive(Clone, Copy, Debug, Default, Deserialize, MallocSizeOf, PartialEq, Serialize, Eq, Hash, PeekPoke)]
1790pub struct PropertyBindingId {
1791 namespace: IdNamespace,
1792 uid: u32,
1793}
1794
1795impl PropertyBindingId {
1796 pub fn new(value: u64) -> Self {
1798 PropertyBindingId {
1799 namespace: IdNamespace((value >> 32) as u32),
1800 uid: value as u32,
1801 }
1802 }
1803}
1804
1805#[repr(C)]
1808#[derive(Clone, Copy, Debug, Default, Deserialize, PartialEq, Serialize, PeekPoke)]
1809pub struct PropertyBindingKey<T> {
1810 pub id: PropertyBindingId,
1812 _phantom: PhantomData<T>,
1813}
1814
1815impl<T: Copy> PropertyBindingKey<T> {
1817 pub fn with(self, value: T) -> PropertyValue<T> {
1819 PropertyValue { key: self, value }
1820 }
1821}
1822
1823impl<T> PropertyBindingKey<T> {
1824 pub fn new(value: u64) -> Self {
1826 PropertyBindingKey {
1827 id: PropertyBindingId::new(value),
1828 _phantom: PhantomData,
1829 }
1830 }
1831}
1832
1833#[repr(C)]
1840#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize, PeekPoke)]
1841pub enum PropertyBinding<T> {
1842 Value(T),
1844 Binding(PropertyBindingKey<T>, T),
1846}
1847
1848impl<T: Default> Default for PropertyBinding<T> {
1849 fn default() -> Self {
1850 PropertyBinding::Value(Default::default())
1851 }
1852}
1853
1854impl<T> From<T> for PropertyBinding<T> {
1855 fn from(value: T) -> PropertyBinding<T> {
1856 PropertyBinding::Value(value)
1857 }
1858}
1859
1860#[derive(Clone, Copy, Debug, Deserialize, Serialize, PartialEq)]
1863pub struct PropertyValue<T> {
1864 pub key: PropertyBindingKey<T>,
1866 pub value: T,
1868}
1869
1870#[derive(Clone, Deserialize, Serialize, Debug, PartialEq, Default)]
1874pub struct DynamicProperties {
1875 pub transforms: Vec<PropertyValue<LayoutTransform>>,
1877 pub floats: Vec<PropertyValue<f32>>,
1879}
1880
1881pub trait RenderNotifier: Send {
1883 fn clone(&self) -> Box<dyn RenderNotifier>;
1885 fn wake_up(&self);
1888 fn new_frame_ready(&self, _: DocumentId, scrolled: bool, composite_needed: bool, render_time_ns: Option<u64>);
1890 fn external_event(&self, _evt: ExternalEvent) {
1894 unimplemented!()
1895 }
1896 fn shut_down(&self) {}
1899}
1900
1901#[repr(u32)]
1903#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
1904pub enum Checkpoint {
1905 SceneBuilt,
1907 FrameBuilt,
1909 FrameTexturesUpdated,
1911 FrameRendered,
1913 TransactionDropped,
1916}
1917
1918pub trait NotificationHandler : Send + Sync {
1921 fn notify(&self, when: Checkpoint);
1923}
1924
1925pub struct NotificationRequest {
1931 handler: Option<Box<dyn NotificationHandler>>,
1932 when: Checkpoint,
1933}
1934
1935impl NotificationRequest {
1936 pub fn new(when: Checkpoint, handler: Box<dyn NotificationHandler>) -> Self {
1938 NotificationRequest {
1939 handler: Some(handler),
1940 when,
1941 }
1942 }
1943
1944 pub fn when(&self) -> Checkpoint { self.when }
1946
1947 pub fn notify(mut self) {
1949 if let Some(handler) = self.handler.take() {
1950 handler.notify(self.when);
1951 }
1952 }
1953}
1954
1955impl Drop for NotificationRequest {
1956 fn drop(&mut self) {
1957 if let Some(ref mut handler) = self.handler {
1958 handler.notify(Checkpoint::TransactionDropped);
1959 }
1960 }
1961}
1962
1963impl Clone for NotificationRequest {
1970 fn clone(&self) -> Self {
1971 NotificationRequest {
1972 when: self.when,
1973 handler: None,
1974 }
1975 }
1976}