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(crate) fn api_extensions(&self) -> ApiExtensions {
859 let mut r = ApiExtensions::new();
860 for ext in &self.exts {
861 r.insert(ext.name().clone()).unwrap();
862 }
863 r
864 }
865
866 pub(crate) fn call_command(&mut self, id: ApiExtensionId, request: ApiExtensionPayload) -> ApiExtensionPayload {
867 let idx = id.index();
868 if idx >= self.exts.len() {
869 ApiExtensionPayload::unknown_extension(id)
870 } else if let Some(r) = self.exts[idx].command(request) {
871 r
872 } else {
873 ApiExtensionPayload::unknown_extension(id)
874 }
875 }
876
877 pub(crate) fn new_window(&mut self) -> Vec<(ApiExtensionId, Box<dyn WindowExtension>)> {
878 self.exts
879 .iter_mut()
880 .enumerate()
881 .filter_map(|(i, e)| e.window().map(|e| (ApiExtensionId::from_index(i), e)))
882 .collect()
883 }
884
885 pub(crate) fn new_renderer(&mut self) -> Vec<(ApiExtensionId, Box<dyn RendererExtension>)> {
886 self.exts
887 .iter_mut()
888 .enumerate()
889 .filter_map(|(i, e)| e.renderer().map(|e| (ApiExtensionId::from_index(i), e)))
890 .collect()
891 }
892
893 pub(crate) fn init(&mut self, event_sender: &crate::AppEventSender) {
894 for (i, ext) in self.exts.iter_mut().enumerate() {
895 ext.init(ViewExtensionInitArgs {
896 event_sender: ExtensionEventSender {
897 sender: event_sender.clone(),
898 id: ApiExtensionId::from_index(i),
899 },
900 });
901 }
902 }
903
904 pub(crate) fn on_low_memory(&mut self) {
905 for ext in self.exts.iter_mut() {
906 ext.low_memory();
907 }
908 }
909
910 pub(crate) fn suspended(&mut self) {
911 for ext in self.exts.iter_mut() {
912 ext.suspended();
913 }
914 }
915
916 pub(crate) fn resumed(&mut self) {
917 for ext in self.exts.iter_mut() {
918 ext.resumed();
919 }
920 }
921
922 pub fn append(&mut self, mut other: ViewExtensions) {
924 self.exts.append(&mut other.exts);
925 }
926}
927
928#[cfg(windows)]
929pub(crate) struct PreferAngleExt {
930 pub(crate) prefer_egl: bool,
931}
932#[cfg(windows)]
933impl PreferAngleExt {
934 pub(crate) fn new(_: ApiExtensionId) -> Self {
935 Self { prefer_egl: false }
936 }
937}
938#[cfg(windows)]
939impl WindowExtension for PreferAngleExt {
940 fn is_init_only(&self) -> bool {
941 true
942 }
943
944 fn configure(&mut self, args: &mut WindowConfigArgs) {
945 if let Some(cfg) = args.config {
946 match cfg.deserialize::<bool>() {
947 Ok(y) => self.prefer_egl = y,
948 Err(e) => tracing::error!("invalid arg for 'zng-view.prefer_angle', {e}"),
949 }
950 }
951 }
952
953 fn as_any(&self) -> &dyn Any {
954 self
955 }
956
957 fn as_any_mut(&mut self) -> &mut dyn Any {
958 self
959 }
960}
961
962pub(crate) struct RendererDebugExt {
966 id: ApiExtensionId,
967 ui: Option<String>,
968}
969
970impl RendererDebugExt {
971 pub(crate) fn new(id: ApiExtensionId) -> Self {
972 Self { id, ui: None }
973 }
974}
975impl RendererExtension for RendererDebugExt {
976 fn is_init_only(&self) -> bool {
977 false
978 }
979
980 fn configure(&mut self, args: &mut RendererConfigArgs) {
981 if let Some(cfg) = args.config.as_ref().and_then(|c| c.deserialize::<RendererDebug>().ok()) {
982 args.options.debug_flags = cfg.flags;
983 self.ui = Some(cfg.profiler_ui);
984 }
985 }
986
987 fn renderer_inited(&mut self, args: &mut RendererInitedArgs) {
988 if let Some(ui) = self.ui.take() {
989 args.renderer.set_profiler_ui(&ui);
990 }
991 }
992
993 fn command(&mut self, args: &mut RendererCommandArgs) -> ApiExtensionPayload {
994 match args.request.deserialize::<RendererDebug>() {
995 Ok(cfg) => {
996 args.renderer.set_debug_flags(cfg.flags);
997 args.renderer.set_profiler_ui(&cfg.profiler_ui);
998 ApiExtensionPayload::empty()
999 }
1000 Err(e) => ApiExtensionPayload::invalid_request(self.id, e),
1001 }
1002 }
1003
1004 fn as_any(&self) -> &dyn Any {
1005 self
1006 }
1007
1008 fn as_any_mut(&mut self) -> &mut dyn Any {
1009 self
1010 }
1011}
1012
1013#[derive(serde::Serialize, serde::Deserialize)]
1015struct RendererDebug {
1016 pub flags: DebugFlags,
1017 pub profiler_ui: String,
1018}
1019
1020pub(crate) struct DisplayListExtAdapter<'a> {
1021 pub extensions: &'a mut Vec<(ApiExtensionId, Box<dyn RendererExtension>)>,
1022 pub transaction: &'a mut webrender::Transaction,
1023 pub renderer: &'a mut webrender::Renderer,
1024 pub document_id: DocumentId,
1025 pub api: &'a mut RenderApi,
1026 pub external_images: &'a mut ExternalImages,
1027 pub frame_id: zng_view_api::window::FrameId,
1028}
1029
1030impl DisplayListExtension for DisplayListExtAdapter<'_> {
1031 fn display_list_start(&mut self, args: &mut DisplayExtensionArgs) {
1032 for (_, ext) in self.extensions.iter_mut() {
1033 ext.render_start(&mut RenderArgs {
1034 frame_id: self.frame_id,
1035 list: args.list,
1036 sc: args.sc,
1037 transaction: self.transaction,
1038 renderer: self.renderer,
1039 document_id: self.document_id,
1040 api: self.api,
1041 external_images: self.external_images,
1042 });
1043 }
1044 }
1045
1046 fn push_display_item(&mut self, args: &mut DisplayExtensionItemArgs) {
1047 for (id, ext) in self.extensions.iter_mut() {
1048 if *id == args.extension_id {
1049 ext.render_push(&mut RenderItemArgs {
1050 extension_id: args.extension_id,
1051 payload: args.payload,
1052 is_reuse: args.is_reuse,
1053 list: args.list,
1054 sc: args.sc,
1055 transaction: self.transaction,
1056 renderer: self.renderer,
1057 document_id: self.document_id,
1058 api: self.api,
1059 external_images: self.external_images,
1060 });
1061 break;
1062 }
1063 }
1064 }
1065
1066 fn pop_display_item(&mut self, args: &mut DisplayExtensionItemArgs) {
1067 for (id, ext) in self.extensions.iter_mut() {
1068 if *id == args.extension_id {
1069 ext.render_pop(&mut RenderItemArgs {
1070 extension_id: args.extension_id,
1071 payload: args.payload,
1072 is_reuse: args.is_reuse,
1073 list: args.list,
1074 sc: args.sc,
1075 transaction: self.transaction,
1076 renderer: self.renderer,
1077 document_id: self.document_id,
1078 api: self.api,
1079 external_images: self.external_images,
1080 });
1081 break;
1082 }
1083 }
1084 }
1085
1086 fn display_list_end(&mut self, args: &mut DisplayExtensionArgs) {
1087 for (_, ext) in self.extensions.iter_mut() {
1088 ext.render_end(&mut RenderArgs {
1089 frame_id: self.frame_id,
1090 list: args.list,
1091 sc: args.sc,
1092 transaction: self.transaction,
1093 renderer: self.renderer,
1094 document_id: self.document_id,
1095 api: self.api,
1096 external_images: self.external_images,
1097 });
1098 }
1099 }
1100
1101 fn update(&mut self, args: &mut DisplayExtensionUpdateArgs) {
1102 for (id, ext) in self.extensions.iter_mut() {
1103 if *id == args.extension_id {
1104 let mut r_args = RenderUpdateArgs {
1105 extension_id: args.extension_id,
1106 payload: args.payload,
1107 new_frame: args.new_frame,
1108 properties: args.properties,
1109 document_id: self.document_id,
1110 transaction: self.transaction,
1111 renderer: self.renderer,
1112 api: self.api,
1113 external_images: self.external_images,
1114 };
1115 ext.render_update(&mut r_args);
1116 args.new_frame = r_args.new_frame;
1117 break;
1118 }
1119 }
1120 }
1121}
1122
1123pub(crate) struct BlobExtensionsImgHandler(pub Vec<Box<dyn BlobExtension>>);
1124
1125impl BlobImageHandler for BlobExtensionsImgHandler {
1126 fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobImageRasterizer> {
1127 Box::new(BlockExtensionsImgRasterizer(
1128 self.0.iter_mut().map(|t| t.create_blob_rasterizer()).collect(),
1129 ))
1130 }
1131
1132 fn create_similar(&self) -> Box<dyn BlobImageHandler> {
1133 Box::new(Self(self.0.iter().map(|e| e.create_similar()).collect()))
1134 }
1135
1136 fn prepare_resources(&mut self, services: &dyn webrender::api::BlobImageResources, requests: &[BlobImageParams]) {
1137 for ext in self.0.iter_mut() {
1138 ext.prepare_resources(&mut BlobPrepareArgs { services, requests })
1139 }
1140 }
1141
1142 fn add(
1143 &mut self,
1144 key: webrender::api::BlobImageKey,
1145 data: std::sync::Arc<webrender::api::BlobImageData>,
1146 visible_rect: &webrender::api::units::DeviceIntRect,
1147 tile_size: webrender::api::TileSize,
1148 ) {
1149 let args = BlobAddArgs {
1150 key,
1151 data,
1152 visible_rect: *visible_rect,
1153 tile_size,
1154 };
1155 for ext in self.0.iter_mut() {
1156 ext.add(&args);
1157 }
1158 }
1159
1160 fn update(
1161 &mut self,
1162 key: webrender::api::BlobImageKey,
1163 data: std::sync::Arc<webrender::api::BlobImageData>,
1164 visible_rect: &webrender::api::units::DeviceIntRect,
1165 dirty_rect: &webrender::api::units::BlobDirtyRect,
1166 ) {
1167 let args = BlobUpdateArgs {
1168 key,
1169 data,
1170 visible_rect: *visible_rect,
1171 dirty_rect: *dirty_rect,
1172 };
1173 for ext in self.0.iter_mut() {
1174 ext.update(&args);
1175 }
1176 }
1177
1178 fn delete(&mut self, key: webrender::api::BlobImageKey) {
1179 for ext in self.0.iter_mut() {
1180 ext.delete(key);
1181 }
1182 }
1183
1184 fn delete_font(&mut self, key: webrender::api::FontKey) {
1185 for ext in self.0.iter_mut() {
1186 ext.delete_font(key);
1187 }
1188 }
1189
1190 fn delete_font_instance(&mut self, key: webrender::api::FontInstanceKey) {
1191 for ext in self.0.iter_mut() {
1192 ext.delete_font_instance(key);
1193 }
1194 }
1195
1196 fn clear_namespace(&mut self, namespace: webrender::api::IdNamespace) {
1197 for ext in self.0.iter_mut() {
1198 ext.clear_namespace(namespace);
1199 }
1200 }
1201
1202 fn enable_multithreading(&mut self, enable: bool) {
1203 for ext in self.0.iter_mut() {
1204 ext.enable_multithreading(enable);
1205 }
1206 }
1207}
1208
1209struct BlockExtensionsImgRasterizer(Vec<Box<dyn AsyncBlobRasterizer>>);
1210impl AsyncBlobImageRasterizer for BlockExtensionsImgRasterizer {
1211 fn rasterize(
1212 &mut self,
1213 requests: &[BlobImageParams],
1214 low_priority: bool,
1215 tile_pool: &mut crate::BlobTilePool,
1216 ) -> Vec<(BlobImageRequest, BlobImageResult)> {
1217 let mut responses = vec![];
1218 for r in &mut self.0 {
1219 r.rasterize(&mut BlobRasterizerArgs {
1220 requests,
1221 low_priority,
1222 tile_pool,
1223 responses: &mut responses,
1224 })
1225 }
1226 responses
1227 }
1228}
1229
1230#[macro_export]
1234macro_rules! view_process_extension {
1235 ($closure:expr) => {
1236 #[used]
1241 #[cfg_attr(
1242 any(
1243 target_os = "none",
1244 target_os = "linux",
1245 target_os = "android",
1246 target_os = "fuchsia",
1247 target_os = "psp"
1248 ),
1249 unsafe(link_section = "linkme_VIEW_EXTENSIONS")
1250 )]
1251 #[cfg_attr(
1252 any(target_os = "macos", target_os = "ios", target_os = "tvos"),
1253 unsafe(link_section = "__DATA,__linkmeTbhLJz52,regular,no_dead_strip")
1254 )]
1255 #[cfg_attr(
1256 any(target_os = "uefi", target_os = "windows"),
1257 unsafe(link_section = ".linkme_VIEW_EXTENSIONS$b")
1258 )]
1259 #[cfg_attr(target_os = "illumos", unsafe(link_section = "set_linkme_VIEW_EXTENSIONS"))]
1260 #[cfg_attr(
1261 any(target_os = "freebsd", target_os = "openbsd"),
1262 unsafe(link_section = "linkme_VIEW_EXTENSIONS")
1263 )]
1264 #[doc(hidden)]
1265 static _VIEW_EXTENSIONS: fn(&mut $crate::extensions::ViewExtensions) = _view_extensions;
1266 #[doc(hidden)]
1267 fn _view_extensions(ext: &mut $crate::extensions::ViewExtensions) {
1268 fn view_extensions(
1269 ext: &mut $crate::extensions::ViewExtensions,
1270 handler: impl FnOnce(&mut $crate::extensions::ViewExtensions),
1271 ) {
1272 handler(ext)
1273 }
1274 view_extensions(ext, $closure)
1275 }
1276 };
1277}
1278
1279#[doc(hidden)]
1280#[linkme::distributed_slice]
1281pub static VIEW_EXTENSIONS: [fn(&mut ViewExtensions)];