1use std::fmt::{Debug, Error, Formatter};
8
9use base::Epoch;
10use base::id::{PipelineId, RenderingGroupId, WebViewId};
11use crossbeam_channel::Sender;
12use embedder_traits::{AnimationState, EventLoopWaker, TouchEventResult};
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 rendering_context;
22pub mod viewport_description;
23
24use std::sync::{Arc, Mutex};
25
26use base::generic_channel::{self, GenericCallback, GenericSender};
27use bitflags::bitflags;
28use display_list::CompositorDisplayListInfo;
29use embedder_traits::ScreenGeometry;
30use euclid::default::Size2D as UntypedSize2D;
31use ipc_channel::ipc::{self, IpcSharedMemory};
32use profile_traits::mem::{OpaqueSender, ReportsChan};
33use serde::{Deserialize, Serialize};
34pub use webrender_api::ExternalImageSource;
35use webrender_api::units::{LayoutVector2D, TexelRect};
36use webrender_api::{
37 BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData,
38 ExternalImageHandler, ExternalImageId, ExternalScrollId, FontInstanceFlags, FontInstanceKey,
39 FontKey, ImageData, ImageDescriptor, ImageKey, NativeFontHandle,
40 PipelineId as WebRenderPipelineId,
41};
42
43use crate::viewport_description::ViewportDescription;
44
45#[derive(Clone)]
47pub struct CompositorProxy {
48 pub sender: Sender<Result<CompositorMsg, ipc_channel::Error>>,
49 pub cross_process_compositor_api: CrossProcessCompositorApi,
53 pub event_loop_waker: Box<dyn EventLoopWaker>,
54}
55
56impl OpaqueSender<CompositorMsg> for CompositorProxy {
57 fn send(&self, message: CompositorMsg) {
58 CompositorProxy::send(self, message)
59 }
60}
61
62impl CompositorProxy {
63 pub fn send(&self, msg: CompositorMsg) {
64 self.route_msg(Ok(msg))
65 }
66
67 pub fn route_msg(&self, msg: Result<CompositorMsg, ipc_channel::Error>) {
72 if let Err(err) = self.sender.send(msg) {
73 warn!("Failed to send response ({:?}).", err);
74 }
75 self.event_loop_waker.wake();
76 }
77}
78
79#[derive(Deserialize, IntoStaticStr, Serialize)]
81pub enum CompositorMsg {
82 ChangeRunningAnimationsState(WebViewId, PipelineId, AnimationState),
84 CreateOrUpdateWebView(SendableFrameTree),
86 RemoveWebView(WebViewId),
88 TouchEventProcessed(WebViewId, TouchEventResult),
90 SetThrottled(WebViewId, PipelineId, bool),
92 NewWebRenderFrameReady(DocumentId, bool),
96 PipelineExited(WebViewId, PipelineId, PipelineExitSource),
101 SendInitialTransaction(WebViewId, WebRenderPipelineId),
103 SendScrollNode(
105 WebViewId,
106 WebRenderPipelineId,
107 LayoutVector2D,
108 ExternalScrollId,
109 ),
110 UpdateEpoch {
112 webview_id: WebViewId,
114 pipeline_id: PipelineId,
116 epoch: Epoch,
118 },
119 SendDisplayList {
121 webview_id: WebViewId,
123 display_list_descriptor: BuiltDisplayListDescriptor,
125 display_list_receiver: ipc::IpcBytesReceiver,
127 },
128 GenerateFrame,
131 GenerateImageKey(GenericSender<ImageKey>),
134 GenerateImageKeysForPipeline(PipelineId),
137 UpdateImages(SmallVec<[ImageUpdate; 1]>),
139 DelayNewFrameForCanvas(PipelineId, Epoch, Vec<ImageKey>),
144
145 GenerateFontKeys(
148 usize,
149 usize,
150 GenericSender<(Vec<FontKey>, Vec<FontInstanceKey>)>,
151 RenderingGroupId,
152 ),
153 AddFont(FontKey, Arc<IpcSharedMemory>, u32),
155 AddSystemFont(FontKey, NativeFontHandle),
157 AddFontInstance(
159 FontInstanceKey,
160 FontKey,
161 f32,
162 FontInstanceFlags,
163 Vec<FontVariation>,
164 ),
165 RemoveFonts(Vec<FontKey>, Vec<FontInstanceKey>),
167 CollectMemoryReport(ReportsChan),
170 Viewport(WebViewId, ViewportDescription),
172 ScreenshotReadinessReponse(WebViewId, FxHashMap<PipelineId, Epoch>),
175}
176
177impl Debug for CompositorMsg {
178 fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
179 let string: &'static str = self.into();
180 write!(formatter, "{string}")
181 }
182}
183
184#[derive(Deserialize, Serialize)]
185pub struct SendableFrameTree {
186 pub pipeline: CompositionPipeline,
187 pub children: Vec<SendableFrameTree>,
188}
189
190#[derive(Clone, Deserialize, Serialize)]
192pub struct CompositionPipeline {
193 pub id: PipelineId,
194 pub webview_id: WebViewId,
195}
196
197#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
199pub struct CrossProcessCompositorApi(GenericCallback<CompositorMsg>);
200
201impl CrossProcessCompositorApi {
202 pub fn new(callback: GenericCallback<CompositorMsg>) -> Self {
204 CrossProcessCompositorApi(callback)
205 }
206
207 pub fn dummy() -> Self {
210 let callback = GenericCallback::new(|_msg| ()).unwrap();
211 Self(callback)
212 }
213
214 pub fn send_initial_transaction(&self, webview_id: WebViewId, pipeline: WebRenderPipelineId) {
216 if let Err(e) = self
217 .0
218 .send(CompositorMsg::SendInitialTransaction(webview_id, pipeline))
219 {
220 warn!("Error sending initial transaction: {}", e);
221 }
222 }
223
224 pub fn send_scroll_node(
226 &self,
227 webview_id: WebViewId,
228 pipeline_id: WebRenderPipelineId,
229 point: LayoutVector2D,
230 scroll_id: ExternalScrollId,
231 ) {
232 if let Err(e) = self.0.send(CompositorMsg::SendScrollNode(
233 webview_id,
234 pipeline_id,
235 point,
236 scroll_id,
237 )) {
238 warn!("Error sending scroll node: {}", e);
239 }
240 }
241
242 pub fn delay_new_frame_for_canvas(
243 &self,
244 pipeline_id: PipelineId,
245 canvas_epoch: Epoch,
246 image_keys: Vec<ImageKey>,
247 ) {
248 if let Err(error) = self.0.send(CompositorMsg::DelayNewFrameForCanvas(
249 pipeline_id,
250 canvas_epoch,
251 image_keys,
252 )) {
253 warn!("Error delaying frames for canvas image updates {error:?}");
254 }
255 }
256
257 pub fn update_epoch(&self, webview_id: WebViewId, pipeline_id: PipelineId, epoch: Epoch) {
260 if let Err(error) = self.0.send(CompositorMsg::UpdateEpoch {
261 webview_id,
262 pipeline_id,
263 epoch,
264 }) {
265 warn!("Error updating epoch for pipeline: {error:?}");
266 }
267 }
268
269 pub fn send_display_list(
271 &self,
272 webview_id: WebViewId,
273 display_list_info: &CompositorDisplayListInfo,
274 list: BuiltDisplayList,
275 ) {
276 let (display_list_data, display_list_descriptor) = list.into_data();
277 let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap();
278 if let Err(e) = self.0.send(CompositorMsg::SendDisplayList {
279 webview_id,
280 display_list_descriptor,
281 display_list_receiver,
282 }) {
283 warn!("Error sending display list: {}", e);
284 }
285
286 let display_list_info_serialized =
287 bincode::serialize(&display_list_info).unwrap_or_default();
288 if let Err(error) = display_list_sender.send(&display_list_info_serialized) {
289 warn!("Error sending display list info: {error}");
290 }
291
292 if let Err(error) = display_list_sender.send(&display_list_data.items_data) {
293 warn!("Error sending display list items: {error}");
294 }
295 if let Err(error) = display_list_sender.send(&display_list_data.cache_data) {
296 warn!("Error sending display list cache data: {error}");
297 }
298 if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) {
299 warn!("Error sending display spatial tree: {error}");
300 }
301 }
302
303 pub fn generate_frame(&self) {
305 if let Err(error) = self.0.send(CompositorMsg::GenerateFrame) {
306 warn!("Error generating frame: {error}");
307 }
308 }
309
310 pub fn generate_image_key_blocking(&self) -> Option<ImageKey> {
312 let (sender, receiver) = generic_channel::channel().unwrap();
313 self.0.send(CompositorMsg::GenerateImageKey(sender)).ok()?;
314 receiver.recv().ok()
315 }
316
317 pub fn generate_image_key_async(&self, pipeline_id: PipelineId) {
321 if let Err(e) = self
322 .0
323 .send(CompositorMsg::GenerateImageKeysForPipeline(pipeline_id))
324 {
325 warn!("Could not send image keys to Compositor {}", e);
326 }
327 }
328
329 pub fn add_image(
330 &self,
331 key: ImageKey,
332 descriptor: ImageDescriptor,
333 data: SerializableImageData,
334 ) {
335 self.update_images([ImageUpdate::AddImage(key, descriptor, data)].into());
336 }
337
338 pub fn update_image(
339 &self,
340 key: ImageKey,
341 descriptor: ImageDescriptor,
342 data: SerializableImageData,
343 epoch: Option<Epoch>,
344 ) {
345 self.update_images([ImageUpdate::UpdateImage(key, descriptor, data, epoch)].into());
346 }
347
348 pub fn delete_image(&self, key: ImageKey) {
349 self.update_images([ImageUpdate::DeleteImage(key)].into());
350 }
351
352 pub fn update_images(&self, updates: SmallVec<[ImageUpdate; 1]>) {
354 if let Err(e) = self.0.send(CompositorMsg::UpdateImages(updates)) {
355 warn!("error sending image updates: {}", e);
356 }
357 }
358
359 pub fn remove_unused_font_resources(
360 &self,
361 keys: Vec<FontKey>,
362 instance_keys: Vec<FontInstanceKey>,
363 ) {
364 if keys.is_empty() && instance_keys.is_empty() {
365 return;
366 }
367 let _ = self.0.send(CompositorMsg::RemoveFonts(keys, instance_keys));
368 }
369
370 pub fn add_font_instance(
371 &self,
372 font_instance_key: FontInstanceKey,
373 font_key: FontKey,
374 size: f32,
375 flags: FontInstanceFlags,
376 variations: Vec<FontVariation>,
377 ) {
378 let _x = self.0.send(CompositorMsg::AddFontInstance(
379 font_instance_key,
380 font_key,
381 size,
382 flags,
383 variations,
384 ));
385 }
386
387 pub fn add_font(&self, font_key: FontKey, data: Arc<IpcSharedMemory>, index: u32) {
388 let _ = self.0.send(CompositorMsg::AddFont(font_key, data, index));
389 }
390
391 pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) {
392 let _ = self.0.send(CompositorMsg::AddSystemFont(font_key, handle));
393 }
394
395 pub fn fetch_font_keys(
396 &self,
397 number_of_font_keys: usize,
398 number_of_font_instance_keys: usize,
399 rendering_group_id: RenderingGroupId,
400 ) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
401 let (sender, receiver) = generic_channel::channel().expect("Could not create IPC channel");
402 let _ = self.0.send(CompositorMsg::GenerateFontKeys(
403 number_of_font_keys,
404 number_of_font_instance_keys,
405 sender,
406 rendering_group_id,
407 ));
408 receiver.recv().unwrap()
409 }
410
411 pub fn viewport(&self, webview_id: WebViewId, description: ViewportDescription) {
412 let _ = self
413 .0
414 .send(CompositorMsg::Viewport(webview_id, description));
415 }
416
417 pub fn pipeline_exited(
418 &self,
419 webview_id: WebViewId,
420 pipeline_id: PipelineId,
421 source: PipelineExitSource,
422 ) {
423 let _ = self.0.send(CompositorMsg::PipelineExited(
424 webview_id,
425 pipeline_id,
426 source,
427 ));
428 }
429}
430
431pub trait WebrenderExternalImageApi {
438 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
439 fn unlock(&mut self, id: u64);
440}
441
442pub enum WebrenderImageHandlerType {
444 WebGL,
445 Media,
446 WebGPU,
447}
448
449#[derive(Default)]
453pub struct WebrenderExternalImageRegistry {
454 external_images: FxHashMap<ExternalImageId, WebrenderImageHandlerType>,
456 next_image_id: u64,
458}
459
460impl WebrenderExternalImageRegistry {
461 pub fn next_id(&mut self, handler_type: WebrenderImageHandlerType) -> ExternalImageId {
462 self.next_image_id += 1;
463 let key = ExternalImageId(self.next_image_id);
464 self.external_images.insert(key, handler_type);
465 key
466 }
467
468 pub fn remove(&mut self, key: &ExternalImageId) {
469 self.external_images.remove(key);
470 }
471
472 pub fn get(&self, key: &ExternalImageId) -> Option<&WebrenderImageHandlerType> {
473 self.external_images.get(key)
474 }
475}
476
477pub struct WebrenderExternalImageHandlers {
479 webgl_handler: Option<Box<dyn WebrenderExternalImageApi>>,
481 media_handler: Option<Box<dyn WebrenderExternalImageApi>>,
483 webgpu_handler: Option<Box<dyn WebrenderExternalImageApi>>,
485 external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
487}
488
489impl WebrenderExternalImageHandlers {
490 pub fn new() -> (Self, Arc<Mutex<WebrenderExternalImageRegistry>>) {
491 let external_images = Arc::new(Mutex::new(WebrenderExternalImageRegistry::default()));
492 (
493 Self {
494 webgl_handler: None,
495 media_handler: None,
496 webgpu_handler: None,
497 external_images: external_images.clone(),
498 },
499 external_images,
500 )
501 }
502
503 pub fn set_handler(
504 &mut self,
505 handler: Box<dyn WebrenderExternalImageApi>,
506 handler_type: WebrenderImageHandlerType,
507 ) {
508 match handler_type {
509 WebrenderImageHandlerType::WebGL => self.webgl_handler = Some(handler),
510 WebrenderImageHandlerType::Media => self.media_handler = Some(handler),
511 WebrenderImageHandlerType::WebGPU => self.webgpu_handler = Some(handler),
512 }
513 }
514}
515
516impl ExternalImageHandler for WebrenderExternalImageHandlers {
517 fn lock(
522 &mut self,
523 key: ExternalImageId,
524 _channel_index: u8,
525 _is_composited: bool,
526 ) -> ExternalImage<'_> {
527 let external_images = self.external_images.lock().unwrap();
528 let handler_type = external_images
529 .get(&key)
530 .expect("Tried to get unknown external image");
531 match handler_type {
532 WebrenderImageHandlerType::WebGL => {
533 let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0);
534 let texture_id = match source {
535 ExternalImageSource::NativeTexture(b) => b,
536 _ => panic!("Wrong type"),
537 };
538 ExternalImage {
539 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
540 source: ExternalImageSource::NativeTexture(texture_id),
541 }
542 },
543 WebrenderImageHandlerType::Media => {
544 let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0);
545 let texture_id = match source {
546 ExternalImageSource::NativeTexture(b) => b,
547 _ => panic!("Wrong type"),
548 };
549 ExternalImage {
550 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
551 source: ExternalImageSource::NativeTexture(texture_id),
552 }
553 },
554 WebrenderImageHandlerType::WebGPU => {
555 let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
556 ExternalImage {
557 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
558 source,
559 }
560 },
561 }
562 }
563
564 fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) {
567 let external_images = self.external_images.lock().unwrap();
568 let handler_type = external_images
569 .get(&key)
570 .expect("Tried to get unknown external image");
571 match handler_type {
572 WebrenderImageHandlerType::WebGL => self.webgl_handler.as_mut().unwrap().unlock(key.0),
573 WebrenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0),
574 WebrenderImageHandlerType::WebGPU => {
575 self.webgpu_handler.as_mut().unwrap().unlock(key.0)
576 },
577 };
578 }
579}
580
581#[derive(Deserialize, Serialize)]
582pub enum ImageUpdate {
584 AddImage(ImageKey, ImageDescriptor, SerializableImageData),
586 DeleteImage(ImageKey),
588 UpdateImage(
590 ImageKey,
591 ImageDescriptor,
592 SerializableImageData,
593 Option<Epoch>,
594 ),
595}
596
597impl Debug for ImageUpdate {
598 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
599 match self {
600 Self::AddImage(image_key, image_desc, _) => f
601 .debug_tuple("AddImage")
602 .field(image_key)
603 .field(image_desc)
604 .finish(),
605 Self::DeleteImage(image_key) => f.debug_tuple("DeleteImage").field(image_key).finish(),
606 Self::UpdateImage(image_key, image_desc, _, epoch) => f
607 .debug_tuple("UpdateImage")
608 .field(image_key)
609 .field(image_desc)
610 .field(epoch)
611 .finish(),
612 }
613 }
614}
615
616#[derive(Debug, Deserialize, Serialize)]
617pub enum SerializableImageData {
620 Raw(IpcSharedMemory),
623 External(ExternalImageData),
626}
627
628impl From<SerializableImageData> for ImageData {
629 fn from(value: SerializableImageData) -> Self {
630 match value {
631 SerializableImageData::Raw(shared_memory) => ImageData::new(shared_memory.to_vec()),
632 SerializableImageData::External(image) => ImageData::External(image),
633 }
634 }
635}
636
637pub trait WebViewTrait {
641 fn id(&self) -> WebViewId;
642 fn rendering_group_id(&self) -> Option<RenderingGroupId>;
643 fn screen_geometry(&self) -> Option<ScreenGeometry>;
644 fn set_animating(&self, new_value: bool);
645}
646
647#[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
650pub struct PipelineExitSource(u8);
651
652bitflags! {
653 impl PipelineExitSource: u8 {
654 const Script = 1 << 0;
655 const Constellation = 1 << 1;
656 }
657}