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 log::warn;
15use malloc_size_of_derive::MallocSizeOf;
16use parking_lot::RwLock;
17use rustc_hash::FxHashMap;
18use smallvec::SmallVec;
19use strum::IntoStaticStr;
20use surfman::{Adapter, Connection};
21use webrender_api::{DocumentId, FontVariation};
22
23pub mod display_list;
24pub mod largest_contentful_paint_candidate;
25pub mod rendering_context;
26pub mod viewport_description;
27
28use std::sync::{Arc, Mutex};
29
30use base::generic_channel::{self, GenericCallback, GenericSender, GenericSharedMemory};
31use bitflags::bitflags;
32use display_list::PaintDisplayListInfo;
33use embedder_traits::ScreenGeometry;
34use euclid::default::Size2D as UntypedSize2D;
35use ipc_channel::ipc::{self};
36use profile_traits::mem::{OpaqueSender, ReportsChan};
37use serde::{Deserialize, Serialize};
38pub use webrender_api::ExternalImageSource;
39use webrender_api::units::{LayoutVector2D, TexelRect};
40use webrender_api::{
41 BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData,
42 ExternalImageHandler, ExternalImageId, ExternalScrollId, FontInstanceFlags, FontInstanceKey,
43 FontKey, ImageData, ImageDescriptor, ImageKey, NativeFontHandle,
44 PipelineId as WebRenderPipelineId,
45};
46
47use crate::largest_contentful_paint_candidate::LCPCandidate;
48use crate::viewport_description::ViewportDescription;
49
50#[derive(Clone)]
52pub struct PaintProxy {
53 pub sender: Sender<Result<PaintMessage, ipc_channel::Error>>,
54 pub cross_process_paint_api: CrossProcessPaintApi,
58 pub event_loop_waker: Box<dyn EventLoopWaker>,
59}
60
61impl OpaqueSender<PaintMessage> for PaintProxy {
62 fn send(&self, message: PaintMessage) {
63 PaintProxy::send(self, message)
64 }
65}
66
67impl PaintProxy {
68 pub fn send(&self, msg: PaintMessage) {
69 self.route_msg(Ok(msg))
70 }
71
72 pub fn route_msg(&self, msg: Result<PaintMessage, ipc_channel::Error>) {
77 if let Err(err) = self.sender.send(msg) {
78 warn!("Failed to send response ({:?}).", err);
79 }
80 self.event_loop_waker.wake();
81 }
82}
83
84#[derive(Deserialize, IntoStaticStr, Serialize)]
86pub enum PaintMessage {
87 ChangeRunningAnimationsState(WebViewId, PipelineId, AnimationState),
89 SetFrameTreeForWebView(WebViewId, SendableFrameTree),
91 SetThrottled(WebViewId, PipelineId, bool),
93 NewWebRenderFrameReady(PainterId, DocumentId, bool),
97 PipelineExited(WebViewId, PipelineId, PipelineExitSource),
102 SendInitialTransaction(WebViewId, WebRenderPipelineId),
104 ScrollNodeByDelta(
108 WebViewId,
109 WebRenderPipelineId,
110 LayoutVector2D,
111 ExternalScrollId,
112 ),
113 ScrollViewportByDelta(WebViewId, LayoutVector2D),
117 UpdateEpoch {
119 webview_id: WebViewId,
121 pipeline_id: PipelineId,
123 epoch: Epoch,
125 },
126 SendDisplayList {
128 webview_id: WebViewId,
130 display_list_descriptor: BuiltDisplayListDescriptor,
132 display_list_receiver: ipc::IpcBytesReceiver,
134 },
135 GenerateFrame(Vec<PainterId>),
138 GenerateImageKey(WebViewId, GenericSender<ImageKey>),
141 GenerateImageKeysForPipeline(WebViewId, PipelineId),
144 UpdateImages(PainterId, SmallVec<[ImageUpdate; 1]>),
146 DelayNewFrameForCanvas(WebViewId, PipelineId, Epoch, Vec<ImageKey>),
151
152 GenerateFontKeys(
155 usize,
156 usize,
157 GenericSender<(Vec<FontKey>, Vec<FontInstanceKey>)>,
158 PainterId,
159 ),
160 AddFont(PainterId, FontKey, Arc<GenericSharedMemory>, u32),
162 AddSystemFont(PainterId, FontKey, NativeFontHandle),
164 AddFontInstance(
166 PainterId,
167 FontInstanceKey,
168 FontKey,
169 f32,
170 FontInstanceFlags,
171 Vec<FontVariation>,
172 ),
173 RemoveFonts(PainterId, Vec<FontKey>, Vec<FontInstanceKey>),
175 CollectMemoryReport(ReportsChan),
178 Viewport(WebViewId, ViewportDescription),
180 ScreenshotReadinessReponse(WebViewId, FxHashMap<PipelineId, Epoch>),
183 SendLCPCandidate(LCPCandidate, WebViewId, PipelineId, Epoch),
185}
186
187impl Debug for PaintMessage {
188 fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
189 let string: &'static str = self.into();
190 write!(formatter, "{string}")
191 }
192}
193
194#[derive(Deserialize, Serialize)]
195pub struct SendableFrameTree {
196 pub pipeline: CompositionPipeline,
197 pub children: Vec<SendableFrameTree>,
198}
199
200#[derive(Clone, Deserialize, Serialize)]
202pub struct CompositionPipeline {
203 pub id: PipelineId,
204 pub webview_id: WebViewId,
205}
206
207#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
209pub struct CrossProcessPaintApi(GenericCallback<PaintMessage>);
210
211impl CrossProcessPaintApi {
212 pub fn new(callback: GenericCallback<PaintMessage>) -> Self {
214 CrossProcessPaintApi(callback)
215 }
216
217 pub fn dummy() -> Self {
220 Self::dummy_with_callback(None)
221 }
222
223 pub fn dummy_with_callback(
226 callback: Option<Box<dyn Fn(PaintMessage) + Send + 'static>>,
227 ) -> Self {
228 let callback = GenericCallback::new(move |msg| {
229 if let Some(ref handler) = callback {
230 if let Ok(paint_message) = msg {
231 handler(paint_message);
232 }
233 }
234 })
235 .unwrap();
236 Self(callback)
237 }
238
239 pub fn send_initial_transaction(&self, webview_id: WebViewId, pipeline: WebRenderPipelineId) {
241 if let Err(e) = self
242 .0
243 .send(PaintMessage::SendInitialTransaction(webview_id, pipeline))
244 {
245 warn!("Error sending initial transaction: {}", e);
246 }
247 }
248
249 pub fn scroll_node_by_delta(
253 &self,
254 webview_id: WebViewId,
255 pipeline_id: WebRenderPipelineId,
256 delta: LayoutVector2D,
257 scroll_id: ExternalScrollId,
258 ) {
259 if let Err(error) = self.0.send(PaintMessage::ScrollNodeByDelta(
260 webview_id,
261 pipeline_id,
262 delta,
263 scroll_id,
264 )) {
265 warn!("Error scrolling node: {error}");
266 }
267 }
268
269 pub fn scroll_viewport_by_delta(&self, webview_id: WebViewId, delta: LayoutVector2D) {
276 if let Err(error) = self
277 .0
278 .send(PaintMessage::ScrollViewportByDelta(webview_id, delta))
279 {
280 warn!("Error scroll viewport: {error}");
281 }
282 }
283
284 pub fn delay_new_frame_for_canvas(
285 &self,
286 webview_id: WebViewId,
287 pipeline_id: PipelineId,
288 canvas_epoch: Epoch,
289 image_keys: Vec<ImageKey>,
290 ) {
291 if let Err(error) = self.0.send(PaintMessage::DelayNewFrameForCanvas(
292 webview_id,
293 pipeline_id,
294 canvas_epoch,
295 image_keys,
296 )) {
297 warn!("Error delaying frames for canvas image updates {error:?}");
298 }
299 }
300
301 pub fn update_epoch(&self, webview_id: WebViewId, pipeline_id: PipelineId, epoch: Epoch) {
304 if let Err(error) = self.0.send(PaintMessage::UpdateEpoch {
305 webview_id,
306 pipeline_id,
307 epoch,
308 }) {
309 warn!("Error updating epoch for pipeline: {error:?}");
310 }
311 }
312
313 pub fn send_display_list(
315 &self,
316 webview_id: WebViewId,
317 display_list_info: &PaintDisplayListInfo,
318 list: BuiltDisplayList,
319 ) {
320 let (display_list_data, display_list_descriptor) = list.into_data();
321 let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap();
322 if let Err(e) = self.0.send(PaintMessage::SendDisplayList {
323 webview_id,
324 display_list_descriptor,
325 display_list_receiver,
326 }) {
327 warn!("Error sending display list: {}", e);
328 }
329
330 let display_list_info_serialized =
331 bincode::serialize(&display_list_info).unwrap_or_default();
332 if let Err(error) = display_list_sender.send(&display_list_info_serialized) {
333 warn!("Error sending display list info: {error}");
334 }
335
336 if let Err(error) = display_list_sender.send(&display_list_data.items_data) {
337 warn!("Error sending display list items: {error}");
338 }
339 if let Err(error) = display_list_sender.send(&display_list_data.cache_data) {
340 warn!("Error sending display list cache data: {error}");
341 }
342 if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) {
343 warn!("Error sending display spatial tree: {error}");
344 }
345 }
346
347 pub fn send_lcp_candidate(
349 &self,
350 lcp_candidate: LCPCandidate,
351 webview_id: WebViewId,
352 pipeline_id: PipelineId,
353 epoch: Epoch,
354 ) {
355 if let Err(error) = self.0.send(PaintMessage::SendLCPCandidate(
356 lcp_candidate,
357 webview_id,
358 pipeline_id,
359 epoch,
360 )) {
361 warn!("Error sending LCPCandidate: {error}");
362 }
363 }
364
365 pub fn generate_frame(&self, painter_ids: Vec<PainterId>) {
367 if let Err(error) = self.0.send(PaintMessage::GenerateFrame(painter_ids)) {
368 warn!("Error generating frame: {error}");
369 }
370 }
371
372 pub fn generate_image_key_blocking(&self, webview_id: WebViewId) -> Option<ImageKey> {
374 let (sender, receiver) = generic_channel::channel().unwrap();
375 self.0
376 .send(PaintMessage::GenerateImageKey(webview_id, sender))
377 .ok()?;
378 receiver.recv().ok()
379 }
380
381 pub fn generate_image_key_async(&self, webview_id: WebViewId, pipeline_id: PipelineId) {
385 if let Err(e) = self.0.send(PaintMessage::GenerateImageKeysForPipeline(
386 webview_id,
387 pipeline_id,
388 )) {
389 warn!("Could not send image keys to Paint {}", e);
390 }
391 }
392
393 pub fn add_image(
394 &self,
395 key: ImageKey,
396 descriptor: ImageDescriptor,
397 data: SerializableImageData,
398 ) {
399 self.update_images(
400 key.into(),
401 [ImageUpdate::AddImage(key, descriptor, data)].into(),
402 );
403 }
404
405 pub fn update_image(
406 &self,
407 key: ImageKey,
408 descriptor: ImageDescriptor,
409 data: SerializableImageData,
410 epoch: Option<Epoch>,
411 ) {
412 self.update_images(
413 key.into(),
414 [ImageUpdate::UpdateImage(key, descriptor, data, epoch)].into(),
415 );
416 }
417
418 pub fn delete_image(&self, key: ImageKey) {
419 self.update_images(key.into(), [ImageUpdate::DeleteImage(key)].into());
420 }
421
422 pub fn update_images(&self, painter_id: PainterId, updates: SmallVec<[ImageUpdate; 1]>) {
424 if let Err(e) = self.0.send(PaintMessage::UpdateImages(painter_id, updates)) {
425 warn!("error sending image updates: {}", e);
426 }
427 }
428
429 pub fn remove_unused_font_resources(
430 &self,
431 painter_id: PainterId,
432 keys: Vec<FontKey>,
433 instance_keys: Vec<FontInstanceKey>,
434 ) {
435 if keys.is_empty() && instance_keys.is_empty() {
436 return;
437 }
438 let _ = self
439 .0
440 .send(PaintMessage::RemoveFonts(painter_id, keys, instance_keys));
441 }
442
443 pub fn add_font_instance(
444 &self,
445 font_instance_key: FontInstanceKey,
446 font_key: FontKey,
447 size: f32,
448 flags: FontInstanceFlags,
449 variations: Vec<FontVariation>,
450 ) {
451 let _x = self.0.send(PaintMessage::AddFontInstance(
452 font_key.into(),
453 font_instance_key,
454 font_key,
455 size,
456 flags,
457 variations,
458 ));
459 }
460
461 pub fn add_font(&self, font_key: FontKey, data: Arc<GenericSharedMemory>, index: u32) {
462 let _ = self.0.send(PaintMessage::AddFont(
463 font_key.into(),
464 font_key,
465 data,
466 index,
467 ));
468 }
469
470 pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) {
471 let _ = self.0.send(PaintMessage::AddSystemFont(
472 font_key.into(),
473 font_key,
474 handle,
475 ));
476 }
477
478 pub fn fetch_font_keys(
479 &self,
480 number_of_font_keys: usize,
481 number_of_font_instance_keys: usize,
482 painter_id: PainterId,
483 ) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
484 let (sender, receiver) = generic_channel::channel().expect("Could not create IPC channel");
485 let _ = self.0.send(PaintMessage::GenerateFontKeys(
486 number_of_font_keys,
487 number_of_font_instance_keys,
488 sender,
489 painter_id,
490 ));
491 receiver.recv().unwrap()
492 }
493
494 pub fn viewport(&self, webview_id: WebViewId, description: ViewportDescription) {
495 let _ = self.0.send(PaintMessage::Viewport(webview_id, description));
496 }
497
498 pub fn pipeline_exited(
499 &self,
500 webview_id: WebViewId,
501 pipeline_id: PipelineId,
502 source: PipelineExitSource,
503 ) {
504 let _ = self.0.send(PaintMessage::PipelineExited(
505 webview_id,
506 pipeline_id,
507 source,
508 ));
509 }
510}
511
512#[derive(Clone)]
513pub struct PainterSurfmanDetails {
514 pub connection: Connection,
515 pub adapter: Adapter,
516}
517
518#[derive(Clone, Default)]
519pub struct PainterSurfmanDetailsMap(Arc<Mutex<HashMap<PainterId, PainterSurfmanDetails>>>);
520
521impl PainterSurfmanDetailsMap {
522 pub fn get(&self, painter_id: PainterId) -> Option<PainterSurfmanDetails> {
523 let map = self.0.lock().expect("poisoned");
524 map.get(&painter_id).cloned()
525 }
526
527 pub fn insert(&self, painter_id: PainterId, details: PainterSurfmanDetails) {
528 let mut map = self.0.lock().expect("poisoned");
529 let existing = map.insert(painter_id, details);
530 assert!(existing.is_none())
531 }
532
533 pub fn remove(&self, painter_id: PainterId) {
534 let mut map = self.0.lock().expect("poisoned");
535 let details = map.remove(&painter_id);
536 assert!(details.is_some());
537 }
538}
539
540pub trait WebRenderExternalImageApi {
547 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
548 fn unlock(&mut self, id: u64);
549}
550
551#[derive(Clone, Copy)]
553pub enum WebRenderImageHandlerType {
554 WebGl,
555 Media,
556 WebGpu,
557}
558
559#[derive(Default)]
563struct WebRenderExternalImageIdManagerInner {
564 external_images: FxHashMap<ExternalImageId, WebRenderImageHandlerType>,
566 next_image_id: u64,
568}
569
570#[derive(Default, Clone)]
571pub struct WebRenderExternalImageIdManager(Arc<RwLock<WebRenderExternalImageIdManagerInner>>);
572
573impl WebRenderExternalImageIdManager {
574 pub fn next_id(&mut self, handler_type: WebRenderImageHandlerType) -> ExternalImageId {
575 let mut inner = self.0.write();
576 inner.next_image_id += 1;
577 let key = ExternalImageId(inner.next_image_id);
578 inner.external_images.insert(key, handler_type);
579 key
580 }
581
582 pub fn remove(&mut self, key: &ExternalImageId) {
583 self.0.write().external_images.remove(key);
584 }
585
586 pub fn get(&self, key: &ExternalImageId) -> Option<WebRenderImageHandlerType> {
587 self.0.read().external_images.get(key).cloned()
588 }
589}
590
591pub struct WebRenderExternalImageHandlers {
593 webgl_handler: Option<Box<dyn WebRenderExternalImageApi>>,
595 media_handler: Option<Box<dyn WebRenderExternalImageApi>>,
597 webgpu_handler: Option<Box<dyn WebRenderExternalImageApi>>,
599 id_manager: WebRenderExternalImageIdManager,
603}
604
605impl WebRenderExternalImageHandlers {
606 pub fn new(id_manager: WebRenderExternalImageIdManager) -> Self {
607 Self {
608 webgl_handler: Default::default(),
609 media_handler: Default::default(),
610 webgpu_handler: Default::default(),
611 id_manager,
612 }
613 }
614
615 pub fn id_manager(&self) -> WebRenderExternalImageIdManager {
616 self.id_manager.clone()
617 }
618
619 pub fn set_handler(
620 &mut self,
621 handler: Box<dyn WebRenderExternalImageApi>,
622 handler_type: WebRenderImageHandlerType,
623 ) {
624 match handler_type {
625 WebRenderImageHandlerType::WebGl => self.webgl_handler = Some(handler),
626 WebRenderImageHandlerType::Media => self.media_handler = Some(handler),
627 WebRenderImageHandlerType::WebGpu => self.webgpu_handler = Some(handler),
628 }
629 }
630}
631
632impl ExternalImageHandler for WebRenderExternalImageHandlers {
633 fn lock(
638 &mut self,
639 key: ExternalImageId,
640 _channel_index: u8,
641 _is_composited: bool,
642 ) -> ExternalImage<'_> {
643 let handler_type = self
644 .id_manager()
645 .get(&key)
646 .expect("Tried to get unknown external image");
647 match handler_type {
648 WebRenderImageHandlerType::WebGl => {
649 let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0);
650 let texture_id = match source {
651 ExternalImageSource::NativeTexture(b) => b,
652 _ => panic!("Wrong type"),
653 };
654 ExternalImage {
655 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
656 source: ExternalImageSource::NativeTexture(texture_id),
657 }
658 },
659 WebRenderImageHandlerType::Media => {
660 let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0);
661 let texture_id = match source {
662 ExternalImageSource::NativeTexture(b) => b,
663 _ => panic!("Wrong type"),
664 };
665 ExternalImage {
666 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
667 source: ExternalImageSource::NativeTexture(texture_id),
668 }
669 },
670 WebRenderImageHandlerType::WebGpu => {
671 let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
672 ExternalImage {
673 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
674 source,
675 }
676 },
677 }
678 }
679
680 fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) {
683 let handler_type = self
684 .id_manager()
685 .get(&key)
686 .expect("Tried to get unknown external image");
687 match handler_type {
688 WebRenderImageHandlerType::WebGl => self.webgl_handler.as_mut().unwrap().unlock(key.0),
689 WebRenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0),
690 WebRenderImageHandlerType::WebGpu => {
691 self.webgpu_handler.as_mut().unwrap().unlock(key.0)
692 },
693 };
694 }
695}
696
697#[derive(Deserialize, Serialize)]
698pub enum ImageUpdate {
700 AddImage(ImageKey, ImageDescriptor, SerializableImageData),
702 DeleteImage(ImageKey),
704 UpdateImage(
706 ImageKey,
707 ImageDescriptor,
708 SerializableImageData,
709 Option<Epoch>,
710 ),
711}
712
713impl Debug for ImageUpdate {
714 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
715 match self {
716 Self::AddImage(image_key, image_desc, _) => f
717 .debug_tuple("AddImage")
718 .field(image_key)
719 .field(image_desc)
720 .finish(),
721 Self::DeleteImage(image_key) => f.debug_tuple("DeleteImage").field(image_key).finish(),
722 Self::UpdateImage(image_key, image_desc, _, epoch) => f
723 .debug_tuple("UpdateImage")
724 .field(image_key)
725 .field(image_desc)
726 .field(epoch)
727 .finish(),
728 }
729 }
730}
731
732#[derive(Debug, Deserialize, Serialize)]
733pub enum SerializableImageData {
736 Raw(GenericSharedMemory),
739 External(ExternalImageData),
742}
743
744impl From<SerializableImageData> for ImageData {
745 fn from(value: SerializableImageData) -> Self {
746 match value {
747 SerializableImageData::Raw(shared_memory) => ImageData::new(shared_memory.to_vec()),
748 SerializableImageData::External(image) => ImageData::External(image),
749 }
750 }
751}
752
753pub trait WebViewTrait {
757 fn id(&self) -> WebViewId;
758 fn screen_geometry(&self) -> Option<ScreenGeometry>;
759 fn set_animating(&self, new_value: bool);
760}
761
762#[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
765pub struct PipelineExitSource(u8);
766
767bitflags! {
768 impl PipelineExitSource: u8 {
769 const Script = 1 << 0;
770 const Constellation = 1 << 1;
771 }
772}