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
194#[non_exhaustive]
196pub struct RenderArgs<'a> {
197 pub frame_id: zng_view_api::window::FrameId,
199
200 pub list: &'a mut webrender::api::DisplayListBuilder,
202 pub sc: &'a mut SpaceAndClip,
204
205 pub transaction: &'a mut webrender::Transaction,
207
208 pub renderer: &'a mut webrender::Renderer,
210 pub api: &'a mut RenderApi,
212 pub external_images: &'a mut ExternalImages,
214}
215
216#[non_exhaustive]
218pub struct RenderItemArgs<'a> {
219 pub extension_id: ApiExtensionId,
221 pub payload: &'a ApiExtensionPayload,
223 pub is_reuse: bool,
228
229 pub list: &'a mut webrender::api::DisplayListBuilder,
231 pub sc: &'a mut SpaceAndClip,
233
234 pub transaction: &'a mut webrender::Transaction,
236
237 pub renderer: &'a mut webrender::Renderer,
239 pub api: &'a mut RenderApi,
241 pub external_images: &'a mut ExternalImages,
243}
244
245#[non_exhaustive]
247pub struct RenderUpdateArgs<'a> {
248 pub extension_id: ApiExtensionId,
250 pub payload: &'a ApiExtensionPayload,
252
253 pub new_frame: bool,
258
259 pub properties: &'a mut webrender::api::DynamicProperties,
264
265 pub transaction: &'a mut webrender::Transaction,
267
268 pub renderer: &'a mut webrender::Renderer,
270 pub api: &'a mut RenderApi,
272 pub external_images: &'a mut ExternalImages,
274}
275
276#[non_exhaustive]
278pub struct FrameReadyArgs {
279 pub frame_id: zng_view_api::window::FrameId,
281 pub redraw: bool,
286}
287
288#[non_exhaustive]
290pub struct RedrawArgs<'a> {
291 pub scale_factor: Factor,
293
294 pub size: PxSize,
296
297 pub context: &'a mut dyn OpenGlContext,
301}
302
303pub trait BlobExtension: Send + Any {
311 fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobRasterizer>;
313
314 fn create_similar(&self) -> Box<dyn BlobExtension>;
316
317 fn prepare_resources(&mut self, args: &mut BlobPrepareArgs) {
321 let _ = args;
322 }
323
324 fn add(&mut self, args: &BlobAddArgs);
326 fn update(&mut self, args: &BlobUpdateArgs);
328
329 fn delete(&mut self, key: webrender::api::BlobImageKey);
331
332 fn delete_font(&mut self, key: webrender::api::FontKey) {
334 let _ = key;
335 }
336
337 fn delete_font_instance(&mut self, key: webrender::api::FontInstanceKey) {
339 let _ = key;
340 }
341
342 fn clear_namespace(&mut self, namespace: webrender::api::IdNamespace) {
344 let _ = namespace;
345 }
346
347 fn enable_multithreading(&mut self, enable: bool);
351}
352
353#[non_exhaustive]
355pub struct ViewExtensionInitArgs {
356 pub event_sender: ExtensionEventSender,
358}
359
360#[derive(Clone)]
364pub struct ExtensionEventSender {
365 sender: crate::AppEventSender,
366 id: ApiExtensionId,
367}
368impl ExtensionEventSender {
369 pub fn send(&self, payload: ApiExtensionPayload) -> Result<(), zng_view_api::ipc::ViewChannelError> {
371 self.sender.send(crate::AppEvent::Notify(Event::ExtensionEvent(self.id, payload)))
372 }
373}
374
375pub trait AsyncBlobRasterizer: Send + Any {
377 fn rasterize(&mut self, args: &mut BlobRasterizerArgs);
382}
383
384#[non_exhaustive]
386pub struct BlobPrepareArgs<'a> {
387 pub services: &'a dyn webrender::api::BlobImageResources,
389 pub requests: &'a [BlobImageParams],
392}
393
394#[non_exhaustive]
396pub struct BlobAddArgs {
397 pub key: webrender::api::BlobImageKey,
401 pub data: std::sync::Arc<webrender::api::BlobImageData>,
403
404 pub visible_rect: webrender::api::units::DeviceIntRect,
406 pub tile_size: webrender::api::TileSize,
408}
409
410#[non_exhaustive]
412pub struct BlobUpdateArgs {
413 pub key: webrender::api::BlobImageKey,
417 pub data: std::sync::Arc<webrender::api::BlobImageData>,
419 pub visible_rect: webrender::api::units::DeviceIntRect,
421 pub dirty_rect: webrender::api::units::BlobDirtyRect,
423}
424
425#[non_exhaustive]
427pub struct BlobRasterizerArgs<'a> {
428 pub requests: &'a [BlobImageParams],
432 pub low_priority: bool,
435
436 pub tile_pool: &'a mut webrender::api::BlobTilePool,
438
439 pub responses: &'a mut Vec<(BlobImageRequest, BlobImageResult)>,
444}
445
446#[non_exhaustive]
448pub struct WindowConfigArgs<'a> {
449 pub config: Option<&'a ApiExtensionPayload>,
453
454 pub window: Option<&'a mut winit::window::WindowAttributes>,
456}
457
458#[non_exhaustive]
460pub struct RendererConfigArgs<'a> {
461 pub config: Option<&'a ApiExtensionPayload>,
465
466 pub options: &'a mut webrender::WebRenderOptions,
475
476 pub blobs: &'a mut Vec<Box<dyn BlobExtension>>,
480
481 pub window: Option<&'a winit::window::Window>,
483
484 pub context: &'a mut dyn OpenGlContext,
486}
487
488#[non_exhaustive]
490pub struct RendererInitedArgs<'a> {
491 pub renderer: &'a mut webrender::Renderer,
498
499 pub api_sender: &'a webrender::RenderApiSender,
501
502 pub api: &'a mut RenderApi,
504
505 pub document_id: DocumentId,
507
508 pub pipeline_id: PipelineId,
510
511 pub window: Option<&'a winit::window::Window>,
513
514 pub context: &'a mut dyn OpenGlContext,
518
519 pub external_images: &'a mut ExternalImages,
521}
522
523#[derive(Default)]
525pub struct ExternalImages {
526 images: Vec<Arc<crate::image_cache::ImageData>>,
527}
528impl ExternalImages {
529 pub fn register_texture(&mut self, uv: TexelRect, texture: gleam::gl::GLuint) -> ExternalImageId {
539 self.register(crate::image_cache::ImageData::NativeTexture { uv, texture })
540 }
541
542 pub fn register_image(&mut self, descriptor: webrender::api::ImageDescriptor, pixels: zng_view_api::ipc::IpcBytes) -> ExternalImageId {
550 self.register(crate::image_cache::ImageData::RawData {
551 size: descriptor.size.cast().cast_unit(), pixels,
553 descriptor,
554 density: None,
555 })
556 }
557
558 pub fn unregister(&mut self, id: ExternalImageId) {
563 if let Some(i) = self.images.iter().position(|img| ExternalImageId(Arc::as_ptr(img) as u64) == id) {
564 self.images.swap_remove(i);
565 }
566 }
567
568 fn register(&mut self, img: crate::image_cache::ImageData) -> ExternalImageId {
569 let img = Arc::new(img);
570 let id = ExternalImageId(Arc::as_ptr(&img) as u64);
571 self.images.push(img);
572 id
573 }
574}
575
576#[non_exhaustive]
578pub struct RendererDeinitedArgs<'a> {
579 pub document_id: DocumentId,
581
582 pub pipeline_id: PipelineId,
584
585 pub window: Option<&'a winit::window::Window>,
587
588 pub context: &'a mut dyn OpenGlContext,
593}
594
595#[non_exhaustive]
597pub struct WindowInitedArgs<'a> {
598 pub window: &'a winit::window::Window,
600
601 pub context: &'a mut dyn OpenGlContext,
603}
604
605#[non_exhaustive]
607pub struct WindowDeinitedArgs<'a> {
608 pub window: &'a winit::window::Window,
610
611 pub context: &'a mut dyn OpenGlContext,
613}
614
615#[non_exhaustive]
617pub struct WindowCommandArgs<'a> {
618 pub window: &'a winit::window::Window,
620
621 pub context: &'a mut dyn OpenGlContext,
623
624 pub request: ApiExtensionPayload,
626}
627
628#[non_exhaustive]
630pub struct WindowEventArgs<'a> {
631 pub window: &'a winit::window::Window,
633
634 pub context: &'a mut dyn OpenGlContext,
636
637 pub event: &'a winit::event::WindowEvent,
639}
640
641pub trait OpenGlContext {
643 fn is_current(&self) -> bool;
645
646 fn make_current(&mut self);
648
649 fn gl(&self) -> &Rc<dyn gleam::gl::Gl>;
651
652 fn render_mode(&self) -> RenderMode;
654
655 fn resize(&mut self, size: PxSize);
657
658 fn is_software(&self) -> bool;
660
661 fn swap_buffers(&mut self);
663}
664impl OpenGlContext for crate::gl::GlContext {
665 fn is_current(&self) -> bool {
666 self.is_current()
667 }
668
669 fn make_current(&mut self) {
670 self.make_current()
671 }
672
673 fn gl(&self) -> &Rc<dyn gleam::gl::Gl> {
674 self.gl()
675 }
676
677 fn render_mode(&self) -> RenderMode {
678 self.render_mode()
679 }
680
681 fn resize(&mut self, size: PxSize) {
682 self.resize(size.to_winit())
683 }
684
685 fn is_software(&self) -> bool {
686 self.is_software()
687 }
688
689 fn swap_buffers(&mut self) {
690 self.swap_buffers()
691 }
692}
693
694#[non_exhaustive]
696pub struct RendererCommandArgs<'a> {
697 pub renderer: &'a mut webrender::Renderer,
699
700 pub api: &'a mut RenderApi,
702
703 pub request: ApiExtensionPayload,
705
706 pub window: Option<&'a winit::window::Window>,
708
709 pub context: &'a mut dyn OpenGlContext,
711
712 pub redraw: &'a mut bool,
716}
717
718pub struct ViewExtensions {
720 exts: Vec<Box<dyn ViewExtension>>,
721}
722impl ViewExtensions {
723 pub(crate) fn new() -> Self {
725 Self { exts: vec![] }
726 }
727
728 pub fn register<E: ViewExtension>(&mut self, ext: impl FnOnce(ApiExtensionId) -> E) -> &mut Self {
736 let id = ApiExtensionId::from_index(self.exts.len());
737 let ext = ext(id);
738 assert!(self.id(ext.name()).is_none(), "extension already registered");
739 self.exts.push(Box::new(ext));
740 self
741 }
742
743 pub fn id(&self, name: &ApiExtensionName) -> Option<ApiExtensionId> {
745 self.exts.iter().position(|e| e.name() == name).map(ApiExtensionId::from_index)
746 }
747
748 pub fn command_raw(
752 &mut self,
753 name: impl Into<ApiExtensionName>,
754 handler: impl FnMut(ApiExtensionPayload, ApiExtensionId) -> ApiExtensionPayload + Send + 'static,
755 ) -> &mut Self {
756 struct CommandExt<F>(ApiExtensionName, ApiExtensionId, F);
757 impl<F: FnMut(ApiExtensionPayload, ApiExtensionId) -> ApiExtensionPayload + Send + 'static> ViewExtension for CommandExt<F> {
758 fn name(&self) -> &ApiExtensionName {
759 &self.0
760 }
761 fn command(&mut self, request: ApiExtensionPayload) -> Option<ApiExtensionPayload> {
762 Some((self.2)(request, self.1))
763 }
764 }
765
766 self.register(|id| CommandExt(name.into(), id, handler));
767 self
768 }
769
770 pub fn command<I: serde::de::DeserializeOwned, O: serde::Serialize>(
774 &mut self,
775 name: impl Into<ApiExtensionName>,
776 mut handler: impl FnMut(I, ApiExtensionId) -> O + Send + 'static,
777 ) -> &mut Self {
778 self.command_raw(name, move |p, id| match p.deserialize::<I>() {
779 Ok(p) => {
780 let o = handler(p, id);
781 ApiExtensionPayload::serialize(&o).unwrap()
782 }
783 Err(e) => ApiExtensionPayload::invalid_request(id, e),
784 })
785 }
786
787 pub fn window<E: WindowExtension>(
789 &mut self,
790 name: impl Into<ApiExtensionName>,
791 new: impl FnMut(ApiExtensionId) -> E + Send + 'static,
792 ) -> &mut Self {
793 struct WindowExt<F>(ApiExtensionName, ApiExtensionId, F);
794 impl<E, F> ViewExtension for WindowExt<F>
795 where
796 E: WindowExtension,
797 F: FnMut(ApiExtensionId) -> E + Send + 'static,
798 {
799 fn name(&self) -> &ApiExtensionName {
800 &self.0
801 }
802
803 fn window(&mut self) -> Option<Box<dyn WindowExtension>> {
804 Some(Box::new((self.2)(self.1)))
805 }
806 }
807 self.register(move |id| WindowExt(name.into(), id, new));
808 self
809 }
810
811 pub fn renderer<E: RendererExtension>(
813 &mut self,
814 name: impl Into<ApiExtensionName>,
815 new: impl FnMut(ApiExtensionId) -> E + Send + 'static,
816 ) -> &mut Self {
817 struct RendererExt<F>(ApiExtensionName, ApiExtensionId, F);
818 impl<E, F> ViewExtension for RendererExt<F>
819 where
820 E: RendererExtension,
821 F: FnMut(ApiExtensionId) -> E + Send + 'static,
822 {
823 fn name(&self) -> &ApiExtensionName {
824 &self.0
825 }
826
827 fn renderer(&mut self) -> Option<Box<dyn RendererExtension>> {
828 Some(Box::new((self.2)(self.1)))
829 }
830 }
831 self.register(move |id| RendererExt(name.into(), id, new));
832 self
833 }
834
835 pub(crate) fn api_extensions(&self) -> ApiExtensions {
836 let mut r = ApiExtensions::new();
837 for ext in &self.exts {
838 r.insert(ext.name().clone()).unwrap();
839 }
840 r
841 }
842
843 pub(crate) fn call_command(&mut self, id: ApiExtensionId, request: ApiExtensionPayload) -> ApiExtensionPayload {
844 let idx = id.index();
845 if idx >= self.exts.len() {
846 ApiExtensionPayload::unknown_extension(id)
847 } else if let Some(r) = self.exts[idx].command(request) {
848 r
849 } else {
850 ApiExtensionPayload::unknown_extension(id)
851 }
852 }
853
854 pub(crate) fn new_window(&mut self) -> Vec<(ApiExtensionId, Box<dyn WindowExtension>)> {
855 self.exts
856 .iter_mut()
857 .enumerate()
858 .filter_map(|(i, e)| e.window().map(|e| (ApiExtensionId::from_index(i), e)))
859 .collect()
860 }
861
862 pub(crate) fn new_renderer(&mut self) -> Vec<(ApiExtensionId, Box<dyn RendererExtension>)> {
863 self.exts
864 .iter_mut()
865 .enumerate()
866 .filter_map(|(i, e)| e.renderer().map(|e| (ApiExtensionId::from_index(i), e)))
867 .collect()
868 }
869
870 pub(crate) fn init(&mut self, event_sender: &crate::AppEventSender) {
871 for (i, ext) in self.exts.iter_mut().enumerate() {
872 ext.init(ViewExtensionInitArgs {
873 event_sender: ExtensionEventSender {
874 sender: event_sender.clone(),
875 id: ApiExtensionId::from_index(i),
876 },
877 });
878 }
879 }
880
881 pub(crate) fn on_low_memory(&mut self) {
882 for ext in self.exts.iter_mut() {
883 ext.low_memory();
884 }
885 }
886
887 pub(crate) fn suspended(&mut self) {
888 for ext in self.exts.iter_mut() {
889 ext.suspended();
890 }
891 }
892
893 pub(crate) fn resumed(&mut self) {
894 for ext in self.exts.iter_mut() {
895 ext.resumed();
896 }
897 }
898
899 pub fn append(&mut self, mut other: ViewExtensions) {
901 self.exts.append(&mut other.exts);
902 }
903}
904
905#[cfg(windows)]
906pub(crate) struct PreferAngleExt {
907 pub(crate) prefer_egl: bool,
908}
909#[cfg(windows)]
910impl PreferAngleExt {
911 pub(crate) fn new(_: ApiExtensionId) -> Self {
912 Self { prefer_egl: false }
913 }
914}
915#[cfg(windows)]
916impl WindowExtension for PreferAngleExt {
917 fn is_init_only(&self) -> bool {
918 true
919 }
920
921 fn configure(&mut self, args: &mut WindowConfigArgs) {
922 if let Some(cfg) = args.config {
923 match cfg.deserialize::<bool>() {
924 Ok(y) => self.prefer_egl = y,
925 Err(e) => tracing::error!("invalid arg for 'zng-view.prefer_angle', {e}"),
926 }
927 }
928 }
929
930 fn as_any(&self) -> &dyn Any {
931 self
932 }
933
934 fn as_any_mut(&mut self) -> &mut dyn Any {
935 self
936 }
937}
938
939pub(crate) struct RendererDebugExt {
943 id: ApiExtensionId,
944 ui: Option<String>,
945}
946
947impl RendererDebugExt {
948 pub(crate) fn new(id: ApiExtensionId) -> Self {
949 Self { id, ui: None }
950 }
951}
952impl RendererExtension for RendererDebugExt {
953 fn is_init_only(&self) -> bool {
954 false
955 }
956
957 fn configure(&mut self, args: &mut RendererConfigArgs) {
958 if let Some(cfg) = args.config.as_ref().and_then(|c| c.deserialize::<RendererDebug>().ok()) {
959 args.options.debug_flags = cfg.flags;
960 self.ui = Some(cfg.profiler_ui);
961 }
962 }
963
964 fn renderer_inited(&mut self, args: &mut RendererInitedArgs) {
965 if let Some(ui) = self.ui.take() {
966 args.renderer.set_profiler_ui(&ui);
967 }
968 }
969
970 fn command(&mut self, args: &mut RendererCommandArgs) -> ApiExtensionPayload {
971 match args.request.deserialize::<RendererDebug>() {
972 Ok(cfg) => {
973 args.renderer.set_debug_flags(cfg.flags);
974 args.renderer.set_profiler_ui(&cfg.profiler_ui);
975 ApiExtensionPayload::empty()
976 }
977 Err(e) => ApiExtensionPayload::invalid_request(self.id, e),
978 }
979 }
980
981 fn as_any(&self) -> &dyn Any {
982 self
983 }
984
985 fn as_any_mut(&mut self) -> &mut dyn Any {
986 self
987 }
988}
989
990#[derive(serde::Serialize, serde::Deserialize)]
992struct RendererDebug {
993 pub flags: DebugFlags,
994 pub profiler_ui: String,
995}
996
997pub(crate) struct DisplayListExtAdapter<'a> {
998 pub extensions: &'a mut Vec<(ApiExtensionId, Box<dyn RendererExtension>)>,
999 pub transaction: &'a mut webrender::Transaction,
1000 pub renderer: &'a mut webrender::Renderer,
1001 pub api: &'a mut RenderApi,
1002 pub external_images: &'a mut ExternalImages,
1003 pub frame_id: zng_view_api::window::FrameId,
1004}
1005
1006impl DisplayListExtension for DisplayListExtAdapter<'_> {
1007 fn display_list_start(&mut self, args: &mut DisplayExtensionArgs) {
1008 for (_, ext) in self.extensions.iter_mut() {
1009 ext.render_start(&mut RenderArgs {
1010 frame_id: self.frame_id,
1011 list: args.list,
1012 sc: args.sc,
1013 transaction: self.transaction,
1014 renderer: self.renderer,
1015 api: self.api,
1016 external_images: self.external_images,
1017 });
1018 }
1019 }
1020
1021 fn push_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_push(&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 pop_display_item(&mut self, args: &mut DisplayExtensionItemArgs) {
1041 for (id, ext) in self.extensions.iter_mut() {
1042 if *id == args.extension_id {
1043 ext.render_pop(&mut RenderItemArgs {
1044 extension_id: args.extension_id,
1045 payload: args.payload,
1046 is_reuse: args.is_reuse,
1047 list: args.list,
1048 sc: args.sc,
1049 transaction: self.transaction,
1050 renderer: self.renderer,
1051 api: self.api,
1052 external_images: self.external_images,
1053 });
1054 break;
1055 }
1056 }
1057 }
1058
1059 fn display_list_end(&mut self, args: &mut DisplayExtensionArgs) {
1060 for (_, ext) in self.extensions.iter_mut() {
1061 ext.render_end(&mut RenderArgs {
1062 frame_id: self.frame_id,
1063 list: args.list,
1064 sc: args.sc,
1065 transaction: self.transaction,
1066 renderer: self.renderer,
1067 api: self.api,
1068 external_images: self.external_images,
1069 });
1070 }
1071 }
1072
1073 fn update(&mut self, args: &mut DisplayExtensionUpdateArgs) {
1074 for (id, ext) in self.extensions.iter_mut() {
1075 if *id == args.extension_id {
1076 let mut r_args = RenderUpdateArgs {
1077 extension_id: args.extension_id,
1078 payload: args.payload,
1079 new_frame: args.new_frame,
1080 properties: args.properties,
1081 transaction: self.transaction,
1082 renderer: self.renderer,
1083 api: self.api,
1084 external_images: self.external_images,
1085 };
1086 ext.render_update(&mut r_args);
1087 args.new_frame = r_args.new_frame;
1088 break;
1089 }
1090 }
1091 }
1092}
1093
1094pub(crate) struct BlobExtensionsImgHandler(pub Vec<Box<dyn BlobExtension>>);
1095
1096impl BlobImageHandler for BlobExtensionsImgHandler {
1097 fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobImageRasterizer> {
1098 Box::new(BlockExtensionsImgRasterizer(
1099 self.0.iter_mut().map(|t| t.create_blob_rasterizer()).collect(),
1100 ))
1101 }
1102
1103 fn create_similar(&self) -> Box<dyn BlobImageHandler> {
1104 Box::new(Self(self.0.iter().map(|e| e.create_similar()).collect()))
1105 }
1106
1107 fn prepare_resources(&mut self, services: &dyn webrender::api::BlobImageResources, requests: &[BlobImageParams]) {
1108 for ext in self.0.iter_mut() {
1109 ext.prepare_resources(&mut BlobPrepareArgs { services, requests })
1110 }
1111 }
1112
1113 fn add(
1114 &mut self,
1115 key: webrender::api::BlobImageKey,
1116 data: std::sync::Arc<webrender::api::BlobImageData>,
1117 visible_rect: &webrender::api::units::DeviceIntRect,
1118 tile_size: webrender::api::TileSize,
1119 ) {
1120 let args = BlobAddArgs {
1121 key,
1122 data,
1123 visible_rect: *visible_rect,
1124 tile_size,
1125 };
1126 for ext in self.0.iter_mut() {
1127 ext.add(&args);
1128 }
1129 }
1130
1131 fn update(
1132 &mut self,
1133 key: webrender::api::BlobImageKey,
1134 data: std::sync::Arc<webrender::api::BlobImageData>,
1135 visible_rect: &webrender::api::units::DeviceIntRect,
1136 dirty_rect: &webrender::api::units::BlobDirtyRect,
1137 ) {
1138 let args = BlobUpdateArgs {
1139 key,
1140 data,
1141 visible_rect: *visible_rect,
1142 dirty_rect: *dirty_rect,
1143 };
1144 for ext in self.0.iter_mut() {
1145 ext.update(&args);
1146 }
1147 }
1148
1149 fn delete(&mut self, key: webrender::api::BlobImageKey) {
1150 for ext in self.0.iter_mut() {
1151 ext.delete(key);
1152 }
1153 }
1154
1155 fn delete_font(&mut self, key: webrender::api::FontKey) {
1156 for ext in self.0.iter_mut() {
1157 ext.delete_font(key);
1158 }
1159 }
1160
1161 fn delete_font_instance(&mut self, key: webrender::api::FontInstanceKey) {
1162 for ext in self.0.iter_mut() {
1163 ext.delete_font_instance(key);
1164 }
1165 }
1166
1167 fn clear_namespace(&mut self, namespace: webrender::api::IdNamespace) {
1168 for ext in self.0.iter_mut() {
1169 ext.clear_namespace(namespace);
1170 }
1171 }
1172
1173 fn enable_multithreading(&mut self, enable: bool) {
1174 for ext in self.0.iter_mut() {
1175 ext.enable_multithreading(enable);
1176 }
1177 }
1178}
1179
1180struct BlockExtensionsImgRasterizer(Vec<Box<dyn AsyncBlobRasterizer>>);
1181impl AsyncBlobImageRasterizer for BlockExtensionsImgRasterizer {
1182 fn rasterize(
1183 &mut self,
1184 requests: &[BlobImageParams],
1185 low_priority: bool,
1186 tile_pool: &mut crate::BlobTilePool,
1187 ) -> Vec<(BlobImageRequest, BlobImageResult)> {
1188 let mut responses = vec![];
1189 for r in &mut self.0 {
1190 r.rasterize(&mut BlobRasterizerArgs {
1191 requests,
1192 low_priority,
1193 tile_pool,
1194 responses: &mut responses,
1195 })
1196 }
1197 responses
1198 }
1199}
1200
1201#[macro_export]
1205macro_rules! view_process_extension {
1206 ($closure:expr) => {
1207 #[used]
1212 #[cfg_attr(
1213 any(
1214 target_os = "none",
1215 target_os = "linux",
1216 target_os = "android",
1217 target_os = "fuchsia",
1218 target_os = "psp"
1219 ),
1220 unsafe(link_section = "linkme_VIEW_EXTENSIONS")
1221 )]
1222 #[cfg_attr(
1223 any(target_os = "macos", target_os = "ios", target_os = "tvos"),
1224 unsafe(link_section = "__DATA,__linkmeTbhLJz52,regular,no_dead_strip")
1225 )]
1226 #[cfg_attr(
1227 any(target_os = "uefi", target_os = "windows"),
1228 unsafe(link_section = ".linkme_VIEW_EXTENSIONS$b")
1229 )]
1230 #[cfg_attr(target_os = "illumos", unsafe(link_section = "set_linkme_VIEW_EXTENSIONS"))]
1231 #[cfg_attr(
1232 any(target_os = "freebsd", target_os = "openbsd"),
1233 unsafe(link_section = "linkme_VIEW_EXTENSIONS")
1234 )]
1235 #[doc(hidden)]
1236 static _VIEW_EXTENSIONS: fn(&mut $crate::extensions::ViewExtensions) = _view_extensions;
1237 #[doc(hidden)]
1238 fn _view_extensions(ext: &mut $crate::extensions::ViewExtensions) {
1239 fn view_extensions(
1240 ext: &mut $crate::extensions::ViewExtensions,
1241 handler: impl FnOnce(&mut $crate::extensions::ViewExtensions),
1242 ) {
1243 handler(ext)
1244 }
1245 view_extensions(ext, $closure)
1246 }
1247 };
1248}
1249
1250#[doc(hidden)]
1251#[linkme::distributed_slice]
1252pub static VIEW_EXTENSIONS: [fn(&mut ViewExtensions)];