paint_api/
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 `paint` crate, which helps to break dependency cycles.
6
7use std::collections::HashMap;
8use std::fmt::{Debug, Error, Formatter};
9
10use base::Epoch;
11use base::id::{PainterId, PipelineId, WebViewId};
12use crossbeam_channel::Sender;
13use embedder_traits::{AnimationState, EventLoopWaker};
14use log::warn;
15use malloc_size_of_derive::MallocSizeOf;
16use parking_lot::RwLock;
17use rustc_hash::FxHashMap;
18use smallvec::SmallVec;
19use strum::IntoStaticStr;
20use surfman::{Adapter, Connection};
21use webrender_api::{DocumentId, FontVariation};
22
23pub mod display_list;
24pub mod largest_contentful_paint_candidate;
25pub mod rendering_context;
26pub mod viewport_description;
27
28use std::sync::{Arc, Mutex};
29
30use base::generic_channel::{self, GenericCallback, GenericSender, GenericSharedMemory};
31use bitflags::bitflags;
32use display_list::PaintDisplayListInfo;
33use embedder_traits::ScreenGeometry;
34use euclid::default::Size2D as UntypedSize2D;
35use ipc_channel::ipc::{self};
36use profile_traits::mem::{OpaqueSender, ReportsChan};
37use serde::{Deserialize, Serialize};
38pub use webrender_api::ExternalImageSource;
39use webrender_api::units::{LayoutVector2D, TexelRect};
40use webrender_api::{
41    BuiltDisplayList, BuiltDisplayListDescriptor, ExternalImage, ExternalImageData,
42    ExternalImageHandler, ExternalImageId, ExternalScrollId, FontInstanceFlags, FontInstanceKey,
43    FontKey, ImageData, ImageDescriptor, ImageKey, NativeFontHandle,
44    PipelineId as WebRenderPipelineId,
45};
46
47use crate::largest_contentful_paint_candidate::LCPCandidate;
48use crate::viewport_description::ViewportDescription;
49
50/// Sends messages to `Paint`.
51#[derive(Clone)]
52pub struct PaintProxy {
53    pub sender: Sender<Result<PaintMessage, ipc_channel::Error>>,
54    /// Access to [`Self::sender`] that is possible to send across an IPC
55    /// channel. These messages are routed via the router thread to
56    /// [`Self::sender`].
57    pub cross_process_paint_api: CrossProcessPaintApi,
58    pub event_loop_waker: Box<dyn EventLoopWaker>,
59}
60
61impl OpaqueSender<PaintMessage> for PaintProxy {
62    fn send(&self, message: PaintMessage) {
63        PaintProxy::send(self, message)
64    }
65}
66
67impl PaintProxy {
68    pub fn send(&self, msg: PaintMessage) {
69        self.route_msg(Ok(msg))
70    }
71
72    /// Helper method to route a deserialized IPC message to the receiver.
73    ///
74    /// This method is a temporary solution, and will be removed when migrating
75    /// to `GenericChannel`.
76    pub fn route_msg(&self, msg: Result<PaintMessage, ipc_channel::Error>) {
77        if let Err(err) = self.sender.send(msg) {
78            warn!("Failed to send response ({:?}).", err);
79        }
80        self.event_loop_waker.wake();
81    }
82}
83
84/// Messages from (or via) the constellation thread to `Paint`.
85#[derive(Deserialize, IntoStaticStr, Serialize)]
86pub enum PaintMessage {
87    /// Alerts `Paint` that the given pipeline has changed whether it is running animations.
88    ChangeRunningAnimationsState(WebViewId, PipelineId, AnimationState),
89    /// Updates the frame tree for the given webview.
90    SetFrameTreeForWebView(WebViewId, SendableFrameTree),
91    /// Set whether to use less resources by stopping animations.
92    SetThrottled(WebViewId, PipelineId, bool),
93    /// WebRender has produced a new frame. This message informs `Paint` that
94    /// the frame is ready. It contains a bool to indicate if it needs to composite, the
95    /// `DocumentId` of the new frame and the `PainterId` of the associated painter.
96    NewWebRenderFrameReady(PainterId, DocumentId, bool),
97    /// Script or the Constellation is notifying the renderer that a Pipeline has finished
98    /// shutting down. The renderer will not discard the Pipeline until both report that
99    /// they have fully shut it down, to avoid recreating it due to any subsequent
100    /// messages.
101    PipelineExited(WebViewId, PipelineId, PipelineExitSource),
102    /// Inform WebRender of the existence of this pipeline.
103    SendInitialTransaction(WebViewId, WebRenderPipelineId),
104    /// Scroll the given node ([`ExternalScrollId`]) by the provided delta. This
105    /// will only adjust the node's scroll position and will *not* do panning in
106    /// the pinch zoom viewport.
107    ScrollNodeByDelta(
108        WebViewId,
109        WebRenderPipelineId,
110        LayoutVector2D,
111        ExternalScrollId,
112    ),
113    /// Scroll the WebView's viewport by the given delta. This will also do panning
114    /// in the pinch zoom viewport if possible and the remaining delta will be used
115    /// to scroll the root layer.
116    ScrollViewportByDelta(WebViewId, LayoutVector2D),
117    /// Update the rendering epoch of the given `Pipeline`.
118    UpdateEpoch {
119        /// The [`WebViewId`] that this display list belongs to.
120        webview_id: WebViewId,
121        /// The [`PipelineId`] of the `Pipeline` to update.
122        pipeline_id: PipelineId,
123        /// The new [`Epoch`] value.
124        epoch: Epoch,
125    },
126    /// Inform WebRender of a new display list for the given pipeline.
127    SendDisplayList {
128        /// The [`WebViewId`] that this display list belongs to.
129        webview_id: WebViewId,
130        /// A descriptor of this display list used to construct this display list from raw data.
131        display_list_descriptor: BuiltDisplayListDescriptor,
132        /// An [ipc::IpcBytesReceiver] used to send the raw data of the display list.
133        display_list_receiver: ipc::IpcBytesReceiver,
134    },
135    /// Ask the renderer to generate a frame for the current set of display lists
136    /// from the given `PainterId`s that have been sent to the renderer.
137    GenerateFrame(Vec<PainterId>),
138    /// Create a new image key. The result will be returned via the
139    /// provided channel sender.
140    GenerateImageKey(WebViewId, GenericSender<ImageKey>),
141    /// The same as the above but it will be forwarded to the pipeline instead
142    /// of send via a channel.
143    GenerateImageKeysForPipeline(WebViewId, PipelineId),
144    /// Perform a resource update operation.
145    UpdateImages(PainterId, SmallVec<[ImageUpdate; 1]>),
146    /// Pause all pipeline display list processing for the given pipeline until the
147    /// following image updates have been received. This is used to ensure that canvas
148    /// elements have had a chance to update their rendering and send the image update to
149    /// the renderer before their associated display list is actually displayed.
150    DelayNewFrameForCanvas(WebViewId, PipelineId, Epoch, Vec<ImageKey>),
151
152    /// Generate a new batch of font keys which can be used to allocate
153    /// keys asynchronously.
154    GenerateFontKeys(
155        usize,
156        usize,
157        GenericSender<(Vec<FontKey>, Vec<FontInstanceKey>)>,
158        PainterId,
159    ),
160    /// Add a font with the given data and font key.
161    AddFont(PainterId, FontKey, Arc<GenericSharedMemory>, u32),
162    /// Add a system font with the given font key and handle.
163    AddSystemFont(PainterId, FontKey, NativeFontHandle),
164    /// Add an instance of a font with the given instance key.
165    AddFontInstance(
166        PainterId,
167        FontInstanceKey,
168        FontKey,
169        f32,
170        FontInstanceFlags,
171        Vec<FontVariation>,
172    ),
173    /// Remove the given font resources from our WebRender instance.
174    RemoveFonts(PainterId, Vec<FontKey>, Vec<FontInstanceKey>),
175    /// Measure the current memory usage associated with `Paint`.
176    /// The report must be sent on the provided channel once it's complete.
177    CollectMemoryReport(ReportsChan),
178    /// A top-level frame has parsed a viewport metatag and is sending the new constraints.
179    Viewport(WebViewId, ViewportDescription),
180    /// Let `Paint` know that the given WebView is ready to have a screenshot taken
181    /// after the given pipeline's epochs have been rendered.
182    ScreenshotReadinessReponse(WebViewId, FxHashMap<PipelineId, Epoch>),
183    /// The candidate of largest-contentful-paint
184    SendLCPCandidate(LCPCandidate, WebViewId, PipelineId, Epoch),
185}
186
187impl Debug for PaintMessage {
188    fn fmt(&self, formatter: &mut Formatter) -> Result<(), Error> {
189        let string: &'static str = self.into();
190        write!(formatter, "{string}")
191    }
192}
193
194#[derive(Deserialize, Serialize)]
195pub struct SendableFrameTree {
196    pub pipeline: CompositionPipeline,
197    pub children: Vec<SendableFrameTree>,
198}
199
200/// The subset of the pipeline that is needed for layer composition.
201#[derive(Clone, Deserialize, Serialize)]
202pub struct CompositionPipeline {
203    pub id: PipelineId,
204    pub webview_id: WebViewId,
205}
206
207/// A mechanism to send messages from ScriptThread to the parent process' WebRender instance.
208#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
209pub struct CrossProcessPaintApi(GenericCallback<PaintMessage>);
210
211impl CrossProcessPaintApi {
212    /// Create a new [`CrossProcessPaintApi`] struct.
213    pub fn new(callback: GenericCallback<PaintMessage>) -> Self {
214        CrossProcessPaintApi(callback)
215    }
216
217    /// Create a new [`CrossProcessPaintApi`] struct that does not have a listener on the other
218    /// end to use for unit testing.
219    pub fn dummy() -> Self {
220        Self::dummy_with_callback(None)
221    }
222
223    /// Create a new [`CrossProcessPaintApi`] struct for unit testing with an optional callback
224    /// that can respond to `PaintMessage`s.
225    pub fn dummy_with_callback(
226        callback: Option<Box<dyn Fn(PaintMessage) + Send + 'static>>,
227    ) -> Self {
228        let callback = GenericCallback::new(move |msg| {
229            if let Some(ref handler) = callback {
230                if let Ok(paint_message) = msg {
231                    handler(paint_message);
232                }
233            }
234        })
235        .unwrap();
236        Self(callback)
237    }
238
239    /// Inform WebRender of the existence of this pipeline.
240    pub fn send_initial_transaction(&self, webview_id: WebViewId, pipeline: WebRenderPipelineId) {
241        if let Err(e) = self
242            .0
243            .send(PaintMessage::SendInitialTransaction(webview_id, pipeline))
244        {
245            warn!("Error sending initial transaction: {}", e);
246        }
247    }
248
249    /// Scroll the given node ([`ExternalScrollId`]) by the provided delta. This
250    /// will only adjust the node's scroll position and will *not* do panning in
251    /// the pinch zoom viewport.
252    pub fn scroll_node_by_delta(
253        &self,
254        webview_id: WebViewId,
255        pipeline_id: WebRenderPipelineId,
256        delta: LayoutVector2D,
257        scroll_id: ExternalScrollId,
258    ) {
259        if let Err(error) = self.0.send(PaintMessage::ScrollNodeByDelta(
260            webview_id,
261            pipeline_id,
262            delta,
263            scroll_id,
264        )) {
265            warn!("Error scrolling node: {error}");
266        }
267    }
268
269    /// Scroll the WebView's viewport by the given delta. This will also do panning
270    /// in the pinch zoom viewport if possible and the remaining delta will be used
271    /// to scroll the root layer.
272    ///
273    /// Note the value provided here is in `DeviceIndependentPixels` and will first be
274    /// converted to `DevicePixels` by the renderer.
275    pub fn scroll_viewport_by_delta(&self, webview_id: WebViewId, delta: LayoutVector2D) {
276        if let Err(error) = self
277            .0
278            .send(PaintMessage::ScrollViewportByDelta(webview_id, delta))
279        {
280            warn!("Error scroll viewport: {error}");
281        }
282    }
283
284    pub fn delay_new_frame_for_canvas(
285        &self,
286        webview_id: WebViewId,
287        pipeline_id: PipelineId,
288        canvas_epoch: Epoch,
289        image_keys: Vec<ImageKey>,
290    ) {
291        if let Err(error) = self.0.send(PaintMessage::DelayNewFrameForCanvas(
292            webview_id,
293            pipeline_id,
294            canvas_epoch,
295            image_keys,
296        )) {
297            warn!("Error delaying frames for canvas image updates {error:?}");
298        }
299    }
300
301    /// Inform the renderer that the rendering epoch has advanced. This typically happens after
302    /// a new display list is sent and/or canvas and animated images are updated.
303    pub fn update_epoch(&self, webview_id: WebViewId, pipeline_id: PipelineId, epoch: Epoch) {
304        if let Err(error) = self.0.send(PaintMessage::UpdateEpoch {
305            webview_id,
306            pipeline_id,
307            epoch,
308        }) {
309            warn!("Error updating epoch for pipeline: {error:?}");
310        }
311    }
312
313    /// Inform WebRender of a new display list for the given pipeline.
314    pub fn send_display_list(
315        &self,
316        webview_id: WebViewId,
317        display_list_info: &PaintDisplayListInfo,
318        list: BuiltDisplayList,
319    ) {
320        let (display_list_data, display_list_descriptor) = list.into_data();
321        let (display_list_sender, display_list_receiver) = ipc::bytes_channel().unwrap();
322        if let Err(e) = self.0.send(PaintMessage::SendDisplayList {
323            webview_id,
324            display_list_descriptor,
325            display_list_receiver,
326        }) {
327            warn!("Error sending display list: {}", e);
328        }
329
330        let display_list_info_serialized =
331            bincode::serialize(&display_list_info).unwrap_or_default();
332        if let Err(error) = display_list_sender.send(&display_list_info_serialized) {
333            warn!("Error sending display list info: {error}");
334        }
335
336        if let Err(error) = display_list_sender.send(&display_list_data.items_data) {
337            warn!("Error sending display list items: {error}");
338        }
339        if let Err(error) = display_list_sender.send(&display_list_data.cache_data) {
340            warn!("Error sending display list cache data: {error}");
341        }
342        if let Err(error) = display_list_sender.send(&display_list_data.spatial_tree) {
343            warn!("Error sending display spatial tree: {error}");
344        }
345    }
346
347    /// Send the largest contentful paint candidate to `Paint`.
348    pub fn send_lcp_candidate(
349        &self,
350        lcp_candidate: LCPCandidate,
351        webview_id: WebViewId,
352        pipeline_id: PipelineId,
353        epoch: Epoch,
354    ) {
355        if let Err(error) = self.0.send(PaintMessage::SendLCPCandidate(
356            lcp_candidate,
357            webview_id,
358            pipeline_id,
359            epoch,
360        )) {
361            warn!("Error sending LCPCandidate: {error}");
362        }
363    }
364
365    /// Ask the Servo renderer to generate a new frame after having new display lists.
366    pub fn generate_frame(&self, painter_ids: Vec<PainterId>) {
367        if let Err(error) = self.0.send(PaintMessage::GenerateFrame(painter_ids)) {
368            warn!("Error generating frame: {error}");
369        }
370    }
371
372    /// Create a new image key. Blocks until the key is available.
373    pub fn generate_image_key_blocking(&self, webview_id: WebViewId) -> Option<ImageKey> {
374        let (sender, receiver) = generic_channel::channel().unwrap();
375        self.0
376            .send(PaintMessage::GenerateImageKey(webview_id, sender))
377            .ok()?;
378        receiver.recv().ok()
379    }
380
381    /// Sends a message to `Paint` for creating new image keys.
382    /// `Paint` will then send a batch of keys over the constellation to the script_thread
383    /// and the appropriate pipeline.
384    pub fn generate_image_key_async(&self, webview_id: WebViewId, pipeline_id: PipelineId) {
385        if let Err(e) = self.0.send(PaintMessage::GenerateImageKeysForPipeline(
386            webview_id,
387            pipeline_id,
388        )) {
389            warn!("Could not send image keys to Paint {}", e);
390        }
391    }
392
393    pub fn add_image(
394        &self,
395        key: ImageKey,
396        descriptor: ImageDescriptor,
397        data: SerializableImageData,
398    ) {
399        self.update_images(
400            key.into(),
401            [ImageUpdate::AddImage(key, descriptor, data)].into(),
402        );
403    }
404
405    pub fn update_image(
406        &self,
407        key: ImageKey,
408        descriptor: ImageDescriptor,
409        data: SerializableImageData,
410        epoch: Option<Epoch>,
411    ) {
412        self.update_images(
413            key.into(),
414            [ImageUpdate::UpdateImage(key, descriptor, data, epoch)].into(),
415        );
416    }
417
418    pub fn delete_image(&self, key: ImageKey) {
419        self.update_images(key.into(), [ImageUpdate::DeleteImage(key)].into());
420    }
421
422    /// Perform an image resource update operation.
423    pub fn update_images(&self, painter_id: PainterId, updates: SmallVec<[ImageUpdate; 1]>) {
424        if let Err(e) = self.0.send(PaintMessage::UpdateImages(painter_id, updates)) {
425            warn!("error sending image updates: {}", e);
426        }
427    }
428
429    pub fn remove_unused_font_resources(
430        &self,
431        painter_id: PainterId,
432        keys: Vec<FontKey>,
433        instance_keys: Vec<FontInstanceKey>,
434    ) {
435        if keys.is_empty() && instance_keys.is_empty() {
436            return;
437        }
438        let _ = self
439            .0
440            .send(PaintMessage::RemoveFonts(painter_id, keys, instance_keys));
441    }
442
443    pub fn add_font_instance(
444        &self,
445        font_instance_key: FontInstanceKey,
446        font_key: FontKey,
447        size: f32,
448        flags: FontInstanceFlags,
449        variations: Vec<FontVariation>,
450    ) {
451        let _x = self.0.send(PaintMessage::AddFontInstance(
452            font_key.into(),
453            font_instance_key,
454            font_key,
455            size,
456            flags,
457            variations,
458        ));
459    }
460
461    pub fn add_font(&self, font_key: FontKey, data: Arc<GenericSharedMemory>, index: u32) {
462        let _ = self.0.send(PaintMessage::AddFont(
463            font_key.into(),
464            font_key,
465            data,
466            index,
467        ));
468    }
469
470    pub fn add_system_font(&self, font_key: FontKey, handle: NativeFontHandle) {
471        let _ = self.0.send(PaintMessage::AddSystemFont(
472            font_key.into(),
473            font_key,
474            handle,
475        ));
476    }
477
478    pub fn fetch_font_keys(
479        &self,
480        number_of_font_keys: usize,
481        number_of_font_instance_keys: usize,
482        painter_id: PainterId,
483    ) -> (Vec<FontKey>, Vec<FontInstanceKey>) {
484        let (sender, receiver) = generic_channel::channel().expect("Could not create IPC channel");
485        let _ = self.0.send(PaintMessage::GenerateFontKeys(
486            number_of_font_keys,
487            number_of_font_instance_keys,
488            sender,
489            painter_id,
490        ));
491        receiver.recv().unwrap()
492    }
493
494    pub fn viewport(&self, webview_id: WebViewId, description: ViewportDescription) {
495        let _ = self.0.send(PaintMessage::Viewport(webview_id, description));
496    }
497
498    pub fn pipeline_exited(
499        &self,
500        webview_id: WebViewId,
501        pipeline_id: PipelineId,
502        source: PipelineExitSource,
503    ) {
504        let _ = self.0.send(PaintMessage::PipelineExited(
505            webview_id,
506            pipeline_id,
507            source,
508        ));
509    }
510}
511
512#[derive(Clone)]
513pub struct PainterSurfmanDetails {
514    pub connection: Connection,
515    pub adapter: Adapter,
516}
517
518#[derive(Clone, Default)]
519pub struct PainterSurfmanDetailsMap(Arc<Mutex<HashMap<PainterId, PainterSurfmanDetails>>>);
520
521impl PainterSurfmanDetailsMap {
522    pub fn get(&self, painter_id: PainterId) -> Option<PainterSurfmanDetails> {
523        let map = self.0.lock().expect("poisoned");
524        map.get(&painter_id).cloned()
525    }
526
527    pub fn insert(&self, painter_id: PainterId, details: PainterSurfmanDetails) {
528        let mut map = self.0.lock().expect("poisoned");
529        let existing = map.insert(painter_id, details);
530        assert!(existing.is_none())
531    }
532
533    pub fn remove(&self, painter_id: PainterId) {
534        let mut map = self.0.lock().expect("poisoned");
535        let details = map.remove(&painter_id);
536        assert!(details.is_some());
537    }
538}
539
540/// This trait is used as a bridge between the different GL clients
541/// in Servo that handles WebRender ExternalImages and the WebRender
542/// ExternalImageHandler API.
543//
544/// This trait is used to notify lock/unlock messages and get the
545/// required info that WR needs.
546pub trait WebRenderExternalImageApi {
547    fn lock(&mut self, id: u64) -> (ExternalImageSource<'_>, UntypedSize2D<i32>);
548    fn unlock(&mut self, id: u64);
549}
550
551/// Type of WebRender External Image Handler.
552#[derive(Clone, Copy)]
553pub enum WebRenderImageHandlerType {
554    WebGl,
555    Media,
556    WebGpu,
557}
558
559/// List of WebRender external images to be shared among all external image
560/// consumers (WebGL, Media, WebGPU).
561/// It ensures that external image identifiers are unique.
562#[derive(Default)]
563struct WebRenderExternalImageIdManagerInner {
564    /// Map of all generated external images.
565    external_images: FxHashMap<ExternalImageId, WebRenderImageHandlerType>,
566    /// Id generator for the next external image identifier.
567    next_image_id: u64,
568}
569
570#[derive(Default, Clone)]
571pub struct WebRenderExternalImageIdManager(Arc<RwLock<WebRenderExternalImageIdManagerInner>>);
572
573impl WebRenderExternalImageIdManager {
574    pub fn next_id(&mut self, handler_type: WebRenderImageHandlerType) -> ExternalImageId {
575        let mut inner = self.0.write();
576        inner.next_image_id += 1;
577        let key = ExternalImageId(inner.next_image_id);
578        inner.external_images.insert(key, handler_type);
579        key
580    }
581
582    pub fn remove(&mut self, key: &ExternalImageId) {
583        self.0.write().external_images.remove(key);
584    }
585
586    pub fn get(&self, key: &ExternalImageId) -> Option<WebRenderImageHandlerType> {
587        self.0.read().external_images.get(key).cloned()
588    }
589}
590
591/// WebRender External Image Handler implementation.
592pub struct WebRenderExternalImageHandlers {
593    /// WebGL handler.
594    webgl_handler: Option<Box<dyn WebRenderExternalImageApi>>,
595    /// Media player handler.
596    media_handler: Option<Box<dyn WebRenderExternalImageApi>>,
597    /// WebGPU handler.
598    webgpu_handler: Option<Box<dyn WebRenderExternalImageApi>>,
599    /// A [`WebRenderExternalImageIdManager`] responsible for creating new [`ExternalImageId`]s.
600    /// This is shared with the WebGL, WebGPU, and hardware-accelerated media threads and
601    /// all other instances of [`WebRenderExternalImageHandlers`] -- one per WebRender instance.
602    id_manager: WebRenderExternalImageIdManager,
603}
604
605impl WebRenderExternalImageHandlers {
606    pub fn new(id_manager: WebRenderExternalImageIdManager) -> Self {
607        Self {
608            webgl_handler: Default::default(),
609            media_handler: Default::default(),
610            webgpu_handler: Default::default(),
611            id_manager,
612        }
613    }
614
615    pub fn id_manager(&self) -> WebRenderExternalImageIdManager {
616        self.id_manager.clone()
617    }
618
619    pub fn set_handler(
620        &mut self,
621        handler: Box<dyn WebRenderExternalImageApi>,
622        handler_type: WebRenderImageHandlerType,
623    ) {
624        match handler_type {
625            WebRenderImageHandlerType::WebGl => self.webgl_handler = Some(handler),
626            WebRenderImageHandlerType::Media => self.media_handler = Some(handler),
627            WebRenderImageHandlerType::WebGpu => self.webgpu_handler = Some(handler),
628        }
629    }
630}
631
632impl ExternalImageHandler for WebRenderExternalImageHandlers {
633    /// Lock the external image. Then, WR could start to read the
634    /// image content.
635    /// The WR client should not change the image content until the
636    /// unlock() call.
637    fn lock(
638        &mut self,
639        key: ExternalImageId,
640        _channel_index: u8,
641        _is_composited: bool,
642    ) -> ExternalImage<'_> {
643        let handler_type = self
644            .id_manager()
645            .get(&key)
646            .expect("Tried to get unknown external image");
647        match handler_type {
648            WebRenderImageHandlerType::WebGl => {
649                let (source, size) = self.webgl_handler.as_mut().unwrap().lock(key.0);
650                let texture_id = match source {
651                    ExternalImageSource::NativeTexture(b) => b,
652                    _ => panic!("Wrong type"),
653                };
654                ExternalImage {
655                    uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
656                    source: ExternalImageSource::NativeTexture(texture_id),
657                }
658            },
659            WebRenderImageHandlerType::Media => {
660                let (source, size) = self.media_handler.as_mut().unwrap().lock(key.0);
661                let texture_id = match source {
662                    ExternalImageSource::NativeTexture(b) => b,
663                    _ => panic!("Wrong type"),
664                };
665                ExternalImage {
666                    uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
667                    source: ExternalImageSource::NativeTexture(texture_id),
668                }
669            },
670            WebRenderImageHandlerType::WebGpu => {
671                let (source, size) = self.webgpu_handler.as_mut().unwrap().lock(key.0);
672                ExternalImage {
673                    uv: TexelRect::new(0.0, size.height as f32, size.width as f32, 0.0),
674                    source,
675                }
676            },
677        }
678    }
679
680    /// Unlock the external image. The WR should not read the image
681    /// content after this call.
682    fn unlock(&mut self, key: ExternalImageId, _channel_index: u8) {
683        let handler_type = self
684            .id_manager()
685            .get(&key)
686            .expect("Tried to get unknown external image");
687        match handler_type {
688            WebRenderImageHandlerType::WebGl => self.webgl_handler.as_mut().unwrap().unlock(key.0),
689            WebRenderImageHandlerType::Media => self.media_handler.as_mut().unwrap().unlock(key.0),
690            WebRenderImageHandlerType::WebGpu => {
691                self.webgpu_handler.as_mut().unwrap().unlock(key.0)
692            },
693        };
694    }
695}
696
697#[derive(Deserialize, Serialize)]
698/// Serializable image updates that must be performed by WebRender.
699pub enum ImageUpdate {
700    /// Register a new image.
701    AddImage(ImageKey, ImageDescriptor, SerializableImageData),
702    /// Delete a previously registered image registration.
703    DeleteImage(ImageKey),
704    /// Update an existing image registration.
705    UpdateImage(
706        ImageKey,
707        ImageDescriptor,
708        SerializableImageData,
709        Option<Epoch>,
710    ),
711}
712
713impl Debug for ImageUpdate {
714    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
715        match self {
716            Self::AddImage(image_key, image_desc, _) => f
717                .debug_tuple("AddImage")
718                .field(image_key)
719                .field(image_desc)
720                .finish(),
721            Self::DeleteImage(image_key) => f.debug_tuple("DeleteImage").field(image_key).finish(),
722            Self::UpdateImage(image_key, image_desc, _, epoch) => f
723                .debug_tuple("UpdateImage")
724                .field(image_key)
725                .field(image_desc)
726                .field(epoch)
727                .finish(),
728        }
729    }
730}
731
732#[derive(Debug, Deserialize, Serialize)]
733/// Serialized `ImageData`. It contains IPC byte channel receiver to prevent from loading bytes too
734/// slow.
735pub enum SerializableImageData {
736    /// A simple series of bytes, provided by the embedding and owned by WebRender.
737    /// The format is stored out-of-band, currently in ImageDescriptor.
738    Raw(GenericSharedMemory),
739    /// An image owned by the embedding, and referenced by WebRender. This may
740    /// take the form of a texture or a heap-allocated buffer.
741    External(ExternalImageData),
742}
743
744impl From<SerializableImageData> for ImageData {
745    fn from(value: SerializableImageData) -> Self {
746        match value {
747            SerializableImageData::Raw(shared_memory) => ImageData::new(shared_memory.to_vec()),
748            SerializableImageData::External(image) => ImageData::External(image),
749        }
750    }
751}
752
753/// A trait that exposes the embedding layer's `WebView` to the Servo renderer.
754/// This is to prevent a dependency cycle between the renderer and the embedding
755/// layer.
756pub trait WebViewTrait {
757    fn id(&self) -> WebViewId;
758    fn screen_geometry(&self) -> Option<ScreenGeometry>;
759    fn set_animating(&self, new_value: bool);
760}
761
762/// What entity is reporting that a `Pipeline` has exited. Only when all have
763/// done this will the renderer discard its details.
764#[derive(Clone, Copy, Default, Deserialize, PartialEq, Serialize)]
765pub struct PipelineExitSource(u8);
766
767bitflags! {
768    impl PipelineExitSource: u8 {
769        const Script = 1 << 0;
770        const Constellation = 1 << 1;
771    }
772}