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_unit::{Factor, PxSize};
17use zng_view_api::window::RenderMode;
18use zng_view_api::{
19 Event,
20 api_extension::{ApiExtensionId, ApiExtensionName, ApiExtensionPayload, ApiExtensions},
21};
22
23use crate::display_list::{DisplayExtensionArgs, DisplayExtensionItemArgs, DisplayExtensionUpdateArgs, DisplayListExtension, SpaceAndClip};
24
25pub use crate::px_wr::{PxToWr, WrToPx};
26use crate::util::PxToWinit;
27
28pub trait ViewExtension: Send + Any {
30 fn init(&mut self, args: ViewExtensionInitArgs) {
32 let _ = args;
33 }
34
35 fn name(&self) -> &ApiExtensionName;
37
38 fn command(&mut self, request: ApiExtensionPayload) -> Option<ApiExtensionPayload> {
40 let _ = request;
41 None
42 }
43
44 fn window(&mut self) -> Option<Box<dyn WindowExtension>> {
46 None
47 }
48
49 fn renderer(&mut self) -> Option<Box<dyn RendererExtension>> {
51 None
52 }
53
54 fn low_memory(&mut self) {}
56
57 fn suspended(&mut self) {}
68
69 fn resumed(&mut self) {}
78}
79
80pub trait WindowExtension: Any {
82 fn configure(&mut self, args: &mut WindowConfigArgs) {
84 let _ = args;
85 }
86
87 fn window_inited(&mut self, args: &mut WindowInitedArgs) {
89 let _ = args;
90 }
91
92 fn is_init_only(&self) -> bool;
94
95 fn command(&mut self, args: &mut WindowCommandArgs) -> ApiExtensionPayload {
97 let _ = args;
98 ApiExtensionPayload::unknown_extension(ApiExtensionId::INVALID)
99 }
100
101 fn event(&mut self, args: &mut WindowEventArgs) {
103 let _ = args;
104 }
105
106 fn low_memory(&mut self) {}
108
109 fn window_deinited(&mut self, args: &mut WindowDeinitedArgs) {
111 let _ = args;
112 }
113
114 fn as_any(&self) -> &dyn Any;
116
117 fn as_any_mut(&mut self) -> &mut dyn Any;
119}
120
121pub trait RendererExtension: Any {
123 fn configure(&mut self, args: &mut RendererConfigArgs) {
125 let _ = args;
126 }
127
128 fn renderer_inited(&mut self, args: &mut RendererInitedArgs) {
130 let _ = args;
131 }
132
133 fn is_init_only(&self) -> bool;
135
136 fn command(&mut self, args: &mut RendererCommandArgs) -> ApiExtensionPayload {
138 let _ = args;
139 ApiExtensionPayload::unknown_extension(ApiExtensionId::INVALID)
140 }
141
142 fn render_start(&mut self, args: &mut RenderArgs) {
144 let _ = args;
145 }
146
147 fn render_push(&mut self, args: &mut RenderItemArgs) {
149 let _ = args;
150 }
151
152 fn render_pop(&mut self, args: &mut RenderItemArgs) {
154 let _ = args;
155 }
156
157 fn render_end(&mut self, args: &mut RenderArgs) {
161 let _ = args;
162 }
163
164 fn render_update(&mut self, args: &mut RenderUpdateArgs) {
166 let _ = args;
167 }
168
169 fn frame_ready(&mut self, args: &mut FrameReadyArgs) {
171 let _ = args;
172 }
173
174 fn redraw(&mut self, args: &mut RedrawArgs) {
176 let _ = args;
177 }
178
179 fn low_memory(&mut self) {}
181
182 fn renderer_deinited(&mut self, args: &mut RendererDeinitedArgs) {
184 let _ = args;
185 }
186
187 fn as_any(&self) -> &dyn Any;
189
190 fn as_any_mut(&mut self) -> &mut dyn Any;
192}
193
194pub struct RenderArgs<'a> {
196 pub frame_id: zng_view_api::window::FrameId,
198
199 pub list: &'a mut webrender::api::DisplayListBuilder,
201 pub sc: &'a mut SpaceAndClip,
203
204 pub transaction: &'a mut webrender::Transaction,
206
207 pub renderer: &'a mut webrender::Renderer,
209 pub api: &'a mut RenderApi,
211 pub external_images: &'a mut ExternalImages,
213}
214
215pub struct RenderItemArgs<'a> {
217 pub extension_id: ApiExtensionId,
219 pub payload: &'a ApiExtensionPayload,
221 pub is_reuse: bool,
226
227 pub list: &'a mut webrender::api::DisplayListBuilder,
229 pub sc: &'a mut SpaceAndClip,
231
232 pub transaction: &'a mut webrender::Transaction,
234
235 pub renderer: &'a mut webrender::Renderer,
237 pub api: &'a mut RenderApi,
239 pub external_images: &'a mut ExternalImages,
241}
242
243pub struct RenderUpdateArgs<'a> {
245 pub extension_id: ApiExtensionId,
247 pub payload: &'a ApiExtensionPayload,
249
250 pub new_frame: bool,
255
256 pub properties: &'a mut webrender::api::DynamicProperties,
261
262 pub transaction: &'a mut webrender::Transaction,
264
265 pub renderer: &'a mut webrender::Renderer,
267 pub api: &'a mut RenderApi,
269 pub external_images: &'a mut ExternalImages,
271}
272
273pub struct FrameReadyArgs {
275 pub frame_id: zng_view_api::window::FrameId,
277 pub redraw: bool,
282}
283
284pub struct RedrawArgs<'a> {
286 pub scale_factor: Factor,
288
289 pub size: PxSize,
291
292 pub context: &'a mut dyn OpenGlContext,
296}
297
298pub trait BlobExtension: Send + Any {
306 fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobRasterizer>;
308
309 fn create_similar(&self) -> Box<dyn BlobExtension>;
311
312 fn prepare_resources(&mut self, args: &mut BlobPrepareArgs) {
316 let _ = args;
317 }
318
319 fn add(&mut self, args: &BlobAddArgs);
321 fn update(&mut self, args: &BlobUpdateArgs);
323
324 fn delete(&mut self, key: webrender::api::BlobImageKey);
326
327 fn delete_font(&mut self, key: webrender::api::FontKey) {
329 let _ = key;
330 }
331
332 fn delete_font_instance(&mut self, key: webrender::api::FontInstanceKey) {
334 let _ = key;
335 }
336
337 fn clear_namespace(&mut self, namespace: webrender::api::IdNamespace) {
339 let _ = namespace;
340 }
341
342 fn enable_multithreading(&mut self, enable: bool);
346}
347
348pub struct ViewExtensionInitArgs {
350 pub event_sender: ExtensionEventSender,
352}
353
354#[derive(Clone)]
358pub struct ExtensionEventSender {
359 sender: crate::AppEventSender,
360 id: ApiExtensionId,
361}
362impl ExtensionEventSender {
363 pub fn send(&self, payload: ApiExtensionPayload) -> Result<(), zng_view_api::ipc::Disconnected> {
365 self.sender.send(crate::AppEvent::Notify(Event::ExtensionEvent(self.id, payload)))
366 }
367}
368
369pub trait AsyncBlobRasterizer: Send + Any {
371 fn rasterize(&mut self, args: &mut BlobRasterizerArgs);
376}
377
378pub struct BlobPrepareArgs<'a> {
380 pub services: &'a dyn webrender::api::BlobImageResources,
382 pub requests: &'a [BlobImageParams],
385}
386
387pub struct BlobAddArgs {
389 pub key: webrender::api::BlobImageKey,
393 pub data: std::sync::Arc<webrender::api::BlobImageData>,
395
396 pub visible_rect: webrender::api::units::DeviceIntRect,
398 pub tile_size: webrender::api::TileSize,
400}
401
402pub struct BlobUpdateArgs {
404 pub key: webrender::api::BlobImageKey,
408 pub data: std::sync::Arc<webrender::api::BlobImageData>,
410 pub visible_rect: webrender::api::units::DeviceIntRect,
412 pub dirty_rect: webrender::api::units::BlobDirtyRect,
414}
415
416pub struct BlobRasterizerArgs<'a> {
418 pub requests: &'a [BlobImageParams],
422 pub low_priority: bool,
425
426 pub tile_pool: &'a mut webrender::api::BlobTilePool,
428
429 pub responses: &'a mut Vec<(BlobImageRequest, BlobImageResult)>,
434}
435
436pub struct WindowConfigArgs<'a> {
438 pub config: Option<&'a ApiExtensionPayload>,
442
443 pub window: Option<&'a mut winit::window::WindowAttributes>,
445}
446
447pub struct RendererConfigArgs<'a> {
449 pub config: Option<&'a ApiExtensionPayload>,
453
454 pub options: &'a mut webrender::WebRenderOptions,
463
464 pub blobs: &'a mut Vec<Box<dyn BlobExtension>>,
468
469 pub window: Option<&'a winit::window::Window>,
471
472 pub context: &'a mut dyn OpenGlContext,
474}
475
476pub struct RendererInitedArgs<'a> {
478 pub renderer: &'a mut webrender::Renderer,
485
486 pub api_sender: &'a webrender::RenderApiSender,
488
489 pub api: &'a mut RenderApi,
491
492 pub document_id: DocumentId,
494
495 pub pipeline_id: PipelineId,
497
498 pub window: Option<&'a winit::window::Window>,
500
501 pub context: &'a mut dyn OpenGlContext,
505
506 pub external_images: &'a mut ExternalImages,
508}
509
510#[derive(Default)]
512pub struct ExternalImages {
513 images: Vec<Arc<crate::image_cache::ImageData>>,
514}
515impl ExternalImages {
516 pub fn register_texture(&mut self, uv: TexelRect, texture: gleam::gl::GLuint) -> ExternalImageId {
526 self.register(crate::image_cache::ImageData::NativeTexture { uv, texture })
527 }
528
529 pub fn register_image(&mut self, descriptor: webrender::api::ImageDescriptor, pixels: zng_view_api::ipc::IpcBytes) -> ExternalImageId {
537 self.register(crate::image_cache::ImageData::RawData {
538 size: descriptor.size.cast().cast_unit(), pixels,
540 descriptor,
541 ppi: None,
542 })
543 }
544
545 pub fn unregister(&mut self, id: ExternalImageId) {
550 if let Some(i) = self.images.iter().position(|img| ExternalImageId(Arc::as_ptr(img) as u64) == id) {
551 self.images.swap_remove(i);
552 }
553 }
554
555 fn register(&mut self, img: crate::image_cache::ImageData) -> ExternalImageId {
556 let img = Arc::new(img);
557 let id = ExternalImageId(Arc::as_ptr(&img) as u64);
558 self.images.push(img);
559 id
560 }
561}
562
563pub struct RendererDeinitedArgs<'a> {
565 pub document_id: DocumentId,
567
568 pub pipeline_id: PipelineId,
570
571 pub window: Option<&'a winit::window::Window>,
573
574 pub context: &'a mut dyn OpenGlContext,
579}
580
581pub struct WindowInitedArgs<'a> {
583 pub window: &'a winit::window::Window,
585
586 pub context: &'a mut dyn OpenGlContext,
588}
589
590pub struct WindowDeinitedArgs<'a> {
592 pub window: &'a winit::window::Window,
594
595 pub context: &'a mut dyn OpenGlContext,
597}
598
599pub struct WindowCommandArgs<'a> {
601 pub window: &'a winit::window::Window,
603
604 pub context: &'a mut dyn OpenGlContext,
606
607 pub request: ApiExtensionPayload,
609}
610
611pub struct WindowEventArgs<'a> {
613 pub window: &'a winit::window::Window,
615
616 pub context: &'a mut dyn OpenGlContext,
618
619 pub event: &'a winit::event::WindowEvent,
621}
622
623pub trait OpenGlContext {
625 fn is_current(&self) -> bool;
627
628 fn make_current(&mut self);
630
631 fn gl(&self) -> &Rc<dyn gleam::gl::Gl>;
633
634 fn render_mode(&self) -> RenderMode;
636
637 fn resize(&mut self, size: PxSize);
639
640 fn is_software(&self) -> bool;
642
643 fn swap_buffers(&mut self);
645}
646impl OpenGlContext for crate::gl::GlContext {
647 fn is_current(&self) -> bool {
648 self.is_current()
649 }
650
651 fn make_current(&mut self) {
652 self.make_current()
653 }
654
655 fn gl(&self) -> &Rc<dyn gleam::gl::Gl> {
656 self.gl()
657 }
658
659 fn render_mode(&self) -> RenderMode {
660 self.render_mode()
661 }
662
663 fn resize(&mut self, size: PxSize) {
664 self.resize(size.to_winit())
665 }
666
667 fn is_software(&self) -> bool {
668 self.is_software()
669 }
670
671 fn swap_buffers(&mut self) {
672 self.swap_buffers()
673 }
674}
675
676pub struct RendererCommandArgs<'a> {
678 pub renderer: &'a mut webrender::Renderer,
680
681 pub api: &'a mut RenderApi,
683
684 pub request: ApiExtensionPayload,
686
687 pub window: Option<&'a winit::window::Window>,
689
690 pub context: &'a mut dyn OpenGlContext,
692
693 pub redraw: &'a mut bool,
697}
698
699pub struct ViewExtensions {
701 exts: Vec<Box<dyn ViewExtension>>,
702}
703impl ViewExtensions {
704 pub(crate) fn new() -> Self {
706 Self { exts: vec![] }
707 }
708
709 pub fn register<E: ViewExtension>(&mut self, ext: impl FnOnce(ApiExtensionId) -> E) -> &mut Self {
717 let id = ApiExtensionId::from_index(self.exts.len());
718 let ext = ext(id);
719 assert!(self.id(ext.name()).is_none(), "extension already registered");
720 self.exts.push(Box::new(ext));
721 self
722 }
723
724 pub fn id(&self, name: &ApiExtensionName) -> Option<ApiExtensionId> {
726 self.exts.iter().position(|e| e.name() == name).map(ApiExtensionId::from_index)
727 }
728
729 pub fn command_raw(
733 &mut self,
734 name: impl Into<ApiExtensionName>,
735 handler: impl FnMut(ApiExtensionPayload, ApiExtensionId) -> ApiExtensionPayload + Send + 'static,
736 ) -> &mut Self {
737 struct CommandExt<F>(ApiExtensionName, ApiExtensionId, F);
738 impl<F: FnMut(ApiExtensionPayload, ApiExtensionId) -> ApiExtensionPayload + Send + 'static> ViewExtension for CommandExt<F> {
739 fn name(&self) -> &ApiExtensionName {
740 &self.0
741 }
742 fn command(&mut self, request: ApiExtensionPayload) -> Option<ApiExtensionPayload> {
743 Some((self.2)(request, self.1))
744 }
745 }
746
747 self.register(|id| CommandExt(name.into(), id, handler));
748 self
749 }
750
751 pub fn command<I: serde::de::DeserializeOwned, O: serde::Serialize>(
755 &mut self,
756 name: impl Into<ApiExtensionName>,
757 mut handler: impl FnMut(I, ApiExtensionId) -> O + Send + 'static,
758 ) -> &mut Self {
759 self.command_raw(name, move |p, id| match p.deserialize::<I>() {
760 Ok(p) => {
761 let o = handler(p, id);
762 ApiExtensionPayload::serialize(&o).unwrap()
763 }
764 Err(e) => ApiExtensionPayload::invalid_request(id, e),
765 })
766 }
767
768 pub fn window<E: WindowExtension>(
770 &mut self,
771 name: impl Into<ApiExtensionName>,
772 new: impl FnMut(ApiExtensionId) -> E + Send + 'static,
773 ) -> &mut Self {
774 struct WindowExt<F>(ApiExtensionName, ApiExtensionId, F);
775 impl<E, F> ViewExtension for WindowExt<F>
776 where
777 E: WindowExtension,
778 F: FnMut(ApiExtensionId) -> E + Send + 'static,
779 {
780 fn name(&self) -> &ApiExtensionName {
781 &self.0
782 }
783
784 fn window(&mut self) -> Option<Box<dyn WindowExtension>> {
785 Some(Box::new((self.2)(self.1)))
786 }
787 }
788 self.register(move |id| WindowExt(name.into(), id, new));
789 self
790 }
791
792 pub fn renderer<E: RendererExtension>(
794 &mut self,
795 name: impl Into<ApiExtensionName>,
796 new: impl FnMut(ApiExtensionId) -> E + Send + 'static,
797 ) -> &mut Self {
798 struct RendererExt<F>(ApiExtensionName, ApiExtensionId, F);
799 impl<E, F> ViewExtension for RendererExt<F>
800 where
801 E: RendererExtension,
802 F: FnMut(ApiExtensionId) -> E + Send + 'static,
803 {
804 fn name(&self) -> &ApiExtensionName {
805 &self.0
806 }
807
808 fn renderer(&mut self) -> Option<Box<dyn RendererExtension>> {
809 Some(Box::new((self.2)(self.1)))
810 }
811 }
812 self.register(move |id| RendererExt(name.into(), id, new));
813 self
814 }
815
816 pub(crate) fn api_extensions(&self) -> ApiExtensions {
817 let mut r = ApiExtensions::new();
818 for ext in &self.exts {
819 r.insert(ext.name().clone()).unwrap();
820 }
821 r
822 }
823
824 pub(crate) fn call_command(&mut self, id: ApiExtensionId, request: ApiExtensionPayload) -> ApiExtensionPayload {
825 let idx = id.index();
826 if idx >= self.exts.len() {
827 ApiExtensionPayload::unknown_extension(id)
828 } else if let Some(r) = self.exts[idx].command(request) {
829 r
830 } else {
831 ApiExtensionPayload::unknown_extension(id)
832 }
833 }
834
835 pub(crate) fn new_window(&mut self) -> Vec<(ApiExtensionId, Box<dyn WindowExtension>)> {
836 self.exts
837 .iter_mut()
838 .enumerate()
839 .filter_map(|(i, e)| e.window().map(|e| (ApiExtensionId::from_index(i), e)))
840 .collect()
841 }
842
843 pub(crate) fn new_renderer(&mut self) -> Vec<(ApiExtensionId, Box<dyn RendererExtension>)> {
844 self.exts
845 .iter_mut()
846 .enumerate()
847 .filter_map(|(i, e)| e.renderer().map(|e| (ApiExtensionId::from_index(i), e)))
848 .collect()
849 }
850
851 pub(crate) fn init(&mut self, event_sender: &crate::AppEventSender) {
852 for (i, ext) in self.exts.iter_mut().enumerate() {
853 ext.init(ViewExtensionInitArgs {
854 event_sender: ExtensionEventSender {
855 sender: event_sender.clone(),
856 id: ApiExtensionId::from_index(i),
857 },
858 });
859 }
860 }
861
862 pub(crate) fn on_low_memory(&mut self) {
863 for ext in self.exts.iter_mut() {
864 ext.low_memory();
865 }
866 }
867
868 pub(crate) fn suspended(&mut self) {
869 for ext in self.exts.iter_mut() {
870 ext.suspended();
871 }
872 }
873
874 pub(crate) fn resumed(&mut self) {
875 for ext in self.exts.iter_mut() {
876 ext.resumed();
877 }
878 }
879
880 pub fn append(&mut self, mut other: ViewExtensions) {
882 self.exts.append(&mut other.exts);
883 }
884}
885
886#[cfg(windows)]
887pub(crate) struct PreferAngleExt {
888 pub(crate) prefer_egl: bool,
889}
890#[cfg(windows)]
891impl PreferAngleExt {
892 pub(crate) fn new(_: ApiExtensionId) -> Self {
893 Self { prefer_egl: false }
894 }
895}
896#[cfg(windows)]
897impl WindowExtension for PreferAngleExt {
898 fn is_init_only(&self) -> bool {
899 true
900 }
901
902 fn configure(&mut self, args: &mut WindowConfigArgs) {
903 if let Some(cfg) = args.config {
904 match cfg.deserialize::<bool>() {
905 Ok(y) => self.prefer_egl = y,
906 Err(e) => tracing::error!("invalid arg for 'zng-view.prefer_angle', {e}"),
907 }
908 }
909 }
910
911 fn as_any(&self) -> &dyn Any {
912 self
913 }
914
915 fn as_any_mut(&mut self) -> &mut dyn Any {
916 self
917 }
918}
919
920pub(crate) struct RendererDebugExt {
924 id: ApiExtensionId,
925 ui: Option<String>,
926}
927
928impl RendererDebugExt {
929 pub(crate) fn new(id: ApiExtensionId) -> Self {
930 Self { id, ui: None }
931 }
932}
933impl RendererExtension for RendererDebugExt {
934 fn is_init_only(&self) -> bool {
935 false
936 }
937
938 fn configure(&mut self, args: &mut RendererConfigArgs) {
939 if let Some(cfg) = args.config.as_ref().and_then(|c| c.deserialize::<RendererDebug>().ok()) {
940 args.options.debug_flags = cfg.flags;
941 self.ui = Some(cfg.profiler_ui);
942 }
943 }
944
945 fn renderer_inited(&mut self, args: &mut RendererInitedArgs) {
946 if let Some(ui) = self.ui.take() {
947 args.renderer.set_profiler_ui(&ui);
948 }
949 }
950
951 fn command(&mut self, args: &mut RendererCommandArgs) -> ApiExtensionPayload {
952 match args.request.deserialize::<RendererDebug>() {
953 Ok(cfg) => {
954 args.renderer.set_debug_flags(cfg.flags);
955 args.renderer.set_profiler_ui(&cfg.profiler_ui);
956 ApiExtensionPayload::empty()
957 }
958 Err(e) => ApiExtensionPayload::invalid_request(self.id, e),
959 }
960 }
961
962 fn as_any(&self) -> &dyn Any {
963 self
964 }
965
966 fn as_any_mut(&mut self) -> &mut dyn Any {
967 self
968 }
969}
970
971#[derive(serde::Serialize, serde::Deserialize)]
973struct RendererDebug {
974 pub flags: DebugFlags,
975 pub profiler_ui: String,
976}
977
978pub(crate) struct DisplayListExtAdapter<'a> {
979 pub extensions: &'a mut Vec<(ApiExtensionId, Box<dyn RendererExtension>)>,
980 pub transaction: &'a mut webrender::Transaction,
981 pub renderer: &'a mut webrender::Renderer,
982 pub api: &'a mut RenderApi,
983 pub external_images: &'a mut ExternalImages,
984 pub frame_id: zng_view_api::window::FrameId,
985}
986
987impl DisplayListExtension for DisplayListExtAdapter<'_> {
988 fn display_list_start(&mut self, args: &mut DisplayExtensionArgs) {
989 for (_, ext) in self.extensions.iter_mut() {
990 ext.render_start(&mut RenderArgs {
991 frame_id: self.frame_id,
992 list: args.list,
993 sc: args.sc,
994 transaction: self.transaction,
995 renderer: self.renderer,
996 api: self.api,
997 external_images: self.external_images,
998 });
999 }
1000 }
1001
1002 fn push_display_item(&mut self, args: &mut DisplayExtensionItemArgs) {
1003 for (id, ext) in self.extensions.iter_mut() {
1004 if *id == args.extension_id {
1005 ext.render_push(&mut RenderItemArgs {
1006 extension_id: args.extension_id,
1007 payload: args.payload,
1008 is_reuse: args.is_reuse,
1009 list: args.list,
1010 sc: args.sc,
1011 transaction: self.transaction,
1012 renderer: self.renderer,
1013 api: self.api,
1014 external_images: self.external_images,
1015 });
1016 break;
1017 }
1018 }
1019 }
1020
1021 fn pop_display_item(&mut self, args: &mut DisplayExtensionItemArgs) {
1022 for (id, ext) in self.extensions.iter_mut() {
1023 if *id == args.extension_id {
1024 ext.render_pop(&mut RenderItemArgs {
1025 extension_id: args.extension_id,
1026 payload: args.payload,
1027 is_reuse: args.is_reuse,
1028 list: args.list,
1029 sc: args.sc,
1030 transaction: self.transaction,
1031 renderer: self.renderer,
1032 api: self.api,
1033 external_images: self.external_images,
1034 });
1035 break;
1036 }
1037 }
1038 }
1039
1040 fn display_list_end(&mut self, args: &mut DisplayExtensionArgs) {
1041 for (_, ext) in self.extensions.iter_mut() {
1042 ext.render_end(&mut RenderArgs {
1043 frame_id: self.frame_id,
1044 list: args.list,
1045 sc: args.sc,
1046 transaction: self.transaction,
1047 renderer: self.renderer,
1048 api: self.api,
1049 external_images: self.external_images,
1050 });
1051 }
1052 }
1053
1054 fn update(&mut self, args: &mut DisplayExtensionUpdateArgs) {
1055 for (id, ext) in self.extensions.iter_mut() {
1056 if *id == args.extension_id {
1057 let mut r_args = RenderUpdateArgs {
1058 extension_id: args.extension_id,
1059 payload: args.payload,
1060 new_frame: args.new_frame,
1061 properties: args.properties,
1062 transaction: self.transaction,
1063 renderer: self.renderer,
1064 api: self.api,
1065 external_images: self.external_images,
1066 };
1067 ext.render_update(&mut r_args);
1068 args.new_frame = r_args.new_frame;
1069 break;
1070 }
1071 }
1072 }
1073}
1074
1075pub(crate) struct BlobExtensionsImgHandler(pub Vec<Box<dyn BlobExtension>>);
1076
1077impl BlobImageHandler for BlobExtensionsImgHandler {
1078 fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobImageRasterizer> {
1079 Box::new(BlockExtensionsImgRasterizer(
1080 self.0.iter_mut().map(|t| t.create_blob_rasterizer()).collect(),
1081 ))
1082 }
1083
1084 fn create_similar(&self) -> Box<dyn BlobImageHandler> {
1085 Box::new(Self(self.0.iter().map(|e| e.create_similar()).collect()))
1086 }
1087
1088 fn prepare_resources(&mut self, services: &dyn webrender::api::BlobImageResources, requests: &[BlobImageParams]) {
1089 for ext in self.0.iter_mut() {
1090 ext.prepare_resources(&mut BlobPrepareArgs { services, requests })
1091 }
1092 }
1093
1094 fn add(
1095 &mut self,
1096 key: webrender::api::BlobImageKey,
1097 data: std::sync::Arc<webrender::api::BlobImageData>,
1098 visible_rect: &webrender::api::units::DeviceIntRect,
1099 tile_size: webrender::api::TileSize,
1100 ) {
1101 let args = BlobAddArgs {
1102 key,
1103 data,
1104 visible_rect: *visible_rect,
1105 tile_size,
1106 };
1107 for ext in self.0.iter_mut() {
1108 ext.add(&args);
1109 }
1110 }
1111
1112 fn update(
1113 &mut self,
1114 key: webrender::api::BlobImageKey,
1115 data: std::sync::Arc<webrender::api::BlobImageData>,
1116 visible_rect: &webrender::api::units::DeviceIntRect,
1117 dirty_rect: &webrender::api::units::BlobDirtyRect,
1118 ) {
1119 let args = BlobUpdateArgs {
1120 key,
1121 data,
1122 visible_rect: *visible_rect,
1123 dirty_rect: *dirty_rect,
1124 };
1125 for ext in self.0.iter_mut() {
1126 ext.update(&args);
1127 }
1128 }
1129
1130 fn delete(&mut self, key: webrender::api::BlobImageKey) {
1131 for ext in self.0.iter_mut() {
1132 ext.delete(key);
1133 }
1134 }
1135
1136 fn delete_font(&mut self, key: webrender::api::FontKey) {
1137 for ext in self.0.iter_mut() {
1138 ext.delete_font(key);
1139 }
1140 }
1141
1142 fn delete_font_instance(&mut self, key: webrender::api::FontInstanceKey) {
1143 for ext in self.0.iter_mut() {
1144 ext.delete_font_instance(key);
1145 }
1146 }
1147
1148 fn clear_namespace(&mut self, namespace: webrender::api::IdNamespace) {
1149 for ext in self.0.iter_mut() {
1150 ext.clear_namespace(namespace);
1151 }
1152 }
1153
1154 fn enable_multithreading(&mut self, enable: bool) {
1155 for ext in self.0.iter_mut() {
1156 ext.enable_multithreading(enable);
1157 }
1158 }
1159}
1160
1161struct BlockExtensionsImgRasterizer(Vec<Box<dyn AsyncBlobRasterizer>>);
1162impl AsyncBlobImageRasterizer for BlockExtensionsImgRasterizer {
1163 fn rasterize(
1164 &mut self,
1165 requests: &[BlobImageParams],
1166 low_priority: bool,
1167 tile_pool: &mut crate::BlobTilePool,
1168 ) -> Vec<(BlobImageRequest, BlobImageResult)> {
1169 let mut responses = vec![];
1170 for r in &mut self.0 {
1171 r.rasterize(&mut BlobRasterizerArgs {
1172 requests,
1173 low_priority,
1174 tile_pool,
1175 responses: &mut responses,
1176 })
1177 }
1178 responses
1179 }
1180}
1181
1182#[macro_export]
1186macro_rules! view_process_extension {
1187 ($closure:expr) => {
1188 #[used]
1193 #[cfg_attr(
1194 any(
1195 target_os = "none",
1196 target_os = "linux",
1197 target_os = "android",
1198 target_os = "fuchsia",
1199 target_os = "psp"
1200 ),
1201 unsafe(link_section = "linkme_VIEW_EXTENSIONS")
1202 )]
1203 #[cfg_attr(
1204 any(target_os = "macos", target_os = "ios", target_os = "tvos"),
1205 unsafe(link_section = "__DATA,__linkmeTbhLJz52,regular,no_dead_strip")
1206 )]
1207 #[cfg_attr(
1208 any(target_os = "uefi", target_os = "windows"),
1209 unsafe(link_section = ".linkme_VIEW_EXTENSIONS$b")
1210 )]
1211 #[cfg_attr(target_os = "illumos", unsafe(link_section = "set_linkme_VIEW_EXTENSIONS"))]
1212 #[cfg_attr(
1213 any(target_os = "freebsd", target_os = "openbsd"),
1214 unsafe(link_section = "linkme_VIEW_EXTENSIONS")
1215 )]
1216 #[doc(hidden)]
1217 static _VIEW_EXTENSIONS: fn(&mut $crate::extensions::ViewExtensions) = _view_extensions;
1218 #[doc(hidden)]
1219 fn _view_extensions(ext: &mut $crate::extensions::ViewExtensions) {
1220 fn view_extensions(
1221 ext: &mut $crate::extensions::ViewExtensions,
1222 handler: impl FnOnce(&mut $crate::extensions::ViewExtensions),
1223 ) {
1224 handler(ext)
1225 }
1226 view_extensions(ext, $closure)
1227 }
1228 };
1229}
1230
1231#[doc(hidden)]
1232#[linkme::distributed_slice]
1233pub static VIEW_EXTENSIONS: [fn(&mut ViewExtensions)];