1use std::rc::Rc;
9use std::{any::Any, sync::Arc};
10
11use webrender::api::{
12 AsyncBlobImageRasterizer, BlobImageHandler, BlobImageParams, BlobImageRequest, BlobImageResult, DocumentId, ExternalImageId,
13 PipelineId, units::TexelRect,
14};
15use webrender::{DebugFlags, RenderApi};
16use zng_task::channel::{ChannelError, IpcBytes};
17use zng_task::parking_lot::Mutex;
18use zng_unit::{Factor, PxSize};
19use zng_view_api::window::RenderMode;
20use zng_view_api::{
21 Event,
22 api_extension::{ApiExtensionId, ApiExtensionName, ApiExtensionPayload, ApiExtensions},
23};
24
25use crate::display_list::{DisplayExtensionArgs, DisplayExtensionItemArgs, DisplayExtensionUpdateArgs, DisplayListExtension, SpaceAndClip};
26
27pub use crate::px_wr::{PxToWr, WrToPx};
28use crate::util::PxToWinit;
29
30pub trait ViewExtension: Send + Any {
32 fn init(&mut self, args: ViewExtensionInitArgs) {
34 let _ = args;
35 }
36
37 fn name(&self) -> &ApiExtensionName;
39
40 fn command(&mut self, request: ApiExtensionPayload) -> Option<ApiExtensionPayload> {
42 let _ = request;
43 None
44 }
45
46 fn window(&mut self) -> Option<Box<dyn WindowExtension>> {
48 None
49 }
50
51 fn renderer(&mut self) -> Option<Box<dyn RendererExtension>> {
53 None
54 }
55
56 fn low_memory(&mut self) {}
58
59 fn suspended(&mut self) {}
70
71 fn resumed(&mut self) {}
80}
81
82pub trait WindowExtension: Any {
84 fn configure(&mut self, args: &mut WindowConfigArgs) {
86 let _ = args;
87 }
88
89 fn window_inited(&mut self, args: &mut WindowInitedArgs) {
91 let _ = args;
92 }
93
94 fn is_init_only(&self) -> bool;
96
97 fn command(&mut self, args: &mut WindowCommandArgs) -> ApiExtensionPayload {
99 let _ = args;
100 ApiExtensionPayload::unknown_extension(ApiExtensionId::INVALID)
101 }
102
103 fn event(&mut self, args: &mut WindowEventArgs) {
105 let _ = args;
106 }
107
108 fn low_memory(&mut self) {}
110
111 fn window_deinited(&mut self, args: &mut WindowDeinitedArgs) {
113 let _ = args;
114 }
115
116 fn as_any(&self) -> &dyn Any;
118
119 fn as_any_mut(&mut self) -> &mut dyn Any;
121}
122
123pub trait RendererExtension: Any {
125 fn configure(&mut self, args: &mut RendererConfigArgs) {
127 let _ = args;
128 }
129
130 fn renderer_inited(&mut self, args: &mut RendererInitedArgs) {
132 let _ = args;
133 }
134
135 fn is_init_only(&self) -> bool;
137
138 fn command(&mut self, args: &mut RendererCommandArgs) -> ApiExtensionPayload {
140 let _ = args;
141 ApiExtensionPayload::unknown_extension(ApiExtensionId::INVALID)
142 }
143
144 fn render_start(&mut self, args: &mut RenderArgs) {
146 let _ = args;
147 }
148
149 fn render_push(&mut self, args: &mut RenderItemArgs) {
151 let _ = args;
152 }
153
154 fn render_pop(&mut self, args: &mut RenderItemArgs) {
156 let _ = args;
157 }
158
159 fn render_end(&mut self, args: &mut RenderArgs) {
163 let _ = args;
164 }
165
166 fn render_update(&mut self, args: &mut RenderUpdateArgs) {
168 let _ = args;
169 }
170
171 fn frame_ready(&mut self, args: &mut FrameReadyArgs) {
173 let _ = args;
174 }
175
176 fn redraw(&mut self, args: &mut RedrawArgs) {
178 let _ = args;
179 }
180
181 fn low_memory(&mut self) {}
183
184 fn renderer_deinited(&mut self, args: &mut RendererDeinitedArgs) {
186 let _ = args;
187 }
188
189 fn as_any(&self) -> &dyn Any;
191
192 fn as_any_mut(&mut self) -> &mut dyn Any;
194}
195
196#[non_exhaustive]
198pub struct RenderArgs<'a> {
199 pub frame_id: zng_view_api::window::FrameId,
201
202 pub list: &'a mut webrender::api::DisplayListBuilder,
204 pub sc: &'a mut SpaceAndClip,
206
207 pub transaction: &'a mut webrender::Transaction,
209
210 pub renderer: &'a mut webrender::Renderer,
212 pub document_id: DocumentId,
214 pub api: &'a mut RenderApi,
216 pub external_images: &'a mut ExternalImages,
218}
219
220#[non_exhaustive]
222pub struct RenderItemArgs<'a> {
223 pub extension_id: ApiExtensionId,
225 pub payload: &'a ApiExtensionPayload,
227 pub is_reuse: bool,
232
233 pub list: &'a mut webrender::api::DisplayListBuilder,
235 pub sc: &'a mut SpaceAndClip,
237
238 pub transaction: &'a mut webrender::Transaction,
240
241 pub renderer: &'a mut webrender::Renderer,
243 pub document_id: DocumentId,
245 pub api: &'a mut RenderApi,
247 pub external_images: &'a mut ExternalImages,
249}
250
251#[non_exhaustive]
253pub struct RenderUpdateArgs<'a> {
254 pub extension_id: ApiExtensionId,
256 pub payload: &'a ApiExtensionPayload,
258
259 pub new_frame: bool,
264
265 pub properties: &'a mut webrender::api::DynamicProperties,
270
271 pub transaction: &'a mut webrender::Transaction,
273
274 pub renderer: &'a mut webrender::Renderer,
276 pub document_id: DocumentId,
278 pub api: &'a mut RenderApi,
280 pub external_images: &'a mut ExternalImages,
282}
283
284#[non_exhaustive]
286pub struct FrameReadyArgs {
287 pub frame_id: zng_view_api::window::FrameId,
289 pub redraw: bool,
294}
295
296#[non_exhaustive]
298pub struct RedrawArgs<'a> {
299 pub scale_factor: Factor,
301
302 pub size: PxSize,
304
305 pub context: &'a mut dyn OpenGlContext,
309}
310
311pub trait BlobExtension: Send + Any {
319 fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobRasterizer>;
321
322 fn create_similar(&self) -> Box<dyn BlobExtension>;
324
325 fn prepare_resources(&mut self, args: &mut BlobPrepareArgs) {
329 let _ = args;
330 }
331
332 fn add(&mut self, args: &BlobAddArgs);
334 fn update(&mut self, args: &BlobUpdateArgs);
336
337 fn delete(&mut self, key: webrender::api::BlobImageKey);
339
340 fn delete_font(&mut self, key: webrender::api::FontKey) {
342 let _ = key;
343 }
344
345 fn delete_font_instance(&mut self, key: webrender::api::FontInstanceKey) {
347 let _ = key;
348 }
349
350 fn clear_namespace(&mut self, namespace: webrender::api::IdNamespace) {
352 let _ = namespace;
353 }
354
355 fn enable_multithreading(&mut self, enable: bool);
359}
360
361#[non_exhaustive]
363pub struct ViewExtensionInitArgs {
364 pub event_sender: ExtensionEventSender,
366}
367
368#[derive(Clone)]
372pub struct ExtensionEventSender {
373 sender: crate::AppEventSender,
374 id: ApiExtensionId,
375}
376impl ExtensionEventSender {
377 pub fn send(&self, payload: ApiExtensionPayload) -> Result<(), ChannelError> {
379 self.sender.send(crate::AppEvent::Notify(Event::ExtensionEvent(self.id, payload)))
380 }
381}
382
383pub trait AsyncBlobRasterizer: Send + Any {
385 fn rasterize(&mut self, args: &mut BlobRasterizerArgs);
390}
391
392#[non_exhaustive]
394pub struct BlobPrepareArgs<'a> {
395 pub services: &'a dyn webrender::api::BlobImageResources,
397 pub requests: &'a [BlobImageParams],
400}
401
402#[non_exhaustive]
404pub struct BlobAddArgs {
405 pub key: webrender::api::BlobImageKey,
409 pub data: std::sync::Arc<webrender::api::BlobImageData>,
411
412 pub visible_rect: webrender::api::units::DeviceIntRect,
414 pub tile_size: webrender::api::TileSize,
416}
417
418#[non_exhaustive]
420pub struct BlobUpdateArgs {
421 pub key: webrender::api::BlobImageKey,
425 pub data: std::sync::Arc<webrender::api::BlobImageData>,
427 pub visible_rect: webrender::api::units::DeviceIntRect,
429 pub dirty_rect: webrender::api::units::BlobDirtyRect,
431}
432
433#[non_exhaustive]
435pub struct BlobRasterizerArgs<'a> {
436 pub requests: &'a [BlobImageParams],
440 pub low_priority: bool,
443
444 pub tile_pool: &'a mut webrender::api::BlobTilePool,
446
447 pub responses: &'a mut Vec<(BlobImageRequest, BlobImageResult)>,
452}
453
454#[non_exhaustive]
456pub struct WindowConfigArgs<'a> {
457 pub config: Option<&'a ApiExtensionPayload>,
461
462 pub window: Option<&'a mut winit::window::WindowAttributes>,
464}
465
466#[non_exhaustive]
468pub struct RendererConfigArgs<'a> {
469 pub config: Option<&'a ApiExtensionPayload>,
473
474 pub options: &'a mut webrender::WebRenderOptions,
483
484 pub blobs: &'a mut Vec<Box<dyn BlobExtension>>,
488
489 pub window: Option<&'a winit::window::Window>,
491
492 pub context: &'a mut dyn OpenGlContext,
494}
495
496#[non_exhaustive]
498pub struct RendererInitedArgs<'a> {
499 pub renderer: &'a mut webrender::Renderer,
506
507 pub api_sender: &'a webrender::RenderApiSender,
509
510 pub api: &'a mut RenderApi,
512
513 pub document_id: DocumentId,
515
516 pub pipeline_id: PipelineId,
518
519 pub window: Option<&'a winit::window::Window>,
521
522 pub context: &'a mut dyn OpenGlContext,
526
527 pub external_images: &'a mut ExternalImages,
529}
530
531#[derive(Default)]
533pub struct ExternalImages {
534 images: Vec<Arc<crate::image_cache::ImageData>>,
535}
536impl ExternalImages {
537 pub fn register_texture(&mut self, uv: TexelRect, texture: gleam::gl::GLuint) -> ExternalImageId {
547 self.register(crate::image_cache::ImageData::NativeTexture { uv, texture })
548 }
549
550 pub fn register_image(&mut self, size: PxSize, is_opaque: bool, pixels: IpcBytes) -> ExternalImageId {
563 let expected_len = size.width.0 as usize * size.height.0 as usize;
564 assert!(
565 pixels.len() == expected_len || pixels.len() == expected_len * 4,
566 "pixels must be BGRA8 or A8"
567 );
568 self.register(crate::image_cache::ImageData::RawData {
569 size,
570 range: 0..pixels.len(),
571 pixels,
572 is_opaque,
573 density: None,
574 stripes: Mutex::new(Box::new([])),
575 })
576 }
577
578 pub fn unregister(&mut self, id: ExternalImageId) {
583 if let Some(i) = self.images.iter().position(|img| ExternalImageId(Arc::as_ptr(img) as u64) == id) {
584 self.images.swap_remove(i);
585 }
586 }
587
588 fn register(&mut self, img: crate::image_cache::ImageData) -> ExternalImageId {
589 let img = Arc::new(img);
590 let id = ExternalImageId(Arc::as_ptr(&img) as u64);
591 self.images.push(img);
592 id
593 }
594}
595
596#[non_exhaustive]
598pub struct RendererDeinitedArgs<'a> {
599 pub document_id: DocumentId,
601
602 pub pipeline_id: PipelineId,
604
605 pub window: Option<&'a winit::window::Window>,
607
608 pub context: &'a mut dyn OpenGlContext,
613}
614
615#[non_exhaustive]
617pub struct WindowInitedArgs<'a> {
618 pub window: &'a winit::window::Window,
620
621 pub context: &'a mut dyn OpenGlContext,
623}
624
625#[non_exhaustive]
627pub struct WindowDeinitedArgs<'a> {
628 pub window: &'a winit::window::Window,
630
631 pub context: &'a mut dyn OpenGlContext,
633}
634
635#[non_exhaustive]
637pub struct WindowCommandArgs<'a> {
638 pub window: &'a winit::window::Window,
640
641 pub context: &'a mut dyn OpenGlContext,
643
644 pub request: ApiExtensionPayload,
646}
647
648#[non_exhaustive]
650pub struct WindowEventArgs<'a> {
651 pub window: &'a winit::window::Window,
653
654 pub context: &'a mut dyn OpenGlContext,
656
657 pub event: &'a winit::event::WindowEvent,
659}
660
661pub trait OpenGlContext {
663 fn is_current(&self) -> bool;
665
666 fn make_current(&mut self);
668
669 fn gl(&self) -> &Rc<dyn gleam::gl::Gl>;
671
672 fn render_mode(&self) -> RenderMode;
674
675 fn resize(&mut self, size: PxSize);
677
678 fn is_software(&self) -> bool;
680
681 fn swap_buffers(&mut self);
683}
684impl OpenGlContext for crate::gl::GlContext {
685 fn is_current(&self) -> bool {
686 self.is_current()
687 }
688
689 fn make_current(&mut self) {
690 self.make_current()
691 }
692
693 fn gl(&self) -> &Rc<dyn gleam::gl::Gl> {
694 self.gl()
695 }
696
697 fn render_mode(&self) -> RenderMode {
698 self.render_mode()
699 }
700
701 fn resize(&mut self, size: PxSize) {
702 self.resize(size.to_winit())
703 }
704
705 fn is_software(&self) -> bool {
706 self.is_software()
707 }
708
709 fn swap_buffers(&mut self) {
710 self.swap_buffers()
711 }
712}
713
714#[non_exhaustive]
716pub struct RendererCommandArgs<'a> {
717 pub renderer: &'a mut webrender::Renderer,
719
720 pub api: &'a mut RenderApi,
722
723 pub document_id: DocumentId,
725
726 pub request: ApiExtensionPayload,
728
729 pub window: Option<&'a winit::window::Window>,
731
732 pub context: &'a mut dyn OpenGlContext,
734
735 pub redraw: &'a mut bool,
739}
740
741pub struct ViewExtensions {
743 exts: Vec<Box<dyn ViewExtension>>,
744}
745impl ViewExtensions {
746 pub(crate) fn new() -> Self {
748 Self { exts: vec![] }
749 }
750
751 pub fn register<E: ViewExtension>(&mut self, ext: impl FnOnce(ApiExtensionId) -> E) -> &mut Self {
759 let id = ApiExtensionId::from_index(self.exts.len());
760 let ext = ext(id);
761 assert!(self.id(ext.name()).is_none(), "extension already registered");
762 self.exts.push(Box::new(ext));
763 self
764 }
765
766 pub fn id(&self, name: &ApiExtensionName) -> Option<ApiExtensionId> {
768 self.exts.iter().position(|e| e.name() == name).map(ApiExtensionId::from_index)
769 }
770
771 pub fn command_raw(
775 &mut self,
776 name: impl Into<ApiExtensionName>,
777 handler: impl FnMut(ApiExtensionPayload, ApiExtensionId) -> ApiExtensionPayload + Send + 'static,
778 ) -> &mut Self {
779 struct CommandExt<F>(ApiExtensionName, ApiExtensionId, F);
780 impl<F: FnMut(ApiExtensionPayload, ApiExtensionId) -> ApiExtensionPayload + Send + 'static> ViewExtension for CommandExt<F> {
781 fn name(&self) -> &ApiExtensionName {
782 &self.0
783 }
784 fn command(&mut self, request: ApiExtensionPayload) -> Option<ApiExtensionPayload> {
785 Some((self.2)(request, self.1))
786 }
787 }
788
789 self.register(|id| CommandExt(name.into(), id, handler));
790 self
791 }
792
793 pub fn command<I: serde::de::DeserializeOwned, O: serde::Serialize>(
797 &mut self,
798 name: impl Into<ApiExtensionName>,
799 mut handler: impl FnMut(I, ApiExtensionId) -> O + Send + 'static,
800 ) -> &mut Self {
801 self.command_raw(name, move |p, id| match p.deserialize::<I>() {
802 Ok(p) => {
803 let o = handler(p, id);
804 ApiExtensionPayload::serialize(&o).unwrap()
805 }
806 Err(e) => ApiExtensionPayload::invalid_request(id, e),
807 })
808 }
809
810 pub fn window<E: WindowExtension>(
812 &mut self,
813 name: impl Into<ApiExtensionName>,
814 new: impl FnMut(ApiExtensionId) -> E + Send + 'static,
815 ) -> &mut Self {
816 struct WindowExt<F>(ApiExtensionName, ApiExtensionId, F);
817 impl<E, F> ViewExtension for WindowExt<F>
818 where
819 E: WindowExtension,
820 F: FnMut(ApiExtensionId) -> E + Send + 'static,
821 {
822 fn name(&self) -> &ApiExtensionName {
823 &self.0
824 }
825
826 fn window(&mut self) -> Option<Box<dyn WindowExtension>> {
827 Some(Box::new((self.2)(self.1)))
828 }
829 }
830 self.register(move |id| WindowExt(name.into(), id, new));
831 self
832 }
833
834 pub fn renderer<E: RendererExtension>(
836 &mut self,
837 name: impl Into<ApiExtensionName>,
838 new: impl FnMut(ApiExtensionId) -> E + Send + 'static,
839 ) -> &mut Self {
840 struct RendererExt<F>(ApiExtensionName, ApiExtensionId, F);
841 impl<E, F> ViewExtension for RendererExt<F>
842 where
843 E: RendererExtension,
844 F: FnMut(ApiExtensionId) -> E + Send + 'static,
845 {
846 fn name(&self) -> &ApiExtensionName {
847 &self.0
848 }
849
850 fn renderer(&mut self) -> Option<Box<dyn RendererExtension>> {
851 Some(Box::new((self.2)(self.1)))
852 }
853 }
854 self.register(move |id| RendererExt(name.into(), id, new));
855 self
856 }
857
858 pub fn data(&mut self, name: impl Into<ApiExtensionName>) -> &mut Self {
864 struct DataExt(ApiExtensionName);
865 impl ViewExtension for DataExt {
866 fn name(&self) -> &ApiExtensionName {
867 &self.0
868 }
869 }
870 self.register(|_| DataExt(name.into()))
871 }
872
873 pub(crate) fn api_extensions(&self) -> ApiExtensions {
874 let mut r = ApiExtensions::new();
875 for ext in &self.exts {
876 r.insert(ext.name().clone()).unwrap();
877 }
878 r
879 }
880
881 pub(crate) fn call_command(&mut self, id: ApiExtensionId, request: ApiExtensionPayload) -> ApiExtensionPayload {
882 let idx = id.index();
883 if idx >= self.exts.len() {
884 ApiExtensionPayload::unknown_extension(id)
885 } else if let Some(r) = self.exts[idx].command(request) {
886 r
887 } else {
888 ApiExtensionPayload::unknown_extension(id)
889 }
890 }
891
892 pub(crate) fn new_window(&mut self) -> Vec<(ApiExtensionId, Box<dyn WindowExtension>)> {
893 self.exts
894 .iter_mut()
895 .enumerate()
896 .filter_map(|(i, e)| e.window().map(|e| (ApiExtensionId::from_index(i), e)))
897 .collect()
898 }
899
900 pub(crate) fn new_renderer(&mut self) -> Vec<(ApiExtensionId, Box<dyn RendererExtension>)> {
901 self.exts
902 .iter_mut()
903 .enumerate()
904 .filter_map(|(i, e)| e.renderer().map(|e| (ApiExtensionId::from_index(i), e)))
905 .collect()
906 }
907
908 pub(crate) fn init(&mut self, event_sender: &crate::AppEventSender) {
909 for (i, ext) in self.exts.iter_mut().enumerate() {
910 ext.init(ViewExtensionInitArgs {
911 event_sender: ExtensionEventSender {
912 sender: event_sender.clone(),
913 id: ApiExtensionId::from_index(i),
914 },
915 });
916 }
917 }
918
919 pub(crate) fn on_low_memory(&mut self) {
920 for ext in self.exts.iter_mut() {
921 ext.low_memory();
922 }
923 }
924
925 pub(crate) fn suspended(&mut self) {
926 for ext in self.exts.iter_mut() {
927 ext.suspended();
928 }
929 }
930
931 pub(crate) fn resumed(&mut self) {
932 for ext in self.exts.iter_mut() {
933 ext.resumed();
934 }
935 }
936
937 pub fn append(&mut self, mut other: ViewExtensions) {
939 self.exts.append(&mut other.exts);
940 }
941}
942
943#[cfg(windows)]
944pub(crate) struct PreferAngleExt {
945 pub(crate) prefer_egl: bool,
946}
947#[cfg(windows)]
948impl PreferAngleExt {
949 pub(crate) fn new(_: ApiExtensionId) -> Self {
950 Self { prefer_egl: false }
951 }
952}
953#[cfg(windows)]
954impl WindowExtension for PreferAngleExt {
955 fn is_init_only(&self) -> bool {
956 true
957 }
958
959 fn configure(&mut self, args: &mut WindowConfigArgs) {
960 if let Some(cfg) = args.config {
961 match cfg.deserialize::<bool>() {
962 Ok(y) => self.prefer_egl = y,
963 Err(e) => tracing::error!("invalid arg for 'zng-view.prefer_angle', {e}"),
964 }
965 }
966 }
967
968 fn as_any(&self) -> &dyn Any {
969 self
970 }
971
972 fn as_any_mut(&mut self) -> &mut dyn Any {
973 self
974 }
975}
976
977pub(crate) struct RendererDebugExt {
981 id: ApiExtensionId,
982 ui: Option<String>,
983}
984
985impl RendererDebugExt {
986 pub(crate) fn new(id: ApiExtensionId) -> Self {
987 Self { id, ui: None }
988 }
989}
990impl RendererExtension for RendererDebugExt {
991 fn is_init_only(&self) -> bool {
992 false
993 }
994
995 fn configure(&mut self, args: &mut RendererConfigArgs) {
996 if let Some(cfg) = args.config.as_ref().and_then(|c| c.deserialize::<RendererDebug>().ok()) {
997 args.options.debug_flags = cfg.flags;
998 self.ui = Some(cfg.profiler_ui);
999 }
1000 }
1001
1002 fn renderer_inited(&mut self, args: &mut RendererInitedArgs) {
1003 if let Some(ui) = self.ui.take() {
1004 args.renderer.set_profiler_ui(&ui);
1005 }
1006 }
1007
1008 fn command(&mut self, args: &mut RendererCommandArgs) -> ApiExtensionPayload {
1009 match args.request.deserialize::<RendererDebug>() {
1010 Ok(cfg) => {
1011 args.renderer.set_debug_flags(cfg.flags);
1012 args.renderer.set_profiler_ui(&cfg.profiler_ui);
1013 ApiExtensionPayload::empty()
1014 }
1015 Err(e) => ApiExtensionPayload::invalid_request(self.id, e),
1016 }
1017 }
1018
1019 fn as_any(&self) -> &dyn Any {
1020 self
1021 }
1022
1023 fn as_any_mut(&mut self) -> &mut dyn Any {
1024 self
1025 }
1026}
1027
1028#[derive(serde::Serialize, serde::Deserialize)]
1030struct RendererDebug {
1031 pub flags: DebugFlags,
1032 pub profiler_ui: String,
1033}
1034
1035pub(crate) struct DisplayListExtAdapter<'a> {
1036 pub extensions: &'a mut Vec<(ApiExtensionId, Box<dyn RendererExtension>)>,
1037 pub transaction: &'a mut webrender::Transaction,
1038 pub renderer: &'a mut webrender::Renderer,
1039 pub document_id: DocumentId,
1040 pub api: &'a mut RenderApi,
1041 pub external_images: &'a mut ExternalImages,
1042 pub frame_id: zng_view_api::window::FrameId,
1043}
1044
1045impl DisplayListExtension for DisplayListExtAdapter<'_> {
1046 fn display_list_start(&mut self, args: &mut DisplayExtensionArgs) {
1047 for (_, ext) in self.extensions.iter_mut() {
1048 ext.render_start(&mut RenderArgs {
1049 frame_id: self.frame_id,
1050 list: args.list,
1051 sc: args.sc,
1052 transaction: self.transaction,
1053 renderer: self.renderer,
1054 document_id: self.document_id,
1055 api: self.api,
1056 external_images: self.external_images,
1057 });
1058 }
1059 }
1060
1061 fn push_display_item(&mut self, args: &mut DisplayExtensionItemArgs) {
1062 for (id, ext) in self.extensions.iter_mut() {
1063 if *id == args.extension_id {
1064 ext.render_push(&mut RenderItemArgs {
1065 extension_id: args.extension_id,
1066 payload: args.payload,
1067 is_reuse: args.is_reuse,
1068 list: args.list,
1069 sc: args.sc,
1070 transaction: self.transaction,
1071 renderer: self.renderer,
1072 document_id: self.document_id,
1073 api: self.api,
1074 external_images: self.external_images,
1075 });
1076 break;
1077 }
1078 }
1079 }
1080
1081 fn pop_display_item(&mut self, args: &mut DisplayExtensionItemArgs) {
1082 for (id, ext) in self.extensions.iter_mut() {
1083 if *id == args.extension_id {
1084 ext.render_pop(&mut RenderItemArgs {
1085 extension_id: args.extension_id,
1086 payload: args.payload,
1087 is_reuse: args.is_reuse,
1088 list: args.list,
1089 sc: args.sc,
1090 transaction: self.transaction,
1091 renderer: self.renderer,
1092 document_id: self.document_id,
1093 api: self.api,
1094 external_images: self.external_images,
1095 });
1096 break;
1097 }
1098 }
1099 }
1100
1101 fn display_list_end(&mut self, args: &mut DisplayExtensionArgs) {
1102 for (_, ext) in self.extensions.iter_mut() {
1103 ext.render_end(&mut RenderArgs {
1104 frame_id: self.frame_id,
1105 list: args.list,
1106 sc: args.sc,
1107 transaction: self.transaction,
1108 renderer: self.renderer,
1109 document_id: self.document_id,
1110 api: self.api,
1111 external_images: self.external_images,
1112 });
1113 }
1114 }
1115
1116 fn update(&mut self, args: &mut DisplayExtensionUpdateArgs) {
1117 for (id, ext) in self.extensions.iter_mut() {
1118 if *id == args.extension_id {
1119 let mut r_args = RenderUpdateArgs {
1120 extension_id: args.extension_id,
1121 payload: args.payload,
1122 new_frame: args.new_frame,
1123 properties: args.properties,
1124 document_id: self.document_id,
1125 transaction: self.transaction,
1126 renderer: self.renderer,
1127 api: self.api,
1128 external_images: self.external_images,
1129 };
1130 ext.render_update(&mut r_args);
1131 args.new_frame = r_args.new_frame;
1132 break;
1133 }
1134 }
1135 }
1136}
1137
1138pub(crate) struct BlobExtensionsImgHandler(pub Vec<Box<dyn BlobExtension>>);
1139
1140impl BlobImageHandler for BlobExtensionsImgHandler {
1141 fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobImageRasterizer> {
1142 Box::new(BlockExtensionsImgRasterizer(
1143 self.0.iter_mut().map(|t| t.create_blob_rasterizer()).collect(),
1144 ))
1145 }
1146
1147 fn create_similar(&self) -> Box<dyn BlobImageHandler> {
1148 Box::new(Self(self.0.iter().map(|e| e.create_similar()).collect()))
1149 }
1150
1151 fn prepare_resources(&mut self, services: &dyn webrender::api::BlobImageResources, requests: &[BlobImageParams]) {
1152 for ext in self.0.iter_mut() {
1153 ext.prepare_resources(&mut BlobPrepareArgs { services, requests })
1154 }
1155 }
1156
1157 fn add(
1158 &mut self,
1159 key: webrender::api::BlobImageKey,
1160 data: std::sync::Arc<webrender::api::BlobImageData>,
1161 visible_rect: &webrender::api::units::DeviceIntRect,
1162 tile_size: webrender::api::TileSize,
1163 ) {
1164 let args = BlobAddArgs {
1165 key,
1166 data,
1167 visible_rect: *visible_rect,
1168 tile_size,
1169 };
1170 for ext in self.0.iter_mut() {
1171 ext.add(&args);
1172 }
1173 }
1174
1175 fn update(
1176 &mut self,
1177 key: webrender::api::BlobImageKey,
1178 data: std::sync::Arc<webrender::api::BlobImageData>,
1179 visible_rect: &webrender::api::units::DeviceIntRect,
1180 dirty_rect: &webrender::api::units::BlobDirtyRect,
1181 ) {
1182 let args = BlobUpdateArgs {
1183 key,
1184 data,
1185 visible_rect: *visible_rect,
1186 dirty_rect: *dirty_rect,
1187 };
1188 for ext in self.0.iter_mut() {
1189 ext.update(&args);
1190 }
1191 }
1192
1193 fn delete(&mut self, key: webrender::api::BlobImageKey) {
1194 for ext in self.0.iter_mut() {
1195 ext.delete(key);
1196 }
1197 }
1198
1199 fn delete_font(&mut self, key: webrender::api::FontKey) {
1200 for ext in self.0.iter_mut() {
1201 ext.delete_font(key);
1202 }
1203 }
1204
1205 fn delete_font_instance(&mut self, key: webrender::api::FontInstanceKey) {
1206 for ext in self.0.iter_mut() {
1207 ext.delete_font_instance(key);
1208 }
1209 }
1210
1211 fn clear_namespace(&mut self, namespace: webrender::api::IdNamespace) {
1212 for ext in self.0.iter_mut() {
1213 ext.clear_namespace(namespace);
1214 }
1215 }
1216
1217 fn enable_multithreading(&mut self, enable: bool) {
1218 for ext in self.0.iter_mut() {
1219 ext.enable_multithreading(enable);
1220 }
1221 }
1222}
1223
1224struct BlockExtensionsImgRasterizer(Vec<Box<dyn AsyncBlobRasterizer>>);
1225impl AsyncBlobImageRasterizer for BlockExtensionsImgRasterizer {
1226 fn rasterize(
1227 &mut self,
1228 requests: &[BlobImageParams],
1229 low_priority: bool,
1230 tile_pool: &mut crate::BlobTilePool,
1231 ) -> Vec<(BlobImageRequest, BlobImageResult)> {
1232 let mut responses = vec![];
1233 for r in &mut self.0 {
1234 r.rasterize(&mut BlobRasterizerArgs {
1235 requests,
1236 low_priority,
1237 tile_pool,
1238 responses: &mut responses,
1239 })
1240 }
1241 responses
1242 }
1243}
1244
1245#[macro_export]
1249macro_rules! view_process_extension {
1250 ($closure:expr) => {
1251 #[used]
1256 #[cfg_attr(
1257 any(
1258 target_os = "none",
1259 target_os = "linux",
1260 target_os = "android",
1261 target_os = "fuchsia",
1262 target_os = "psp"
1263 ),
1264 unsafe(link_section = "linkme_VIEW_EXTENSIONS")
1265 )]
1266 #[cfg_attr(
1267 any(target_os = "macos", target_os = "ios", target_os = "tvos"),
1268 unsafe(link_section = "__DATA,__linkmeTbhLJz52,regular,no_dead_strip")
1269 )]
1270 #[cfg_attr(
1271 any(target_os = "uefi", target_os = "windows"),
1272 unsafe(link_section = ".linkme_VIEW_EXTENSIONS$b")
1273 )]
1274 #[cfg_attr(target_os = "illumos", unsafe(link_section = "set_linkme_VIEW_EXTENSIONS"))]
1275 #[cfg_attr(
1276 any(target_os = "freebsd", target_os = "openbsd"),
1277 unsafe(link_section = "linkme_VIEW_EXTENSIONS")
1278 )]
1279 #[doc(hidden)]
1280 static _VIEW_EXTENSIONS: fn(&mut $crate::extensions::ViewExtensions) = _view_extensions;
1281 #[doc(hidden)]
1282 fn _view_extensions(ext: &mut $crate::extensions::ViewExtensions) {
1283 fn view_extensions(
1284 ext: &mut $crate::extensions::ViewExtensions,
1285 handler: impl FnOnce(&mut $crate::extensions::ViewExtensions),
1286 ) {
1287 handler(ext)
1288 }
1289 view_extensions(ext, $closure)
1290 }
1291 };
1292}
1293
1294#[doc(hidden)]
1295#[linkme::distributed_slice]
1296pub static VIEW_EXTENSIONS: [fn(&mut ViewExtensions)];