Skip to content

Commit

Permalink
Add get_image_properties() to resource cache.
Browse files Browse the repository at this point in the history
This allows querying image opacity before an image is added to
the texture cache.

This doesn't change functionality, but it's prep work for some
of the upcoming interface changes in the resource cache that are
needed for subpixel glyph functionality.

This is arguably a much cleaner interface as well, it never really
made sense to have this accessible only via the texture cache.
  • Loading branch information
gw3583 committed Nov 1, 2016
1 parent b47e11c commit c698a16
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 38 deletions.
3 changes: 2 additions & 1 deletion webrender/src/prim_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,7 @@ impl ImagePrimitiveCpu {
match self.kind {
ImagePrimitiveKind::Image(image_key, image_rendering, stretch_size, tile_spacing) => {
let info = resource_cache.get_image(image_key, image_rendering, frame_id);
let image_properties = resource_cache.get_image_properties(image_key);
ImageInfo {
color_texture_id: info.texture_id,
uv0: Point2D::new(info.pixel_rect.top_left.x as f32,
Expand All @@ -995,7 +996,7 @@ impl ImagePrimitiveCpu {
stretch_size: Some(stretch_size),
uv_kind: TextureCoordKind::Pixel,
tile_spacing: tile_spacing,
is_opaque: info.is_opaque,
is_opaque: image_properties.is_opaque,
}
}
ImagePrimitiveKind::WebGL(context_id) => {
Expand Down
40 changes: 40 additions & 0 deletions webrender/src/resource_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ use webrender_traits::{GlyphDimensions, PipelineId, WebGLContextId};

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

pub struct ImageProperties {
pub format: ImageFormat,
pub is_opaque: bool,
}

pub struct DummyResources {
pub white_image_id: TextureCacheItemId,
pub opaque_mask_image_id: TextureCacheItemId,
Expand All @@ -38,6 +43,7 @@ struct ImageResource {
height: u32,
format: ImageFormat,
epoch: Epoch,
is_opaque: bool,
}

struct GlyphRasterJob {
Expand Down Expand Up @@ -158,6 +164,7 @@ impl ResourceCache {
format: ImageFormat,
bytes: Vec<u8>) {
let resource = ImageResource {
is_opaque: is_image_opaque(format, &bytes),
width: width,
height: height,
format: format,
Expand Down Expand Up @@ -185,6 +192,7 @@ impl ResourceCache {
};

let resource = ImageResource {
is_opaque: is_image_opaque(format, &bytes),
width: width,
height: height,
format: format,
Expand Down Expand Up @@ -371,6 +379,15 @@ impl ResourceCache {
self.texture_cache.get(image_info.texture_cache_id)
}

pub fn get_image_properties(&self, image_key: ImageKey) -> ImageProperties {
let image_template = &self.image_templates[&image_key];

ImageProperties {
format: image_template.format,
is_opaque: image_template.is_opaque,
}
}

#[inline]
pub fn get_image_by_cache_id(&self, texture_cache_id: TextureCacheItemId)
-> &TextureCacheItem {
Expand Down Expand Up @@ -440,3 +457,26 @@ impl Resource for CachedImageInfo {
}
}

// TODO(gw): If this ever shows up in profiles, consider calculating
// this lazily on demand, possibly via the resource cache thread.
// It can probably be made a lot faster with SIMD too!
// This assumes that A8 textures are never opaque, since they are
// typically used for alpha masks. We could revisit that if it
// ever becomes an issue in real world usage.
fn is_image_opaque(format: ImageFormat, bytes: &[u8]) -> bool {
match format {
ImageFormat::RGBA8 => {
let mut is_opaque = true;
for i in 0..(bytes.len() / 4) {
if bytes[i * 4 + 3] != 255 {
is_opaque = false;
break;
}
}
is_opaque
}
ImageFormat::RGB8 => true,
ImageFormat::A8 => false,
ImageFormat::Invalid | ImageFormat::RGBAF32 => unreachable!(),
}
}
44 changes: 7 additions & 37 deletions webrender/src/texture_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,6 @@ pub struct TextureCacheItem {
// bilinear filtering / texture bleeding purposes.
pub allocated_rect: Rect<u32>,
pub requested_rect: Rect<u32>,

pub is_opaque: bool,
}

// Structure squat the width/height fields to maintain the free list information :)
Expand Down Expand Up @@ -491,8 +489,7 @@ impl TextureCacheItem {
user_x0: i32, user_y0: i32,
allocated_rect: Rect<u32>,
requested_rect: Rect<u32>,
texture_size: &Size2D<u32>,
is_opaque: bool)
texture_size: &Size2D<u32>)
-> TextureCacheItem {
TextureCacheItem {
texture_id: texture_id,
Expand All @@ -513,7 +510,6 @@ impl TextureCacheItem {
},
allocated_rect: allocated_rect,
requested_rect: requested_rect,
is_opaque: is_opaque,
}
}

Expand Down Expand Up @@ -645,7 +641,6 @@ impl TextureCache {
requested_rect: Rect::zero(),
texture_size: Size2D::zero(),
texture_id: TextureId::invalid(),
is_opaque: false,
};
self.items.insert(new_item)
}
Expand All @@ -659,8 +654,7 @@ impl TextureCache {
format: ImageFormat,
kind: TextureCacheItemKind,
border_type: BorderType,
filter: TextureFilter,
is_opaque: bool)
filter: TextureFilter)
-> AllocationResult {
let requested_size = Size2D::new(requested_width, requested_height);

Expand All @@ -679,8 +673,7 @@ impl TextureCache {
user_x0, user_y0,
Rect::new(Point2D::zero(), requested_size),
Rect::new(Point2D::zero(), requested_size),
&requested_size,
is_opaque);
&requested_size);
*self.items.get_mut(image_id) = cache_item;

return AllocationResult {
Expand Down Expand Up @@ -740,8 +733,7 @@ impl TextureCache {
user_x0, user_y0,
allocated_rect,
requested_rect,
&Size2D::new(page.texture_size, page.texture_size),
is_opaque);
&Size2D::new(page.texture_size, page.texture_size));
*self.items.get_mut(image_id) = cache_item;

return AllocationResult {
Expand Down Expand Up @@ -847,25 +839,6 @@ impl TextureCache {
filter: TextureFilter,
insert_op: TextureInsertOp,
border_type: BorderType) {

let is_opaque = match (&insert_op, format) {
(&TextureInsertOp::Blit(ref bytes), ImageFormat::RGBA8) => {
let mut is_opaque = true;
for i in 0..(bytes.len() / 4) {
if bytes[i * 4 + 3] != 255 {
is_opaque = false;
break;
}
}
is_opaque
}
(&TextureInsertOp::Blit(..), ImageFormat::RGB8) => true,
(&TextureInsertOp::Blit(..), ImageFormat::A8) => false,
(&TextureInsertOp::Blit(..), ImageFormat::Invalid) |
(&TextureInsertOp::Blit(..), ImageFormat::RGBAF32) => unreachable!(),
(&TextureInsertOp::Blur(..), _) => false,
};

let result = self.allocate(image_id,
x0,
y0,
Expand All @@ -874,8 +847,7 @@ impl TextureCache {
format,
TextureCacheItemKind::Standard,
border_type,
filter,
is_opaque);
filter);

let op = match (result.kind, insert_op) {
(AllocationKind::TexturePage, TextureInsertOp::Blit(bytes)) => {
Expand Down Expand Up @@ -971,16 +943,14 @@ impl TextureCache {
ImageFormat::RGBA8,
TextureCacheItemKind::Standard,
BorderType::SinglePixel,
TextureFilter::Linear,
false);
TextureFilter::Linear);
self.allocate(horizontal_blur_image_id,
0, 0,
width, height,
ImageFormat::RGBA8,
TextureCacheItemKind::Alternate,
BorderType::SinglePixel,
TextureFilter::Linear,
false);
TextureFilter::Linear);
let unblurred_glyph_item = self.get(unblurred_glyph_image_id);
let horizontal_blur_item = self.get(horizontal_blur_image_id);
TextureUpdateOp::Update(
Expand Down

0 comments on commit c698a16

Please sign in to comment.