1use std::fmt::{Debug, Error, Formatter};
8
9use base::Epoch;
10use base::id::{PainterId, PipelineId, WebViewId};
11use crossbeam_channel::Sender;
12use embedder_traits::{AnimationState, EventLoopWaker};
13use log::warn;
14use malloc_size_of_derive::MallocSizeOf;
15use rustc_hash::FxHashMap;
16use smallvec::SmallVec;
17use strum_macros::IntoStaticStr;
18use webrender_api::{DocumentId, FontVariation};
19
20pub mod display_list;
21pub mod largest_contentful_paint_candidate;
22pub mod rendering_context;
23pub mod viewport_description;
24
25use std::sync::{Arc, Mutex};
26
27use base::generic_channel::{self, GenericCallback, GenericSender};
28use bitflags::bitflags;
29use display_list::CompositorDisplayListInfo;
30use embedder_traits::ScreenGeometry;
31use euclid::default::Size2D as UntypedSize2D;
32use ipc_channel::ipc::{self, IpcSharedMemory};
33use profile_traits::mem::{OpaqueSender, ReportsChan};
34use serde::{Deserialize, Serialize};
35pub use webrender_api::ExternalImageSource;
36use webrender_api::units::{LayoutVector2D, TexelRect};
37use webrender_api::{
38 BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData,
39 ExternalImageHandler, ExternalImageId, ExternalScrollId, FontInstanceFlags, FontInstanceKey,
40 FontKey, ImageData, ImageDescriptor, ImageKey, NativeFontHandle,
41 PipelineId as WebRenderPipelineId,
42};
43
44use crate::largest_contentful_paint_candidate::LCPCandidate;
45use crate::viewport_description::ViewportDescription;
46
47#[derive(Clone)]
49pub struct CompositorProxy {
50 pub sender: Sender<Result<CompositorMsg, ipc_channel::Error>>,
51 pub cross_process_compositor_api: CrossProcessCompositorApi,
55 pub event_loop_waker: Box<dyn EventLoopWaker>,
56}
57
58impl OpaqueSender<CompositorMsg> for CompositorProxy {
59 fn send(&self, message: CompositorMsg) {
60 CompositorProxy::send(self, message)
61 }
62}
63
64impl CompositorProxy {
65 pub fn send(&self, msg: CompositorMsg) {
66 self.route_msg(Ok(msg))
67 }
68
69 pub fn route_msg(&self, msg: Result<CompositorMsg, ipc_channel::Error>) {
74 if let Err(err) = self.sender.send(msg) {
75 warn!("Failed to send response ({:?}).", err);
76 }
77 self.event_loop_waker.wake();
78 }
79}
80
81#[derive(Deserialize, IntoStaticStr, Serialize)]
83pub enum CompositorMsg {
84 ChangeRunningAnimationsState(WebViewId, PipelineId, AnimationState),
86 CreateOrUpdateWebView(SendableFrameTree),
88 RemoveWebView(WebViewId),
90 SetThrottled(WebViewId, PipelineId, bool),
92 NewWebRenderFrameReady(PainterId, DocumentId, bool),
96 PipelineExited(WebViewId, PipelineId, PipelineExitSource),
101 SendInitialTransaction(WebViewId, WebRenderPipelineId),
103 ScrollNodeByDelta(
107 WebViewId,
108 WebRenderPipelineId,
109 LayoutVector2D,
110 ExternalScrollId,
111 ),
112 ScrollViewportByDelta(WebViewId, LayoutVector2D),
116 UpdateEpoch {
118 webview_id: WebViewId,
120 pipeline_id: PipelineId,
122 epoch: Epoch,
124 },
125 SendDisplayList {
127 webview_id: WebViewId,
129 display_list_descriptor: BuiltDisplayListDescriptor,
131 display_list_receiver: ipc::IpcBytesReceiver,
133 },
134 GenerateFrame(Vec<WebViewId>),
137 GenerateImageKey(GenericSender<ImageKey>),
140 GenerateImageKeysForPipeline(PipelineId),
143 UpdateImages(SmallVec<[ImageUpdate; 1]>),
145 DelayNewFrameForCanvas(PipelineId, Epoch, Vec<ImageKey>),
150
151 GenerateFontKeys(
154 usize,
155 usize,
156 GenericSender<(Vec<FontKey>, Vec<FontInstanceKey>)>,
157 PainterId,
158 ),
159 AddFont(FontKey, Arc<IpcSharedMemory>, u32),
161 AddSystemFont(FontKey, NativeFontHandle),
163 AddFontInstance(
165 FontInstanceKey,
166 FontKey,
167 f32,
168 FontInstanceFlags,
169 Vec<FontVariation>,
170 ),
171 RemoveFonts(Vec<FontKey>, Vec<FontInstanceKey>),
173 CollectMemoryReport(ReportsChan),
176 Viewport(WebViewId, ViewportDescription),
178 ScreenshotReadinessReponse(WebViewId, FxHashMap<PipelineId, Epoch>),
181 SendLCPCandidate(LCPCandidate, WebViewId, PipelineId, Epoch),
183}
184
185impl Debug for CompositorMsg {
186 fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
187 let string: &'static str = self.into();
188 write!(formatter, "{string}")
189 }
190}
191
192#[derive(Deserialize, Serialize)]
193pub struct SendableFrameTree {
194 pub pipeline: CompositionPipeline,
195 pub children: Vec<SendableFrameTree>,
196}
197
198#[derive(Clone, Deserialize, Serialize)]
200pub struct CompositionPipeline {
201 pub id: PipelineId,
202 pub webview_id: WebViewId,
203}
204
205#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
207pub struct CrossProcessCompositorApi(GenericCallback<CompositorMsg>);
208
209impl CrossProcessCompositorApi {
210 pub fn new(callback: GenericCallback<CompositorMsg>) -> Self {
212 CrossProcessCompositorApi(callback)
213 }
214
215 pub fn dummy() -> Self {
218 Self::dummy_with_callback(None)
219 }
220
221 pub fn dummy_with_callback(
224 callback: Option<Box<dyn Fn(CompositorMsg) + Send + 'static>>,
225 ) -> Self {
226 let callback = GenericCallback::new(move |msg| {
227 if let Some(ref handler) = callback {
228 if let Ok(compositor_msg) = msg {
229 handler(compositor_msg);
230 }
231 }
232 })
233 .unwrap();
234 Self(callback)
235 }
236
237 pub fn send_initial_transaction(&self, webview_id: WebViewId, pipeline: WebRenderPipelineId) {
239 if let Err(e) = self
240 .0
241 .send(CompositorMsg::SendInitialTransaction(webview_id, pipeline))
242 {
243 warn!("Error sending initial transaction: {}", e);
244 }
245 }
246
247 pub fn scroll_node_by_delta(
251 &self,
252 webview_id: WebViewId,
253 pipeline_id: WebRenderPipelineId,
254 delta: LayoutVector2D,
255 scroll_id: ExternalScrollId,
256 ) {
257 if let Err(error) = self.0.send(CompositorMsg::ScrollNodeByDelta(
258 webview_id,
259 pipeline_id,
260 delta,
261 scroll_id,
262 )) {
263 warn!("Error scrolling node: {error}");
264 }
265 }
266
267 pub fn scroll_viewport_by_delta(&self, webview_id: WebViewId, delta: LayoutVector2D) {
274 if let Err(error) = self
275 .0
276 .send(CompositorMsg::ScrollViewportByDelta(webview_id, delta))
277 {
278 warn!("Error scroll viewport: {error}");
279 }
280 }
281
282 pub fn delay_new_frame_for_canvas(
283 &self,
284 pipeline_id: PipelineId,
285 canvas_epoch: Epoch,
286 image_keys: Vec<ImageKey>,
287 ) {
288 if let Err(error) = self.0.send(CompositorMsg::DelayNewFrameForCanvas(
289 pipeline_id,
290 canvas_epoch,
291 image_keys,
292 )) {
293 warn!("Error delaying frames for canvas image updates {error:?}");
294 }
295 }
296
297 pub fn update_epoch(&self, webview_id: WebViewId, pipeline_id: PipelineId, epoch: Epoch) {
300 if let Err(error) = self.0.send(CompositorMsg::UpdateEpoch {
301 webview_id,
302 pipeline_id,
303 epoch,
304 }) {
305 warn!("Error updating epoch for pipeline: {error:?}");
306 }
307 }
308
309 pub fn send_display_list(
311 &self,
312 webview_id: WebViewId,
313 display_list_info: &CompositorDisplayListInfo,
314 list: BuiltDisplayList,
315 ) {
316 let (display_list_data, display_list_descriptor) = list.into_data();
317 let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap();
318 if let Err(e) = self.0.send(CompositorMsg::SendDisplayList {
319 webview_id,
320 display_list_descriptor,
321 display_list_receiver,
322 }) {
323 warn!("Error sending display list: {}", e);
324 }
325
326 let display_list_info_serialized =
327 bincode::serialize(&display_list_info).unwrap_or_default();
328 if let Err(error) = display_list_sender.send(&display_list_info_serialized) {
329 warn!("Error sending display list info: {error}");
330 }
331
332 if let Err(error) = display_list_sender.send(&display_list_data.items_data) {
333 warn!("Error sending display list items: {error}");
334 }
335 if let Err(error) = display_list_sender.send(&display_list_data.cache_data) {
336 warn!("Error sending display list cache data: {error}");
337 }
338 if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) {
339 warn!("Error sending display spatial tree: {error}");
340 }
341 }
342
343 pub fn send_lcp_candidate(
345 &self,
346 lcp_candidate: LCPCandidate,
347 webview_id: WebViewId,
348 pipeline_id: PipelineId,
349 epoch: Epoch,
350 ) {
351 if let Err(error) = self.0.send(CompositorMsg::SendLCPCandidate(
352 lcp_candidate,
353 webview_id,
354 pipeline_id,
355 epoch,
356 )) {
357 warn!("Error sending LCPCandidate: {error}");
358 }
359 }
360
361 pub fn generate_frame(&self, webview_ids: Vec<WebViewId>) {
363 if let Err(error) = self.0.send(CompositorMsg::GenerateFrame(webview_ids)) {
364 warn!("Error generating frame: {error}");
365 }
366 }
367
368 pub fn generate_image_key_blocking(&self) -> Option<ImageKey> {
370 let (sender, receiver) = generic_channel::channel().unwrap();
371 self.0.send(CompositorMsg::GenerateImageKey(sender)).ok()?;
372 receiver.recv().ok()
373 }
374
375 pub fn generate_image_key_async(&self, pipeline_id: PipelineId) {
379 if let Err(e) = self
380 .0
381 .send(CompositorMsg::GenerateImageKeysForPipeline(pipeline_id))
382 {
383 warn!("Could not send image keys to Compositor {}", e);
384 }
385 }
386
387 pub fn add_image(
388 &self,
389 key: ImageKey,
390 descriptor: ImageDescriptor,
391 data: SerializableImageData,
392 ) {
393 self.update_images([ImageUpdate::AddImage(key, descriptor, data)].into());
394 }
395
396 pub fn update_image(
397 &self,
398 key: ImageKey,
399 descriptor: ImageDescriptor,
400 data: SerializableImageData,
401 epoch: Option<Epoch>,
402 ) {
403 self.update_images([ImageUpdate::UpdateImage(key, descriptor, data, epoch)].into());
404 }
405
406 pub fn delete_image(&self, key: ImageKey) {
407 self.update_images([ImageUpdate::DeleteImage(key)].into());
408 }
409
410 pub fn update_images(&self, updates: SmallVec<[ImageUpdate; 1]>) {
412 if let Err(e) = self.0.send(CompositorMsg::UpdateImages(updates)) {
413 warn!("error sending image updates: {}", e);
414 }
415 }
416
417 pub fn remove_unused_font_resources(
418 &self,
419 keys: Vec<FontKey>,
420 instance_keys: Vec<FontInstanceKey>,
421 ) {
422 if keys.is_empty() && instance_keys.is_empty() {
423 return;
424 }
425 let _ = self.0.send(CompositorMsg::RemoveFonts(keys, instance_keys));
426 }
427
428 pub fn add_font_instance(
429 &self,
430 font_instance_key: FontInstanceKey,
431 font_key: FontKey,
432 size: f32,
433 flags: FontInstanceFlags,
434 variations: Vec<FontVariation>,
435 ) {
436 let _x = self.0.send(CompositorMsg::AddFontInstance(
437 font_instance_key,
438 font_key,
439 size,
440 flags,
441 variations,
442 ));
443 }
444
445 pub fn add_font(&self, font_key: FontKey, data: Arc<IpcSharedMemory>, index: u32) {
446 let _ = self.0.send(CompositorMsg::AddFont(font_key, data, index));
447 }
448
449 pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) {
450 let _ = self.0.send(CompositorMsg::AddSystemFont(font_key, handle));
451 }
452
453 pub fn fetch_font_keys(
454 &self,
455 number_of_font_keys: usize,
456 number_of_font_instance_keys: usize,
457 painter_id: PainterId,
458 ) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
459 let (sender, receiver) = generic_channel::channel().expect("Could not create IPC channel");
460 let _ = self.0.send(CompositorMsg::GenerateFontKeys(
461 number_of_font_keys,
462 number_of_font_instance_keys,
463 sender,
464 painter_id,
465 ));
466 receiver.recv().unwrap()
467 }
468
469 pub fn viewport(&self, webview_id: WebViewId, description: ViewportDescription) {
470 let _ = self
471 .0
472 .send(CompositorMsg::Viewport(webview_id, description));
473 }
474
475 pub fn pipeline_exited(
476 &self,
477 webview_id: WebViewId,
478 pipeline_id: PipelineId,
479 source: PipelineExitSource,
480 ) {
481 let _ = self.0.send(CompositorMsg::PipelineExited(
482 webview_id,
483 pipeline_id,
484 source,
485 ));
486 }
487}
488
489pub trait WebRenderExternalImageApi {
496 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
497 fn unlock(&mut self, id: u64);
498}
499
500pub enum WebRenderImageHandlerType {
502 WebGl,
503 Media,
504 WebGpu,
505}
506
507#[derive(Default)]
511pub struct WebRenderExternalImageRegistry {
512 external_images: FxHashMap<ExternalImageId, WebRenderImageHandlerType>,
514 next_image_id: u64,
516}
517
518impl WebRenderExternalImageRegistry {
519 pub fn next_id(&mut self, handler_type: WebRenderImageHandlerType) -> ExternalImageId {
520 self.next_image_id += 1;
521 let key = ExternalImageId(self.next_image_id);
522 self.external_images.insert(key, handler_type);
523 key
524 }
525
526 pub fn remove(&mut self, key: &ExternalImageId) {
527 self.external_images.remove(key);
528 }
529
530 pub fn get(&self, key: &ExternalImageId) -> Option<&WebRenderImageHandlerType> {
531 self.external_images.get(key)
532 }
533}
534
535pub struct WebRenderExternalImageHandlers {
537 webgl_handler: Option<Box<dyn WebRenderExternalImageApi>>,
539 media_handler: Option<Box<dyn WebRenderExternalImageApi>>,
541 webgpu_handler: Option<Box<dyn WebRenderExternalImageApi>>,
543 external_images: Arc<Mutex<WebRenderExternalImageRegistry>>,
545}
546
547impl WebRenderExternalImageHandlers {
548 pub fn new() -> (Self, Arc<Mutex<WebRenderExternalImageRegistry>>) {
549 let external_images = Arc::new(Mutex::new(WebRenderExternalImageRegistry::default()));
550 (
551 Self {
552 webgl_handler: None,
553 media_handler: None,
554 webgpu_handler: None,
555 external_images: external_images.clone(),
556 },
557 external_images,
558 )
559 }
560
561 pub fn set_handler(
562 &mut self,
563 handler: Box<dyn WebRenderExternalImageApi>,
564 handler_type: WebRenderImageHandlerType,
565 ) {
566 match handler_type {
567 WebRenderImageHandlerType::WebGl => self.webgl_handler = Some(handler),
568 WebRenderImageHandlerType::Media => self.media_handler = Some(handler),
569 WebRenderImageHandlerType::WebGpu => self.webgpu_handler = Some(handler),
570 }
571 }
572}
573
574impl ExternalImageHandler for WebRenderExternalImageHandlers {
575 fn lock(
580 &mut self,
581 key: ExternalImageId,
582 _channel_index: u8,
583 _is_composited: bool,
584 ) -> ExternalImage<'_> {
585 let external_images = self.external_images.lock().unwrap();
586 let handler_type = external_images
587 .get(&key)
588 .expect("Tried to get unknown external image");
589 match handler_type {
590 WebRenderImageHandlerType::WebGl => {
591 let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0);
592 let texture_id = match source {
593 ExternalImageSource::NativeTexture(b) => b,
594 _ => panic!("Wrong type"),
595 };
596 ExternalImage {
597 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
598 source: ExternalImageSource::NativeTexture(texture_id),
599 }
600 },
601 WebRenderImageHandlerType::Media => {
602 let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0);
603 let texture_id = match source {
604 ExternalImageSource::NativeTexture(b) => b,
605 _ => panic!("Wrong type"),
606 };
607 ExternalImage {
608 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
609 source: ExternalImageSource::NativeTexture(texture_id),
610 }
611 },
612 WebRenderImageHandlerType::WebGpu => {
613 let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
614 ExternalImage {
615 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
616 source,
617 }
618 },
619 }
620 }
621
622 fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) {
625 let external_images = self.external_images.lock().unwrap();
626 let handler_type = external_images
627 .get(&key)
628 .expect("Tried to get unknown external image");
629 match handler_type {
630 WebRenderImageHandlerType::WebGl => self.webgl_handler.as_mut().unwrap().unlock(key.0),
631 WebRenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0),
632 WebRenderImageHandlerType::WebGpu => {
633 self.webgpu_handler.as_mut().unwrap().unlock(key.0)
634 },
635 };
636 }
637}
638
639#[derive(Deserialize, Serialize)]
640pub enum ImageUpdate {
642 AddImage(ImageKey, ImageDescriptor, SerializableImageData),
644 DeleteImage(ImageKey),
646 UpdateImage(
648 ImageKey,
649 ImageDescriptor,
650 SerializableImageData,
651 Option<Epoch>,
652 ),
653}
654
655impl Debug for ImageUpdate {
656 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
657 match self {
658 Self::AddImage(image_key, image_desc, _) => f
659 .debug_tuple("AddImage")
660 .field(image_key)
661 .field(image_desc)
662 .finish(),
663 Self::DeleteImage(image_key) => f.debug_tuple("DeleteImage").field(image_key).finish(),
664 Self::UpdateImage(image_key, image_desc, _, epoch) => f
665 .debug_tuple("UpdateImage")
666 .field(image_key)
667 .field(image_desc)
668 .field(epoch)
669 .finish(),
670 }
671 }
672}
673
674#[derive(Debug, Deserialize, Serialize)]
675pub enum SerializableImageData {
678 Raw(IpcSharedMemory),
681 External(ExternalImageData),
684}
685
686impl From<SerializableImageData> for ImageData {
687 fn from(value: SerializableImageData) -> Self {
688 match value {
689 SerializableImageData::Raw(shared_memory) => ImageData::new(shared_memory.to_vec()),
690 SerializableImageData::External(image) => ImageData::External(image),
691 }
692 }
693}
694
695pub trait WebViewTrait {
699 fn id(&self) -> WebViewId;
700 fn screen_geometry(&self) -> Option<ScreenGeometry>;
701 fn set_animating(&self, new_value: bool);
702}
703
704#[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
707pub struct PipelineExitSource(u8);
708
709bitflags! {
710 impl PipelineExitSource: u8 {
711 const Script = 1 << 0;
712 const Constellation = 1 << 1;
713 }
714}