compositing_traits/
lib.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5//! The interface to the `compositing` crate.
6
7use 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/// Sends messages to the compositor.
48#[derive(Clone)]
49pub struct CompositorProxy {
50    pub sender: Sender<Result<CompositorMsg, ipc_channel::Error>>,
51    /// Access to [`Self::sender`] that is possible to send across an IPC
52    /// channel. These messages are routed via the router thread to
53    /// [`Self::sender`].
54    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    /// Helper method to route a deserialized IPC message to the receiver.
70    ///
71    /// This method is a temporary solution, and will be removed when migrating
72    /// to `GenericChannel`.
73    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/// Messages from (or via) the constellation thread to the compositor.
82#[derive(Deserialize, IntoStaticStr, Serialize)]
83pub enum CompositorMsg {
84    /// Alerts the compositor that the given pipeline has changed whether it is running animations.
85    ChangeRunningAnimationsState(WebViewId, PipelineId, AnimationState),
86    /// Create or update a webview, given its frame tree.
87    CreateOrUpdateWebView(SendableFrameTree),
88    /// Remove a webview.
89    RemoveWebView(WebViewId),
90    /// Set whether to use less resources by stopping animations.
91    SetThrottled(WebViewId, PipelineId, bool),
92    /// WebRender has produced a new frame. This message informs the compositor that
93    /// the frame is ready. It contains a bool to indicate if it needs to composite, the
94    /// `DocumentId` of the new frame and the `PainterId` of the associated painter.
95    NewWebRenderFrameReady(PainterId, DocumentId, bool),
96    /// Script or the Constellation is notifying the renderer that a Pipeline has finished
97    /// shutting down. The renderer will not discard the Pipeline until both report that
98    /// they have fully shut it down, to avoid recreating it due to any subsequent
99    /// messages.
100    PipelineExited(WebViewId, PipelineId, PipelineExitSource),
101    /// Inform WebRender of the existence of this pipeline.
102    SendInitialTransaction(WebViewId, WebRenderPipelineId),
103    /// Scroll the given node ([`ExternalScrollId`]) by the provided delta. This
104    /// will only adjust the node's scroll position and will *not* do panning in
105    /// the pinch zoom viewport.
106    ScrollNodeByDelta(
107        WebViewId,
108        WebRenderPipelineId,
109        LayoutVector2D,
110        ExternalScrollId,
111    ),
112    /// Scroll the WebView's viewport by the given delta. This will also do panning
113    /// in the pinch zoom viewport if possible and the remaining delta will be used
114    /// to scroll the root layer.
115    ScrollViewportByDelta(WebViewId, LayoutVector2D),
116    /// Update the rendering epoch of the given `Pipeline`.
117    UpdateEpoch {
118        /// The [`WebViewId`] that this display list belongs to.
119        webview_id: WebViewId,
120        /// The [`PipelineId`] of the `Pipeline` to update.
121        pipeline_id: PipelineId,
122        /// The new [`Epoch`] value.
123        epoch: Epoch,
124    },
125    /// Inform WebRender of a new display list for the given pipeline.
126    SendDisplayList {
127        /// The [`WebViewId`] that this display list belongs to.
128        webview_id: WebViewId,
129        /// A descriptor of this display list used to construct this display list from raw data.
130        display_list_descriptor: BuiltDisplayListDescriptor,
131        /// An [ipc::IpcBytesReceiver] used to send the raw data of the display list.
132        display_list_receiver: ipc::IpcBytesReceiver,
133    },
134    /// Ask the renderer to generate a frame for the current set of display lists
135    /// from the given `WebViewId`s that have been sent to the renderer.
136    GenerateFrame(Vec<WebViewId>),
137    /// Create a new image key. The result will be returned via the
138    /// provided channel sender.
139    GenerateImageKey(GenericSender<ImageKey>),
140    /// The same as the above but it will be forwarded to the pipeline instead
141    /// of send via a channel.
142    GenerateImageKeysForPipeline(PipelineId),
143    /// Perform a resource update operation.
144    UpdateImages(SmallVec<[ImageUpdate; 1]>),
145    /// Pause all pipeline display list processing for the given pipeline until the
146    /// following image updates have been received. This is used to ensure that canvas
147    /// elements have had a chance to update their rendering and send the image update to
148    /// the renderer before their associated display list is actually displayed.
149    DelayNewFrameForCanvas(PipelineId, Epoch, Vec<ImageKey>),
150
151    /// Generate a new batch of font keys which can be used to allocate
152    /// keys asynchronously.
153    GenerateFontKeys(
154        usize,
155        usize,
156        GenericSender<(Vec<FontKey>, Vec<FontInstanceKey>)>,
157        PainterId,
158    ),
159    /// Add a font with the given data and font key.
160    AddFont(FontKey, Arc<IpcSharedMemory>, u32),
161    /// Add a system font with the given font key and handle.
162    AddSystemFont(FontKey, NativeFontHandle),
163    /// Add an instance of a font with the given instance key.
164    AddFontInstance(
165        FontInstanceKey,
166        FontKey,
167        f32,
168        FontInstanceFlags,
169        Vec<FontVariation>,
170    ),
171    /// Remove the given font resources from our WebRender instance.
172    RemoveFonts(Vec<FontKey>, Vec<FontInstanceKey>),
173    /// Measure the current memory usage associated with the compositor.
174    /// The report must be sent on the provided channel once it's complete.
175    CollectMemoryReport(ReportsChan),
176    /// A top-level frame has parsed a viewport metatag and is sending the new constraints.
177    Viewport(WebViewId, ViewportDescription),
178    /// Let the compositor know that the given WebView is ready to have a screenshot taken
179    /// after the given pipeline's epochs have been rendered.
180    ScreenshotReadinessReponse(WebViewId, FxHashMap<PipelineId, Epoch>),
181    /// The candidate of largest-contentful-paint
182    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/// The subset of the pipeline that is needed for layer composition.
199#[derive(Clone, Deserialize, Serialize)]
200pub struct CompositionPipeline {
201    pub id: PipelineId,
202    pub webview_id: WebViewId,
203}
204
205/// A mechanism to send messages from ScriptThread to the parent process' WebRender instance.
206#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
207pub struct CrossProcessCompositorApi(GenericCallback<CompositorMsg>);
208
209impl CrossProcessCompositorApi {
210    /// Create a new [`CrossProcessCompositorApi`] struct.
211    pub fn new(callback: GenericCallback<CompositorMsg>) -> Self {
212        CrossProcessCompositorApi(callback)
213    }
214
215    /// Create a new [`CrossProcessCompositorApi`] struct that does not have a listener on the other
216    /// end to use for unit testing.
217    pub fn dummy() -> Self {
218        Self::dummy_with_callback(None)
219    }
220
221    /// Create a new [`CrossProcessCompositorApi`] struct for unit testing with an optional callback
222    /// that can respond to compositor messages.
223    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    /// Inform WebRender of the existence of this pipeline.
238    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    /// Scroll the given node ([`ExternalScrollId`]) by the provided delta. This
248    /// will only adjust the node's scroll position and will *not* do panning in
249    /// the pinch zoom viewport.
250    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    /// Scroll the WebView's viewport by the given delta. This will also do panning
268    /// in the pinch zoom viewport if possible and the remaining delta will be used
269    /// to scroll the root layer.
270    ///
271    /// Note the value provided here is in `DeviceIndependentPixels` and will first be
272    /// converted to `DevicePixels` by the renderer.
273    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    /// Inform the renderer that the rendering epoch has advanced. This typically happens after
298    /// a new display list is sent and/or canvas and animated images are updated.
299    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    /// Inform WebRender of a new display list for the given pipeline.
310    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    /// Send the largest contentful paint candidate to the compositor.
344    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    /// Ask the Servo renderer to generate a new frame after having new display lists.
362    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    /// Create a new image key. Blocks until the key is available.
369    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    /// Sends a message to the compositor for creating new image keys.
376    /// The compositor will then send a batch of keys over the constellation to the script_thread
377    /// and the appropriate pipeline.
378    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    /// Perform an image resource update operation.
411    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
489/// This trait is used as a bridge between the different GL clients
490/// in Servo that handles WebRender ExternalImages and the WebRender
491/// ExternalImageHandler API.
492//
493/// This trait is used to notify lock/unlock messages and get the
494/// required info that WR needs.
495pub trait WebRenderExternalImageApi {
496    fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
497    fn unlock(&mut self, id: u64);
498}
499
500/// Type of WebRender External Image Handler.
501pub enum WebRenderImageHandlerType {
502    WebGl,
503    Media,
504    WebGpu,
505}
506
507/// List of WebRender external images to be shared among all external image
508/// consumers (WebGL, Media, WebGPU).
509/// It ensures that external image identifiers are unique.
510#[derive(Default)]
511pub struct WebRenderExternalImageRegistry {
512    /// Map of all generated external images.
513    external_images: FxHashMap<ExternalImageId, WebRenderImageHandlerType>,
514    /// Id generator for the next external image identifier.
515    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
535/// WebRender External Image Handler implementation.
536pub struct WebRenderExternalImageHandlers {
537    /// WebGL handler.
538    webgl_handler: Option<Box<dyn WebRenderExternalImageApi>>,
539    /// Media player handler.
540    media_handler: Option<Box<dyn WebRenderExternalImageApi>>,
541    /// WebGPU handler.
542    webgpu_handler: Option<Box<dyn WebRenderExternalImageApi>>,
543    /// WebRender external images.
544    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    /// Lock the external image. Then, WR could start to read the
576    /// image content.
577    /// The WR client should not change the image content until the
578    /// unlock() call.
579    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    /// Unlock the external image. The WR should not read the image
623    /// content after this call.
624    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)]
640/// Serializable image updates that must be performed by WebRender.
641pub enum ImageUpdate {
642    /// Register a new image.
643    AddImage(ImageKey, ImageDescriptor, SerializableImageData),
644    /// Delete a previously registered image registration.
645    DeleteImage(ImageKey),
646    /// Update an existing image registration.
647    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)]
675/// Serialized `ImageData`. It contains IPC byte channel receiver to prevent from loading bytes too
676/// slow.
677pub enum SerializableImageData {
678    /// A simple series of bytes, provided by the embedding and owned by WebRender.
679    /// The format is stored out-of-band, currently in ImageDescriptor.
680    Raw(IpcSharedMemory),
681    /// An image owned by the embedding, and referenced by WebRender. This may
682    /// take the form of a texture or a heap-allocated buffer.
683    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
695/// A trait that exposes the embedding layer's `WebView` to the Servo renderer.
696/// This is to prevent a dependency cycle between the renderer and the embedding
697/// layer.
698pub 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/// What entity is reporting that a `Pipeline` has exited. Only when all have
705/// done this will the renderer discard its details.
706#[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}