compositor: Move WebRender-ish messages and types to webrender_traits (#32315)

* Move WebRender related types to `webrender_traits`

This refactor moves several WebRender related types
from `compositing_traits`, `script_traits` and `net_traits`
crates to the `webrender_traits` crate.

This change also moves the `Image` type and associated
function out of `net_traits` and into the `pixels` crate.

Co-authored-by: Martin Robinson <mrobinson@igalia.com>
Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>

* Move `script_traits::WebrenderIpcSender` to `webrender_traits::WebRenderScriptApi`

---------

Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com>
Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
Mukilan Thiyagarajan 2024-05-20 16:05:18 +05:30 committed by GitHub
parent c2076580f3
commit 2af6fe0b30
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
53 changed files with 666 additions and 617 deletions

View file

@ -39,3 +39,4 @@ servo_url = { path = "../../url" }
url = { workspace = true }
uuid = { workspace = true }
webrender_api = { workspace = true }
webrender_traits = { workspace = true }

View file

@ -1,121 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use std::fmt;
use image::ImageFormat;
use ipc_channel::ipc::IpcSharedMemory;
use log::debug;
use malloc_size_of_derive::MallocSizeOf;
use pixels::PixelFormat;
use serde::{Deserialize, Serialize};
use webrender_api::ImageKey;
use crate::image_cache::CorsStatus;
#[derive(Clone, Deserialize, MallocSizeOf, Serialize)]
pub struct Image {
pub width: u32,
pub height: u32,
pub format: PixelFormat,
#[ignore_malloc_size_of = "Defined in ipc-channel"]
pub bytes: IpcSharedMemory,
#[ignore_malloc_size_of = "Defined in webrender_api"]
pub id: Option<ImageKey>,
pub cors_status: CorsStatus,
}
impl fmt::Debug for Image {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Image {{ width: {}, height: {}, format: {:?}, ..., id: {:?} }}",
self.width, self.height, self.format, self.id
)
}
}
#[derive(Clone, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
pub struct ImageMetadata {
pub width: u32,
pub height: u32,
}
// FIXME: Images must not be copied every frame. Instead we should atomically
// reference count them.
pub fn load_from_memory(buffer: &[u8], cors_status: CorsStatus) -> Option<Image> {
if buffer.is_empty() {
return None;
}
let image_fmt_result = detect_image_format(buffer);
match image_fmt_result {
Err(msg) => {
debug!("{}", msg);
None
},
Ok(_) => match image::load_from_memory(buffer) {
Ok(image) => {
let mut rgba = image.into_rgba8();
pixels::rgba8_byte_swap_colors_inplace(&mut rgba);
Some(Image {
width: rgba.width(),
height: rgba.height(),
format: PixelFormat::BGRA8,
bytes: IpcSharedMemory::from_bytes(&rgba),
id: None,
cors_status,
})
},
Err(e) => {
debug!("Image decoding error: {:?}", e);
None
},
},
}
}
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/img
pub fn detect_image_format(buffer: &[u8]) -> Result<ImageFormat, &str> {
if is_gif(buffer) {
Ok(ImageFormat::Gif)
} else if is_jpeg(buffer) {
Ok(ImageFormat::Jpeg)
} else if is_png(buffer) {
Ok(ImageFormat::Png)
} else if is_webp(buffer) {
Ok(ImageFormat::WebP)
} else if is_bmp(buffer) {
Ok(ImageFormat::Bmp)
} else if is_ico(buffer) {
Ok(ImageFormat::Ico)
} else {
Err("Image Format Not Supported")
}
}
fn is_gif(buffer: &[u8]) -> bool {
buffer.starts_with(b"GIF87a") || buffer.starts_with(b"GIF89a")
}
fn is_jpeg(buffer: &[u8]) -> bool {
buffer.starts_with(&[0xff, 0xd8, 0xff])
}
fn is_png(buffer: &[u8]) -> bool {
buffer.starts_with(&[0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A])
}
fn is_bmp(buffer: &[u8]) -> bool {
buffer.starts_with(&[0x42, 0x4D])
}
fn is_ico(buffer: &[u8]) -> bool {
buffer.starts_with(&[0x00, 0x00, 0x01, 0x00])
}
fn is_webp(buffer: &[u8]) -> bool {
buffer.starts_with(b"RIFF") && buffer.len() >= 14 && &buffer[8..14] == b"WEBPVP"
}

View file

@ -7,12 +7,13 @@ use std::sync::Arc;
use ipc_channel::ipc::IpcSender;
use log::debug;
use malloc_size_of_derive::MallocSizeOf;
use pixels::{Image, ImageMetadata};
use serde::{Deserialize, Serialize};
use servo_url::{ImmutableOrigin, ServoUrl};
use webrender_traits::WebRenderNetApi;
use crate::image::base::{Image, ImageMetadata};
use crate::request::CorsSettings;
use crate::{FetchResponseMsg, WebrenderIpcSender};
use crate::FetchResponseMsg;
// ======================================================================
// Aux structs and enums.
@ -98,7 +99,7 @@ pub enum ImageCacheResult {
}
pub trait ImageCache: Sync + Send {
fn new(webrender_api: WebrenderIpcSender) -> Self
fn new(webrender_api: WebRenderNetApi) -> Self
where
Self: Sized;
@ -140,14 +141,3 @@ pub trait ImageCache: Sync + Send {
/// Inform the image cache about a response for a pending request.
fn notify_pending_response(&self, id: PendingImageId, action: FetchResponseMsg);
}
/// Whether this response passed any CORS checks, and is thus safe to read from
/// in cross-origin environments.
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
pub enum CorsStatus {
/// The response is either same-origin or cross-origin but passed CORS checks.
Safe,
/// The response is cross-origin and did not pass CORS checks. It is unsafe
/// to expose pixel data to the requesting environment.
Unsafe,
}

View file

@ -16,7 +16,6 @@ use ipc_channel::ipc::{self, IpcReceiver, IpcSender};
use ipc_channel::router::ROUTER;
use ipc_channel::Error as IpcError;
use lazy_static::lazy_static;
use log::warn;
use malloc_size_of::malloc_size_of_is_0;
use malloc_size_of_derive::MallocSizeOf;
use mime::Mime;
@ -25,7 +24,6 @@ use rustls::Certificate;
use serde::{Deserialize, Serialize};
use servo_rand::RngCore;
use servo_url::{ImmutableOrigin, ServoUrl};
use webrender_api::{ImageData, ImageDescriptor, ImageKey};
use crate::filemanager_thread::FileManagerThreadMsg;
use crate::request::{Request, RequestBuilder};
@ -41,15 +39,6 @@ pub mod request;
pub mod response;
pub mod storage_thread;
/// Image handling.
///
/// It may be surprising that this goes in the network crate as opposed to the graphics crate.
/// However, image handling is generally very integrated with the network stack (especially where
/// caching is involved) and as a result it must live in here.
pub mod image {
pub mod base;
}
/// An implementation of the [Fetch specification](https://fetch.spec.whatwg.org/)
pub mod fetch {
pub mod headers;
@ -829,38 +818,6 @@ pub fn http_percent_encode(bytes: &[u8]) -> String {
percent_encoding::percent_encode(bytes, HTTP_VALUE).to_string()
}
#[derive(Deserialize, Serialize)]
pub enum NetToCompositorMsg {
AddImage(ImageKey, ImageDescriptor, ImageData),
GenerateImageKey(IpcSender<ImageKey>),
}
#[derive(Clone, Deserialize, Serialize)]
pub struct WebrenderIpcSender(IpcSender<NetToCompositorMsg>);
impl WebrenderIpcSender {
pub fn new(sender: IpcSender<NetToCompositorMsg>) -> Self {
Self(sender)
}
pub fn generate_image_key(&self) -> ImageKey {
let (sender, receiver) = ipc::channel().unwrap();
self.0
.send(NetToCompositorMsg::GenerateImageKey(sender))
.expect("error sending image key generation");
receiver.recv().expect("error receiving image key result")
}
pub fn add_image(&self, key: ImageKey, descriptor: ImageDescriptor, data: ImageData) {
if let Err(e) = self
.0
.send(NetToCompositorMsg::AddImage(key, descriptor, data))
{
warn!("Error sending image update: {}", e);
}
}
}
lazy_static! {
pub static ref PRIVILEGED_SECRET: u32 = servo_rand::ServoRng::default().next_u32();
}

View file

@ -1,28 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use net_traits::image::base::detect_image_format;
#[test]
fn test_supported_images() {
let gif1 = [b'G', b'I', b'F', b'8', b'7', b'a'];
let gif2 = [b'G', b'I', b'F', b'8', b'9', b'a'];
let jpeg = [0xff, 0xd8, 0xff];
let png = [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A];
let webp = [
b'R', b'I', b'F', b'F', 0x01, 0x02, 0x03, 0x04, b'W', b'E', b'B', b'P', b'V', b'P',
];
let bmp = [0x42, 0x4D];
let ico = [0x00, 0x00, 0x01, 0x00];
let junk_format = [0x01, 0x02, 0x03, 0x04, 0x05];
assert!(detect_image_format(&gif1).is_ok());
assert!(detect_image_format(&gif2).is_ok());
assert!(detect_image_format(&jpeg).is_ok());
assert!(detect_image_format(&png).is_ok());
assert!(detect_image_format(&webp).is_ok());
assert!(detect_image_format(&bmp).is_ok());
assert!(detect_image_format(&ico).is_ok());
assert!(detect_image_format(&junk_format).is_err());
}