diff --git a/webrender/res/clip_shared.glsl b/webrender/res/clip_shared.glsl index 2c1993b1fa..62e51c3bbf 100644 --- a/webrender/res/clip_shared.glsl +++ b/webrender/res/clip_shared.glsl @@ -9,7 +9,7 @@ flat varying vec4 vClipMaskUvRect; flat varying vec4 vClipMaskLocalRect; #ifdef WR_VERTEX_SHADER -void write_clip(ClipInfo clip) { +void write_clip(ClipData clip) { vClipRect = vec4(clip.rect.rect.xy, clip.rect.rect.xy + clip.rect.rect.zw); vClipRadius = vec4(clip.top_left.outer_inner_radius.x, clip.top_right.outer_inner_radius.x, @@ -17,8 +17,8 @@ void write_clip(ClipInfo clip) { clip.bottom_left.outer_inner_radius.x); //TODO: interpolate the final mask UV vec2 texture_size = textureSize(sMask, 0); - vClipMaskUvRect = clip.mask_info.uv_rect / texture_size.xyxy; - vClipMaskLocalRect = clip.mask_info.local_rect; //TODO: transform + vClipMaskUvRect = clip.mask_data.uv_rect / texture_size.xyxy; + vClipMaskLocalRect = clip.mask_data.local_rect; //TODO: transform } #endif diff --git a/webrender/res/prim_shared.glsl b/webrender/res/prim_shared.glsl index d624803064..e4803c42a6 100644 --- a/webrender/res/prim_shared.glsl +++ b/webrender/res/prim_shared.glsl @@ -347,13 +347,13 @@ ClipRect fetch_clip_rect(int index) { return rect; } -struct ImageMaskInfo { +struct ImageMaskData { vec4 uv_rect; vec4 local_rect; }; -ImageMaskInfo fetch_mask_info(int index) { - ImageMaskInfo info; +ImageMaskData fetch_mask_data(int index) { + ImageMaskData info; ivec2 uv = get_fetch_uv_2(index); @@ -379,24 +379,24 @@ ClipCorner fetch_clip_corner(int index) { return corner; } -struct ClipInfo { +struct ClipData { ClipRect rect; ClipCorner top_left; ClipCorner top_right; ClipCorner bottom_left; ClipCorner bottom_right; - ImageMaskInfo mask_info; + ImageMaskData mask_data; }; -ClipInfo fetch_clip(int index) { - ClipInfo clip; +ClipData fetch_clip(int index) { + ClipData clip; clip.rect = fetch_clip_rect(index + 0); clip.top_left = fetch_clip_corner(index + 1); clip.top_right = fetch_clip_corner(index + 2); clip.bottom_left = fetch_clip_corner(index + 3); clip.bottom_right = fetch_clip_corner(index + 4); - clip.mask_info = fetch_mask_info(index + 5); + clip.mask_data = fetch_mask_data(index + 5); return clip; } diff --git a/webrender/res/ps_gradient_clip.vs.glsl b/webrender/res/ps_gradient_clip.vs.glsl index 62e7caeb7f..8c20dfdbfa 100644 --- a/webrender/res/ps_gradient_clip.vs.glsl +++ b/webrender/res/ps_gradient_clip.vs.glsl @@ -66,6 +66,6 @@ void main(void) { break; } - ClipInfo clip = fetch_clip(prim.clip_index); + ClipData clip = fetch_clip(prim.clip_index); write_clip(clip); } diff --git a/webrender/res/ps_image_clip.vs.glsl b/webrender/res/ps_image_clip.vs.glsl index b272b27140..ba88620fe6 100644 --- a/webrender/res/ps_image_clip.vs.glsl +++ b/webrender/res/ps_image_clip.vs.glsl @@ -23,7 +23,7 @@ void main(void) { vLocalPos = vi.local_clamped_pos; #endif - ClipInfo clip = fetch_clip(prim.clip_index); + ClipData clip = fetch_clip(prim.clip_index); write_clip(clip); // vUv will contain how many times this image has wrapped around the image size. diff --git a/webrender/res/ps_rectangle_clip.vs.glsl b/webrender/res/ps_rectangle_clip.vs.glsl index 20fef16a3d..1cc281ac61 100644 --- a/webrender/res/ps_rectangle_clip.vs.glsl +++ b/webrender/res/ps_rectangle_clip.vs.glsl @@ -22,6 +22,6 @@ void main(void) { vPos = vi.local_clamped_pos; #endif - ClipInfo clip = fetch_clip(prim.clip_index); + ClipData clip = fetch_clip(prim.clip_index); write_clip(clip); } diff --git a/webrender/src/frame.rs b/webrender/src/frame.rs index 3c9c709401..8f620c3678 100644 --- a/webrender/src/frame.rs +++ b/webrender/src/frame.rs @@ -11,16 +11,14 @@ use internal_types::{CompositionOp}; use internal_types::{LowLevelFilterOp}; use internal_types::{RendererFrame}; use layer::{Layer, ScrollingState}; -use prim_store::ClipInfo; use resource_cache::{DummyResources, ResourceCache}; use scene::{SceneStackingContext, ScenePipeline, Scene, SceneItem, SpecificSceneItem}; use std::collections::{HashMap, HashSet}; use std::hash::BuildHasherDefault; -use tiling::{FrameBuilder, FrameBuilderConfig, InsideTest, Clip, MaskImageSource}; -use tiling::PrimitiveFlags; +use tiling::{AuxiliaryListsMap, FrameBuilder, FrameBuilderConfig, PrimitiveFlags}; use util::MatrixHelpers; use webrender_traits::{AuxiliaryLists, PipelineId, Epoch, ScrollPolicy, ScrollLayerId}; -use webrender_traits::{ColorF, StackingContext, FilterOp, MixBlendMode}; +use webrender_traits::{ClipRegion, ColorF, StackingContext, FilterOp, MixBlendMode}; use webrender_traits::{ScrollEventPhase, ScrollLayerInfo, SpecificDisplayItem, ScrollLayerState}; #[cfg(target_os = "macos")] @@ -36,7 +34,6 @@ static DEFAULT_SCROLLBAR_COLOR: ColorF = ColorF { r: 0.3, g: 0.3, b: 0.3, a: 0.6 struct FlattenContext<'a> { resource_cache: &'a mut ResourceCache, - dummy_resources: &'a DummyResources, scene: &'a Scene, pipeline_sizes: &'a mut HashMap>, builder: &'a mut FrameBuilder, @@ -411,13 +408,13 @@ impl Frame { { let mut frame_builder = FrameBuilder::new(root_pipeline.viewport_size, device_pixel_ratio, + dummy_resources.clone(), self.debug, self.frame_builder_config); { let mut context = FlattenContext { resource_cache: resource_cache, - dummy_resources: dummy_resources, scene: scene, pipeline_sizes: pipeline_sizes, builder: &mut frame_builder, @@ -538,67 +535,27 @@ impl Frame { // // If we do need this, does it make sense to keep Frame::clear_tiles? context.builder.add_solid_rectangle(&stacking_context.bounds, - &stacking_context.bounds, - None, + &ClipRegion::simple(&stacking_context.bounds), &ColorF::new(1.0, 1.0, 1.0, 1.0), PrimitiveFlags::None); } - let dummy_mask_source = { - let cache_id = context.dummy_resources.opaque_mask_image_id; - let cache_item = context.resource_cache.get_image_by_cache_id(cache_id); - MaskImageSource::Renderer(cache_item.texture_id) - }; - for item in scene_items { match item.specific { SpecificSceneItem::DrawList(draw_list_id) => { let draw_list = context.resource_cache.get_draw_list(draw_list_id); let builder = &mut context.builder; - let auxiliary_lists = self.pipeline_auxiliary_lists - .get(&parent_info.pipeline_id) - .expect("No auxiliary lists?!"); for item in &draw_list.items { - let clips = auxiliary_lists.complex_clip_regions(&item.clip.complex); - let mut clip = match clips.len() { - 0 if item.clip.image_mask.is_none() => None, - 0 => Some(Clip::new(ClipInfo::uniform(item.clip.main, 0.0), dummy_mask_source)), - 1 => Some(Clip::new(ClipInfo::from_clip_region(&clips[0]), dummy_mask_source)), - _ => { - let internal_clip = clips.last().unwrap(); - let region = if clips.iter().all(|current_clip| current_clip.might_contain(internal_clip)) { - internal_clip - } else { - &clips[0] - }; - Some(Clip::new(ClipInfo::from_clip_region(region), dummy_mask_source)) - }, - }; - - if let Some(ref mask) = item.clip.image_mask { - let old = match clip { - Some(masked) => *masked.clip, - None => ClipInfo::uniform(item.clip.main, 0.0), - }; - //Note: can't call `tex_cache.aligned_uv_rect()` here since the image - // is not yet marked as needed this frame. - clip = Some(Clip::new(old.with_mask(Rect::zero(), mask.rect), - MaskImageSource::User(mask.image))); - } - - match item.item { SpecificDisplayItem::WebGL(ref info) => { builder.add_webgl_rectangle(item.rect, - &item.clip.main, - clip, + &item.clip, info.context_id); } SpecificDisplayItem::Image(ref info) => { builder.add_image(item.rect, - &item.clip.main, - clip, + &item.clip, &info.stretch_size, &info.tile_spacing, info.image_key, @@ -606,8 +563,7 @@ impl Frame { } SpecificDisplayItem::Text(ref text_info) => { builder.add_text(item.rect, - &item.clip.main, - clip, + &item.clip, text_info.font_key, text_info.size, text_info.blur_radius, @@ -616,23 +572,20 @@ impl Frame { } SpecificDisplayItem::Rectangle(ref info) => { builder.add_solid_rectangle(&item.rect, - &item.clip.main, - clip, + &item.clip, &info.color, PrimitiveFlags::None); } SpecificDisplayItem::Gradient(ref info) => { builder.add_gradient(item.rect, - &item.clip.main, - clip, + &item.clip, info.start_point, info.end_point, info.stops); } SpecificDisplayItem::BoxShadow(ref box_shadow_info) => { builder.add_box_shadow(&box_shadow_info.box_bounds, - &item.clip.main, - clip, + &item.clip, &box_shadow_info.offset, &box_shadow_info.color, box_shadow_info.blur_radius, @@ -642,8 +595,7 @@ impl Frame { } SpecificDisplayItem::Border(ref info) => { builder.add_border(item.rect, - &item.clip.main, - clip, + &item.clip, info); } } @@ -762,8 +714,7 @@ impl Frame { let scrollbar_rect = Rect::new(Point2D::zero(), Size2D::new(10.0, 70.0)); context.builder.add_solid_rectangle(&scrollbar_rect, - &scrollbar_rect, - None, + &ClipRegion::simple(&scrollbar_rect), &DEFAULT_SCROLLBAR_COLOR, PrimitiveFlags::Scrollbar(self.root_scroll_layer_id.unwrap(), 4.0)); @@ -774,10 +725,11 @@ impl Frame { pub fn build(&mut self, resource_cache: &mut ResourceCache, + auxiliary_lists_map: &AuxiliaryListsMap, device_pixel_ratio: f32) -> RendererFrame { self.update_layer_transforms(device_pixel_ratio); - let frame = self.build_frame(resource_cache); + let frame = self.build_frame(resource_cache, auxiliary_lists_map); resource_cache.expire_old_resources(self.id); frame } @@ -853,14 +805,12 @@ impl Frame { } fn build_frame(&mut self, - resource_cache: &mut ResourceCache) -> RendererFrame { + resource_cache: &mut ResourceCache, + auxiliary_lists_map: &AuxiliaryListsMap) -> RendererFrame { let mut frame_builder = self.frame_builder.take(); - let frame = frame_builder.as_mut().map(|builder| { - builder.build(resource_cache, - self.id, - &self.pipeline_auxiliary_lists, - &self.layers) - }); + let frame = frame_builder.as_mut().map(|builder| + builder.build(resource_cache, self.id, &self.layers, auxiliary_lists_map) + ); self.frame_builder = frame_builder; let layers_bouncing_back = self.collect_layers_bouncing_back(); diff --git a/webrender/src/prim_store.rs b/webrender/src/prim_store.rs index ad8b3f1321..a42f2bfb95 100644 --- a/webrender/src/prim_store.rs +++ b/webrender/src/prim_store.rs @@ -11,10 +11,10 @@ use renderer::BLUR_INFLATION_FACTOR; use resource_cache::ResourceCache; use std::mem; use std::usize; -use tiling::{Clip, MaskImageSource}; +use texture_cache::TextureCacheItem; use util::TransformedRect; use webrender_traits::{AuxiliaryLists, ColorF, ImageKey, ImageRendering, WebGLContextId}; -use webrender_traits::{FontKey, ItemRange, ComplexClipRegion, GlyphKey}; +use webrender_traits::{ClipRegion, FontKey, ItemRange, ComplexClipRegion, GlyphKey}; #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Ord, PartialOrd)] pub struct SpecificPrimitiveIndex(pub usize); @@ -56,13 +56,20 @@ pub struct PrimitiveCacheInfo { pub key: PrimitiveCacheKey, } +#[derive(Debug)] +pub enum PrimitiveClipSource { + NoClip, + Complex(Rect, f32), + Region(ClipRegion), +} + // TODO(gw): Pack the fields here better! #[derive(Debug)] pub struct PrimitiveMetadata { pub is_opaque: bool, pub mask_texture_id: TextureId, - pub mask_image: Option, pub clip_index: Option, + pub clip_source: Box, pub prim_kind: PrimitiveKind, pub cpu_prim_index: SpecificPrimitiveIndex, pub gpu_prim_index: GpuStoreAddress, @@ -217,24 +224,24 @@ impl ClipCorner { } #[derive(Debug, Clone)] -struct ImageMaskInfo { +struct ImageMaskData { uv_rect: Rect, local_rect: Rect, } #[derive(Debug, Clone)] -pub struct ClipInfo { +pub struct ClipData { rect: ClipRect, top_left: ClipCorner, top_right: ClipCorner, bottom_left: ClipCorner, bottom_right: ClipCorner, - mask_info: ImageMaskInfo, + mask_data: ImageMaskData, } -impl ClipInfo { - pub fn from_clip_region(clip: &ComplexClipRegion) -> ClipInfo { - ClipInfo { +impl ClipData { + pub fn from_clip_region(clip: &ComplexClipRegion) -> ClipData { + ClipData { rect: ClipRect { rect: clip.rect, padding: [0.0, 0.0, 0.0, 0.0], @@ -274,15 +281,15 @@ impl ClipInfo { inner_radius_x: 0.0, inner_radius_y: 0.0, }, - mask_info: ImageMaskInfo { + mask_data: ImageMaskData { uv_rect: Rect::zero(), local_rect: Rect::zero(), }, } } - pub fn uniform(rect: Rect, radius: f32) -> ClipInfo { - ClipInfo { + pub fn uniform(rect: Rect, radius: f32) -> ClipData { + ClipData { rect: ClipRect { rect: rect, padding: [0.0; 4], @@ -307,22 +314,12 @@ impl ClipInfo { Size2D::new(radius, radius)), radius, 0.0), - mask_info: ImageMaskInfo { + mask_data: ImageMaskData { uv_rect: Rect::zero(), local_rect: Rect::zero(), }, } } - - pub fn with_mask(self, uv_rect: Rect, local_rect: Rect) -> ClipInfo { - ClipInfo { - mask_info: ImageMaskInfo { - uv_rect: uv_rect, - local_rect: local_rect, - }, - .. self - } - } } #[derive(Debug)] @@ -375,20 +372,18 @@ impl PrimitiveStore { } } - fn populate_clip_data(&mut self, address: GpuStoreAddress, clip: ClipInfo) { - let data = self.gpu_data32.get_slice_mut(address, 6); + fn populate_clip_data(data: &mut [GpuBlock32], clip: ClipData) { data[0] = GpuBlock32::from(clip.rect); data[1] = GpuBlock32::from(clip.top_left); data[2] = GpuBlock32::from(clip.top_right); data[3] = GpuBlock32::from(clip.bottom_left); data[4] = GpuBlock32::from(clip.bottom_right); - data[5] = GpuBlock32::from(clip.mask_info); + data[5] = GpuBlock32::from(clip.mask_data); } pub fn add_primitive(&mut self, rect: &Rect, - clip_rect: &Rect, - clip: Option, + clip: &ClipRegion, container: PrimitiveContainer) -> PrimitiveIndex { let prim_index = self.cpu_metadata.len(); @@ -396,24 +391,14 @@ impl PrimitiveStore { self.gpu_geometry.push(PrimitiveGeometry { local_rect: *rect, - local_clip_rect: *clip_rect, + local_clip_rect: clip.main.clone(), }); - let (clip_index, (mask_image, mask_texture_id)) = if let Some(ref masked) = clip { - let clip = masked.clip.as_ref().clone(); - // TODO(gw): This is slightly inefficient. It - // pushes default data on when we already have - // the data we need to push on available now. - let gpu_address = self.gpu_data32.alloc(6); - self.populate_clip_data(gpu_address, clip); - let mask = match masked.mask { - MaskImageSource::User(image_key) => (Some(image_key), TextureId::invalid()), - MaskImageSource::Renderer(texture_id) => (None, texture_id), - }; - (Some(gpu_address), mask) + let clip_source = Box::new(if clip.is_complex() { + PrimitiveClipSource::Region(clip.clone()) } else { - (None, (None, TextureId::invalid())) - }; + PrimitiveClipSource::NoClip + }); let metadata = match container { PrimitiveContainer::Rectangle(rect) => { @@ -422,9 +407,9 @@ impl PrimitiveStore { let metadata = PrimitiveMetadata { is_opaque: is_opaque, - mask_image: mask_image, - mask_texture_id: mask_texture_id, - clip_index: clip_index, + mask_texture_id: TextureId::invalid(), + clip_index: None, + clip_source: clip_source, prim_kind: PrimitiveKind::Rectangle, cpu_prim_index: SpecificPrimitiveIndex::invalid(), gpu_prim_index: gpu_address, @@ -441,9 +426,9 @@ impl PrimitiveStore { let metadata = PrimitiveMetadata { is_opaque: false, - mask_image: mask_image, - mask_texture_id: mask_texture_id, - clip_index: clip_index, + mask_texture_id: TextureId::invalid(), + clip_index: None, + clip_source: clip_source, prim_kind: PrimitiveKind::TextRun, cpu_prim_index: SpecificPrimitiveIndex(self.cpu_text_runs.len()), gpu_prim_index: gpu_address, @@ -460,9 +445,9 @@ impl PrimitiveStore { let metadata = PrimitiveMetadata { is_opaque: false, - mask_image: mask_image, - mask_texture_id: mask_texture_id, - clip_index: clip_index, + mask_texture_id: TextureId::invalid(), + clip_index: None, + clip_source: clip_source, prim_kind: PrimitiveKind::Image, cpu_prim_index: SpecificPrimitiveIndex(self.cpu_images.len()), gpu_prim_index: gpu_address, @@ -479,9 +464,9 @@ impl PrimitiveStore { let metadata = PrimitiveMetadata { is_opaque: false, - mask_image: mask_image, - mask_texture_id: mask_texture_id, - clip_index: clip_index, + mask_texture_id: TextureId::invalid(), + clip_index: None, + clip_source: clip_source, prim_kind: PrimitiveKind::Border, cpu_prim_index: SpecificPrimitiveIndex(self.cpu_borders.len()), gpu_prim_index: gpu_address, @@ -499,9 +484,9 @@ impl PrimitiveStore { let metadata = PrimitiveMetadata { is_opaque: false, - mask_image: mask_image, - mask_texture_id: mask_texture_id, - clip_index: clip_index, + mask_texture_id: TextureId::invalid(), + clip_index: None, + clip_source: clip_source, prim_kind: PrimitiveKind::Gradient, cpu_prim_index: SpecificPrimitiveIndex(self.cpu_gradients.len()), gpu_prim_index: gpu_address, @@ -537,9 +522,9 @@ impl PrimitiveStore { let metadata = PrimitiveMetadata { is_opaque: false, - mask_image: mask_image, - mask_texture_id: mask_texture_id, - clip_index: clip_index, + mask_texture_id: TextureId::invalid(), + clip_index: None, + clip_source: clip_source, prim_kind: PrimitiveKind::BoxShadow, cpu_prim_index: SpecificPrimitiveIndex::invalid(), gpu_prim_index: gpu_prim_address, @@ -570,18 +555,16 @@ impl PrimitiveStore { for prim_index in self.prims_to_resolve.drain(..) { let metadata = &mut self.cpu_metadata[prim_index.0]; - if let Some(mask_key) = metadata.mask_image { - let tex_cache = resource_cache.get_image(mask_key, ImageRendering::Auto); + if let &PrimitiveClipSource::Region(ClipRegion { image_mask: Some(mask), .. }) = metadata.clip_source.as_ref() { + let tex_cache = resource_cache.get_image(mask.image, ImageRendering::Auto); metadata.mask_texture_id = tex_cache.texture_id; if let Some(address) = metadata.clip_index { - let clip = self.gpu_data32.get_slice_mut(address, 6); - let old = clip[5].data; //TODO: avoid retaining the screen rectangle - clip[5] = GpuBlock32::from(ImageMaskInfo { + let clip_data = self.gpu_data32.get_slice_mut(address, 6); + clip_data[5] = GpuBlock32::from(ImageMaskData { uv_rect: Rect::new(tex_cache.uv0, Size2D::new(tex_cache.uv1.x - tex_cache.uv0.x, - tex_cache.uv1.y - tex_cache.uv0.x)), - local_rect: Rect::new(Point2D::new(old[4], old[5]), - Size2D::new(old[6], old[7])), + tex_cache.uv1.y - tex_cache.uv0.y)), + local_rect: mask.rect, }); } } @@ -638,24 +621,21 @@ impl PrimitiveStore { &self.cpu_bounding_rects[index.0] } - pub fn set_complex_clip(&mut self, index: PrimitiveIndex, clip: Option) { - self.cpu_metadata[index.0].clip_index = match (self.cpu_metadata[index.0].clip_index, clip) { - (Some(clip_index), Some(clip)) => { - self.populate_clip_data(clip_index, clip); - Some(clip_index) - } - (Some(..), None) => { - // TODO(gw): Add to clip free list! - None - } - (None, Some(clip)) => { - // TODO(gw): Pull from clip free list! - let gpu_address = self.gpu_data32.alloc(6); - self.populate_clip_data(gpu_address, clip); - Some(gpu_address) + pub fn set_clip_source(&mut self, index: PrimitiveIndex, source: PrimitiveClipSource) { + let metadata = &mut self.cpu_metadata[index.0]; + let (rect, is_complex) = match source { + PrimitiveClipSource::NoClip => (None, false), + PrimitiveClipSource::Complex(rect, radius) => (Some(rect), radius > 0.0), + PrimitiveClipSource::Region(ref region) => (Some(region.main), region.is_complex()), + }; + if let Some(rect) = rect { + self.gpu_geometry.get_mut(GpuStoreAddress(index.0 as i32)) + .local_clip_rect = rect; + if is_complex && metadata.clip_index.is_none() { + metadata.clip_index = Some(self.gpu_data32.alloc(6)) } - (None, None) => None, } + *metadata.clip_source.as_mut() = source; } pub fn get_metadata(&self, index: PrimitiveIndex) -> &PrimitiveMetadata { @@ -688,19 +668,55 @@ impl PrimitiveStore { bounding_rect.is_some() } + /// Returns true if the bounding box needs to be updated. pub fn prepare_prim_for_render(&mut self, prim_index: PrimitiveIndex, resource_cache: &mut ResourceCache, device_pixel_ratio: f32, + dummy_mask_cache_item: &TextureCacheItem, auxiliary_lists: &AuxiliaryLists) -> bool { let metadata = &mut self.cpu_metadata[prim_index.0]; - let mut prim_needs_resolve = false; let mut rebuild_bounding_rect = false; - if let Some(mask_key) = metadata.mask_image { - resource_cache.request_image(mask_key, ImageRendering::Auto); - prim_needs_resolve = true; + if metadata.clip_index.is_none() { + // if the `clip_index` already exist, we consider the contents up to date + let clip_data = match metadata.clip_source.as_ref() { + &PrimitiveClipSource::NoClip => None, + &PrimitiveClipSource::Complex(rect, radius) => { + Some(ClipData::uniform(rect, radius)) + } + &PrimitiveClipSource::Region(ref clip_region) => { + if let Some(mask) = clip_region.image_mask { + resource_cache.request_image(mask.image, ImageRendering::Auto); + } + let clips = auxiliary_lists.complex_clip_regions(&clip_region.complex); + //TODO: proper solution to multiple complex clips + match clips.len() { + 0 if clip_region.image_mask.is_none() => None, + 0 => Some(ClipData::uniform(clip_region.main, 0.0)), + 1 => Some(ClipData::from_clip_region(&clips[0])), + _ => { + let internal_clip = clips.last().unwrap(); + let region = if clips.iter().all(|current_clip| current_clip.might_contain(internal_clip)) { + internal_clip + } else { + &clips[0] + }; + Some(ClipData::from_clip_region(region)) + }, + } + } + }; + + if let Some(data) = clip_data { + prim_needs_resolve = true; + let gpu_address = self.gpu_data32.alloc(6); + let gpu_data = self.gpu_data32.get_slice_mut(gpu_address, 6); + Self::populate_clip_data(gpu_data, data); + metadata.clip_index = Some(gpu_address); + metadata.mask_texture_id = dummy_mask_cache_item.texture_id; + } } match metadata.prim_kind { @@ -921,10 +937,10 @@ impl From for GpuBlock32 { } } -impl From for GpuBlock32 { - fn from(data: ImageMaskInfo) -> GpuBlock32 { +impl From for GpuBlock32 { + fn from(data: ImageMaskData) -> GpuBlock32 { unsafe { - mem::transmute::(data) + mem::transmute::(data) } } } @@ -978,3 +994,31 @@ impl From for GpuBlock128 { } } } + +//Test for one clip region contains another +trait InsideTest { + fn might_contain(&self, clip: &T) -> bool; +} + +impl InsideTest for ComplexClipRegion { + // Returns true if clip is inside self, can return false negative + fn might_contain(&self, clip: &ComplexClipRegion) -> bool { + let delta_left = clip.rect.origin.x - self.rect.origin.x; + let delta_top = clip.rect.origin.y - self.rect.origin.y; + let delta_right = self.rect.max_x() - clip.rect.max_x(); + let delta_bottom = self.rect.max_y() - clip.rect.max_y(); + + delta_left >= 0f32 && + delta_top >= 0f32 && + delta_right >= 0f32 && + delta_bottom >= 0f32 && + clip.radii.top_left.width >= self.radii.top_left.width - delta_left && + clip.radii.top_left.height >= self.radii.top_left.height - delta_top && + clip.radii.top_right.width >= self.radii.top_right.width - delta_right && + clip.radii.top_right.height >= self.radii.top_right.height - delta_top && + clip.radii.bottom_left.width >= self.radii.bottom_left.width - delta_left && + clip.radii.bottom_left.height >= self.radii.bottom_left.height - delta_bottom && + clip.radii.bottom_right.width >= self.radii.bottom_right.width - delta_right && + clip.radii.bottom_right.height >= self.radii.bottom_right.height - delta_bottom + } +} diff --git a/webrender/src/render_backend.rs b/webrender/src/render_backend.rs index dca700a447..4b7ddcce41 100644 --- a/webrender/src/render_backend.rs +++ b/webrender/src/render_backend.rs @@ -411,6 +411,7 @@ impl RenderBackend { fn render(&mut self) -> RendererFrame { let frame = self.frame.build(&mut self.resource_cache, + &self.scene.pipeline_auxiliary_lists, self.device_pixel_ratio); let pending_update = self.resource_cache.pending_updates(); diff --git a/webrender/src/resource_cache.rs b/webrender/src/resource_cache.rs index da5a17a821..1f218b8b2c 100644 --- a/webrender/src/resource_cache.rs +++ b/webrender/src/resource_cache.rs @@ -53,6 +53,7 @@ enum State { QueryResources, } +#[derive(Clone, Debug)] pub struct DummyResources { pub white_image_id: TextureCacheItemId, pub opaque_mask_image_id: TextureCacheItemId, diff --git a/webrender/src/scene.rs b/webrender/src/scene.rs index a12d6728c3..0f42254d6c 100644 --- a/webrender/src/scene.rs +++ b/webrender/src/scene.rs @@ -8,7 +8,8 @@ use internal_types::DrawListId; use resource_cache::ResourceCache; use std::collections::HashMap; use std::hash::BuildHasherDefault; -use webrender_traits::{AuxiliaryLists, BuiltDisplayList, ItemRange, PipelineId, Epoch}; +use tiling::AuxiliaryListsMap; +use webrender_traits::{AuxiliaryLists, BuiltDisplayList, PipelineId, Epoch}; use webrender_traits::{ColorF, DisplayListId, StackingContext, StackingContextId}; use webrender_traits::{SpecificDisplayListItem}; use webrender_traits::{IframeInfo}; @@ -29,9 +30,7 @@ pub struct Scene { pub root_pipeline_id: Option, pub pipeline_map: HashMap>, pub pipeline_sizes: HashMap>, - pub pipeline_auxiliary_lists: HashMap>, + pub pipeline_auxiliary_lists: AuxiliaryListsMap, pub display_list_map: HashMap>, pub stacking_context_map: HashMap>, } @@ -185,15 +184,10 @@ impl Scene { let rectangle_item = RectangleDisplayItem { color: background_color, }; - let clip = ClipRegion { - main: overflow, - complex: ItemRange::empty(), - image_mask: None, - }; let root_bg_color_item = DisplayItem { item: SpecificDisplayItem::Rectangle(rectangle_item), rect: overflow, - clip: clip, + clip: ClipRegion::simple(&overflow), }; let draw_list_id = resource_cache.add_draw_list(vec![root_bg_color_item], pipeline_id); diff --git a/webrender/src/tiling.rs b/webrender/src/tiling.rs index 4a7ee267af..37a27b0003 100644 --- a/webrender/src/tiling.rs +++ b/webrender/src/tiling.rs @@ -14,14 +14,15 @@ use internal_types::{ANGLE_FLOAT_TO_FIXED, LowLevelFilterOp}; use layer::Layer; use prim_store::{PrimitiveGeometry, RectanglePrimitive, PrimitiveContainer}; use prim_store::{BorderPrimitiveCpu, BorderPrimitiveGpu, BoxShadowPrimitiveGpu}; -use prim_store::{ClipInfo, ImagePrimitiveCpu, ImagePrimitiveKind, ImagePrimitiveGpu}; +use prim_store::{ImagePrimitiveCpu, ImagePrimitiveGpu, ImagePrimitiveKind}; use prim_store::{PrimitiveKind, PrimitiveIndex, PrimitiveMetadata, PrimitiveCacheInfo}; +use prim_store::PrimitiveClipSource; use prim_store::{GradientPrimitiveCpu, GradientPrimitiveGpu, GradientType}; use prim_store::{PrimitiveCacheKey, TextRunPrimitiveGpu, TextRunPrimitiveCpu}; use prim_store::{PrimitiveStore, GpuBlock16, GpuBlock32, GpuBlock64, GpuBlock128}; use profiler::FrameProfileCounters; use renderer::BlendMode; -use resource_cache::ResourceCache; +use resource_cache::{DummyResources, ResourceCache}; use std::cmp; use std::collections::{HashMap}; use std::f32; @@ -32,12 +33,20 @@ use std::usize; use texture_cache::TexturePage; use util::{self, rect_from_points, MatrixHelpers, rect_from_points_f}; use util::{TransformedRect, TransformedRectKind, subtract_rect, pack_as_float}; -use webrender_traits::{ColorF, FontKey, ImageKey, ImageRendering, ComplexClipRegion, MixBlendMode}; -use webrender_traits::{BorderDisplayItem, BorderStyle, ItemRange, AuxiliaryLists, BorderSide}; -use webrender_traits::{BoxShadowClipMode, PipelineId, ScrollLayerId, WebGLContextId}; +use webrender_traits::{ColorF, FontKey, ImageKey, ImageRendering, MixBlendMode}; +use webrender_traits::{BorderDisplayItem, BorderSide, BorderStyle}; +use webrender_traits::{AuxiliaryLists, ItemRange, BoxShadowClipMode, ClipRegion}; +use webrender_traits::{PipelineId, ScrollLayerId, WebGLContextId}; const FLOATS_PER_RENDER_TASK_INFO: usize = 8; +pub type LayerMap = HashMap>; +pub type AuxiliaryListsMap = HashMap>; + trait AlphaBatchHelpers { fn get_batch_kind(&self, metadata: &PrimitiveMetadata) -> AlphaBatchKind; fn get_texture_id(&self, metadata: &PrimitiveMetadata) -> TextureId; @@ -788,29 +797,6 @@ impl RenderTask { pub const SCREEN_TILE_SIZE: i32 = 256; pub const RENDERABLE_CACHE_SIZE: i32 = 2048; -#[derive(Clone, Copy, Debug)] -pub enum MaskImageSource { - User(ImageKey), - Renderer(TextureId), -} - -/// Per-batch clipping info merged with the mask image. -#[derive(Clone, Debug)] -pub struct Clip { - pub clip: Box, - pub mask: MaskImageSource, -} - -impl Clip { - pub fn new(clip: ClipInfo, mask: MaskImageSource) ->Clip { - Clip { - clip: Box::new(clip), - mask: mask, - } - } -} - - #[derive(Debug, Clone)] pub struct DebugRect { pub label: String, @@ -1173,6 +1159,7 @@ pub struct FrameBuilder { prim_store: PrimitiveStore, cmds: Vec, device_pixel_ratio: f32, + dummy_resources: DummyResources, debug: bool, layer_store: Vec, @@ -1401,6 +1388,7 @@ impl ScreenTile { impl FrameBuilder { pub fn new(viewport_size: Size2D, device_pixel_ratio: f32, + dummy_resources: DummyResources, debug: bool, _config: FrameBuilderConfig) -> FrameBuilder { let viewport_size = Size2D::new(viewport_size.width as i32, viewport_size.height as i32); @@ -1410,6 +1398,7 @@ impl FrameBuilder { prim_store: PrimitiveStore::new(device_pixel_ratio), cmds: Vec::new(), device_pixel_ratio: device_pixel_ratio, + dummy_resources: dummy_resources, debug: debug, packed_layers: Vec::new(), scrollbar_prims: Vec::new(), @@ -1418,12 +1407,10 @@ impl FrameBuilder { fn add_primitive(&mut self, rect: &Rect, - clip_rect: &Rect, - clip: Option, + clip_region: &ClipRegion, container: PrimitiveContainer) -> PrimitiveIndex { let prim_index = self.prim_store.add_primitive(rect, - clip_rect, - clip, + clip_region, container); match self.cmds.last_mut().unwrap() { @@ -1478,8 +1465,7 @@ impl FrameBuilder { pub fn add_solid_rectangle(&mut self, rect: &Rect, - clip_rect: &Rect, - clip: Option, + clip_region: &ClipRegion, color: &ColorF, flags: PrimitiveFlags) { if color.a == 0.0 { @@ -1491,8 +1477,7 @@ impl FrameBuilder { }; let prim_index = self.add_primitive(rect, - clip_rect, - clip, + clip_region, PrimitiveContainer::Rectangle(prim)); match flags { @@ -1527,8 +1512,7 @@ impl FrameBuilder { pub fn add_border(&mut self, rect: Rect, - clip_rect: &Rect, - clip: Option, + clip_region: &ClipRegion, border: &BorderDisplayItem) { let radius = &border.radius; let left = &border.left; @@ -1592,15 +1576,13 @@ impl FrameBuilder { }; self.add_primitive(&rect, - clip_rect, - clip, + clip_region, PrimitiveContainer::Border(prim_cpu, prim_gpu)); } pub fn add_gradient(&mut self, rect: Rect, - clip_rect: &Rect, - clip: Option, + clip_region: &ClipRegion, start_point: Point2D, end_point: Point2D, stops: ItemRange) { @@ -1639,15 +1621,13 @@ impl FrameBuilder { }; self.add_primitive(&rect, - clip_rect, - clip, + clip_region, PrimitiveContainer::Gradient(gradient_cpu, gradient_gpu)); } pub fn add_text(&mut self, rect: Rect, - clip_rect: &Rect, - clip: Option, + clip_region: &ClipRegion, font_key: FontKey, size: Au, blur_radius: Au, @@ -1685,16 +1665,14 @@ impl FrameBuilder { }; self.add_primitive(&rect, - clip_rect, - clip.clone(), + clip_region, PrimitiveContainer::TextRun(prim_cpu, prim_gpu)); } } pub fn add_box_shadow(&mut self, box_bounds: &Rect, - clip_rect: &Rect, - clip: Option, + clip_region: &ClipRegion, box_offset: &Point2D, color: &ColorF, blur_radius: f32, @@ -1708,8 +1686,7 @@ impl FrameBuilder { // Fast path. if blur_radius == 0.0 && spread_radius == 0.0 && clip_mode == BoxShadowClipMode::None { self.add_solid_rectangle(&box_bounds, - clip_rect, - None, + clip_region, color, PrimitiveFlags::None); return; @@ -1737,8 +1714,7 @@ impl FrameBuilder { if edge_size == 0.0 { for rect in &instance_rects { self.add_solid_rectangle(rect, - clip_rect, - clip.clone(), + clip_region, color, PrimitiveFlags::None) } @@ -1754,16 +1730,14 @@ impl FrameBuilder { }; self.add_primitive(&prim_rect, - clip_rect, - clip, + clip_region, PrimitiveContainer::BoxShadow(prim_gpu, instance_rects)); } } pub fn add_webgl_rectangle(&mut self, rect: Rect, - clip_rect: &Rect, - clip: Option, + clip_region: &ClipRegion, context_id: WebGLContextId) { let prim_cpu = ImagePrimitiveCpu { kind: ImagePrimitiveKind::WebGL(context_id), @@ -1778,15 +1752,13 @@ impl FrameBuilder { }; self.add_primitive(&rect, - clip_rect, - clip, + clip_region, PrimitiveContainer::Image(prim_cpu, prim_gpu)); } pub fn add_image(&mut self, rect: Rect, - clip_rect: &Rect, - clip: Option, + clip_region: &ClipRegion, stretch_size: &Size2D, tile_spacing: &Size2D, image_key: ImageKey, @@ -1806,8 +1778,7 @@ impl FrameBuilder { }; self.add_primitive(&rect, - clip_rect, - clip, + clip_region, PrimitiveContainer::Image(prim_cpu, prim_gpu)); } @@ -1815,8 +1786,8 @@ impl FrameBuilder { /// primitives in screen space. fn cull_layers(&mut self, screen_rect: &DeviceRect, - layer_map: &HashMap>, - pipeline_auxiliary_lists: &HashMap>, + layer_map: &LayerMap, + auxiliary_lists_map: &AuxiliaryListsMap, x_tile_count: i32, y_tile_count: i32, resource_cache: &mut ResourceCache, @@ -1826,6 +1797,10 @@ impl FrameBuilder { // TODO(gw): Remove this stack once the layers refactor is done! let mut layer_stack: Vec = Vec::new(); + let dummy_mask_cache_item = { + let opaque_mask_id = self.dummy_resources.opaque_mask_image_id; + resource_cache.get_image_by_cache_id(opaque_mask_id).clone() + }; for cmd in &self.cmds { match cmd { @@ -1897,8 +1872,8 @@ impl FrameBuilder { } let packed_layer = &self.packed_layers[sc_index.0]; - let auxiliary_lists = pipeline_auxiliary_lists.get(&layer.pipeline_id) - .expect("No auxiliary lists?!"); + let auxiliary_lists = auxiliary_lists_map.get(&layer.pipeline_id) + .expect("No auxiliary lists?"); for i in 0..prim_count { let prim_index = PrimitiveIndex(prim_index.0 + i); @@ -1912,6 +1887,7 @@ impl FrameBuilder { if self.prim_store.prepare_prim_for_render(prim_index, resource_cache, self.device_pixel_ratio, + &dummy_mask_cache_item, auxiliary_lists) { self.prim_store.build_bounding_rect(prim_index, screen_rect, @@ -2049,7 +2025,7 @@ impl FrameBuilder { } fn update_scroll_bars(&mut self, - layer_map: &HashMap>) { + layer_map: &LayerMap) { let distance_from_edge = 8.0; for scrollbar_prim in &self.scrollbar_prims { @@ -2084,12 +2060,13 @@ impl FrameBuilder { geom.local_rect.origin.y = util::lerp(min_y, max_y, f); geom.local_clip_rect = geom.local_rect; - if scrollbar_prim.border_radius == 0.0 { - self.prim_store.set_complex_clip(scrollbar_prim.prim_index, None); + let clip_source = if scrollbar_prim.border_radius == 0.0 { + PrimitiveClipSource::NoClip } else { - let clip = ClipInfo::uniform(geom.local_rect, scrollbar_prim.border_radius); - self.prim_store.set_complex_clip(scrollbar_prim.prim_index, Some(clip)); - } + PrimitiveClipSource::Complex(geom.local_rect, + scrollbar_prim.border_radius) + }; + self.prim_store.set_clip_source(scrollbar_prim.prim_index, clip_source); *self.prim_store.gpu_geometry.get_mut(GpuStoreAddress(scrollbar_prim.prim_index.0 as i32)) = geom; } } @@ -2097,8 +2074,9 @@ impl FrameBuilder { pub fn build(&mut self, resource_cache: &mut ResourceCache, frame_id: FrameId, - pipeline_auxiliary_lists: &HashMap>, - layer_map: &HashMap>) -> Frame { + layer_map: &LayerMap, + auxiliary_lists_map: &AuxiliaryListsMap) -> Frame { + let mut profile_counters = FrameProfileCounters::new(); profile_counters.total_primitives.set(self.prim_store.prim_count()); @@ -2116,7 +2094,7 @@ impl FrameBuilder { self.cull_layers(&screen_rect, layer_map, - pipeline_auxiliary_lists, + auxiliary_lists_map, x_tile_count, y_tile_count, resource_cache, @@ -2229,31 +2207,3 @@ impl FrameBuilder { } } } - -//Test for one clip region contains another -pub trait InsideTest { - fn might_contain(&self, clip: &T) -> bool; -} - -impl InsideTest for ComplexClipRegion { - // Returns true if clip is inside self, can return false negative - fn might_contain(&self, clip: &ComplexClipRegion) -> bool { - let delta_left = clip.rect.origin.x - self.rect.origin.x; - let delta_top = clip.rect.origin.y - self.rect.origin.y; - let delta_right = self.rect.max_x() - clip.rect.max_x(); - let delta_bottom = self.rect.max_y() - clip.rect.max_y(); - - delta_left >= 0f32 && - delta_top >= 0f32 && - delta_right >= 0f32 && - delta_bottom >= 0f32 && - clip.radii.top_left.width >= self.radii.top_left.width - delta_left && - clip.radii.top_left.height >= self.radii.top_left.height - delta_top && - clip.radii.top_right.width >= self.radii.top_right.width - delta_right && - clip.radii.top_right.height >= self.radii.top_right.height - delta_top && - clip.radii.bottom_left.width >= self.radii.bottom_left.width - delta_left && - clip.radii.bottom_left.height >= self.radii.bottom_left.height - delta_bottom && - clip.radii.bottom_right.width >= self.radii.bottom_right.width - delta_right && - clip.radii.bottom_right.height >= self.radii.bottom_right.height - delta_bottom - } -} diff --git a/webrender_traits/src/display_item.rs b/webrender_traits/src/display_item.rs index d420f31c25..e0873fa60f 100644 --- a/webrender_traits/src/display_item.rs +++ b/webrender_traits/src/display_item.rs @@ -6,7 +6,7 @@ use display_list::AuxiliaryListsBuilder; use euclid::{Rect, Size2D}; use {BorderRadius, BorderDisplayItem, ClipRegion, ColorF, ComplexClipRegion}; use {FontKey, ImageKey, PipelineId, ScrollLayerId, ScrollLayerInfo, ServoScrollRootId}; -use {ImageMask}; +use {ImageMask, ItemRange}; impl BorderDisplayItem { pub fn top_left_inner_radius(&self) -> Size2D { @@ -62,6 +62,14 @@ impl ClipRegion { image_mask: image_mask, } } + + pub fn simple(rect: &Rect) -> ClipRegion { + ClipRegion { + main: *rect, + complex: ItemRange::empty(), + image_mask: None, + } + } } impl ColorF { diff --git a/webrender_traits/src/types.rs b/webrender_traits/src/types.rs index e86b349ee9..b21cd63723 100644 --- a/webrender_traits/src/types.rs +++ b/webrender_traits/src/types.rs @@ -187,6 +187,12 @@ pub struct ClipRegion { pub image_mask: Option, } +impl ClipRegion { + pub fn is_complex(&self) -> bool { + self.complex.length !=0 || self.image_mask.is_some() + } +} + #[derive(Clone, Copy, Debug, Deserialize, PartialEq, Serialize)] pub struct ComplexClipRegion { /// The boundaries of the rectangle.