diff --git a/src/batch.rs b/src/batch.rs index 4bb71fc41e..b59d78119f 100644 --- a/src/batch.rs +++ b/src/batch.rs @@ -1,6 +1,10 @@ use device::{ProgramId, TextureId}; -use internal_types::{BlurDirection, PackedVertex}; -use internal_types::{PackedVertexForTextureCacheUpdate, Primitive}; +use fnv::FnvHasher; +use internal_types::{AxisDirection, PackedVertex, PackedVertexForTextureCacheUpdate, Primitive}; +use std::collections::HashMap; +use std::collections::hash_map::Entry; +use std::collections::hash_state::DefaultState; +use std::u16; use std::sync::atomic::Ordering::SeqCst; use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT}; @@ -207,7 +211,7 @@ impl<'a> BatchBuilder<'a> { /// A batch for raster jobs. pub struct RasterBatch { pub program_id: ProgramId, - pub blur_direction: Option, + pub blur_direction: Option, pub dest_texture_id: TextureId, pub color_texture_id: TextureId, pub vertices: Vec, @@ -216,7 +220,7 @@ pub struct RasterBatch { impl RasterBatch { pub fn new(program_id: ProgramId, - blur_direction: Option, + blur_direction: Option, dest_texture_id: TextureId, color_texture_id: TextureId) -> RasterBatch { @@ -235,7 +239,7 @@ impl RasterBatch { dest_texture_id: TextureId, color_texture_id: TextureId, program_id: ProgramId, - blur_direction: Option) + blur_direction: Option) -> bool { let batch_ok = program_id == self.program_id && blur_direction == self.blur_direction && diff --git a/src/batch_builder.rs b/src/batch_builder.rs index 3503f78a8a..049044e0f9 100644 --- a/src/batch_builder.rs +++ b/src/batch_builder.rs @@ -4,10 +4,10 @@ use clipper::{self, ClipBuffers, Polygon}; use device::TextureId; use euclid::{Rect, Point2D, Size2D}; use fnv::FnvHasher; -use internal_types::{CombinedClipRegion, RectPosUv}; +use internal_types::{CombinedClipRegion, RectColors, RectColorsUv, RectPolygon}; use internal_types::{RectUv, Primitive, BorderRadiusRasterOp, RasterItem, ClipRectToRegionResult}; use internal_types::{GlyphKey, PackedVertex, WorkVertex}; -use internal_types::{PolygonPosColorUv, BorderEdgeDirection}; +use internal_types::{PolygonPosColorUv, AxisDirection}; use internal_types::{BasicRotationAngle, BoxShadowRasterOp}; use renderer::BLUR_INFLATION_FACTOR; use resource_cache::ResourceCache; @@ -16,6 +16,7 @@ use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::collections::hash_state::DefaultState; use tessellator::{self, BorderCornerTessellation}; use texture_cache::{TextureCacheItem}; +use util; use webrender_traits::{ColorF, ImageFormat, BorderStyle, BoxShadowClipMode}; use webrender_traits::{BorderRadius, BorderSide, FontKey, GlyphInstance, ImageKey}; use webrender_traits::{BorderDisplayItem, GradientStop, ComplexClipRegion, ImageRendering}; @@ -65,8 +66,7 @@ impl<'a> BatchBuilder<'a> { image_key: ImageKey, image_rendering: ImageRendering, resource_cache: &ResourceCache, - clip_buffers: &mut ClipBuffers, - color: &ColorF) { + clip_buffers: &mut ClipBuffers) { // Should be caught higher up debug_assert!(stretch_size.width > 0.0 && stretch_size.height > 0.0); let image_info = resource_cache.get_image(image_key, image_rendering); @@ -90,17 +90,16 @@ impl<'a> BatchBuilder<'a> { v_size: uv_size.y, }; - clipper::clip_rect_to_combined_region(RectPosUv { + clipper::clip_rect_to_combined_region(RectPolygon { pos: *rect, - uv: uv + varyings: uv, }, &mut clip_buffers.sh_clip_buffers, &mut clip_buffers.rect_pos_uv, clip); for clip_region in clip_buffers.rect_pos_uv.clip_rect_to_region_result_output.drain(..) { let mask = mask_for_clip_region(resource_cache, &clip_region, false); - let colors = [*color, *color, *color, *color]; - let mut vertices = clip_region.make_packed_vertices_for_rect(&colors, mask); + let mut vertices = clip_region.make_packed_vertices_for_rect(mask); self.add_draw_item(matrix_index, image_info.texture_id, @@ -134,7 +133,9 @@ impl<'a> BatchBuilder<'a> { let mut glyph_key = GlyphKey::new(font_key, size, blur_radius, glyphs[0].index); let blur_offset = blur_radius.to_f32_px() * (BLUR_INFLATION_FACTOR as f32) / 2.0; - let mut text_batches: HashMap, DefaultState> = + let mut text_batches: HashMap>, + DefaultState> = HashMap::with_hash_state(Default::default()); for glyph in glyphs { @@ -146,10 +147,10 @@ impl<'a> BatchBuilder<'a> { let width = image_info.requested_rect.size.width as f32 / device_pixel_ratio; let height = image_info.requested_rect.size.height as f32 / device_pixel_ratio; - let rect = RectPosUv { + let rect = RectPolygon { pos: Rect::new(Point2D::new(x, y), Size2D::new(width, height)), - uv: image_info.uv_rect, + varyings: image_info.uv_rect, }; let rect_buffer = match text_batches.entry(image_info.texture_id) { @@ -186,25 +187,25 @@ impl<'a> BatchBuilder<'a> { vertex_buffer.push(PackedVertex::from_components( x0, y0, color, - rect.uv.top_left.x, rect.uv.top_left.y, + rect.varyings.top_left.x, rect.varyings.top_left.y, dummy_mask_image.uv_rect.top_left.x, dummy_mask_image.uv_rect.top_left.y)); vertex_buffer.push(PackedVertex::from_components( x1, y0, color, - rect.uv.top_right.x, rect.uv.top_right.y, + rect.varyings.top_right.x, rect.varyings.top_right.y, dummy_mask_image.uv_rect.top_right.x, dummy_mask_image.uv_rect.top_right.y)); vertex_buffer.push(PackedVertex::from_components( x0, y1, color, - rect.uv.bottom_left.x, rect.uv.bottom_left.y, + rect.varyings.bottom_left.x, rect.varyings.bottom_left.y, dummy_mask_image.uv_rect.bottom_left.x, dummy_mask_image.uv_rect.bottom_left.y)); vertex_buffer.push(PackedVertex::from_components( x1, y1, color, - rect.uv.bottom_right.x, rect.uv.bottom_right.y, + rect.varyings.bottom_right.x, rect.varyings.bottom_right.y, dummy_mask_image.uv_rect.bottom_right.x, dummy_mask_image.uv_rect.bottom_right.y)); } @@ -251,18 +252,21 @@ impl<'a> BatchBuilder<'a> { } clipper::clip_rect_to_combined_region( - RectPosUv { + RectPolygon { pos: *rect, - uv: image_info.uv_rect, + varyings: RectColorsUv { + colors: RectColors::new(colors), + uv: image_info.uv_rect, + }, }, &mut clip_buffers.sh_clip_buffers, - &mut clip_buffers.rect_pos_uv, + &mut clip_buffers.rect_pos_colors_uv, clip); - for clip_region in clip_buffers.rect_pos_uv.clip_rect_to_region_result_output.drain(..) { + for clip_region in clip_buffers.rect_pos_colors_uv + .clip_rect_to_region_result_output + .drain(..) { let mask = mask_for_clip_region(resource_cache, &clip_region, false); - - let mut vertices = clip_region.make_packed_vertices_for_rect(colors, mask); - + let mut vertices = clip_region.make_packed_vertices_for_rect(mask); self.add_draw_item(matrix_index, image_info.texture_id, mask.texture_id, @@ -272,6 +276,53 @@ impl<'a> BatchBuilder<'a> { } } + fn add_axis_aligned_gradient_with_stops(&mut self, + matrix_index: MatrixIndex, + clip: &CombinedClipRegion, + rect: &Rect, + direction: AxisDirection, + stops: &[GradientStop], + resource_cache: &ResourceCache, + clip_buffers: &mut ClipBuffers) { + for i in 0..(stops.len() - 1) { + let (prev_stop, next_stop) = (&stops[i], &stops[i + 1]); + let piece_rect; + let piece_colors; + match direction { + AxisDirection::Horizontal => { + let prev_x = util::lerp(rect.origin.x, rect.max_x(), prev_stop.offset); + let next_x = util::lerp(rect.origin.x, rect.max_x(), next_stop.offset); + piece_rect = Rect::new(Point2D::new(prev_x, rect.origin.y), + Size2D::new(next_x - prev_x, rect.size.height)); + piece_colors = [ + prev_stop.color, + next_stop.color, + next_stop.color, + prev_stop.color + ]; + } + AxisDirection::Vertical => { + let prev_y = util::lerp(rect.origin.y, rect.max_y(), prev_stop.offset); + let next_y = util::lerp(rect.origin.y, rect.max_y(), next_stop.offset); + piece_rect = Rect::new(Point2D::new(rect.origin.x, prev_y), + Size2D::new(rect.size.width, next_y - prev_y)); + piece_colors = [ + prev_stop.color, + prev_stop.color, + next_stop.color, + next_stop.color + ]; + } + } + self.add_axis_aligned_gradient(matrix_index, + &piece_rect, + clip, + resource_cache, + clip_buffers, + &piece_colors) + } + } + pub fn add_gradient(&mut self, matrix_index: MatrixIndex, clip: &CombinedClipRegion, @@ -280,6 +331,34 @@ impl<'a> BatchBuilder<'a> { stops: &[GradientStop], resource_cache: &ResourceCache, clip_buffers: &mut ClipBuffers) { + // Fast paths for axis-aligned gradients: + // + // FIXME(pcwalton): Determine the start and end points properly! + if start_point.x == end_point.x { + let rect = Rect::new(Point2D::new(-10000.0, start_point.y), + Size2D::new(20000.0, end_point.y - start_point.y)); + self.add_axis_aligned_gradient_with_stops(matrix_index, + clip, + &rect, + AxisDirection::Vertical, + stops, + resource_cache, + clip_buffers); + return + } + if start_point.y == end_point.y { + let rect = Rect::new(Point2D::new(start_point.x, -10000.0), + Size2D::new(end_point.x - start_point.x, 20000.0)); + self.add_axis_aligned_gradient_with_stops(matrix_index, + clip, + &rect, + AxisDirection::Horizontal, + stops, + resource_cache, + clip_buffers); + return + } + let white_image = resource_cache.get_dummy_color_image(); debug_assert!(stops.len() >= 2); @@ -345,10 +424,10 @@ impl<'a> BatchBuilder<'a> { let mut packed_vertices = Vec::new(); if clip_result.rect_result.vertices.len() >= 3 { for vert in clip_result.rect_result.vertices.iter() { - packed_vertices.push(clip_result.make_packed_vertex(&vert.position(), - &vert.uv(), - &vert.color(), - &mask)); + packed_vertices.push(clip_result.make_packed_vertex( + &vert.position(), + &(vert.color(), vert.uv()), + &mask)); } } @@ -728,7 +807,7 @@ impl<'a> BatchBuilder<'a> { matrix_index: MatrixIndex, rect: &Rect, clip: &CombinedClipRegion, - direction: BorderEdgeDirection, + direction: AxisDirection, color: &ColorF, border_style: BorderStyle, resource_cache: &ResourceCache, @@ -743,22 +822,22 @@ impl<'a> BatchBuilder<'a> { match border_style { BorderStyle::Dashed => { let (extent, step) = match direction { - BorderEdgeDirection::Horizontal => { + AxisDirection::Horizontal => { (rect.size.width, rect.size.height * BORDER_DASH_SIZE) } - BorderEdgeDirection::Vertical => { + AxisDirection::Vertical => { (rect.size.height, rect.size.width * BORDER_DASH_SIZE) } }; let mut origin = 0.0; while origin < extent { let dash_rect = match direction { - BorderEdgeDirection::Horizontal => { + AxisDirection::Horizontal => { Rect::new(Point2D::new(rect.origin.x + origin, rect.origin.y), Size2D::new(f32::min(step, extent - origin), rect.size.height)) } - BorderEdgeDirection::Vertical => { + AxisDirection::Vertical => { Rect::new(Point2D::new(rect.origin.x, rect.origin.y + origin), Size2D::new(rect.size.width, f32::min(step, extent - origin))) @@ -777,19 +856,19 @@ impl<'a> BatchBuilder<'a> { } BorderStyle::Dotted => { let (extent, step) = match direction { - BorderEdgeDirection::Horizontal => (rect.size.width, rect.size.height), - BorderEdgeDirection::Vertical => (rect.size.height, rect.size.width), + AxisDirection::Horizontal => (rect.size.width, rect.size.height), + AxisDirection::Vertical => (rect.size.height, rect.size.width), }; let mut origin = 0.0; while origin < extent { let (dot_rect, mask_radius) = match direction { - BorderEdgeDirection::Horizontal => { + AxisDirection::Horizontal => { (Rect::new(Point2D::new(rect.origin.x + origin, rect.origin.y), Size2D::new(f32::min(step, extent - origin), rect.size.height)), rect.size.height / 2.0) } - BorderEdgeDirection::Vertical => { + AxisDirection::Vertical => { (Rect::new(Point2D::new(rect.origin.x, rect.origin.y + origin), Size2D::new(rect.size.width, f32::min(step, extent - origin))), @@ -856,14 +935,14 @@ impl<'a> BatchBuilder<'a> { } BorderStyle::Double => { let (outer_rect, inner_rect) = match direction { - BorderEdgeDirection::Horizontal => { + AxisDirection::Horizontal => { (Rect::new(rect.origin, Size2D::new(rect.size.width, rect.size.height / 3.0)), Rect::new(Point2D::new(rect.origin.x, rect.origin.y + rect.size.height * 2.0 / 3.0), Size2D::new(rect.size.width, rect.size.height / 3.0))) } - BorderEdgeDirection::Vertical => { + AxisDirection::Vertical => { (Rect::new(rect.origin, Size2D::new(rect.size.width / 3.0, rect.size.height)), Rect::new(Point2D::new(rect.origin.x + rect.size.width * 2.0 / 3.0, @@ -936,9 +1015,9 @@ impl<'a> BatchBuilder<'a> { // FIXME(pcwalton): Either use RGBA8 textures instead of alpha masks here, or implement // a mask combiner. let mask_uv = RectUv::from_image_and_rotation_angle(mask_image, rotation_angle, true); - let tessellated_rect = RectPosUv { + let tessellated_rect = RectPolygon { pos: tessellated_rect, - uv: mask_uv, + varyings: mask_uv, }; clipper::clip_rect_to_combined_region(tessellated_rect, @@ -960,34 +1039,34 @@ impl<'a> BatchBuilder<'a> { BasicRotationAngle::Upright => { v0 = rect_pos_uv.pos.origin; v1 = rect_pos_uv.pos.bottom_right(); - muv0 = rect_pos_uv.uv.top_left; - muv1 = rect_pos_uv.uv.top_right; - muv2 = rect_pos_uv.uv.bottom_right; - muv3 = rect_pos_uv.uv.bottom_left; + muv0 = rect_pos_uv.varyings.top_left; + muv1 = rect_pos_uv.varyings.top_right; + muv2 = rect_pos_uv.varyings.bottom_right; + muv3 = rect_pos_uv.varyings.bottom_left; } BasicRotationAngle::Clockwise90 => { v0 = rect_pos_uv.pos.top_right(); v1 = rect_pos_uv.pos.bottom_left(); - muv0 = rect_pos_uv.uv.top_right; - muv1 = rect_pos_uv.uv.top_left; - muv2 = rect_pos_uv.uv.bottom_left; - muv3 = rect_pos_uv.uv.bottom_right; + muv0 = rect_pos_uv.varyings.top_right; + muv1 = rect_pos_uv.varyings.top_left; + muv2 = rect_pos_uv.varyings.bottom_left; + muv3 = rect_pos_uv.varyings.bottom_right; } BasicRotationAngle::Clockwise180 => { v0 = rect_pos_uv.pos.bottom_right(); v1 = rect_pos_uv.pos.origin; - muv0 = rect_pos_uv.uv.bottom_right; - muv1 = rect_pos_uv.uv.bottom_left; - muv2 = rect_pos_uv.uv.top_left; - muv3 = rect_pos_uv.uv.top_right; + muv0 = rect_pos_uv.varyings.bottom_right; + muv1 = rect_pos_uv.varyings.bottom_left; + muv2 = rect_pos_uv.varyings.top_left; + muv3 = rect_pos_uv.varyings.top_right; } BasicRotationAngle::Clockwise270 => { v0 = rect_pos_uv.pos.bottom_left(); v1 = rect_pos_uv.pos.top_right(); - muv0 = rect_pos_uv.uv.bottom_left; - muv1 = rect_pos_uv.uv.bottom_right; - muv2 = rect_pos_uv.uv.top_right; - muv3 = rect_pos_uv.uv.top_left; + muv0 = rect_pos_uv.varyings.bottom_left; + muv1 = rect_pos_uv.varyings.bottom_right; + muv2 = rect_pos_uv.varyings.top_right; + muv3 = rect_pos_uv.varyings.top_left; } } @@ -1028,19 +1107,24 @@ impl<'a> BatchBuilder<'a> { let vertices_rect = Rect::new(*v0, Size2D::new(v1.x - v0.x, v1.y - v0.y)); let color_uv = RectUv::from_image_and_rotation_angle(color_image, rotation_angle, false); - clipper::clip_rect_to_combined_region(RectPosUv { + let colors = RectColors::new(&[*color0, *color0, *color1, *color1]); + clipper::clip_rect_to_combined_region(RectPolygon { pos: vertices_rect, - uv: color_uv, + varyings: RectColorsUv { + colors: colors, + uv: color_uv, + }, }, &mut clip_buffers.sh_clip_buffers, - &mut clip_buffers.rect_pos_uv, + &mut clip_buffers.rect_pos_colors_uv, clip); - for clip_region in clip_buffers.rect_pos_uv.clip_rect_to_region_result_output.drain(..) { + for clip_region in clip_buffers.rect_pos_colors_uv + .clip_rect_to_region_result_output + .drain(..) { let mask = mask_for_clip_region(resource_cache, &clip_region, false); - let colors = [*color0, *color0, *color1, *color1]; - let mut vertices = clip_region.make_packed_vertices_for_rect(&colors, mask); + let mut vertices = clip_region.make_packed_vertices_for_rect(mask); self.add_draw_item(matrix_index, color_image.texture_id, @@ -1093,7 +1177,7 @@ impl<'a> BatchBuilder<'a> { &Rect::new(Point2D::new(tl_outer.x, tl_inner.y), Size2D::new(left.width, bl_inner.y - tl_inner.y)), clip, - BorderEdgeDirection::Vertical, + AxisDirection::Vertical, &left_color, info.left.style, resource_cache, @@ -1104,7 +1188,7 @@ impl<'a> BatchBuilder<'a> { Size2D::new(tr_inner.x - tl_inner.x, tr_outer.y + top.width - tl_outer.y)), clip, - BorderEdgeDirection::Horizontal, + AxisDirection::Horizontal, &top_color, info.top.style, resource_cache, @@ -1114,7 +1198,7 @@ impl<'a> BatchBuilder<'a> { &Rect::new(Point2D::new(br_outer.x - right.width, tr_inner.y), Size2D::new(right.width, br_inner.y - tr_inner.y)), clip, - BorderEdgeDirection::Vertical, + AxisDirection::Vertical, &right_color, info.right.style, resource_cache, @@ -1125,7 +1209,7 @@ impl<'a> BatchBuilder<'a> { Size2D::new(br_inner.x - bl_inner.x, br_outer.y - bl_outer.y + bottom.width)), clip, - BorderEdgeDirection::Horizontal, + AxisDirection::Horizontal, &bottom_color, info.bottom.style, resource_cache, diff --git a/src/clipper.rs b/src/clipper.rs index ac457b714f..164bb72fed 100644 --- a/src/clipper.rs +++ b/src/clipper.rs @@ -1,11 +1,11 @@ use euclid::{Point2D, Rect, Size2D}; -use internal_types::{ClipRectToRegionMaskResult, ClipRectToRegionResult}; -use internal_types::{CombinedClipRegion, PolygonPosColorUv, RectPosUv, WorkVertex}; +use internal_types::{ClipRectToRegionMaskResult, ClipRectToRegionResult, CombinedClipRegion}; +use internal_types::{PolygonPosColorUv, RectColorsUv, RectPolygon, RectUv, WorkVertex}; use simd::f32x4; use std::fmt::Debug; use std::mem; use webrender_traits::{ColorF, ComplexClipRegion}; -use util; +use util::{self, RectVaryings, VaryingElement}; pub static MAX_RECT: Rect = Rect { origin: Point2D { @@ -88,7 +88,8 @@ impl

TypedClipBuffers

{ pub struct ClipBuffers { pub sh_clip_buffers: ShClipBuffers, - pub rect_pos_uv: TypedClipBuffers, + pub rect_pos_uv: TypedClipBuffers>, + pub rect_pos_colors_uv: TypedClipBuffers>, pub polygon_pos_color_uv: TypedClipBuffers, } @@ -97,6 +98,7 @@ impl ClipBuffers { ClipBuffers { sh_clip_buffers: ShClipBuffers::new(), rect_pos_uv: TypedClipBuffers::new(), + rect_pos_colors_uv: TypedClipBuffers::new(), polygon_pos_color_uv: TypedClipBuffers::new(), } } @@ -391,24 +393,28 @@ pub trait Polygon : Sized { fn intersects_rect(&self, rect: &Rect) -> bool; } -impl RectPosUv { - fn push_clipped_rect(&self, clipped_rect: &Rect, output: &mut Vec) { +impl RectPolygon where Varyings: RectVaryings, + Varyings::Element: VaryingElement { + fn push_clipped_rect(&self, + clipped_rect: &Rect, + output: &mut Vec>) { if util::rect_is_empty(&clipped_rect) { return } - output.push(RectPosUv { + output.push(RectPolygon { pos: *clipped_rect, - uv: util::bilerp_rect(clipped_rect, &self.pos, &self.uv), + varyings: util::bilerp_rect(clipped_rect, &self.pos, &self.varyings), }); } } -impl Polygon for RectPosUv { +impl Polygon for RectPolygon where Varyings: RectVaryings + Clone, + Varyings::Element: VaryingElement { fn clip_to_rect(&self, _: &mut ShClipBuffers, clip_rect: &Rect, - output: &mut Vec) { + output: &mut Vec>) { for clipped_rect in self.pos.intersection(clip_rect).iter() { self.push_clipped_rect(clipped_rect, output) } @@ -417,11 +423,11 @@ impl Polygon for RectPosUv { fn clip_out_rect(&self, _: &mut ShClipBuffers, clip_rect: &Rect, - output: &mut Vec) { + output: &mut Vec>) { let clip_rect = match self.pos.intersection(clip_rect) { Some(clip_rect) => clip_rect, None => { - output.push(*self); + output.push((*self).clone()); return } }; diff --git a/src/frame.rs b/src/frame.rs index 6627f1c5fc..16526feb27 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -3,7 +3,7 @@ use batch::MAX_MATRICES_PER_BATCH; use device::{TextureId}; use euclid::{Rect, Point2D, Size2D, Matrix4}; use fnv::FnvHasher; -use internal_types::{BlurDirection, LowLevelFilterOp, CompositionOp, DrawListItemIndex}; +use internal_types::{AxisDirection, LowLevelFilterOp, CompositionOp, DrawListItemIndex}; use internal_types::{BatchUpdateList, DrawListId}; use internal_types::{RendererFrame, DrawListContext, BatchInfo, DrawCall}; use internal_types::{BatchUpdate, BatchUpdateOp, DrawLayer}; @@ -420,10 +420,10 @@ impl Frame { FilterOp::Blur(radius) => { composition_operations.push(CompositionOp::Filter(LowLevelFilterOp::Blur( radius, - BlurDirection::Horizontal))); + AxisDirection::Horizontal))); composition_operations.push(CompositionOp::Filter(LowLevelFilterOp::Blur( radius, - BlurDirection::Vertical))); + AxisDirection::Vertical))); } FilterOp::Brightness(amount) => { composition_operations.push(CompositionOp::Filter( diff --git a/src/internal_types.rs b/src/internal_types.rs index c66a082ec5..3d58486d28 100644 --- a/src/internal_types.rs +++ b/src/internal_types.rs @@ -8,10 +8,10 @@ use std::collections::HashMap; use std::collections::hash_state::DefaultState; use std::sync::Arc; use texture_cache::TextureCacheItem; +use util::{self, RectVaryings, VaryingElement}; use webrender_traits::{FontKey, Epoch, ColorF, PipelineId}; use webrender_traits::{ImageFormat}; use webrender_traits::{ComplexClipRegion, MixBlendMode, NativeFontHandle, DisplayItem}; -use util; const UV_FLOAT_TO_FIXED: f32 = 65535.0; const COLOR_FLOAT_TO_FIXED: f32 = 255.0; @@ -425,8 +425,9 @@ impl

ClipRectToRegionResult

{ }; let muv_rect = - Rect::new(Point2D::new(mask.uv_rect.top_left.x + mask_result.muv_rect.origin.x * mask_uv_size.width, - mask.uv_rect.top_left.y + mask_result.muv_rect.origin.y * mask_uv_size.height), + Rect::new(Point2D::new( + mask.uv_rect.top_left.x + mask_result.muv_rect.origin.x * mask_uv_size.width, + mask.uv_rect.top_left.y + mask_result.muv_rect.origin.y * mask_uv_size.height), Size2D::new(mask_result.muv_rect.size.width * mask_uv_size.width, mask_result.muv_rect.size.height * mask_uv_size.height)); let position_rect = &mask_result.position_rect; @@ -439,43 +440,38 @@ impl

ClipRectToRegionResult

{ (position.y - position_rect.origin.y) / position_rect.size.height)) } - pub fn make_packed_vertex(&self, - position: &Point2D, - uv: &Point2D, - color: &ColorF, - mask: &TextureCacheItem) - -> PackedVertex { - PackedVertex::from_points(position, color, uv, &self.muv_for_position(position, mask)) + pub fn make_packed_vertex(&self, + position: &Point2D, + varying_element: &VE, + mask: &TextureCacheItem) + -> PackedVertex + where VE: VaryingElement { + varying_element.make_packed_vertex(position, &self.muv_for_position(position, mask)) } } -impl ClipRectToRegionResult { - // TODO(pcwalton): Clip colors too! - pub fn make_packed_vertices_for_rect(&self, colors: &[ColorF; 4], mask: &TextureCacheItem) - -> [PackedVertex; 4] { +impl ClipRectToRegionResult> + where Varyings: RectVaryings, Varyings::Element: VaryingElement { + pub fn make_packed_vertices_for_rect(&self, mask: &TextureCacheItem) -> [PackedVertex; 4] { [ self.make_packed_vertex(&self.rect_result.pos.origin, - &self.rect_result.uv.top_left, - &colors[0], + &self.rect_result.varyings.top_left(), mask), self.make_packed_vertex(&self.rect_result.pos.top_right(), - &self.rect_result.uv.top_right, - &colors[1], + &self.rect_result.varyings.top_right(), mask), self.make_packed_vertex(&self.rect_result.pos.bottom_left(), - &self.rect_result.uv.bottom_left, - &colors[3], + &self.rect_result.varyings.bottom_left(), mask), self.make_packed_vertex(&self.rect_result.pos.bottom_right(), - &self.rect_result.uv.bottom_right, - &colors[2], + &self.rect_result.varyings.bottom_right(), mask), ] } } -#[derive(Debug, Clone, Copy)] -pub enum BorderEdgeDirection { +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum AxisDirection { Horizontal, Vertical, } @@ -552,11 +548,36 @@ impl CompiledNode { } #[derive(Clone, Copy, Debug)] -pub struct RectPosUv { +pub struct RectPolygon { pub pos: Rect, + pub varyings: Varyings, +} + +#[derive(Clone, Copy, Debug)] +pub struct RectColorsUv { + pub colors: RectColors, pub uv: RectUv, } +#[derive(Clone, Copy, Debug)] +pub struct RectColors { + pub top_left: ColorF, + pub top_right: ColorF, + pub bottom_right: ColorF, + pub bottom_left: ColorF, +} + +impl RectColors { + pub fn new(colors: &[ColorF; 4]) -> RectColors { + RectColors { + top_left: colors[0], + top_right: colors[1], + bottom_right: colors[2], + bottom_left: colors[3], + } + } +} + #[derive(Clone, Copy, Debug)] pub struct RectUv { pub top_left: Point2D, @@ -863,7 +884,7 @@ impl<'a> CombinedClipRegion<'a> { #[derive(Clone, Copy, Debug, PartialEq)] pub enum LowLevelFilterOp { - Blur(Au, BlurDirection), + Blur(Au, AxisDirection), Brightness(Au), Contrast(Au), Grayscale(Au), @@ -881,8 +902,3 @@ pub enum CompositionOp { Filter(LowLevelFilterOp), } -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum BlurDirection { - Horizontal, - Vertical, -} diff --git a/src/node_compiler.rs b/src/node_compiler.rs index e121144746..53594b79b3 100644 --- a/src/node_compiler.rs +++ b/src/node_compiler.rs @@ -18,7 +18,6 @@ impl NodeCompiler for AABBTreeNode { resource_cache: &ResourceCache, render_targets: &Vec, device_pixel_ratio: f32) { - let color_white = ColorF::new(1.0, 1.0, 1.0, 1.0); let mut compiled_node = CompiledNode::new(); let mut vertex_buffer = VertexBuffer::new(); @@ -69,8 +68,7 @@ impl NodeCompiler for AABBTreeNode { info.image_key, info.image_rendering, resource_cache, - &mut clip_buffers, - &color_white); + &mut clip_buffers); } SpecificDisplayItem::Text(ref info) => { builder.add_text(matrix_index, diff --git a/src/renderer.rs b/src/renderer.rs index bf71e40806..a566ac218a 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -9,7 +9,7 @@ use internal_types::{RendererFrame, ResultMsg, TextureUpdateOp, BatchUpdateOp, B use internal_types::{TextureUpdateDetails, TextureUpdateList, PackedVertex, RenderTargetMode}; use internal_types::{ORTHO_NEAR_PLANE, ORTHO_FAR_PLANE, BoxShadowPart, BasicRotationAngle}; use internal_types::{PackedVertexForTextureCacheUpdate, CompositionOp}; -use internal_types::{BlurDirection, LowLevelFilterOp, DrawCommand, ANGLE_FLOAT_TO_FIXED}; +use internal_types::{AxisDirection, LowLevelFilterOp, DrawCommand, ANGLE_FLOAT_TO_FIXED}; use ipc_channel::ipc; use render_backend::RenderBackend; use std::collections::HashMap; @@ -374,7 +374,7 @@ impl Renderer { horizontal_blur_texture_image.texture_id, unblurred_glyph_texture_image.texture_id, blur_program_id, - Some(BlurDirection::Horizontal)); + Some(AxisDirection::Horizontal)); batch.add_draw_item(horizontal_blur_texture_image.texture_id, unblurred_glyph_texture_image.texture_id, &vertices); @@ -434,7 +434,7 @@ impl Renderer { update.id, horizontal_blur_texture_image.texture_id, blur_program_id, - Some(BlurDirection::Vertical)); + Some(AxisDirection::Vertical)); batch.add_draw_item(update.id, horizontal_blur_texture_image.texture_id, &vertices); @@ -635,7 +635,7 @@ impl Renderer { dest_texture_id: TextureId, color_texture_id: TextureId, program_id: ProgramId, - blur_direction: Option) + blur_direction: Option) -> &mut RasterBatch { // FIXME(pcwalton): Use a hash table if this linear search shows up in the profile. let mut index = None; @@ -669,7 +669,7 @@ impl Renderer { // All horizontal blurs must complete before anything else. let mut remaining_batches = vec![]; for batch in batches.into_iter() { - if batch.blur_direction != Some(BlurDirection::Horizontal) { + if batch.blur_direction != Some(AxisDirection::Horizontal) { remaining_batches.push(batch); continue } @@ -695,7 +695,7 @@ impl Renderer { update_id: TextureId, color_texture_id: TextureId, program_id: ProgramId, - blur_direction: Option) { + blur_direction: Option) { gl::disable(gl::BLEND); gl::disable(gl::DEPTH_TEST); @@ -717,10 +717,10 @@ impl Renderer { self.device.bind_mask_texture_for_noncomposite_operation(TextureId(0)); match blur_direction { - Some(BlurDirection::Horizontal) => { + Some(AxisDirection::Horizontal) => { self.device.set_uniform_2f(self.u_direction, 1.0, 0.0) } - Some(BlurDirection::Vertical) => { + Some(AxisDirection::Vertical) => { self.device.set_uniform_2f(self.u_direction, 0.0, 1.0) } None => {} @@ -921,14 +921,14 @@ impl Renderer { let (opcode, amount, param0, param1) = match filter_op { LowLevelFilterOp::Blur(radius, - BlurDirection::Horizontal) => { + AxisDirection::Horizontal) => { (0.0, radius.to_f32_px() * self.device_pixel_ratio, 1.0, 0.0) } LowLevelFilterOp::Blur(radius, - BlurDirection::Vertical) => { + AxisDirection::Vertical) => { (0.0, radius.to_f32_px() * self.device_pixel_ratio, 0.0, diff --git a/src/util.rs b/src/util.rs index a822602e0b..3697526abb 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,7 +1,8 @@ use euclid::{Matrix4, Point2D, Rect, Size2D}; -use internal_types::RectUv; +use internal_types::{PackedVertex, RectColors, RectColorsUv, RectUv}; use std::num::Zero; use time::precise_time_ns; +use webrender_traits::ColorF; #[allow(dead_code)] pub struct ProfileScope { @@ -66,24 +67,136 @@ pub fn lerp(a: f32, b: f32, t: f32) -> f32 { (b - a) * t + a } -pub fn bilerp(point: &Point2D, quad: &Rect, uv: &RectUv) -> Point2D { +pub fn bilerp(point: &Point2D, quad: &Rect, varyings: &V) -> V::Element + where V: RectVaryings, V::Element: VaryingElement { let (x1, y1, x2, y2) = (quad.origin.x, quad.origin.y, quad.max_x(), quad.max_y()); - (uv.top_left * (x2 - point.x) * (y2 - point.y) + - uv.top_right * (point.x - x1) * (y2 - point.y) + - uv.bottom_left * (x2 - point.x) * (point.y - y1) + - uv.bottom_right * (point.x - x1) * (point.y - y1)) / ((x2 - x1) * (y2 - y1)) -} - -pub fn bilerp_rect(clipped_rect: &Rect, quad: &Rect, uv: &RectUv) -> RectUv { - let uv_tl = bilerp(&clipped_rect.origin, quad, uv); - let uv_tr = bilerp(&clipped_rect.top_right(), quad, uv); - let uv_br = bilerp(&clipped_rect.bottom_right(), quad, uv); - let uv_bl = bilerp(&clipped_rect.bottom_left(), quad, uv); - RectUv { - top_left: uv_tl, - top_right: uv_tr, - bottom_left: uv_bl, - bottom_right: uv_br, + let top_left = varyings.top_left().scale((x2 - point.x) * (y2 - point.y)); + let top_right = varyings.top_right().scale((point.x - x1) * (y2 - point.y)); + let bottom_left = varyings.bottom_left().scale((x2 - point.x) * (point.y - y1)); + let bottom_right = varyings.bottom_right().scale((point.x - x1) * (point.y - y1)); + let sum = VaryingElement::accumulate(&[top_left, top_right, bottom_left, bottom_right]); + sum.scale(1.0 / ((x2 - x1) * (y2 - y1))) +} + +pub fn bilerp_rect(clipped_rect: &Rect, quad: &Rect, varyings: &V) -> V + where V: RectVaryings, V::Element: VaryingElement { + let top_left = bilerp(&clipped_rect.origin, quad, varyings); + let top_right = bilerp(&clipped_rect.top_right(), quad, varyings); + let bottom_right = bilerp(&clipped_rect.bottom_right(), quad, varyings); + let bottom_left = bilerp(&clipped_rect.bottom_left(), quad, varyings); + V::from_elements(&[top_left, top_right, bottom_right, bottom_left]) +} + +pub trait RectVaryings { + type Element; + fn top_left(&self) -> Self::Element; + fn top_right(&self) -> Self::Element; + fn bottom_right(&self) -> Self::Element; + fn bottom_left(&self) -> Self::Element; + fn from_elements(elements: &[Self::Element; 4]) -> Self; +} + +impl RectVaryings for RectUv { + type Element = Point2D; + fn top_left(&self) -> Point2D { self.top_left } + fn top_right(&self) -> Point2D { self.top_right } + fn bottom_right(&self) -> Point2D { self.bottom_right } + fn bottom_left(&self) -> Point2D { self.bottom_left } + fn from_elements(elements: &[Point2D; 4]) -> RectUv { + RectUv { + top_left: elements[0], + top_right: elements[1], + bottom_right: elements[2], + bottom_left: elements[3], + } + } +} + +impl RectVaryings for RectColors { + type Element = ColorF; + fn top_left(&self) -> ColorF { self.top_left } + fn top_right(&self) -> ColorF { self.top_right } + fn bottom_right(&self) -> ColorF { self.bottom_right } + fn bottom_left(&self) -> ColorF { self.bottom_left } + fn from_elements(elements: &[ColorF; 4]) -> RectColors { + RectColors { + top_left: elements[0], + top_right: elements[1], + bottom_right: elements[2], + bottom_left: elements[3], + } + } +} + +impl RectVaryings for RectColorsUv { + type Element = (ColorF, Point2D); + fn top_left(&self) -> (ColorF, Point2D) { + (self.colors.top_left, self.uv.top_left) + } + fn top_right(&self) -> (ColorF, Point2D) { + (self.colors.top_right, self.uv.top_right) + } + fn bottom_left(&self) -> (ColorF, Point2D) { + (self.colors.bottom_left, self.uv.bottom_left) + } + fn bottom_right(&self) -> (ColorF, Point2D) { + (self.colors.bottom_right, self.uv.bottom_right) + } + fn from_elements(elements: &[(ColorF, Point2D); 4]) -> RectColorsUv { + let colors = [elements[0].0, elements[1].0, elements[2].0, elements[3].0]; + let uv = [elements[0].1, elements[1].1, elements[2].1, elements[3].1]; + RectColorsUv { + colors: RectColors::from_elements(&colors), + uv: RectUv::from_elements(&uv), + } + } +} + +pub trait VaryingElement : Sized { + fn scale(&self, factor: f32) -> Self; + fn accumulate(values: &[Self; 4]) -> Self; + fn make_packed_vertex(&self, position: &Point2D, muv: &Point2D) -> PackedVertex; +} + +impl VaryingElement for Point2D { + fn scale(&self, factor: f32) -> Point2D { + *self * factor + } + fn accumulate(values: &[Point2D; 4]) -> Point2D { + values[0] + values[1] + values[2] + values[3] + } + fn make_packed_vertex(&self, position: &Point2D, muv: &Point2D) -> PackedVertex { + static WHITE: ColorF = ColorF { + r: 1.0, + g: 1.0, + b: 1.0, + a: 1.0, + }; + PackedVertex::from_points(position, &WHITE, self, muv) + } +} + +impl VaryingElement for (ColorF, Point2D) { + fn scale(&self, factor: f32) -> (ColorF, Point2D) { + let color = ColorF { + r: self.0.r * factor, + g: self.0.g * factor, + b: self.0.b * factor, + a: self.0.a * factor, + }; + (color, self.1 * factor) + } + fn accumulate(values: &[(ColorF, Point2D); 4]) -> (ColorF, Point2D) { + let color = ColorF { + r: values[0].0.r + values[1].0.r + values[2].0.r + values[3].0.r, + g: values[0].0.g + values[1].0.g + values[2].0.g + values[3].0.g, + b: values[0].0.b + values[1].0.b + values[2].0.b + values[3].0.b, + a: values[0].0.a + values[1].0.a + values[2].0.a + values[3].0.a, + }; + (color, values[0].1 + values[1].1 + values[2].1 + values[3].1) + } + fn make_packed_vertex(&self, position: &Point2D, muv: &Point2D) -> PackedVertex { + PackedVertex::from_points(position, &self.0, &self.1, muv) } }