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 EnableLCPCalculation(WebViewId),
192}
193
194impl Debug for PaintMessage {
195 fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
196 let string: &'static str = self.into();
197 write!(formatter, "{string}")
198 }
199}
200
201#[derive(Deserialize, Serialize)]
202pub struct SendableFrameTree {
203 pub pipeline: CompositionPipeline,
204 pub children: Vec<SendableFrameTree>,
205}
206
207#[derive(Clone, Deserialize, Serialize)]
209pub struct CompositionPipeline {
210 pub id: PipelineId,
211 pub webview_id: WebViewId,
212}
213
214#[derive(Serialize, Deserialize)]
216pub struct SerializableDisplayListPayload {
217 #[serde(with = "serde_bytes")]
219 pub items_data: Vec<u8>,
220
221 #[serde(with = "serde_bytes")]
222 pub spatial_tree: Vec<u8>,
223}
224
225#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
227pub struct CrossProcessPaintApi(GenericCallback<PaintMessage>);
228
229impl CrossProcessPaintApi {
230 pub fn new(callback: GenericCallback<PaintMessage>) -> Self {
232 CrossProcessPaintApi(callback)
233 }
234
235 pub fn dummy() -> Self {
238 Self::dummy_with_callback(None)
239 }
240
241 pub fn dummy_with_callback(
244 callback: Option<Box<dyn Fn(PaintMessage) + Send + 'static>>,
245 ) -> Self {
246 let callback = GenericCallback::new(move |msg| {
247 if let Some(ref handler) = callback &&
248 let Ok(paint_message) = msg
249 {
250 handler(paint_message);
251 }
252 })
253 .unwrap();
254 Self(callback)
255 }
256
257 pub fn send_initial_transaction(&self, webview_id: WebViewId, pipeline: WebRenderPipelineId) {
259 if let Err(e) = self
260 .0
261 .send(PaintMessage::SendInitialTransaction(webview_id, pipeline))
262 {
263 warn!("Error sending initial transaction: {}", e);
264 }
265 }
266
267 pub fn scroll_node_by_delta(
271 &self,
272 webview_id: WebViewId,
273 pipeline_id: WebRenderPipelineId,
274 delta: LayoutVector2D,
275 scroll_id: ExternalScrollId,
276 ) {
277 if let Err(error) = self.0.send(PaintMessage::ScrollNodeByDelta(
278 webview_id,
279 pipeline_id,
280 delta,
281 scroll_id,
282 )) {
283 warn!("Error scrolling node: {error}");
284 }
285 }
286
287 pub fn scroll_viewport_by_delta(&self, webview_id: WebViewId, delta: LayoutVector2D) {
294 if let Err(error) = self
295 .0
296 .send(PaintMessage::ScrollViewportByDelta(webview_id, delta))
297 {
298 warn!("Error scroll viewport: {error}");
299 }
300 }
301
302 pub fn delay_new_frame_for_canvas(
303 &self,
304 webview_id: WebViewId,
305 pipeline_id: PipelineId,
306 canvas_epoch: Epoch,
307 image_keys: Vec<ImageKey>,
308 ) {
309 if let Err(error) = self.0.send(PaintMessage::DelayNewFrameForCanvas(
310 webview_id,
311 pipeline_id,
312 canvas_epoch,
313 image_keys,
314 )) {
315 warn!("Error delaying frames for canvas image updates {error:?}");
316 }
317 }
318
319 pub fn update_epoch(&self, webview_id: WebViewId, pipeline_id: PipelineId, epoch: Epoch) {
322 if let Err(error) = self.0.send(PaintMessage::UpdateEpoch {
323 webview_id,
324 pipeline_id,
325 epoch,
326 }) {
327 warn!("Error updating epoch for pipeline: {error:?}");
328 }
329 }
330
331 #[servo_tracing::instrument(skip_all)]
335 pub fn send_display_list(
336 &self,
337 webview_id: WebViewId,
338 display_list_info: &PaintDisplayListInfo,
339 list: BuiltDisplayList,
340 ) {
341 let (display_list_data, display_list_descriptor) = list.into_data();
342 let (display_list_data_sender, display_list_data_receiver) =
343 generic_channel::channel().unwrap();
344 let (display_list_info_sender, display_list_info_receiver) =
345 generic_channel::channel().unwrap();
346 if let Err(e) = self.0.send(PaintMessage::SendDisplayList {
347 webview_id,
348 display_list_descriptor,
349 display_list_info_receiver,
350 display_list_data_receiver,
351 }) {
352 warn!("Error sending display list: {}", e);
353 }
354
355 if let Err(error) = display_list_info_sender.send(display_list_info.clone()) {
356 warn!("Error sending display list info: {error}. Not sending the rest");
357 return;
358 }
359 let display_list_data = SerializableDisplayListPayload {
360 items_data: display_list_data.items_data,
361 spatial_tree: display_list_data.spatial_tree,
362 };
363
364 if let Err(error) = display_list_data_sender.send(display_list_data) {
365 warn!("Error sending display list: {error}");
366 }
367 }
368
369 pub fn send_lcp_candidate(
371 &self,
372 lcp_candidate: LCPCandidate,
373 webview_id: WebViewId,
374 pipeline_id: PipelineId,
375 epoch: Epoch,
376 ) {
377 if let Err(error) = self.0.send(PaintMessage::SendLCPCandidate(
378 lcp_candidate,
379 webview_id,
380 pipeline_id,
381 epoch,
382 )) {
383 warn!("Error sending LCPCandidate: {error}");
384 }
385 }
386
387 pub fn generate_frame(&self, painter_ids: Vec<PainterId>) {
389 if let Err(error) = self.0.send(PaintMessage::GenerateFrame(painter_ids)) {
390 warn!("Error generating frame: {error}");
391 }
392 }
393
394 pub fn generate_image_key_blocking(&self, webview_id: WebViewId) -> Option<ImageKey> {
396 let (sender, receiver) = generic_channel::channel().unwrap();
397 self.0
398 .send(PaintMessage::GenerateImageKey(webview_id, sender))
399 .ok()?;
400 receiver.recv().ok()
401 }
402
403 pub fn generate_image_key_async(&self, webview_id: WebViewId, pipeline_id: PipelineId) {
407 if let Err(e) = self.0.send(PaintMessage::GenerateImageKeysForPipeline(
408 webview_id,
409 pipeline_id,
410 )) {
411 warn!("Could not send image keys to Paint {}", e);
412 }
413 }
414
415 pub fn add_image(
416 &self,
417 key: ImageKey,
418 descriptor: ImageDescriptor,
419 data: SerializableImageData,
420 is_animated_image: bool,
421 ) {
422 self.update_images(
423 key.into(),
424 [ImageUpdate::AddImage(
425 key,
426 descriptor,
427 data,
428 is_animated_image,
429 )]
430 .into(),
431 );
432 }
433
434 pub fn update_image(
435 &self,
436 key: ImageKey,
437 descriptor: ImageDescriptor,
438 data: SerializableImageData,
439 epoch: Option<Epoch>,
440 ) {
441 self.update_images(
442 key.into(),
443 [ImageUpdate::UpdateImage(key, descriptor, data, epoch)].into(),
444 );
445 }
446
447 pub fn delete_image(&self, key: ImageKey) {
448 self.update_images(key.into(), [ImageUpdate::DeleteImage(key)].into());
449 }
450
451 pub fn update_images(&self, painter_id: PainterId, updates: SmallVec<[ImageUpdate; 1]>) {
453 if let Err(e) = self.0.send(PaintMessage::UpdateImages(painter_id, updates)) {
454 warn!("error sending image updates: {}", e);
455 }
456 }
457
458 pub fn remove_unused_font_resources(
459 &self,
460 painter_id: PainterId,
461 keys: Vec<FontKey>,
462 instance_keys: Vec<FontInstanceKey>,
463 ) {
464 if keys.is_empty() && instance_keys.is_empty() {
465 return;
466 }
467 let _ = self
468 .0
469 .send(PaintMessage::RemoveFonts(painter_id, keys, instance_keys));
470 }
471
472 pub fn add_font_instance(
473 &self,
474 font_instance_key: FontInstanceKey,
475 font_key: FontKey,
476 size: f32,
477 flags: FontInstanceFlags,
478 variations: Vec<FontVariation>,
479 ) {
480 let _x = self.0.send(PaintMessage::AddFontInstance(
481 font_key.into(),
482 font_instance_key,
483 font_key,
484 size,
485 flags,
486 variations,
487 ));
488 }
489
490 pub fn add_font(&self, font_key: FontKey, data: Arc<GenericSharedMemory>, index: u32) {
491 let _ = self.0.send(PaintMessage::AddFont(
492 font_key.into(),
493 font_key,
494 data,
495 index,
496 ));
497 }
498
499 pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) {
500 let _ = self.0.send(PaintMessage::AddSystemFont(
501 font_key.into(),
502 font_key,
503 handle,
504 ));
505 }
506
507 pub fn fetch_font_keys(
508 &self,
509 number_of_font_keys: usize,
510 number_of_font_instance_keys: usize,
511 painter_id: PainterId,
512 ) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
513 let (sender, receiver) = generic_channel::channel().expect("Could not create IPC channel");
514 let _ = self.0.send(PaintMessage::GenerateFontKeys(
515 number_of_font_keys,
516 number_of_font_instance_keys,
517 sender,
518 painter_id,
519 ));
520 receiver.recv().unwrap()
521 }
522
523 pub fn viewport(&self, webview_id: WebViewId, description: ViewportDescription) {
524 let _ = self.0.send(PaintMessage::Viewport(webview_id, description));
525 }
526
527 pub fn pipeline_exited(
528 &self,
529 webview_id: WebViewId,
530 pipeline_id: PipelineId,
531 source: PipelineExitSource,
532 ) {
533 let _ = self.0.send(PaintMessage::PipelineExited(
534 webview_id,
535 pipeline_id,
536 source,
537 ));
538 }
539}
540
541#[derive(Clone)]
542pub struct PainterSurfmanDetails {
543 pub connection: Connection,
544 pub adapter: Adapter,
545}
546
547#[derive(Clone, Default)]
548pub struct PainterSurfmanDetailsMap(Arc<Mutex<HashMap<PainterId, PainterSurfmanDetails>>>);
549
550impl PainterSurfmanDetailsMap {
551 pub fn get(&self, painter_id: PainterId) -> Option<PainterSurfmanDetails> {
552 let map = self.0.lock().expect("poisoned");
553 map.get(&painter_id).cloned()
554 }
555
556 pub fn insert(&self, painter_id: PainterId, details: PainterSurfmanDetails) {
557 let mut map = self.0.lock().expect("poisoned");
558 let existing = map.insert(painter_id, details);
559 assert!(existing.is_none())
560 }
561
562 pub fn remove(&self, painter_id: PainterId) {
563 let mut map = self.0.lock().expect("poisoned");
564 let details = map.remove(&painter_id);
565 assert!(details.is_some());
566 }
567}
568
569pub trait WebRenderExternalImageApi {
576 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
577 fn unlock(&mut self, id: u64);
578}
579
580#[derive(Clone, Copy)]
582pub enum WebRenderImageHandlerType {
583 WebGl,
584 Media,
585 WebGpu,
586}
587
588#[derive(Default)]
592struct WebRenderExternalImageIdManagerInner {
593 external_images: FxHashMap<ExternalImageId, WebRenderImageHandlerType>,
595 next_image_id: u64,
597}
598
599#[derive(Default, Clone)]
600pub struct WebRenderExternalImageIdManager(Arc<RwLock<WebRenderExternalImageIdManagerInner>>);
601
602impl WebRenderExternalImageIdManager {
603 pub fn next_id(&mut self, handler_type: WebRenderImageHandlerType) -> ExternalImageId {
604 let mut inner = self.0.write();
605 inner.next_image_id += 1;
606 let key = ExternalImageId(inner.next_image_id);
607 inner.external_images.insert(key, handler_type);
608 key
609 }
610
611 pub fn remove(&mut self, key: &ExternalImageId) {
612 self.0.write().external_images.remove(key);
613 }
614
615 pub fn get(&self, key: &ExternalImageId) -> Option<WebRenderImageHandlerType> {
616 self.0.read().external_images.get(key).cloned()
617 }
618}
619
620pub struct WebRenderExternalImageHandlers {
622 webgl_handler: Option<Box<dyn WebRenderExternalImageApi>>,
624 media_handler: Option<Box<dyn WebRenderExternalImageApi>>,
626 webgpu_handler: Option<Box<dyn WebRenderExternalImageApi>>,
628 id_manager: WebRenderExternalImageIdManager,
632}
633
634impl WebRenderExternalImageHandlers {
635 pub fn new(id_manager: WebRenderExternalImageIdManager) -> Self {
636 Self {
637 webgl_handler: Default::default(),
638 media_handler: Default::default(),
639 webgpu_handler: Default::default(),
640 id_manager,
641 }
642 }
643
644 pub fn id_manager(&self) -> WebRenderExternalImageIdManager {
645 self.id_manager.clone()
646 }
647
648 pub fn set_handler(
649 &mut self,
650 handler: Box<dyn WebRenderExternalImageApi>,
651 handler_type: WebRenderImageHandlerType,
652 ) {
653 match handler_type {
654 WebRenderImageHandlerType::WebGl => self.webgl_handler = Some(handler),
655 WebRenderImageHandlerType::Media => self.media_handler = Some(handler),
656 WebRenderImageHandlerType::WebGpu => self.webgpu_handler = Some(handler),
657 }
658 }
659}
660
661impl ExternalImageHandler for WebRenderExternalImageHandlers {
662 fn lock(
667 &mut self,
668 key: ExternalImageId,
669 _channel_index: u8,
670 _is_composited: bool,
671 ) -> ExternalImage<'_> {
672 let handler_type = self
673 .id_manager()
674 .get(&key)
675 .expect("Tried to get unknown external image");
676 match handler_type {
677 WebRenderImageHandlerType::WebGl => {
678 let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0);
679 let texture_id = match source {
680 ExternalImageSource::NativeTexture(b) => b,
681 _ => panic!("Wrong type"),
682 };
683 ExternalImage {
684 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
685 source: ExternalImageSource::NativeTexture(texture_id),
686 }
687 },
688 WebRenderImageHandlerType::Media => {
689 let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0);
690 let texture_id = match source {
691 ExternalImageSource::NativeTexture(b) => b,
692 _ => panic!("Wrong type"),
693 };
694 ExternalImage {
695 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
696 source: ExternalImageSource::NativeTexture(texture_id),
697 }
698 },
699 WebRenderImageHandlerType::WebGpu => {
700 let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
701 ExternalImage {
702 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
703 source,
704 }
705 },
706 }
707 }
708
709 fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) {
712 let handler_type = self
713 .id_manager()
714 .get(&key)
715 .expect("Tried to get unknown external image");
716 match handler_type {
717 WebRenderImageHandlerType::WebGl => self.webgl_handler.as_mut().unwrap().unlock(key.0),
718 WebRenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0),
719 WebRenderImageHandlerType::WebGpu => {
720 self.webgpu_handler.as_mut().unwrap().unlock(key.0)
721 },
722 };
723 }
724}
725
726#[derive(Deserialize, Serialize)]
727pub enum ImageUpdate {
729 AddImage(
731 ImageKey,
732 ImageDescriptor,
733 SerializableImageData,
734 bool, ),
736 DeleteImage(ImageKey),
738 UpdateImage(
740 ImageKey,
741 ImageDescriptor,
742 SerializableImageData,
743 Option<Epoch>,
744 ),
745 UpdateImageForAnimation(ImageKey, ImageDescriptor),
748}
749
750impl Debug for ImageUpdate {
751 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
752 match self {
753 Self::AddImage(image_key, image_desc, _, is_animated_image) => f
754 .debug_tuple("AddImage")
755 .field(image_key)
756 .field(image_desc)
757 .field(is_animated_image)
758 .finish(),
759 Self::DeleteImage(image_key) => f.debug_tuple("DeleteImage").field(image_key).finish(),
760 Self::UpdateImage(image_key, image_desc, _, epoch) => f
761 .debug_tuple("UpdateImage")
762 .field(image_key)
763 .field(image_desc)
764 .field(epoch)
765 .finish(),
766 Self::UpdateImageForAnimation(image_key, image_desc) => f
767 .debug_tuple("UpdateAnimation")
768 .field(image_key)
769 .field(image_desc)
770 .finish(),
771 }
772 }
773}
774
775#[derive(Debug, Deserialize, Serialize)]
776pub enum SerializableImageData {
778 Raw(GenericSharedMemory),
781 External(ExternalImageData),
784}
785
786impl From<SerializableImageData> for ImageData {
787 fn from(value: SerializableImageData) -> Self {
788 match value {
789 SerializableImageData::Raw(shared_memory) => {
790 ImageData::Raw(shared_memory.into_arc_vec())
791 },
792 SerializableImageData::External(image) => ImageData::External(image),
793 }
794 }
795}
796
797pub trait WebViewTrait {
801 fn id(&self) -> WebViewId;
802 fn screen_geometry(&self) -> Option<ScreenGeometry>;
803 fn set_animating(&self, new_value: bool);
804}
805
806#[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
809pub struct PipelineExitSource(u8);
810
811bitflags! {
812 impl PipelineExitSource: u8 {
813 const Script = 1 << 0;
814 const Constellation = 1 << 1;
815 }
816}
817
818#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
822pub struct PinchZoomInfos {
823 pub zoom_factor: Scale<f32, DevicePixel, DevicePixel>,
825
826 pub rect: Rect<f32, CSSPixel>,
828}
829
830impl PinchZoomInfos {
831 pub fn new_from_viewport_size(size: Size2D<f32, CSSPixel>) -> Self {
834 Self {
835 zoom_factor: Scale::identity(),
836 rect: Rect::from_size(size),
837 }
838 }
839}