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,
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 let callback = GenericCallback::new(|_msg| ()).unwrap();
219 Self(callback)
220 }
221
222 pub fn send_initial_transaction(&self, webview_id: WebViewId, pipeline: WebRenderPipelineId) {
224 if let Err(e) = self
225 .0
226 .send(CompositorMsg::SendInitialTransaction(webview_id, pipeline))
227 {
228 warn!("Error sending initial transaction: {}", e);
229 }
230 }
231
232 pub fn scroll_node_by_delta(
236 &self,
237 webview_id: WebViewId,
238 pipeline_id: WebRenderPipelineId,
239 delta: LayoutVector2D,
240 scroll_id: ExternalScrollId,
241 ) {
242 if let Err(error) = self.0.send(CompositorMsg::ScrollNodeByDelta(
243 webview_id,
244 pipeline_id,
245 delta,
246 scroll_id,
247 )) {
248 warn!("Error scrolling node: {error}");
249 }
250 }
251
252 pub fn scroll_viewport_by_delta(&self, webview_id: WebViewId, delta: LayoutVector2D) {
259 if let Err(error) = self
260 .0
261 .send(CompositorMsg::ScrollViewportByDelta(webview_id, delta))
262 {
263 warn!("Error scroll viewport: {error}");
264 }
265 }
266
267 pub fn delay_new_frame_for_canvas(
268 &self,
269 pipeline_id: PipelineId,
270 canvas_epoch: Epoch,
271 image_keys: Vec<ImageKey>,
272 ) {
273 if let Err(error) = self.0.send(CompositorMsg::DelayNewFrameForCanvas(
274 pipeline_id,
275 canvas_epoch,
276 image_keys,
277 )) {
278 warn!("Error delaying frames for canvas image updates {error:?}");
279 }
280 }
281
282 pub fn update_epoch(&self, webview_id: WebViewId, pipeline_id: PipelineId, epoch: Epoch) {
285 if let Err(error) = self.0.send(CompositorMsg::UpdateEpoch {
286 webview_id,
287 pipeline_id,
288 epoch,
289 }) {
290 warn!("Error updating epoch for pipeline: {error:?}");
291 }
292 }
293
294 pub fn send_display_list(
296 &self,
297 webview_id: WebViewId,
298 display_list_info: &CompositorDisplayListInfo,
299 list: BuiltDisplayList,
300 ) {
301 let (display_list_data, display_list_descriptor) = list.into_data();
302 let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap();
303 if let Err(e) = self.0.send(CompositorMsg::SendDisplayList {
304 webview_id,
305 display_list_descriptor,
306 display_list_receiver,
307 }) {
308 warn!("Error sending display list: {}", e);
309 }
310
311 let display_list_info_serialized =
312 bincode::serialize(&display_list_info).unwrap_or_default();
313 if let Err(error) = display_list_sender.send(&display_list_info_serialized) {
314 warn!("Error sending display list info: {error}");
315 }
316
317 if let Err(error) = display_list_sender.send(&display_list_data.items_data) {
318 warn!("Error sending display list items: {error}");
319 }
320 if let Err(error) = display_list_sender.send(&display_list_data.cache_data) {
321 warn!("Error sending display list cache data: {error}");
322 }
323 if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) {
324 warn!("Error sending display spatial tree: {error}");
325 }
326 }
327
328 pub fn send_lcp_candidate(
330 &self,
331 lcp_candidate: LCPCandidate,
332 webview_id: WebViewId,
333 pipeline_id: PipelineId,
334 epoch: Epoch,
335 ) {
336 if let Err(error) = self.0.send(CompositorMsg::SendLCPCandidate(
337 lcp_candidate,
338 webview_id,
339 pipeline_id,
340 epoch,
341 )) {
342 warn!("Error sending LCPCandidate: {error}");
343 }
344 }
345
346 pub fn generate_frame(&self) {
348 if let Err(error) = self.0.send(CompositorMsg::GenerateFrame) {
349 warn!("Error generating frame: {error}");
350 }
351 }
352
353 pub fn generate_image_key_blocking(&self) -> Option<ImageKey> {
355 let (sender, receiver) = generic_channel::channel().unwrap();
356 self.0.send(CompositorMsg::GenerateImageKey(sender)).ok()?;
357 receiver.recv().ok()
358 }
359
360 pub fn generate_image_key_async(&self, pipeline_id: PipelineId) {
364 if let Err(e) = self
365 .0
366 .send(CompositorMsg::GenerateImageKeysForPipeline(pipeline_id))
367 {
368 warn!("Could not send image keys to Compositor {}", e);
369 }
370 }
371
372 pub fn add_image(
373 &self,
374 key: ImageKey,
375 descriptor: ImageDescriptor,
376 data: SerializableImageData,
377 ) {
378 self.update_images([ImageUpdate::AddImage(key, descriptor, data)].into());
379 }
380
381 pub fn update_image(
382 &self,
383 key: ImageKey,
384 descriptor: ImageDescriptor,
385 data: SerializableImageData,
386 epoch: Option<Epoch>,
387 ) {
388 self.update_images([ImageUpdate::UpdateImage(key, descriptor, data, epoch)].into());
389 }
390
391 pub fn delete_image(&self, key: ImageKey) {
392 self.update_images([ImageUpdate::DeleteImage(key)].into());
393 }
394
395 pub fn update_images(&self, updates: SmallVec<[ImageUpdate; 1]>) {
397 if let Err(e) = self.0.send(CompositorMsg::UpdateImages(updates)) {
398 warn!("error sending image updates: {}", e);
399 }
400 }
401
402 pub fn remove_unused_font_resources(
403 &self,
404 keys: Vec<FontKey>,
405 instance_keys: Vec<FontInstanceKey>,
406 ) {
407 if keys.is_empty() && instance_keys.is_empty() {
408 return;
409 }
410 let _ = self.0.send(CompositorMsg::RemoveFonts(keys, instance_keys));
411 }
412
413 pub fn add_font_instance(
414 &self,
415 font_instance_key: FontInstanceKey,
416 font_key: FontKey,
417 size: f32,
418 flags: FontInstanceFlags,
419 variations: Vec<FontVariation>,
420 ) {
421 let _x = self.0.send(CompositorMsg::AddFontInstance(
422 font_instance_key,
423 font_key,
424 size,
425 flags,
426 variations,
427 ));
428 }
429
430 pub fn add_font(&self, font_key: FontKey, data: Arc<IpcSharedMemory>, index: u32) {
431 let _ = self.0.send(CompositorMsg::AddFont(font_key, data, index));
432 }
433
434 pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) {
435 let _ = self.0.send(CompositorMsg::AddSystemFont(font_key, handle));
436 }
437
438 pub fn fetch_font_keys(
439 &self,
440 number_of_font_keys: usize,
441 number_of_font_instance_keys: usize,
442 painter_id: PainterId,
443 ) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
444 let (sender, receiver) = generic_channel::channel().expect("Could not create IPC channel");
445 let _ = self.0.send(CompositorMsg::GenerateFontKeys(
446 number_of_font_keys,
447 number_of_font_instance_keys,
448 sender,
449 painter_id,
450 ));
451 receiver.recv().unwrap()
452 }
453
454 pub fn viewport(&self, webview_id: WebViewId, description: ViewportDescription) {
455 let _ = self
456 .0
457 .send(CompositorMsg::Viewport(webview_id, description));
458 }
459
460 pub fn pipeline_exited(
461 &self,
462 webview_id: WebViewId,
463 pipeline_id: PipelineId,
464 source: PipelineExitSource,
465 ) {
466 let _ = self.0.send(CompositorMsg::PipelineExited(
467 webview_id,
468 pipeline_id,
469 source,
470 ));
471 }
472}
473
474pub trait WebRenderExternalImageApi {
481 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
482 fn unlock(&mut self, id: u64);
483}
484
485pub enum WebRenderImageHandlerType {
487 WebGl,
488 Media,
489 WebGpu,
490}
491
492#[derive(Default)]
496pub struct WebRenderExternalImageRegistry {
497 external_images: FxHashMap<ExternalImageId, WebRenderImageHandlerType>,
499 next_image_id: u64,
501}
502
503impl WebRenderExternalImageRegistry {
504 pub fn next_id(&mut self, handler_type: WebRenderImageHandlerType) -> ExternalImageId {
505 self.next_image_id += 1;
506 let key = ExternalImageId(self.next_image_id);
507 self.external_images.insert(key, handler_type);
508 key
509 }
510
511 pub fn remove(&mut self, key: &ExternalImageId) {
512 self.external_images.remove(key);
513 }
514
515 pub fn get(&self, key: &ExternalImageId) -> Option<&WebRenderImageHandlerType> {
516 self.external_images.get(key)
517 }
518}
519
520pub struct WebRenderExternalImageHandlers {
522 webgl_handler: Option<Box<dyn WebRenderExternalImageApi>>,
524 media_handler: Option<Box<dyn WebRenderExternalImageApi>>,
526 webgpu_handler: Option<Box<dyn WebRenderExternalImageApi>>,
528 external_images: Arc<Mutex<WebRenderExternalImageRegistry>>,
530}
531
532impl WebRenderExternalImageHandlers {
533 pub fn new() -> (Self, Arc<Mutex<WebRenderExternalImageRegistry>>) {
534 let external_images = Arc::new(Mutex::new(WebRenderExternalImageRegistry::default()));
535 (
536 Self {
537 webgl_handler: None,
538 media_handler: None,
539 webgpu_handler: None,
540 external_images: external_images.clone(),
541 },
542 external_images,
543 )
544 }
545
546 pub fn set_handler(
547 &mut self,
548 handler: Box<dyn WebRenderExternalImageApi>,
549 handler_type: WebRenderImageHandlerType,
550 ) {
551 match handler_type {
552 WebRenderImageHandlerType::WebGl => self.webgl_handler = Some(handler),
553 WebRenderImageHandlerType::Media => self.media_handler = Some(handler),
554 WebRenderImageHandlerType::WebGpu => self.webgpu_handler = Some(handler),
555 }
556 }
557}
558
559impl ExternalImageHandler for WebRenderExternalImageHandlers {
560 fn lock(
565 &mut self,
566 key: ExternalImageId,
567 _channel_index: u8,
568 _is_composited: bool,
569 ) -> ExternalImage<'_> {
570 let external_images = self.external_images.lock().unwrap();
571 let handler_type = external_images
572 .get(&key)
573 .expect("Tried to get unknown external image");
574 match handler_type {
575 WebRenderImageHandlerType::WebGl => {
576 let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0);
577 let texture_id = match source {
578 ExternalImageSource::NativeTexture(b) => b,
579 _ => panic!("Wrong type"),
580 };
581 ExternalImage {
582 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
583 source: ExternalImageSource::NativeTexture(texture_id),
584 }
585 },
586 WebRenderImageHandlerType::Media => {
587 let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0);
588 let texture_id = match source {
589 ExternalImageSource::NativeTexture(b) => b,
590 _ => panic!("Wrong type"),
591 };
592 ExternalImage {
593 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
594 source: ExternalImageSource::NativeTexture(texture_id),
595 }
596 },
597 WebRenderImageHandlerType::WebGpu => {
598 let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
599 ExternalImage {
600 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
601 source,
602 }
603 },
604 }
605 }
606
607 fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) {
610 let external_images = self.external_images.lock().unwrap();
611 let handler_type = external_images
612 .get(&key)
613 .expect("Tried to get unknown external image");
614 match handler_type {
615 WebRenderImageHandlerType::WebGl => self.webgl_handler.as_mut().unwrap().unlock(key.0),
616 WebRenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0),
617 WebRenderImageHandlerType::WebGpu => {
618 self.webgpu_handler.as_mut().unwrap().unlock(key.0)
619 },
620 };
621 }
622}
623
624#[derive(Deserialize, Serialize)]
625pub enum ImageUpdate {
627 AddImage(ImageKey, ImageDescriptor, SerializableImageData),
629 DeleteImage(ImageKey),
631 UpdateImage(
633 ImageKey,
634 ImageDescriptor,
635 SerializableImageData,
636 Option<Epoch>,
637 ),
638}
639
640impl Debug for ImageUpdate {
641 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
642 match self {
643 Self::AddImage(image_key, image_desc, _) => f
644 .debug_tuple("AddImage")
645 .field(image_key)
646 .field(image_desc)
647 .finish(),
648 Self::DeleteImage(image_key) => f.debug_tuple("DeleteImage").field(image_key).finish(),
649 Self::UpdateImage(image_key, image_desc, _, epoch) => f
650 .debug_tuple("UpdateImage")
651 .field(image_key)
652 .field(image_desc)
653 .field(epoch)
654 .finish(),
655 }
656 }
657}
658
659#[derive(Debug, Deserialize, Serialize)]
660pub enum SerializableImageData {
663 Raw(IpcSharedMemory),
666 External(ExternalImageData),
669}
670
671impl From<SerializableImageData> for ImageData {
672 fn from(value: SerializableImageData) -> Self {
673 match value {
674 SerializableImageData::Raw(shared_memory) => ImageData::new(shared_memory.to_vec()),
675 SerializableImageData::External(image) => ImageData::External(image),
676 }
677 }
678}
679
680pub trait WebViewTrait {
684 fn id(&self) -> WebViewId;
685 fn screen_geometry(&self) -> Option<ScreenGeometry>;
686 fn set_animating(&self, new_value: bool);
687}
688
689#[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
692pub struct PipelineExitSource(u8);
693
694bitflags! {
695 impl PipelineExitSource: u8 {
696 const Script = 1 << 0;
697 const Constellation = 1 << 1;
698 }
699}