1use std::collections::HashMap;
8use std::fmt::{Debug, Error, Formatter};
9
10use crossbeam_channel::Sender;
11use embedder_traits::{AnimationState, EventLoopWaker};
12use euclid::{Rect, Scale, Size2D};
13use log::warn;
14use malloc_size_of_derive::MallocSizeOf;
15use parking_lot::RwLock;
16use rustc_hash::FxHashMap;
17use servo_base::Epoch;
18use servo_base::id::{PainterId, PipelineId, WebViewId};
19use smallvec::SmallVec;
20use strum::IntoStaticStr;
21use style_traits::CSSPixel;
22use surfman::{Adapter, Connection};
23use webrender_api::{DocumentId, FontVariation};
24
25pub mod display_list;
26pub mod largest_contentful_paint_candidate;
27pub mod rendering_context;
28pub mod viewport_description;
29
30use std::sync::{Arc, Mutex};
31
32use bitflags::bitflags;
33use display_list::PaintDisplayListInfo;
34use embedder_traits::ScreenGeometry;
35use euclid::default::Size2D as UntypedSize2D;
36use profile_traits::mem::{OpaqueSender, ReportsChan};
37use serde::{Deserialize, Serialize};
38use servo_base::generic_channel::{
39 self, GenericCallback, GenericReceiver, GenericSender, GenericSharedMemory,
40};
41pub use webrender_api::ExternalImageSource;
42use webrender_api::units::{DevicePixel, LayoutVector2D, TexelRect};
43use webrender_api::{
44 BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData,
45 ExternalImageHandler, ExternalImageId, ExternalScrollId, FontInstanceFlags, FontInstanceKey,
46 FontKey, ImageData, ImageDescriptor, ImageKey, NativeFontHandle,
47 PipelineId as WebRenderPipelineId,
48};
49
50use crate::largest_contentful_paint_candidate::LCPCandidate;
51use crate::viewport_description::ViewportDescription;
52
53#[derive(Clone)]
55pub struct PaintProxy {
56 pub sender: Sender<Result<PaintMessage, ipc_channel::IpcError>>,
57 pub cross_process_paint_api: CrossProcessPaintApi,
61 pub event_loop_waker: Box<dyn EventLoopWaker>,
62}
63
64impl OpaqueSender<PaintMessage> for PaintProxy {
65 fn send(&self, message: PaintMessage) {
66 PaintProxy::send(self, message)
67 }
68}
69
70impl PaintProxy {
71 pub fn send(&self, msg: PaintMessage) {
72 self.route_msg(Ok(msg))
73 }
74
75 pub fn route_msg(&self, msg: Result<PaintMessage, ipc_channel::IpcError>) {
80 if let Err(err) = self.sender.send(msg) {
81 warn!("Failed to send response ({:?}).", err);
82 }
83 self.event_loop_waker.wake();
84 }
85}
86
87#[derive(Deserialize, IntoStaticStr, Serialize)]
89pub enum PaintMessage {
90 ChangeRunningAnimationsState(WebViewId, PipelineId, AnimationState),
92 SetFrameTreeForWebView(WebViewId, SendableFrameTree),
94 SetThrottled(WebViewId, PipelineId, bool),
96 NewWebRenderFrameReady(PainterId, DocumentId, bool),
100 PipelineExited(WebViewId, PipelineId, PipelineExitSource),
105 SendInitialTransaction(WebViewId, WebRenderPipelineId),
107 ScrollNodeByDelta(
111 WebViewId,
112 WebRenderPipelineId,
113 LayoutVector2D,
114 ExternalScrollId,
115 ),
116 ScrollViewportByDelta(WebViewId, LayoutVector2D),
120 UpdateEpoch {
122 webview_id: WebViewId,
124 pipeline_id: PipelineId,
126 epoch: Epoch,
128 },
129 SendDisplayList {
131 webview_id: WebViewId,
133 display_list_descriptor: BuiltDisplayListDescriptor,
135 display_list_info_receiver: GenericReceiver<PaintDisplayListInfo>,
137 display_list_data_receiver: GenericReceiver<SerializableDisplayListPayload>,
139 },
140 GenerateFrame(Vec<PainterId>),
143 GenerateImageKey(WebViewId, GenericSender<ImageKey>),
146 GenerateImageKeysForPipeline(WebViewId, PipelineId),
149 UpdateImages(PainterId, SmallVec<[ImageUpdate; 1]>),
151 DelayNewFrameForCanvas(WebViewId, PipelineId, Epoch, Vec<ImageKey>),
156
157 GenerateFontKeys(
160 usize,
161 usize,
162 GenericSender<(Vec<FontKey>, Vec<FontInstanceKey>)>,
163 PainterId,
164 ),
165 AddFont(PainterId, FontKey, Arc<GenericSharedMemory>, u32),
167 AddSystemFont(PainterId, FontKey, NativeFontHandle),
169 AddFontInstance(
171 PainterId,
172 FontInstanceKey,
173 FontKey,
174 f32,
175 FontInstanceFlags,
176 Vec<FontVariation>,
177 ),
178 RemoveFonts(PainterId, Vec<FontKey>, Vec<FontInstanceKey>),
180 CollectMemoryReport(ReportsChan),
183 Viewport(WebViewId, ViewportDescription),
185 ScreenshotReadinessReponse(WebViewId, FxHashMap<PipelineId, Epoch>),
188 SendLCPCandidate(LCPCandidate, WebViewId, PipelineId, Epoch),
190}
191
192impl Debug for PaintMessage {
193 fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
194 let string: &'static str = self.into();
195 write!(formatter, "{string}")
196 }
197}
198
199#[derive(Deserialize, Serialize)]
200pub struct SendableFrameTree {
201 pub pipeline: CompositionPipeline,
202 pub children: Vec<SendableFrameTree>,
203}
204
205#[derive(Clone, Deserialize, Serialize)]
207pub struct CompositionPipeline {
208 pub id: PipelineId,
209 pub webview_id: WebViewId,
210}
211
212#[derive(Serialize, Deserialize)]
214pub struct SerializableDisplayListPayload {
215 #[serde(with = "serde_bytes")]
217 pub items_data: Vec<u8>,
218
219 #[serde(with = "serde_bytes")]
220 pub spatial_tree: Vec<u8>,
221}
222
223#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
225pub struct CrossProcessPaintApi(GenericCallback<PaintMessage>);
226
227impl CrossProcessPaintApi {
228 pub fn new(callback: GenericCallback<PaintMessage>) -> Self {
230 CrossProcessPaintApi(callback)
231 }
232
233 pub fn dummy() -> Self {
236 Self::dummy_with_callback(None)
237 }
238
239 pub fn dummy_with_callback(
242 callback: Option<Box<dyn Fn(PaintMessage) + Send + 'static>>,
243 ) -> Self {
244 let callback = GenericCallback::new(move |msg| {
245 if let Some(ref handler) = callback &&
246 let Ok(paint_message) = msg
247 {
248 handler(paint_message);
249 }
250 })
251 .unwrap();
252 Self(callback)
253 }
254
255 pub fn send_initial_transaction(&self, webview_id: WebViewId, pipeline: WebRenderPipelineId) {
257 if let Err(e) = self
258 .0
259 .send(PaintMessage::SendInitialTransaction(webview_id, pipeline))
260 {
261 warn!("Error sending initial transaction: {}", e);
262 }
263 }
264
265 pub fn scroll_node_by_delta(
269 &self,
270 webview_id: WebViewId,
271 pipeline_id: WebRenderPipelineId,
272 delta: LayoutVector2D,
273 scroll_id: ExternalScrollId,
274 ) {
275 if let Err(error) = self.0.send(PaintMessage::ScrollNodeByDelta(
276 webview_id,
277 pipeline_id,
278 delta,
279 scroll_id,
280 )) {
281 warn!("Error scrolling node: {error}");
282 }
283 }
284
285 pub fn scroll_viewport_by_delta(&self, webview_id: WebViewId, delta: LayoutVector2D) {
292 if let Err(error) = self
293 .0
294 .send(PaintMessage::ScrollViewportByDelta(webview_id, delta))
295 {
296 warn!("Error scroll viewport: {error}");
297 }
298 }
299
300 pub fn delay_new_frame_for_canvas(
301 &self,
302 webview_id: WebViewId,
303 pipeline_id: PipelineId,
304 canvas_epoch: Epoch,
305 image_keys: Vec<ImageKey>,
306 ) {
307 if let Err(error) = self.0.send(PaintMessage::DelayNewFrameForCanvas(
308 webview_id,
309 pipeline_id,
310 canvas_epoch,
311 image_keys,
312 )) {
313 warn!("Error delaying frames for canvas image updates {error:?}");
314 }
315 }
316
317 pub fn update_epoch(&self, webview_id: WebViewId, pipeline_id: PipelineId, epoch: Epoch) {
320 if let Err(error) = self.0.send(PaintMessage::UpdateEpoch {
321 webview_id,
322 pipeline_id,
323 epoch,
324 }) {
325 warn!("Error updating epoch for pipeline: {error:?}");
326 }
327 }
328
329 #[servo_tracing::instrument(skip_all)]
333 pub fn send_display_list(
334 &self,
335 webview_id: WebViewId,
336 display_list_info: &PaintDisplayListInfo,
337 list: BuiltDisplayList,
338 ) {
339 let (display_list_data, display_list_descriptor) = list.into_data();
340 let (display_list_data_sender, display_list_data_receiver) =
341 generic_channel::channel().unwrap();
342 let (display_list_info_sender, display_list_info_receiver) =
343 generic_channel::channel().unwrap();
344 if let Err(e) = self.0.send(PaintMessage::SendDisplayList {
345 webview_id,
346 display_list_descriptor,
347 display_list_info_receiver,
348 display_list_data_receiver,
349 }) {
350 warn!("Error sending display list: {}", e);
351 }
352
353 if let Err(error) = display_list_info_sender.send(display_list_info.clone()) {
354 warn!("Error sending display list info: {error}. Not sending the rest");
355 return;
356 }
357 let display_list_data = SerializableDisplayListPayload {
358 items_data: display_list_data.items_data,
359 spatial_tree: display_list_data.spatial_tree,
360 };
361
362 if let Err(error) = display_list_data_sender.send(display_list_data) {
363 warn!("Error sending display list: {error}");
364 }
365 }
366
367 pub fn send_lcp_candidate(
369 &self,
370 lcp_candidate: LCPCandidate,
371 webview_id: WebViewId,
372 pipeline_id: PipelineId,
373 epoch: Epoch,
374 ) {
375 if let Err(error) = self.0.send(PaintMessage::SendLCPCandidate(
376 lcp_candidate,
377 webview_id,
378 pipeline_id,
379 epoch,
380 )) {
381 warn!("Error sending LCPCandidate: {error}");
382 }
383 }
384
385 pub fn generate_frame(&self, painter_ids: Vec<PainterId>) {
387 if let Err(error) = self.0.send(PaintMessage::GenerateFrame(painter_ids)) {
388 warn!("Error generating frame: {error}");
389 }
390 }
391
392 pub fn generate_image_key_blocking(&self, webview_id: WebViewId) -> Option<ImageKey> {
394 let (sender, receiver) = generic_channel::channel().unwrap();
395 self.0
396 .send(PaintMessage::GenerateImageKey(webview_id, sender))
397 .ok()?;
398 receiver.recv().ok()
399 }
400
401 pub fn generate_image_key_async(&self, webview_id: WebViewId, pipeline_id: PipelineId) {
405 if let Err(e) = self.0.send(PaintMessage::GenerateImageKeysForPipeline(
406 webview_id,
407 pipeline_id,
408 )) {
409 warn!("Could not send image keys to Paint {}", e);
410 }
411 }
412
413 pub fn add_image(
414 &self,
415 key: ImageKey,
416 descriptor: ImageDescriptor,
417 data: SerializableImageData,
418 is_animated_image: bool,
419 ) {
420 self.update_images(
421 key.into(),
422 [ImageUpdate::AddImage(
423 key,
424 descriptor,
425 data,
426 is_animated_image,
427 )]
428 .into(),
429 );
430 }
431
432 pub fn update_image(
433 &self,
434 key: ImageKey,
435 descriptor: ImageDescriptor,
436 data: SerializableImageData,
437 epoch: Option<Epoch>,
438 ) {
439 self.update_images(
440 key.into(),
441 [ImageUpdate::UpdateImage(key, descriptor, data, epoch)].into(),
442 );
443 }
444
445 pub fn delete_image(&self, key: ImageKey) {
446 self.update_images(key.into(), [ImageUpdate::DeleteImage(key)].into());
447 }
448
449 pub fn update_images(&self, painter_id: PainterId, updates: SmallVec<[ImageUpdate; 1]>) {
451 if let Err(e) = self.0.send(PaintMessage::UpdateImages(painter_id, updates)) {
452 warn!("error sending image updates: {}", e);
453 }
454 }
455
456 pub fn remove_unused_font_resources(
457 &self,
458 painter_id: PainterId,
459 keys: Vec<FontKey>,
460 instance_keys: Vec<FontInstanceKey>,
461 ) {
462 if keys.is_empty() && instance_keys.is_empty() {
463 return;
464 }
465 let _ = self
466 .0
467 .send(PaintMessage::RemoveFonts(painter_id, keys, instance_keys));
468 }
469
470 pub fn add_font_instance(
471 &self,
472 font_instance_key: FontInstanceKey,
473 font_key: FontKey,
474 size: f32,
475 flags: FontInstanceFlags,
476 variations: Vec<FontVariation>,
477 ) {
478 let _x = self.0.send(PaintMessage::AddFontInstance(
479 font_key.into(),
480 font_instance_key,
481 font_key,
482 size,
483 flags,
484 variations,
485 ));
486 }
487
488 pub fn add_font(&self, font_key: FontKey, data: Arc<GenericSharedMemory>, index: u32) {
489 let _ = self.0.send(PaintMessage::AddFont(
490 font_key.into(),
491 font_key,
492 data,
493 index,
494 ));
495 }
496
497 pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) {
498 let _ = self.0.send(PaintMessage::AddSystemFont(
499 font_key.into(),
500 font_key,
501 handle,
502 ));
503 }
504
505 pub fn fetch_font_keys(
506 &self,
507 number_of_font_keys: usize,
508 number_of_font_instance_keys: usize,
509 painter_id: PainterId,
510 ) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
511 let (sender, receiver) = generic_channel::channel().expect("Could not create IPC channel");
512 let _ = self.0.send(PaintMessage::GenerateFontKeys(
513 number_of_font_keys,
514 number_of_font_instance_keys,
515 sender,
516 painter_id,
517 ));
518 receiver.recv().unwrap()
519 }
520
521 pub fn viewport(&self, webview_id: WebViewId, description: ViewportDescription) {
522 let _ = self.0.send(PaintMessage::Viewport(webview_id, description));
523 }
524
525 pub fn pipeline_exited(
526 &self,
527 webview_id: WebViewId,
528 pipeline_id: PipelineId,
529 source: PipelineExitSource,
530 ) {
531 let _ = self.0.send(PaintMessage::PipelineExited(
532 webview_id,
533 pipeline_id,
534 source,
535 ));
536 }
537}
538
539#[derive(Clone)]
540pub struct PainterSurfmanDetails {
541 pub connection: Connection,
542 pub adapter: Adapter,
543}
544
545#[derive(Clone, Default)]
546pub struct PainterSurfmanDetailsMap(Arc<Mutex<HashMap<PainterId, PainterSurfmanDetails>>>);
547
548impl PainterSurfmanDetailsMap {
549 pub fn get(&self, painter_id: PainterId) -> Option<PainterSurfmanDetails> {
550 let map = self.0.lock().expect("poisoned");
551 map.get(&painter_id).cloned()
552 }
553
554 pub fn insert(&self, painter_id: PainterId, details: PainterSurfmanDetails) {
555 let mut map = self.0.lock().expect("poisoned");
556 let existing = map.insert(painter_id, details);
557 assert!(existing.is_none())
558 }
559
560 pub fn remove(&self, painter_id: PainterId) {
561 let mut map = self.0.lock().expect("poisoned");
562 let details = map.remove(&painter_id);
563 assert!(details.is_some());
564 }
565}
566
567pub trait WebRenderExternalImageApi {
574 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
575 fn unlock(&mut self, id: u64);
576}
577
578#[derive(Clone, Copy)]
580pub enum WebRenderImageHandlerType {
581 WebGl,
582 Media,
583 WebGpu,
584}
585
586#[derive(Default)]
590struct WebRenderExternalImageIdManagerInner {
591 external_images: FxHashMap<ExternalImageId, WebRenderImageHandlerType>,
593 next_image_id: u64,
595}
596
597#[derive(Default, Clone)]
598pub struct WebRenderExternalImageIdManager(Arc<RwLock<WebRenderExternalImageIdManagerInner>>);
599
600impl WebRenderExternalImageIdManager {
601 pub fn next_id(&mut self, handler_type: WebRenderImageHandlerType) -> ExternalImageId {
602 let mut inner = self.0.write();
603 inner.next_image_id += 1;
604 let key = ExternalImageId(inner.next_image_id);
605 inner.external_images.insert(key, handler_type);
606 key
607 }
608
609 pub fn remove(&mut self, key: &ExternalImageId) {
610 self.0.write().external_images.remove(key);
611 }
612
613 pub fn get(&self, key: &ExternalImageId) -> Option<WebRenderImageHandlerType> {
614 self.0.read().external_images.get(key).cloned()
615 }
616}
617
618pub struct WebRenderExternalImageHandlers {
620 webgl_handler: Option<Box<dyn WebRenderExternalImageApi>>,
622 media_handler: Option<Box<dyn WebRenderExternalImageApi>>,
624 webgpu_handler: Option<Box<dyn WebRenderExternalImageApi>>,
626 id_manager: WebRenderExternalImageIdManager,
630}
631
632impl WebRenderExternalImageHandlers {
633 pub fn new(id_manager: WebRenderExternalImageIdManager) -> Self {
634 Self {
635 webgl_handler: Default::default(),
636 media_handler: Default::default(),
637 webgpu_handler: Default::default(),
638 id_manager,
639 }
640 }
641
642 pub fn id_manager(&self) -> WebRenderExternalImageIdManager {
643 self.id_manager.clone()
644 }
645
646 pub fn set_handler(
647 &mut self,
648 handler: Box<dyn WebRenderExternalImageApi>,
649 handler_type: WebRenderImageHandlerType,
650 ) {
651 match handler_type {
652 WebRenderImageHandlerType::WebGl => self.webgl_handler = Some(handler),
653 WebRenderImageHandlerType::Media => self.media_handler = Some(handler),
654 WebRenderImageHandlerType::WebGpu => self.webgpu_handler = Some(handler),
655 }
656 }
657}
658
659impl ExternalImageHandler for WebRenderExternalImageHandlers {
660 fn lock(
665 &mut self,
666 key: ExternalImageId,
667 _channel_index: u8,
668 _is_composited: bool,
669 ) -> ExternalImage<'_> {
670 let handler_type = self
671 .id_manager()
672 .get(&key)
673 .expect("Tried to get unknown external image");
674 match handler_type {
675 WebRenderImageHandlerType::WebGl => {
676 let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0);
677 let texture_id = match source {
678 ExternalImageSource::NativeTexture(b) => b,
679 _ => panic!("Wrong type"),
680 };
681 ExternalImage {
682 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
683 source: ExternalImageSource::NativeTexture(texture_id),
684 }
685 },
686 WebRenderImageHandlerType::Media => {
687 let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0);
688 let texture_id = match source {
689 ExternalImageSource::NativeTexture(b) => b,
690 _ => panic!("Wrong type"),
691 };
692 ExternalImage {
693 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
694 source: ExternalImageSource::NativeTexture(texture_id),
695 }
696 },
697 WebRenderImageHandlerType::WebGpu => {
698 let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
699 ExternalImage {
700 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
701 source,
702 }
703 },
704 }
705 }
706
707 fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) {
710 let handler_type = self
711 .id_manager()
712 .get(&key)
713 .expect("Tried to get unknown external image");
714 match handler_type {
715 WebRenderImageHandlerType::WebGl => self.webgl_handler.as_mut().unwrap().unlock(key.0),
716 WebRenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0),
717 WebRenderImageHandlerType::WebGpu => {
718 self.webgpu_handler.as_mut().unwrap().unlock(key.0)
719 },
720 };
721 }
722}
723
724#[derive(Deserialize, Serialize)]
725pub enum ImageUpdate {
727 AddImage(
729 ImageKey,
730 ImageDescriptor,
731 SerializableImageData,
732 bool, ),
734 DeleteImage(ImageKey),
736 UpdateImage(
738 ImageKey,
739 ImageDescriptor,
740 SerializableImageData,
741 Option<Epoch>,
742 ),
743 UpdateImageForAnimation(ImageKey, ImageDescriptor),
746}
747
748impl Debug for ImageUpdate {
749 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
750 match self {
751 Self::AddImage(image_key, image_desc, _, is_animated_image) => f
752 .debug_tuple("AddImage")
753 .field(image_key)
754 .field(image_desc)
755 .field(is_animated_image)
756 .finish(),
757 Self::DeleteImage(image_key) => f.debug_tuple("DeleteImage").field(image_key).finish(),
758 Self::UpdateImage(image_key, image_desc, _, epoch) => f
759 .debug_tuple("UpdateImage")
760 .field(image_key)
761 .field(image_desc)
762 .field(epoch)
763 .finish(),
764 Self::UpdateImageForAnimation(image_key, image_desc) => f
765 .debug_tuple("UpdateAnimation")
766 .field(image_key)
767 .field(image_desc)
768 .finish(),
769 }
770 }
771}
772
773#[derive(Debug, Deserialize, Serialize)]
774pub enum SerializableImageData {
776 Raw(GenericSharedMemory),
779 External(ExternalImageData),
782}
783
784impl From<SerializableImageData> for ImageData {
785 fn from(value: SerializableImageData) -> Self {
786 match value {
787 SerializableImageData::Raw(shared_memory) => {
788 ImageData::Raw(shared_memory.into_arc_vec())
789 },
790 SerializableImageData::External(image) => ImageData::External(image),
791 }
792 }
793}
794
795pub trait WebViewTrait {
799 fn id(&self) -> WebViewId;
800 fn screen_geometry(&self) -> Option<ScreenGeometry>;
801 fn set_animating(&self, new_value: bool);
802 fn notify_viewport_updated(&self);
806}
807
808#[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
811pub struct PipelineExitSource(u8);
812
813bitflags! {
814 impl PipelineExitSource: u8 {
815 const Script = 1 << 0;
816 const Constellation = 1 << 1;
817 }
818}
819
820#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
824pub struct PinchZoomInfos {
825 pub zoom_factor: Scale<f32, DevicePixel, DevicePixel>,
827
828 pub rect: Rect<f32, CSSPixel>,
830}
831
832impl PinchZoomInfos {
833 pub fn new_from_viewport_size(size: Size2D<f32, CSSPixel>) -> Self {
836 Self {
837 zoom_factor: Scale::identity(),
838 rect: Rect::from_size(size),
839 }
840 }
841}