1use std::collections::HashMap;
8use std::fmt::{Debug, Error, Formatter};
9
10use base::Epoch;
11use base::id::{PainterId, PipelineId, WebViewId};
12use crossbeam_channel::Sender;
13use embedder_traits::{AnimationState, EventLoopWaker};
14use euclid::{Rect, Scale, Size2D};
15use log::warn;
16use malloc_size_of_derive::MallocSizeOf;
17use parking_lot::RwLock;
18use rustc_hash::FxHashMap;
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 base::generic_channel::{
33 self, GenericCallback, GenericReceiver, GenericSender, GenericSharedMemory,
34};
35use bitflags::bitflags;
36use display_list::PaintDisplayListInfo;
37use embedder_traits::ScreenGeometry;
38use euclid::default::Size2D as UntypedSize2D;
39use profile_traits::mem::{OpaqueSender, ReportsChan};
40use serde::{Deserialize, Serialize};
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")]
223 pub cache_data: Vec<u8>,
224
225 #[serde(with = "serde_bytes")]
227 pub spatial_tree: Vec<u8>,
228}
229
230#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
232pub struct CrossProcessPaintApi(GenericCallback<PaintMessage>);
233
234impl CrossProcessPaintApi {
235 pub fn new(callback: GenericCallback<PaintMessage>) -> Self {
237 CrossProcessPaintApi(callback)
238 }
239
240 pub fn dummy() -> Self {
243 Self::dummy_with_callback(None)
244 }
245
246 pub fn dummy_with_callback(
249 callback: Option<Box<dyn Fn(PaintMessage) + Send + 'static>>,
250 ) -> Self {
251 let callback = GenericCallback::new(move |msg| {
252 if let Some(ref handler) = callback {
253 if let Ok(paint_message) = msg {
254 handler(paint_message);
255 }
256 }
257 })
258 .unwrap();
259 Self(callback)
260 }
261
262 pub fn send_initial_transaction(&self, webview_id: WebViewId, pipeline: WebRenderPipelineId) {
264 if let Err(e) = self
265 .0
266 .send(PaintMessage::SendInitialTransaction(webview_id, pipeline))
267 {
268 warn!("Error sending initial transaction: {}", e);
269 }
270 }
271
272 pub fn scroll_node_by_delta(
276 &self,
277 webview_id: WebViewId,
278 pipeline_id: WebRenderPipelineId,
279 delta: LayoutVector2D,
280 scroll_id: ExternalScrollId,
281 ) {
282 if let Err(error) = self.0.send(PaintMessage::ScrollNodeByDelta(
283 webview_id,
284 pipeline_id,
285 delta,
286 scroll_id,
287 )) {
288 warn!("Error scrolling node: {error}");
289 }
290 }
291
292 pub fn scroll_viewport_by_delta(&self, webview_id: WebViewId, delta: LayoutVector2D) {
299 if let Err(error) = self
300 .0
301 .send(PaintMessage::ScrollViewportByDelta(webview_id, delta))
302 {
303 warn!("Error scroll viewport: {error}");
304 }
305 }
306
307 pub fn delay_new_frame_for_canvas(
308 &self,
309 webview_id: WebViewId,
310 pipeline_id: PipelineId,
311 canvas_epoch: Epoch,
312 image_keys: Vec<ImageKey>,
313 ) {
314 if let Err(error) = self.0.send(PaintMessage::DelayNewFrameForCanvas(
315 webview_id,
316 pipeline_id,
317 canvas_epoch,
318 image_keys,
319 )) {
320 warn!("Error delaying frames for canvas image updates {error:?}");
321 }
322 }
323
324 pub fn update_epoch(&self, webview_id: WebViewId, pipeline_id: PipelineId, epoch: Epoch) {
327 if let Err(error) = self.0.send(PaintMessage::UpdateEpoch {
328 webview_id,
329 pipeline_id,
330 epoch,
331 }) {
332 warn!("Error updating epoch for pipeline: {error:?}");
333 }
334 }
335
336 #[servo_tracing::instrument(skip_all)]
340 pub fn send_display_list(
341 &self,
342 webview_id: WebViewId,
343 display_list_info: &PaintDisplayListInfo,
344 list: BuiltDisplayList,
345 ) {
346 let (display_list_data, display_list_descriptor) = list.into_data();
347 let (display_list_data_sender, display_list_data_receiver) =
348 generic_channel::channel().unwrap();
349 let (display_list_info_sender, display_list_info_receiver) =
350 generic_channel::channel().unwrap();
351 if let Err(e) = self.0.send(PaintMessage::SendDisplayList {
352 webview_id,
353 display_list_descriptor,
354 display_list_info_receiver,
355 display_list_data_receiver,
356 }) {
357 warn!("Error sending display list: {}", e);
358 }
359
360 if let Err(error) = display_list_info_sender.send(display_list_info.clone()) {
361 warn!("Error sending display list info: {error}. Not sending the rest");
362 return;
363 }
364 let display_list_data = SerializableDisplayListPayload {
365 items_data: display_list_data.items_data,
366 cache_data: display_list_data.cache_data,
367 spatial_tree: display_list_data.spatial_tree,
368 };
369
370 if let Err(error) = display_list_data_sender.send(display_list_data) {
371 warn!("Error sending display list: {error}");
372 }
373 }
374
375 pub fn send_lcp_candidate(
377 &self,
378 lcp_candidate: LCPCandidate,
379 webview_id: WebViewId,
380 pipeline_id: PipelineId,
381 epoch: Epoch,
382 ) {
383 if let Err(error) = self.0.send(PaintMessage::SendLCPCandidate(
384 lcp_candidate,
385 webview_id,
386 pipeline_id,
387 epoch,
388 )) {
389 warn!("Error sending LCPCandidate: {error}");
390 }
391 }
392
393 pub fn generate_frame(&self, painter_ids: Vec<PainterId>) {
395 if let Err(error) = self.0.send(PaintMessage::GenerateFrame(painter_ids)) {
396 warn!("Error generating frame: {error}");
397 }
398 }
399
400 pub fn generate_image_key_blocking(&self, webview_id: WebViewId) -> Option<ImageKey> {
402 let (sender, receiver) = generic_channel::channel().unwrap();
403 self.0
404 .send(PaintMessage::GenerateImageKey(webview_id, sender))
405 .ok()?;
406 receiver.recv().ok()
407 }
408
409 pub fn generate_image_key_async(&self, webview_id: WebViewId, pipeline_id: PipelineId) {
413 if let Err(e) = self.0.send(PaintMessage::GenerateImageKeysForPipeline(
414 webview_id,
415 pipeline_id,
416 )) {
417 warn!("Could not send image keys to Paint {}", e);
418 }
419 }
420
421 pub fn add_image(
422 &self,
423 key: ImageKey,
424 descriptor: ImageDescriptor,
425 data: SerializableImageData,
426 is_animated_image: bool,
427 ) {
428 self.update_images(
429 key.into(),
430 [ImageUpdate::AddImage(
431 key,
432 descriptor,
433 data,
434 is_animated_image,
435 )]
436 .into(),
437 );
438 }
439
440 pub fn update_image(
441 &self,
442 key: ImageKey,
443 descriptor: ImageDescriptor,
444 data: SerializableImageData,
445 epoch: Option<Epoch>,
446 ) {
447 self.update_images(
448 key.into(),
449 [ImageUpdate::UpdateImage(key, descriptor, data, epoch)].into(),
450 );
451 }
452
453 pub fn delete_image(&self, key: ImageKey) {
454 self.update_images(key.into(), [ImageUpdate::DeleteImage(key)].into());
455 }
456
457 pub fn update_images(&self, painter_id: PainterId, updates: SmallVec<[ImageUpdate; 1]>) {
459 if let Err(e) = self.0.send(PaintMessage::UpdateImages(painter_id, updates)) {
460 warn!("error sending image updates: {}", e);
461 }
462 }
463
464 pub fn remove_unused_font_resources(
465 &self,
466 painter_id: PainterId,
467 keys: Vec<FontKey>,
468 instance_keys: Vec<FontInstanceKey>,
469 ) {
470 if keys.is_empty() && instance_keys.is_empty() {
471 return;
472 }
473 let _ = self
474 .0
475 .send(PaintMessage::RemoveFonts(painter_id, keys, instance_keys));
476 }
477
478 pub fn add_font_instance(
479 &self,
480 font_instance_key: FontInstanceKey,
481 font_key: FontKey,
482 size: f32,
483 flags: FontInstanceFlags,
484 variations: Vec<FontVariation>,
485 ) {
486 let _x = self.0.send(PaintMessage::AddFontInstance(
487 font_key.into(),
488 font_instance_key,
489 font_key,
490 size,
491 flags,
492 variations,
493 ));
494 }
495
496 pub fn add_font(&self, font_key: FontKey, data: Arc<GenericSharedMemory>, index: u32) {
497 let _ = self.0.send(PaintMessage::AddFont(
498 font_key.into(),
499 font_key,
500 data,
501 index,
502 ));
503 }
504
505 pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) {
506 let _ = self.0.send(PaintMessage::AddSystemFont(
507 font_key.into(),
508 font_key,
509 handle,
510 ));
511 }
512
513 pub fn fetch_font_keys(
514 &self,
515 number_of_font_keys: usize,
516 number_of_font_instance_keys: usize,
517 painter_id: PainterId,
518 ) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
519 let (sender, receiver) = generic_channel::channel().expect("Could not create IPC channel");
520 let _ = self.0.send(PaintMessage::GenerateFontKeys(
521 number_of_font_keys,
522 number_of_font_instance_keys,
523 sender,
524 painter_id,
525 ));
526 receiver.recv().unwrap()
527 }
528
529 pub fn viewport(&self, webview_id: WebViewId, description: ViewportDescription) {
530 let _ = self.0.send(PaintMessage::Viewport(webview_id, description));
531 }
532
533 pub fn pipeline_exited(
534 &self,
535 webview_id: WebViewId,
536 pipeline_id: PipelineId,
537 source: PipelineExitSource,
538 ) {
539 let _ = self.0.send(PaintMessage::PipelineExited(
540 webview_id,
541 pipeline_id,
542 source,
543 ));
544 }
545}
546
547#[derive(Clone)]
548pub struct PainterSurfmanDetails {
549 pub connection: Connection,
550 pub adapter: Adapter,
551}
552
553#[derive(Clone, Default)]
554pub struct PainterSurfmanDetailsMap(Arc<Mutex<HashMap<PainterId, PainterSurfmanDetails>>>);
555
556impl PainterSurfmanDetailsMap {
557 pub fn get(&self, painter_id: PainterId) -> Option<PainterSurfmanDetails> {
558 let map = self.0.lock().expect("poisoned");
559 map.get(&painter_id).cloned()
560 }
561
562 pub fn insert(&self, painter_id: PainterId, details: PainterSurfmanDetails) {
563 let mut map = self.0.lock().expect("poisoned");
564 let existing = map.insert(painter_id, details);
565 assert!(existing.is_none())
566 }
567
568 pub fn remove(&self, painter_id: PainterId) {
569 let mut map = self.0.lock().expect("poisoned");
570 let details = map.remove(&painter_id);
571 assert!(details.is_some());
572 }
573}
574
575pub trait WebRenderExternalImageApi {
582 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
583 fn unlock(&mut self, id: u64);
584}
585
586#[derive(Clone, Copy)]
588pub enum WebRenderImageHandlerType {
589 WebGl,
590 Media,
591 WebGpu,
592}
593
594#[derive(Default)]
598struct WebRenderExternalImageIdManagerInner {
599 external_images: FxHashMap<ExternalImageId, WebRenderImageHandlerType>,
601 next_image_id: u64,
603}
604
605#[derive(Default, Clone)]
606pub struct WebRenderExternalImageIdManager(Arc<RwLock<WebRenderExternalImageIdManagerInner>>);
607
608impl WebRenderExternalImageIdManager {
609 pub fn next_id(&mut self, handler_type: WebRenderImageHandlerType) -> ExternalImageId {
610 let mut inner = self.0.write();
611 inner.next_image_id += 1;
612 let key = ExternalImageId(inner.next_image_id);
613 inner.external_images.insert(key, handler_type);
614 key
615 }
616
617 pub fn remove(&mut self, key: &ExternalImageId) {
618 self.0.write().external_images.remove(key);
619 }
620
621 pub fn get(&self, key: &ExternalImageId) -> Option<WebRenderImageHandlerType> {
622 self.0.read().external_images.get(key).cloned()
623 }
624}
625
626pub struct WebRenderExternalImageHandlers {
628 webgl_handler: Option<Box<dyn WebRenderExternalImageApi>>,
630 media_handler: Option<Box<dyn WebRenderExternalImageApi>>,
632 webgpu_handler: Option<Box<dyn WebRenderExternalImageApi>>,
634 id_manager: WebRenderExternalImageIdManager,
638}
639
640impl WebRenderExternalImageHandlers {
641 pub fn new(id_manager: WebRenderExternalImageIdManager) -> Self {
642 Self {
643 webgl_handler: Default::default(),
644 media_handler: Default::default(),
645 webgpu_handler: Default::default(),
646 id_manager,
647 }
648 }
649
650 pub fn id_manager(&self) -> WebRenderExternalImageIdManager {
651 self.id_manager.clone()
652 }
653
654 pub fn set_handler(
655 &mut self,
656 handler: Box<dyn WebRenderExternalImageApi>,
657 handler_type: WebRenderImageHandlerType,
658 ) {
659 match handler_type {
660 WebRenderImageHandlerType::WebGl => self.webgl_handler = Some(handler),
661 WebRenderImageHandlerType::Media => self.media_handler = Some(handler),
662 WebRenderImageHandlerType::WebGpu => self.webgpu_handler = Some(handler),
663 }
664 }
665}
666
667impl ExternalImageHandler for WebRenderExternalImageHandlers {
668 fn lock(
673 &mut self,
674 key: ExternalImageId,
675 _channel_index: u8,
676 _is_composited: bool,
677 ) -> ExternalImage<'_> {
678 let handler_type = self
679 .id_manager()
680 .get(&key)
681 .expect("Tried to get unknown external image");
682 match handler_type {
683 WebRenderImageHandlerType::WebGl => {
684 let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0);
685 let texture_id = match source {
686 ExternalImageSource::NativeTexture(b) => b,
687 _ => panic!("Wrong type"),
688 };
689 ExternalImage {
690 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
691 source: ExternalImageSource::NativeTexture(texture_id),
692 }
693 },
694 WebRenderImageHandlerType::Media => {
695 let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0);
696 let texture_id = match source {
697 ExternalImageSource::NativeTexture(b) => b,
698 _ => panic!("Wrong type"),
699 };
700 ExternalImage {
701 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
702 source: ExternalImageSource::NativeTexture(texture_id),
703 }
704 },
705 WebRenderImageHandlerType::WebGpu => {
706 let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
707 ExternalImage {
708 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
709 source,
710 }
711 },
712 }
713 }
714
715 fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) {
718 let handler_type = self
719 .id_manager()
720 .get(&key)
721 .expect("Tried to get unknown external image");
722 match handler_type {
723 WebRenderImageHandlerType::WebGl => self.webgl_handler.as_mut().unwrap().unlock(key.0),
724 WebRenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0),
725 WebRenderImageHandlerType::WebGpu => {
726 self.webgpu_handler.as_mut().unwrap().unlock(key.0)
727 },
728 };
729 }
730}
731
732#[derive(Deserialize, Serialize)]
733pub enum ImageUpdate {
735 AddImage(
737 ImageKey,
738 ImageDescriptor,
739 SerializableImageData,
740 bool, ),
742 DeleteImage(ImageKey),
744 UpdateImage(
746 ImageKey,
747 ImageDescriptor,
748 SerializableImageData,
749 Option<Epoch>,
750 ),
751 UpdateImageForAnimation(ImageKey, ImageDescriptor),
754}
755
756impl Debug for ImageUpdate {
757 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
758 match self {
759 Self::AddImage(image_key, image_desc, _, is_animated_image) => f
760 .debug_tuple("AddImage")
761 .field(image_key)
762 .field(image_desc)
763 .field(is_animated_image)
764 .finish(),
765 Self::DeleteImage(image_key) => f.debug_tuple("DeleteImage").field(image_key).finish(),
766 Self::UpdateImage(image_key, image_desc, _, epoch) => f
767 .debug_tuple("UpdateImage")
768 .field(image_key)
769 .field(image_desc)
770 .field(epoch)
771 .finish(),
772 Self::UpdateImageForAnimation(image_key, image_desc) => f
773 .debug_tuple("UpdateAnimation")
774 .field(image_key)
775 .field(image_desc)
776 .finish(),
777 }
778 }
779}
780
781#[derive(Debug, Deserialize, Serialize)]
782pub enum SerializableImageData {
785 Raw(GenericSharedMemory),
788 External(ExternalImageData),
791}
792
793impl From<SerializableImageData> for ImageData {
794 fn from(value: SerializableImageData) -> Self {
795 match value {
796 SerializableImageData::Raw(shared_memory) => ImageData::new(shared_memory.to_vec()),
797 SerializableImageData::External(image) => ImageData::External(image),
798 }
799 }
800}
801
802pub trait WebViewTrait {
806 fn id(&self) -> WebViewId;
807 fn screen_geometry(&self) -> Option<ScreenGeometry>;
808 fn set_animating(&self, new_value: bool);
809}
810
811#[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
814pub struct PipelineExitSource(u8);
815
816bitflags! {
817 impl PipelineExitSource: u8 {
818 const Script = 1 << 0;
819 const Constellation = 1 << 1;
820 }
821}
822
823#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
827pub struct PinchZoomInfos {
828 pub zoom_factor: Scale<f32, DevicePixel, DevicePixel>,
830
831 pub rect: Rect<f32, CSSPixel>,
833}
834
835impl PinchZoomInfos {
836 pub fn new_from_viewport_size(size: Size2D<f32, CSSPixel>) -> Self {
839 Self {
840 zoom_factor: Scale::identity(),
841 rect: Rect::from_size(size),
842 }
843 }
844}