From 34b3dafab8067c68d4776565949fa80ea6f0da86 Mon Sep 17 00:00:00 2001 From: Yu-Wei Wu Date: Wed, 9 Mar 2022 23:30:28 +0800 Subject: [PATCH 1/2] Add SerializedImageData to use IpcBytesReceiver --- components/compositing/compositor.rs | 23 ++++++-- components/script_traits/lib.rs | 78 ++++++++++++++++++++++++++-- 2 files changed, 93 insertions(+), 8 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index fd645f309de..4c7461dd955 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -668,12 +668,25 @@ impl IOCompositor { let mut txn = webrender_api::Transaction::new(); for update in updates { match update { - script_traits::ImageUpdate::AddImage(key, desc, data) => { - txn.add_image(key, desc, data, None) + script_traits::SerializedImageUpdate::AddImage(key, desc, data) => { + match data.to_image_data() { + Ok(data) => txn.add_image(key, desc, data, None), + Err(e) => warn!("error when sending image data: {:?}", e), + } }, - script_traits::ImageUpdate::DeleteImage(key) => txn.delete_image(key), - script_traits::ImageUpdate::UpdateImage(key, desc, data) => { - txn.update_image(key, desc, data, &webrender_api::DirtyRect::All) + script_traits::SerializedImageUpdate::DeleteImage(key) => { + txn.delete_image(key) + }, + script_traits::SerializedImageUpdate::UpdateImage(key, desc, data) => { + match data.to_image_data() { + Ok(data) => txn.update_image( + key, + desc, + data, + &webrender_api::DirtyRect::All, + ), + Err(e) => warn!("error when sending image data: {:?}", e), + } }, } } diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 4d8ba59c0ea..0fc56a9f2e3 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -71,8 +71,8 @@ use webrender_api::units::{ DeviceIntSize, DevicePixel, LayoutPixel, LayoutPoint, LayoutSize, WorldPoint, }; use webrender_api::{ - BuiltDisplayList, DocumentId, ExternalScrollId, ImageData, ImageDescriptor, ImageKey, - ScrollClamping, + BuiltDisplayList, DocumentId, ExternalImageData, ExternalScrollId, ImageData, ImageDescriptor, + ImageKey, ScrollClamping, }; use webrender_api::{BuiltDisplayListDescriptor, HitTestFlags, HitTestResult}; @@ -1138,7 +1138,7 @@ pub enum WebrenderMsg { /// provided channel sender. GenerateImageKey(IpcSender), /// Perform a resource update operation. - UpdateImages(Vec), + UpdateImages(Vec), } #[derive(Clone, Deserialize, Serialize)] @@ -1219,9 +1219,48 @@ impl WebrenderIpcSender { /// Perform a resource update operation. pub fn update_images(&self, updates: Vec) { + let mut senders = Vec::new(); + // Convert `ImageUpdate` to `SerializedImageUpdate` because `ImageData` may contain large + // byes. With this conversion, we send `IpcBytesReceiver` instead and use it to send the + // actual bytes. + let updates = updates + .into_iter() + .map(|update| match update { + ImageUpdate::AddImage(k, d, data) => { + let data = match data { + ImageData::Raw(r) => { + let (sender, receiver) = ipc::bytes_channel().unwrap(); + senders.push((sender, r)); + SerializedImageData::Raw(receiver) + }, + ImageData::External(e) => SerializedImageData::External(e), + }; + SerializedImageUpdate::AddImage(k, d, data) + }, + ImageUpdate::DeleteImage(k) => SerializedImageUpdate::DeleteImage(k), + ImageUpdate::UpdateImage(k, d, data) => { + let data = match data { + ImageData::Raw(r) => { + let (sender, receiver) = ipc::bytes_channel().unwrap(); + senders.push((sender, r)); + SerializedImageData::Raw(receiver) + }, + ImageData::External(e) => SerializedImageData::External(e), + }; + SerializedImageUpdate::UpdateImage(k, d, data) + }, + }) + .collect(); + if let Err(e) = self.0.send(WebrenderMsg::UpdateImages(updates)) { warn!("error sending image updates: {}", e); } + + senders.into_iter().for_each(|(tx, data)| { + if let Err(e) = tx.send(&*data) { + warn!("error sending image data: {}", e); + } + }); } } @@ -1235,3 +1274,36 @@ pub enum ImageUpdate { /// Update an existing image registration. UpdateImage(ImageKey, ImageDescriptor, ImageData), } + +#[derive(Deserialize, Serialize)] +/// Serialized `ImageUpdate`. +pub enum SerializedImageUpdate { + /// Register a new image. + AddImage(ImageKey, ImageDescriptor, SerializedImageData), + /// Delete a previously registered image registration. + DeleteImage(ImageKey), + /// Update an existing image registration. + UpdateImage(ImageKey, ImageDescriptor, SerializedImageData), +} + +#[derive(Debug, Deserialize, Serialize)] +/// Serialized `ImageData`. It contains IPC byte channel receiver to prevent from loading bytes too +/// slow. +pub enum SerializedImageData { + /// A simple series of bytes, provided by the embedding and owned by WebRender. + /// The format is stored out-of-band, currently in ImageDescriptor. + Raw(ipc::IpcBytesReceiver), + /// An image owned by the embedding, and referenced by WebRender. This may + /// take the form of a texture or a heap-allocated buffer. + External(ExternalImageData), +} + +impl SerializedImageData { + /// Convert to ``ImageData`. + pub fn to_image_data(&self) -> Result { + match self { + SerializedImageData::Raw(rx) => rx.recv().map(|data| ImageData::new(data)), + SerializedImageData::External(image) => Ok(ImageData::External(image.clone())), + } + } +} From 2cffbd75279b72feeb067a680a248b155d224e2c Mon Sep 17 00:00:00 2001 From: Wu Yu Wei Date: Thu, 10 Mar 2022 17:51:53 +0800 Subject: [PATCH 2/2] Use IpcBytesReceiver to send Display list data --- components/compositing/compositor.rs | 39 +++++++++++++++------------- components/script_traits/lib.rs | 9 +++++-- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 4c7461dd955..023c3cac959 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -626,25 +626,28 @@ impl IOCompositor { size, pipeline, size2, - data, + receiver, descriptor, - )) => { - self.waiting_on_pending_frame = true; - let mut txn = webrender_api::Transaction::new(); - txn.set_display_list( - epoch, - None, - size, - ( - pipeline, - size2, - webrender_api::BuiltDisplayList::from_data(data, descriptor), - ), - true, - ); - txn.generate_frame(); - self.webrender_api - .send_transaction(self.webrender_document, txn); + )) => match receiver.recv() { + Ok(data) => { + self.waiting_on_pending_frame = true; + let mut txn = webrender_api::Transaction::new(); + txn.set_display_list( + epoch, + None, + size, + ( + pipeline, + size2, + webrender_api::BuiltDisplayList::from_data(data, descriptor), + ), + true, + ); + txn.generate_frame(); + self.webrender_api + .send_transaction(self.webrender_document, txn); + }, + Err(e) => warn!("error receiving display data: {:?}", e), }, WebrenderMsg::Layout(script_traits::WebrenderMsg::HitTest( diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 0fc56a9f2e3..af336a41374 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -1123,7 +1123,7 @@ pub enum WebrenderMsg { LayoutSize, webrender_api::PipelineId, LayoutSize, - Vec, + ipc::IpcBytesReceiver, BuiltDisplayListDescriptor, ), /// Perform a hit test operation. The result will be returned via @@ -1181,16 +1181,21 @@ impl WebrenderIpcSender { (pipeline, size2, list): (webrender_api::PipelineId, LayoutSize, BuiltDisplayList), ) { let (data, descriptor) = list.into_data(); + let (sender, receiver) = ipc::bytes_channel().unwrap(); if let Err(e) = self.0.send(WebrenderMsg::SendDisplayList( webrender_api::Epoch(epoch.0), size, pipeline, size2, - data, + receiver, descriptor, )) { warn!("Error sending display list: {}", e); } + + if let Err(e) = sender.send(&data) { + warn!("Error sending display data: {}", e); + } } /// Perform a hit test operation. Blocks until the operation is complete and