Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow updating images that are not raw buffers #1004

Merged
merged 4 commits into from Mar 29, 2017
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -20,9 +20,10 @@ use std::io::Read;
use std::path::PathBuf;
use std::sync::Arc;
use webrender_traits::{BlobImageData, BlobImageDescriptor, BlobImageError, BlobImageRenderer};
use webrender_traits::{BlobImageResult, ClipRegion, ColorF, DeviceIntPoint, DeviceUintSize, Epoch, GlyphInstance};
use webrender_traits::{BlobImageResult, ClipRegion, ColorF, Epoch, GlyphInstance};
use webrender_traits::{DeviceIntPoint, DeviceUintSize, DeviceUintRect, LayoutPoint, LayoutRect, LayoutSize};
use webrender_traits::{ImageData, ImageDescriptor, ImageFormat, ImageKey, ImageRendering};
use webrender_traits::{LayoutPoint, LayoutRect, LayoutSize, PipelineId, RasterizedBlobImage};
use webrender_traits::{PipelineId, RasterizedBlobImage};

#[derive(Debug)]
enum Gesture {
@@ -455,7 +456,11 @@ impl FakeBlobImageRenderer {
}

impl BlobImageRenderer for FakeBlobImageRenderer {
fn request_blob_image(&mut self, key: ImageKey, _: Arc<BlobImageData>, descriptor: &BlobImageDescriptor) {
fn request_blob_image(&mut self,
key: ImageKey,
_: Arc<BlobImageData>,
descriptor: &BlobImageDescriptor,
_dirty_rect: Option<DeviceUintRect>) {
let mut texels = Vec::with_capacity((descriptor.width * descriptor.height * 4) as usize);
for y in 0..descriptor.height {
for x in 0..descriptor.width {
@@ -29,6 +29,8 @@ use webrender_traits::{BlobImageRenderer, BlobImageDescriptor, BlobImageError};
use threadpool::ThreadPool;
use euclid::Point2D;

const DEFAULT_TILE_SIZE: TileSize = 512;

thread_local!(pub static FONT_CONTEXT: RefCell<FontContext> = RefCell::new(FontContext::new()));

type GlyphCache = ResourceClassCache<RenderedGlyphKey, Option<TextureCacheItemId>>;
@@ -254,6 +256,16 @@ impl ResourceCache {
self.texture_cache.max_texture_size()
}

fn should_tile(&self, descriptor: &ImageDescriptor, data: &ImageData) -> bool {
let limit = self.max_texture_size();
return match data {
// Tiled external images are not implemented.
&ImageData::ExternalHandle(_) => false,
&ImageData::ExternalBuffer(_) => false,
_ => { descriptor.width > limit || descriptor.height > limit }

This comment has been minimized.

@glennw

glennw Mar 28, 2017

Member

As a follow up, could we explicitly list all the variations here rather than _ ? I like the safety of a compiler bug when new enum variants are introduced.

};
}

pub fn add_font_template(&mut self, font_key: FontKey, template: FontTemplate) {
// Push the new font to the glyph cache thread, and also store
// it locally for glyph metric requests.
@@ -275,10 +287,10 @@ impl ResourceCache {
descriptor: ImageDescriptor,
data: ImageData,
mut tiling: Option<TileSize>) {
if descriptor.width > self.max_texture_size() || descriptor.height > self.max_texture_size() {
if tiling.is_none() && self.should_tile(&descriptor, &data) {
// We aren't going to be able to upload a texture this big, so tile it, even
// if tiling was not requested.
tiling = Some(512);
tiling = Some(DEFAULT_TILE_SIZE);
}

let resource = ImageResource {
@@ -295,36 +307,34 @@ impl ResourceCache {
pub fn update_image_template(&mut self,
image_key: ImageKey,
descriptor: ImageDescriptor,
bytes: Vec<u8>,
data: ImageData,
dirty_rect: Option<DeviceUintRect>) {
let (next_epoch, prev_dirty_rect) = match self.image_templates.get(&image_key) {
Some(image) => {
// This image should not be an external image.
match image.data {
ImageData::ExternalHandle(id) => {
panic!("Update an external image with buffer, id={} image_key={:?}", id.0, image_key);
},
_ => {},
}

let Epoch(current_epoch) = image.epoch;
(Epoch(current_epoch + 1), image.dirty_rect)
}
None => {
(Epoch(0), None)
let resource = if let Some(image) = self.image_templates.get(&image_key) {
assert!(image.descriptor.width == descriptor.width);
assert!(image.descriptor.height == descriptor.height);
assert!(image.descriptor.format == descriptor.format);

let next_epoch = Epoch(image.epoch.0 + 1);

let mut tiling = image.tiling;
if tiling.is_none() && self.should_tile(&descriptor, &data) {
tiling = Some(DEFAULT_TILE_SIZE);
}
};

let resource = ImageResource {
descriptor: descriptor,
data: ImageData::new(bytes),
epoch: next_epoch,
tiling: None,
dirty_rect: match (dirty_rect, prev_dirty_rect) {
(Some(rect), Some(prev_rect)) => Some(rect.union(&prev_rect)),
(Some(rect), None) => Some(rect),
_ => None,
},
ImageResource {
descriptor: descriptor,
data: data,
epoch: next_epoch,
tiling: tiling,
dirty_rect: match (dirty_rect, image.dirty_rect) {
(Some(rect), Some(prev_rect)) => Some(rect.union(&prev_rect)),
(Some(rect), None) => Some(rect),
_ => None,
},
}
} else {
panic!("Attempt to update non-existant image (key {:?}).", image_key);
};

self.image_templates.insert(image_key, resource);
@@ -394,6 +404,7 @@ impl ResourceCache {
// TODO(nical): figure out the scale factor (should change with zoom).
scale_factor: 1.0,
},
template.dirty_rect,
);
}
}
@@ -722,27 +722,30 @@ impl TextureCache {
panic!("The vector image should have been rasterized into a raw image.");
}
ImageData::Raw(bytes) => {
if let Some(dirty) = dirty_rect {
let stride = descriptor.compute_stride();
let offset = descriptor.offset + dirty.origin.y * stride + dirty.origin.x;
TextureUpdateOp::Update {
page_pos_x: existing_item.allocated_rect.origin.x + dirty.origin.x,
page_pos_y: existing_item.allocated_rect.origin.y + dirty.origin.y,
width: dirty.size.width,
height: dirty.size.height,
data: bytes,
stride: Some(stride),
offset: offset,
match dirty_rect {
Some(dirty) => {
let stride = descriptor.compute_stride();
let offset = descriptor.offset + dirty.origin.y * stride + dirty.origin.x;
TextureUpdateOp::Update {
page_pos_x: existing_item.allocated_rect.origin.x + dirty.origin.x,
page_pos_y: existing_item.allocated_rect.origin.y + dirty.origin.y,
width: dirty.size.width,
height: dirty.size.height,
data: bytes,
stride: Some(stride),
offset: offset,
}
}
} else {
TextureUpdateOp::Update {
page_pos_x: existing_item.allocated_rect.origin.x,
page_pos_y: existing_item.allocated_rect.origin.y,
width: descriptor.width,
height: descriptor.height,
data: bytes,
stride: descriptor.stride,
offset: descriptor.offset,
None => {
TextureUpdateOp::Update {
page_pos_x: existing_item.allocated_rect.origin.x,
page_pos_y: existing_item.allocated_rect.origin.y,
width: descriptor.width,
height: descriptor.height,
data: bytes,
stride: descriptor.stride,
offset: descriptor.offset,
}
}
}
}
@@ -25,7 +25,7 @@ pub enum ApiMsg {
/// Adds an image from the resource cache.
AddImage(ImageKey, ImageDescriptor, ImageData, Option<TileSize>),
/// Updates the the resource cache with the new image data.
UpdateImage(ImageKey, ImageDescriptor, Vec<u8>, Option<DeviceUintRect>),
UpdateImage(ImageKey, ImageDescriptor, ImageData, Option<DeviceUintRect>),
/// Drops an image from the resource cache.
DeleteImage(ImageKey),
CloneApi(MsgSender<IdNamespace>),
@@ -229,9 +229,9 @@ impl RenderApi {
pub fn update_image(&self,
key: ImageKey,
descriptor: ImageDescriptor,
bytes: Vec<u8>,
data: ImageData,
dirty_rect: Option<DeviceUintRect>) {
let msg = ApiMsg::UpdateImage(key, descriptor, bytes, dirty_rect);
let msg = ApiMsg::UpdateImage(key, descriptor, data, dirty_rect);
self.api_sender.send(msg).unwrap();
}

@@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::sync::Arc;
use DeviceUintRect;

#[repr(C)]
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
@@ -99,7 +100,8 @@ pub trait BlobImageRenderer: Send {
fn request_blob_image(&mut self,
key: ImageKey,
data: Arc<BlobImageData>,
descriptor: &BlobImageDescriptor);
descriptor: &BlobImageDescriptor,
dirty_rect: Option<DeviceUintRect>);
fn resolve_blob_image(&mut self, key: ImageKey) -> BlobImageResult;
}

@@ -234,14 +234,19 @@ impl webrender::ApiRecordingReceiver for JsonFrameWriter {
});
}

&ApiMsg::UpdateImage(ref key, descriptor, ref bytes, _dirty_rect) => {
&ApiMsg::UpdateImage(ref key, descriptor, ref img_data, _dirty_rect) => {
if let Some(ref mut data) = self.images.get_mut(key) {
assert!(data.width == descriptor.width);
assert!(data.height == descriptor.height);
assert!(data.format == descriptor.format);

*data.path.borrow_mut() = None;
*data.bytes.borrow_mut() = Some(bytes.clone());
if let &ImageData::Raw(ref bytes) = img_data {
*data.path.borrow_mut() = None;
*data.bytes.borrow_mut() = Some((**bytes).clone());
} else {
// Other existing image types only make sense within the gecko integration.
println!("Wrench only supports updating buffer images (ignoring update command).");
}
}
}

@@ -797,14 +797,19 @@ impl webrender::ApiRecordingReceiver for YamlFrameWriterReceiver {
});
}

&ApiMsg::UpdateImage(ref key, ref descriptor, ref bytes, _dirty_rect) => {
&ApiMsg::UpdateImage(ref key, ref descriptor, ref img_data, _dirty_rect) => {
if let Some(ref mut data) = self.frame_writer.images.get_mut(key) {
assert!(data.width == descriptor.width);
assert!(data.height == descriptor.height);
assert!(data.format == descriptor.format);

*data.path.borrow_mut() = None;
*data.bytes.borrow_mut() = Some(bytes.clone());
if let &ImageData::Raw(ref bytes) = img_data {
*data.path.borrow_mut() = None;
*data.bytes.borrow_mut() = Some((**bytes).clone());
} else {
// Other existing image types only make sense within the gecko integration.
println!("Wrench only supports updating buffer images (ignoring update command).");
}
}
}

ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.