1#![deny(missing_docs)]
6
7use std::cell::Cell;
8use std::fmt;
9use std::marker::PhantomData;
10use std::path::PathBuf;
11use std::sync::Arc;
12use std::u32;
13use api::{MinimapData, SnapshotImageKey};
14use crate::util::precise_time_ns;
15use crate::api::channel::{Sender, single_msg_channel, unbounded_channel};
16use crate::api::{BuiltDisplayList, IdNamespace, ExternalScrollId, Parameter, BoolParameter};
17use crate::api::{FontKey, FontInstanceKey, NativeFontHandle};
18use crate::api::{BlobImageData, BlobImageKey, ImageData, ImageDescriptor, ImageKey, Epoch, QualitySettings};
19use crate::api::{BlobImageParams, BlobImageRequest, BlobImageResult, AsyncBlobImageRasterizer, BlobImageHandler};
20use crate::api::{DocumentId, PipelineId, PropertyBindingId, PropertyBindingKey, ExternalEvent};
21use crate::api::{HitTestResult, HitTesterRequest, ApiHitTester, PropertyValue, DynamicProperties};
22use crate::api::{SampledScrollOffset, TileSize, NotificationRequest, DebugFlags};
23use crate::api::{GlyphDimensionRequest, GlyphIndexRequest, GlyphIndex, GlyphDimensions};
24use crate::api::{FontInstanceOptions, FontInstancePlatformOptions, FontVariation, RenderReasons};
25use crate::api::DEFAULT_TILE_SIZE;
26use crate::api::units::*;
27use crate::api_resources::ApiResources;
28use glyph_rasterizer::SharedFontResources;
29use crate::scene_builder_thread::{SceneBuilderRequest, SceneBuilderResult};
30use crate::intern::InterningMemoryReport;
31use crate::profiler::{self, TransactionProfile};
32
33#[repr(C)]
34#[derive(Clone, Copy, Debug)]
35#[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
36struct ResourceId(pub u32);
37
38#[derive(Clone)]
42#[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
43pub enum ResourceUpdate {
44 AddImage(AddImage),
46 UpdateImage(UpdateImage),
48 DeleteImage(ImageKey),
54 AddBlobImage(AddBlobImage),
56 UpdateBlobImage(UpdateBlobImage),
58 DeleteBlobImage(BlobImageKey),
60 SetBlobImageVisibleArea(BlobImageKey, DeviceIntRect),
62 AddSnapshotImage(AddSnapshotImage),
64 DeleteSnapshotImage(SnapshotImageKey),
66 AddFont(AddFont),
68 DeleteFont(FontKey),
74 AddFontInstance(AddFontInstance),
76 DeleteFontInstance(FontInstanceKey),
82}
83
84impl fmt::Debug for ResourceUpdate {
85 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86 match self {
87 ResourceUpdate::AddImage(ref i) => f.write_fmt(format_args!(
88 "ResourceUpdate::AddImage size({:?})",
89 &i.descriptor.size
90 )),
91 ResourceUpdate::UpdateImage(ref i) => f.write_fmt(format_args!(
92 "ResourceUpdate::UpdateImage size({:?})",
93 &i.descriptor.size
94 )),
95 ResourceUpdate::AddBlobImage(ref i) => f.write_fmt(format_args!(
96 "ResourceUFpdate::AddBlobImage size({:?})",
97 &i.descriptor.size
98 )),
99 ResourceUpdate::UpdateBlobImage(i) => f.write_fmt(format_args!(
100 "ResourceUpdate::UpdateBlobImage size({:?})",
101 &i.descriptor.size
102 )),
103 ResourceUpdate::DeleteImage(..) => f.write_str("ResourceUpdate::DeleteImage"),
104 ResourceUpdate::DeleteBlobImage(..) => f.write_str("ResourceUpdate::DeleteBlobImage"),
105 ResourceUpdate::SetBlobImageVisibleArea(..) => f.write_str("ResourceUpdate::SetBlobImageVisibleArea"),
106 ResourceUpdate::AddSnapshotImage(..) => f.write_str("ResourceUpdate::AddSnapshotImage"),
107 ResourceUpdate::DeleteSnapshotImage(..) => f.write_str("ResourceUpdate::DeleteSnapshotImage"),
108 ResourceUpdate::AddFont(..) => f.write_str("ResourceUpdate::AddFont"),
109 ResourceUpdate::DeleteFont(..) => f.write_str("ResourceUpdate::DeleteFont"),
110 ResourceUpdate::AddFontInstance(..) => f.write_str("ResourceUpdate::AddFontInstance"),
111 ResourceUpdate::DeleteFontInstance(..) => f.write_str("ResourceUpdate::DeleteFontInstance"),
112 }
113 }
114}
115
116#[derive(Clone, Debug)]
119pub enum GenerateFrame {
120 Yes {
122 id: u64,
125 present: bool,
128 },
129 No,
131}
132
133impl GenerateFrame {
134 pub fn as_bool(&self) -> bool {
136 match self {
137 GenerateFrame::Yes { .. } => true,
138 GenerateFrame::No => false,
139 }
140 }
141
142 pub fn present(&self) -> bool {
145 match self {
146 GenerateFrame::Yes { present, .. } => *present,
147 GenerateFrame::No => false,
148 }
149 }
150
151 pub fn id(&self) -> Option<u64> {
153 match self {
154 GenerateFrame::Yes { id, .. } => Some(*id),
155 GenerateFrame::No => None,
156 }
157 }
158}
159
160pub struct Transaction {
167 scene_ops: Vec<SceneMsg>,
169 frame_ops: Vec<FrameMsg>,
171
172 notifications: Vec<NotificationRequest>,
173
174 pub resource_updates: Vec<ResourceUpdate>,
176
177 use_scene_builder_thread: bool,
185
186 generate_frame: GenerateFrame,
190
191 creation_time: u64,
193
194 pub invalidate_rendered_frame: bool,
197
198 low_priority: bool,
199
200 pub render_reasons: RenderReasons,
202}
203
204impl Transaction {
205 pub fn new() -> Self {
207 Transaction {
208 scene_ops: Vec::new(),
209 frame_ops: Vec::new(),
210 resource_updates: Vec::new(),
211 notifications: Vec::new(),
212 use_scene_builder_thread: true,
213 generate_frame: GenerateFrame::No,
214 creation_time: precise_time_ns(),
215 invalidate_rendered_frame: false,
216 low_priority: false,
217 render_reasons: RenderReasons::empty(),
218 }
219 }
220
221 pub fn skip_scene_builder(&mut self) {
230 self.use_scene_builder_thread = false;
231 }
232
233 pub fn use_scene_builder_thread(&mut self) {
235 self.use_scene_builder_thread = true;
236 }
237
238 pub fn is_empty(&self) -> bool {
240 !self.generate_frame.as_bool() &&
241 !self.invalidate_rendered_frame &&
242 self.scene_ops.is_empty() &&
243 self.frame_ops.is_empty() &&
244 self.resource_updates.is_empty() &&
245 self.notifications.is_empty()
246 }
247
248 pub fn update_epoch(&mut self, pipeline_id: PipelineId, epoch: Epoch) {
250 self.scene_ops.push(SceneMsg::UpdateEpoch(pipeline_id, epoch));
253 self.frame_ops.push(FrameMsg::UpdateEpoch(pipeline_id, epoch));
256 }
260
261 pub fn set_root_pipeline(&mut self, pipeline_id: PipelineId) {
276 self.scene_ops.push(SceneMsg::SetRootPipeline(pipeline_id));
277 }
278
279 pub fn remove_pipeline(&mut self, pipeline_id: PipelineId) {
283 self.scene_ops.push(SceneMsg::RemovePipeline(pipeline_id));
284 }
285
286 pub fn set_display_list(
298 &mut self,
299 epoch: Epoch,
300 (pipeline_id, mut display_list): (PipelineId, BuiltDisplayList),
301 ) {
302 display_list.set_send_time_ns(precise_time_ns());
303 self.scene_ops.push(
304 SceneMsg::SetDisplayList {
305 display_list,
306 epoch,
307 pipeline_id,
308 }
309 );
310 }
311
312 pub fn update_resources(&mut self, mut resources: Vec<ResourceUpdate>) {
314 self.resource_updates.append(&mut resources);
315 }
316
317 pub fn notify(&mut self, event: NotificationRequest) {
329 self.notifications.push(event);
330 }
331
332 pub fn set_document_view(
334 &mut self,
335 device_rect: DeviceIntRect,
336 ) {
337 window_size_sanity_check(device_rect.size());
338 self.scene_ops.push(
339 SceneMsg::SetDocumentView {
340 device_rect,
341 },
342 );
343 }
344
345 pub fn set_scroll_offsets(
349 &mut self,
350 id: ExternalScrollId,
351 sampled_scroll_offsets: Vec<SampledScrollOffset>,
352 ) {
353 self.frame_ops.push(FrameMsg::SetScrollOffsets(id, sampled_scroll_offsets));
354 }
355
356 pub fn set_quality_settings(&mut self, settings: QualitySettings) {
358 self.scene_ops.push(SceneMsg::SetQualitySettings { settings });
359 }
360
361 pub fn set_is_transform_async_zooming(&mut self, is_zooming: bool, animation_id: PropertyBindingId) {
363 self.frame_ops.push(FrameMsg::SetIsTransformAsyncZooming(is_zooming, animation_id));
364 }
365
366 pub fn set_minimap_data(&mut self, id: ExternalScrollId, minimap_data: MinimapData) {
368 self.frame_ops.push(FrameMsg::SetMinimapData(id, minimap_data));
369 }
370
371 pub fn generate_frame(&mut self, id: u64, present: bool, reasons: RenderReasons) {
379 self.generate_frame = GenerateFrame::Yes{ id, present };
380 self.render_reasons |= reasons;
381 }
382
383 pub fn invalidate_rendered_frame(&mut self, reasons: RenderReasons) {
390 self.invalidate_rendered_frame = true;
391 self.render_reasons |= reasons
392 }
393
394 pub fn reset_dynamic_properties(&mut self) {
397 self.frame_ops.push(FrameMsg::ResetDynamicProperties);
398 }
399
400 pub fn append_dynamic_properties(&mut self, properties: DynamicProperties) {
403 self.frame_ops.push(FrameMsg::AppendDynamicProperties(properties));
404 }
405
406 pub fn append_dynamic_transform_properties(&mut self, transforms: Vec<PropertyValue<LayoutTransform>>) {
411 self.frame_ops.push(FrameMsg::AppendDynamicTransformProperties(transforms));
412 }
413
414 pub fn get_frame_ops(self) -> Vec<FrameMsg> {
416 self.frame_ops
417 }
418
419 fn finalize(self, document_id: DocumentId) -> Box<TransactionMsg> {
420 Box::new(TransactionMsg {
421 document_id,
422 scene_ops: self.scene_ops,
423 frame_ops: self.frame_ops,
424 resource_updates: self.resource_updates,
425 notifications: self.notifications,
426 use_scene_builder_thread: self.use_scene_builder_thread,
427 generate_frame: self.generate_frame,
428 creation_time: Some(self.creation_time),
429 invalidate_rendered_frame: self.invalidate_rendered_frame,
430 low_priority: self.low_priority,
431 blob_rasterizer: None,
432 blob_requests: Vec::new(),
433 rasterized_blobs: Vec::new(),
434 profile: TransactionProfile::new(),
435 render_reasons: self.render_reasons,
436 })
437 }
438
439 pub fn add_image(
441 &mut self,
442 key: ImageKey,
443 descriptor: ImageDescriptor,
444 data: ImageData,
445 tiling: Option<TileSize>,
446 ) {
447 self.resource_updates.push(ResourceUpdate::AddImage(AddImage {
448 key,
449 descriptor,
450 data,
451 tiling,
452 }));
453 }
454
455 pub fn update_image(
457 &mut self,
458 key: ImageKey,
459 descriptor: ImageDescriptor,
460 data: ImageData,
461 dirty_rect: &ImageDirtyRect,
462 ) {
463 self.resource_updates.push(ResourceUpdate::UpdateImage(UpdateImage {
464 key,
465 descriptor,
466 data,
467 dirty_rect: *dirty_rect,
468 }));
469 }
470
471 pub fn delete_image(&mut self, key: ImageKey) {
473 self.resource_updates.push(ResourceUpdate::DeleteImage(key));
474 }
475
476 pub fn add_blob_image(
478 &mut self,
479 key: BlobImageKey,
480 descriptor: ImageDescriptor,
481 data: Arc<BlobImageData>,
482 visible_rect: DeviceIntRect,
483 tile_size: Option<TileSize>,
484 ) {
485 self.resource_updates.push(
486 ResourceUpdate::AddBlobImage(AddBlobImage {
487 key,
488 descriptor,
489 data,
490 visible_rect,
491 tile_size: tile_size.unwrap_or(DEFAULT_TILE_SIZE),
492 })
493 );
494 }
495
496 pub fn update_blob_image(
498 &mut self,
499 key: BlobImageKey,
500 descriptor: ImageDescriptor,
501 data: Arc<BlobImageData>,
502 visible_rect: DeviceIntRect,
503 dirty_rect: &BlobDirtyRect,
504 ) {
505 self.resource_updates.push(
506 ResourceUpdate::UpdateBlobImage(UpdateBlobImage {
507 key,
508 descriptor,
509 data,
510 visible_rect,
511 dirty_rect: *dirty_rect,
512 })
513 );
514 }
515
516 pub fn delete_blob_image(&mut self, key: BlobImageKey) {
518 self.resource_updates.push(ResourceUpdate::DeleteBlobImage(key));
519 }
520
521 pub fn set_blob_image_visible_area(&mut self, key: BlobImageKey, area: DeviceIntRect) {
523 self.resource_updates.push(ResourceUpdate::SetBlobImageVisibleArea(key, area));
524 }
525
526 pub fn add_snapshot_image(
528 &mut self,
529 key: SnapshotImageKey,
530 ) {
531 self.resource_updates.push(
532 ResourceUpdate::AddSnapshotImage(AddSnapshotImage { key })
533 );
534 }
535
536 pub fn delete_snapshot_image(&mut self, key: SnapshotImageKey) {
538 self.resource_updates.push(ResourceUpdate::DeleteSnapshotImage(key));
539 }
540
541 pub fn add_raw_font(&mut self, key: FontKey, bytes: Vec<u8>, index: u32) {
543 self.resource_updates
544 .push(ResourceUpdate::AddFont(AddFont::Raw(key, Arc::new(bytes), index)));
545 }
546
547 pub fn add_native_font(&mut self, key: FontKey, native_handle: NativeFontHandle) {
549 self.resource_updates
550 .push(ResourceUpdate::AddFont(AddFont::Native(key, native_handle)));
551 }
552
553 pub fn delete_font(&mut self, key: FontKey) {
555 self.resource_updates.push(ResourceUpdate::DeleteFont(key));
556 }
557
558 pub fn add_font_instance(
560 &mut self,
561 key: FontInstanceKey,
562 font_key: FontKey,
563 glyph_size: f32,
564 options: Option<FontInstanceOptions>,
565 platform_options: Option<FontInstancePlatformOptions>,
566 variations: Vec<FontVariation>,
567 ) {
568 self.resource_updates
569 .push(ResourceUpdate::AddFontInstance(AddFontInstance {
570 key,
571 font_key,
572 glyph_size,
573 options,
574 platform_options,
575 variations,
576 }));
577 }
578
579 pub fn delete_font_instance(&mut self, key: FontInstanceKey) {
581 self.resource_updates.push(ResourceUpdate::DeleteFontInstance(key));
582 }
583
584 pub fn set_low_priority(&mut self, low_priority: bool) {
589 self.low_priority = low_priority;
590 }
591
592 pub fn is_low_priority(&self) -> bool {
594 self.low_priority
595 }
596
597 pub fn render_offscreen(&mut self, pipeline_id: PipelineId) {
602 self.scene_ops.push(SceneMsg::RenderOffscreen(pipeline_id));
603 }
604}
605
606pub struct DocumentTransaction {
608 pub document_id: DocumentId,
610 pub transaction: Transaction,
612}
613
614pub struct TransactionMsg {
616 pub document_id: DocumentId,
618 pub scene_ops: Vec<SceneMsg>,
620 pub frame_ops: Vec<FrameMsg>,
622 pub resource_updates: Vec<ResourceUpdate>,
624 pub generate_frame: GenerateFrame,
626 pub creation_time: Option<u64>,
628 pub invalidate_rendered_frame: bool,
631 pub use_scene_builder_thread: bool,
633 pub low_priority: bool,
635
636 pub notifications: Vec<NotificationRequest>,
638 pub blob_rasterizer: Option<Box<dyn AsyncBlobImageRasterizer>>,
640 pub blob_requests: Vec<BlobImageParams>,
642 pub rasterized_blobs: Vec<(BlobImageRequest, BlobImageResult)>,
644 pub profile: TransactionProfile,
646 pub render_reasons: RenderReasons,
648}
649
650impl fmt::Debug for TransactionMsg {
651 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
652 writeln!(f, "threaded={}, genframe={:?}, invalidate={}, low_priority={}",
653 self.use_scene_builder_thread,
654 self.generate_frame,
655 self.invalidate_rendered_frame,
656 self.low_priority,
657 ).unwrap();
658 for scene_op in &self.scene_ops {
659 writeln!(f, "\t\t{:?}", scene_op).unwrap();
660 }
661
662 for frame_op in &self.frame_ops {
663 writeln!(f, "\t\t{:?}", frame_op).unwrap();
664 }
665
666 for resource_update in &self.resource_updates {
667 writeln!(f, "\t\t{:?}", resource_update).unwrap();
668 }
669 Ok(())
670 }
671}
672
673impl TransactionMsg {
674 pub fn is_empty(&self) -> bool {
676 !self.generate_frame.as_bool() &&
677 !self.invalidate_rendered_frame &&
678 self.scene_ops.is_empty() &&
679 self.frame_ops.is_empty() &&
680 self.resource_updates.is_empty() &&
681 self.notifications.is_empty()
682 }
683}
684
685#[derive(Clone)]
689#[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
690pub struct AddImage {
691 pub key: ImageKey,
693 pub descriptor: ImageDescriptor,
695 pub data: ImageData,
697 pub tiling: Option<TileSize>,
703}
704
705#[derive(Clone)]
707#[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
708pub struct UpdateImage {
709 pub key: ImageKey,
711 pub descriptor: ImageDescriptor,
713 pub data: ImageData,
715 pub dirty_rect: ImageDirtyRect,
720}
721
722#[derive(Clone)]
726#[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
727pub struct AddBlobImage {
728 pub key: BlobImageKey,
730 pub descriptor: ImageDescriptor,
732 pub data: Arc<BlobImageData>,
734 pub visible_rect: DeviceIntRect,
743 pub tile_size: TileSize,
749}
750
751#[derive(Clone)]
753#[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
754pub struct UpdateBlobImage {
755 pub key: BlobImageKey,
757 pub descriptor: ImageDescriptor,
759 pub data: Arc<BlobImageData>,
761 pub visible_rect: DeviceIntRect,
763 pub dirty_rect: BlobDirtyRect,
766}
767
768#[derive(Clone)]
772#[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
773pub struct AddSnapshotImage {
774 pub key: SnapshotImageKey,
776}
777
778#[derive(Clone)]
783#[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
784pub enum AddFont {
785 Raw(FontKey, Arc<Vec<u8>>, u32),
787 Native(FontKey, NativeFontHandle),
789}
790
791#[derive(Clone)]
796#[cfg_attr(any(feature = "serde"), derive(Deserialize, Serialize))]
797pub struct AddFontInstance {
798 pub key: FontInstanceKey,
800 pub font_key: FontKey,
802 pub glyph_size: f32,
804 pub options: Option<FontInstanceOptions>,
806 pub platform_options: Option<FontInstancePlatformOptions>,
808 pub variations: Vec<FontVariation>,
810}
811
812pub enum SceneMsg {
814 UpdateEpoch(PipelineId, Epoch),
816 SetRootPipeline(PipelineId),
818 RemovePipeline(PipelineId),
820 SetDisplayList {
822 display_list: BuiltDisplayList,
824 epoch: Epoch,
826 pipeline_id: PipelineId,
828 },
829 RenderOffscreen(PipelineId),
834 SetDocumentView {
836 device_rect: DeviceIntRect,
838 },
839 SetQualitySettings {
841 settings: QualitySettings,
843 },
844}
845
846pub enum FrameMsg {
848 UpdateEpoch(PipelineId, Epoch),
850 HitTest(WorldPoint, Sender<HitTestResult>),
852 RequestHitTester(Sender<Arc<dyn ApiHitTester>>),
854 SetScrollOffsets(ExternalScrollId, Vec<SampledScrollOffset>),
856 ResetDynamicProperties,
858 AppendDynamicProperties(DynamicProperties),
860 AppendDynamicTransformProperties(Vec<PropertyValue<LayoutTransform>>),
862 SetIsTransformAsyncZooming(bool, PropertyBindingId),
864 SetMinimapData(ExternalScrollId, MinimapData)
866}
867
868impl fmt::Debug for SceneMsg {
869 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
870 f.write_str(match *self {
871 SceneMsg::UpdateEpoch(..) => "SceneMsg::UpdateEpoch",
872 SceneMsg::SetDisplayList { .. } => "SceneMsg::SetDisplayList",
873 SceneMsg::RemovePipeline(..) => "SceneMsg::RemovePipeline",
874 SceneMsg::SetDocumentView { .. } => "SceneMsg::SetDocumentView",
875 SceneMsg::SetRootPipeline(..) => "SceneMsg::SetRootPipeline",
876 SceneMsg::SetQualitySettings { .. } => "SceneMsg::SetQualitySettings",
877 SceneMsg::RenderOffscreen(..) => "SceneMsg::BuildOffscreen",
878 })
879 }
880}
881
882impl fmt::Debug for FrameMsg {
883 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
884 f.write_str(match *self {
885 FrameMsg::UpdateEpoch(..) => "FrameMsg::UpdateEpoch",
886 FrameMsg::HitTest(..) => "FrameMsg::HitTest",
887 FrameMsg::RequestHitTester(..) => "FrameMsg::RequestHitTester",
888 FrameMsg::SetScrollOffsets(..) => "FrameMsg::SetScrollOffsets",
889 FrameMsg::ResetDynamicProperties => "FrameMsg::ResetDynamicProperties",
890 FrameMsg::AppendDynamicProperties(..) => "FrameMsg::AppendDynamicProperties",
891 FrameMsg::AppendDynamicTransformProperties(..) => "FrameMsg::AppendDynamicTransformProperties",
892 FrameMsg::SetIsTransformAsyncZooming(..) => "FrameMsg::SetIsTransformAsyncZooming",
893 FrameMsg::SetMinimapData(..) => "FrameMsg::SetMinimapData",
894 })
895 }
896}
897
898bitflags!{
899 #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
902 pub struct CaptureBits: u8 {
903 const SCENE = 0x1;
905 const FRAME = 0x2;
907 const TILE_CACHE = 0x4;
909 const EXTERNAL_RESOURCES = 0x8;
911 }
912}
913
914bitflags!{
915 #[derive(Debug, Copy, PartialEq, Eq, Clone, PartialOrd, Ord, Hash)]
917 pub struct ClearCache: u8 {
918 const IMAGES = 0b1;
920 const GLYPHS = 0b10;
922 const GLYPH_DIMENSIONS = 0b100;
924 const RENDER_TASKS = 0b1000;
926 const TEXTURE_CACHE = 0b10000;
928 const RENDER_TARGETS = 0b100000;
930 }
931}
932
933#[derive(Clone, Debug)]
936pub struct CapturedDocument {
937 pub document_id: DocumentId,
939 pub root_pipeline_id: Option<PipelineId>,
941}
942
943#[derive(Clone)]
945pub enum DebugCommand {
946 SetFlags(DebugFlags),
948 SaveCapture(PathBuf, CaptureBits),
950 LoadCapture(PathBuf, Option<(u32, u32)>, Sender<CapturedDocument>),
952 StartCaptureSequence(PathBuf, CaptureBits),
954 StopCaptureSequence,
956 ClearCaches(ClearCache),
958 EnableNativeCompositor(bool),
960 SetBatchingLookback(u32),
962 InvalidateGpuCache,
964 SimulateLongSceneBuild(u32),
967 SetPictureTileSize(Option<DeviceIntSize>),
969 SetMaximumSurfaceSize(Option<usize>),
971}
972
973pub enum ApiMsg {
975 CloneApi(Sender<IdNamespace>),
977 CloneApiByClient(IdNamespace),
979 AddDocument(DocumentId, DeviceIntSize),
981 UpdateDocuments(Vec<Box<TransactionMsg>>),
983 MemoryPressure,
985 ReportMemory(Sender<Box<MemoryReport>>),
987 DebugCommand(DebugCommand),
989 SceneBuilderResult(SceneBuilderResult),
991}
992
993impl fmt::Debug for ApiMsg {
994 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
995 f.write_str(match *self {
996 ApiMsg::CloneApi(..) => "ApiMsg::CloneApi",
997 ApiMsg::CloneApiByClient(..) => "ApiMsg::CloneApiByClient",
998 ApiMsg::AddDocument(..) => "ApiMsg::AddDocument",
999 ApiMsg::UpdateDocuments(..) => "ApiMsg::UpdateDocuments",
1000 ApiMsg::MemoryPressure => "ApiMsg::MemoryPressure",
1001 ApiMsg::ReportMemory(..) => "ApiMsg::ReportMemory",
1002 ApiMsg::DebugCommand(..) => "ApiMsg::DebugCommand",
1003 ApiMsg::SceneBuilderResult(..) => "ApiMsg::SceneBuilderResult",
1004 })
1005 }
1006}
1007
1008pub struct RenderApiSender {
1013 api_sender: Sender<ApiMsg>,
1014 scene_sender: Sender<SceneBuilderRequest>,
1015 low_priority_scene_sender: Sender<SceneBuilderRequest>,
1016 blob_image_handler: Option<Box<dyn BlobImageHandler>>,
1017 fonts: SharedFontResources,
1018}
1019
1020impl RenderApiSender {
1021 pub fn new(
1023 api_sender: Sender<ApiMsg>,
1024 scene_sender: Sender<SceneBuilderRequest>,
1025 low_priority_scene_sender: Sender<SceneBuilderRequest>,
1026 blob_image_handler: Option<Box<dyn BlobImageHandler>>,
1027 fonts: SharedFontResources,
1028 ) -> Self {
1029 RenderApiSender {
1030 api_sender,
1031 scene_sender,
1032 low_priority_scene_sender,
1033 blob_image_handler,
1034 fonts,
1035 }
1036 }
1037
1038 pub fn create_api(&self) -> RenderApi {
1040 let (sync_tx, sync_rx) = single_msg_channel();
1041 let msg = ApiMsg::CloneApi(sync_tx);
1042 self.api_sender.send(msg).expect("Failed to send CloneApi message");
1043 let namespace_id = sync_rx.recv().expect("Failed to receive CloneApi reply");
1044 RenderApi {
1045 api_sender: self.api_sender.clone(),
1046 scene_sender: self.scene_sender.clone(),
1047 low_priority_scene_sender: self.low_priority_scene_sender.clone(),
1048 namespace_id,
1049 next_id: Cell::new(ResourceId(0)),
1050 resources: ApiResources::new(
1051 self.blob_image_handler.as_ref().map(|handler| handler.create_similar()),
1052 self.fonts.clone(),
1053 ),
1054 }
1055 }
1056
1057 pub fn create_api_by_client(&self, namespace_id: IdNamespace) -> RenderApi {
1063 let msg = ApiMsg::CloneApiByClient(namespace_id);
1064 self.api_sender.send(msg).expect("Failed to send CloneApiByClient message");
1065 RenderApi {
1066 api_sender: self.api_sender.clone(),
1067 scene_sender: self.scene_sender.clone(),
1068 low_priority_scene_sender: self.low_priority_scene_sender.clone(),
1069 namespace_id,
1070 next_id: Cell::new(ResourceId(0)),
1071 resources: ApiResources::new(
1072 self.blob_image_handler.as_ref().map(|handler| handler.create_similar()),
1073 self.fonts.clone(),
1074 ),
1075 }
1076 }
1077}
1078
1079pub struct RenderApi {
1081 api_sender: Sender<ApiMsg>,
1082 scene_sender: Sender<SceneBuilderRequest>,
1083 low_priority_scene_sender: Sender<SceneBuilderRequest>,
1084 namespace_id: IdNamespace,
1085 next_id: Cell<ResourceId>,
1086 resources: ApiResources,
1087}
1088
1089impl RenderApi {
1090 pub fn get_namespace_id(&self) -> IdNamespace {
1092 self.namespace_id
1093 }
1094
1095 pub fn create_sender(&self) -> RenderApiSender {
1097 RenderApiSender::new(
1098 self.api_sender.clone(),
1099 self.scene_sender.clone(),
1100 self.low_priority_scene_sender.clone(),
1101 self.resources.blob_image_handler.as_ref().map(|handler| handler.create_similar()),
1102 self.resources.get_fonts(),
1103 )
1104 }
1105
1106 pub fn add_document(&self, initial_size: DeviceIntSize) -> DocumentId {
1112 let new_id = self.next_unique_id();
1113 self.add_document_with_id(initial_size, new_id)
1114 }
1115
1116 pub fn add_document_with_id(&self,
1118 initial_size: DeviceIntSize,
1119 id: u32) -> DocumentId {
1120 window_size_sanity_check(initial_size);
1121
1122 let document_id = DocumentId::new(self.namespace_id, id);
1123
1124 self.api_sender.send(
1130 ApiMsg::AddDocument(document_id, initial_size)
1131 ).unwrap();
1132 self.scene_sender.send(
1133 SceneBuilderRequest::AddDocument(document_id, initial_size)
1134 ).unwrap();
1135
1136 document_id
1137 }
1138
1139 pub fn delete_document(&self, document_id: DocumentId) {
1141 self.low_priority_scene_sender.send(
1142 SceneBuilderRequest::DeleteDocument(document_id)
1143 ).unwrap();
1144 }
1145
1146 pub fn generate_font_key(&self) -> FontKey {
1148 let new_id = self.next_unique_id();
1149 FontKey::new(self.namespace_id, new_id)
1150 }
1151
1152 pub fn generate_font_instance_key(&self) -> FontInstanceKey {
1154 let new_id = self.next_unique_id();
1155 FontInstanceKey::new(self.namespace_id, new_id)
1156 }
1157
1158 pub fn get_glyph_dimensions(
1164 &self,
1165 key: FontInstanceKey,
1166 glyph_indices: Vec<GlyphIndex>,
1167 ) -> Vec<Option<GlyphDimensions>> {
1168 let (sender, rx) = single_msg_channel();
1169 let msg = SceneBuilderRequest::GetGlyphDimensions(GlyphDimensionRequest {
1170 key,
1171 glyph_indices,
1172 sender
1173 });
1174 self.low_priority_scene_sender.send(msg).unwrap();
1175 rx.recv().unwrap()
1176 }
1177
1178 pub fn get_glyph_indices(&self, key: FontKey, text: &str) -> Vec<Option<u32>> {
1181 let (sender, rx) = single_msg_channel();
1182 let msg = SceneBuilderRequest::GetGlyphIndices(GlyphIndexRequest {
1183 key,
1184 text: text.to_string(),
1185 sender,
1186 });
1187 self.low_priority_scene_sender.send(msg).unwrap();
1188 rx.recv().unwrap()
1189 }
1190
1191 pub fn generate_image_key(&self) -> ImageKey {
1193 let new_id = self.next_unique_id();
1194 ImageKey::new(self.namespace_id, new_id)
1195 }
1196
1197 pub fn generate_blob_image_key(&self) -> BlobImageKey {
1199 BlobImageKey(self.generate_image_key())
1200 }
1201
1202 pub fn send_external_event(&self, evt: ExternalEvent) {
1206 let msg = SceneBuilderRequest::ExternalEvent(evt);
1207 self.low_priority_scene_sender.send(msg).unwrap();
1208 }
1209
1210 pub fn notify_memory_pressure(&self) {
1213 self.api_sender.send(ApiMsg::MemoryPressure).unwrap();
1214 }
1215
1216 pub fn report_memory(&self, _ops: malloc_size_of::MallocSizeOfOps) -> MemoryReport {
1218 let (tx, rx) = single_msg_channel();
1219 self.api_sender.send(ApiMsg::ReportMemory(tx)).unwrap();
1220 *rx.recv().unwrap()
1221 }
1222
1223 pub fn set_debug_flags(&mut self, flags: DebugFlags) {
1225 self.resources.set_debug_flags(flags);
1226 let cmd = DebugCommand::SetFlags(flags);
1227 self.api_sender.send(ApiMsg::DebugCommand(cmd)).unwrap();
1228 self.scene_sender.send(SceneBuilderRequest ::SetFlags(flags)).unwrap();
1229 self.low_priority_scene_sender.send(SceneBuilderRequest ::SetFlags(flags)).unwrap();
1230 }
1231
1232 pub fn stop_render_backend(&self) {
1234 self.low_priority_scene_sender.send(SceneBuilderRequest::StopRenderBackend).unwrap();
1235 }
1236
1237 pub fn shut_down(&self, synchronously: bool) {
1239 if synchronously {
1240 let (tx, rx) = single_msg_channel();
1241 self.low_priority_scene_sender.send(SceneBuilderRequest::ShutDown(Some(tx))).unwrap();
1242 rx.recv().unwrap();
1243 } else {
1244 self.low_priority_scene_sender.send(SceneBuilderRequest::ShutDown(None)).unwrap();
1245 }
1246 }
1247
1248 pub fn generate_property_binding_key<T: Copy>(&self) -> PropertyBindingKey<T> {
1251 let new_id = self.next_unique_id();
1252 PropertyBindingKey {
1253 id: PropertyBindingId {
1254 namespace: self.namespace_id,
1255 uid: new_id,
1256 },
1257 _phantom: PhantomData,
1258 }
1259 }
1260
1261 #[inline]
1262 fn next_unique_id(&self) -> u32 {
1263 let ResourceId(id) = self.next_id.get();
1264 self.next_id.set(ResourceId(id + 1));
1265 id
1266 }
1267
1268 #[doc(hidden)]
1270 pub fn send_message(&self, msg: ApiMsg) {
1271 self.api_sender.send(msg).unwrap();
1272 }
1273
1274 fn frame_message(&self, msg: FrameMsg, document_id: DocumentId) -> Box<TransactionMsg> {
1276 Box::new(TransactionMsg {
1277 document_id,
1278 scene_ops: Vec::new(),
1279 frame_ops: vec![msg],
1280 resource_updates: Vec::new(),
1281 notifications: Vec::new(),
1282 generate_frame: GenerateFrame::No,
1283 creation_time: None,
1284 invalidate_rendered_frame: false,
1285 use_scene_builder_thread: false,
1286 low_priority: false,
1287 blob_rasterizer: None,
1288 blob_requests: Vec::new(),
1289 rasterized_blobs: Vec::new(),
1290 profile: TransactionProfile::new(),
1291 render_reasons: RenderReasons::empty(),
1292 })
1293 }
1294
1295 fn send_frame_msg(&self, document_id: DocumentId, msg: FrameMsg) {
1297 self.api_sender
1301 .send(ApiMsg::UpdateDocuments(vec![self.frame_message(msg, document_id)]))
1302 .unwrap()
1303 }
1304
1305 pub fn send_transaction(&mut self, document_id: DocumentId, transaction: Transaction) {
1307 let mut transaction = transaction.finalize(document_id);
1308
1309 self.resources.update(&mut transaction);
1310
1311 if transaction.generate_frame.as_bool() {
1312 transaction.profile.start_time(profiler::API_SEND_TIME);
1313 transaction.profile.start_time(profiler::TOTAL_FRAME_CPU_TIME);
1314 }
1315
1316 if transaction.use_scene_builder_thread {
1317 let sender = if transaction.low_priority {
1318 &mut self.low_priority_scene_sender
1319 } else {
1320 &mut self.scene_sender
1321 };
1322
1323 sender.send(SceneBuilderRequest::Transactions(vec![transaction]))
1324 .expect("send by scene sender failed");
1325 } else {
1326 self.api_sender.send(ApiMsg::UpdateDocuments(vec![transaction]))
1327 .expect("send by api sender failed");
1328 }
1329 }
1330
1331 pub fn hit_test(&self,
1337 document_id: DocumentId,
1338 point: WorldPoint,
1339 ) -> HitTestResult {
1340 let (tx, rx) = single_msg_channel();
1341
1342 self.send_frame_msg(
1343 document_id,
1344 FrameMsg::HitTest(point, tx)
1345 );
1346 rx.recv().unwrap()
1347 }
1348
1349 pub fn request_hit_tester(&self, document_id: DocumentId) -> HitTesterRequest {
1351 let (tx, rx) = single_msg_channel();
1352 self.send_frame_msg(
1353 document_id,
1354 FrameMsg::RequestHitTester(tx)
1355 );
1356
1357 HitTesterRequest { rx }
1358 }
1359
1360 #[doc(hidden)]
1363 pub fn wake_scene_builder(&self) {
1364 self.scene_sender.send(SceneBuilderRequest::WakeUp).unwrap();
1365 }
1366
1367 pub fn flush_scene_builder(&self) {
1371 let (tx, rx) = single_msg_channel();
1372 self.low_priority_scene_sender.send(SceneBuilderRequest::Flush(tx)).unwrap();
1373 rx.recv().unwrap(); }
1375
1376 pub fn save_capture(&self, path: PathBuf, bits: CaptureBits) {
1378 let msg = ApiMsg::DebugCommand(DebugCommand::SaveCapture(path, bits));
1379 self.send_message(msg);
1380 }
1381
1382 pub fn load_capture(&self, path: PathBuf, ids: Option<(u32, u32)>) -> Vec<CapturedDocument> {
1384 self.flush_scene_builder();
1387
1388 let (tx, rx) = unbounded_channel();
1389 let msg = ApiMsg::DebugCommand(DebugCommand::LoadCapture(path, ids, tx));
1390 self.send_message(msg);
1391
1392 let mut documents = Vec::new();
1393 while let Ok(captured_doc) = rx.recv() {
1394 documents.push(captured_doc);
1395 }
1396 documents
1397 }
1398
1399 pub fn start_capture_sequence(&self, path: PathBuf, bits: CaptureBits) {
1401 let msg = ApiMsg::DebugCommand(DebugCommand::StartCaptureSequence(path, bits));
1402 self.send_message(msg);
1403 }
1404
1405 pub fn stop_capture_sequence(&self) {
1407 let msg = ApiMsg::DebugCommand(DebugCommand::StopCaptureSequence);
1408 self.send_message(msg);
1409 }
1410
1411 pub fn send_debug_cmd(&self, cmd: DebugCommand) {
1413 let msg = ApiMsg::DebugCommand(cmd);
1414 self.send_message(msg);
1415 }
1416
1417 pub fn set_parameter(&mut self, parameter: Parameter) {
1419 if let Parameter::Bool(BoolParameter::Multithreading, enabled) = parameter {
1420 self.resources.enable_multithreading(enabled);
1421 }
1422
1423 let _ = self.low_priority_scene_sender.send(
1424 SceneBuilderRequest::SetParameter(parameter)
1425 );
1426 }
1427}
1428
1429impl Drop for RenderApi {
1430 fn drop(&mut self) {
1431 let msg = SceneBuilderRequest::ClearNamespace(self.namespace_id);
1432 let _ = self.low_priority_scene_sender.send(msg);
1433 }
1434}
1435
1436
1437fn window_size_sanity_check(size: DeviceIntSize) {
1438 use crate::api::MAX_RENDER_TASK_SIZE;
1441 if size.width > MAX_RENDER_TASK_SIZE || size.height > MAX_RENDER_TASK_SIZE {
1442 panic!("Attempting to create a {}x{} window/document", size.width, size.height);
1443 }
1444}
1445
1446#[repr(C)]
1450#[allow(missing_docs)]
1451#[derive(AddAssign, Clone, Debug, Default)]
1452pub struct MemoryReport {
1453 pub clip_stores: usize,
1457 pub gpu_cache_metadata: usize,
1458 pub gpu_cache_cpu_mirror: usize,
1459 pub hit_testers: usize,
1460 pub fonts: usize,
1461 pub weak_fonts: usize,
1462 pub images: usize,
1463 pub rasterized_blobs: usize,
1464 pub shader_cache: usize,
1465 pub interning: InterningMemoryReport,
1466 pub display_list: usize,
1467 pub upload_staging_memory: usize,
1468 pub swgl: usize,
1469 pub frame_allocator: usize,
1470 pub render_tasks: usize,
1471
1472 pub gpu_cache_textures: usize,
1476 pub vertex_data_textures: usize,
1477 pub render_target_textures: usize,
1478 pub picture_tile_textures: usize,
1479 pub atlas_textures: usize,
1480 pub standalone_textures: usize,
1481 pub texture_cache_structures: usize,
1482 pub depth_target_textures: usize,
1483 pub texture_upload_pbos: usize,
1484 pub swap_chain: usize,
1485 pub render_texture_hosts: usize,
1486 pub upload_staging_textures: usize,
1487}