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};
31use bitflags::bitflags;
32use display_list::CompositorDisplayListInfo;
33use embedder_traits::ScreenGeometry;
34use euclid::default::Size2D as UntypedSize2D;
35use ipc_channel::ipc::{self, IpcSharedMemory};
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 CompositorProxy {
53 pub sender: Sender<Result<CompositorMsg, ipc_channel::Error>>,
54 pub cross_process_compositor_api: CrossProcessCompositorApi,
58 pub event_loop_waker: Box<dyn EventLoopWaker>,
59}
60
61impl OpaqueSender<CompositorMsg> for CompositorProxy {
62 fn send(&self, message: CompositorMsg) {
63 CompositorProxy::send(self, message)
64 }
65}
66
67impl CompositorProxy {
68 pub fn send(&self, msg: CompositorMsg) {
69 self.route_msg(Ok(msg))
70 }
71
72 pub fn route_msg(&self, msg: Result<CompositorMsg, 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 CompositorMsg {
87 ChangeRunningAnimationsState(WebViewId, PipelineId, AnimationState),
89 SetFrameTreeForWebView(WebViewId, SendableFrameTree),
91 RemoveWebView(WebViewId),
93 SetThrottled(WebViewId, PipelineId, bool),
95 NewWebRenderFrameReady(PainterId, DocumentId, bool),
99 PipelineExited(WebViewId, PipelineId, PipelineExitSource),
104 SendInitialTransaction(WebViewId, WebRenderPipelineId),
106 ScrollNodeByDelta(
110 WebViewId,
111 WebRenderPipelineId,
112 LayoutVector2D,
113 ExternalScrollId,
114 ),
115 ScrollViewportByDelta(WebViewId, LayoutVector2D),
119 UpdateEpoch {
121 webview_id: WebViewId,
123 pipeline_id: PipelineId,
125 epoch: Epoch,
127 },
128 SendDisplayList {
130 webview_id: WebViewId,
132 display_list_descriptor: BuiltDisplayListDescriptor,
134 display_list_receiver: ipc::IpcBytesReceiver,
136 },
137 GenerateFrame(Vec<PainterId>),
140 GenerateImageKey(WebViewId, GenericSender<ImageKey>),
143 GenerateImageKeysForPipeline(WebViewId, PipelineId),
146 UpdateImages(PainterId, SmallVec<[ImageUpdate; 1]>),
148 DelayNewFrameForCanvas(WebViewId, PipelineId, Epoch, Vec<ImageKey>),
153
154 GenerateFontKeys(
157 usize,
158 usize,
159 GenericSender<(Vec<FontKey>, Vec<FontInstanceKey>)>,
160 PainterId,
161 ),
162 AddFont(PainterId, FontKey, Arc<IpcSharedMemory>, u32),
164 AddSystemFont(PainterId, FontKey, NativeFontHandle),
166 AddFontInstance(
168 PainterId,
169 FontInstanceKey,
170 FontKey,
171 f32,
172 FontInstanceFlags,
173 Vec<FontVariation>,
174 ),
175 RemoveFonts(PainterId, Vec<FontKey>, Vec<FontInstanceKey>),
177 CollectMemoryReport(ReportsChan),
180 Viewport(WebViewId, ViewportDescription),
182 ScreenshotReadinessReponse(WebViewId, FxHashMap<PipelineId, Epoch>),
185 SendLCPCandidate(LCPCandidate, WebViewId, PipelineId, Epoch),
187}
188
189impl Debug for CompositorMsg {
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(Clone, Deserialize, MallocSizeOf, Serialize)]
211pub struct CrossProcessCompositorApi(GenericCallback<CompositorMsg>);
212
213impl CrossProcessCompositorApi {
214 pub fn new(callback: GenericCallback<CompositorMsg>) -> Self {
216 CrossProcessCompositorApi(callback)
217 }
218
219 pub fn dummy() -> Self {
222 Self::dummy_with_callback(None)
223 }
224
225 pub fn dummy_with_callback(
228 callback: Option<Box<dyn Fn(CompositorMsg) + Send + 'static>>,
229 ) -> Self {
230 let callback = GenericCallback::new(move |msg| {
231 if let Some(ref handler) = callback {
232 if let Ok(compositor_msg) = msg {
233 handler(compositor_msg);
234 }
235 }
236 })
237 .unwrap();
238 Self(callback)
239 }
240
241 pub fn send_initial_transaction(&self, webview_id: WebViewId, pipeline: WebRenderPipelineId) {
243 if let Err(e) = self
244 .0
245 .send(CompositorMsg::SendInitialTransaction(webview_id, pipeline))
246 {
247 warn!("Error sending initial transaction: {}", e);
248 }
249 }
250
251 pub fn scroll_node_by_delta(
255 &self,
256 webview_id: WebViewId,
257 pipeline_id: WebRenderPipelineId,
258 delta: LayoutVector2D,
259 scroll_id: ExternalScrollId,
260 ) {
261 if let Err(error) = self.0.send(CompositorMsg::ScrollNodeByDelta(
262 webview_id,
263 pipeline_id,
264 delta,
265 scroll_id,
266 )) {
267 warn!("Error scrolling node: {error}");
268 }
269 }
270
271 pub fn scroll_viewport_by_delta(&self, webview_id: WebViewId, delta: LayoutVector2D) {
278 if let Err(error) = self
279 .0
280 .send(CompositorMsg::ScrollViewportByDelta(webview_id, delta))
281 {
282 warn!("Error scroll viewport: {error}");
283 }
284 }
285
286 pub fn delay_new_frame_for_canvas(
287 &self,
288 webview_id: WebViewId,
289 pipeline_id: PipelineId,
290 canvas_epoch: Epoch,
291 image_keys: Vec<ImageKey>,
292 ) {
293 if let Err(error) = self.0.send(CompositorMsg::DelayNewFrameForCanvas(
294 webview_id,
295 pipeline_id,
296 canvas_epoch,
297 image_keys,
298 )) {
299 warn!("Error delaying frames for canvas image updates {error:?}");
300 }
301 }
302
303 pub fn update_epoch(&self, webview_id: WebViewId, pipeline_id: PipelineId, epoch: Epoch) {
306 if let Err(error) = self.0.send(CompositorMsg::UpdateEpoch {
307 webview_id,
308 pipeline_id,
309 epoch,
310 }) {
311 warn!("Error updating epoch for pipeline: {error:?}");
312 }
313 }
314
315 pub fn send_display_list(
317 &self,
318 webview_id: WebViewId,
319 display_list_info: &CompositorDisplayListInfo,
320 list: BuiltDisplayList,
321 ) {
322 let (display_list_data, display_list_descriptor) = list.into_data();
323 let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap();
324 if let Err(e) = self.0.send(CompositorMsg::SendDisplayList {
325 webview_id,
326 display_list_descriptor,
327 display_list_receiver,
328 }) {
329 warn!("Error sending display list: {}", e);
330 }
331
332 let display_list_info_serialized =
333 bincode::serialize(&display_list_info).unwrap_or_default();
334 if let Err(error) = display_list_sender.send(&display_list_info_serialized) {
335 warn!("Error sending display list info: {error}");
336 }
337
338 if let Err(error) = display_list_sender.send(&display_list_data.items_data) {
339 warn!("Error sending display list items: {error}");
340 }
341 if let Err(error) = display_list_sender.send(&display_list_data.cache_data) {
342 warn!("Error sending display list cache data: {error}");
343 }
344 if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) {
345 warn!("Error sending display spatial tree: {error}");
346 }
347 }
348
349 pub fn send_lcp_candidate(
351 &self,
352 lcp_candidate: LCPCandidate,
353 webview_id: WebViewId,
354 pipeline_id: PipelineId,
355 epoch: Epoch,
356 ) {
357 if let Err(error) = self.0.send(CompositorMsg::SendLCPCandidate(
358 lcp_candidate,
359 webview_id,
360 pipeline_id,
361 epoch,
362 )) {
363 warn!("Error sending LCPCandidate: {error}");
364 }
365 }
366
367 pub fn generate_frame(&self, painter_ids: Vec<PainterId>) {
369 if let Err(error) = self.0.send(CompositorMsg::GenerateFrame(painter_ids)) {
370 warn!("Error generating frame: {error}");
371 }
372 }
373
374 pub fn generate_image_key_blocking(&self, webview_id: WebViewId) -> Option<ImageKey> {
376 let (sender, receiver) = generic_channel::channel().unwrap();
377 self.0
378 .send(CompositorMsg::GenerateImageKey(webview_id, sender))
379 .ok()?;
380 receiver.recv().ok()
381 }
382
383 pub fn generate_image_key_async(&self, webview_id: WebViewId, pipeline_id: PipelineId) {
387 if let Err(e) = self.0.send(CompositorMsg::GenerateImageKeysForPipeline(
388 webview_id,
389 pipeline_id,
390 )) {
391 warn!("Could not send image keys to Compositor {}", e);
392 }
393 }
394
395 pub fn add_image(
396 &self,
397 key: ImageKey,
398 descriptor: ImageDescriptor,
399 data: SerializableImageData,
400 ) {
401 self.update_images(
402 key.into(),
403 [ImageUpdate::AddImage(key, descriptor, data)].into(),
404 );
405 }
406
407 pub fn update_image(
408 &self,
409 key: ImageKey,
410 descriptor: ImageDescriptor,
411 data: SerializableImageData,
412 epoch: Option<Epoch>,
413 ) {
414 self.update_images(
415 key.into(),
416 [ImageUpdate::UpdateImage(key, descriptor, data, epoch)].into(),
417 );
418 }
419
420 pub fn delete_image(&self, key: ImageKey) {
421 self.update_images(key.into(), [ImageUpdate::DeleteImage(key)].into());
422 }
423
424 pub fn update_images(&self, painter_id: PainterId, updates: SmallVec<[ImageUpdate; 1]>) {
426 if let Err(e) = self
427 .0
428 .send(CompositorMsg::UpdateImages(painter_id, updates))
429 {
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(CompositorMsg::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(CompositorMsg::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<IpcSharedMemory>, index: u32) {
467 let _ = self.0.send(CompositorMsg::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(CompositorMsg::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(CompositorMsg::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
501 .0
502 .send(CompositorMsg::Viewport(webview_id, description));
503 }
504
505 pub fn pipeline_exited(
506 &self,
507 webview_id: WebViewId,
508 pipeline_id: PipelineId,
509 source: PipelineExitSource,
510 ) {
511 let _ = self.0.send(CompositorMsg::PipelineExited(
512 webview_id,
513 pipeline_id,
514 source,
515 ));
516 }
517}
518
519#[derive(Clone)]
520pub struct PainterSurfmanDetails {
521 pub connection: Connection,
522 pub adapter: Adapter,
523}
524
525#[derive(Clone, Default)]
526pub struct PainterSurfmanDetailsMap(Arc<Mutex<HashMap<PainterId, PainterSurfmanDetails>>>);
527
528impl PainterSurfmanDetailsMap {
529 pub fn get(&self, painter_id: PainterId) -> Option<PainterSurfmanDetails> {
530 let map = self.0.lock().expect("poisoned");
531 map.get(&painter_id).cloned()
532 }
533
534 pub fn insert(&mut self, painter_id: PainterId, details: PainterSurfmanDetails) {
535 let mut map = self.0.lock().expect("poisoned");
536 let existing = map.insert(painter_id, details);
537 assert!(existing.is_none())
538 }
539}
540
541pub trait WebRenderExternalImageApi {
548 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
549 fn unlock(&mut self, id: u64);
550}
551
552#[derive(Clone, Copy)]
554pub enum WebRenderImageHandlerType {
555 WebGl,
556 Media,
557 WebGpu,
558}
559
560#[derive(Default)]
564struct WebRenderExternalImageIdManagerInner {
565 external_images: FxHashMap<ExternalImageId, WebRenderImageHandlerType>,
567 next_image_id: u64,
569}
570
571#[derive(Default, Clone)]
572pub struct WebRenderExternalImageIdManager(Arc<RwLock<WebRenderExternalImageIdManagerInner>>);
573
574impl WebRenderExternalImageIdManager {
575 pub fn next_id(&mut self, handler_type: WebRenderImageHandlerType) -> ExternalImageId {
576 let mut inner = self.0.write();
577 inner.next_image_id += 1;
578 let key = ExternalImageId(inner.next_image_id);
579 inner.external_images.insert(key, handler_type);
580 key
581 }
582
583 pub fn remove(&mut self, key: &ExternalImageId) {
584 self.0.write().external_images.remove(key);
585 }
586
587 pub fn get(&self, key: &ExternalImageId) -> Option<WebRenderImageHandlerType> {
588 self.0.read().external_images.get(key).cloned()
589 }
590}
591
592pub struct WebRenderExternalImageHandlers {
594 webgl_handler: Option<Box<dyn WebRenderExternalImageApi>>,
596 media_handler: Option<Box<dyn WebRenderExternalImageApi>>,
598 webgpu_handler: Option<Box<dyn WebRenderExternalImageApi>>,
600 id_manager: WebRenderExternalImageIdManager,
604}
605
606impl WebRenderExternalImageHandlers {
607 pub fn new(id_manager: WebRenderExternalImageIdManager) -> Self {
608 Self {
609 webgl_handler: Default::default(),
610 media_handler: Default::default(),
611 webgpu_handler: Default::default(),
612 id_manager,
613 }
614 }
615
616 pub fn id_manager(&self) -> WebRenderExternalImageIdManager {
617 self.id_manager.clone()
618 }
619
620 pub fn set_handler(
621 &mut self,
622 handler: Box<dyn WebRenderExternalImageApi>,
623 handler_type: WebRenderImageHandlerType,
624 ) {
625 match handler_type {
626 WebRenderImageHandlerType::WebGl => self.webgl_handler = Some(handler),
627 WebRenderImageHandlerType::Media => self.media_handler = Some(handler),
628 WebRenderImageHandlerType::WebGpu => self.webgpu_handler = Some(handler),
629 }
630 }
631}
632
633impl ExternalImageHandler for WebRenderExternalImageHandlers {
634 fn lock(
639 &mut self,
640 key: ExternalImageId,
641 _channel_index: u8,
642 _is_composited: bool,
643 ) -> ExternalImage<'_> {
644 let handler_type = self
645 .id_manager()
646 .get(&key)
647 .expect("Tried to get unknown external image");
648 match handler_type {
649 WebRenderImageHandlerType::WebGl => {
650 let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0);
651 let texture_id = match source {
652 ExternalImageSource::NativeTexture(b) => b,
653 _ => panic!("Wrong type"),
654 };
655 ExternalImage {
656 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
657 source: ExternalImageSource::NativeTexture(texture_id),
658 }
659 },
660 WebRenderImageHandlerType::Media => {
661 let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0);
662 let texture_id = match source {
663 ExternalImageSource::NativeTexture(b) => b,
664 _ => panic!("Wrong type"),
665 };
666 ExternalImage {
667 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
668 source: ExternalImageSource::NativeTexture(texture_id),
669 }
670 },
671 WebRenderImageHandlerType::WebGpu => {
672 let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
673 ExternalImage {
674 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
675 source,
676 }
677 },
678 }
679 }
680
681 fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) {
684 let handler_type = self
685 .id_manager()
686 .get(&key)
687 .expect("Tried to get unknown external image");
688 match handler_type {
689 WebRenderImageHandlerType::WebGl => self.webgl_handler.as_mut().unwrap().unlock(key.0),
690 WebRenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0),
691 WebRenderImageHandlerType::WebGpu => {
692 self.webgpu_handler.as_mut().unwrap().unlock(key.0)
693 },
694 };
695 }
696}
697
698#[derive(Deserialize, Serialize)]
699pub enum ImageUpdate {
701 AddImage(ImageKey, ImageDescriptor, SerializableImageData),
703 DeleteImage(ImageKey),
705 UpdateImage(
707 ImageKey,
708 ImageDescriptor,
709 SerializableImageData,
710 Option<Epoch>,
711 ),
712}
713
714impl Debug for ImageUpdate {
715 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
716 match self {
717 Self::AddImage(image_key, image_desc, _) => f
718 .debug_tuple("AddImage")
719 .field(image_key)
720 .field(image_desc)
721 .finish(),
722 Self::DeleteImage(image_key) => f.debug_tuple("DeleteImage").field(image_key).finish(),
723 Self::UpdateImage(image_key, image_desc, _, epoch) => f
724 .debug_tuple("UpdateImage")
725 .field(image_key)
726 .field(image_desc)
727 .field(epoch)
728 .finish(),
729 }
730 }
731}
732
733#[derive(Debug, Deserialize, Serialize)]
734pub enum SerializableImageData {
737 Raw(IpcSharedMemory),
740 External(ExternalImageData),
743}
744
745impl From<SerializableImageData> for ImageData {
746 fn from(value: SerializableImageData) -> Self {
747 match value {
748 SerializableImageData::Raw(shared_memory) => ImageData::new(shared_memory.to_vec()),
749 SerializableImageData::External(image) => ImageData::External(image),
750 }
751 }
752}
753
754pub trait WebViewTrait {
758 fn id(&self) -> WebViewId;
759 fn screen_geometry(&self) -> Option<ScreenGeometry>;
760 fn set_animating(&self, new_value: bool);
761}
762
763#[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
766pub struct PipelineExitSource(u8);
767
768bitflags! {
769 impl PipelineExitSource: u8 {
770 const Script = 1 << 0;
771 const Constellation = 1 << 1;
772 }
773}