Skip to content

Commit 69aa818

Browse files
authored
Auto merge of servo#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 #servo#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.
2 parents 26da8a2 + 2cffbd7 commit 69aa818

File tree

2 files changed

+121
-28
lines changed

2 files changed

+121
-28
lines changed

components/compositing/compositor.rs

+39-23
Original file line numberDiff line numberDiff line change
@@ -626,25 +626,28 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
626626
size,
627627
pipeline,
628628
size2,
629-
data,
629+
receiver,
630630
descriptor,
631-
)) => {
632-
self.waiting_on_pending_frame = true;
633-
let mut txn = webrender_api::Transaction::new();
634-
txn.set_display_list(
635-
epoch,
636-
None,
637-
size,
638-
(
639-
pipeline,
640-
size2,
641-
webrender_api::BuiltDisplayList::from_data(data, descriptor),
642-
),
643-
true,
644-
);
645-
txn.generate_frame();
646-
self.webrender_api
647-
.send_transaction(self.webrender_document, txn);
631+
)) => match receiver.recv() {
632+
Ok(data) => {
633+
self.waiting_on_pending_frame = true;
634+
let mut txn = webrender_api::Transaction::new();
635+
txn.set_display_list(
636+
epoch,
637+
None,
638+
size,
639+
(
640+
pipeline,
641+
size2,
642+
webrender_api::BuiltDisplayList::from_data(data, descriptor),
643+
),
644+
true,
645+
);
646+
txn.generate_frame();
647+
self.webrender_api
648+
.send_transaction(self.webrender_document, txn);
649+
},
650+
Err(e) => warn!("error receiving display data: {:?}", e),
648651
},
649652

650653
WebrenderMsg::Layout(script_traits::WebrenderMsg::HitTest(
@@ -668,12 +671,25 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
668671
let mut txn = webrender_api::Transaction::new();
669672
for update in updates {
670673
match update {
671-
script_traits::ImageUpdate::AddImage(key, desc, data) => {
672-
txn.add_image(key, desc, data, None)
674+
script_traits::SerializedImageUpdate::AddImage(key, desc, data) => {
675+
match data.to_image_data() {
676+
Ok(data) => txn.add_image(key, desc, data, None),
677+
Err(e) => warn!("error when sending image data: {:?}", e),
678+
}
679+
},
680+
script_traits::SerializedImageUpdate::DeleteImage(key) => {
681+
txn.delete_image(key)
673682
},
674-
script_traits::ImageUpdate::DeleteImage(key) => txn.delete_image(key),
675-
script_traits::ImageUpdate::UpdateImage(key, desc, data) => {
676-
txn.update_image(key, desc, data, &webrender_api::DirtyRect::All)
683+
script_traits::SerializedImageUpdate::UpdateImage(key, desc, data) => {
684+
match data.to_image_data() {
685+
Ok(data) => txn.update_image(
686+
key,
687+
desc,
688+
data,
689+
&webrender_api::DirtyRect::All,
690+
),
691+
Err(e) => warn!("error when sending image data: {:?}", e),
692+
}
677693
},
678694
}
679695
}

components/script_traits/lib.rs

+82-5
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ use webrender_api::units::{
7171
DeviceIntSize, DevicePixel, LayoutPixel, LayoutPoint, LayoutSize, WorldPoint,
7272
};
7373
use webrender_api::{
74-
BuiltDisplayList, DocumentId, ExternalScrollId, ImageData, ImageDescriptor, ImageKey,
75-
ScrollClamping,
74+
BuiltDisplayList, DocumentId, ExternalImageData, ExternalScrollId, ImageData, ImageDescriptor,
75+
ImageKey, ScrollClamping,
7676
};
7777
use webrender_api::{BuiltDisplayListDescriptor, HitTestFlags, HitTestResult};
7878

@@ -1123,7 +1123,7 @@ pub enum WebrenderMsg {
11231123
LayoutSize,
11241124
webrender_api::PipelineId,
11251125
LayoutSize,
1126-
Vec<u8>,
1126+
ipc::IpcBytesReceiver,
11271127
BuiltDisplayListDescriptor,
11281128
),
11291129
/// Perform a hit test operation. The result will be returned via
@@ -1138,7 +1138,7 @@ pub enum WebrenderMsg {
11381138
/// provided channel sender.
11391139
GenerateImageKey(IpcSender<ImageKey>),
11401140
/// Perform a resource update operation.
1141-
UpdateImages(Vec<ImageUpdate>),
1141+
UpdateImages(Vec<SerializedImageUpdate>),
11421142
}
11431143

11441144
#[derive(Clone, Deserialize, Serialize)]
@@ -1181,16 +1181,21 @@ impl WebrenderIpcSender {
11811181
(pipeline, size2, list): (webrender_api::PipelineId, LayoutSize, BuiltDisplayList),
11821182
) {
11831183
let (data, descriptor) = list.into_data();
1184+
let (sender, receiver) = ipc::bytes_channel().unwrap();
11841185
if let Err(e) = self.0.send(WebrenderMsg::SendDisplayList(
11851186
webrender_api::Epoch(epoch.0),
11861187
size,
11871188
pipeline,
11881189
size2,
1189-
data,
1190+
receiver,
11901191
descriptor,
11911192
)) {
11921193
warn!("Error sending display list: {}", e);
11931194
}
1195+
1196+
if let Err(e) = sender.send(&data) {
1197+
warn!("Error sending display data: {}", e);
1198+
}
11941199
}
11951200

11961201
/// Perform a hit test operation. Blocks until the operation is complete and
@@ -1219,9 +1224,48 @@ impl WebrenderIpcSender {
12191224

12201225
/// Perform a resource update operation.
12211226
pub fn update_images(&self, updates: Vec<ImageUpdate>) {
1227+
let mut senders = Vec::new();
1228+
// Convert `ImageUpdate` to `SerializedImageUpdate` because `ImageData` may contain large
1229+
// byes. With this conversion, we send `IpcBytesReceiver` instead and use it to send the
1230+
// actual bytes.
1231+
let updates = updates
1232+
.into_iter()
1233+
.map(|update| match update {
1234+
ImageUpdate::AddImage(k, d, data) => {
1235+
let data = match data {
1236+
ImageData::Raw(r) => {
1237+
let (sender, receiver) = ipc::bytes_channel().unwrap();
1238+
senders.push((sender, r));
1239+
SerializedImageData::Raw(receiver)
1240+
},
1241+
ImageData::External(e) => SerializedImageData::External(e),
1242+
};
1243+
SerializedImageUpdate::AddImage(k, d, data)
1244+
},
1245+
ImageUpdate::DeleteImage(k) => SerializedImageUpdate::DeleteImage(k),
1246+
ImageUpdate::UpdateImage(k, d, data) => {
1247+
let data = match data {
1248+
ImageData::Raw(r) => {
1249+
let (sender, receiver) = ipc::bytes_channel().unwrap();
1250+
senders.push((sender, r));
1251+
SerializedImageData::Raw(receiver)
1252+
},
1253+
ImageData::External(e) => SerializedImageData::External(e),
1254+
};
1255+
SerializedImageUpdate::UpdateImage(k, d, data)
1256+
},
1257+
})
1258+
.collect();
1259+
12221260
if let Err(e) = self.0.send(WebrenderMsg::UpdateImages(updates)) {
12231261
warn!("error sending image updates: {}", e);
12241262
}
1263+
1264+
senders.into_iter().for_each(|(tx, data)| {
1265+
if let Err(e) = tx.send(&*data) {
1266+
warn!("error sending image data: {}", e);
1267+
}
1268+
});
12251269
}
12261270
}
12271271

@@ -1235,3 +1279,36 @@ pub enum ImageUpdate {
12351279
/// Update an existing image registration.
12361280
UpdateImage(ImageKey, ImageDescriptor, ImageData),
12371281
}
1282+
1283+
#[derive(Deserialize, Serialize)]
1284+
/// Serialized `ImageUpdate`.
1285+
pub enum SerializedImageUpdate {
1286+
/// Register a new image.
1287+
AddImage(ImageKey, ImageDescriptor, SerializedImageData),
1288+
/// Delete a previously registered image registration.
1289+
DeleteImage(ImageKey),
1290+
/// Update an existing image registration.
1291+
UpdateImage(ImageKey, ImageDescriptor, SerializedImageData),
1292+
}
1293+
1294+
#[derive(Debug, Deserialize, Serialize)]
1295+
/// Serialized `ImageData`. It contains IPC byte channel receiver to prevent from loading bytes too
1296+
/// slow.
1297+
pub enum SerializedImageData {
1298+
/// A simple series of bytes, provided by the embedding and owned by WebRender.
1299+
/// The format is stored out-of-band, currently in ImageDescriptor.
1300+
Raw(ipc::IpcBytesReceiver),
1301+
/// An image owned by the embedding, and referenced by WebRender. This may
1302+
/// take the form of a texture or a heap-allocated buffer.
1303+
External(ExternalImageData),
1304+
}
1305+
1306+
impl SerializedImageData {
1307+
/// Convert to ``ImageData`.
1308+
pub fn to_image_data(&self) -> Result<ImageData, ipc::IpcError> {
1309+
match self {
1310+
SerializedImageData::Raw(rx) => rx.recv().map(|data| ImageData::new(data)),
1311+
SerializedImageData::External(image) => Ok(ImageData::External(image.clone())),
1312+
}
1313+
}
1314+
}

0 commit comments

Comments
 (0)