1use std::fmt::{Debug, Error, Formatter};
8
9use base::Epoch;
10use base::id::{PipelineId, WebViewId};
11use crossbeam_channel::Sender;
12use embedder_traits::{AnimationState, EventLoopWaker, TouchEventResult};
13use log::warn;
14use malloc_size_of_derive::MallocSizeOf;
15use smallvec::SmallVec;
16use strum_macros::IntoStaticStr;
17use webrender_api::{DocumentId, FontVariation};
18
19pub mod display_list;
20pub mod rendering_context;
21pub mod viewport_description;
22
23use std::collections::HashMap;
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 IsReadyToSaveImageReply(bool),
92 SetThrottled(WebViewId, PipelineId, bool),
94 NewWebRenderFrameReady(DocumentId, bool),
98 PipelineExited(WebViewId, PipelineId, PipelineExitSource),
103 LoadComplete(WebViewId),
105 SendInitialTransaction(WebRenderPipelineId),
107 SendScrollNode(
109 WebViewId,
110 WebRenderPipelineId,
111 LayoutVector2D,
112 ExternalScrollId,
113 ),
114 SendDisplayList {
116 webview_id: WebViewId,
118 display_list_descriptor: BuiltDisplayListDescriptor,
120 display_list_receiver: ipc::IpcBytesReceiver,
122 },
123 GenerateFrame,
126 GenerateImageKey(GenericSender<ImageKey>),
129 GenerateImageKeysForPipeline(PipelineId),
132 UpdateImages(SmallVec<[ImageUpdate; 1]>),
134 DelayNewFrameForCanvas(PipelineId, Epoch, Vec<ImageKey>),
139
140 GenerateFontKeys(
143 usize,
144 usize,
145 GenericSender<(Vec<FontKey>, Vec<FontInstanceKey>)>,
146 ),
147 AddFont(FontKey, Arc<IpcSharedMemory>, u32),
149 AddSystemFont(FontKey, NativeFontHandle),
151 AddFontInstance(
153 FontInstanceKey,
154 FontKey,
155 f32,
156 FontInstanceFlags,
157 Vec<FontVariation>,
158 ),
159 RemoveFonts(Vec<FontKey>, Vec<FontInstanceKey>),
161 CollectMemoryReport(ReportsChan),
164 Viewport(WebViewId, ViewportDescription),
166}
167
168impl Debug for CompositorMsg {
169 fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
170 let string: &'static str = self.into();
171 write!(formatter, "{string}")
172 }
173}
174
175#[derive(Deserialize, Serialize)]
176pub struct SendableFrameTree {
177 pub pipeline: CompositionPipeline,
178 pub children: Vec<SendableFrameTree>,
179}
180
181#[derive(Clone, Deserialize, Serialize)]
183pub struct CompositionPipeline {
184 pub id: PipelineId,
185 pub webview_id: WebViewId,
186}
187
188#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
190pub struct CrossProcessCompositorApi(GenericCallback<CompositorMsg>);
191
192impl CrossProcessCompositorApi {
193 pub fn new(callback: GenericCallback<CompositorMsg>) -> Self {
195 CrossProcessCompositorApi(callback)
196 }
197
198 pub fn dummy() -> Self {
201 let callback = GenericCallback::new(|_msg| ()).unwrap();
202 Self(callback)
203 }
204
205 pub fn send_initial_transaction(&self, pipeline: WebRenderPipelineId) {
207 if let Err(e) = self.0.send(CompositorMsg::SendInitialTransaction(pipeline)) {
208 warn!("Error sending initial transaction: {}", e);
209 }
210 }
211
212 pub fn send_scroll_node(
214 &self,
215 webview_id: WebViewId,
216 pipeline_id: WebRenderPipelineId,
217 point: LayoutVector2D,
218 scroll_id: ExternalScrollId,
219 ) {
220 if let Err(e) = self.0.send(CompositorMsg::SendScrollNode(
221 webview_id,
222 pipeline_id,
223 point,
224 scroll_id,
225 )) {
226 warn!("Error sending scroll node: {}", e);
227 }
228 }
229
230 pub fn delay_new_frame_for_canvas(
231 &self,
232 pipeline_id: PipelineId,
233 canvas_epoch: Epoch,
234 image_keys: Vec<ImageKey>,
235 ) {
236 if let Err(error) = self.0.send(CompositorMsg::DelayNewFrameForCanvas(
237 pipeline_id,
238 canvas_epoch,
239 image_keys,
240 )) {
241 warn!("Error delaying frames for canvas image updates {error:?}");
242 }
243 }
244
245 pub fn send_display_list(
247 &self,
248 webview_id: WebViewId,
249 display_list_info: &CompositorDisplayListInfo,
250 list: BuiltDisplayList,
251 ) {
252 let (display_list_data, display_list_descriptor) = list.into_data();
253 let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap();
254 if let Err(e) = self.0.send(CompositorMsg::SendDisplayList {
255 webview_id,
256 display_list_descriptor,
257 display_list_receiver,
258 }) {
259 warn!("Error sending display list: {}", e);
260 }
261
262 let display_list_info_serialized =
263 bincode::serialize(&display_list_info).unwrap_or_default();
264 if let Err(error) = display_list_sender.send(&display_list_info_serialized) {
265 warn!("Error sending display list info: {error}");
266 }
267
268 if let Err(error) = display_list_sender.send(&display_list_data.items_data) {
269 warn!("Error sending display list items: {error}");
270 }
271 if let Err(error) = display_list_sender.send(&display_list_data.cache_data) {
272 warn!("Error sending display list cache data: {error}");
273 }
274 if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) {
275 warn!("Error sending display spatial tree: {error}");
276 }
277 }
278
279 pub fn generate_frame(&self) {
281 if let Err(error) = self.0.send(CompositorMsg::GenerateFrame) {
282 warn!("Error generating frame: {error}");
283 }
284 }
285
286 pub fn generate_image_key_blocking(&self) -> Option<ImageKey> {
288 let (sender, receiver) = generic_channel::channel().unwrap();
289 self.0.send(CompositorMsg::GenerateImageKey(sender)).ok()?;
290 receiver.recv().ok()
291 }
292
293 pub fn generate_image_key_async(&self, pipeline_id: PipelineId) {
297 if let Err(e) = self
298 .0
299 .send(CompositorMsg::GenerateImageKeysForPipeline(pipeline_id))
300 {
301 warn!("Could not send image keys to Compositor {}", e);
302 }
303 }
304
305 pub fn add_image(
306 &self,
307 key: ImageKey,
308 descriptor: ImageDescriptor,
309 data: SerializableImageData,
310 ) {
311 self.update_images([ImageUpdate::AddImage(key, descriptor, data)].into());
312 }
313
314 pub fn update_image(
315 &self,
316 key: ImageKey,
317 descriptor: ImageDescriptor,
318 data: SerializableImageData,
319 epoch: Option<Epoch>,
320 ) {
321 self.update_images([ImageUpdate::UpdateImage(key, descriptor, data, epoch)].into());
322 }
323
324 pub fn delete_image(&self, key: ImageKey) {
325 self.update_images([ImageUpdate::DeleteImage(key)].into());
326 }
327
328 pub fn update_images(&self, updates: SmallVec<[ImageUpdate; 1]>) {
330 if let Err(e) = self.0.send(CompositorMsg::UpdateImages(updates)) {
331 warn!("error sending image updates: {}", e);
332 }
333 }
334
335 pub fn remove_unused_font_resources(
336 &self,
337 keys: Vec<FontKey>,
338 instance_keys: Vec<FontInstanceKey>,
339 ) {
340 if keys.is_empty() && instance_keys.is_empty() {
341 return;
342 }
343 let _ = self.0.send(CompositorMsg::RemoveFonts(keys, instance_keys));
344 }
345
346 pub fn add_font_instance(
347 &self,
348 font_instance_key: FontInstanceKey,
349 font_key: FontKey,
350 size: f32,
351 flags: FontInstanceFlags,
352 variations: Vec<FontVariation>,
353 ) {
354 let _x = self.0.send(CompositorMsg::AddFontInstance(
355 font_instance_key,
356 font_key,
357 size,
358 flags,
359 variations,
360 ));
361 }
362
363 pub fn add_font(&self, font_key: FontKey, data: Arc<IpcSharedMemory>, index: u32) {
364 let _ = self.0.send(CompositorMsg::AddFont(font_key, data, index));
365 }
366
367 pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) {
368 let _ = self.0.send(CompositorMsg::AddSystemFont(font_key, handle));
369 }
370
371 pub fn fetch_font_keys(
372 &self,
373 number_of_font_keys: usize,
374 number_of_font_instance_keys: usize,
375 ) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
376 let (sender, receiver) = generic_channel::channel().expect("Could not create IPC channel");
377 let _ = self.0.send(CompositorMsg::GenerateFontKeys(
378 number_of_font_keys,
379 number_of_font_instance_keys,
380 sender,
381 ));
382 receiver.recv().unwrap()
383 }
384
385 pub fn viewport(&self, webview_id: WebViewId, description: ViewportDescription) {
386 let _ = self
387 .0
388 .send(CompositorMsg::Viewport(webview_id, description));
389 }
390
391 pub fn pipeline_exited(
392 &self,
393 webview_id: WebViewId,
394 pipeline_id: PipelineId,
395 source: PipelineExitSource,
396 ) {
397 let _ = self.0.send(CompositorMsg::PipelineExited(
398 webview_id,
399 pipeline_id,
400 source,
401 ));
402 }
403}
404
405pub trait WebrenderExternalImageApi {
412 fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
413 fn unlock(&mut self, id: u64);
414}
415
416pub enum WebrenderImageHandlerType {
418 WebGL,
419 Media,
420 WebGPU,
421}
422
423#[derive(Default)]
427pub struct WebrenderExternalImageRegistry {
428 external_images: HashMap<ExternalImageId, WebrenderImageHandlerType>,
430 next_image_id: u64,
432}
433
434impl WebrenderExternalImageRegistry {
435 pub fn next_id(&mut self, handler_type: WebrenderImageHandlerType) -> ExternalImageId {
436 self.next_image_id += 1;
437 let key = ExternalImageId(self.next_image_id);
438 self.external_images.insert(key, handler_type);
439 key
440 }
441
442 pub fn remove(&mut self, key: &ExternalImageId) {
443 self.external_images.remove(key);
444 }
445
446 pub fn get(&self, key: &ExternalImageId) -> Option<&WebrenderImageHandlerType> {
447 self.external_images.get(key)
448 }
449}
450
451pub struct WebrenderExternalImageHandlers {
453 webgl_handler: Option<Box<dyn WebrenderExternalImageApi>>,
455 media_handler: Option<Box<dyn WebrenderExternalImageApi>>,
457 webgpu_handler: Option<Box<dyn WebrenderExternalImageApi>>,
459 external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
461}
462
463impl WebrenderExternalImageHandlers {
464 pub fn new() -> (Self, Arc<Mutex<WebrenderExternalImageRegistry>>) {
465 let external_images = Arc::new(Mutex::new(WebrenderExternalImageRegistry::default()));
466 (
467 Self {
468 webgl_handler: None,
469 media_handler: None,
470 webgpu_handler: None,
471 external_images: external_images.clone(),
472 },
473 external_images,
474 )
475 }
476
477 pub fn set_handler(
478 &mut self,
479 handler: Box<dyn WebrenderExternalImageApi>,
480 handler_type: WebrenderImageHandlerType,
481 ) {
482 match handler_type {
483 WebrenderImageHandlerType::WebGL => self.webgl_handler = Some(handler),
484 WebrenderImageHandlerType::Media => self.media_handler = Some(handler),
485 WebrenderImageHandlerType::WebGPU => self.webgpu_handler = Some(handler),
486 }
487 }
488}
489
490impl ExternalImageHandler for WebrenderExternalImageHandlers {
491 fn lock(&mut self, key: ExternalImageId, _channel_index: u8) -> ExternalImage<'_> {
496 let external_images = self.external_images.lock().unwrap();
497 let handler_type = external_images
498 .get(&key)
499 .expect("Tried to get unknown external image");
500 match handler_type {
501 WebrenderImageHandlerType::WebGL => {
502 let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0);
503 let texture_id = match source {
504 ExternalImageSource::NativeTexture(b) => b,
505 _ => panic!("Wrong type"),
506 };
507 ExternalImage {
508 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
509 source: ExternalImageSource::NativeTexture(texture_id),
510 }
511 },
512 WebrenderImageHandlerType::Media => {
513 let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0);
514 let texture_id = match source {
515 ExternalImageSource::NativeTexture(b) => b,
516 _ => panic!("Wrong type"),
517 };
518 ExternalImage {
519 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
520 source: ExternalImageSource::NativeTexture(texture_id),
521 }
522 },
523 WebrenderImageHandlerType::WebGPU => {
524 let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
525 ExternalImage {
526 uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
527 source,
528 }
529 },
530 }
531 }
532
533 fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) {
536 let external_images = self.external_images.lock().unwrap();
537 let handler_type = external_images
538 .get(&key)
539 .expect("Tried to get unknown external image");
540 match handler_type {
541 WebrenderImageHandlerType::WebGL => self.webgl_handler.as_mut().unwrap().unlock(key.0),
542 WebrenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0),
543 WebrenderImageHandlerType::WebGPU => {
544 self.webgpu_handler.as_mut().unwrap().unlock(key.0)
545 },
546 };
547 }
548}
549
550#[derive(Deserialize, Serialize)]
551pub enum ImageUpdate {
553 AddImage(ImageKey, ImageDescriptor, SerializableImageData),
555 DeleteImage(ImageKey),
557 UpdateImage(
559 ImageKey,
560 ImageDescriptor,
561 SerializableImageData,
562 Option<Epoch>,
563 ),
564}
565
566impl Debug for ImageUpdate {
567 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
568 match self {
569 Self::AddImage(image_key, image_desc, _) => f
570 .debug_tuple("AddImage")
571 .field(image_key)
572 .field(image_desc)
573 .finish(),
574 Self::DeleteImage(image_key) => f.debug_tuple("DeleteImage").field(image_key).finish(),
575 Self::UpdateImage(image_key, image_desc, _, epoch) => f
576 .debug_tuple("UpdateImage")
577 .field(image_key)
578 .field(image_desc)
579 .field(epoch)
580 .finish(),
581 }
582 }
583}
584
585#[derive(Debug, Deserialize, Serialize)]
586pub enum SerializableImageData {
589 Raw(IpcSharedMemory),
592 External(ExternalImageData),
595}
596
597impl From<SerializableImageData> for ImageData {
598 fn from(value: SerializableImageData) -> Self {
599 match value {
600 SerializableImageData::Raw(shared_memory) => ImageData::new(shared_memory.to_vec()),
601 SerializableImageData::External(image) => ImageData::External(image),
602 }
603 }
604}
605
606pub trait WebViewTrait {
610 fn id(&self) -> WebViewId;
611 fn screen_geometry(&self) -> Option<ScreenGeometry>;
612 fn set_animating(&self, new_value: bool);
613}
614
615#[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
618pub struct PipelineExitSource(u8);
619
620bitflags! {
621 impl PipelineExitSource: u8 {
622 const Script = 1 << 0;
623 const Constellation = 1 << 1;
624 }
625}