Auto merge of #28739 - wusyong:ipc-bytes, r=jdm

Send webrender message's data through IPCBytesChannel

<!-- Please describe your changes on the following line: -->

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix ##28738 (GitHub issue number if applicable)

<!-- Either: -->
- [x] There are tests for these changes OR
- [ ] These changes do not require tests because ___

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

For display list data, I tested with https://svelte.dev/docs in release build. I seems to have 20~30% improvement on `Display List Construction` when I profiling.

For image data, I tested with http://slither.io/ (on the page for you to customize snek). It seems identical and I'm not sure where should I look at when profiling.
This commit is contained in:
bors-servo 2022-03-11 05:05:08 -05:00 committed by GitHub
commit 69aa81838d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 121 additions and 28 deletions

View file

@ -626,25 +626,28 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
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(
@ -668,12 +671,25 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
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),
}
},
}
}

View file

@ -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};
@ -1123,7 +1123,7 @@ pub enum WebrenderMsg {
LayoutSize,
webrender_api::PipelineId,
LayoutSize,
Vec<u8>,
ipc::IpcBytesReceiver,
BuiltDisplayListDescriptor,
),
/// Perform a hit test operation. The result will be returned via
@ -1138,7 +1138,7 @@ pub enum WebrenderMsg {
/// provided channel sender.
GenerateImageKey(IpcSender<ImageKey>),
/// Perform a resource update operation.
UpdateImages(Vec<ImageUpdate>),
UpdateImages(Vec<SerializedImageUpdate>),
}
#[derive(Clone, Deserialize, Serialize)]
@ -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
@ -1219,9 +1224,48 @@ impl WebrenderIpcSender {
/// Perform a resource update operation.
pub fn update_images(&self, updates: Vec<ImageUpdate>) {
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 +1279,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<ImageData, ipc::IpcError> {
match self {
SerializedImageData::Raw(rx) => rx.recv().map(|data| ImageData::new(data)),
SerializedImageData::External(image) => Ok(ImageData::External(image.clone())),
}
}
}