1use std::sync::Arc;
6
7use base::id::PipelineId;
8use compositing_traits::CrossProcessCompositorApi;
9use ipc_channel::ipc::IpcSender;
10use log::debug;
11use malloc_size_of::MallocSizeOfOps;
12use malloc_size_of_derive::MallocSizeOf;
13use pixels::{CorsStatus, ImageMetadata, RasterImage};
14use profile_traits::mem::Report;
15use serde::{Deserialize, Serialize};
16use servo_url::{ImmutableOrigin, ServoUrl};
17use webrender_api::ImageKey;
18use webrender_api::units::DeviceIntSize;
19
20use crate::FetchResponseMsg;
21use crate::request::CorsSettings;
22
23pub type VectorImageId = PendingImageId;
28
29#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
33pub enum Image {
34 Raster(#[conditional_malloc_size_of] Arc<RasterImage>),
35 Vector(VectorImage),
36}
37
38#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
39pub struct VectorImage {
40 pub id: VectorImageId,
41 pub metadata: ImageMetadata,
42 pub cors_status: CorsStatus,
43}
44
45impl Image {
46 pub fn metadata(&self) -> ImageMetadata {
47 match self {
48 Image::Vector(image, ..) => image.metadata,
49 Image::Raster(image) => image.metadata,
50 }
51 }
52
53 pub fn cors_status(&self) -> CorsStatus {
54 match self {
55 Image::Vector(image) => image.cors_status,
56 Image::Raster(image) => image.cors_status,
57 }
58 }
59
60 pub fn as_raster_image(&self) -> Option<Arc<RasterImage>> {
61 match self {
62 Image::Raster(image) => Some(image.clone()),
63 Image::Vector(..) => None,
64 }
65 }
66}
67
68#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
70pub enum ImageOrMetadataAvailable {
71 ImageAvailable {
72 image: Image,
73 url: ServoUrl,
74 is_placeholder: bool,
75 },
76 MetadataAvailable(ImageMetadata, PendingImageId),
77}
78
79#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
84pub struct ImageLoadListener {
85 pipeline_id: PipelineId,
86 pub id: PendingImageId,
87 sender: IpcSender<ImageCacheResponseMessage>,
88}
89
90impl ImageLoadListener {
91 pub fn new(
92 sender: IpcSender<ImageCacheResponseMessage>,
93 pipeline_id: PipelineId,
94 id: PendingImageId,
95 ) -> ImageLoadListener {
96 ImageLoadListener {
97 pipeline_id,
98 sender,
99 id,
100 }
101 }
102
103 pub fn respond(&self, response: ImageResponse) {
104 debug!("Notifying listener");
105 let _ = self
109 .sender
110 .send(ImageCacheResponseMessage::NotifyPendingImageLoadStatus(
111 PendingImageResponse {
112 pipeline_id: self.pipeline_id,
113 response,
114 id: self.id,
115 },
116 ));
117 }
118}
119
120#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
122pub enum ImageResponse {
123 Loaded(Image, ServoUrl),
125 MetadataLoaded(ImageMetadata),
127 PlaceholderLoaded(#[conditional_malloc_size_of] Arc<RasterImage>, ServoUrl),
129 None,
131}
132
133#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
135pub struct PendingImageId(pub u64);
136
137#[derive(Clone, Debug, Deserialize, Serialize)]
138pub struct PendingImageResponse {
139 pub pipeline_id: PipelineId,
140 pub response: ImageResponse,
141 pub id: PendingImageId,
142}
143
144#[derive(Clone, Debug, Deserialize, Serialize)]
145pub struct RasterizationCompleteResponse {
146 pub pipeline_id: PipelineId,
147 pub image_id: PendingImageId,
148 pub requested_size: DeviceIntSize,
149}
150
151#[derive(Clone, Debug, Deserialize, Serialize)]
152pub enum ImageCacheResponseMessage {
153 NotifyPendingImageLoadStatus(PendingImageResponse),
154 VectorImageRasterizationComplete(RasterizationCompleteResponse),
155}
156
157#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
158pub enum UsePlaceholder {
159 No,
160 Yes,
161}
162
163pub enum ImageCacheResult {
168 Available(ImageOrMetadataAvailable),
169 LoadError,
170 Pending(PendingImageId),
171 ReadyForRequest(PendingImageId),
172}
173
174pub trait ImageCache: Sync + Send {
175 fn new(compositor_api: CrossProcessCompositorApi, rippy_data: Vec<u8>) -> Self
176 where
177 Self: Sized;
178
179 fn memory_report(&self, prefix: &str, ops: &mut MallocSizeOfOps) -> Report;
180
181 fn get_image(
183 &self,
184 url: ServoUrl,
185 origin: ImmutableOrigin,
186 cors_setting: Option<CorsSettings>,
187 ) -> Option<Image>;
188
189 fn get_cached_image_status(
190 &self,
191 url: ServoUrl,
192 origin: ImmutableOrigin,
193 cors_setting: Option<CorsSettings>,
194 use_placeholder: UsePlaceholder,
195 ) -> ImageCacheResult;
196
197 fn rasterize_vector_image(
202 &self,
203 image_id: VectorImageId,
204 size: DeviceIntSize,
205 ) -> Option<RasterImage>;
206
207 fn add_rasterization_complete_listener(
212 &self,
213 pipeline_id: PipelineId,
214 image_id: VectorImageId,
215 size: DeviceIntSize,
216 sender: IpcSender<ImageCacheResponseMessage>,
217 );
218
219 fn add_listener(&self, listener: ImageLoadListener);
222
223 fn notify_pending_response(&self, id: PendingImageId, action: FetchResponseMsg);
225
226 fn create_new_image_cache(
228 &self,
229 pipeline_id: Option<PipelineId>,
230 compositor_api: CrossProcessCompositorApi,
231 ) -> Arc<dyn ImageCache>;
232
233 fn fill_key_cache_with_batch_of_keys(&self, image_keys: Vec<ImageKey>);
235}