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