Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 33 additions & 4 deletions webrender/src/internal_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use tiling;
use webrender_traits::{Epoch, ColorF, PipelineId, DeviceIntSize};
use webrender_traits::{ImageFormat, MixBlendMode, NativeFontHandle};
use webrender_traits::{ExternalImageId, ScrollLayerId, WebGLCommand};
use webrender_traits::{ImageData};
use webrender_traits::{DeviceUintRect};

// An ID for a texture that is owned by the
// texture cache module. This can include atlases
Expand Down Expand Up @@ -342,10 +344,37 @@ pub enum RenderTargetMode {
}

pub enum TextureUpdateOp {
Create(u32, u32, ImageFormat, TextureFilter, RenderTargetMode, Option<Arc<Vec<u8>>>),
Update(u32, u32, u32, u32, Arc<Vec<u8>>, Option<u32>),
Grow(u32, u32, ImageFormat, TextureFilter, RenderTargetMode),
Free
Create {
width: u32,
height: u32,
format: ImageFormat,
filter: TextureFilter,
mode: RenderTargetMode,
data: Option<ImageData>,
},
Update {
page_pos_x: u32, // the texture page position which we want to upload
page_pos_y: u32,
width: u32,
height: u32,
data: Arc<Vec<u8>>,
stride: Option<u32>,
},
UpdateForExternalBuffer {
allocated_rect: DeviceUintRect,
requested_rect: DeviceUintRect,
id: ExternalImageId,
bpp: u32,
stride: Option<u32>,
},
Grow {
width: u32,
height: u32,
format: ImageFormat,
filter: TextureFilter,
mode: RenderTargetMode,
},
Free,
}

pub type ExternalImageUpdateList = Vec<ExternalImageId>;
Expand Down
122 changes: 92 additions & 30 deletions webrender/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ use tiling::{BlurCommand, CacheClipInstance, PrimitiveInstance, RenderTarget, Re
use time::precise_time_ns;
use util::TransformedRectKind;
use webrender_traits::{ColorF, Epoch, PipelineId, RenderNotifier, RenderDispatcher};
use webrender_traits::{ExternalImageId, ImageFormat, RenderApiSender, RendererKind};
use webrender_traits::{ExternalImageId, ImageData, ImageFormat, RenderApiSender, RendererKind};
use webrender_traits::{DeviceIntRect, DevicePoint, DeviceIntPoint, DeviceIntSize, DeviceUintSize};
use webrender_traits::ImageDescriptor;
use webrender_traits::channel;
Expand Down Expand Up @@ -571,7 +571,7 @@ impl Renderer {
is_opaque: false,
},
TextureFilter::Linear,
Arc::new(white_pixels));
ImageData::Raw(Arc::new(white_pixels)));

let dummy_mask_image_id = texture_cache.new_item_id();
texture_cache.insert(dummy_mask_image_id,
Expand All @@ -583,7 +583,7 @@ impl Renderer {
is_opaque: false,
},
TextureFilter::Linear,
Arc::new(mask_pixels));
ImageData::Raw(Arc::new(mask_pixels)));

let debug_renderer = DebugRenderer::new(&mut device);

Expand Down Expand Up @@ -903,45 +903,107 @@ impl Renderer {
for update_list in pending_texture_updates.drain(..) {
for update in update_list.updates {
match update.op {
TextureUpdateOp::Create(width, height, format, filter, mode, maybe_bytes) => {
TextureUpdateOp::Create { width, height, format, filter, mode, data } => {
let CacheTextureId(cache_texture_index) = update.id;
if self.cache_texture_id_map.len() == cache_texture_index {
// Create a new native texture, as requested by the texture cache.
let texture_id = self.device
.create_texture_ids(1, TextureTarget::Default)[0];
.create_texture_ids(1, TextureTarget::Default)[0];
self.cache_texture_id_map.push(texture_id);
}
let texture_id = self.cache_texture_id_map[cache_texture_index];

let maybe_slice = maybe_bytes.as_ref().map(|bytes|{ bytes.as_slice() });
self.device.init_texture(texture_id,
width,
height,
format,
filter,
mode,
maybe_slice);
if let Some(image) = data {
match image {
ImageData::Raw(raw) => {
self.device.init_texture(texture_id,
width,
height,
format,
filter,
mode,
Some(raw.as_slice()));
}
ImageData::ExternalBuffer(id) => {
let handler = self.external_image_handler
.as_mut()
.expect("Found external image, but no handler set!");

match handler.lock(id).source {
ExternalImageSource::RawData(raw) => {
self.device.init_texture(texture_id,
width,
height,
format,
filter,
mode,
Some(raw));
}
_ => panic!("No external buffer found"),
};
handler.unlock(id);
}
_ => {
panic!("No suitable image buffer for TextureUpdateOp::Create.");
}
}
} else {
self.device.init_texture(texture_id,
width,
height,
format,
filter,
mode,
None);
}
}
TextureUpdateOp::Grow(new_width,
new_height,
format,
filter,
mode) => {
TextureUpdateOp::Grow { width, height, format, filter, mode } => {
let texture_id = self.cache_texture_id_map[update.id.0];
self.device.resize_texture(texture_id,
new_width,
new_height,
width,
height,
format,
filter,
mode);
}
TextureUpdateOp::Update(x, y, width, height, bytes, stride) => {
TextureUpdateOp::Update { page_pos_x, page_pos_y, width, height, data, stride } => {
let texture_id = self.cache_texture_id_map[update.id.0];
self.device.update_texture(texture_id,
x,
y,
page_pos_x,
page_pos_y,
width, height, stride,
bytes.as_slice());
data.as_slice());
}
TextureUpdateOp::UpdateForExternalBuffer { allocated_rect, requested_rect, id, bpp, stride } => {
let handler = self.external_image_handler
.as_mut()
.expect("Found external image, but no handler set!");
let device = &mut self.device;
let cached_id = self.cache_texture_id_map[update.id.0];

match handler.lock(id).source {
ExternalImageSource::RawData(data) => {
// image itself
device.update_texture(cached_id,
requested_rect.origin.x,
requested_rect.origin.y,
requested_rect.size.width,
requested_rect.size.height,
stride, data);
// image's borders
let op = |x , y , w , h , src: Arc<Vec<u8>> , stride| {
device.update_texture(cached_id, x, y, w, h, stride, src.as_slice());
};
TextureCache::insert_image_border(data,
allocated_rect,
requested_rect,
stride,
bpp,
op);
}
_ => panic!("No external buffer found"),
};
handler.unlock(id);
}
TextureUpdateOp::Free => {
let texture_id = self.cache_texture_id_map[update.id.0];
Expand Down Expand Up @@ -1341,6 +1403,7 @@ impl Renderer {

let texture_id = match image.source {
ExternalImageSource::NativeTexture(texture_id) => TextureId::new(texture_id),
_ => panic!("No native texture found."),
};

self.external_images.insert(external_id, texture_id);
Expand Down Expand Up @@ -1507,10 +1570,9 @@ impl Renderer {
}
}

pub enum ExternalImageSource {
// TODO(gw): Work out the API for raw buffers.
//RawData(*const u8, usize),
NativeTexture(u32), // Is a gl::GLuint texture handle
pub enum ExternalImageSource<'a> {
RawData(&'a [u8]), // raw buffers.
NativeTexture(u32), // Is a gl::GLuint texture handle
}

/// The data that an external client should provide about
Expand All @@ -1522,12 +1584,12 @@ pub enum ExternalImageSource {
/// the returned timestamp for a given image, the renderer
/// will know to re-upload the image data to the GPU.
/// Note that the UV coords are supplied in texel-space!
pub struct ExternalImage {
pub struct ExternalImage<'a> {
pub u0: f32,
pub v0: f32,
pub u1: f32,
pub v1: f32,
pub source: ExternalImageSource,
pub source: ExternalImageSource<'a>,
}

/// The interfaces that an application can implement to support providing
Expand Down
24 changes: 13 additions & 11 deletions webrender/src/resource_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ impl ResourceCache {
Some(image) => {
// This image should not be an external image.
match image.data {
ImageData::External(id) => {
ImageData::ExternalHandle(id) => {
panic!("Update an external image with buffer, id={} image_key={:?}", id.0, image_key);
},
_ => {},
Expand Down Expand Up @@ -291,7 +291,7 @@ impl ResourceCache {
// If the key is associated to an external image, pass the external id to renderer for cleanup.
if let Some(image) = value {
match image.data {
ImageData::External(id) => {
ImageData::ExternalHandle(id) => {
self.pending_external_image_update_list.push(id);
},
_ => {},
Expand Down Expand Up @@ -451,8 +451,9 @@ impl ResourceCache {
let image_template = &self.image_templates[&image_key];

let external_id = match image_template.data {
ImageData::External(id) => Some(id),
ImageData::Raw(..) => None,
ImageData::ExternalHandle(id) => Some(id),
// raw and externalBuffer are all use resource_cache.
ImageData::Raw(..) | ImageData::ExternalBuffer(..) => None,
};

ImageProperties {
Expand Down Expand Up @@ -520,7 +521,7 @@ impl ResourceCache {
is_opaque: false,
},
TextureFilter::Linear,
Arc::new(glyph.bytes));
ImageData::Raw(Arc::new(glyph.bytes)));
Some(image_id)
} else {
None
Expand All @@ -539,19 +540,21 @@ impl ResourceCache {
for request in self.pending_image_requests.drain(..) {
let cached_images = &mut self.cached_images;
let image_template = &self.image_templates[&request.key];
let image_data = image_template.data.clone();

match image_template.data {
ImageData::External(..) => {}
ImageData::Raw(ref bytes) => {
ImageData::ExternalHandle(..) => {
// external handle doesn't need to update the texture_cache.
}
ImageData::Raw(..) | ImageData::ExternalBuffer(..) => {
match cached_images.entry(request.clone(), self.current_frame_id) {
Occupied(entry) => {
let image_id = entry.get().texture_cache_id;

if entry.get().epoch != image_template.epoch {
// TODO: Can we avoid the clone of the bytes here?
self.texture_cache.update(image_id,
image_template.descriptor,
bytes.clone());
image_data);

// Update the cached epoch
*entry.into_mut() = CachedImageInfo {
Expand All @@ -568,11 +571,10 @@ impl ResourceCache {
ImageRendering::Auto | ImageRendering::CrispEdges => TextureFilter::Linear,
};

// TODO: Can we avoid the clone of the bytes here?
self.texture_cache.insert(image_id,
image_template.descriptor,
filter,
bytes.clone());
image_data);

entry.insert(CachedImageInfo {
texture_cache_id: image_id,
Expand Down
Loading