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 rendering_context;
27pub mod viewport_description;
28
29use std::sync::{Arc, Mutex};
30
31use bitflags::bitflags;
32use display_list::PaintDisplayListInfo;
33use embedder_traits::ScreenGeometry;
34use euclid::default::Size2D as UntypedSize2D;
35use profile_traits::mem::{OpaqueSender, ReportsChan};
36use serde::{Deserialize, Serialize};
37use servo_base::generic_channel::{
38 self, GenericCallback, GenericReceiver, GenericSender, GenericSharedMemory, SendError,
39};
40pub use webrender_api::ExternalImageSource;
41use webrender_api::units::{DevicePixel, LayoutVector2D, TexelRect};
42use webrender_api::{
43 BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData,
44 ExternalImageHandler, ExternalImageId, ExternalScrollId, FontInstanceFlags, FontInstanceKey,
45 FontKey, ImageData, ImageDescriptor, ImageKey, NativeFontHandle,
46 PipelineId as WebRenderPipelineId,
47};
48
49use crate::viewport_description::ViewportDescription;
50
51#[derive(Clone)]
53pub struct PaintProxy {
54 pub sender: Sender<Result<PaintMessage, SendError>>,
55 pub cross_process_paint_api: CrossProcessPaintApi,
59 pub event_loop_waker: Box<dyn EventLoopWaker>,
60}
61
62impl OpaqueSender<PaintMessage> for PaintProxy {
63 fn send(&self, message: PaintMessage) {
64 PaintProxy::send(self, message)
65 }
66}
67
68impl PaintProxy {
69 pub fn send(&self, msg: PaintMessage) {
70 self.route_msg(Ok(msg))
71 }
72
73 pub fn route_msg(&self, msg: Result<PaintMessage, SendError>) {
78 if let Err(err) = self.sender.send(msg) {
79 warn!("Failed to send response ({:?}).", err);
80 }
81 self.event_loop_waker.wake();
82 }
83}
84
85#[derive(Deserialize, IntoStaticStr, Serialize)]
87pub enum PaintMessage {
88 ChangeRunningAnimationsState(WebViewId, PipelineId, AnimationState),
90 SetFrameTreeForWebView(WebViewId, SendableFrameTree),
92 SetThrottled(WebViewId, PipelineId, bool),
94 NewWebRenderFrameReady(PainterId, DocumentId, bool),
98 PipelineExited(WebViewId, PipelineId, PipelineExitSource),
103 SendInitialTransaction(WebViewId, WebRenderPipelineId),
105 ScrollNodeByDelta(
109 WebViewId,
110 WebRenderPipelineId,
111 LayoutVector2D,
112 ExternalScrollId,
113 ),
114 ScrollViewportByDelta(WebViewId, LayoutVector2D),
118 UpdateEpoch {
120 webview_id: WebViewId,
122 pipeline_id: PipelineId,
124 epoch: Epoch,
126 },
127 SendDisplayList {
129 webview_id: WebViewId,
131 display_list_descriptor: BuiltDisplayListDescriptor,
133 display_list_info_receiver: GenericReceiver<PaintDisplayListInfo>,
135 display_list_data_receiver: GenericReceiver<SerializableDisplayListPayload>,
137 },
138 GenerateFrame(Vec<PainterId>),
141 GenerateImageKey(WebViewId, GenericSender<ImageKey>),
144 GenerateImageKeysForPipeline(WebViewId, PipelineId),
147 UpdateImages(PainterId, SmallVec<[ImageUpdate; 1]>),
149 DelayNewFrameForCanvas(WebViewId, PipelineId, Epoch, Vec<ImageKey>),
154
155 GenerateFontKeys(
158 usize,
159 usize,
160 GenericSender<(Vec<FontKey>, Vec<FontInstanceKey>)>,
161 PainterId,
162 ),
163 AddFont(PainterId, FontKey, Arc<GenericSharedMemory>, u32),
165 AddSystemFont(PainterId, FontKey, NativeFontHandle),
167 AddFontInstance(
169 PainterId,
170 FontInstanceKey,
171 FontKey,
172 f32,
173 FontInstanceFlags,
174 Vec<FontVariation>,
175 ),
176 RemoveFonts(PainterId, Vec<FontKey>, Vec<FontInstanceKey>),
178 CollectMemoryReport(ReportsChan),
181 Viewport(WebViewId, ViewportDescription),
183 ScreenshotReadinessReponse(WebViewId, FxHashMap<PipelineId, Epoch>),
186}
187
188impl Debug for PaintMessage {
189 fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
190 let string: &'static str = self.into();
191 write!(formatter, "{string}")
192 }
193}
194
195#[derive(Deserialize, Serialize)]
196pub struct SendableFrameTree {
197 pub pipeline: CompositionPipeline,
198 pub children: Vec<SendableFrameTree>,
199}
200
201#[derive(Clone, Deserialize, Serialize)]
203pub struct CompositionPipeline {
204 pub id: PipelineId,
205 pub webview_id: WebViewId,
206}
207
208#[derive(Serialize, Deserialize)]
210pub struct SerializableDisplayListPayload {
211 #[serde(with = "serde_bytes")]
213 pub items_data: Vec<u8>,
214
215 #[serde(with = "serde_bytes")]
216 pub spatial_tree: Vec<u8>,
217}
218
219#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
221pub struct CrossProcessPaintApi(GenericCallback<PaintMessage>);
222
223impl CrossProcessPaintApi {
224 pub fn new(callback: GenericCallback<PaintMessage>) -> Self {
226 CrossProcessPaintApi(callback)
227 }
228
229 pub fn dummy() -> Self {
232 Self::dummy_with_callback(None)
233 }
234
235 pub fn dummy_with_callback(
238 callback: Option<Box<dyn Fn(PaintMessage) + Send + 'static>>,
239 ) -> Self {
240 let callback = GenericCallback::new(move |msg| {
241 if let Some(ref handler) = callback &&
242 let Ok(paint_message) = msg
243 {
244 handler(paint_message);
245 }
246 })
247 .unwrap();
248 Self(callback)
249 }
250
251 pub fn send_initial_transaction(&self, webview_id: WebViewId, pipeline: WebRenderPipelineId) {
253 if let Err(e) = self
254 .0
255 .send(PaintMessage::SendInitialTransaction(webview_id, pipeline))
256 {
257 warn!("Error sending initial transaction: {}", e);
258 }
259 }
260
261 pub fn scroll_node_by_delta(
265 &self,
266 webview_id: WebViewId,
267 pipeline_id: WebRenderPipelineId,
268 delta: LayoutVector2D,
269 scroll_id: ExternalScrollId,
270 ) {
271 if let Err(error) = self.0.send(PaintMessage::ScrollNodeByDelta(
272 webview_id,
273 pipeline_id,
274 delta,
275 scroll_id,
276 )) {
277 warn!("Error scrolling node: {error}");
278 }
279 }
280
281 pub fn scroll_viewport_by_delta(&self, webview_id: WebViewId, delta: LayoutVector2D) {
288 if let Err(error) = self
289 .0
290 .send(PaintMessage::ScrollViewportByDelta(webview_id, delta))
291 {
292 warn!("Error scroll viewport: {error}");
293 }
294 }
295
296 pub fn delay_new_frame_for_canvas(
297 &self,
298 webview_id: WebViewId,
299 pipeline_id: PipelineId,
300 canvas_epoch: Epoch,
301 image_keys: Vec<ImageKey>,
302 ) {
303 if let Err(error) = self.0.send(PaintMessage::DelayNewFrameForCanvas(
304 webview_id,
305 pipeline_id,
306 canvas_epoch,
307 image_keys,
308 )) {
309 warn!("Error delaying frames for canvas image updates {error:?}");
310 }
311 }
312
313 pub fn update_epoch(&self, webview_id: WebViewId, pipeline_id: PipelineId, epoch: Epoch) {
316 if let Err(error) = self.0.send(PaintMessage::UpdateEpoch {
317 webview_id,
318 pipeline_id,
319 epoch,
320 }) {
321 warn!("Error updating epoch for pipeline: {error:?}");
322 }
323 }
324
325 #[servo_tracing::instrument(skip_all)]
329 pub fn send_display_list(
330 &self,
331 webview_id: WebViewId,
332 display_list_info: &PaintDisplayListInfo,
333 list: BuiltDisplayList,
334 ) {
335 let (display_list_data, display_list_descriptor) = list.into_data();
336 let (display_list_data_sender, display_list_data_receiver) =
337 generic_channel::channel().unwrap();
338 let (display_list_info_sender, display_list_info_receiver) =
339 generic_channel::channel().unwrap();
340 if let Err(e) = self.0.send(PaintMessage::SendDisplayList {
341 webview_id,
342 display_list_descriptor,
343 display_list_info_receiver,
344 display_list_data_receiver,
345 }) {
346 warn!("Error sending display list: {}", e);
347 }
348
349 if let Err(error) = display_list_info_sender.send(display_list_info.clone()) {
350 warn!("Error sending display list info: {error}. Not sending the rest");
351 return;
352 }
353 let display_list_data = SerializableDisplayListPayload {
354 items_data: display_list_data.items_data,
355 spatial_tree: display_list_data.spatial_tree,
356 };
357
358 if let Err(error) = display_list_data_sender.send(display_list_data) {
359 warn!("Error sending display list: {error}");
360 }
361 }
362
363 pub fn generate_frame(&self, painter_ids: Vec<PainterId>) {
365 if let Err(error) = self.0.send(PaintMessage::GenerateFrame(painter_ids)) {
366 warn!("Error generating frame: {error}");
367 }
368 }
369
370 pub fn generate_image_key_blocking(&self, webview_id: WebViewId) -> Option<ImageKey> {
372 let (sender, receiver) = generic_channel::channel().unwrap();
373 self.0
374 .send(PaintMessage::GenerateImageKey(webview_id, sender))
375 .ok()?;
376 receiver.recv().ok()
377 }
378
379 pub fn generate_image_key_async(&self, webview_id: WebViewId, pipeline_id: PipelineId) {
383 if let Err(e) = self.0.send(PaintMessage::GenerateImageKeysForPipeline(
384 webview_id,
385 pipeline_id,
386 )) {
387 warn!("Could not send image keys to Paint {}", e);
388 }
389 }
390
391 pub fn add_image(
392 &self,
393 key: ImageKey,
394 descriptor: ImageDescriptor,
395 data: SerializableImageData,
396 is_animated_image: bool,
397 ) {
398 self.update_images(
399 key.into(),
400 [ImageUpdate::AddImage(
401 key,
402 descriptor,
403 data,
404 is_animated_image,
405 )]
406 .into(),
407 );
408 }
409
410 pub fn update_image(
411 &self,
412 key: ImageKey,
413 descriptor: ImageDescriptor,
414 data: SerializableImageData,
415 epoch: Option<Epoch>,
416 ) {
417 self.update_images(
418 key.into(),
419 [ImageUpdate::UpdateImage(key, descriptor, data, epoch)].into(),
420 );
421 }
422
423 pub fn delete_image(&self, key: ImageKey) {
424 self.update_images(key.into(), [ImageUpdate::DeleteImage(key)].into());
425 }
426
427 pub fn update_images(&self, painter_id: PainterId, updates: SmallVec<[ImageUpdate; 1]>) {
429 if let Err(e) = self.0.send(PaintMessage::UpdateImages(painter_id, updates)) {
430 warn!("error sending image updates: {}", e);
431 }
432 }
433
434 pub fn remove_unused_font_resources(
435 &self,
436 painter_id: PainterId,
437 keys: Vec<FontKey>,
438 instance_keys: Vec<FontInstanceKey>,
439 ) {
440 if keys.is_empty() && instance_keys.is_empty() {
441 return;
442 }
443 let _ = self
444 .0
445 .send(PaintMessage::RemoveFonts(painter_id, keys, instance_keys));
446 }
447
448 pub fn add_font_instance(
449 &self,
450 font_instance_key: FontInstanceKey,
451 font_key: FontKey,
452 size: f32,
453 flags: FontInstanceFlags,
454 variations: Vec<FontVariation>,
455 ) {
456 let _x = self.0.send(PaintMessage::AddFontInstance(
457 font_key.into(),
458 font_instance_key,
459 font_key,
460 size,
461 flags,
462 variations,
463 ));
464 }
465
466 pub fn add_font(&self, font_key: FontKey, data: Arc<GenericSharedMemory>, index: u32) {
467 let _ = self.0.send(PaintMessage::AddFont(
468 font_key.into(),
469 font_key,
470 data,
471 index,
472 ));
473 }
474
475 pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) {
476 let _ = self.0.send(PaintMessage::AddSystemFont(
477 font_key.into(),
478 font_key,
479 handle,
480 ));
481 }
482
483 pub fn fetch_font_keys(
484 &self,
485 number_of_font_keys: usize,
486 number_of_font_instance_keys: usize,
487 painter_id: PainterId,
488 ) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
489 let (sender, receiver) = generic_channel::channel().expect("Could not create IPC channel");
490 let _ = self.0.send(PaintMessage::GenerateFontKeys(
491 number_of_font_keys,
492 number_of_font_instance_keys,
493 sender,
494 painter_id,
495 ));
496 receiver.recv().unwrap()
497 }
498
499 pub fn viewport(&self, webview_id: WebViewId, description: ViewportDescription) {
500 let _ = self.0.send(PaintMessage::Viewport(webview_id, description));
501 }
502
503 pub fn pipeline_exited(
504 &self,
505 webview_id: WebViewId,
506 pipeline_id: PipelineId,
507 source: PipelineExitSource,
508 ) {
509 let _ = self.0.send(PaintMessage::PipelineExited(
510 webview_id,
511 pipeline_id,
512 source,
513 ));
514 }
515}
516
517#[derive(Clone)]
518pub struct PainterSurfmanDetails {
519 pub connection: Connection,
520 pub adapter: Adapter,
521}
522
523#[derive(Clone, Default)]
524pub struct PainterSurfmanDetailsMap(Arc<Mutex<HashMap<PainterId, PainterSurfmanDetails>>>);
525
526impl PainterSurfmanDetailsMap {
527 pub fn get(&self, painter_id: PainterId) -> Option<PainterSurfmanDetails> {
528 let map = self.0.lock().expect("poisoned");
529 map.get(&painter_id).cloned()
530 }
531
532 pub fn insert(&self, painter_id: PainterId, details: PainterSurfmanDetails) {
533 let mut map = self.0.lock().expect("poisoned");
534 let existing = map.insert(painter_id, details);
535 assert!(existing.is_none())
536 }
537
538 pub fn remove(&self, painter_id: PainterId) {
539 let mut map = self.0.lock().expect("poisoned");
540 map.remove(&painter_id);
541 }
542}
543
544pub trait WebRenderExternalImageApi {
551 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
552 fn unlock(&mut self, id: u64);
553}
554
555#[derive(Clone, Copy)]
557pub enum WebRenderImageHandlerType {
558 WebGl,
559 Media,
560 WebGpu,
561}
562
563#[derive(Default)]
567struct WebRenderExternalImageIdManagerInner {
568 external_images: FxHashMap<ExternalImageId, WebRenderImageHandlerType>,
570 next_image_id: u64,
572}
573
574#[derive(Default, Clone)]
575pub struct WebRenderExternalImageIdManager(Arc<RwLock<WebRenderExternalImageIdManagerInner>>);
576
577impl WebRenderExternalImageIdManager {
578 pub fn next_id(&mut self, handler_type: WebRenderImageHandlerType) -> ExternalImageId {
579 let mut inner = self.0.write();
580 inner.next_image_id += 1;
581 let key = ExternalImageId(inner.next_image_id);
582 inner.external_images.insert(key, handler_type);
583 key
584 }
585
586 pub fn remove(&mut self, key: &ExternalImageId) {
587 self.0.write().external_images.remove(key);
588 }
589
590 pub fn get(&self, key: &ExternalImageId) -> Option<WebRenderImageHandlerType> {
591 self.0.read().external_images.get(key).cloned()
592 }
593}
594
595pub struct WebRenderExternalImageHandlers {
597 webgl_handler: Option<Box<dyn WebRenderExternalImageApi>>,
599 media_handler: Option<Box<dyn WebRenderExternalImageApi>>,
601 webgpu_handler: Option<Box<dyn WebRenderExternalImageApi>>,
603 id_manager: WebRenderExternalImageIdManager,
607}
608
609impl WebRenderExternalImageHandlers {
610 pub fn new(id_manager: WebRenderExternalImageIdManager) -> Self {
611 Self {
612 webgl_handler: Default::default(),
613 media_handler: Default::default(),
614 webgpu_handler: Default::default(),
615 id_manager,
616 }
617 }
618
619 pub fn id_manager(&self) -> WebRenderExternalImageIdManager {
620 self.id_manager.clone()
621 }
622
623 pub fn set_handler(
624 &mut self,
625 handler: Box<dyn WebRenderExternalImageApi>,
626 handler_type: WebRenderImageHandlerType,
627 ) {
628 match handler_type {
629 WebRenderImageHandlerType::WebGl => self.webgl_handler = Some(handler),
630 WebRenderImageHandlerType::Media => self.media_handler = Some(handler),
631 WebRenderImageHandlerType::WebGpu => self.webgpu_handler = Some(handler),
632 }
633 }
634}
635
636impl ExternalImageHandler for WebRenderExternalImageHandlers {
637 fn lock(
642 &mut self,
643 key: ExternalImageId,
644 _channel_index: u8,
645 _is_composited: bool,
646 ) -> ExternalImage<'_> {
647 let handler_type = self
648 .id_manager()
649 .get(&key)
650 .expect("Tried to get unknown external image");
651 match handler_type {
652 WebRenderImageHandlerType::WebGl => {
653 let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0);
654 let texture_id = match source {
655 ExternalImageSource::NativeTexture(b) => b,
656 _ => panic!("Wrong type"),
657 };
658 ExternalImage {
659 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
660 source: ExternalImageSource::NativeTexture(texture_id),
661 }
662 },
663 WebRenderImageHandlerType::Media => {
664 let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0);
665 let texture_id = match source {
666 ExternalImageSource::NativeTexture(b) => b,
667 _ => panic!("Wrong type"),
668 };
669 ExternalImage {
670 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
671 source: ExternalImageSource::NativeTexture(texture_id),
672 }
673 },
674 WebRenderImageHandlerType::WebGpu => {
675 let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
676 ExternalImage {
677 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
678 source,
679 }
680 },
681 }
682 }
683
684 fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) {
687 let handler_type = self
688 .id_manager()
689 .get(&key)
690 .expect("Tried to get unknown external image");
691 match handler_type {
692 WebRenderImageHandlerType::WebGl => self.webgl_handler.as_mut().unwrap().unlock(key.0),
693 WebRenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0),
694 WebRenderImageHandlerType::WebGpu => {
695 self.webgpu_handler.as_mut().unwrap().unlock(key.0)
696 },
697 };
698 }
699}
700
701#[derive(Deserialize, Serialize)]
702pub enum ImageUpdate {
704 AddImage(
706 ImageKey,
707 ImageDescriptor,
708 SerializableImageData,
709 bool, ),
711 DeleteImage(ImageKey),
713 UpdateImage(
715 ImageKey,
716 ImageDescriptor,
717 SerializableImageData,
718 Option<Epoch>,
719 ),
720 UpdateImageForAnimation(ImageKey, ImageDescriptor),
723}
724
725impl Debug for ImageUpdate {
726 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
727 match self {
728 Self::AddImage(image_key, image_desc, _, is_animated_image) => f
729 .debug_tuple("AddImage")
730 .field(image_key)
731 .field(image_desc)
732 .field(is_animated_image)
733 .finish(),
734 Self::DeleteImage(image_key) => f.debug_tuple("DeleteImage").field(image_key).finish(),
735 Self::UpdateImage(image_key, image_desc, _, epoch) => f
736 .debug_tuple("UpdateImage")
737 .field(image_key)
738 .field(image_desc)
739 .field(epoch)
740 .finish(),
741 Self::UpdateImageForAnimation(image_key, image_desc) => f
742 .debug_tuple("UpdateAnimation")
743 .field(image_key)
744 .field(image_desc)
745 .finish(),
746 }
747 }
748}
749
750#[derive(Debug, Deserialize, Serialize)]
751pub enum SerializableImageData {
753 Raw(GenericSharedMemory),
756 External(ExternalImageData),
759}
760
761impl From<SerializableImageData> for ImageData {
762 fn from(value: SerializableImageData) -> Self {
763 match value {
764 SerializableImageData::Raw(shared_memory) => {
765 ImageData::Raw(shared_memory.into_arc_vec())
766 },
767 SerializableImageData::External(image) => ImageData::External(image),
768 }
769 }
770}
771
772pub trait WebViewTrait {
776 fn id(&self) -> WebViewId;
777 fn screen_geometry(&self) -> Option<ScreenGeometry>;
778 fn set_animating(&self, new_value: bool);
779 fn notify_viewport_updated(&self);
783}
784
785#[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
788pub struct PipelineExitSource(u8);
789
790bitflags! {
791 impl PipelineExitSource: u8 {
792 const Script = 1 << 0;
793 const Constellation = 1 << 1;
794 }
795}
796
797#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)]
801pub struct PinchZoomInfos {
802 pub zoom_factor: Scale<f32, DevicePixel, DevicePixel>,
804
805 pub rect: Rect<f32, CSSPixel>,
807}
808
809impl PinchZoomInfos {
810 pub fn new_from_viewport_size(size: Size2D<f32, CSSPixel>) -> Self {
813 Self {
814 zoom_factor: Scale::identity(),
815 rect: Rect::from_size(size),
816 }
817 }
818}