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 mipmap: Mutex::new(Box::new([])),
575 stripes: Mutex::new(Box::new([])),
576 })
577 }
578
579 pub fn unregister(&mut self, id: ExternalImageId) {
584 if let Some(i) = self.images.iter().position(|img| ExternalImageId(Arc::as_ptr(img) as u64) == id) {
585 self.images.swap_remove(i);
586 }
587 }
588
589 fn register(&mut self, img: crate::image_cache::ImageData) -> ExternalImageId {
590 let img = Arc::new(img);
591 let id = ExternalImageId(Arc::as_ptr(&img) as u64);
592 self.images.push(img);
593 id
594 }
595}
596
597#[non_exhaustive]
599pub struct RendererDeinitedArgs<'a> {
600 pub document_id: DocumentId,
602
603 pub pipeline_id: PipelineId,
605
606 pub window: Option<&'a winit::window::Window>,
608
609 pub context: &'a mut dyn OpenGlContext,
614}
615
616#[non_exhaustive]
618pub struct WindowInitedArgs<'a> {
619 pub window: &'a winit::window::Window,
621
622 pub context: &'a mut dyn OpenGlContext,
624}
625
626#[non_exhaustive]
628pub struct WindowDeinitedArgs<'a> {
629 pub window: &'a winit::window::Window,
631
632 pub context: &'a mut dyn OpenGlContext,
634}
635
636#[non_exhaustive]
638pub struct WindowCommandArgs<'a> {
639 pub window: &'a winit::window::Window,
641
642 pub context: &'a mut dyn OpenGlContext,
644
645 pub request: ApiExtensionPayload,
647}
648
649#[non_exhaustive]
651pub struct WindowEventArgs<'a> {
652 pub window: &'a winit::window::Window,
654
655 pub context: &'a mut dyn OpenGlContext,
657
658 pub event: &'a winit::event::WindowEvent,
660}
661
662pub trait OpenGlContext {
664 fn is_current(&self) -> bool;
666
667 fn make_current(&mut self);
669
670 fn gl(&self) -> &Rc<dyn gleam::gl::Gl>;
672
673 fn render_mode(&self) -> RenderMode;
675
676 fn resize(&mut self, size: PxSize);
678
679 fn is_software(&self) -> bool;
681
682 fn swap_buffers(&mut self);
684}
685impl OpenGlContext for crate::gl::GlContext {
686 fn is_current(&self) -> bool {
687 self.is_current()
688 }
689
690 fn make_current(&mut self) {
691 self.make_current()
692 }
693
694 fn gl(&self) -> &Rc<dyn gleam::gl::Gl> {
695 self.gl()
696 }
697
698 fn render_mode(&self) -> RenderMode {
699 self.render_mode()
700 }
701
702 fn resize(&mut self, size: PxSize) {
703 self.resize(size.to_winit())
704 }
705
706 fn is_software(&self) -> bool {
707 self.is_software()
708 }
709
710 fn swap_buffers(&mut self) {
711 self.swap_buffers()
712 }
713}
714
715#[non_exhaustive]
717pub struct RendererCommandArgs<'a> {
718 pub renderer: &'a mut webrender::Renderer,
720
721 pub api: &'a mut RenderApi,
723
724 pub document_id: DocumentId,
726
727 pub request: ApiExtensionPayload,
729
730 pub window: Option<&'a winit::window::Window>,
732
733 pub context: &'a mut dyn OpenGlContext,
735
736 pub redraw: &'a mut bool,
740}
741
742pub struct ViewExtensions {
744 exts: Vec<Box<dyn ViewExtension>>,
745}
746impl ViewExtensions {
747 pub(crate) fn new() -> Self {
749 Self { exts: vec![] }
750 }
751
752 pub fn register<E: ViewExtension>(&mut self, ext: impl FnOnce(ApiExtensionId) -> E) -> &mut Self {
760 let id = ApiExtensionId::from_index(self.exts.len());
761 let ext = ext(id);
762 assert!(self.id(ext.name()).is_none(), "extension already registered");
763 self.exts.push(Box::new(ext));
764 self
765 }
766
767 pub fn id(&self, name: &ApiExtensionName) -> Option<ApiExtensionId> {
769 self.exts.iter().position(|e| e.name() == name).map(ApiExtensionId::from_index)
770 }
771
772 pub fn command_raw(
776 &mut self,
777 name: impl Into<ApiExtensionName>,
778 handler: impl FnMut(ApiExtensionPayload, ApiExtensionId) -> ApiExtensionPayload + Send + 'static,
779 ) -> &mut Self {
780 struct CommandExt<F>(ApiExtensionName, ApiExtensionId, F);
781 impl<F: FnMut(ApiExtensionPayload, ApiExtensionId) -> ApiExtensionPayload + Send + 'static> ViewExtension for CommandExt<F> {
782 fn name(&self) -> &ApiExtensionName {
783 &self.0
784 }
785 fn command(&mut self, request: ApiExtensionPayload) -> Option<ApiExtensionPayload> {
786 Some((self.2)(request, self.1))
787 }
788 }
789
790 self.register(|id| CommandExt(name.into(), id, handler));
791 self
792 }
793
794 pub fn command<I: serde::de::DeserializeOwned, O: serde::Serialize>(
798 &mut self,
799 name: impl Into<ApiExtensionName>,
800 mut handler: impl FnMut(I, ApiExtensionId) -> O + Send + 'static,
801 ) -> &mut Self {
802 self.command_raw(name, move |p, id| match p.deserialize::<I>() {
803 Ok(p) => {
804 let o = handler(p, id);
805 ApiExtensionPayload::serialize(&o).unwrap()
806 }
807 Err(e) => ApiExtensionPayload::invalid_request(id, e),
808 })
809 }
810
811 pub fn window<E: WindowExtension>(
813 &mut self,
814 name: impl Into<ApiExtensionName>,
815 new: impl FnMut(ApiExtensionId) -> E + Send + 'static,
816 ) -> &mut Self {
817 struct WindowExt<F>(ApiExtensionName, ApiExtensionId, F);
818 impl<E, F> ViewExtension for WindowExt<F>
819 where
820 E: WindowExtension,
821 F: FnMut(ApiExtensionId) -> E + Send + 'static,
822 {
823 fn name(&self) -> &ApiExtensionName {
824 &self.0
825 }
826
827 fn window(&mut self) -> Option<Box<dyn WindowExtension>> {
828 Some(Box::new((self.2)(self.1)))
829 }
830 }
831 self.register(move |id| WindowExt(name.into(), id, new));
832 self
833 }
834
835 pub fn renderer<E: RendererExtension>(
837 &mut self,
838 name: impl Into<ApiExtensionName>,
839 new: impl FnMut(ApiExtensionId) -> E + Send + 'static,
840 ) -> &mut Self {
841 struct RendererExt<F>(ApiExtensionName, ApiExtensionId, F);
842 impl<E, F> ViewExtension for RendererExt<F>
843 where
844 E: RendererExtension,
845 F: FnMut(ApiExtensionId) -> E + Send + 'static,
846 {
847 fn name(&self) -> &ApiExtensionName {
848 &self.0
849 }
850
851 fn renderer(&mut self) -> Option<Box<dyn RendererExtension>> {
852 Some(Box::new((self.2)(self.1)))
853 }
854 }
855 self.register(move |id| RendererExt(name.into(), id, new));
856 self
857 }
858
859 pub(crate) fn api_extensions(&self) -> ApiExtensions {
860 let mut r = ApiExtensions::new();
861 for ext in &self.exts {
862 r.insert(ext.name().clone()).unwrap();
863 }
864 r
865 }
866
867 pub(crate) fn call_command(&mut self, id: ApiExtensionId, request: ApiExtensionPayload) -> ApiExtensionPayload {
868 let idx = id.index();
869 if idx >= self.exts.len() {
870 ApiExtensionPayload::unknown_extension(id)
871 } else if let Some(r) = self.exts[idx].command(request) {
872 r
873 } else {
874 ApiExtensionPayload::unknown_extension(id)
875 }
876 }
877
878 pub(crate) fn new_window(&mut self) -> Vec<(ApiExtensionId, Box<dyn WindowExtension>)> {
879 self.exts
880 .iter_mut()
881 .enumerate()
882 .filter_map(|(i, e)| e.window().map(|e| (ApiExtensionId::from_index(i), e)))
883 .collect()
884 }
885
886 pub(crate) fn new_renderer(&mut self) -> Vec<(ApiExtensionId, Box<dyn RendererExtension>)> {
887 self.exts
888 .iter_mut()
889 .enumerate()
890 .filter_map(|(i, e)| e.renderer().map(|e| (ApiExtensionId::from_index(i), e)))
891 .collect()
892 }
893
894 pub(crate) fn init(&mut self, event_sender: &crate::AppEventSender) {
895 for (i, ext) in self.exts.iter_mut().enumerate() {
896 ext.init(ViewExtensionInitArgs {
897 event_sender: ExtensionEventSender {
898 sender: event_sender.clone(),
899 id: ApiExtensionId::from_index(i),
900 },
901 });
902 }
903 }
904
905 pub(crate) fn on_low_memory(&mut self) {
906 for ext in self.exts.iter_mut() {
907 ext.low_memory();
908 }
909 }
910
911 pub(crate) fn suspended(&mut self) {
912 for ext in self.exts.iter_mut() {
913 ext.suspended();
914 }
915 }
916
917 pub(crate) fn resumed(&mut self) {
918 for ext in self.exts.iter_mut() {
919 ext.resumed();
920 }
921 }
922
923 pub fn append(&mut self, mut other: ViewExtensions) {
925 self.exts.append(&mut other.exts);
926 }
927}
928
929#[cfg(windows)]
930pub(crate) struct PreferAngleExt {
931 pub(crate) prefer_egl: bool,
932}
933#[cfg(windows)]
934impl PreferAngleExt {
935 pub(crate) fn new(_: ApiExtensionId) -> Self {
936 Self { prefer_egl: false }
937 }
938}
939#[cfg(windows)]
940impl WindowExtension for PreferAngleExt {
941 fn is_init_only(&self) -> bool {
942 true
943 }
944
945 fn configure(&mut self, args: &mut WindowConfigArgs) {
946 if let Some(cfg) = args.config {
947 match cfg.deserialize::<bool>() {
948 Ok(y) => self.prefer_egl = y,
949 Err(e) => tracing::error!("invalid arg for 'zng-view.prefer_angle', {e}"),
950 }
951 }
952 }
953
954 fn as_any(&self) -> &dyn Any {
955 self
956 }
957
958 fn as_any_mut(&mut self) -> &mut dyn Any {
959 self
960 }
961}
962
963pub(crate) struct RendererDebugExt {
967 id: ApiExtensionId,
968 ui: Option<String>,
969}
970
971impl RendererDebugExt {
972 pub(crate) fn new(id: ApiExtensionId) -> Self {
973 Self { id, ui: None }
974 }
975}
976impl RendererExtension for RendererDebugExt {
977 fn is_init_only(&self) -> bool {
978 false
979 }
980
981 fn configure(&mut self, args: &mut RendererConfigArgs) {
982 if let Some(cfg) = args.config.as_ref().and_then(|c| c.deserialize::<RendererDebug>().ok()) {
983 args.options.debug_flags = cfg.flags;
984 self.ui = Some(cfg.profiler_ui);
985 }
986 }
987
988 fn renderer_inited(&mut self, args: &mut RendererInitedArgs) {
989 if let Some(ui) = self.ui.take() {
990 args.renderer.set_profiler_ui(&ui);
991 }
992 }
993
994 fn command(&mut self, args: &mut RendererCommandArgs) -> ApiExtensionPayload {
995 match args.request.deserialize::<RendererDebug>() {
996 Ok(cfg) => {
997 args.renderer.set_debug_flags(cfg.flags);
998 args.renderer.set_profiler_ui(&cfg.profiler_ui);
999 ApiExtensionPayload::empty()
1000 }
1001 Err(e) => ApiExtensionPayload::invalid_request(self.id, e),
1002 }
1003 }
1004
1005 fn as_any(&self) -> &dyn Any {
1006 self
1007 }
1008
1009 fn as_any_mut(&mut self) -> &mut dyn Any {
1010 self
1011 }
1012}
1013
1014#[derive(serde::Serialize, serde::Deserialize)]
1016struct RendererDebug {
1017 pub flags: DebugFlags,
1018 pub profiler_ui: String,
1019}
1020
1021pub(crate) struct DisplayListExtAdapter<'a> {
1022 pub extensions: &'a mut Vec<(ApiExtensionId, Box<dyn RendererExtension>)>,
1023 pub transaction: &'a mut webrender::Transaction,
1024 pub renderer: &'a mut webrender::Renderer,
1025 pub document_id: DocumentId,
1026 pub api: &'a mut RenderApi,
1027 pub external_images: &'a mut ExternalImages,
1028 pub frame_id: zng_view_api::window::FrameId,
1029}
1030
1031impl DisplayListExtension for DisplayListExtAdapter<'_> {
1032 fn display_list_start(&mut self, args: &mut DisplayExtensionArgs) {
1033 for (_, ext) in self.extensions.iter_mut() {
1034 ext.render_start(&mut RenderArgs {
1035 frame_id: self.frame_id,
1036 list: args.list,
1037 sc: args.sc,
1038 transaction: self.transaction,
1039 renderer: self.renderer,
1040 document_id: self.document_id,
1041 api: self.api,
1042 external_images: self.external_images,
1043 });
1044 }
1045 }
1046
1047 fn push_display_item(&mut self, args: &mut DisplayExtensionItemArgs) {
1048 for (id, ext) in self.extensions.iter_mut() {
1049 if *id == args.extension_id {
1050 ext.render_push(&mut RenderItemArgs {
1051 extension_id: args.extension_id,
1052 payload: args.payload,
1053 is_reuse: args.is_reuse,
1054 list: args.list,
1055 sc: args.sc,
1056 transaction: self.transaction,
1057 renderer: self.renderer,
1058 document_id: self.document_id,
1059 api: self.api,
1060 external_images: self.external_images,
1061 });
1062 break;
1063 }
1064 }
1065 }
1066
1067 fn pop_display_item(&mut self, args: &mut DisplayExtensionItemArgs) {
1068 for (id, ext) in self.extensions.iter_mut() {
1069 if *id == args.extension_id {
1070 ext.render_pop(&mut RenderItemArgs {
1071 extension_id: args.extension_id,
1072 payload: args.payload,
1073 is_reuse: args.is_reuse,
1074 list: args.list,
1075 sc: args.sc,
1076 transaction: self.transaction,
1077 renderer: self.renderer,
1078 document_id: self.document_id,
1079 api: self.api,
1080 external_images: self.external_images,
1081 });
1082 break;
1083 }
1084 }
1085 }
1086
1087 fn display_list_end(&mut self, args: &mut DisplayExtensionArgs) {
1088 for (_, ext) in self.extensions.iter_mut() {
1089 ext.render_end(&mut RenderArgs {
1090 frame_id: self.frame_id,
1091 list: args.list,
1092 sc: args.sc,
1093 transaction: self.transaction,
1094 renderer: self.renderer,
1095 document_id: self.document_id,
1096 api: self.api,
1097 external_images: self.external_images,
1098 });
1099 }
1100 }
1101
1102 fn update(&mut self, args: &mut DisplayExtensionUpdateArgs) {
1103 for (id, ext) in self.extensions.iter_mut() {
1104 if *id == args.extension_id {
1105 let mut r_args = RenderUpdateArgs {
1106 extension_id: args.extension_id,
1107 payload: args.payload,
1108 new_frame: args.new_frame,
1109 properties: args.properties,
1110 document_id: self.document_id,
1111 transaction: self.transaction,
1112 renderer: self.renderer,
1113 api: self.api,
1114 external_images: self.external_images,
1115 };
1116 ext.render_update(&mut r_args);
1117 args.new_frame = r_args.new_frame;
1118 break;
1119 }
1120 }
1121 }
1122}
1123
1124pub(crate) struct BlobExtensionsImgHandler(pub Vec<Box<dyn BlobExtension>>);
1125
1126impl BlobImageHandler for BlobExtensionsImgHandler {
1127 fn create_blob_rasterizer(&mut self) -> Box<dyn AsyncBlobImageRasterizer> {
1128 Box::new(BlockExtensionsImgRasterizer(
1129 self.0.iter_mut().map(|t| t.create_blob_rasterizer()).collect(),
1130 ))
1131 }
1132
1133 fn create_similar(&self) -> Box<dyn BlobImageHandler> {
1134 Box::new(Self(self.0.iter().map(|e| e.create_similar()).collect()))
1135 }
1136
1137 fn prepare_resources(&mut self, services: &dyn webrender::api::BlobImageResources, requests: &[BlobImageParams]) {
1138 for ext in self.0.iter_mut() {
1139 ext.prepare_resources(&mut BlobPrepareArgs { services, requests })
1140 }
1141 }
1142
1143 fn add(
1144 &mut self,
1145 key: webrender::api::BlobImageKey,
1146 data: std::sync::Arc<webrender::api::BlobImageData>,
1147 visible_rect: &webrender::api::units::DeviceIntRect,
1148 tile_size: webrender::api::TileSize,
1149 ) {
1150 let args = BlobAddArgs {
1151 key,
1152 data,
1153 visible_rect: *visible_rect,
1154 tile_size,
1155 };
1156 for ext in self.0.iter_mut() {
1157 ext.add(&args);
1158 }
1159 }
1160
1161 fn update(
1162 &mut self,
1163 key: webrender::api::BlobImageKey,
1164 data: std::sync::Arc<webrender::api::BlobImageData>,
1165 visible_rect: &webrender::api::units::DeviceIntRect,
1166 dirty_rect: &webrender::api::units::BlobDirtyRect,
1167 ) {
1168 let args = BlobUpdateArgs {
1169 key,
1170 data,
1171 visible_rect: *visible_rect,
1172 dirty_rect: *dirty_rect,
1173 };
1174 for ext in self.0.iter_mut() {
1175 ext.update(&args);
1176 }
1177 }
1178
1179 fn delete(&mut self, key: webrender::api::BlobImageKey) {
1180 for ext in self.0.iter_mut() {
1181 ext.delete(key);
1182 }
1183 }
1184
1185 fn delete_font(&mut self, key: webrender::api::FontKey) {
1186 for ext in self.0.iter_mut() {
1187 ext.delete_font(key);
1188 }
1189 }
1190
1191 fn delete_font_instance(&mut self, key: webrender::api::FontInstanceKey) {
1192 for ext in self.0.iter_mut() {
1193 ext.delete_font_instance(key);
1194 }
1195 }
1196
1197 fn clear_namespace(&mut self, namespace: webrender::api::IdNamespace) {
1198 for ext in self.0.iter_mut() {
1199 ext.clear_namespace(namespace);
1200 }
1201 }
1202
1203 fn enable_multithreading(&mut self, enable: bool) {
1204 for ext in self.0.iter_mut() {
1205 ext.enable_multithreading(enable);
1206 }
1207 }
1208}
1209
1210struct BlockExtensionsImgRasterizer(Vec<Box<dyn AsyncBlobRasterizer>>);
1211impl AsyncBlobImageRasterizer for BlockExtensionsImgRasterizer {
1212 fn rasterize(
1213 &mut self,
1214 requests: &[BlobImageParams],
1215 low_priority: bool,
1216 tile_pool: &mut crate::BlobTilePool,
1217 ) -> Vec<(BlobImageRequest, BlobImageResult)> {
1218 let mut responses = vec![];
1219 for r in &mut self.0 {
1220 r.rasterize(&mut BlobRasterizerArgs {
1221 requests,
1222 low_priority,
1223 tile_pool,
1224 responses: &mut responses,
1225 })
1226 }
1227 responses
1228 }
1229}
1230
1231#[macro_export]
1235macro_rules! view_process_extension {
1236 ($closure:expr) => {
1237 #[used]
1242 #[cfg_attr(
1243 any(
1244 target_os = "none",
1245 target_os = "linux",
1246 target_os = "android",
1247 target_os = "fuchsia",
1248 target_os = "psp"
1249 ),
1250 unsafe(link_section = "linkme_VIEW_EXTENSIONS")
1251 )]
1252 #[cfg_attr(
1253 any(target_os = "macos", target_os = "ios", target_os = "tvos"),
1254 unsafe(link_section = "__DATA,__linkmeTbhLJz52,regular,no_dead_strip")
1255 )]
1256 #[cfg_attr(
1257 any(target_os = "uefi", target_os = "windows"),
1258 unsafe(link_section = ".linkme_VIEW_EXTENSIONS$b")
1259 )]
1260 #[cfg_attr(target_os = "illumos", unsafe(link_section = "set_linkme_VIEW_EXTENSIONS"))]
1261 #[cfg_attr(
1262 any(target_os = "freebsd", target_os = "openbsd"),
1263 unsafe(link_section = "linkme_VIEW_EXTENSIONS")
1264 )]
1265 #[doc(hidden)]
1266 static _VIEW_EXTENSIONS: fn(&mut $crate::extensions::ViewExtensions) = _view_extensions;
1267 #[doc(hidden)]
1268 fn _view_extensions(ext: &mut $crate::extensions::ViewExtensions) {
1269 fn view_extensions(
1270 ext: &mut $crate::extensions::ViewExtensions,
1271 handler: impl FnOnce(&mut $crate::extensions::ViewExtensions),
1272 ) {
1273 handler(ext)
1274 }
1275 view_extensions(ext, $closure)
1276 }
1277 };
1278}
1279
1280#[doc(hidden)]
1281#[linkme::distributed_slice]
1282pub static VIEW_EXTENSIONS: [fn(&mut ViewExtensions)];