Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign upImplement sub-image updates. #1003
Conversation
|
r? @glennw |
|
One nit and a question about the purpose of the union() and how that works. |
| @@ -317,6 +320,11 @@ impl ResourceCache { | |||
| data: ImageData::new(bytes), | |||
| epoch: next_epoch, | |||
| tiling: None, | |||
| dirty_rect: match (dirty_rect, prev_dirty_rect) { | |||
This comment has been minimized.
This comment has been minimized.
glennw
Mar 22, 2017
Member
I don't really understand this part. I'm assuming the union() here is for the case where you update different parts of the same image multiple times in one frame? But then, the second update loses the bytes from the original update doesn't it?
This comment has been minimized.
This comment has been minimized.
nical
Mar 23, 2017
•
Author
Collaborator
The case I'm trying to support is updating an image several times (either several times in the same frame or across several frames if the image isn't requested (not in the viewport?)). In this situation the idea is to keep a dirty rectangle containing all dirty rectangles since the last time the texture_cache was updated.
I'm not sure what you mean by losing the bytes of the original update.
Edit: Ah! After talking with @kvark on irc I realize you probably meant by losing the bytes. The image data sent in update image still contains the whole image, the optional dirty rect only gives a hint that only a portion of the new image is different from the previous version.
So at any time the ImageData that we have can fully describe the whole image (only sending the damaged part would make things more complicated because the image might not be in the texture cache, in which case the dirty rect isn't useful since we need to upload the whole thing).
Same thing for blob images, the new blob is the whole "blob display list" for that image.
| data: bytes, | ||
| stride: descriptor.stride, | ||
| offset: descriptor.offset, | ||
| if let Some(dirty) = dirty_rect { |
This comment has been minimized.
This comment has been minimized.
| @@ -147,8 +147,8 @@ impl RenderBackend { | |||
| } | |||
| self.resource_cache.add_image_template(id, descriptor, data, tiling); | |||
| } | |||
| ApiMsg::UpdateImage(id, descriptor, bytes) => { | |||
| self.resource_cache.update_image_template(id, descriptor, bytes); | |||
| ApiMsg::UpdateImage(id, descriptor, bytes, dirty_rect) => { | |||
This comment has been minimized.
This comment has been minimized.
kvark
Mar 23, 2017
Member
naming nit: this is not a "dirty" rectangle, just the one to update. "dirty" brings on more semantics than the interface really provides.
This comment has been minimized.
This comment has been minimized.
| stride: descriptor.stride, | ||
| offset: descriptor.offset, | ||
| if let Some(dirty) = dirty_rect { | ||
| let stride = descriptor.compute_stride(); |
This comment has been minimized.
This comment has been minimized.
kvark
Mar 23, 2017
Member
that's a bit confusing that we have both descriptor.stride and descriptor.compute_stride()
This comment has been minimized.
This comment has been minimized.
nical
Mar 23, 2017
Author
Collaborator
What you mean is that ImageDescriptor::stride being an option is confusing, and that's true (but it's convenient because in a lot of cases we don't have a stride larger than width * bpp).
You can fix that by making the stride not optional, and computing it in a construction function if you want.
This comment has been minimized.
This comment has been minimized.
| @@ -317,6 +320,11 @@ impl ResourceCache { | |||
| data: ImageData::new(bytes), | |||
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
nical
Mar 23, 2017
Author
Collaborator
The old image data is replaced by the new one, yes. The underlying buffer is reference counted, not sure what you mean by lost.
| offset: descriptor.offset, | ||
| if let Some(dirty) = dirty_rect { | ||
| let stride = descriptor.compute_stride(); | ||
| let offset = descriptor.offset + dirty.origin.y * stride + dirty.origin.x; |
This comment has been minimized.
This comment has been minimized.
kvark
Mar 23, 2017
Member
gotta double-check this line, but it depends on the answers to previous questions
|
Yes, I considered only passing the updated rect's worth of pixel data in the update message, but that makes the implementation a lot more complicated, and isn't necessarily more efficient because we currently save copies thanks to the image data being immutable and atomically ref counted. I'm not against doing it this way but I would prefer to have a compelling use case to motivate the extra complexity. |
|
@nical OK, that makes sense. Let's get this merged - but it would be good to change that |
|
@bors-servo r+ |
|
|
Implement sub-image updates. Add an optional dirty rect to the update_image command (None means invalidate all), and only upload the required part of the image if the image was already in the texture cache. This will become more important when used with blob images since the blob image renderer will use this information to avoid repainting the entire image when possible. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/webrender/1003) <!-- Reviewable:end -->
|
|
nical commentedMar 22, 2017
•
edited by larsbergstrom
Add an optional dirty rect to the update_image command (None means invalidate all), and only upload the required part of the image if the image was already in the texture cache. This will become more important when used with blob images since the blob image renderer will use this information to avoid repainting the entire image when possible.
This change is